Commit 94947589 authored by Henri-Damien LAURENT's avatar Henri-Damien LAURENT
Browse files

Ajout du cache disque

parent 10e9bcbc
Pipeline #9379 failed with stage
in 1 minute and 15 seconds
......@@ -20,5 +20,8 @@
"psr-4": {
"Pellicule\\Tests\\": "tests"
}
},
"require-dev": {
"mikey179/vfsstream": "^1.6"
}
}
This diff is collapsed.
<?php
return ['enabled' => 0,
'facility' => 'disk'];
\ No newline at end of file
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use \Storm\Persistence\Connections;
use \Storm\Persistence\Mysqli\Connection;
use \Storm\Persistence\Configuration;
use \Storm\Model\Loader;
use \Storm\Persistence\SqlStrategy;
use \Storm\FileSystem\Disk;
use \Storm\FileSystem\Volatile;
require __DIR__ . '/../vendor/autoload.php';
$app = Pellicule\AppFactory::create();
$app = \Pellicule\AppFactory::create();
$app->add(function(Request $request, RequestHandler $handler)
$app->add(function($request, $handler)
{
$settings = require __DIR__ . '/../conf/database.php';
$database_settings = require __DIR__ . '/../conf/database.php';
\Storm\Persistence\Connections::getInstance()
->setDefault(new \Storm\Persistence\Mysqli\Connection(new \Storm\Persistence\Configuration($settings)));
\Storm\Model\Loader::defaultTo(\Storm\Persistence\SqlStrategy::class);
Connections::getInstance()->setDefault(new Connection(new Configuration($settings)));
Loader::defaultTo(SqlStrategy::class);
return $handler->handle($request);
});
$app->add(function($request, $handler)
{
$settings = require __DIR__ . '/../conf/filesystem.php';
$filesystem = $setting['facility'] == 'disk'
? new Disk()
: new Volatile();
Media::setFileSystem($filesystem);
return $handler->handle($request);
}
);
$app->run();
\ No newline at end of file
<?php
namespace Pellicule;
use \Buzz\Client\Curl;
use \Slim\Psr7\Factory\RequestFactory;
class FileSystem {
use HttpClientAware;
protected static $_base_path;
public static function setBasePath($path) {
static::$_base_path = $path;
}
public function download($media) {
$settings = require __DIR__ . '/../conf/filesystem.php';
if (!$settings['enabled'])
return;
$directory = static::$_base_path . $media->getLocation();
if (false === \file_exists($directory))
\mkdir($directory, 0755, true);
if (!$url_to_fetch = $media->getUrl())
return;
$client = $this->newHttpClient();
if (false === ($local_file = fopen($directory . '/' . $media->getLocalFileName() , 'w')))
return;
$request = (new RequestFactory())->createRequest('GET', $url_to_fetch);
if ($request)
$client->sendRequest($request,['curl' => ['CURLOPT_FILE', $local_file ]] );
fclose($local_file);
// $media->resizeTo('thumbnail');
// $directory = static::$_base_path . $media->getLocation();
//
}
}
<?php
namespace Pellicule;
use \Buzz\Browser;
use \Buzz\Client\Curl;
use \Slim\Psr7\Factory\ResponseFactory;
use \Slim\Psr7\Factory\RequestFactory;
trait HttpClientAware {
protected static $_default_http_client;
static public function newHttpClient() {
if (static::$_default_http_client)
return static::$_default_http_client;
$client = new Curl(new ResponseFactory());
$browser = new Browser($client, new RequestFactory());
return $browser;
}
static public function setDefaultHttpClient($client) {
static::$_default_http_client = $client;
}
}
\ No newline at end of file
......@@ -5,9 +5,68 @@ use \Storm\Model\ModelAbstract;
class Media extends ModelAbstract {
protected static $_file_system;
protected
$_size;
protected
$_table_name = 'media',
$_belongs_to = [ 'record' => ['model' => Record::class ]
];
$_belongs_to = [ 'record' => ['model' => Record::class ] ];
public static function setFileSystem($filesystem) {
static::$_file_system = $filesystem;
}
public static function getFileSystem() {
return isset(static::$_file_system)
? static::$_file_system
: new \Pellicule\FileSystem();
}
public function getJsonAttributes() {
return array_intersect_key($this->getRawAttributes(),
['type' => 1, 'url' => 1]);
}
public function afterSave() {
$this->getFileSystem()->download($this);
}
public function getSize(){
return (isset($this->_size))
? $this->_size
: 'fullsize';
}
public function setSize($string){
$this->_size = $string;
return $this;
}
public function splitId(){
return array_slice(str_split(sprintf("%04d", $this->getId()))
, 0, 4 );
}
public function getLocation(){
return '/' . implode('/', array_merge([$this->getSize(), $this->getType()], $this->splitId())) .'/';
}
public function getLocalFileName(){
return $this->getId() . '.' . $this->getExtension();
}
public function getExtension(){
return pathinfo( $this->getUrl() , PATHINFO_EXTENSION );
}
}
......@@ -15,11 +15,12 @@ class Record extends ModelAbstract {
]
];
public function asJSON(){
$datas = [ 'media' => array_map( function($medium){ return array_intersect_key($medium->getRawAttributes(),['type' => 1, 'original' => 1, 'url' => 1]);
},
$this->getMedia()) ];
return json_encode($datas);
public function asJSON() {
return json_encode(['media' => array_map(function($medium)
{
return $medium->getJsonAttributes();
},
$this->getMedia()) ]);
}
}
\ No newline at end of file
......@@ -99,7 +99,7 @@ class Electre extends Provider {
{
return (new \Pellicule\Models\Media())
->setProvider($this->providerName())
->setOriginal($link->href)
->setUrl($link->href)
->setType( (($link->rel=='coverCopy')
? 'back_cover'
: $link->rel));
......
......@@ -54,7 +54,6 @@ class Orb extends Provider {
return (new FetchRecordResult())->beError($response->getStatusCode(),
$response->getReasonPhrase());
$response->getBody()->rewind();
$json_content = json_decode(zlib_decode($response->getBody()->getContents()), TRUE);
......@@ -74,7 +73,7 @@ class Orb extends Provider {
$medialist[] = (new \Pellicule\Models\Media())
->setProvider($this->providerName())
->setType($imagetype_translate[$image_type])
->setOriginal($images[$image_type]['original']['src']);
->setUrl($images[$image_type]['original']['src']);
}
$record = (new Record())
......
<?php
namespace Pellicule\Providers;
use \Buzz\Browser;
use \Buzz\Client\FileGetContents;
use \Slim\Psr7\Factory\ResponseFactory;
use \Slim\Psr7\Factory\RequestFactory;
use \Slim\Psr7\Request;
use \Pellicule\HttpClientAware;
abstract class Provider {
protected static $_default_http_client;
use HttpClientAware;
abstract public function providerName();
abstract public function fetchRecord($search_args);
static public function newHttpClient() {
if (static::$_default_http_client)
return static::$_default_http_client;
$client = new FileGetContents(new ResponseFactory());
$browser = new Browser($client, new RequestFactory());
return $browser;
}
static public function setDefaultHttpClient($client) {
static::$_default_http_client = $client;
}
static public function newProvider($credentials) {
if ($credentials['provider'] == 'electre')
return new Electre($credentials);
......
......@@ -11,6 +11,25 @@ class BrowserMockBuilder {
}
public function expectHttpQuery($request, $response) {
$request = array_merge(['type' => 'get', 'url' => '', 'headers' => [], 'body' => []],
$request);
$with_params = [];
$with_params[] = $request['url'];
$sith_params[] = $request['headers'];
if ($request['type'] == 'post')
$with_params[] = http_build_query($request['body']);
$this
->_mock
->whenCalled($request['type'])
->with($with_params)
->answers($this->_forgePSR7Response($response));
return $this;
}
public function expectPost($post, $response) {
$post = array_merge(['url' => '', 'headers' => [], 'body' => []],
......
<?php
namespace Pellicule\Tests;
use Pellicule\AppFactory;
use Pellicule\Models\Record;
use Pellicule\Models\Media;
use Pellicule\Providers\Electre;
use Pellicule\Providers\Orb;
use Pellicule\FileSystem;
use \org\bovigo\vfs\vfsStream;
class FileSystemTest extends TestCase {
protected $_root;
public function setUp(){
$this->_root = vfsStream::setup('myDir');
FileSystem::setBasePath(vfsStream::url('myDir'));
$mock_browser = (new BrowserMockBuilder())
->expectGet(['url' => 'http://image.org/city.jpg',
],
['content' => file_get_contents(realpath(dirname(__FILE__)) . '/' .'imagefullsize.jpg')])
->getMock()
->beStrict();
$app = AppFactory::create();
Record::newInstance(['id' => 1,
'isbn' => '2259228194',
'ean' => '9782259228190',
'ark' => 'https://catalogue.bnf.fr/ark:/12148/cb445155569'])
->assertSave();
Media::newInstance(['id'=> 135,
'record_id'=> 1,
'type' => 'cover',
'url' => 'http://image.org/city.jpg',
'provider' => 'Me',
'created_at' => '2020-01-13 08:00:00',
'updated_at' => '2020-01-16 08:00:00'
])
->assertSave();
}
/** @test */
public function fullsizeCoverDirectoryShouldBeCreated() {
$this->assertTrue($this->_root->hasChild('fullsize/cover/0/1'));
}
/** @test */
public function fullsizeCoverFileShouldBeCreated() {
$this->assertTrue($this->_root->hasChild('fullsize/cover/0/1/3/5/135.jpg'));
}
//TBD
/** @test */
// public function thumbnailCoverDirectoryShouldBeCreated() {
// $this->assertTrue($this->_root->hasChild('thumbnail/cover/0/1/3/5/135.jpg'));
//}
}
......@@ -2,17 +2,24 @@
namespace Pellicule\Tests;
use Pellicule\AppFactory;
use Pellicule\Models\Record;
use Pellicule\Models\Media;
use Pellicule\Providers\Electre;
use Pellicule\Providers\Orb;
use \Pellicule\AppFactory;
use \Pellicule\Models\Record;
use \Pellicule\Models\Media;
use \Pellicule\FileSystem;
use \Pellicule\Providers\Electre;
use \Pellicule\Providers\Orb;
use \org\bovigo\vfs\vfsStream;
class MediaGetTest extends TestCase {
protected $_response;
protected
$_response,
$_root;
public function setUp(){
$this->_root = vfsStream::setup('myDir');
FileSystem::setBasePath(vfsStream::url('myDir'));
$app = AppFactory::create();
Record::newInstance(['id' => 1,
'isbn' => '2259228194',
......@@ -23,7 +30,7 @@ class MediaGetTest extends TestCase {
Media::newInstance(['id'=> 135,
'record_id'=> 1,
'type' => 'cover',
'original' => 'http://image.org/city.jpg',
'url' => 'http://image.org/city.jpg',
'provider' => 'Me',
'created_at' => '2020-01-13 08:00:00',
'updated_at' => '2020-01-16 08:00:00'
......@@ -33,7 +40,7 @@ class MediaGetTest extends TestCase {
Media::newInstance(['id'=> 147,
'record_id'=>1,
'type' => 'back_cover',
'original' => 'http://image.org/cityback.jpg',
'url' => 'http://image.org/cityback.jpg',
'provider' => 'Me',
'created_at' => '2020-01-21 08:00:00',
'updated_at' => '2020-02-14 08:00:00'
......@@ -50,7 +57,7 @@ class MediaGetTest extends TestCase {
Media::newInstance(['id'=> 155,
'record_id'=>4,
'type' => 'cover',
'original' => 'http://image.org/ARDTP-ALODJFEF.jpg',
'url' => 'http://image.org/ARDTP-ALODJFEF.jpg',
'provider' => 'Me',
'created_at' => '1980-01-13 08:00:00',
'updated_at' => '1980-01-16 08:00:00'
......@@ -72,9 +79,9 @@ class MediaGetTest extends TestCase {
public function whenCalledWithISBNAndISBNFoundResponseShouldContainsMedia($url) {
$expected = [ 'media'=>
[
[ 'original' => 'http://image.org/city.jpg',
[ 'url' => 'http://image.org/city.jpg',
'type' => 'cover'],
[ 'original' => 'http://image.org/cityback.jpg',
[ 'url' => 'http://image.org/cityback.jpg',
'type' => 'back_cover'
]
]
......@@ -153,9 +160,9 @@ abstract class MediaWithElectreTestCase extends TestCase {
public function whenCalledWithElectreIdentifiersAndDataNotInCacheShouldReturnExpectedJSON() {
$return_data =
[ 'media' => [
['original'=> 'http://image.org/city.jpg',
['url'=> 'http://image.org/city.jpg',
'type' => 'cover'],
['original' => 'http://image.org/cityback.jpg',
['url' => 'http://image.org/cityback.jpg',
'type' => 'back_cover']
]
];
......@@ -472,7 +479,7 @@ abstract class MediaWithOrbTestCase extends TestCase {
public function whenCalledWithOrbIdentifiersAndDataNotInCacheShouldReturnExpectedJSON() {
$return_data =
[ 'media' => [
['original'=> 'https://products-images.di-static.com/image/orb-9162f416a0b7b2e64a1f5480db8d4394/2259228234-475x500-1.jpg',
['url'=> 'https://products-images.di-static.com/image/orb-9162f416a0b7b2e64a1f5480db8d4394/2259228234-475x500-1.jpg',
'type' => 'cover']
]
......
<?php
namespace Pellicule\Tests;
use \Pellicule\AppFactory;
use \Pellicule\Models\Media;
use \Slim\Psr7\Request;
use \Slim\Psr7\Headers;
use \Slim\Psr7\Factory\UriFactory;
use \Slim\Psr7\Factory\StreamFactory;
use \Storm\Test\THelpers;
use \Storm\Model\ModelAbstract;
abstract class TestCase extends \PHPUnit\Framework\TestCase {
use THelpers;
public function setUp() {
parent::setUp();
\Storm\Model\ModelAbstract::unsetLoaders();
ModelAbstract::unsetLoaders();
Media::setFileSystem(null);
}
public function dispatch($url, $headers = []){
$app = \Pellicule\AppFactory::create();
$app = AppFactory::create();
$request = new Request('GET',
(new \Slim\Psr7\Factory\UriFactory())->createUri($url),
(new UriFactory())->createUri($url),
new Headers($headers),
[],
[],
(new \Slim\Psr7\Factory\StreamFactory())->createStream(),
(new StreamFactory())->createStream(),
[]
);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment