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

refactoring

parent ba7e79a4
Pipeline #10298 failed with stage
in 35 minutes and 5 seconds
<?php
namespace Pellicule\Controllers;
use Slim\Routing\RouteContext;
use Slim\Psr7\Request;
use Slim\Psr7\Response;
use Fig\Http\Message\StatusCodeInterface;
use Pellicule\Models\Record;
use Pellicule\Providers\Provider;
......@@ -11,8 +9,15 @@ use Pellicule\Providers\FetchRecordResult;
class Media {
protected
$_request,
$_args = [];
public function __invoke($request, $response, $args) {
$fetch_result = $this->_fetchRecord($request, $args);
$this->_request = $request;
$this->_args = $this->_processArgs($args);
$fetch_result = $this->_fetchRecord();
if ($fetch_result->hasError()) {
$response->getBody()->write(json_encode(['error' => $fetch_result->getErrorCode()]));
......@@ -23,52 +28,56 @@ class Media {
$record = $fetch_result->getRecord();
$record->save();
$response->getBody()->write($record->asJSON());
return $response->withHeader('Content-Type', 'application/json');
}
protected function _fetchRecord($request, $args) {
$findargs = $this->_processParams($args);
if ($record = Record::findFirstBy($findargs))
protected function _fetchRecord() {
if (!$this->_args)
return (new FetchRecordResult())->beError(StatusCodeInterface::STATUS_BAD_REQUEST, 'no valid params provided');
if ($record = Record::findFirstBy($this->_args))
return (new FetchRecordResult())->beSuccess($record);
if (!$request->hasHeader('Authorization'))
if (!$this->_request->hasHeader('Authorization'))
return (new FetchRecordResult())->beError(StatusCodeInterface::STATUS_NOT_FOUND, 'record not found');
return $this->_fetchRecordFromProviders($request, $findargs);
return $this->_fetchRecordFromProviders();
}
protected function _fetchRecordFromProviders($request, $args){
$credentials = array_filter($this->_parseAuthorizationHeader($request));
if (!$credentials)
return (new FetchRecordResult())->beError(StatusCodeInterface::STATUS_PROXY_AUTHENTICATION_REQUIRED, 'no_valid_authentication_information_provided');
protected function _fetchRecordFromProviders() {
if (!$credentials = array_filter($this->_parseAuthorizationHeader()))
return (new FetchRecordResult())
->beError(StatusCodeInterface::STATUS_PROXY_AUTHENTICATION_REQUIRED,
'no_valid_authentication_information_provided');
$provider = Provider::newProvider($credentials[0]);
return $provider->fetchRecord($this->_processParams($args));
return $provider->fetchRecord($this->_args);
}
protected function _parseAuthorizationHeader($request){
return (new \Storm\Model\Collection($request->getHeader('Authorization')))
protected function _parseAuthorizationHeader() {
return (new \Storm\Collection($this->_request->getHeader('Authorization')))
->select(function($header)
{
return ($header && (strpos('Pellicule ', $header) == 0));
return ($header && 'Pellicule ' == substr($header, 0, 10));
})
->collect([$this, 'decodeAuthorizationHeader'])->getArrayCopy();
->collect([$this, 'decodeAuthorizationHeader'])
->getArrayCopy();
}
public function decodeAuthorizationHeader($string){
public function decodeAuthorizationHeader($string) {
return json_decode(base64_decode(str_replace('Pellicule ', '', $string)), true);
}
protected function _processParams($args){
protected function _processArgs($args) {
if (!$args)
return;
return [];
if (isset($args['isbn']))
return ['isbn' => $args['isbn']];
......
......@@ -38,11 +38,11 @@ class Electre extends Provider {
public function fetchRecord($search_request) {
try{
try {
$response = $this->_getToken($this->_client_id, $this->_client_secret);
} catch(\Exception $exception) {
return (new FetchRecordResult())->beError(StatusCodeInterface::STATUS_GATEWAY_TIMEOUT
,
,
'no_answer_from_gateway');
}
......
<?php
namespace Pellicule\Tests;
class BrowserMockBuilder {
protected $_mock;
public function __construct() {
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$this->_mock = \Storm\Test\ObjectWrapper::mock('from ' . $stack[0]['file'] . ':' . $stack[0]['line']);
}
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' => []],
$post);
$this
->_mock
->whenCalled('post')
->with($post['url'],
$post['headers'],
http_build_query($post['body']))
->answers($this->_forgePSR7Response($response));
return $this;
}
public function expectGet($get, $response) {
$get = array_merge(['url' => '', 'headers' => []],
$get);
$this
->_mock
->whenCalled('get')
->with($get['url'],
$get['headers'])
->answers($this->_forgePSR7Response($response));
return $this;
}
public function getMock() {
return $this->_mock;
}
protected function _forgePSR7Response($response) {
$response = array_merge(['status' => 200, 'headers' => null, 'content' => ''],
$response);
return new \Slim\Psr7\Response($response['status'],
$response['headers'],
(new \Slim\Psr7\Factory\StreamFactory())->createStream($response['content']));
}
}
......@@ -11,72 +11,75 @@ use \Pellicule\Providers\Orb;
use \org\bovigo\vfs\vfsStream;
class MediaGetTest extends TestCase {
abstract class MediaTestCase extends TestCase {
public function setUp(){
parent::setUp();
$this->_root = vfsStream::setup('myDir');
FileSystem::setBasePath(vfsStream::url('myDir'));
}
protected function _forgePSR7Response($response) {
$response = array_merge(['status' => 200, 'headers' => null, 'content' => ''],
$response);
return new \Slim\Psr7\Response($response['status'],
$response['headers'],
(new \Slim\Psr7\Factory\StreamFactory())->createStream($response['content']));
}
}
class MediaLocalRecordTest extends MediaTestCase {
protected
$_response,
$_root;
public function setUp(){
$this->_root = vfsStream::setup('myDir');
FileSystem::setBasePath(vfsStream::url('myDir'));
parent::setUp();
$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();
Media::newInstance(['id'=> 147,
'record_id'=>1,
'type' => 'back_cover',
'url' => 'http://image.org/cityback.jpg',
'provider' => 'Me',
'created_at' => '2020-01-21 08:00:00',
'updated_at' => '2020-02-14 08:00:00'
])
->assertSave();
Record::newInstance(['id'=> 4,
'isbn' => '9782072843334',
'ean' => '2070380513',
'ark' => 'https://catalogue.bnf.fr/ark:/12148/cb35097231f'])
->assertSave();
Media::newInstance(['id'=> 155,
'record_id'=>4,
'type' => 'cover',
'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'
])
->assertSave();
}
public function urlsToTest(){
return [['/1.0/media/isbn/2259228194']
,['/1.0/media/ark:/12148/cb445155569']
,['/1.0/media/ean/9782259228190']];
}
/** @test
* @dataProvider urlsToTest
$this->fixture(Record::class,
['id' => 1,
'isbn' => '9782259228190',
'ean' => '9782259228190',
'ark' => 'https://catalogue.bnf.fr/ark:/12148/cb445155569']);
$this->fixture(Media::class,
['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'
]);
$this->fixture(Media::class,
['id'=> 147,
'record_id'=>1,
'type' => 'back_cover',
'url' => 'http://image.org/cityback.jpg',
'provider' => 'Me',
'created_at' => '2020-01-21 08:00:00',
'updated_at' => '2020-02-14 08:00:00'
]);
}
public function possibleRecord1Urls() {
return [['/1.0/media/isbn/9782259228190'],
['/1.0/media/ark:/12148/cb445155569'],
['/1.0/media/ean/9782259228190']];
}
/**
* @test
* @dataProvider possibleRecord1Urls
*/
public function whenCalledWithISBNAndISBNFoundResponseShouldContainsMedia($url) {
public function whenCalledWithPossibleRecord1UrlsResponseShouldContainsMedia($url) {
$expected = [ 'media'=>
[
[ 'url' => 'http://image.org/city.jpg',
......@@ -87,25 +90,26 @@ class MediaGetTest extends TestCase {
]
];
$this->assertEquals($expected,
json_decode($this->httpGet($url),TRUE));
}
public function urlsFailuresToTest(){
return [['/1.0/media/isbn/2413004084', 404]
,['/1.0/media/UNEAUTREREQUETE', 501]];
/**
* @test
*/
public function whenCalledWithunknownIsbnResponseCodeShouldBe404() {
$this->assertEquals(404,
$this->httpStatusCode('/1.0/media/isbn/2413004084'));
}
/**
* @test
* @dataProvider urlsFailuresToTest
*/
public function whenCalledWithErroneousDataResponseCodeShouldBeCorrect($url, $status) {
$this->assertEquals($status,
$this->httpHeader($url));
public function whenCalledWithBadParametersResponseCodeShouldBeNotImplemented() {
$this->assertEquals(501,
$this->httpStatusCode('/1.0/media/UNEAUTREREQUETE'));
}
}
......@@ -114,45 +118,38 @@ class MediaGetTest extends TestCase {
class MediaWithErrorOnAuthenticationTest extends TestCase {
/** @test */
public function withAuthorizationHeaderEmptyResponseStatusShouldBe407() {
public function withAuthorizationHeaderEmptyResponseStatusShouldBeProxyAuthRequired() {
$this->assertEquals(407,
$this->dispatch('/1.0/media/isbn/2259228180',
['Authorization' => ""])->getStatusCode());
$this->httpStatusCode('/1.0/media/isbn/2259228180',
['Authorization' => '']));
}
/** @test */
public function withAuthorizationHeaderEmptyWithPelliculeEmptyResponseStatusShouldBe407() {
public function withPelliculeEmptyHeaderResponseStatusShouldBeProxyAuthRequired() {
$this->assertEquals(407,
$this->dispatch('/1.0/media/isbn/2259228180',
['Authorization' => "Pellicule "])->getStatusCode());
$this->httpStatusCode('/1.0/media/isbn/2259228180',
['Authorization' => "Pellicule "]));
}
}
abstract class MediaWithElectreTestCase extends TestCase {
protected $_mock_browser;
abstract class MediaWithElectreTestCase extends MediaTestCase {
protected $_http_client;
public function setUp(){
parent::setUp();
$this->_mock_browser = (new BrowserMockBuilder())
->expectPost(['url' => 'https://electre3staging-idp.bvdep.com/connect/token',
'body' => ['client_id' => 'multipass',
'client_secret' => 'leeloo',
'grant_type'=> 'client_credentials',
'scope'=>'webapi']],
['content' => '{"access_token":"MyPr3ttyT0k3n","expires_in":3600,"token_type":"Bearer"}'])
->expectGet(['url' => 'https://electre3staging-api.bvdep.com/v1.0/eans/2259228194',
'headers' => ['Authorization' => 'Bearer MyPr3ttyT0k3n']],
['content' => '{"_links":[{"rel":"cover","href":"http://image.org/city.jpg"},{"rel":"coverCopy","href":"http://image.org/cityback.jpg"},{"rel":"summary","href":"https://electre3staging-api.bvdep.com/v1.0/eans/2259228194/summary"},{"rel":"biographie","href":"https://electre3staging-api.bvdep.com/v1.0/eans/2259228194/biography"}]}'])
->getMock();
$this->_http_client = $this
->mock()
->whenCalled('post')
->answers($this->_forgePSR7Response(['content' => '{"access_token":"MyPr3ttyT0k3n","expires_in":3600,"token_type":"Bearer"}']))
->whenCalled('get')
->answers($this->_forgePSR7Response(['content' => '{"_links":[{"rel":"cover","href":"http://image.org/city.jpg"},{"rel":"coverCopy","href":"http://image.org/cityback.jpg"},{"rel":"summary","href":"https://electre3staging-api.bvdep.com/v1.0/eans/2259228194/summary"},{"rel":"biographie","href":"https://electre3staging-api.bvdep.com/v1.0/eans/2259228194/biography"}]}']));
Electre::setDefaultHttpClient($this->_mock_browser);
Electre::setDefaultHttpClient($this->_http_client);
}
......@@ -166,9 +163,9 @@ abstract class MediaWithElectreTestCase extends TestCase {
'type' => 'back_cover']
]
];
$this->assertEquals($return_data,
json_decode($this->_response,TRUE)
);
json_decode($this->_response, true));
}
}
......@@ -178,12 +175,14 @@ abstract class MediaWithElectreTestCase extends TestCase {
class MediaWithElectreOnIsbnTest extends MediaWithElectreTestCase {
public function setUp() {
parent::setUp();
$this->_response = $this->httpGet('/1.0/media/isbn/2259228194',
['Authorization' => ['Pellicule ' . base64_encode(json_encode(['provider'=> 'electre',
'client_secret'=>'leeloo',
'client_id'=>'multipass']))]]);
}
$payload = base64_encode(json_encode(['provider'=> 'electre',
'client_secret' => 'leeloo',
'client_id' => 'multipass']));
$headers = ['Authorization' => ['Pellicule ' . $payload]];
$this->_response = $this->httpGet('/1.0/media/isbn/2259228194', $headers);
}
/** @test */
......@@ -233,6 +232,7 @@ class MediaWithElectreWithSearchError extends TestCase {
->getMock();
Electre::setDefaultHttpClient($mock_browser);
$this->_response = $this->dispatch('/1.0/media/ean/123456789',
['Authorization' => ['Pellicule ' . base64_encode(json_encode(['provider'=> 'electre',
'client_secret'=>'leeloo',
......
......@@ -43,7 +43,8 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
return $response->getBody()->getContents();
}
public function httpHeader($url, $headers = []){
public function httpStatusCode($url, $headers = []){
$response = $this->dispatch($url, $headers);
return $response->getStatusCode();
}
......
......@@ -2,6 +2,6 @@
error_reporting(E_ALL^E_DEPRECATED);
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
ini_set('xdebug.remote_port', '9301');
ini_set('xdebug.remote_port', '9312');
ini_set('xdebug.remote_host', '10.13.78.15');
require __DIR__ . '/../vendor/autoload.php';
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