diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9b6d45a8..027b1ff6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,6 +12,7 @@ tests/ + tests/ diff --git a/spec/AkeneoPimClientSpec.php b/spec/AkeneoPimClientSpec.php index dd7e844e..53b0c04c 100644 --- a/spec/AkeneoPimClientSpec.php +++ b/spec/AkeneoPimClientSpec.php @@ -4,9 +4,19 @@ use Akeneo\Pim\ApiClient\AkeneoPimClient; use Akeneo\Pim\ApiClient\AkeneoPimClientInterface; +use Akeneo\Pim\ApiClient\Api\AssetApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetCategoryApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetApiInterface as AssetManagerApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetFamilyApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetReferenceFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetTagApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetVariationFileApiInterface; use Akeneo\Pim\ApiClient\Api\AssociationTypeApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeApiInterface; -use Akeneo\Pim\ApiClient\Api\AttributeGroupApi; +use Akeneo\Pim\ApiClient\Api\AttributeGroupApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeOptionApiInterface; use Akeneo\Pim\ApiClient\Api\CategoryApiInterface; use Akeneo\Pim\ApiClient\Api\ChannelApiInterface; @@ -18,7 +28,15 @@ use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApiInterface; use Akeneo\Pim\ApiClient\Api\MediaFileApiInterface; use Akeneo\Pim\ApiClient\Api\ProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductDraftApiInterface; use Akeneo\Pim\ApiClient\Api\ProductModelApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductModelDraftApiInterface; +use Akeneo\Pim\ApiClient\Api\PublishedProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityRecordApiInterface; use Akeneo\Pim\ApiClient\Security\Authentication; use PhpSpec\ObjectBehavior; @@ -30,7 +48,7 @@ function let( CategoryApiInterface $categoryApi, AttributeApiInterface $attributeApi, AttributeOptionApiInterface $attributeOptionApi, - AttributeGroupApi $attributeGroupApi, + AttributeGroupApiInterface $attributeGroupApi, FamilyApiInterface $familyApi, MediaFileApiInterface $productMediaFileApi, LocaleApiInterface $localeApi, @@ -40,7 +58,25 @@ function let( MeasurementFamilyApiInterface $measurementFamilyApi, AssociationTypeApiInterface $associationTypeApi, FamilyVariantApiInterface $familyVariantApi, - ProductModelApiInterface $productModelApi + ProductModelApiInterface $productModelApi, + ProductModelDraftApiInterface $productModelDraftApi, + PublishedProductApiInterface $publishedProductApi, + ProductDraftApiInterface $productDraftApi, + AssetApiInterface $assetApi, + AssetCategoryApiInterface $assetCategoryApi, + AssetTagApiInterface $assetTagApi, + AssetReferenceFileApiInterface $assetReferenceFileApi, + AssetVariationFileApiInterface $assetVariationFileApi, + ReferenceEntityRecordApiInterface $referenceEntityRecordApi, + ReferenceEntityMediaFileApiInterface $referenceEntityMediaFileApi, + ReferenceEntityAttributeApiInterface $referenceEntityAttributeApi, + ReferenceEntityAttributeOptionApiInterface $referenceEntityAttributeOptionApi, + ReferenceEntityApiInterface $referenceEntityApi, + AssetManagerApiInterface $assetManagerApi, + AssetFamilyApiInterface $assetFamilyApi, + AssetAttributeApiInterface $assetAttributeApi, + AssetAttributeOptionApiInterface $assetAttributeOptionApi, + AssetMediaFileApiInterface $assetMediaFileApi ) { $this->beConstructedWith( $authentication, @@ -48,7 +84,8 @@ function let( $categoryApi, $attributeApi, $attributeOptionApi, - $attributeGroupApi, $familyApi, + $attributeGroupApi, + $familyApi, $productMediaFileApi, $localeApi, $channelApi, @@ -57,7 +94,25 @@ function let( $measurementFamilyApi, $associationTypeApi, $familyVariantApi, - $productModelApi + $productModelApi, + $productModelDraftApi, + $publishedProductApi, + $productDraftApi, + $assetApi, + $assetCategoryApi, + $assetTagApi, + $assetReferenceFileApi, + $assetVariationFileApi, + $referenceEntityRecordApi, + $referenceEntityMediaFileApi, + $referenceEntityAttributeApi, + $referenceEntityAttributeOptionApi, + $referenceEntityApi, + $assetManagerApi, + $assetFamilyApi, + $assetAttributeApi, + $assetAttributeOptionApi, + $assetMediaFileApi ); } @@ -150,4 +205,84 @@ function it_gets_product_model_api($productModelApi) { $this->getProductModelApi()->shouldReturn($productModelApi); } + + function it_gets_published_product_api($publishedProductApi) + { + $this->getPublishedProductApi()->shouldReturn($publishedProductApi); + } + + function it_gets_draft_product_api($productDraftApi) + { + $this->getProductDraftApi()->shouldReturn($productDraftApi); + } + + function it_gets_draft_product_model_api($productModelDraftApi) + { + $this->getProductModelDraftApi()->shouldReturn($productModelDraftApi); + } + + function it_gets_asset_api($assetApi) + { + $this->getAssetApi()->shouldReturn($assetApi); + } + + function it_gets_asset_category_api($assetCategoryApi) + { + $this->getAssetCategoryApi()->shouldReturn($assetCategoryApi); + } + + function it_gets_asset_tags_api($assetTagApi) + { + $this->getAssetTagApi()->shouldReturn($assetTagApi); + } + + function it_gets_asset_reference_file_api($assetReferenceFileApi) + { + $this->getAssetReferenceFileApi()->shouldReturn($assetReferenceFileApi); + } + + function it_gets_reference_entity_record_api($referenceEntityRecordApi) + { + $this->getReferenceEntityRecordApi()->shouldReturn($referenceEntityRecordApi); + } + + function it_gets_reference_entity_media_file_api($referenceEntityMediaFileApi) + { + $this->getReferenceEntityMediaFileApi()->shouldReturn($referenceEntityMediaFileApi); + } + + function it_gets_reference_entity_attribute_api($referenceEntityAttributeApi) + { + $this->getReferenceEntityAttributeApi()->shouldReturn($referenceEntityAttributeApi); + } + + function it_gets_reference_entity_api($referenceEntityApi) + { + $this->getReferenceEntityApi()->shouldReturn($referenceEntityApi); + } + + function it_gets_asset_manager_api($assetManagerApi) + { + $this->getAssetManagerApi()->shouldReturn($assetManagerApi); + } + + function it_gets_asset_family_api($assetFamilyApi) + { + $this->getAssetFamilyApi()->shouldReturn($assetFamilyApi); + } + + function it_gets_asset_attribute_api($assetAttributeApi) + { + $this->getAssetAttributeApi()->shouldReturn($assetAttributeApi); + } + + function it_gets_asset_attribute_option_api($assetAttributeOptionApi) + { + $this->getAssetAttributeOptionApi()->shouldReturn($assetAttributeOptionApi); + } + + function it_gets_asset_media_file_api($assetMediaFileApi) + { + $this->getAssetMediaFileApi()->shouldReturn($assetMediaFileApi); + } } diff --git a/spec/Api/AssetApiSpec.php b/spec/Api/AssetApiSpec.php new file mode 100644 index 00000000..b2ea9db8 --- /dev/null +++ b/spec/Api/AssetApiSpec.php @@ -0,0 +1,177 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_initializable() + { + $this->shouldHaveType(AssetApi::class); + } + + function it_gets_an_asset($resourceClient) + { + $asset = [ + 'code' => 'akeneo_logo', + 'localized' => false, + 'description' => 'Akeneo logo', + 'end_of_use' => null, + 'tags' => [], + 'categories' => ['asset_main_catalog'], + 'variation_files' => [], + 'reference_files' => [], + ]; + + $resourceClient->getResource(AssetApi::ASSET_URI, ['akeneo_logo'])->willReturn($asset); + + $this->get('akeneo_logo')->shouldReturn($asset); + } + + function it_returns_a_list_of_assets_with_default_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetApi::ASSETS_URI, [], 10, false, []) + ->willReturn([]); + $pageFactory->createPage([])->willReturn($page); + $this->listPerPage()->shouldReturn($page); + } + + function it_returns_a_list_of_assets_with_limit_and_count( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetApi::ASSETS_URI, [], 10, true, []) + ->willReturn([]); + $pageFactory->createPage([])->willReturn($page); + $this->listPerPage(10, true)->shouldReturn($page); + } + + function it_returns_a_cursor_on_the_list_of_assets( + $resourceClient, + $pageFactory, + $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources( + AssetApi::ASSETS_URI, + [], + 10, + false, + ['pagination_type' => 'search_after'] + ) + ->willReturn([]); + $pageFactory->createPage([])->willReturn($page); + $cursorFactory->createCursor(10, $page)->willReturn($cursor); + $this->all(10, [])->shouldReturn($cursor); + } + + function it_returns_a_list_of_assets_with_additional_query_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetApi::ASSETS_URI, [], 10, true, ['foo' => 'bar']) + ->willReturn([]); + $pageFactory->createPage([])->willReturn($page); + $this->listPerPage(10, true, ['foo' => 'bar'])->shouldReturn($page); + } + + function it_creates_an_asset($resourceClient) + { + $resourceClient->createResource(AssetApi::ASSETS_URI, [], [ + 'code' => 'unicorn', + 'localized' => false, + 'description' => 'The wonderful unicorn', + 'end_of_use' => null, + 'tags' => [], + 'categories' => ['asset_main_catalog'], + 'variation_files' => [], + 'reference_files' => [], + ])->willReturn(201); + + $this->create('unicorn', [ + 'localized' => false, + 'description' => 'The wonderful unicorn', + 'end_of_use' => null, + 'tags' => [], + 'categories' => ['asset_main_catalog'], + 'variation_files' => [], + 'reference_files' => [], + ])->shouldReturn(201); + } + + function it_throws_an_exception_if_code_is_provided_in_data_when_creating_an_asset() + { + $this + ->shouldThrow(new InvalidArgumentException('The parameter "code" should not be defined in the data parameter')) + ->during('create', ['unicorn', ['code' => 'unicorn', 'localized' => false]]); + } + + function it_upserts_an_asset($resourceClient) + { + $resourceClient + ->upsertResource(AssetApi::ASSET_URI, ['akeneo_logo'], [ + 'localized' => false, + 'description' => 'Akeneo logo updated', + 'categories' => ['asset_main_catalog'], + ]) + ->willReturn(204); + + $this->upsert('akeneo_logo', [ + 'localized' => false, + 'description' => 'Akeneo logo updated', + 'categories' => ['asset_main_catalog'], + ])->shouldReturn(204); + } + + function it_upserts_a_list_of_assets($resourceClient, UpsertResourceListResponse $response) + { + $resourceClient->upsertStreamResourceList(AssetApi::ASSETS_URI, [], [ + [ + 'code' => 'akeneo_logo', + 'description' => 'Akeneo logo updated', + ], + [ + 'code' => 'unicorn', + 'description' => 'Created asset', + ] + ])->willReturn($response); + + $this->upsertList([ + [ + 'code' => 'akeneo_logo', + 'description' => 'Akeneo logo updated', + ], + [ + 'code' => 'unicorn', + 'description' => 'Created asset', + ] + ])->shouldReturn($response); + } +} diff --git a/spec/Api/AssetCategoryApiSpec.php b/spec/Api/AssetCategoryApiSpec.php new file mode 100644 index 00000000..2f97dc17 --- /dev/null +++ b/spec/Api/AssetCategoryApiSpec.php @@ -0,0 +1,184 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_initializable() + { + $this->shouldHaveType(AssetCategoryApi::class); + $this->shouldImplement(AssetCategoryApiInterface::class); + $this->shouldImplement(GettableResourceInterface::class); + $this->shouldImplement(ListableResourceInterface::class); + } + + public function it_gets_an_asset_category($resourceClient) + { + $assetCategory = [ + 'code' => 'asset_main_catalog', + 'parent' => null, + 'labels' => [ + 'en_US' => 'dolor sed perferendis', + ], + ]; + + $resourceClient->getResource(AssetCategoryApi::ASSET_CATEGORY_URI, ['asset_main_catalog'])->willReturn($assetCategory); + + $this->get('asset_main_catalog')->shouldReturn($assetCategory); + } + + function it_returns_a_list_of_asset_categories_with_default_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetCategoryApi::ASSET_CATEGORIES_URI, [], 10, false, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage()->shouldReturn($page); + } + + function it_returns_a_list_of_asset_categories_with_limit_and_count( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetCategoryApi::ASSET_CATEGORIES_URI, [], 10, true, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true)->shouldReturn($page); + } + + function it_returns_a_cursor_on_the_list_of_asset_categories( + $resourceClient, + $pageFactory, + $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources( + AssetCategoryApi::ASSET_CATEGORIES_URI, + [], + 10, + false, + [] + ) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $cursorFactory->createCursor(10, $page)->willReturn($cursor); + + $this->all(10, [])->shouldReturn($cursor); + } + + function it_returns_a_list_of_asset_categories_with_additional_query_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetCategoryApi::ASSET_CATEGORIES_URI, [], 10, true, ['foo' => 'bar']) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true, ['foo' => 'bar'])->shouldReturn($page); + } + + function it_upserts_an_asset_category($resourceClient) + { + $resourceClient + ->upsertResource(AssetCategoryApi::ASSET_CATEGORY_URI, ['asset_main_catalog'], [ + 'labels' => [ + 'en_US' => 'Nullam ullamcorper', + ] + ]) + ->willReturn(204); + + $this->upsert('asset_main_catalog', [ + 'labels' => [ + 'en_US' => 'Nullam ullamcorper', + ] + ])->shouldReturn(204); + } + + function it_upserts_a_list_of_asset_categories($resourceClient, UpsertResourceListResponse $response) + { + $resourceClient + ->upsertStreamResourceList( + AssetCategoryApi::ASSET_CATEGORIES_URI, + [], + [ + ['code' => 'asset_1'], + ['code' => 'asset_2'], + ] + ) + ->willReturn($response); + + $this + ->upsertList([ + ['code' => 'asset_1'], + ['code' => 'asset_2'], + ])->shouldReturn($response); + } + + function it_creates_an_asset_category($resourceClient) + { + $resourceClient->createResource(AssetCategoryApi::ASSET_CATEGORIES_URI, [], [ + 'code' => 'asset_spring', + 'parent' => null, + 'labels' => [ + 'en_US' => 'Nullam ullamcorper', + ], + ])->willReturn(201); + + $this->create('asset_spring', [ + 'parent' => null, + 'labels' => [ + 'en_US' => 'Nullam ullamcorper', + ], + ])->shouldReturn(201); + } + + function it_throws_an_exception_if_code_is_provided_in_data_when_creating_an_asset_category() + { + $this + ->shouldThrow(new InvalidArgumentException('The parameter "code" should not be defined in the data parameter')) + ->during('create', ['asset_spring', [ + 'code' => 'asset_spring', + 'parent' => null, + 'labels' => [ + 'en_US' => 'Nullam ullamcorper', + ], + ]]); + } +} diff --git a/spec/Api/AssetReferenceFileApiSpec.php b/spec/Api/AssetReferenceFileApiSpec.php new file mode 100644 index 00000000..f5ac58a9 --- /dev/null +++ b/spec/Api/AssetReferenceFileApiSpec.php @@ -0,0 +1,213 @@ +beConstructedWith($resourceClient, $fileSystem); + } + + function it_is_initializable() + { + $this->shouldHaveType(AssetReferenceFileApi::class); + $this->shouldImplement(AssetReferenceFileApiInterface::class); + } + + function it_gets_a_localizable_asset_reference_file($resourceClient) + { + $assetReferenceFile = [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_Ziggy.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => 'http://akeneo-ped-master.local/api/rest/v1/assets/ziggy/reference-files/en_US/download' + ] + ], + ]; + + $resourceClient + ->getResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', 'en_US']) + ->willReturn($assetReferenceFile); + + $this->getFromLocalizableAsset('ziggy', 'en_US')->shouldReturn($assetReferenceFile); + } + + function it_gets_a_not_localizable_asset_reference_file($resourceClient) + { + $assetReferenceFile = [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_Ziggy.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => 'http://akeneo-ped-master.local/api/rest/v1/assets/ziggy/reference-files/no-locale/download' + ] + ], + ]; + + $resourceClient + ->getResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE]) + ->willReturn($assetReferenceFile); + + $this->getFromNotLocalizableAsset('ziggy')->shouldReturn($assetReferenceFile); + } + + function it_uploads_a_localizable_asset_reference_file( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath('images/ziggy.png')->willReturn('fileResource'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => 'fileResource', + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', 'en_US'], $requestParts) + ->willReturn($response); + + $this->uploadForLocalizableAsset('images/ziggy.png', 'ziggy', 'en_US')->shouldReturn(201); + } + + function it_uploads_a_not_localizable_asset_reference_file( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath('images/ziggy.png')->willReturn('fileResource'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => 'fileResource', + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE], $requestParts) + ->willReturn($response); + + $this->uploadForNotLocalizableAsset('images/ziggy.png', 'ziggy')->shouldReturn(201); + } + + function it_uploads_an_asset_reference_file_from_a_file_resource( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath(Argument::any())->shouldNotBeCalled(); + + $fileResource = fopen('php://stdin', 'r'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => $fileResource, + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', 'en_US'], $requestParts) + ->willReturn($response); + + $this->uploadForLocalizableAsset($fileResource, 'ziggy', 'en_US')->shouldReturn(201); + } + + function it_throws_an_exception_if_the_upload_response_contains_errors( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath('images/ziggy.png')->willReturn('fileResource'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => 'fileResource', + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + + $responseContent = +<<getContents()->willReturn($responseContent); + + $resourceClient + ->createMultipartResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, ['ziggy', 'en_US'], $requestParts) + ->willReturn($response); + + $this->shouldThrow(new UploadAssetReferenceFileErrorException('Some variation files were not generated properly.', [ + [ + 'message' => 'Impossible to "resize" the image "/tmp/pim/file_storage/4/2/5/1/ziggy-en_US-ecommerce.png" with a width bigger than the original.', + 'scope' => 'ecommerce', + 'locale' => 'en_US' + ], + [ + 'message' => 'Impossible to "resize" the image "/tmp/pim/file_storage/4/2/5/1/ziggy-en_US-mobile.png" with a height bigger than the original.', + 'scope' => 'mobile', + 'locale' => 'en_US' + ] + ])) + ->during('uploadForLocalizableAsset', ['images/ziggy.png', 'ziggy', 'en_US']); + } + + function it_downloads_a_localizable_asset_reference_file($resourceClient, ResponseInterface $response, StreamInterface $streamBody) + { + $resourceClient + ->getStreamedResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, ['ziggy', 'en_US']) + ->willReturn($response); + + $this->downloadFromLocalizableAsset('ziggy', 'en_US')->shouldReturn($response); + } + + function it_downloads_a_not_localizable_asset_reference_file($resourceClient, ResponseInterface $response, StreamInterface $streamBody) + { + $resourceClient + ->getStreamedResource(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, ['ziggy', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE]) + ->willReturn($response); + + $this->downloadFromNotLocalizableAsset('ziggy')->shouldReturn($response); + } +} diff --git a/spec/Api/AssetTagApiSpec.php b/spec/Api/AssetTagApiSpec.php new file mode 100644 index 00000000..10147c96 --- /dev/null +++ b/spec/Api/AssetTagApiSpec.php @@ -0,0 +1,111 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + public function it_is_initializable() + { + $this->shouldHaveType('Akeneo\Pim\ApiClient\Api\AssetTagApi'); + } + + public function it_gets_an_asset_tag($resourceClient) + { + $assetTag = ['code' => 'logo']; + + $resourceClient->getResource(AssetTagApi::ASSET_TAG_URI, ['logo'])->willReturn($assetTag); + + $this->get('logo')->shouldReturn($assetTag); + } + + public function it_upserts_an_asset_tag($resourceClient) + { + $resourceClient + ->upsertResource(AssetTagApi::ASSET_TAG_URI, ['logo'], []) + ->willReturn(201); + + $this->upsert('logo')->shouldReturn(201); + } + + function it_returns_a_list_of_asset_tags_with_default_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetTagApi::ASSET_TAGS_URI, [], 10, false, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage()->shouldReturn($page); + } + + function it_returns_a_list_of_asset_tags_with_limit_and_count( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetTagApi::ASSET_TAGS_URI, [], 10, true, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true)->shouldReturn($page); + } + + function it_returns_a_cursor_on_the_list_of_asset_tags( + $resourceClient, + $pageFactory, + $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources( + AssetTagApi::ASSET_TAGS_URI, + [], + 10, + false, + [] + ) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $cursorFactory->createCursor(10, $page)->willReturn($cursor); + + $this->all(10, [])->shouldReturn($cursor); + } + + function it_returns_a_list_of_asset_tags_with_additional_query_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(AssetTagApi::ASSET_TAGS_URI, [], 10, true, ['foo' => 'bar']) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true, ['foo' => 'bar'])->shouldReturn($page); + } +} diff --git a/spec/Api/AssetVariationFileApiSpec.php b/spec/Api/AssetVariationFileApiSpec.php new file mode 100644 index 00000000..7e2b427b --- /dev/null +++ b/spec/Api/AssetVariationFileApiSpec.php @@ -0,0 +1,138 @@ +beConstructedWith($resourceClient, $fileSystem); + } + + function it_is_initializable() + { + $this->shouldHaveType(AssetVariationFileApi::class); + $this->shouldImplement(AssetVariationFileApiInterface::class); + } + + function it_gets_a_localizable_asset_variation_file($resourceClient) + { + $assetVariationFile = [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_ziggy_en_US_mobile.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => 'http://akeneo-ped-master.local/api/rest/v1/assets/ziggy/variation-files/mobile/en_US/download' + ] + ], + ]; + + $resourceClient + ->getResource(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, ['ziggy', 'mobile', 'en_US']) + ->willReturn($assetVariationFile); + + $this->getFromLocalizableAsset('ziggy', 'mobile', 'en_US')->shouldReturn($assetVariationFile); + } + + function it_gets_a_not_localizable_asset_variation_file($resourceClient) + { + $assetVariationFile = [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_ziggy_mobile.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => 'http://akeneo-ped-master.local/api/rest/v1/assets/ziggy/variation-files/mobile/no-locale/download' + ] + ], + ]; + + $resourceClient + ->getResource(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, ['ziggy', 'mobile', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE]) + ->willReturn($assetVariationFile); + + $this->getFromNotLocalizableAsset('ziggy', 'mobile')->shouldReturn($assetVariationFile); + } + + function it_uploads_a_localizable_asset_variation_file( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath('images/ziggy.png')->willReturn('fileResource'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => 'fileResource', + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, ['ziggy', 'mobile', 'en_US'], $requestParts) + ->willReturn($response); + + $this->uploadForLocalizableAsset('images/ziggy.png', 'ziggy', 'mobile', 'en_US')->shouldReturn(201); + } + + function it_uploads_a_not_localizable_asset_variation_file( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath('images/ziggy.png')->willReturn('fileResource'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => 'fileResource', + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, ['ziggy', 'mobile', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE], $requestParts) + ->willReturn($response); + + $this->uploadForNotLocalizableAsset('images/ziggy.png', 'ziggy', 'mobile')->shouldReturn(201); + } + + function it_uploads_an_asset_variation_file_from_a_file_resource( + $resourceClient, + $fileSystem, + ResponseInterface $response, + StreamInterface $responseBody + ) { + $fileSystem->getResourceFromPath(Argument::any())->shouldNotBeCalled(); + + $fileResource = fopen('php://stdin', 'r'); + + $requestParts = [[ + 'name' => 'file', + 'contents' => $fileResource, + ]]; + + $response->getStatusCode()->willReturn(201); + $response->getBody()->willReturn($responseBody); + $responseBody->getContents()->willReturn(''); + + $resourceClient + ->createMultipartResource(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, ['ziggy', 'mobile', 'en_US'], $requestParts) + ->willReturn($response); + + $this->uploadForLocalizableAsset($fileResource, 'ziggy', 'mobile', 'en_US')->shouldReturn(201); + } +} diff --git a/spec/Api/LocaleApiSpec.php b/spec/Api/LocaleApiSpec.php index 3e82385e..798749a8 100644 --- a/spec/Api/LocaleApiSpec.php +++ b/spec/Api/LocaleApiSpec.php @@ -6,8 +6,8 @@ use Akeneo\Pim\ApiClient\Api\LocaleApiInterface; use Akeneo\Pim\ApiClient\Api\Operation\ListableResourceInterface; use Akeneo\Pim\ApiClient\Client\ResourceClientInterface; -use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\PageFactoryInterface; +use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; use PhpSpec\ObjectBehavior; diff --git a/spec/Api/MeasurementFamilyApiSpec.php b/spec/Api/MeasurementFamilyApiSpec.php index cf03d5ab..3cf27dd7 100644 --- a/spec/Api/MeasurementFamilyApiSpec.php +++ b/spec/Api/MeasurementFamilyApiSpec.php @@ -4,14 +4,7 @@ use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApi; use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApiInterface; -use Akeneo\Pim\ApiClient\Api\Operation\ListableResourceInterface; -use Akeneo\Pim\ApiClient\Api\Operation\UpsertableResourceListInterface; use Akeneo\Pim\ApiClient\Client\ResourceClientInterface; -use Akeneo\Pim\ApiClient\Pagination\PageFactoryInterface; -use Akeneo\Pim\ApiClient\Pagination\PageInterface; -use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface; -use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; -use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponse; use PhpSpec\ObjectBehavior; class MeasurementFamilyApiSpec extends ObjectBehavior diff --git a/spec/Api/ProductApiSpec.php b/spec/Api/ProductApiSpec.php index 37491985..6a9855bc 100644 --- a/spec/Api/ProductApiSpec.php +++ b/spec/Api/ProductApiSpec.php @@ -12,8 +12,8 @@ use Akeneo\Pim\ApiClient\Api\ProductApiInterface; use Akeneo\Pim\ApiClient\Client\ResourceClientInterface; use Akeneo\Pim\ApiClient\Exception\InvalidArgumentException; -use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\PageFactoryInterface; +use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponse; diff --git a/spec/Api/ProductDraftApiSpec.php b/spec/Api/ProductDraftApiSpec.php new file mode 100644 index 00000000..bd41142e --- /dev/null +++ b/spec/Api/ProductDraftApiSpec.php @@ -0,0 +1,59 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_initializable() + { + $this->shouldHaveType(ProductDraftApi::class); + $this->shouldImplement(ProductDraftApiInterface::class); + $this->shouldImplement(GettableResourceInterface::class); + } + + function it_gets_a_product_draft($resourceClient) + { + $draft = [ + 'identifier' => 'foo', + 'family' => 'bar', + 'parent' => null, + 'groups' => [], + 'categories' => [], + 'enabled' => true, + 'values' => [], + 'created' => 'this is a date formatted to ISO-8601', + 'updated' => 'this is a date formatted to ISO-8601', + 'associations' => [], + 'metadata' => [ + 'workflow_status' => 'draft_in_progress', + ], + ]; + + $resourceClient->getResource(ProductDraftApi::PRODUCT_DRAFT_URI, ['foo'])->willReturn($draft); + + $this->get('foo')->shouldReturn($draft); + } + + function it_submits_a_product_draft_for_approval($resourceClient) + { + $resourceClient->createResource(ProductDraftApi::PRODUCT_PROPOSAL_URI, ['foo'])->willReturn(201); + + $this->submitForApproval('foo')->shouldReturn(201); + } +} diff --git a/spec/Api/ProductMediaFileApiSpec.php b/spec/Api/ProductMediaFileApiSpec.php index dd887d07..d5d7db9d 100644 --- a/spec/Api/ProductMediaFileApiSpec.php +++ b/spec/Api/ProductMediaFileApiSpec.php @@ -2,16 +2,16 @@ namespace spec\Akeneo\Pim\ApiClient\Api; +use Akeneo\Pim\ApiClient\Api\MediaFileApiInterface; use Akeneo\Pim\ApiClient\Api\Operation\DownloadableResourceInterface; use Akeneo\Pim\ApiClient\Api\Operation\GettableResourceInterface; use Akeneo\Pim\ApiClient\Api\Operation\ListableResourceInterface; use Akeneo\Pim\ApiClient\Api\ProductMediaFileApi; -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\PageInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; use PhpSpec\ObjectBehavior; diff --git a/spec/Api/ProductModelDraftApiSpec.php b/spec/Api/ProductModelDraftApiSpec.php new file mode 100644 index 00000000..6ef8ab7a --- /dev/null +++ b/spec/Api/ProductModelDraftApiSpec.php @@ -0,0 +1,56 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_initializable() + { + $this->shouldHaveType(ProductModelDraftApi::class); + $this->shouldImplement(ProductModelDraftApiInterface::class); + $this->shouldImplement(GettableResourceInterface::class); + } + + function it_gets_a_product_model_draft($resourceClient) + { + $draft = [ + 'identifier' => 'a_product_model', + 'family_variant' => 'bar', + 'parent' => null, + 'values' => [], + 'created' => 'this is a date formatted to ISO-8601', + 'updated' => 'this is a date formatted to ISO-8601', + 'associations' => [], + 'metadata' => [ + 'workflow_status' => 'draft_in_progress', + ], + ]; + + $resourceClient->getResource(ProductModelDraftApi::PRODUCT_MODEL_DRAFT_URI, ['a_product_model'])->willReturn($draft); + + $this->get('a_product_model')->shouldReturn($draft); + } + + function it_submits_a_product_model_draft_for_approval($resourceClient) + { + $resourceClient->createResource(ProductModelDraftApi::PRODUCT_MODEL_PROPOSAL_URI, ['a_product_model'])->willReturn(201); + + $this->submitForApproval('a_product_model')->shouldReturn(201); + } +} diff --git a/spec/Api/PublishedProductApiSpec.php b/spec/Api/PublishedProductApiSpec.php new file mode 100644 index 00000000..5e3ac249 --- /dev/null +++ b/spec/Api/PublishedProductApiSpec.php @@ -0,0 +1,118 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_initializable() + { + $this->shouldHaveType(PublishedProductApi::class); + $this->shouldImplement(PublishedProductApiInterface::class); + $this->shouldImplement(GettableResourceInterface::class); + $this->shouldImplement(ListableResourceInterface::class); + } + + function it_returns_a_published_product($resourceClient) + { + $publishedProductCode = 'foo'; + $publishedProduct = [ + 'identifier' => 'foo', + 'family' => 'tshirts', + 'enabled' => true, + 'categories' => [ + 'bar', + ], + ]; + + $resourceClient + ->getResource(PublishedProductApi::PUBLISHED_PRODUCT_URI, [$publishedProductCode]) + ->willReturn($publishedProduct); + + $this->get($publishedProductCode)->shouldReturn($publishedProduct); + } + + function it_returns_a_list_of_published_products_with_default_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(PublishedProductApi::PUBLISHED_PRODUCTS_URI, [], 10, false, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage()->shouldReturn($page); + } + + function it_returns_a_list_of_published_products_with_limit_and_count( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(PublishedProductApi::PUBLISHED_PRODUCTS_URI, [], 10, true, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true)->shouldReturn($page); + } + + function it_returns_a_cursor_on_the_list_of_published_products( + $resourceClient, + $pageFactory, + $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources( + PublishedProductApi::PUBLISHED_PRODUCTS_URI, + [], + 10, + false, + ['pagination_type' => 'search_after'] + ) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $cursorFactory->createCursor(10, $page)->willReturn($cursor); + + $this->all(10, [])->shouldReturn($cursor); + } + + function it_returns_a_list_of_published_products_with_additional_query_parameters( + $resourceClient, + $pageFactory, + PageInterface $page + ) { + $resourceClient + ->getResources(PublishedProductApi::PUBLISHED_PRODUCTS_URI, [], 10, true, ['foo' => 'bar']) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + + $this->listPerPage(10, true, ['foo' => 'bar'])->shouldReturn($page); + } +} diff --git a/spec/Api/ReferenceEntityApiSpec.php b/spec/Api/ReferenceEntityApiSpec.php new file mode 100644 index 00000000..41251643 --- /dev/null +++ b/spec/Api/ReferenceEntityApiSpec.php @@ -0,0 +1,84 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_a_reference_entity_api() + { + $this->shouldImplement(ReferenceEntityApiInterface::class); + } + + function it_returns_a_reference_entity(ResourceClientInterface $resourceClient) + { + $referenceEntity = [ + '_links' => [ + 'image_download' => [ + 'href' => 'https://localhost/api/rest/v1/reference-entities-media-files/img.png' + ] + ], + 'code' => 'designer', + 'labels' => [ + 'en_US' => 'Designer' + ], + 'image' => 'img.png' + ]; + + $resourceClient + ->getResource(ReferenceEntityApi::REFERENCE_ENTITY_URI, ['designer']) + ->willReturn($referenceEntity); + + $this->get('designer')->shouldReturn($referenceEntity); + } + + function it_returns_a_cursor_to_list_all_the_reference_entities( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources(ReferenceEntityApi::REFERENCE_ENTITIES_URI, [], null, false, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + $cursorFactory->createCursor(null, $page)->willReturn($cursor); + + $this->all()->shouldReturn($cursor); + } + + function it_upserts_a_reference_entity(ResourceClientInterface $resourceClient) + { + $referenceEntityData = [ + 'code' => 'designer', + 'labels' => [ + 'en_US' => 'Designer' + ] + ]; + $resourceClient + ->upsertResource(ReferenceEntityApi::REFERENCE_ENTITY_URI, ['designer'], $referenceEntityData) + ->willReturn(204); + + $this->upsert('designer', $referenceEntityData)->shouldReturn(204); + } +} diff --git a/spec/Api/ReferenceEntityAttributeApiSpec.php b/spec/Api/ReferenceEntityAttributeApiSpec.php new file mode 100644 index 00000000..d4773201 --- /dev/null +++ b/spec/Api/ReferenceEntityAttributeApiSpec.php @@ -0,0 +1,126 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_a_reference_entity_attribute_api() + { + $this->shouldImplement(ReferenceEntityAttributeApiInterface::class); + } + + function it_returns_a_reference_entity_attribute(ResourceClientInterface $resourceClient) + { + $attribute = [ + 'code' => 'description', + 'labels' => [ + 'en_US' => 'Description', + 'fr_FR' => 'Description', + ], + 'type' => 'text', + 'localizable' => true, + 'scopable' => false, + 'is_required_for_completeness' => true, + 'max_characters' => null, + 'is_textarea' => true, + 'is_rich_text_editor' => true, + 'validation_rule' => null, + 'validation_regexp' => null, + ]; + + $resourceClient + ->getResource(ReferenceEntityAttributeApi::REFERENCE_ENTITY_ATTRIBUTE_URI, ['designer', 'description']) + ->willReturn($attribute); + + $this->get('designer', 'description')->shouldReturn($attribute); + } + + function it_returns_a_cursor_to_list_all_the_attributes_of_a_reference_entity(ResourceClientInterface $resourceClient) + { + $attributes = [ + [ + 'code' => 'label', + 'labels' => [ + 'en_US' => 'Label', + ], + 'type' => 'text', + 'localizable' => true, + 'scopable' => false, + 'is_required_for_completeness' => false, + 'max_characters' => null, + 'is_textarea' => false, + 'is_rich_text_editor' => false, + 'validation_rule' => 'none', + 'validation_regexp' => null, + '_links' => [ + 'self' => [ + 'href' => 'http://localhost/api/rest/v1/reference-entities/designer/attributes/label', + ], + ], + ], + [ + 'code' => 'birthdate', + 'labels' => [ + 'en_US' => 'Birthdate', + ], + 'type' => 'text', + 'localizable' => false, + 'scopable' => false, + 'is_required_for_completeness' => false, + 'max_characters' => null, + 'is_textarea' => false, + 'is_rich_text_editor' => false, + 'validation_rule' => 'none', + 'validation_regexp' => null, + '_links' => [ + 'self' => [ + 'href' => 'http://localhost/api/rest/v1/reference-entities/designer/attributes/birthdate', + ], + ], + ], + ]; + + $resourceClient + ->getResource(ReferenceEntityAttributeApi::REFERENCE_ENTITY_ATTRIBUTES_URI, ['designer']) + ->willReturn($attributes); + + $this->all('designer', [])->shouldReturn($attributes); + } + + function it_upserts_a_reference_entity_attribute(ResourceClientInterface $resourceClient) + { + $attributeData = [ + 'code' => 'description', + 'labels' => [ + 'en_US' => 'Description', + 'fr_FR' => 'Description', + ], + 'type' => 'text', + 'localizable' => true, + 'scopable' => false + ]; + + $resourceClient + ->upsertResource(ReferenceEntityAttributeApi::REFERENCE_ENTITY_ATTRIBUTE_URI, ['designer', 'description'], $attributeData) + ->willReturn(204); + + $this->upsert('designer', 'description', $attributeData)->shouldReturn(204); + } +} diff --git a/spec/Api/ReferenceEntityAttributeOptionApiSpec.php b/spec/Api/ReferenceEntityAttributeOptionApiSpec.php new file mode 100644 index 00000000..14ca5610 --- /dev/null +++ b/spec/Api/ReferenceEntityAttributeOptionApiSpec.php @@ -0,0 +1,91 @@ +beConstructedWith($resourceClient); + } + + function it_is_a_reference_entity_attribute_api() + { + $this->shouldImplement(ReferenceEntityAttributeOptionApiInterface::class); + } + + function it_returns_a_reference_entity_attribute_option(ResourceClientInterface $resourceClient) + { + $option = [ + 'code' => 'red', + 'labels' => [ + 'en_US' => 'Red', + 'fr_FR' => 'Rouge', + ], + ]; + + $resourceClient + ->getResource( + ReferenceEntityAttributeOptionApi::REFERENCE_ENTITY_ATTRIBUTE_OPTION_URI, + ['designer', 'favorite_color', 'red'] + ) + ->willReturn($option); + + $this->get('designer', 'favorite_color', 'red')->shouldReturn($option); + } + + function it_returns_the_list_of_attribute_options_of_a_reference_entity_attribute(ResourceClientInterface $resourceClient) + { + $options = [ + [ + 'code' => 'red', + 'labels' => [ + 'en_US' => 'Red', + 'fr_FR' => 'Rouge', + ], + ], + [ + 'code' => 'blue', + 'labels' => [ + 'en_US' => 'Blue', + 'fr_FR' => 'Bleu', + ], + ] + ]; + + $resourceClient + ->getResource( + ReferenceEntityAttributeOptionApi::REFERENCE_ENTITY_ATTRIBUTE_OPTIONS_URI, + ['designer', 'favorite_color'] + ) + ->willReturn($options); + + $this->all('designer', 'favorite_color')->shouldReturn($options); + } + + function it_upserts_a_reference_entity_attribute_option(ResourceClientInterface $resourceClient) + { + $option = [ + 'code' => 'red', + 'labels' => [ + 'en_US' => 'Red', + 'fr_FR' => 'Rouge', + ], + ]; + + $resourceClient + ->upsertResource( + ReferenceEntityAttributeOptionApi::REFERENCE_ENTITY_ATTRIBUTE_OPTION_URI, + ['designer', 'favorite_color', 'red'], + $option + ) + ->willReturn(204); + + $this->upsert('designer', 'favorite_color', 'red', $option)->shouldReturn(204); + } +} diff --git a/spec/Api/ReferenceEntityMediaFileApiSpec.php b/spec/Api/ReferenceEntityMediaFileApiSpec.php new file mode 100644 index 00000000..e0abd26f --- /dev/null +++ b/spec/Api/ReferenceEntityMediaFileApiSpec.php @@ -0,0 +1,63 @@ +beConstructedWith($resourceClient, $fileSystem); + } + + function it_is_a_reference_entity_media_file_api() + { + $this->shouldImplement(ReferenceEntityMediaFileApiInterface::class); + } + + function it_downloads_a_reference_entity_media_file(ResourceClientInterface $resourceClient, ResponseInterface $response) + { + $resourceClient + ->getStreamedResource(ReferenceEntityMediaFileApi::MEDIA_FILE_DOWNLOAD_URI, ['images/starck.jpg']) + ->willReturn($response); + + $this->download('images/starck.jpg')->shouldReturn($response); + } + + function it_creates_a_reference_entity_media_file( + ResourceClientInterface $resourceClient, + FileSystemInterface $fileSystem, + ResponseInterface $response + ) { + $fileResource = fopen('php://memory', 'r'); + $fileSystem->getResourceFromPath(Argument::any())->shouldNotBeCalled(); + + $requestParts = [ + [ + 'name' => 'file', + 'contents' => $fileResource, + ] + ]; + + $response->getHeader('Reference-entities-media-file-code')->shouldBeCalled()->willReturn( + [ + '0/f/b/f/0fbffddc95c3d610b39e3f3797b14c6c33e98a4f_starck.jpg' + ] + ); + + $resourceClient + ->createMultipartResource(ReferenceEntityMediaFileApi::MEDIA_FILE_CREATE_URI, [], $requestParts) + ->shouldBeCalled() + ->willReturn($response); + + $this->create($fileResource) + ->shouldReturn('0/f/b/f/0fbffddc95c3d610b39e3f3797b14c6c33e98a4f_starck.jpg'); + } +} diff --git a/spec/Api/ReferenceEntityRecordApiSpec.php b/spec/Api/ReferenceEntityRecordApiSpec.php new file mode 100644 index 00000000..808c4cc9 --- /dev/null +++ b/spec/Api/ReferenceEntityRecordApiSpec.php @@ -0,0 +1,137 @@ +beConstructedWith($resourceClient, $pageFactory, $cursorFactory); + } + + function it_is_a_reference_entity_record_api() + { + $this->shouldImplement(ReferenceEntityRecordApiInterface::class); + } + + function it_returns_a_reference_entity_record(ResourceClientInterface $resourceClient) + { + $record = [ + 'code' => 'starck', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'Philippe Starck' + ], + ] + ] + ]; + + $resourceClient + ->getResource(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORD_URI, ['designer', 'starck']) + ->willReturn($record); + + $this->get('designer', 'starck')->shouldReturn($record); + } + + function it_returns_a_cursor_to_list_all_the_records_of_reference_entity( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory, + PageInterface $page, + ResourceCursorInterface $cursor + ) { + $resourceClient + ->getResources(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORDS_URI, ['designer'], null, false, []) + ->willReturn([]); + + $pageFactory->createPage([])->willReturn($page); + $cursorFactory->createCursor(null, $page)->willReturn($cursor); + + $this->all('designer', [])->shouldReturn($cursor); + } + + function it_upserts_a_reference_entity_record(ResourceClientInterface $resourceClient) + { + $recordData = [ + 'code' => 'starck', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'Philippe Starck' + ], + ] + ] + ]; + $resourceClient + ->upsertResource(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORD_URI, ['designer', 'starck'], $recordData) + ->willReturn(204); + + $this->upsert('designer', 'starck', $recordData)->shouldReturn(204); + } + + function it_upserts_a_list_of_reference_entity_records(ResourceClientInterface $resourceClient) + { + $records = [ + [ + 'code' => 'starck', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'Philippe Starck' + ], + ] + ] + ], + [ + 'code' => 'dyson', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'James Dyson' + ], + ] + ] + ] + ]; + + $responses = [ + [ + 'code' => 'starck', + 'status_code' =>204 + ], + [ + 'code' => 'dyson', + 'status_code' =>201 + ], + ]; + + $resourceClient + ->upsertJsonResourceList(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORDS_URI, ['designer'], $records) + ->willReturn($responses); + + $this->upsertList('designer', $records)->shouldReturn($responses); + } +} diff --git a/spec/Client/AuthenticatedHttpClientSpec.php b/spec/Client/AuthenticatedHttpClientSpec.php index 35ab751d..8ae0b81f 100644 --- a/spec/Client/AuthenticatedHttpClientSpec.php +++ b/spec/Client/AuthenticatedHttpClientSpec.php @@ -3,10 +3,10 @@ namespace spec\Akeneo\Pim\ApiClient\Client; use Akeneo\Pim\ApiClient\Api\AuthenticationApiInterface; -use Akeneo\Pim\ApiClient\Exception\UnauthorizedHttpException; use Akeneo\Pim\ApiClient\Client\AuthenticatedHttpClient; use Akeneo\Pim\ApiClient\Client\HttpClient; use Akeneo\Pim\ApiClient\Client\HttpClientInterface; +use Akeneo\Pim\ApiClient\Exception\UnauthorizedHttpException; use Akeneo\Pim\ApiClient\Security\Authentication; use PhpSpec\ObjectBehavior; use Psr\Http\Message\ResponseInterface; diff --git a/spec/Client/HttpClientSpec.php b/spec/Client/HttpClientSpec.php index c139eaa9..5141e4cc 100644 --- a/spec/Client/HttpClientSpec.php +++ b/spec/Client/HttpClientSpec.php @@ -3,8 +3,8 @@ namespace spec\Akeneo\Pim\ApiClient\Client; use Akeneo\Pim\ApiClient\Client\HttpClient; -use Akeneo\Pim\ApiClient\Exception\HttpException; use Akeneo\Pim\ApiClient\Client\HttpClientInterface; +use Akeneo\Pim\ApiClient\Exception\HttpException; use PhpSpec\ObjectBehavior; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; diff --git a/spec/Client/HttpExceptionHandlerSpec.php b/spec/Client/HttpExceptionHandlerSpec.php index e70db4b2..f26ec7d0 100644 --- a/spec/Client/HttpExceptionHandlerSpec.php +++ b/spec/Client/HttpExceptionHandlerSpec.php @@ -2,6 +2,7 @@ namespace spec\Akeneo\Pim\ApiClient\Client; +use Akeneo\Pim\ApiClient\Client\HttpExceptionHandler; use Akeneo\Pim\ApiClient\Exception\BadRequestHttpException; use Akeneo\Pim\ApiClient\Exception\ClientErrorHttpException; use Akeneo\Pim\ApiClient\Exception\ForbiddenHttpException; @@ -13,7 +14,6 @@ use Akeneo\Pim\ApiClient\Exception\TooManyRequestsHttpException; use Akeneo\Pim\ApiClient\Exception\UnauthorizedHttpException; use Akeneo\Pim\ApiClient\Exception\UnprocessableEntityHttpException; -use Akeneo\Pim\ApiClient\Client\HttpExceptionHandler; use Akeneo\Pim\ApiClient\Exception\UnsupportedMediaTypeHttpException; use PhpSpec\ObjectBehavior; use Psr\Http\Message\RequestInterface; diff --git a/spec/Client/ResourceClientSpec.php b/spec/Client/ResourceClientSpec.php index 8f683e82..84064540 100644 --- a/spec/Client/ResourceClientSpec.php +++ b/spec/Client/ResourceClientSpec.php @@ -2,14 +2,14 @@ namespace spec\Akeneo\Pim\ApiClient\Client; +use Akeneo\Pim\ApiClient\Client\HttpClient; use Akeneo\Pim\ApiClient\Client\HttpClientInterface; use Akeneo\Pim\ApiClient\Client\ResourceClient; use Akeneo\Pim\ApiClient\Client\ResourceClientInterface; use Akeneo\Pim\ApiClient\Exception\InvalidArgumentException; -use Akeneo\Pim\ApiClient\Client\HttpClient; use Akeneo\Pim\ApiClient\MultipartStream\MultipartStreamBuilder; -use Akeneo\Pim\ApiClient\Stream\MultipartStreamBuilderFactory; use Akeneo\Pim\ApiClient\Routing\UriGeneratorInterface; +use Akeneo\Pim\ApiClient\Stream\MultipartStreamBuilderFactory; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponse; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponseFactory; use PhpSpec\ObjectBehavior; diff --git a/spec/Exception/HttpExceptionSpec.php b/spec/Exception/HttpExceptionSpec.php index 2da09893..a44ca5bc 100644 --- a/spec/Exception/HttpExceptionSpec.php +++ b/spec/Exception/HttpExceptionSpec.php @@ -7,7 +7,6 @@ use PhpSpec\ObjectBehavior; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; class HttpExceptionSpec extends ObjectBehavior { diff --git a/src/AkeneoPimClient.php b/src/AkeneoPimClient.php index bda181ce..8bdb5a9a 100644 --- a/src/AkeneoPimClient.php +++ b/src/AkeneoPimClient.php @@ -2,6 +2,16 @@ namespace Akeneo\Pim\ApiClient; +use Akeneo\Pim\ApiClient\Api\AssetApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetCategoryApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetApiInterface as AssetManagerApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetFamilyApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetReferenceFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetTagApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetVariationFileApiInterface; use Akeneo\Pim\ApiClient\Api\AssociationTypeApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeGroupApiInterface; @@ -16,7 +26,15 @@ use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApiInterface; use Akeneo\Pim\ApiClient\Api\MediaFileApiInterface; use Akeneo\Pim\ApiClient\Api\ProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductDraftApiInterface; use Akeneo\Pim\ApiClient\Api\ProductModelApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductModelDraftApiInterface; +use Akeneo\Pim\ApiClient\Api\PublishedProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityRecordApiInterface; use Akeneo\Pim\ApiClient\Security\Authentication; /** @@ -76,6 +94,60 @@ class AkeneoPimClient implements AkeneoPimClientInterface /** @var MeasurementFamilyApiInterface */ private $measurementFamilyApi; + /** @var PublishedProductApiInterface */ + private $publishedProductApi; + + /** @var ProductModelDraftApiInterface */ + private $productModelDraftApi; + + /** @var ProductDraftApiInterface */ + private $productDraftApi; + + /** @var AssetApiInterface */ + private $assetApi; + + /** @var AssetCategoryApiInterface */ + private $assetCategoryApi; + + /** @var AssetTagApiInterface */ + private $assetTagApi; + + /** @var AssetReferenceFileApiInterface */ + private $assetReferenceFileApi; + + /** @var AssetVariationFileApiInterface */ + private $assetVariationFileApi; + + /** @var ReferenceEntityRecordApiInterface */ + private $referenceEntityRecordApi; + + /** @var ReferenceEntityMediaFileApiInterface */ + private $referenceEntityMediaFileApi; + + /** @var ReferenceEntityAttributeApiInterface */ + private $referenceEntityAttributeApi; + + /** @var ReferenceEntityAttributeOptionApiInterface */ + private $referenceEntityAttributeOptionApi; + + /** @var ReferenceEntityApiInterface */ + private $referenceEntityApi; + + /** @var AssetManagerApiInterface */ + private $assetManagerApi; + + /** @var AssetFamilyApiInterface */ + private $assetFamilyApi; + + /** @var AssetAttributeApiInterface */ + private $assetAttributeApi; + + /** @var AssetAttributeOptionApiInterface */ + private $assetAttributeOptionApi; + + /** @var AssetMediaFileApiInterface */ + private $assetMediaFileApi; + public function __construct( Authentication $authentication, ProductApiInterface $productApi, @@ -92,7 +164,25 @@ public function __construct( MeasurementFamilyApiInterface $measurementFamilyApi, AssociationTypeApiInterface $associationTypeApi, FamilyVariantApiInterface $familyVariantApi, - ProductModelApiInterface $productModelApi + ProductModelApiInterface $productModelApi, + ProductModelDraftApiInterface $productModelDraftApi, + PublishedProductApiInterface $publishedProductApi, + ProductDraftApiInterface $productDraftApi, + AssetApiInterface $assetApi, + AssetCategoryApiInterface $assetCategoryApi, + AssetTagApiInterface $assetTagApi, + AssetReferenceFileApiInterface $assetReferenceFileApi, + AssetVariationFileApiInterface $assetVariationFileApi, + ReferenceEntityRecordApiInterface $referenceEntityRecordApi, + ReferenceEntityMediaFileApiInterface $referenceEntityMediaFileApi, + ReferenceEntityAttributeApiInterface $referenceEntityAttributeApi, + ReferenceEntityAttributeOptionApiInterface $referenceEntityAttributeOptionApi, + ReferenceEntityApiInterface $referenceEntityApi, + AssetManagerApiInterface $assetManagerApi, + AssetFamilyApiInterface $assetFamilyApi, + AssetAttributeApiInterface $assetAttributeApi, + AssetAttributeOptionApiInterface $assetAttributeOptionApi, + AssetMediaFileApiInterface $assetMediaFileApi ) { $this->authentication = $authentication; $this->productApi = $productApi; @@ -110,6 +200,24 @@ public function __construct( $this->associationTypeApi = $associationTypeApi; $this->familyVariantApi = $familyVariantApi; $this->productModelApi = $productModelApi; + $this->publishedProductApi = $publishedProductApi; + $this->productDraftApi = $productDraftApi; + $this->productModelDraftApi = $productModelDraftApi; + $this->assetApi = $assetApi; + $this->assetCategoryApi = $assetCategoryApi; + $this->assetTagApi = $assetTagApi; + $this->assetReferenceFileApi = $assetReferenceFileApi; + $this->assetVariationFileApi = $assetVariationFileApi; + $this->referenceEntityRecordApi = $referenceEntityRecordApi; + $this->referenceEntityMediaFileApi = $referenceEntityMediaFileApi; + $this->referenceEntityAttributeApi = $referenceEntityAttributeApi; + $this->referenceEntityAttributeOptionApi = $referenceEntityAttributeOptionApi; + $this->referenceEntityApi = $referenceEntityApi; + $this->assetManagerApi = $assetManagerApi; + $this->assetFamilyApi = $assetFamilyApi; + $this->assetAttributeApi = $assetAttributeApi; + $this->assetAttributeOptionApi = $assetAttributeOptionApi; + $this->assetMediaFileApi = $assetMediaFileApi; } /** @@ -247,4 +355,148 @@ public function getProductModelApi(): ProductModelApiInterface { return $this->productModelApi; } + + /** + * {@inheritdoc} + */ + public function getPublishedProductApi(): PublishedProductApiInterface + { + return $this->publishedProductApi; + } + + /** + * {@inheritdoc} + */ + public function getProductModelDraftApi(): ProductModelDraftApiInterface + { + return $this->productModelDraftApi; + } + + /** + * {@inheritdoc} + */ + public function getProductDraftApi(): ProductDraftApiInterface + { + return $this->productDraftApi; + } + + /** + * @return AssetApiInterface + */ + public function getAssetApi(): AssetApiInterface + { + return $this->assetApi; + } + + /** + * {@inheritdoc} + */ + public function getAssetCategoryApi(): AssetCategoryApiInterface + { + return $this->assetCategoryApi; + } + + /** + * {@inheritdoc} + */ + public function getAssetTagApi(): AssetTagApiInterface + { + return $this->assetTagApi; + } + + /** + * {@inheritdoc} + */ + public function getAssetReferenceFileApi(): AssetReferenceFileApiInterface + { + return $this->assetReferenceFileApi; + } + + /** + * {@inheritdoc} + */ + public function getAssetVariationFileApi(): AssetVariationFileApiInterface + { + return $this->assetVariationFileApi; + } + + /** + * {@inheritdoc} + */ + public function getReferenceEntityRecordApi(): ReferenceEntityRecordApiInterface + { + return $this->referenceEntityRecordApi; + } + + /** + * {@inheritdoc} + */ + public function getReferenceEntityMediaFileApi(): ReferenceEntityMediaFileApiInterface + { + return $this->referenceEntityMediaFileApi; + } + + /** + * {@inheritdoc} + */ + public function getReferenceEntityAttributeApi(): ReferenceEntityAttributeApiInterface + { + return $this->referenceEntityAttributeApi; + } + + /** + * {@inheritdoc} + */ + public function getReferenceEntityAttributeOptionApi(): ReferenceEntityAttributeOptionApiInterface + { + return $this->referenceEntityAttributeOptionApi; + } + + /** + * {@inheritdoc} + */ + public function getReferenceEntityApi(): ReferenceEntityApiInterface + { + return $this->referenceEntityApi; + } + + /** + * {@inheritDoc} + */ + public function getAssetManagerApi(): AssetManagerApiInterface + { + return $this->assetManagerApi; + } + + /** + * {@inheritDoc} + */ + public function getAssetFamilyApi(): AssetFamilyApiInterface + { + return $this->assetFamilyApi; + } + + /** + * {@inheritDoc} + */ + public function getAssetAttributeApi(): AssetAttributeApiInterface + { + return $this->assetAttributeApi; + } + + /** + * {@inheritDoc} + */ + public function getAssetAttributeOptionApi(): AssetAttributeOptionApiInterface + { + return $this->assetAttributeOptionApi; + } + + /** + * {@inheritDoc} + */ + public function getAssetMediaFileApi(): AssetMediaFileApiInterface + { + return $this->assetMediaFileApi; + } } diff --git a/src/AkeneoPimClientBuilder.php b/src/AkeneoPimClientBuilder.php index 7e74618b..0589b5fb 100644 --- a/src/AkeneoPimClientBuilder.php +++ b/src/AkeneoPimClientBuilder.php @@ -2,6 +2,16 @@ namespace Akeneo\Pim\ApiClient; +use Akeneo\Pim\ApiClient\Api\AssetApi; +use Akeneo\Pim\ApiClient\Api\AssetCategoryApi; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetApi as AssetManagerApi; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeApi; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeOptionApi; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetFamilyApi; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetMediaFileApi; +use Akeneo\Pim\ApiClient\Api\AssetReferenceFileApi; +use Akeneo\Pim\ApiClient\Api\AssetTagApi; +use Akeneo\Pim\ApiClient\Api\AssetVariationFileApi; use Akeneo\Pim\ApiClient\Api\AssociationTypeApi; use Akeneo\Pim\ApiClient\Api\AttributeApi; use Akeneo\Pim\ApiClient\Api\AttributeGroupApi; @@ -16,8 +26,16 @@ use Akeneo\Pim\ApiClient\Api\MeasureFamilyApi; use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApi; use Akeneo\Pim\ApiClient\Api\ProductApi; +use Akeneo\Pim\ApiClient\Api\ProductDraftApi; use Akeneo\Pim\ApiClient\Api\ProductMediaFileApi; use Akeneo\Pim\ApiClient\Api\ProductModelApi; +use Akeneo\Pim\ApiClient\Api\ProductModelDraftApi; +use Akeneo\Pim\ApiClient\Api\PublishedProductApi; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityApi; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeApi; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeOptionApi; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityMediaFileApi; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityRecordApi; use Akeneo\Pim\ApiClient\Cache\LRUCache; use Akeneo\Pim\ApiClient\Client\AuthenticatedHttpClient; use Akeneo\Pim\ApiClient\Client\CachedResourceClient; @@ -181,7 +199,7 @@ protected function buildAuthenticatedClient(Authentication $authentication): Ake { [$resourceClient, $pageFactory, $cursorFactory, $fileSystem] = $this->setUp($authentication); - $resourceClientWithCache = !$this->cacheEnabled ? $resourceClient : new CachedResourceClient($resourceClient, new Cache()); + $resourceClientWithCache = !$this->cacheEnabled ? $resourceClient : new CachedResourceClient($resourceClient, new LRUCache()); return new AkeneoPimClient( $authentication, @@ -199,7 +217,25 @@ protected function buildAuthenticatedClient(Authentication $authentication): Ake new MeasurementFamilyApi($resourceClientWithCache), new AssociationTypeApi($resourceClientWithCache, $pageFactory, $cursorFactory), new FamilyVariantApi($resourceClientWithCache, $pageFactory, $cursorFactory), - new ProductModelApi($resourceClient, $pageFactory, $cursorFactory) + new ProductModelApi($resourceClient, $pageFactory, $cursorFactory), + new ProductModelDraftApi($resourceClient, $pageFactory, $cursorFactory), + new PublishedProductApi($resourceClient, $pageFactory, $cursorFactory), + new ProductDraftApi($resourceClient, $pageFactory, $cursorFactory), + new AssetApi($resourceClient, $pageFactory, $cursorFactory), + new AssetCategoryApi($resourceClient, $pageFactory, $cursorFactory), + new AssetTagApi($resourceClient, $pageFactory, $cursorFactory), + new AssetReferenceFileApi($resourceClient, $fileSystem), + new AssetVariationFileApi($resourceClient, $fileSystem), + new ReferenceEntityRecordApi($resourceClient, $pageFactory, $cursorFactory), + new ReferenceEntityMediaFileApi($resourceClient, $fileSystem), + new ReferenceEntityAttributeApi($resourceClient), + new ReferenceEntityAttributeOptionApi($resourceClient), + new ReferenceEntityApi($resourceClient, $pageFactory, $cursorFactory), + new AssetManagerApi($resourceClient, $pageFactory, $cursorFactory), + new AssetFamilyApi($resourceClient, $pageFactory, $cursorFactory), + new AssetAttributeApi($resourceClient), + new AssetAttributeOptionApi($resourceClient), + new AssetMediaFileApi($resourceClient, $fileSystem) ); } diff --git a/src/AkeneoPimClientInterface.php b/src/AkeneoPimClientInterface.php index 94e20804..83e65b5a 100644 --- a/src/AkeneoPimClientInterface.php +++ b/src/AkeneoPimClientInterface.php @@ -2,6 +2,16 @@ namespace Akeneo\Pim\ApiClient; +use Akeneo\Pim\ApiClient\Api\AssetApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetCategoryApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetApiInterface as AssetManagerApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetFamilyApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetManager\AssetMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetReferenceFileApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetTagApiInterface; +use Akeneo\Pim\ApiClient\Api\AssetVariationFileApiInterface; use Akeneo\Pim\ApiClient\Api\AssociationTypeApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeApiInterface; use Akeneo\Pim\ApiClient\Api\AttributeGroupApiInterface; @@ -16,7 +26,15 @@ use Akeneo\Pim\ApiClient\Api\MeasurementFamilyApiInterface; use Akeneo\Pim\ApiClient\Api\MediaFileApiInterface; use Akeneo\Pim\ApiClient\Api\ProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductDraftApiInterface; use Akeneo\Pim\ApiClient\Api\ProductModelApiInterface; +use Akeneo\Pim\ApiClient\Api\ProductModelDraftApiInterface; +use Akeneo\Pim\ApiClient\Api\PublishedProductApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityAttributeOptionApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityMediaFileApiInterface; +use Akeneo\Pim\ApiClient\Api\ReferenceEntityRecordApiInterface; /** * Client to use the Akeneo PIM API. @@ -60,4 +78,40 @@ public function getAssociationTypeApi(): AssociationTypeApiInterface; public function getFamilyVariantApi(): FamilyVariantApiInterface; public function getProductModelApi(): ProductModelApiInterface; + + public function getPublishedProductApi(): PublishedProductApiInterface; + + public function getProductModelDraftApi(): ProductModelDraftApiInterface; + + public function getProductDraftApi(): ProductDraftApiInterface; + + public function getAssetApi(): AssetApiInterface; + + public function getAssetCategoryApi(): AssetCategoryApiInterface; + + public function getAssetTagApi(): AssetTagApiInterface; + + public function getAssetReferenceFileApi(): AssetReferenceFileApiInterface; + + public function getAssetVariationFileApi(): AssetVariationFileApiInterface; + + public function getReferenceEntityRecordApi(): ReferenceEntityRecordApiInterface; + + public function getReferenceEntityMediaFileApi(): ReferenceEntityMediaFileApiInterface; + + public function getReferenceEntityAttributeApi(): ReferenceEntityAttributeApiInterface; + + public function getReferenceEntityAttributeOptionApi(): ReferenceEntityAttributeOptionApiInterface; + + public function getReferenceEntityApi(): ReferenceEntityApiInterface; + + public function getAssetManagerApi(): AssetManagerApiInterface; + + public function getAssetFamilyApi(): AssetFamilyApiInterface; + + public function getAssetAttributeApi(): AssetAttributeApiInterface; + + public function getAssetAttributeOptionApi(): AssetAttributeOptionApiInterface; + + public function getAssetMediaFileApi(): AssetMediaFileApiInterface; } diff --git a/src/Api/AssetApi.php b/src/Api/AssetApi.php new file mode 100644 index 00000000..86a16603 --- /dev/null +++ b/src/Api/AssetApi.php @@ -0,0 +1,109 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class AssetApi implements AssetApiInterface +{ + const ASSETS_URI = '/api/rest/v1/assets'; + const ASSET_URI = '/api/rest/v1/assets/%s'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var PageFactoryInterface */ + private $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + private $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::ASSET_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function all(int $pageSize = 10, array $queryParameters = []): ResourceCursorInterface + { + $queryParameters['pagination_type'] = 'search_after'; + + $firstPage = $this->listPerPage($pageSize, false, $queryParameters); + + return $this->cursorFactory->createCursor($pageSize, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function listPerPage(int $limit = 10, bool $withCount = false, array $queryParameters = []): PageInterface + { + $data = $this->resourceClient->getResources( + static::ASSETS_URI, + [], + $limit, + $withCount, + $queryParameters + ); + return $this->pageFactory->createPage($data); + } + + /** + * {@inheritdoc} + */ + public function create(string $code, array $data = []): int + { + if (array_key_exists('code', $data)) { + throw new InvalidArgumentException('The parameter "code" should not be defined in the data parameter'); + } + + $data['code'] = $code; + + return $this->resourceClient->createResource(static::ASSETS_URI, [], $data); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $code, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_URI, [$code], $data); + } + + /** + * {@inheritdoc} + */ + public function upsertList($resources): \Traversable + { + return $this->resourceClient->upsertStreamResourceList(static::ASSETS_URI, [], $resources); + } +} diff --git a/src/Api/AssetApiInterface.php b/src/Api/AssetApiInterface.php new file mode 100644 index 00000000..aa1dc85c --- /dev/null +++ b/src/Api/AssetApiInterface.php @@ -0,0 +1,27 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface AssetApiInterface extends + GettableResourceInterface, + ListableResourceInterface, + CreatableResourceInterface, + UpsertableResourceInterface, + UpsertableResourceListInterface +{ +} diff --git a/src/Api/AssetCategoryApi.php b/src/Api/AssetCategoryApi.php new file mode 100644 index 00000000..2dd04c0c --- /dev/null +++ b/src/Api/AssetCategoryApi.php @@ -0,0 +1,108 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class AssetCategoryApi implements AssetCategoryApiInterface +{ + const ASSET_CATEGORIES_URI = '/api/rest/v1/asset-categories'; + const ASSET_CATEGORY_URI = '/api/rest/v1/asset-categories/%s'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var PageFactoryInterface */ + private $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + private $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::ASSET_CATEGORY_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function all(int $pageSize = 10, array $queryParameters = []): ResourceCursorInterface + { + $firstPage = $this->listPerPage($pageSize, false, $queryParameters); + + return $this->cursorFactory->createCursor($pageSize, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function listPerPage(int $limit = 10, bool $withCount = false, array $queryParameters = []): PageInterface + { + $data = $this->resourceClient->getResources( + static::ASSET_CATEGORIES_URI, + [], + $limit, + $withCount, + $queryParameters + ); + + return $this->pageFactory->createPage($data); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $code, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_CATEGORY_URI, [$code], $data); + } + + /** + * {@inheritdoc} + */ + public function upsertList($resources): \Traversable + { + return $this->resourceClient->upsertStreamResourceList(static::ASSET_CATEGORIES_URI, [], $resources); + } + + /** + * {@inheritdoc} + */ + public function create(string $code, array $data = []): int + { + if (array_key_exists('code', $data)) { + throw new InvalidArgumentException('The parameter "code" should not be defined in the data parameter'); + } + + $data['code'] = $code; + + return $this->resourceClient->createResource(static::ASSET_CATEGORIES_URI, [], $data); + } +} diff --git a/src/Api/AssetCategoryApiInterface.php b/src/Api/AssetCategoryApiInterface.php new file mode 100644 index 00000000..03ea3b0c --- /dev/null +++ b/src/Api/AssetCategoryApiInterface.php @@ -0,0 +1,27 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface AssetCategoryApiInterface extends + GettableResourceInterface, + ListableResourceInterface, + UpsertableResourceInterface, + UpsertableResourceListInterface, + CreatableResourceInterface +{ +} diff --git a/src/Api/AssetManager/AssetApi.php b/src/Api/AssetManager/AssetApi.php new file mode 100644 index 00000000..2435e304 --- /dev/null +++ b/src/Api/AssetManager/AssetApi.php @@ -0,0 +1,85 @@ +resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $assetFamilyCode, string $assetCode): array + { + return $this->resourceClient->getResource(static::ASSET_URI, [$assetFamilyCode, $assetCode]); + } + + /** + * {@inheritdoc} + */ + public function all(string $assetFamilyCode, array $queryParameters = []): ResourceCursorInterface + { + $data = $this->resourceClient->getResources( + static::ASSETS_URI, + [$assetFamilyCode], + null, + null, + $queryParameters + ); + + $firstPage = $this->pageFactory->createPage($data); + + return $this->cursorFactory->createCursor(null, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $assetFamilyCode, string $assetCode, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_URI, [$assetFamilyCode, $assetCode], $data); + } + + /** + * {@inheritdoc} + */ + public function upsertList(string $assetFamilyCode, array $assets): array + { + return $this->resourceClient->upsertJsonResourceList(static::ASSETS_URI, [$assetFamilyCode], $assets); + } + + /** + * {@inheritdoc} + */ + public function delete(string $assetFamilyCode, string $assetCode): int + { + return $this->resourceClient->deleteResource(static::ASSET_URI, [$assetFamilyCode, $assetCode]); + } +} diff --git a/src/Api/AssetManager/AssetApiInterface.php b/src/Api/AssetManager/AssetApiInterface.php new file mode 100644 index 00000000..07fe5b36 --- /dev/null +++ b/src/Api/AssetManager/AssetApiInterface.php @@ -0,0 +1,70 @@ +resourceClient = $resourceClient; + } + + /** + * {@inheritdoc} + */ + public function get(string $assetFamilyCode, string $attributeCode): array + { + return $this->resourceClient->getResource(static::ASSET_ATTRIBUTE_URI, [$assetFamilyCode, $attributeCode]); + } + + /** + * {@inheritdoc} + */ + public function all(string $assetFamilyCode, array $queryParameters = []): array + { + return $this->resourceClient->getResource(static::ASSET_ATTRIBUTES_URI, [$assetFamilyCode]); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $assetFamilyCode, string $attributeCode, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_ATTRIBUTE_URI, [$assetFamilyCode, $attributeCode], $data); + } +} diff --git a/src/Api/AssetManager/AssetAttributeApiInterface.php b/src/Api/AssetManager/AssetAttributeApiInterface.php new file mode 100644 index 00000000..a1ccbf76 --- /dev/null +++ b/src/Api/AssetManager/AssetAttributeApiInterface.php @@ -0,0 +1,34 @@ +resourceClient = $resourceClient; + } + + /** + * {@inheritdoc} + */ + public function get(string $assetFamilyCode, string $attributeCode, string $attributeOptionCode): array + { + return $this->resourceClient->getResource( + static::ASSET_ATTRIBUTE_OPTION_URI, + [$assetFamilyCode, $attributeCode, $attributeOptionCode] + ); + } + + /** + * {@inheritdoc} + */ + public function all(string $assetFamilyCode, string $attributeCode): array + { + return $this->resourceClient->getResource( + static::ASSET_ATTRIBUTE_OPTIONS_URI, + [$assetFamilyCode, $attributeCode] + ); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $assetFamilyCode, string $attributeCode, string $attributeOptionCode, array $data = []): int + { + return $this->resourceClient->upsertResource( + static::ASSET_ATTRIBUTE_OPTION_URI, + [$assetFamilyCode, $attributeCode, $attributeOptionCode], + $data + ); + } +} diff --git a/src/Api/AssetManager/AssetAttributeOptionApiInterface.php b/src/Api/AssetManager/AssetAttributeOptionApiInterface.php new file mode 100644 index 00000000..510d0724 --- /dev/null +++ b/src/Api/AssetManager/AssetAttributeOptionApiInterface.php @@ -0,0 +1,34 @@ +resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::ASSET_FAMILY_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function all(array $queryParameters = []): ResourceCursorInterface + { + $data = $this->resourceClient->getResources( + static::ASSET_FAMILIES_URI, + [], + null, + false, + $queryParameters + ); + + $firstPage = $this->pageFactory->createPage($data); + + return $this->cursorFactory->createCursor(null, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $code, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_FAMILY_URI, [$code], $data); + } +} diff --git a/src/Api/AssetManager/AssetFamilyApiInterface.php b/src/Api/AssetManager/AssetFamilyApiInterface.php new file mode 100644 index 00000000..e892f909 --- /dev/null +++ b/src/Api/AssetManager/AssetFamilyApiInterface.php @@ -0,0 +1,35 @@ +resourceClient = $resourceClient; + $this->fileSystem = $fileSystem; + } + + /** + * {@inheritdoc} + */ + public function download($code): ResponseInterface + { + return $this->resourceClient->getStreamedResource(static::MEDIA_FILE_DOWNLOAD_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function create($mediaFile): string + { + if (is_string($mediaFile)) { + $mediaFile = $this->fileSystem->getResourceFromPath($mediaFile); + } + + $requestParts = [ + [ + 'name' => 'file', + 'contents' => $mediaFile, + ] + ]; + + $response = $this->resourceClient->createMultipartResource(static::MEDIA_FILE_CREATE_URI, [], $requestParts); + + return $this->extractCodeFromCreationResponse($response); + } + + /** + * Extracts the code of a media-file from a creation response. + * + * @param ResponseInterface $response + * + * @throws RuntimeException if unable to extract the code + * + * @return string + */ + private function extractCodeFromCreationResponse(ResponseInterface $response): string + { + $header = $response->getHeader('asset-media-file-code'); + + if (empty($header)) { + throw new RuntimeException('The response does not contain the code of the created media-file.'); + } + + return (string) $header[0]; + } +} diff --git a/src/Api/AssetManager/AssetMediaFileApiInterface.php b/src/Api/AssetManager/AssetMediaFileApiInterface.php new file mode 100644 index 00000000..b62b4998 --- /dev/null +++ b/src/Api/AssetManager/AssetMediaFileApiInterface.php @@ -0,0 +1,34 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class AssetReferenceFileApi implements AssetReferenceFileApiInterface +{ + const ASSET_REFERENCE_FILE_URI = '/api/rest/v1/assets/%s/reference-files/%s'; + const ASSET_REFERENCE_FILE_DOWNLOAD_URI = '/api/rest/v1/assets/%s/reference-files/%s/download'; + const NOT_LOCALIZABLE_ASSET_LOCALE_CODE = 'no-locale'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var FileSystemInterface */ + private $fileSystem; + + public function __construct(ResourceClientInterface $resourceClient, FileSystemInterface $fileSystem) + { + $this->resourceClient = $resourceClient; + $this->fileSystem = $fileSystem; + } + + /** + * {@inheritdoc} + */ + public function getFromLocalizableAsset(string $assetCode, string $localeCode): array + { + return $this->get($assetCode, $localeCode); + } + + /** + * {@inheritdoc} + */ + public function getFromNotLocalizableAsset(string $assetCode): array + { + return $this->get($assetCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE); + } + + /** + * {@inheritdoc} + */ + public function uploadForLocalizableAsset($referenceFile, string $assetCode, string $localeCode): int + { + return $this->upload($referenceFile, $assetCode, $localeCode); + } + + /** + * {@inheritdoc} + */ + public function uploadForNotLocalizableAsset($referenceFile, string $assetCode): int + { + return $this->upload($referenceFile, $assetCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE); + } + + /** + * {@inheritdoc} + */ + public function downloadFromLocalizableAsset(string $assetCode, string $localeCode): ResponseInterface + { + return $this->resourceClient + ->getStreamedResource(static::ASSET_REFERENCE_FILE_DOWNLOAD_URI, [$assetCode, $localeCode]); + } + + /** + * {@inheritdoc} + */ + public function downloadFromNotLocalizableAsset(string $assetCode): ResponseInterface + { + return $this->resourceClient + ->getStreamedResource(static::ASSET_REFERENCE_FILE_DOWNLOAD_URI, [$assetCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE]); + } + + /** + * @param string|resource $referenceFile + * @param string $assetCode + * @param string $localeCode + * + * @return int + */ + private function upload($referenceFile, string $assetCode, string $localeCode): int + { + if (is_string($referenceFile)) { + $referenceFile = $this->fileSystem->getResourceFromPath($referenceFile); + } + + $requestParts = [[ + 'name' => 'file', + 'contents' => $referenceFile, + ]]; + + $response = $this->resourceClient->createMultipartResource(static::ASSET_REFERENCE_FILE_URI, [$assetCode, $localeCode], $requestParts); + $this->handleUploadErrors($response); + + return $response->getStatusCode(); + } + + /** + * @throws UploadAssetReferenceFileErrorException if an upload returns any errors. + */ + private function handleUploadErrors(ResponseInterface $response): void + { + $decodedResponse = json_decode($response->getBody()->getContents(), true); + $errors = isset($decodedResponse['errors']) ? $decodedResponse['errors'] : null; + + if (is_array($errors) && !empty($errors)) { + $message = isset($decodedResponse['message']) ? $decodedResponse['message'] : 'Errors occurred during the upload.'; + + throw new UploadAssetReferenceFileErrorException($message, $errors); + } + } + + private function get(string $assetCode, string $localeCode): array + { + return $this->resourceClient->getResource(static::ASSET_REFERENCE_FILE_URI, [$assetCode, $localeCode]); + } +} diff --git a/src/Api/AssetReferenceFileApiInterface.php b/src/Api/AssetReferenceFileApiInterface.php new file mode 100644 index 00000000..3c3eda6b --- /dev/null +++ b/src/Api/AssetReferenceFileApiInterface.php @@ -0,0 +1,100 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface AssetReferenceFileApiInterface +{ + /** + * Available since Akeneo PIM 2.1. + * Gets an asset reference file by its asset code and local code for a localizable asset. + * + * @param string $assetCode code of the asset + * @param string $localeCode code of the locale + * + * @throws HttpException If the request failed + * + * @return array + */ + public function getFromLocalizableAsset(string $assetCode, string $localeCode): array; + + /** + * Available since Akeneo PIM 2.1. + * Gets an asset reference file by its asset code for a not localizable asset. + * + * @param string $assetCode code of the asset + * + * @throws HttpException If the request failed + * + * @return array + */ + public function getFromNotLocalizableAsset(string $assetCode): array; + + /** + * Available since Akeneo PIM 2.1. + * Uploads a new reference file for a given localizable asset and locale. + * It will also automatically generate all the variation files corresponding to this reference file. + * + * @param string|resource $referenceFile file path or resource of the reference file to upload + * @param string $assetCode code of the asset + * @param string $localeCode code of the locale + * + * @throws HttpException If the request failed + * @throws UploadAssetReferenceFileErrorException If the upload returned any errors + * + * @return int Status code 201 indicating that the asset reference file has been well uploaded + */ + public function uploadForLocalizableAsset($referenceFile, string $assetCode, string $localeCode): int; + + /** + * Available since Akeneo PIM 2.1. + * Uploads a new reference file for a given not localizable asset. + * It will also automatically generate all the variation files corresponding to this reference file. + * + * @param string|resource $referenceFile file path or resource of the reference file to upload + * @param string $assetCode code of the asset + * + * @throws HttpException If the request failed + * @throws UploadAssetReferenceFileErrorException If the upload returned any errors + * + * @return int Status code 201 indicating that the asset reference file has been well uploaded + */ + public function uploadForNotLocalizableAsset($referenceFile, string $assetCode): int; + + /** + * Available since Akeneo PIM 2.1. + * Download an asset reference file by its asset code and local code for a localizable asset. + * + * @param string $assetCode code of the asset + * @param string $localeCode code of the locale + * + * @throws HttpException If the request failed + * + * @return ResponseInterface + */ + public function downloadFromLocalizableAsset(string $assetCode, string $localeCode): ResponseInterface; + + /** + * Available since Akeneo PIM 2.1. + * Download an asset reference file by its asset code for a not localizable asset. + * + * @param string $assetCode code of the asset + * + * @throws HttpException If the request failed + * + * @return ResponseInterface + */ + public function downloadFromNotLocalizableAsset(string $assetCode): ResponseInterface; +} diff --git a/src/Api/AssetTagApi.php b/src/Api/AssetTagApi.php new file mode 100644 index 00000000..31bc78b9 --- /dev/null +++ b/src/Api/AssetTagApi.php @@ -0,0 +1,85 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class AssetTagApi implements AssetTagApiInterface +{ + const ASSET_TAGS_URI = '/api/rest/v1/asset-tags'; + const ASSET_TAG_URI = '/api/rest/v1/asset-tags/%s'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var PageFactoryInterface */ + private $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + private $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::ASSET_TAG_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $code, array $data = []): int + { + return $this->resourceClient->upsertResource(static::ASSET_TAG_URI, [$code], $data); + } + + /** + * {@inheritdoc} + */ + public function all(int $pageSize = 10, array $queryParameters = []): ResourceCursorInterface + { + $firstPage = $this->listPerPage($pageSize, false, $queryParameters); + + return $this->cursorFactory->createCursor($pageSize, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function listPerPage(int $limit = 10, bool $withCount = false, array $queryParameters = []): PageInterface + { + $data = $this->resourceClient->getResources( + static::ASSET_TAGS_URI, + [], + $limit, + $withCount, + $queryParameters + ); + + return $this->pageFactory->createPage($data); + } +} diff --git a/src/Api/AssetTagApiInterface.php b/src/Api/AssetTagApiInterface.php new file mode 100644 index 00000000..f4283f5f --- /dev/null +++ b/src/Api/AssetTagApiInterface.php @@ -0,0 +1,20 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface AssetTagApiInterface extends GettableResourceInterface, ListableResourceInterface, UpsertableResourceInterface +{ +} diff --git a/src/Api/AssetVariationFileApi.php b/src/Api/AssetVariationFileApi.php new file mode 100644 index 00000000..217ee420 --- /dev/null +++ b/src/Api/AssetVariationFileApi.php @@ -0,0 +1,122 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class AssetVariationFileApi implements AssetVariationFileApiInterface +{ + const ASSET_VARIATION_FILE_URI = '/api/rest/v1/assets/%s/variation-files/%s/%s'; + const ASSET_VARIATION_FILE_DOWNLOAD_URI = '/api/rest/v1/assets/%s/variation-files/%s/%s/download'; + const NOT_LOCALIZABLE_ASSET_LOCALE_CODE = 'no-locale'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var FileSystemInterface */ + private $fileSystem; + + public function __construct(ResourceClientInterface $resourceClient, FileSystemInterface $fileSystem) + { + $this->resourceClient = $resourceClient; + $this->fileSystem = $fileSystem; + } + + /** + * {@inheritdoc} + */ + public function getFromNotLocalizableAsset(string $assetCode, string $channelCode): array + { + return $this->get($assetCode, $channelCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE); + } + + /** + * {@inheritdoc} + */ + public function getFromLocalizableAsset(string $assetCode, string $channelCode, string $localeCode): array + { + return $this->get($assetCode, $channelCode, $localeCode); + } + + /** + * {@inheritdoc} + */ + public function uploadForNotLocalizableAsset($variationFile, string $assetCode, string $channelCode): int + { + return $this->upload($variationFile, $assetCode, $channelCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE); + } + + /** + * {@inheritdoc} + */ + public function uploadForLocalizableAsset($variationFile, string $assetCode, string $channelCode, string $localeCode): int + { + return $this->upload($variationFile, $assetCode, $channelCode, $localeCode); + } + + /** + * {@inheritdoc} + */ + public function downloadFromLocalizableAsset(string $assetCode, string $channelCode, string $localeCode): ResponseInterface + { + return $this->resourceClient->getStreamedResource( + static::ASSET_VARIATION_FILE_DOWNLOAD_URI, + [$assetCode, $channelCode, $localeCode] + ); + } + + /** + * {@inheritdoc} + */ + public function downloadFromNotLocalizableAsset(string $assetCode, string $channelCode): ResponseInterface + { + return $this->resourceClient->getStreamedResource( + static::ASSET_VARIATION_FILE_DOWNLOAD_URI, + [$assetCode, $channelCode, static::NOT_LOCALIZABLE_ASSET_LOCALE_CODE] + ); + } + + private function get(string $assetCode, string $channelCode, string $localeCode): array + { + return $this->resourceClient->getResource(static::ASSET_VARIATION_FILE_URI, [$assetCode, $channelCode, $localeCode]); + } + + /** + * @param string|resource $variationFile + * @param string $assetCode + * @param string $channelCode + * @param string $localeCode + * + * @return int + */ + private function upload($variationFile, string $assetCode, string $channelCode, string $localeCode): int + { + if (is_string($variationFile)) { + $variationFile = $this->fileSystem->getResourceFromPath($variationFile); + } + + $requestParts = [[ + 'name' => 'file', + 'contents' => $variationFile, + ]]; + + $response = $this->resourceClient->createMultipartResource( + static::ASSET_VARIATION_FILE_URI, + [$assetCode, $channelCode, $localeCode], + $requestParts + ); + + return $response->getStatusCode(); + } +} diff --git a/src/Api/AssetVariationFileApiInterface.php b/src/Api/AssetVariationFileApiInterface.php new file mode 100644 index 00000000..188e358f --- /dev/null +++ b/src/Api/AssetVariationFileApiInterface.php @@ -0,0 +1,88 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface AssetVariationFileApiInterface +{ + /** + * Available since Akeneo PIM 2.1. + * Gets an asset variation file by its asset code, channel code and local code for a localizable asset. + * + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * @param string $localeCode code of the locale + * + * @return array + */ + public function getFromLocalizableAsset(string $assetCode, string $channelCode, string $localeCode): array; + + /** + * Available since Akeneo PIM 2.1. + * Gets an asset variation file by its asset code and channel code for a not localizable asset. + * + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * + * @return array + */ + public function getFromNotLocalizableAsset(string $assetCode, string $channelCode): array; + + /** + * Available since Akeneo PIM 2.1. + * Uploads a new variation file for a given localizable asset, channel and locale. + * + * @param string|resource $variationFile file path or resource of the variation file to upload + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * @param string $localeCode code of the locale + * + * @return int Status code 201 indicating that the asset variation file has been well uploaded + */ + public function uploadForLocalizableAsset($variationFile, string $assetCode, string $channelCode, string $localeCode): int; + + /** + * Available since Akeneo PIM 2.1. + * Uploads a new variation file for a given not localizable asset and channel. + * + * @param string|resource $variationFile file path or resource of the variation file to upload + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * + * @return int Status code 201 indicating that the asset variation file has been well uploaded + */ + public function uploadForNotLocalizableAsset($variationFile, string $assetCode, string $channelCode): int; + + /** + * Available since Akeneo PIM 2.1. + * Downloads an asset variation file by its asset code, channel code and local code for a localizable asset. + * + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * @param string $localeCode code of the locale + * + * @return ResponseInterface + */ + public function downloadFromLocalizableAsset(string $assetCode, string $channelCode, string $localeCode): ResponseInterface; + + /** + * Available since Akeneo PIM 2.1. + * Downloads an asset variation file by its asset code and channel code for a not localizable asset. + * + * @param string $assetCode code of the asset + * @param string $channelCode code of the channel + * + * @return ResponseInterface + */ + public function downloadFromNotLocalizableAsset(string $assetCode, string $channelCode): ResponseInterface; +} diff --git a/src/Api/Operation/DownloadableResourceInterface.php b/src/Api/Operation/DownloadableResourceInterface.php index 916c62dd..dd5ee5a2 100644 --- a/src/Api/Operation/DownloadableResourceInterface.php +++ b/src/Api/Operation/DownloadableResourceInterface.php @@ -4,7 +4,6 @@ use Akeneo\Pim\ApiClient\Exception\HttpException; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; /** * API that can download a resource. diff --git a/src/Api/ProductDraftApi.php b/src/Api/ProductDraftApi.php new file mode 100644 index 00000000..7ef80932 --- /dev/null +++ b/src/Api/ProductDraftApi.php @@ -0,0 +1,57 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ProductDraftApi implements ProductDraftApiInterface +{ + const PRODUCT_DRAFT_URI = '/api/rest/v1/products/%s/draft'; + const PRODUCT_PROPOSAL_URI = '/api/rest/v1/products/%s/proposal'; + + /** @var ResourceClientInterface */ + protected $resourceClient; + + /** @var PageFactoryInterface */ + protected $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + protected $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::PRODUCT_DRAFT_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function submitForApproval($code) + { + return $this->resourceClient->createResource(static::PRODUCT_PROPOSAL_URI, [$code]); + } +} diff --git a/src/Api/ProductDraftApiInterface.php b/src/Api/ProductDraftApiInterface.php new file mode 100644 index 00000000..f82360f1 --- /dev/null +++ b/src/Api/ProductDraftApiInterface.php @@ -0,0 +1,26 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ProductDraftApiInterface extends GettableResourceInterface +{ + /** + * Submits a product draft for approval, by its code. + * + * @param string $code + * + * @return int + */ + public function submitForApproval($code); +} diff --git a/src/Api/ProductMediaFileApi.php b/src/Api/ProductMediaFileApi.php index 77bacb5c..4e27e7f9 100644 --- a/src/Api/ProductMediaFileApi.php +++ b/src/Api/ProductMediaFileApi.php @@ -10,7 +10,6 @@ use Akeneo\Pim\ApiClient\Pagination\ResourceCursorFactoryInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; /** * API implementation to manage the media files for the products. diff --git a/src/Api/ProductModelDraftApi.php b/src/Api/ProductModelDraftApi.php new file mode 100644 index 00000000..a789074c --- /dev/null +++ b/src/Api/ProductModelDraftApi.php @@ -0,0 +1,57 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ProductModelDraftApi implements ProductModelDraftApiInterface +{ + const PRODUCT_MODEL_DRAFT_URI = '/api/rest/v1/product-models/%s/draft'; + const PRODUCT_MODEL_PROPOSAL_URI = '/api/rest/v1/product-models/%s/proposal'; + + /** @var ResourceClientInterface */ + protected $resourceClient; + + /** @var PageFactoryInterface */ + protected $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + protected $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::PRODUCT_MODEL_DRAFT_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function submitForApproval($code) + { + return $this->resourceClient->createResource(static::PRODUCT_MODEL_PROPOSAL_URI, [$code]); + } +} diff --git a/src/Api/ProductModelDraftApiInterface.php b/src/Api/ProductModelDraftApiInterface.php new file mode 100644 index 00000000..22013155 --- /dev/null +++ b/src/Api/ProductModelDraftApiInterface.php @@ -0,0 +1,26 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ProductModelDraftApiInterface extends GettableResourceInterface +{ + /** + * Submits a product model draft for approval, by its code. + * + * @param string $code + * + * @return int + */ + public function submitForApproval($code); +} diff --git a/src/Api/PublishedProductApi.php b/src/Api/PublishedProductApi.php new file mode 100644 index 00000000..9dfd0a82 --- /dev/null +++ b/src/Api/PublishedProductApi.php @@ -0,0 +1,79 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class PublishedProductApi implements PublishedProductApiInterface +{ + const PUBLISHED_PRODUCTS_URI = 'api/rest/v1/published-products'; + const PUBLISHED_PRODUCT_URI = 'api/rest/v1/published-products/%s'; + + /** @var ResourceClientInterface */ + protected $resourceClient; + + /** @var PageFactoryInterface */ + protected $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + protected $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $code): array + { + return $this->resourceClient->getResource(static::PUBLISHED_PRODUCT_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function listPerPage(int $limit = 10, bool $withCount = false, array $queryParameters = []): PageInterface + { + $data = $this->resourceClient->getResources( + static::PUBLISHED_PRODUCTS_URI, + [], + $limit, + $withCount, + $queryParameters + ); + + return $this->pageFactory->createPage($data); + } + + /** + * {@inheritdoc} + */ + public function all(int $pageSize = 10, array $queryParameters = []): ResourceCursorInterface + { + $queryParameters['pagination_type'] = 'search_after'; + + $firstPage = $this->listPerPage($pageSize, false, $queryParameters); + + return $this->cursorFactory->createCursor($pageSize, $firstPage); + } +} diff --git a/src/Api/PublishedProductApiInterface.php b/src/Api/PublishedProductApiInterface.php new file mode 100644 index 00000000..20ee9efa --- /dev/null +++ b/src/Api/PublishedProductApiInterface.php @@ -0,0 +1,21 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface PublishedProductApiInterface extends + ListableResourceInterface, + GettableResourceInterface +{ +} diff --git a/src/Api/ReferenceEntityApi.php b/src/Api/ReferenceEntityApi.php new file mode 100644 index 00000000..0351ba39 --- /dev/null +++ b/src/Api/ReferenceEntityApi.php @@ -0,0 +1,74 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceEntityApi implements ReferenceEntityApiInterface +{ + const REFERENCE_ENTITY_URI = 'api/rest/v1/reference-entities/%s'; + const REFERENCE_ENTITIES_URI= 'api/rest/v1/reference-entities'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var PageFactoryInterface */ + private $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + private $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $referenceEntityCode): array + { + return $this->resourceClient->getResource(static::REFERENCE_ENTITY_URI, [$referenceEntityCode]); + } + + /** + * {@inheritdoc} + */ + public function all(array $queryParameters = []): ResourceCursorInterface + { + $data = $this->resourceClient->getResources( + static::REFERENCE_ENTITIES_URI, + [], + null, + false, + $queryParameters + ); + + $firstPage = $this->pageFactory->createPage($data); + + return $this->cursorFactory->createCursor(null, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $referenceEntityCode, array $data = []): int + { + return $this->resourceClient->upsertResource(static::REFERENCE_ENTITY_URI, [$referenceEntityCode], $data); + } +} diff --git a/src/Api/ReferenceEntityApiInterface.php b/src/Api/ReferenceEntityApiInterface.php new file mode 100644 index 00000000..2e085ad2 --- /dev/null +++ b/src/Api/ReferenceEntityApiInterface.php @@ -0,0 +1,53 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ReferenceEntityApiInterface +{ + /** + * Gets a single reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function get(string $referenceEntityCode): array; + + /** + * Gets a cursor to iterate over the list of reference entities + * + * @param array $queryParameters Additional query parameters to pass in the request + * + * @throws HttpException If the request failed. + * + * @return ResourceCursorInterface + */ + public function all(array $queryParameters = []): ResourceCursorInterface; + + /** + * Creates a reference entity if it does not exist yet, otherwise updates partially the reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * @param array $data Data of the reference entity to create or update + * + * @throws HttpException If the request failed. + * + * @return int Status code 201 indicating that the reference entity has been well created. + * Status code 204 indicating that the reference entity has been well updated. + */ + public function upsert(string $referenceEntityCode, array $data = []): int; +} diff --git a/src/Api/ReferenceEntityAttributeApi.php b/src/Api/ReferenceEntityAttributeApi.php new file mode 100644 index 00000000..bc96dfa1 --- /dev/null +++ b/src/Api/ReferenceEntityAttributeApi.php @@ -0,0 +1,50 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceEntityAttributeApi implements ReferenceEntityAttributeApiInterface +{ + const REFERENCE_ENTITY_ATTRIBUTE_URI = 'api/rest/v1/reference-entities/%s/attributes/%s'; + const REFERENCE_ENTITY_ATTRIBUTES_URI = 'api/rest/v1/reference-entities/%s/attributes'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + public function __construct(ResourceClientInterface $resourceClient) + { + $this->resourceClient = $resourceClient; + } + + /** + * {@inheritdoc} + */ + public function get(string $referenceEntityCode, string $attributeCode): array + { + return $this->resourceClient->getResource(static::REFERENCE_ENTITY_ATTRIBUTE_URI, [$referenceEntityCode, $attributeCode]); + } + + /** + * {@inheritdoc} + */ + public function all(string $referenceEntityCode, array $queryParameters = []): array + { + return $this->resourceClient->getResource(static::REFERENCE_ENTITY_ATTRIBUTES_URI, [$referenceEntityCode]); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $referenceEntityCode, string $attributeCode, array $data = []): int + { + return $this->resourceClient->upsertResource(static::REFERENCE_ENTITY_ATTRIBUTE_URI, [$referenceEntityCode, $attributeCode], $data); + } +} diff --git a/src/Api/ReferenceEntityAttributeApiInterface.php b/src/Api/ReferenceEntityAttributeApiInterface.php new file mode 100644 index 00000000..04b7f117 --- /dev/null +++ b/src/Api/ReferenceEntityAttributeApiInterface.php @@ -0,0 +1,53 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ReferenceEntityAttributeApiInterface +{ + /** + * Gets a single reference entity attribute. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $attributeCode Code of the attribute + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function get(string $referenceEntityCode, string $attributeCode): array; + + /** + * Gets the list of the attributes of a given reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * @param array $queryParameters Additional query parameters to pass in the request + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function all(string $referenceEntityCode, array $queryParameters = []): array; + + /** + * Creates a reference entity attribute if it does not exist yet, otherwise updates partially the attribute. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $attributeCode Code of the attribute + * @param array $data Data of the attribute to create or update + * + * @throws HttpException If the request failed. + * + * @return int Status code 201 indicating that the reference entity attribute has been well created. + * Status code 204 indicating that the reference entity attribute has been well updated. + */ + public function upsert(string $referenceEntityCode, string $attributeCode, array $data = []): int; +} diff --git a/src/Api/ReferenceEntityAttributeOptionApi.php b/src/Api/ReferenceEntityAttributeOptionApi.php new file mode 100644 index 00000000..915fcf81 --- /dev/null +++ b/src/Api/ReferenceEntityAttributeOptionApi.php @@ -0,0 +1,60 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceEntityAttributeOptionApi implements ReferenceEntityAttributeOptionApiInterface +{ + const REFERENCE_ENTITY_ATTRIBUTE_OPTION_URI = 'api/rest/v1/reference-entities/%s/attributes/%s/options/%s'; + const REFERENCE_ENTITY_ATTRIBUTE_OPTIONS_URI = 'api/rest/v1/reference-entities/%s/attributes/%s/options'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + public function __construct(ResourceClientInterface $resourceClient) + { + $this->resourceClient = $resourceClient; + } + + /** + * {@inheritdoc} + */ + public function get(string $referenceEntityCode, string $attributeCode, string $attributeOptionCode): array + { + return $this->resourceClient->getResource( + static::REFERENCE_ENTITY_ATTRIBUTE_OPTION_URI, + [$referenceEntityCode, $attributeCode, $attributeOptionCode] + ); + } + + /** + * {@inheritdoc} + */ + public function all(string $referenceEntityCode, string $attributeCode): array + { + return $this->resourceClient->getResource( + static::REFERENCE_ENTITY_ATTRIBUTE_OPTIONS_URI, + [$referenceEntityCode, $attributeCode] + ); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $referenceEntityCode, string $attributeCode, string $attributeOptionCode, array $data = []): int + { + return $this->resourceClient->upsertResource( + static::REFERENCE_ENTITY_ATTRIBUTE_OPTION_URI, + [$referenceEntityCode, $attributeCode, $attributeOptionCode], + $data + ); + } +} diff --git a/src/Api/ReferenceEntityAttributeOptionApiInterface.php b/src/Api/ReferenceEntityAttributeOptionApiInterface.php new file mode 100644 index 00000000..1b1c5f80 --- /dev/null +++ b/src/Api/ReferenceEntityAttributeOptionApiInterface.php @@ -0,0 +1,55 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ReferenceEntityAttributeOptionApiInterface +{ + /** + * Get an attribute option for a given attribute of a given reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $attributeCode Code of the attribute + * @param string $attributeOptionCode Code of the attribute option + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function get(string $referenceEntityCode, string $attributeCode, string $attributeOptionCode): array; + + /** + * Get the list of attribute options of a given attribute for a given reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $attributeCode Code of the attribute + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function all(string $referenceEntityCode, string $attributeCode): array; + + /** + * Creates a reference entity attribute option if it does not exist yet, otherwise updates partially the attribute option. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $attributeCode Code of the attribute + * @param string $attributeOptionCode Code of the attribute option + * @param array $data Data of the attribute option to create or update + * + * @throws HttpException If the request failed. + * + * @return int Status code 201 indicating that the reference entity attribute option has been well created. + * Status code 204 indicating that the reference entity attribute option has been well updated. + */ + public function upsert(string $referenceEntityCode, string $attributeCode, string $attributeOptionCode, array $data = []): int; +} diff --git a/src/Api/ReferenceEntityMediaFileApi.php b/src/Api/ReferenceEntityMediaFileApi.php new file mode 100644 index 00000000..2c99a2da --- /dev/null +++ b/src/Api/ReferenceEntityMediaFileApi.php @@ -0,0 +1,82 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceEntityMediaFileApi implements ReferenceEntityMediaFileApiInterface +{ + const MEDIA_FILE_DOWNLOAD_URI = 'api/rest/v1/reference-entities-media-files/%s'; + const MEDIA_FILE_CREATE_URI = 'api/rest/v1/reference-entities-media-files'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var FileSystemInterface */ + private $fileSystem; + + public function __construct(ResourceClientInterface $resourceClient, FileSystemInterface $fileSystem) + { + $this->resourceClient = $resourceClient; + $this->fileSystem = $fileSystem; + } + + /** + * {@inheritdoc} + */ + public function download($code): ResponseInterface + { + return $this->resourceClient->getStreamedResource(static::MEDIA_FILE_DOWNLOAD_URI, [$code]); + } + + /** + * {@inheritdoc} + */ + public function create($mediaFile): string + { + if (is_string($mediaFile)) { + $mediaFile = $this->fileSystem->getResourceFromPath($mediaFile); + } + + $requestParts = [ + [ + 'name' => 'file', + 'contents' => $mediaFile, + ] + ]; + + $response = $this->resourceClient->createMultipartResource(static::MEDIA_FILE_CREATE_URI, [], $requestParts); + + return $this->extractCodeFromCreationResponse($response); + } + + /** + * Extracts the code of a media-file from a creation response. + * + * @param ResponseInterface $response + * + * @throws RuntimeException if unable to extract the code + * + * @return string + */ + private function extractCodeFromCreationResponse(ResponseInterface $response): string + { + $header = $response->getHeader('Reference-entities-media-file-code'); + + if (empty($header)) { + throw new RuntimeException('The response does not contain the code of the created media-file.'); + } + + return (string)$header[0]; + } +} diff --git a/src/Api/ReferenceEntityMediaFileApiInterface.php b/src/Api/ReferenceEntityMediaFileApiInterface.php new file mode 100644 index 00000000..a7d4b40c --- /dev/null +++ b/src/Api/ReferenceEntityMediaFileApiInterface.php @@ -0,0 +1,40 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ReferenceEntityMediaFileApiInterface +{ + /** + * Downloads a reference entity media file by its code + * + * @param string $code Code of the media file + * + * @throws HttpException If the request failed. + * + * @return ResponseInterface + */ + public function download($code): ResponseInterface; + + /** + * Creates a new reference entity media file. + * + * @param string|resource $mediaFile File path or resource of the media file + * + * @throws HttpException If the request failed. + * @throws RuntimeException If the file could not be opened. + * + * @return string returns the code of the created media file + */ + public function create($mediaFile): string; +} diff --git a/src/Api/ReferenceEntityRecordApi.php b/src/Api/ReferenceEntityRecordApi.php new file mode 100644 index 00000000..dce21e24 --- /dev/null +++ b/src/Api/ReferenceEntityRecordApi.php @@ -0,0 +1,82 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceEntityRecordApi implements ReferenceEntityRecordApiInterface +{ + const REFERENCE_ENTITY_RECORD_URI = 'api/rest/v1/reference-entities/%s/records/%s'; + const REFERENCE_ENTITY_RECORDS_URI = 'api/rest/v1/reference-entities/%s/records'; + + /** @var ResourceClientInterface */ + private $resourceClient; + + /** @var PageFactoryInterface */ + private $pageFactory; + + /** @var ResourceCursorFactoryInterface */ + private $cursorFactory; + + public function __construct( + ResourceClientInterface $resourceClient, + PageFactoryInterface $pageFactory, + ResourceCursorFactoryInterface $cursorFactory + ) { + $this->resourceClient = $resourceClient; + $this->pageFactory = $pageFactory; + $this->cursorFactory = $cursorFactory; + } + + /** + * {@inheritdoc} + */ + public function get(string $referenceEntityCode, string $recordCode): array + { + return $this->resourceClient->getResource(static::REFERENCE_ENTITY_RECORD_URI, [$referenceEntityCode, $recordCode]); + } + + /** + * {@inheritdoc} + */ + public function all(string $referenceEntityCode, array $queryParameters = []): ResourceCursorInterface + { + $data = $this->resourceClient->getResources( + static::REFERENCE_ENTITY_RECORDS_URI, + [$referenceEntityCode], + null, + false, + $queryParameters + ); + + $firstPage = $this->pageFactory->createPage($data); + + return $this->cursorFactory->createCursor(null, $firstPage); + } + + /** + * {@inheritdoc} + */ + public function upsert(string $referenceEntityCode, string $recordCode, array $data = []): int + { + return $this->resourceClient->upsertResource(static::REFERENCE_ENTITY_RECORD_URI, [$referenceEntityCode, $recordCode], $data); + } + + /** + * {@inheritdoc} + */ + public function upsertList(string $referenceEntityCode, array $records): array + { + return $this->resourceClient->upsertJsonResourceList(static::REFERENCE_ENTITY_RECORDS_URI, [$referenceEntityCode], $records); + } +} diff --git a/src/Api/ReferenceEntityRecordApiInterface.php b/src/Api/ReferenceEntityRecordApiInterface.php new file mode 100644 index 00000000..f516050f --- /dev/null +++ b/src/Api/ReferenceEntityRecordApiInterface.php @@ -0,0 +1,68 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface ReferenceEntityRecordApiInterface +{ + /** + * Gets a single reference entity record. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $recordCode Code of the record + * + * @throws HttpException If the request failed. + * + * @return array + */ + public function get(string $referenceEntityCode, string $recordCode): array; + + /** + * Gets a cursor to iterate over the list of records of a given reference entity. + * + * @param string $referenceEntityCode Code of the reference entity + * @param array $queryParameters Additional query parameters to pass in the request + * + * @throws HttpException If the request failed. + * + * @return ResourceCursorInterface + */ + public function all(string $referenceEntityCode, array $queryParameters = []): ResourceCursorInterface; + + /** + * Creates a reference entity record if it does not exist yet, otherwise updates partially the record. + * + * @param string $referenceEntityCode Code of the reference entity + * @param string $recordCode Code of the record + * @param array $data Data of the record to create or update + * + * @throws HttpException If the request failed. + * + * @return int Status code 201 indicating that the reference entity record has been well created. + * Status code 204 indicating that the reference entity record has been well updated. + */ + public function upsert(string $referenceEntityCode, string $recordCode, array $data = []): int; + + /** + * Updates or creates several reference entity records. + * + * @param string $referenceEntityCode Code of the reference entity + * @param array $records Array containing the records to create or update + * + * @throws HttpException + * + * @return array returns the list of the responses of each created or updated record. + */ + public function upsertList(string $referenceEntityCode, array $records): array; +} diff --git a/src/Exception/UploadAssetReferenceFileErrorException.php b/src/Exception/UploadAssetReferenceFileErrorException.php new file mode 100644 index 00000000..15147241 --- /dev/null +++ b/src/Exception/UploadAssetReferenceFileErrorException.php @@ -0,0 +1,35 @@ + + * @copyright 2017 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class UploadAssetReferenceFileErrorException extends RuntimeException +{ + /** @var array */ + private $errors; + + /** + * @param string $message + * @param array $errors + */ + public function __construct($message, array $errors) + { + parent::__construct($message); + + $this->errors = $errors; + } + + public function getErrors(): array + { + return $this->errors; + } +} diff --git a/tests/Api/Asset/GetAssetIntegration.php b/tests/Api/Asset/GetAssetIntegration.php new file mode 100644 index 00000000..330319fa --- /dev/null +++ b/tests/Api/Asset/GetAssetIntegration.php @@ -0,0 +1,70 @@ +server->setResponseOfPath( + '/'. sprintf(AssetApi::ASSET_URI, 'packshot', 'battleship'), + new ResponseStack( + new Response($this->getAsset(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetManagerApi(); + $asset = $api->get('packshot', 'battleship'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($asset, json_decode($this->getAsset(), true)); + } + + public function test_get_unknown_asset() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetApi::ASSET_URI, 'packshot', 'peace-sheep'), + new ResponseStack( + new Response('{"code": 404, "message":"Asset \"peace-sheep\" does not exist."}', [], 404) + ) + ); + + $this->expectException(\Akeneo\Pim\ApiClient\Exception\NotFoundHttpException::class); + $this->expectExceptionMessage('Asset "peace-sheep" does not exist.'); + + $api = $this->createClient()->getAssetManagerApi(); + $api->get('packshot', 'peace-sheep'); + } + + private function getAsset(): string + { + return <<server->setResponseOfPath( + '/'. sprintf(AssetApi::ASSETS_URI, 'packshot'), + new ResponseStack( + new Response($this->getFirstPage(), [], 200), + new Response($this->getSecondPage(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetManagerApi(); + $assetCursor = $api->all('packshot'); + $assets = iterator_to_array($assetCursor); + + Assert::assertCount(3, $assets); + } + + private function getFirstPage(): string + { + $baseUri = $this->server->getServerRoot(); + + return <<server->getServerRoot(); + + return <<server->setResponseOfPath( + '/'. sprintf(AssetApi::ASSET_URI, 'packshot', 'sku_54628_telescope'), + new ResponseStack( + new Response('', [], 204) + ) + ); + + $asset = [ + "code" => "sku_54628_telescope", + "values" => [ + "media_preview" => [ + [ + "locale" => null, + "channel" => null, + "data" => "sku_54628_picture1.jpg" + ] + ], + "photographer" => [ + [ + "locale" => null, + "channel" => null, + "data" => "ben_levy" + ] + ] + ] + ]; + + $api = $this->createClient()->getAssetManagerApi(); + $response = $api->upsert('packshot', 'sku_54628_telescope', $asset); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($asset)); + Assert::assertSame(204, $response); + } +} diff --git a/tests/Api/Asset/UpsertListAssetIntegration.php b/tests/Api/Asset/UpsertListAssetIntegration.php new file mode 100644 index 00000000..6f0363d1 --- /dev/null +++ b/tests/Api/Asset/UpsertListAssetIntegration.php @@ -0,0 +1,96 @@ +server->setResponseOfPath( + '/'. sprintf(AssetApi::ASSETS_URI, 'packshot'), + new ResponseStack( + new Response($responseBody, [], 200) + ) + ); + + $assets = [ + [ + "code" => "sku_54628_telescope", + "values" => [ + "media_preview" => [ + [ + "locale" => null, + "channel" => null, + "data" => "sku_54628_picture1.jpg" + ] + ], + "photographer" => [ + [ + "locale" => null, + "channel" => null, + "data" => "ben_levy" + ] + ] + ] + ], + [ + "code" => "sku_45689_dobson", + "values" => [ + "media_preview" => [ + [ + "locale" => null, + "channel" => null, + "data" => "sku_45689_dobson_pic1.jpg" + ] + ], + "photographer" => [ + [ + "locale" => null, + "channel" => null, + "data" => "ben_levy" + ] + ] + ] + ] + ]; + + $expectedResponses = [ + [ + 'code' => 'sku_54628_telescope', + 'status_code' => 204 + ], + [ + 'code' => 'sku_45689_dobson', + 'status_code' => 201 + ], + ]; + + $api = $this->createClient()->getAssetManagerApi(); + $responses = $api->upsertList('packshot', $assets); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($assets)); + Assert::assertSame($expectedResponses, $responses); + } +} diff --git a/tests/Api/AssetAttribute/GetAssetFamilyAttributeIntegration.php b/tests/Api/AssetAttribute/GetAssetFamilyAttributeIntegration.php new file mode 100644 index 00000000..73fe0d6f --- /dev/null +++ b/tests/Api/AssetAttribute/GetAssetFamilyAttributeIntegration.php @@ -0,0 +1,68 @@ +server->setResponseOfPath( + '/'. sprintf(AssetAttributeApi::ASSET_ATTRIBUTE_URI, 'packshot', 'media_preview'), + new ResponseStack( + new Response($this->getPackshotPreviewAttribute(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetAttributeApi(); + $familyAttribute = $api->get('packshot', 'media_preview'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($familyAttribute, json_decode($this->getPackshotPreviewAttribute(), true)); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + * @expectedExceptionMessage Resource `foo` does not exist. + */ + public function test_get_unknown_asset_family_attribute() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetAttributeApi::ASSET_ATTRIBUTE_URI, 'packshot', 'foo'), + new ResponseStack( + new Response('{"code": 404, "message":"Resource `foo` does not exist."}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetAttributeApi(); + $api->get('packshot', 'foo'); + } + + private function getPackshotPreviewAttribute(): string + { + return <<server->setResponseOfPath( + '/' . sprintf(AssetAttributeApi::ASSET_ATTRIBUTES_URI, 'packshot'), + new ResponseStack( + new Response($this->getAssetFamilyAttributes(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetAttributeApi(); + $assetFamilyAttributes = $api->all('packshot'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($assetFamilyAttributes, json_decode($this->getAssetFamilyAttributes(), true)); + } + + private function getAssetFamilyAttributes(): string + { + return <<server->setResponseOfPath( + '/'. sprintf(AssetAttributeApi::ASSET_ATTRIBUTE_URI, 'packshot', 'media_preview'), + new ResponseStack( + new Response('', [], 204) + ) + ); + + $assetFamilyAttribute = [ + 'code' => 'media_preview', + 'labels' => [ + 'en_US' => 'Media Preview' + ], + 'type' => 'media_link', + "value_per_locale" => false, + "value_per_channel" => false, + "is_required_for_completeness" => false, + "prefix" => "dam.com/my_assets/", + "suffix" => null, + "media_type" => "image" + ]; + + $api = $this->createClient()->getAssetAttributeApi(); + $response = $api->upsert('packshot', 'media_preview', $assetFamilyAttribute); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($assetFamilyAttribute)); + Assert::assertSame(204, $response); + } +} diff --git a/tests/Api/AssetAttributeOption/GetAssetFamilyAttributeOptionIntegration.php b/tests/Api/AssetAttributeOption/GetAssetFamilyAttributeOptionIntegration.php new file mode 100644 index 00000000..4f48436c --- /dev/null +++ b/tests/Api/AssetAttributeOption/GetAssetFamilyAttributeOptionIntegration.php @@ -0,0 +1,61 @@ +server->setResponseOfPath( + '/'. sprintf(AssetAttributeOptionApi::ASSET_ATTRIBUTE_OPTION_URI, 'packshot', 'wearing_model_size', 'small'), + new ResponseStack( + new Response($this->getPackshotAttributeOption(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetAttributeOptionApi(); + $familyAttributeOption = $api->get('packshot', 'wearing_model_size', 'small'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($familyAttributeOption, json_decode($this->getPackshotAttributeOption(), true)); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + * @expectedExceptionMessage Resource `XLS` does not exist. + */ + public function test_get_unknown_asset_family_attribute_option() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetAttributeOptionApi::ASSET_ATTRIBUTE_OPTION_URI, 'packshot', 'wearing_model_size', 'XLS'), + new ResponseStack( + new Response('{"code": 404, "message":"Resource `XLS` does not exist."}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetAttributeOptionApi(); + $api->get('packshot', 'wearing_model_size', 'XLS'); + } + + private function getPackshotAttributeOption(): string + { + return <<server->setResponseOfPath( + '/' . sprintf( + AssetAttributeOptionApi::ASSET_ATTRIBUTE_OPTIONS_URI, + 'packshot', + 'wearing_model_size' + ), + new ResponseStack( + new Response($this->getAssetFamilyAttributeOptions(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetAttributeOptionApi(); + $assetFamilyAttributeOptions = $api->all('packshot', 'wearing_model_size'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($assetFamilyAttributeOptions, json_decode($this->getAssetFamilyAttributeOptions(), true)); + } + + private function getAssetFamilyAttributeOptions(): string + { + return <<server->setResponseOfPath( + '/'. sprintf( + AssetAttributeOptionApi::ASSET_ATTRIBUTE_OPTION_URI, + 'packshot', + 'wearing_model_size', + 'size_27' + ), + new ResponseStack( + new Response('', [], 204) + ) + ); + + $assetFamilyAttributeOption = [ + "code" => "size_27", + "labels" => [ + "en_US" => "Size 27", + "fr_FR" => "Taille 36" + ] + ]; + + $api = $this->createClient()->getAssetAttributeOptionApi(); + $response = $api->upsert('packshot', 'wearing_model_size', 'size_27', $assetFamilyAttributeOption); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($assetFamilyAttributeOption)); + Assert::assertSame(204, $response); + } +} diff --git a/tests/Api/AssetFamily/GetAssetFamilyIntegration.php b/tests/Api/AssetFamily/GetAssetFamilyIntegration.php new file mode 100644 index 00000000..1c89589c --- /dev/null +++ b/tests/Api/AssetFamily/GetAssetFamilyIntegration.php @@ -0,0 +1,60 @@ +server->setResponseOfPath( + '/'. sprintf(AssetFamilyApi::ASSET_FAMILY_URI, 'packshot'), + new ResponseStack( + new Response($this->getPackshot(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetFamilyApi(); + $product = $api->get('packshot'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($product, json_decode($this->getPackshot(), true)); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + * @expectedExceptionMessage Asset family "foo" does not exist. + */ + public function test_get_unknown_asset_family() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetFamilyApi::ASSET_FAMILY_URI, 'foo'), + new ResponseStack( + new Response('{"code": 404, "message":"Asset family \"foo\" does not exist."}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetFamilyApi(); + $api->get('foo'); + } + + private function getPackshot(): string + { + return <<server->setResponseOfPath( + '/' . sprintf(AssetFamilyApi::ASSET_FAMILIES_URI), + new ResponseStack( + new Response($this->getFirstPage(), [], 200), + new Response($this->getSecondPage(), [], 200) + ) + ); + + $api = $this->createClient()->getAssetFamilyApi(); + $assetFamilyCursor = $api->all(); + $assetFamilies = iterator_to_array($assetFamilyCursor); + + Assert::assertCount(3, $assetFamilies); + } + + private function getFirstPage(): string + { + $baseUri = $this->server->getServerRoot(); + + return <<server->getServerRoot(); + + return <<server->setResponseOfPath( + '/'. sprintf(AssetFamilyApi::ASSET_FAMILY_URI, 'packshot'), + new ResponseStack( + new Response('', [], 201) + ) + ); + + $assetFamily = [ + 'code' => 'packshot', + 'labels' => [ + 'en_US' => 'Packshots' + ] + ]; + + $api = $this->createClient()->getAssetFamilyApi(); + $response = $api->upsert('packshot', $assetFamily); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($assetFamily)); + Assert::assertSame(201, $response); + } +} diff --git a/tests/Api/AssetMediaFile/CreateAssetMediaFileIntegration.php b/tests/Api/AssetMediaFile/CreateAssetMediaFileIntegration.php new file mode 100644 index 00000000..57c18c57 --- /dev/null +++ b/tests/Api/AssetMediaFile/CreateAssetMediaFileIntegration.php @@ -0,0 +1,54 @@ +server->setResponseOfPath( + '/' . AssetMediaFileApi::MEDIA_FILE_CREATE_URI, + new ResponseStack( + new Response('', ['Asset-media-file-code' => 'my-asset-media-code'], 201) + ) + ); + $mediaFile = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + $response = $this->createClient()->getAssetMediaFileApi()->create($mediaFile); + + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], + 'unicorn.png' + ); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], + 'image/png' + ); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], + 11255 + ); + Assert::assertSame('my-asset-media-code', $response); + } + + public function test_get_asset_media_file_code_regardless_of_the_header_case() + { + $this->server->setResponseOfPath( + '/' . AssetMediaFileApi::MEDIA_FILE_CREATE_URI, + new ResponseStack( + new Response('', ['Asset-Media-File-Code' => 'my-asset-media-code'], 201) + ) + ); + $mediaFile = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + $response = $this->createClient()->getAssetMediaFileApi()->create($mediaFile); + + Assert::assertSame('my-asset-media-code', $response); + } +} diff --git a/tests/Api/AssetReferenceFile/DownloadAssetReferenceFileIntegration.php b/tests/Api/AssetReferenceFile/DownloadAssetReferenceFileIntegration.php new file mode 100644 index 00000000..be36d505 --- /dev/null +++ b/tests/Api/AssetReferenceFile/DownloadAssetReferenceFileIntegration.php @@ -0,0 +1,87 @@ +server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, 'ziggy', 'en_US'), + new ResponseStack( + new Response(file_get_contents($expectedFilePath), [], 201) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $downloadResponse = $api->downloadFromLocalizableAsset('ziggy', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + + Assert::assertInstanceOf(ResponseInterface::class, $downloadResponse); + Assert::assertSame(file_get_contents($expectedFilePath), $downloadResponse->getBody()->getContents()); + } + + public function test_download_a_not_localizable_asset_reference_file() + { + $expectedFilePath = realpath(__DIR__ . '/../../fixtures/ziggy-certification.jpg'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, 'ziggy_certif', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response(file_get_contents($expectedFilePath), [], 201) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $downloadResponse = $api->downloadFromNotLocalizableAsset('ziggy_certif'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + + $this->assertInstanceOf(ResponseInterface::class, $downloadResponse); + Assert::assertSame(file_get_contents($expectedFilePath), $downloadResponse->getBody()->getContents()); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_download_from_localizable_asset_not_found() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, 'ziggy', 'en_US'), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $api->downloadFromLocalizableAsset('ziggy', 'en_US'); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_download_from_not_localizable_asset_not_found() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_DOWNLOAD_URI, 'ziggy_certif', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + + $api->downloadFromNotLocalizableAsset('ziggy_certif'); + } +} diff --git a/tests/Api/AssetReferenceFile/UploadAssetReferenceFileIntegration.php b/tests/Api/AssetReferenceFile/UploadAssetReferenceFileIntegration.php new file mode 100644 index 00000000..dfc67808 --- /dev/null +++ b/tests/Api/AssetReferenceFile/UploadAssetReferenceFileIntegration.php @@ -0,0 +1,176 @@ +server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, 'ziggy', 'en_US'), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $responseCode = $api->uploadForLocalizableAsset($filePath, 'ziggy', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy.png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 25685); + + Assert::assertSame(201, $responseCode); + + $assetReferenceFile = $api->getFromLocalizableAsset('ziggy', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadLocalizableInformations(), $assetReferenceFile); + } + + public function test_upload_a_not_localizable_asset_reference_file() + { + $filePath = realpath(__DIR__ . '/../../fixtures/ziggy-certification.jpg'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, 'ziggy-certification', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadNotLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $responseCode = $api->uploadForNotLocalizableAsset($filePath, 'ziggy-certification'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy-certification.jpg'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/jpeg'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 10513); + + Assert::assertSame(201, $responseCode); + + $assetReferenceFile = $api->getFromNotLocalizableAsset('ziggy-certification'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadNotLocalizableInformations(), $assetReferenceFile); + } + + public function test_upload_from_resource_file() + { + $filePath = __DIR__ . '/../../fixtures/ziggy.png'; + $file = fopen($filePath, 'rb'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, 'ziggy', 'en_US'), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + $responseCode = $api->uploadForLocalizableAsset($file, 'ziggy', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy.png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 25685); + + Assert::assertSame(201, $responseCode); + + $assetReferenceFile = $api->getFromLocalizableAsset('ziggy', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadLocalizableInformations(), $assetReferenceFile); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_upload_for_an_unknown_asset() + { + $filePath = realpath(__DIR__ . '/../../fixtures/ziggy.png'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, 'unknown_asset', 'en_US'), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + + $api->uploadForLocalizableAsset($filePath, 'unknown_asset', 'en_US'); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\UploadAssetReferenceFileErrorException + */ + public function test_upload_a_file_that_cannot_be_transformed_for_the_variations() + { + $filePath = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetReferenceFileApi::ASSET_REFERENCE_FILE_URI, 'unicorn', AssetReferenceFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response(json_encode($this->generateMessageForUploadAssetReferenceFileErrorException())) + ) + ); + + $api = $this->createClient()->getAssetReferenceFileApi(); + + $api->uploadForNotLocalizableAsset($filePath, 'unicorn'); + } + + protected function fakeUploadLocalizableInformations(){ + return [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_ziggy.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => '/api/rest/v1/assets/ziggy/reference-files/en_US/download' + ] + ], + ]; + } + + protected function fakeUploadNotLocalizableInformations(){ + return [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_ziggy_certification.jpg', + 'locale' => null, + '_link' => [ + 'download' => [ + 'href' => '/api/rest/v1/assets/ziggy_certif/reference-files/no-locale/download' + ] + ], + ]; + } + + protected function generateMessageForUploadAssetReferenceFileErrorException(){ + return [ + 'message' => 'Some variation files were not generated properly.', + 'errors' => [ + [ + 'message' => 'Impossible to "resize" the image "/tmp/pim/file_storage/4/2/5/1/unicorn-en_US-ecommerce.png" with a width bigger than the original.', + 'scope' => 'ecommerce', + 'locale' => null + ] + ] + ]; + } +} diff --git a/tests/Api/AssetVariationFile/DownloadAssetVariationFileApiIntegration.php b/tests/Api/AssetVariationFile/DownloadAssetVariationFileApiIntegration.php new file mode 100644 index 00000000..af67e48a --- /dev/null +++ b/tests/Api/AssetVariationFile/DownloadAssetVariationFileApiIntegration.php @@ -0,0 +1,88 @@ +server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_DOWNLOAD_URI, 'ziggy', 'ecommerce', 'en_US'), + new ResponseStack( + new Response(file_get_contents($expectedFilePath), [], 201) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $downloadResponse = $api->downloadFromLocalizableAsset('ziggy', 'ecommerce', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + + Assert::assertInstanceOf(ResponseInterface::class, $downloadResponse); + Assert::assertSame(file_get_contents($expectedFilePath), $downloadResponse->getBody()->getContents()); + } + + + public function test_download_a_not_localizable_asset_variation_file() + { + $expectedFilePath = realpath(__DIR__ . '/../../fixtures/ziggy-certification.jpg'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_DOWNLOAD_URI, 'ziggy_certif', 'ecommerce', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response(file_get_contents($expectedFilePath), [], 201) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $downloadResponse = $api->downloadFromNotLocalizableAsset('ziggy_certif', 'ecommerce'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + + Assert::assertInstanceOf(ResponseInterface::class, $downloadResponse); + Assert::assertSame(file_get_contents($expectedFilePath), $downloadResponse->getBody()->getContents()); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_download_from_localizable_asset_not_found() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_DOWNLOAD_URI, 'ziggy', 'mobile', 'en_US'), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $api->downloadFromLocalizableAsset('ziggy', 'mobile', 'en_US'); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_download_from_not_localizable_asset_not_found() + { + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_DOWNLOAD_URI, 'ziggy_certif', 'mobile', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $api->downloadFromNotLocalizableAsset('ziggy_certif', 'mobile'); + } +} diff --git a/tests/Api/AssetVariationFile/UploadAssetVariationFileApiIntegration.php b/tests/Api/AssetVariationFile/UploadAssetVariationFileApiIntegration.php new file mode 100644 index 00000000..cb0d9220 --- /dev/null +++ b/tests/Api/AssetVariationFile/UploadAssetVariationFileApiIntegration.php @@ -0,0 +1,164 @@ +server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, 'ziggy', 'ecommerce', 'en_US'), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $responseCode = $api->uploadForLocalizableAsset($filePath, 'ziggy', 'ecommerce', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy.png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 25685); + + Assert::assertSame(201, $responseCode); + + $assetVariationFile = $api->getFromLocalizableAsset('ziggy', 'ecommerce', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadLocalizableInformations(), $assetVariationFile); + } + + + public function test_upload_a_not_localizable_asset_variation_file() + { + $filePath = realpath(__DIR__ . '/../../fixtures/ziggy-certification.jpg'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, 'ziggy_certif', 'ecommerce', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadNotLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $responseCode = $api->uploadForNotLocalizableAsset($filePath, 'ziggy_certif', 'ecommerce'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy-certification.jpg'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/jpeg'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 10513); + + Assert::assertSame(201, $responseCode); + + $assetVariationFile = $api->getFromNotLocalizableAsset('ziggy_certif', 'ecommerce'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadNotLocalizableInformations(), $assetVariationFile); + } + + public function test_upload_from_resource_file() + { + $filePath = __DIR__ . '/../../fixtures/ziggy.png'; + $file = fopen($filePath, 'rb'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, 'ziggy', 'ecommerce', 'en_US'), + new ResponseStack( + new Response(file_get_contents($filePath), [], 201), + new Response(json_encode($this->fakeUploadLocalizableInformations()), [], 201) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + $responseCode = $api->uploadForLocalizableAsset($file, 'ziggy', 'ecommerce', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'POST'); + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], 'ziggy.png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], 'image/png'); + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], 25685); + + Assert::assertSame(201, $responseCode); + + $assetReferenceFile = $api->getFromLocalizableAsset('ziggy', 'ecommerce', 'en_US'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($this->fakeUploadLocalizableInformations(), $assetReferenceFile); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + */ + public function test_upload_for_an_unknown_asset() + { + $filePath = realpath(__DIR__ . '/../../fixtures/ziggy.png'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, 'unknown_asset', 'ecommerce', 'en_US'), + new ResponseStack( + new Response('{"code": 404, "message":"Not found"}', [], 404) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + + $api->uploadForLocalizableAsset($filePath, 'unknown_asset', 'ecommerce', 'en_US'); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\UnprocessableEntityHttpException + */ + public function test_upload_for_an_asset_that_should_be_localizable() + { + $filePath = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + + $this->server->setResponseOfPath( + '/'. sprintf(AssetVariationFileApi::ASSET_VARIATION_FILE_URI, 'unicorn', 'ecommerce', AssetVariationFileApi::NOT_LOCALIZABLE_ASSET_LOCALE_CODE), + new ResponseStack( + new Response('{"code": 422, "message":"Unprocessable Entity"}', [], 422) + ) + ); + + $api = $this->createClient()->getAssetVariationFileApi(); + + $api->uploadForNotLocalizableAsset($filePath, 'unicorn', 'ecommerce'); + } + + protected function fakeUploadLocalizableInformations(){ + return [ + 'code' => '5/c/8/3/5c835e7785cb174d8e7e39d7ee63be559f233be0_ziggy_ecommerce.jpg', + 'locale' => 'en_US', + '_link' => [ + 'download' => [ + 'href' => '/api/rest/v1/assets/ziggy/variation-files/ecommerce/en_US/download' + ] + ] + ]; + } + + protected function fakeUploadNotLocalizableInformations(){ + return [ + 'code' => '2/9/b/f/29bfa18ced500c5fca2072dab978737576ca47ca_ziggy_certification_ecommerce.jpg', + 'locale' => null, + '_link' => [ + 'download' => [ + 'href' => '/api/rest/v1/assets/ziggy_certif/variation-files/ecommerce/no-locale/download' + ] + ] + ]; + } +} diff --git a/tests/Api/DownloadProductMediaFileTest.php b/tests/Api/DownloadProductMediaFileTest.php index 9e57fe50..d3ad3e74 100644 --- a/tests/Api/DownloadProductMediaFileTest.php +++ b/tests/Api/DownloadProductMediaFileTest.php @@ -8,7 +8,6 @@ use donatj\MockWebServer\ResponseStack; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; class DownloadProductMediaFileTest extends ApiTestCase { diff --git a/tests/Api/ReferenceEntity/GetReferenceEntityIntegration.php b/tests/Api/ReferenceEntity/GetReferenceEntityIntegration.php new file mode 100644 index 00000000..66591000 --- /dev/null +++ b/tests/Api/ReferenceEntity/GetReferenceEntityIntegration.php @@ -0,0 +1,65 @@ +server->setResponseOfPath( + '/'. sprintf(ReferenceEntityApi::REFERENCE_ENTITY_URI, 'brand'), + new ResponseStack( + new Response($this->getBrand(), [], 200) + ) + ); + + $api = $this->createClient()->getReferenceEntityApi(); + $product = $api->get('brand'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($product, json_decode($this->getBrand(), true)); + } + + public function test_get_unknown_reference_entity() + { + $this->server->setResponseOfPath( + '/'. sprintf(ReferenceEntityApi::REFERENCE_ENTITY_URI, 'foo'), + new ResponseStack( + new Response('{"code": 404, "message":"Reference entity \"foo\" does not exist."}', [], 404) + ) + ); + + $this->expectException(\Akeneo\Pim\ApiClient\Exception\NotFoundHttpException::class); + $this->expectExceptionMessage('Reference entity "foo" does not exist.'); + + $api = $this->createClient()->getReferenceEntityApi(); + $api->get('foo'); + } + + private function getBrand(): string + { + return <<server->setResponseOfPath( + '/'. sprintf(ReferenceEntityApi::REFERENCE_ENTITIES_URI), + new ResponseStack( + new Response($this->getFirstPage(), [], 200), + new Response($this->getSecondPage(), [], 200) + ) + ); + + $api = $this->createClient()->getReferenceEntityApi(); + $referenceEntityCursor = $api->all(); + $referenceEntities = iterator_to_array($referenceEntityCursor); + + Assert::assertCount(3, $referenceEntities); + } + + private function getFirstPage(): string + { + $baseUri = $this->server->getServerRoot(); + + return <<server->getServerRoot(); + + return <<server->setResponseOfPath( + '/'. sprintf(ReferenceEntityApi::REFERENCE_ENTITY_URI, 'brand'), + new ResponseStack( + new Response('', [], 204) + ) + ); + + $referenceEntity = [ + 'code' => 'brand', + 'labels' => [ + 'en_US' => 'Brand' + ] + ]; + + $api = $this->createClient()->getReferenceEntityApi(); + $response = $api->upsert('brand', $referenceEntity); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($referenceEntity)); + Assert::assertSame(204, $response); + } +} diff --git a/tests/Api/ReferenceEntityMediaFile/CreateReferenceEntityMediaFileIntegration.php b/tests/Api/ReferenceEntityMediaFile/CreateReferenceEntityMediaFileIntegration.php new file mode 100644 index 00000000..93f931c4 --- /dev/null +++ b/tests/Api/ReferenceEntityMediaFile/CreateReferenceEntityMediaFileIntegration.php @@ -0,0 +1,60 @@ +server->setResponseOfPath( + '/' . ReferenceEntityMediaFileApi::MEDIA_FILE_CREATE_URI, + new ResponseStack( + new Response('', ['Reference-entities-media-file-code' => 'my-media-code'], 201) + ) + ); + $mediaFile = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + $response = $this->createClient()->getReferenceEntityMediaFileApi()->create($mediaFile); + + Assert::assertNotEmpty($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['name'], + 'unicorn.png' + ); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['type'], + 'image/png' + ); + Assert::assertSame( + $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_FILES]['file']['size'], + 11255 + ); + Assert::assertSame('my-media-code', $response); + } + + public function test_get_media_file_code_regardless_of_the_header_case() + { + $this->server->setResponseOfPath( + '/' . ReferenceEntityMediaFileApi::MEDIA_FILE_CREATE_URI, + new ResponseStack( + new Response('', ['Reference-Entities-Media-File-Code' => 'my-media-code'], 201) + ) + ); + $mediaFile = realpath(__DIR__ . '/../../fixtures/unicorn.png'); + $response = $this->createClient()->getReferenceEntityMediaFileApi()->create($mediaFile); + + Assert::assertSame('my-media-code', $response); + } +} diff --git a/tests/Api/ReferenceEntityRecord/GetReferenceEntityRecordIntegration.php b/tests/Api/ReferenceEntityRecord/GetReferenceEntityRecordIntegration.php new file mode 100644 index 00000000..aff2e944 --- /dev/null +++ b/tests/Api/ReferenceEntityRecord/GetReferenceEntityRecordIntegration.php @@ -0,0 +1,66 @@ +server->setResponseOfPath( + '/'. sprintf(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORD_URI, 'designer', 'starck'), + new ResponseStack( + new Response($this->getStarckRecord(), [], 200) + ) + ); + + $api = $this->createClient()->getReferenceEntityRecordApi(); + $product = $api->get('designer', 'starck'); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_METHOD], 'GET'); + Assert::assertEquals($product, json_decode($this->getStarckRecord(), true)); + } + + /** + * @expectedException \Akeneo\Pim\ApiClient\Exception\NotFoundHttpException + * @expectedExceptionMessage Record "foo" does not exist for the reference entity "designer". + */ + public function test_get_unknow_product() + { + $this->server->setResponseOfPath( + '/'. sprintf(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORD_URI, 'designer', 'foo'), + new ResponseStack( + new Response('{"code": 404, "message":"Record \"foo\" does not exist for the reference entity \"designer\"."}', [], 404) + ) + ); + + $api = $this->createClient()->getReferenceEntityRecordApi(); + $api->get('designer', 'foo'); + } + + private function getStarckRecord(): string + { + return <<server->setResponseOfPath( + '/'. sprintf(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORDS_URI, 'designer'), + new ResponseStack( + new Response($this->getFirstPage(), [], 200), + new Response($this->getSecondPage(), [], 200) + ) + ); + + $api = $this->createClient()->getReferenceEntityRecordApi(); + $recordCursor = $api->all('designer'); + $records = iterator_to_array($recordCursor); + + Assert::assertCount(3, $records); + } + + private function getFirstPage(): string + { + $baseUri = $this->server->getServerRoot(); + + return <<server->getServerRoot(); + + return <<server->setResponseOfPath( + '/'. sprintf(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORDS_URI, 'designer'), + new ResponseStack( + new Response($responseBody, [], 200) + ) + ); + + $records = [ + [ + 'code' => 'starck', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'Philippe Starck' + ], + ] + ] + ], + [ + 'code' => 'dyson', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'James Dyson' + ], + ] + ] + ] + ]; + + $expectedResponses = [ + [ + 'code' => 'starck', + 'status_code' =>204 + ], + [ + 'code' => 'dyson', + 'status_code' =>201 + ], + ]; + + $api = $this->createClient()->getReferenceEntityRecordApi(); + $responses = $api->upsertList('designer', $records); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($records)); + Assert::assertSame($expectedResponses, $responses); + } +} diff --git a/tests/Api/ReferenceEntityRecord/UpsertReferenceEntityRecordIntegration.php b/tests/Api/ReferenceEntityRecord/UpsertReferenceEntityRecordIntegration.php new file mode 100644 index 00000000..d6277c06 --- /dev/null +++ b/tests/Api/ReferenceEntityRecord/UpsertReferenceEntityRecordIntegration.php @@ -0,0 +1,42 @@ +server->setResponseOfPath( + '/'. sprintf(ReferenceEntityRecordApi::REFERENCE_ENTITY_RECORD_URI, 'designer', 'starck'), + new ResponseStack( + new Response('', [], 204) + ) + ); + + $recordData = [ + 'code' => 'starck', + 'values' => [ + 'label' => [ + [ + 'channel' => null, + 'locale' => 'en_US', + 'data' => 'Philippe Starck' + ], + ] + ] + ]; + + $api = $this->createClient()->getReferenceEntityRecordApi(); + $response = $api->upsert('designer', 'starck', $recordData); + + Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($recordData)); + Assert::assertSame(204, $response); + } +} diff --git a/tests/Api/UpsertListProductTest.php b/tests/Api/UpsertListProductTest.php index c17d45d9..2cf6903e 100644 --- a/tests/Api/UpsertListProductTest.php +++ b/tests/Api/UpsertListProductTest.php @@ -7,7 +7,6 @@ use donatj\MockWebServer\Response; use donatj\MockWebServer\ResponseStack; use Http\Discovery\Psr17FactoryDiscovery; -use Http\Discovery\StreamFactoryDiscovery; use PHPUnit\Framework\Assert; class UpsertListProductTest extends ApiTestCase diff --git a/tests/fixtures/akeneo-logo.pdf b/tests/fixtures/akeneo-logo.pdf new file mode 100644 index 00000000..f09613c8 Binary files /dev/null and b/tests/fixtures/akeneo-logo.pdf differ diff --git a/tests/fixtures/unicorn.png b/tests/fixtures/unicorn.png new file mode 100644 index 00000000..a15a9a09 Binary files /dev/null and b/tests/fixtures/unicorn.png differ diff --git a/tests/fixtures/ziggy-certification.jpg b/tests/fixtures/ziggy-certification.jpg new file mode 100644 index 00000000..38fb9430 Binary files /dev/null and b/tests/fixtures/ziggy-certification.jpg differ diff --git a/tests/fixtures/ziggy.png b/tests/fixtures/ziggy.png new file mode 100644 index 00000000..8aa27348 Binary files /dev/null and b/tests/fixtures/ziggy.png differ