Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 41 additions & 16 deletions spec/Api/ProductMediaFileApiSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
use Akeneo\Pim\ApiClient\Api\MediaFileApiInterface;
use Akeneo\Pim\ApiClient\Client\ResourceClientInterface;
use Akeneo\Pim\ApiClient\Exception\RuntimeException;
use Akeneo\Pim\ApiClient\FileSystem\FileSystemInterface;
use Akeneo\Pim\ApiClient\Pagination\PageInterface;
use Akeneo\Pim\ApiClient\Pagination\PageFactoryInterface;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;

Expand All @@ -22,9 +24,10 @@ class ProductMediaFileApiSpec extends ObjectBehavior
function let(
ResourceClientInterface $resourceClient,
PageFactoryInterface $pageFactory,
ResourceCursorFactoryInterface $cursorFactory
ResourceCursorFactoryInterface $cursorFactory,
FileSystemInterface $fileSystem
) {
$this->beConstructedWith($resourceClient, $pageFactory, $cursorFactory);
$this->beConstructedWith($resourceClient, $pageFactory, $cursorFactory, $fileSystem);
}

function it_is_initializable()
Expand Down Expand Up @@ -103,9 +106,11 @@ function it_returns_a_list_of_media_files_with_additional_query_parameters($reso
$this->listPerPage(null, null, ['foo' => 'bar'])->shouldReturn($page);
}

function it_creates_a_media_file($resourceClient, ResponseInterface $response)
function it_creates_a_media_file_from_a_path($resourceClient, $fileSystem, ResponseInterface $response)
{
$fileResource = fopen('php://stdin', 'r');
$fileSystem->getResourceFromPath('/images/akeneo.png')->willReturn($fileResource);

$product = [
'identifier' => 'foo',
'attribute' => 'picture',
Expand All @@ -132,23 +137,43 @@ function it_creates_a_media_file($resourceClient, ResponseInterface $response)
->createMultipartResource(ProductMediaFileApi::MEDIA_FILES_URI, [], $requestParts)
->willReturn($response);

$this->create($fileResource, $product)
$this->create('/images/akeneo.png', $product)
->shouldReturn('1/e/e/d/1eed10f108bde68b279d6f903f17b4b053e9d89d_akeneo.png');
}

function it_throws_an_exception_if_the_file_is_unreadable_when_creating_a_media_file()
function it_creates_a_media_file_from_a_resource($resourceClient, $fileSystem, ResponseInterface $response)
{
$this
->shouldThrow(new RuntimeException('The file "/foo.bar" could not be read.'))
->during('create', [
'/foo.bar',
[
'identifier' => 'foo',
'attribute' => 'picture',
'scope' => 'e-commerce',
'locale' => 'en_US',
]
]);
$fileResource = fopen('php://stdin', 'r');
$fileSystem->getResourceFromPath(Argument::any())->shouldNotBeCalled();

$product = [
'identifier' => 'foo',
'attribute' => 'picture',
'scope' => 'e-commerce',
'locale' => 'en_US',
];

$requestParts = [
[
'name' => 'product',
'contents' => json_encode($product),
],
[
'name' => 'file',
'contents' => $fileResource,
]
];

$response->getHeaders()->willReturn(['Location' => [
'http://localhost/api/rest/v1/media-files/1/e/e/d/1eed10f108bde68b279d6f903f17b4b053e9d89d_akeneo.png'
]]);

$resourceClient
->createMultipartResource(ProductMediaFileApi::MEDIA_FILES_URI, [], $requestParts)
->willReturn($response);

$this->create($fileResource, $product)
->shouldReturn('1/e/e/d/1eed10f108bde68b279d6f903f17b4b053e9d89d_akeneo.png');
}

function it_throws_an_exception_if_the_response_does_not_contain_the_uri_of_the_created_media_file($resourceClient, ResponseInterface $response)
Expand Down
26 changes: 23 additions & 3 deletions src/AkeneoPimClientBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
use Akeneo\Pim\ApiClient\Client\AuthenticatedHttpClient;
use Akeneo\Pim\ApiClient\Client\HttpClient;
use Akeneo\Pim\ApiClient\Client\ResourceClient;
use Akeneo\Pim\ApiClient\FileSystem\FileSystemInterface;
use Akeneo\Pim\ApiClient\FileSystem\LocalFileSystem;
use Akeneo\Pim\ApiClient\Pagination\PageFactory;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactory;
use Akeneo\Pim\ApiClient\Routing\UriGenerator;
Expand Down Expand Up @@ -55,6 +57,9 @@ class AkeneoPimClientBuilder
/** @var StreamFactory */
protected $streamFactory;

/** @var FileSystemInterface */
protected $fileSystem;

/**
* @param string $baseUri Base uri to request the API
*/
Expand Down Expand Up @@ -105,6 +110,20 @@ public function setStreamFactory($streamFactory)
return $this;
}

/**
* Allows to define another implementation than LocalFileSystem
*
* @param FileSystemInterface $fileSystem
*
* @return AkeneoPimClientBuilder
*/
public function setFileSystem($fileSystem)
{
$this->fileSystem = $fileSystem;

return $this;
}

