diff --git a/.env b/.env index fc02053..0174966 100644 --- a/.env +++ b/.env @@ -32,3 +32,8 @@ AKENEO_CLIENT_ID= AKENEO_SECRET= AKENEO_USERNAME= AKENEO_PASSWORD= + +# Cloudinary credentials +CLOUDINARY_CLOUD_NAME= +CLOUDINARY_API_KEY= +CLOUDINARY_API_SECRET= \ No newline at end of file diff --git a/.php_cd.php b/.php_cd.php index 4049a19..81ee2b1 100644 --- a/.php_cd.php +++ b/.php_cd.php @@ -32,6 +32,11 @@ /** * INFRASTRUCTURE */ + $builder->only([ + 'AkeneoDAMConnector\Application\DamAdapter', + 'AkeneoDAMConnector\Domain', + ])->in('AkeneoDAMConnector\Infrastructure\DAM\Cloudinary'), + $builder->only([ 'AkeneoDAMConnector\Application\DamAdapter', 'AkeneoDAMConnector\Domain', diff --git a/composer.json b/composer.json index 9801f67..24460d7 100644 --- a/composer.json +++ b/composer.json @@ -13,8 +13,9 @@ "php": "^7.1.3", "ext-ctype": "*", "ext-iconv": "*", - "akeneo/api-php-client-ee": "dev-asset-family@dev", "akeneo/api-php-client": "dev-master@dev", + "akeneo/api-php-client-ee": "dev-asset-family@dev", + "cloudinary/cloudinary_php": "1.14.*", "doctrine/dbal": "2.9.*", "http-interop/http-factory-guzzle": "^1.0", "php-http/guzzle6-adapter": "^2.0", diff --git a/composer.lock b/composer.lock index 5b72740..c608ad4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ab4674bf83dab4ce9f62c7b2190a1562", + "content-hash": "d73004be6cd8af02e7c63c6aa4fa78f4", "packages": [ { "name": "akeneo/api-php-client", @@ -115,6 +115,58 @@ }, "time": "2019-09-19T14:32:27+00:00" }, + { + "name": "cloudinary/cloudinary_php", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/cloudinary/cloudinary_php.git", + "reference": "d4c947f6728c339649a10999a6a6362e5c7b9490" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cloudinary/cloudinary_php/zipball/d4c947f6728c339649a10999a6a6362e5c7b9490", + "reference": "d4c947f6728c339649a10999a6a6362e5c7b9490", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "src" + ], + "files": [ + "src/Helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cloudinary", + "homepage": "https://github.com/cloudinary/cloudinary_php/graphs/contributors" + } + ], + "description": "Cloudinary PHP SDK", + "homepage": "https://github.com/cloudinary/cloudinary_php", + "keywords": [ + "cdn", + "cloud", + "cloudinary", + "image management", + "sdk" + ], + "time": "2019-05-13T14:27:40+00:00" + }, { "name": "doctrine/cache", "version": "v1.8.0", @@ -4348,8 +4400,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "akeneo/api-php-client-ee": 20, - "akeneo/api-php-client": 20 + "akeneo/api-php-client": 20, + "akeneo/api-php-client-ee": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config/resources/cloudinary/mapping.yaml b/config/resources/cloudinary/mapping.yaml new file mode 100644 index 0000000..e69de29 diff --git a/config/resources/cloudinary/structure.yaml b/config/resources/cloudinary/structure.yaml new file mode 100644 index 0000000..e69de29 diff --git a/config/services.yaml b/config/services.yaml index 6779ac6..b3c141f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -3,7 +3,7 @@ imports: # Import the configuration for our DAM example implementation - - { resource: services/dam-example.yaml } + - { resource: services/dam-adapter.yaml } # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration diff --git a/config/services/dam-adapter.yaml b/config/services/dam-adapter.yaml new file mode 100644 index 0000000..70bd0ef --- /dev/null +++ b/config/services/dam-adapter.yaml @@ -0,0 +1,20 @@ +parameters: + app.pim_structure.config_path: '%kernel.project_dir%/config/resources/cloudinary/structure.yaml' + app.dam_to_pim_mapping.config_path: '%kernel.project_dir%/config/resources/cloudinary/mapping.yaml' + +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + AkeneoDAMConnector\Infrastructure\DAM\Cloudinary\: + resource: '../../src/Infrastructure/DAM/Cloudinary/*' + + AkeneoDAMConnector\Infrastructure\DAM\Cloudinary\Search: + arguments: + $cloudName: '%env(CLOUDINARY_CLOUD_NAME)%' + $apiKey: '%env(CLOUDINARY_API_KEY)%' + $apiSecret: '%env(CLOUDINARY_API_SECRET)%' + + AkeneoDAMConnector\Application\DamAdapter\FetchAssets: '@AkeneoDAMConnector\Infrastructure\DAM\Cloudinary\FetchAssets' diff --git a/config/services/dam-example.yaml b/config/services/dam-example.yaml~ similarity index 100% rename from config/services/dam-example.yaml rename to config/services/dam-example.yaml~ diff --git a/src/Infrastructure/DAM/Cloudinary/FetchAssets.php b/src/Infrastructure/DAM/Cloudinary/FetchAssets.php new file mode 100644 index 0000000..c118a1e --- /dev/null +++ b/src/Infrastructure/DAM/Cloudinary/FetchAssets.php @@ -0,0 +1,60 @@ +search = $search; + } + + public function fetch(FamilyCode $assetFamilyCode, ?\DateTimeInterface $lastFetchDate): \Iterator + { + $expression = sprintf('tags:akeneo AND folder="%s"', (string) $assetFamilyCode); + $response = $this->search->search($expression, ['tags', 'context']); + + $staticAttributes = ['filename', 'url', 'secure_url', 'status', 'public_id']; + + $damAssets = []; + + $assets = $response['resources'] ?? []; + foreach ($assets as $asset) { + $damAsset = new DamAsset( + new DamAssetIdentifier($asset['filename']), + $assetFamilyCode, + new Locale('en_US') + ); + + foreach ($staticAttributes as $staticAttribute) { + $damAsset->addValue($staticAttribute, $asset[$staticAttribute]); + } + + foreach ($asset['context'] as $property => $value) { + $damAsset->addValue($property, $value); + } + $damAsset->addValue('tags', implode(', ', $asset['tags'])); + + $damAssets[] = $damAsset; + } + + return new \ArrayIterator($damAssets); + } +} diff --git a/src/Infrastructure/DAM/Cloudinary/Search.php b/src/Infrastructure/DAM/Cloudinary/Search.php new file mode 100644 index 0000000..a0f71cf --- /dev/null +++ b/src/Infrastructure/DAM/Cloudinary/Search.php @@ -0,0 +1,31 @@ + $cloudName, + 'api_key' => $apiKey, + 'api_secret' => $apiSecret, + 'secure' => true + )); + } + + public function search(string $expression, array $withFields) + { + $searchEngine = new \Cloudinary\Search(); + $searchEngine->expression($expression); + if (!empty($withFields)) { + foreach ($withFields as $field) { + $searchEngine->with_field($field); + } + } + + return $searchEngine->execute(); + } +} diff --git a/symfony.lock b/symfony.lock index c0db319..0c765a5 100644 --- a/symfony.lock +++ b/symfony.lock @@ -8,6 +8,9 @@ "akeneo/php-coupling-detector": { "version": "0.3.1" }, + "cloudinary/cloudinary_php": { + "version": "1.14.0" + }, "composer/semver": { "version": "1.x-dev" },