/**
* Build the Akeneo PIM client authenticated by user name and password.
*
Expand Down Expand Up @@ -146,7 +165,7 @@ public function buildAuthenticatedByToken($clientId, $secret, $token, $refreshTo
*/
protected function buildAuthenticatedClient(Authentication $authentication)
{
list($resourceClient, $pageFactory, $cursorFactory) = $this->setUp($authentication);
list($resourceClient, $pageFactory, $cursorFactory, $fileSystem) = $this->setUp($authentication);

$client = new AkeneoPimClient(
$authentication,
Expand All @@ -156,7 +175,7 @@ protected function buildAuthenticatedClient(Authentication $authentication)
new AttributeOptionApi($resourceClient, $pageFactory, $cursorFactory),
new AttributeGroupApi($resourceClient, $pageFactory, $cursorFactory),
new FamilyApi($resourceClient, $pageFactory, $cursorFactory),
new ProductMediaFileApi($resourceClient, $pageFactory, $cursorFactory),
new ProductMediaFileApi($resourceClient, $pageFactory, $cursorFactory, $fileSystem),
new LocaleApi($resourceClient, $pageFactory, $cursorFactory),
new ChannelApi($resourceClient, $pageFactory, $cursorFactory),
new CurrencyApi($resourceClient, $pageFactory, $cursorFactory),
Expand Down Expand Up @@ -193,8 +212,9 @@ protected function setUp(Authentication $authentication)

$pageFactory = new PageFactory($authenticatedHttpClient);
$cursorFactory = new ResourceCursorFactory();
$fileSystem = null !== $this->fileSystem ? $this->fileSystem : new LocalFileSystem();

return [$resourceClient, $pageFactory, $cursorFactory];
return [$resourceClient, $pageFactory, $cursorFactory, $fileSystem];
}

/**
Expand Down
15 changes: 9 additions & 6 deletions src/Api/ProductMediaFileApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Akeneo\Pim\ApiClient\Client\ResourceClientInterface;
use Akeneo\Pim\ApiClient\Exception\RuntimeException;
use Akeneo\Pim\ApiClient\FileSystem\FileSystemInterface;
use Akeneo\Pim\ApiClient\Pagination\PageFactoryInterface;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface;
use Psr\Http\Message\ResponseInterface;
Expand Down Expand Up @@ -31,19 +32,25 @@ class ProductMediaFileApi implements MediaFileApiInterface
/** @var ResourceCursorFactoryInterface */
protected $cursorFactory;

/** @var FileSystemInterface */
private $fileSystem;

/**
* @param ResourceClientInterface $resourceClient
* @param PageFactoryInterface $pageFactory
* @param ResourceCursorFactoryInterface $cursorFactory
* @param FileSystemInterface $fileSystem
*/
public function __construct(
ResourceClientInterface $resourceClient,
PageFactoryInterface $pageFactory,
ResourceCursorFactoryInterface $cursorFactory
ResourceCursorFactoryInterface $cursorFactory,
FileSystemInterface $fileSystem
) {
$this->resourceClient = $resourceClient;
$this->pageFactory = $pageFactory;
$this->cursorFactory = $cursorFactory;
$this->fileSystem = $fileSystem;
}

/**
Expand Down Expand Up @@ -80,11 +87,7 @@ public function all($pageSize = 10, array $queryParameters = [])
public function create($mediaFile, array $productData)
{
if (is_string($mediaFile)) {
if (!is_readable($mediaFile)) {
throw new RuntimeException(sprintf('The file "%s" could not be read.', $mediaFile));
}

$mediaFile = fopen($mediaFile, 'rb');
$mediaFile = $this->fileSystem->getResourceFromPath($mediaFile);
}

$requestParts = [
Expand Down
14 changes: 14 additions & 0 deletions src/Exception/UnreadableFileException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Akeneo\Pim\ApiClient\Exception;

/**
* Exception thrown when a file can not be read.
*
* @author Laurent Petard <laurent.petard@akeneo.com>
* @copyright 2017 Akeneo SAS (http://www.akeneo.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
class UnreadableFileException extends RuntimeException
{
}
26 changes: 26 additions & 0 deletions src/FileSystem/FileSystemInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Akeneo\Pim\ApiClient\FileSystem;

use Akeneo\Pim\ApiClient\Exception\UnreadableFileException;

/**
* Manipulates files for the API.
*
* @author Laurent Petard <laurent.petard@akeneo.com>
* @copyright 2017 Akeneo SAS (http://www.akeneo.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
interface FileSystemInterface
{
/**
* Gets the resource of a file from its path.
*
* @param string $filePath Path of the file
*
* @throws UnreadableFileException if the file doesn't exists or is not readable
*
* @return resource
*/
public function getResourceFromPath($filePath);
}
33 changes: 33 additions & 0 deletions src/FileSystem/LocalFileSystem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Akeneo\Pim\ApiClient\FileSystem;

use Akeneo\Pim\ApiClient\Exception\UnreadableFileException;

/**
* File system to manipulate files stored locally.
*
* @author Laurent Petard <laurent.petard@akeneo.com>
* @copyright 2017 Akeneo SAS (http://www.akeneo.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
class LocalFileSystem implements FileSystemInterface
{
/**
* {@inheritdoc}
*/
public function getResourceFromPath($filePath)
{
if (!is_readable($filePath)) {
throw new UnreadableFileException(sprintf('The file "%s" could not be read.', $filePath));
}

$fileResource = fopen($filePath, 'rb');

if (!is_resource($fileResource)) {
throw new \RuntimeException(sprintf('The file "%s" could not be opened.', $filePath));
}

return $fileResource;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ public function testCreateWithAnInvalidRequest()
]);
}

/**
* @expectedException \Akeneo\Pim\ApiClient\Exception\UnreadableFileException
*/
public function testCreateWithAnInvalidFile()
{
$api = $this->createClient()->getProductMediaFileApi();

$api->create('foo.jpg', [
'identifier' => 'medium_boot',
'attribute' => 'side_view',
'scope' => null,
'locale' => null,
]);
}

/**
* Sanitize the code and links of a media file, because the code is generated randomly.
*
Expand Down