diff --git a/README.md b/README.md index 1d5323f..daf4398 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,1145 @@ -[DEPRECATED] Sylius ElasticSearchPlugin +Sylius ElasticSearchPlugin ========================== +Elastic search for Sylius. +[![Build status on Linux](https://img.shields.io/travis/Sylius/SyliusElasticSearchPlugin/master.svg)](https://travis-ci.org/Sylius/SyliusElasticSearchPlugin) -The development of this plugin by Sylius organization is currently frozen. We may or may not approach the problem again but nothing is planned yet. Please use the production-ready plugin by BitBag available here: https://github.com/BitBagCommerce/SyliusElasticsearchPlugin. +## Usage -If you would like to fork this plugin and continue its development, please consider contributing to the plugin mentioned above. If you still think it is a good idea to fork, then feel free to do so when respecting the MIT license. +1. Install it: -Thanks for your understanding and happy coding! :) + ```bash + $ composer require sylius/elastic-search-plugin + ``` + +2. Install elastic search server: + + ```bash + $ brew install elasticsearch@5.0 + ``` + +3. Run elastic search server: + + ```bash + $ elasticsearch + ``` + +4. Add those bundles to `AppKernel.php`: + + ```php + new \ONGR\ElasticsearchBundle\ONGRElasticsearchBundle(), + new \SimpleBus\SymfonyBridge\SimpleBusCommandBusBundle(), + new \SimpleBus\SymfonyBridge\SimpleBusEventBusBundle(), + new \ONGR\FilterManagerBundle\ONGRFilterManagerBundle(), + new \Sylius\ElasticSearchPlugin\SyliusElasticSearchPlugin(), + ``` + +5. Create/Setup database: + + ```bash + $ bin/console ongr:es:index:create + $ bin/console do:da:cr + $ bin/console do:sch:cr + $ bin/console syl:fix:lo + ``` + + If there is a problem with creating elastic search index run those commands: + + ```bash + $ bin/console ongr:es:index:drop --force + $ bin/console ongr:es:index:create + ``` + +7. Import config file in `app/config/config.yml` for default filter set configuration: + + ```yaml + imports: + - { resource: "@SyliusElasticSearchPlugin/Resources/config/app/config.yml" } + ``` + For more configuration take a look at [ONGRFilterManager](http://docs.ongr.io/FilterManagerBundle) + +8. Configure ONGR bundle in `app/config/config.yml`: + + ```yaml + ongr_elasticsearch: + managers: + default: + index: + index_name: sylius + mappings: + SyliusElasticSearchPlugin: {} + + sylius_elastic_search: + attribute_whitelist: ['MUG_COLLECTION_CODE', 'MUG_MATERIAL_CODE'] #Only attibutes with these codes will be indexed + ``` + +8. Import routing file: + + ```yaml + sylius_search: + resource: "@SyliusElasticSearchPlugin/Resources/config/routing.yml" + ``` + +9. Example Request/Response: + +It's required to pass `channel` argument to the search. +To activate filter you need to pass in parameter (query, request, attribute) ``requested field`` see reference in configuration section. + +For e.g: + +``` + /shop-api/taxon-products/mugs?channel=WEB_DE&price=2000;3000 +``` + +It will activate ``taxon_slug``, ``price_range`` and ``channel`` filter. + +Request: + +``` + /shop-api/taxon-products/mugs?channel=WEB_GB +``` + +Response: + +```json +{ + "items": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "slug": "logan-mug", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection", + "value": "HOLIDAY COLLECTION" + }, + { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material", + "value": "Wood" + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "slug": "logan-becher", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection", + "value": "FEIERTAGSKOLLEKTION" + }, + { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material", + "value": "Holz" + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + } + ], + "filters": { + "channel": { + "state": { + "active": false, + "urlParameters": [], + "name": "channel", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "channel", + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "channel": "WEB_GB" + }, + "label": "WEB_GB", + "count": 2 + } + ] + }, + "taxon_slug": { + "state": { + "active": true, + "value": "mugs", + "urlParameters": { + "taxon_slug": "mugs" + }, + "name": "taxon_slug", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": [], + "name": "taxon_slug", + "choices": [ + { + "active": true, + "default": false, + "urlParameters": [], + "label": "mugs", + "count": 2 + }, + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "t-shirts" + }, + "label": "t-shirts", + "count": 2 + } + ] + }, + "price_range": { + "state": { + "active": false, + "urlParameters": [], + "name": "price_range", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "price_range", + "minBounds": 1999, + "maxBounds": 1999 + }, + "locale": { + "state": { + "active": false, + "urlParameters": [], + "name": "locale", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "locale", + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "locale_code": "de_DE" + }, + "label": "de_DE", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "locale_code": "en_GB" + }, + "label": "en_GB", + "count": 1 + } + ] + }, + "attribute_values": { + "state": { + "active": false, + "urlParameters": [], + "name": "attribute_values", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "attribute_values", + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "attributeValues": [ + "FEIERTAGSKOLLEKTION" + ] + }, + "label": "FEIERTAGSKOLLEKTION", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "attributeValues": [ + "HOLIDAY COLLECTION" + ] + }, + "label": "HOLIDAY COLLECTION", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "attributeValues": [ + "Holz" + ] + }, + "label": "Holz", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "taxon_slug": "mugs", + "attributeValues": [ + "Wood" + ] + }, + "label": "Wood", + "count": 1 + } + ] + }, + "paginator": { + "state": { + "active": false, + "value": 1, + "urlParameters": [], + "name": "paginator", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "paginator", + "currentPage": 1, + "totalItems": 2, + "maxPages": 10, + "itemsPerPage": 10, + "numPages": 1, + "options": [] + }, + "search": { + "state": { + "active": false, + "urlParameters": [], + "name": "search", + "options": [] + }, + "tags": [], + "urlParameters": { + "taxon_slug": "mugs" + }, + "resetUrlParameters": { + "taxon_slug": "mugs" + }, + "name": "search" + } + } +} +``` + +10. Filtering by attributes: + +You need use attributes query parameter which is an associative array where key is the attribute name and value is an array of attribute values. +For e.g: +```php +$this->client->request('GET', '/shop-api/products', ['attributes' => ['Mug material' => ['Wood']]], [], ['ACCEPT' => 'application/json']); +``` + +This filter also aggregates all attribute values and it will group them by attribute name +Aggregation response from this request: + +```json + "attributes":{ + "state":{ + "active":true, + "value":{ + "Mug material":[ + "Wood" + ] + }, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"attributes", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":[ + + ], + "name":"attributes", + "items":[ + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":[ + + ], + "name":"Mug collection", + "choices":{ + "HOLIDAY COLLECTION":{ + "active":false, + "default":false, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ], + "Mug collection":[ + "HOLIDAY COLLECTION" + ] + } + }, + "label":"HOLIDAY COLLECTION", + "count":1 + } + } + }, + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":[ + + ], + "name":"Mug material", + "choices":{ + "Holz":{ + "active":false, + "default":false, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood", + "Holz" + ] + } + }, + "label":"Holz", + "count":1 + }, + "Wood":{ + "active":true, + "default":false, + "urlParameters":{ + "attributes":{ + "Mug material":[ + + ] + } + }, + "label":"Wood", + "count":1 + } + } + } + ] + } +``` + +You can combine filters so for example if you want your products to be filtered in specific locale you can add another query parameter + +Example request with locale: +```php +$this->client->request('GET', '/shop-api/products', ['attributes' => ['Mug material' => ['Wood']], 'locale' => 'en_GB'], [], ['ACCEPT' => 'application/json']); +``` + +Aggregation response from this request: + +```json + "attributes":{ + "state":{ + "active":true, + "value":{ + "Mug material":[ + "Wood" + ] + }, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"attributes", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"attributes", + "items":[ + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"Mug collection", + "choices":{ + "HOLIDAY COLLECTION":{ + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ], + "Mug collection":[ + "HOLIDAY COLLECTION" + ] + } + }, + "label":"HOLIDAY COLLECTION", + "count":1 + } + } + }, + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"Mug material", + "choices":{ + "Wood":{ + "active":true, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + + ] + } + }, + "label":"Wood", + "count":1 + } + } + } + ] + } +``` + +Whole response: + +```json +{ + "items":[ + { + "code":"LOGAN_MUG_CODE", + "name":"Logan Mug", + "slug":"logan-mug", + "taxons":{ + "main":"MUG", + "others":[ + "MUG", + "CATEGORY", + "BRAND" + ] + }, + "variants":[ + { + "code":"LOGAN_MUG_CODE", + "name":"Logan Mug", + "price":{ + "current":1999, + "currency":"GBP" + }, + "images":[ + + ] + } + ], + "attributes":[ + { + "code":"MUG_COLLECTION_CODE", + "name":"Mug collection", + "value":"HOLIDAY COLLECTION" + }, + { + "code":"MUG_MATERIAL_CODE", + "name":"Mug material", + "value":"Wood" + } + ], + "images":[ + + ], + "channelCode":"WEB_GB", + "localeCode":"en_GB" + } + ], + "filters":{ + "channel":{ + "state":{ + "active":false, + "urlParameters":[ + + ], + "name":"channel", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"channel", + "choices":[ + { + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + }, + "channel":"WEB_GB" + }, + "label":"WEB_GB", + "count":1 + } + ] + }, + "taxon_code":{ + "state":{ + "active":false, + "urlParameters":[ + + ], + "name":"taxon_code", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"taxon_code", + "choices":[ + { + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + }, + "taxonCode":"BRAND" + }, + "label":"BRAND", + "count":1 + }, + { + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + }, + "taxonCode":"CATEGORY" + }, + "label":"CATEGORY", + "count":1 + }, + { + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + }, + "taxonCode":"MUG" + }, + "label":"MUG", + "count":1 + } + ] + }, + "price_range":{ + "state":{ + "active":false, + "urlParameters":[ + + ], + "name":"price_range", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"price_range", + "minBounds":1999, + "maxBounds":2999 + }, + "locale":{ + "state":{ + "active":true, + "value":"en_GB", + "urlParameters":{ + "locale":"en_GB" + }, + "name":"locale", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"locale", + "choices":[ + { + "active":true, + "default":false, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "label":"en_GB", + "count":1 + } + ] + }, + "paginator":{ + "state":{ + "active":false, + "value":1, + "urlParameters":[ + + ], + "name":"paginator", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"paginator", + "currentPage":1, + "totalItems":1, + "maxPages":10, + "itemsPerPage":10, + "numPages":1, + "options":[ + + ] + }, + "search":{ + "state":{ + "active":false, + "urlParameters":[ + + ], + "name":"search", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"search" + }, + "attributes":{ + "state":{ + "active":true, + "value":{ + "Mug material":[ + "Wood" + ] + }, + "urlParameters":{ + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "name":"attributes", + "options":[ + + ] + }, + "tags":[ + + ], + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ] + } + }, + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"attributes", + "items":[ + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"Mug collection", + "choices":{ + "HOLIDAY COLLECTION":{ + "active":false, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + "Wood" + ], + "Mug collection":[ + "HOLIDAY COLLECTION" + ] + } + }, + "label":"HOLIDAY COLLECTION", + "count":1 + } + } + }, + { + "tags":[ + + ], + "urlParameters":[ + + ], + "resetUrlParameters":{ + "locale":"en_GB" + }, + "name":"Mug material", + "choices":{ + "Wood":{ + "active":true, + "default":false, + "urlParameters":{ + "locale":"en_GB", + "attributes":{ + "Mug material":[ + + ] + } + }, + "label":"Wood", + "count":1 + } + } + } + ] + } + } +} +``` + +11. Sorting + +* By name ascending: + + ``` + /shop-api/products?channel=WEB_DE&sort[name]=asc + ``` + +* By price descending: + + ``` + /shop-api/products?channel=WEB_DE&sort[price]=desc + ``` + +* By attribute `ATTRIBUTE_CODE` ascending: + + ``` + /shop-api/products?channel=WEB_DE&sort[attributes][ATTRIBUTE_CODE]=asc + ``` + +* By price ascending, then by name descending: + + ``` + /shop-api/products?channel=WEB_DE&sort[price]=asc&sort[name]=desc + ``` + +12. Filtering by attribute + +* By attribute name and value: + + ``` + /shop-api/products?channel=WEB_DE&attributes[Attribute name]=value + ``` + +* By attribute code and value: + + ``` + /shop-api/products?channel=WEB_DE&attributesByCode[ATTRIBUTE_CODE]=value + ``` + +13. Reindexing Elasticsearch + +The current implementation does not support updating Elasticsearch when an entity is updated. +In order to stay up-to-date, run the following command: + + ``` + bin/console sylius:elastic-search:update-product-index + ``` + +If you want to recreate the index, run (it will drop it): + + ``` + bin/console sylius:elastic-search:reset-product-index + ``` diff --git a/composer.json b/composer.json index 9c11a77..d0a78f3 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "ecedi/elastic-search-plugin", + "name": "sylius/elastic-search-plugin", "type": "sylius-bundle", "description": "Elastic search integration for Sylius.", "license": "MIT", @@ -12,11 +12,12 @@ ], "require": { "php": "^7.1", + "sylius/sylius": "^1.0", "ongr/elasticsearch-dsl": "^5.0", "ongr/elasticsearch-bundle": "^5.0", "simple-bus/symfony-bridge": "^4.1", - "ongr/filter-manager-bundle": "^2.1", + "ongr/filter-manager-bundle": "2.1.x-dev as v2.1.1", "ramsey/uuid": "^3.7" }, "require-dev": { @@ -39,21 +40,17 @@ "behat/mink-selenium2-driver": "^1.3", "lakion/api-test-case": "^1.1", "doctrine/common": "<2.8", - "symplify/easy-coding-standard": "^2.4", - "sylius-labs/coding-standard": "^1.0" + "symplify/easy-coding-standard": "^2.4" }, "config": { "bin-dir": "bin" }, - "minimum-stability": "stable", + "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { "Sylius\\ElasticSearchPlugin\\": "src/", "Tests\\Sylius\\ElasticSearchPlugin\\": "tests/" } - }, - "autoload-dev": { - "classmap": ["tests/Application/app/AppKernel.php"] } } diff --git a/easy-coding-standard.neon b/easy-coding-standard.neon index 004aef0..da8c20d 100644 --- a/easy-coding-standard.neon +++ b/easy-coding-standard.neon @@ -1,2 +1,145 @@ -includes: - - vendor/sylius-labs/coding-standard/easy-coding-standard.neon +checkers: + PhpCsFixer\Fixer\Alias\EregToPregFixer: {} + PhpCsFixer\Fixer\Alias\NoAliasFunctionsFixer: {} + PhpCsFixer\Fixer\Alias\PowToExponentiationFixer: {} + PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer: + use: echo + PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer: + syntax: short + PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer: {} + PhpCsFixer\Fixer\ArrayNotation\NormalizeIndexBraceFixer: {} + PhpCsFixer\Fixer\ArrayNotation\NoTrailingCommaInSinglelineArrayFixer: {} + PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer: {} + PhpCsFixer\Fixer\ArrayNotation\TrailingCommaInMultilineArrayFixer: {} + PhpCsFixer\Fixer\ArrayNotation\TrimArraySpacesFixer: {} + PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer: {} + PhpCsFixer\Fixer\Basic\BracesFixer: + allow_single_line_closure: true + PhpCsFixer\Fixer\Basic\EncodingFixer: {} + PhpCsFixer\Fixer\Basic\NonPrintableCharacterFixer: {} + PhpCsFixer\Fixer\Casing\LowercaseConstantsFixer: {} + PhpCsFixer\Fixer\Casing\LowercaseKeywordsFixer: {} + PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer: {} + PhpCsFixer\Fixer\Casing\MagicConstantCasingFixer: {} + PhpCsFixer\Fixer\CastNotation\CastSpacesFixer: {} + PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer: {} + PhpCsFixer\Fixer\CastNotation\ModernizeTypesCastingFixer: {} + PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer: {} + PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer: {} + PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer: + singleItemSingleLine: true + multiLineExtendsEachSingleLine: true + PhpCsFixer\Fixer\ClassNotation\MethodSeparationFixer: {} + PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer: {} + PhpCsFixer\Fixer\ClassNotation\NoNullPropertyInitializationFixer: {} + PhpCsFixer\Fixer\ClassNotation\NoPhp4ConstructorFixer: {} + PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer: {} + PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer: {} + PhpCsFixer\Fixer\ClassNotation\SelfAccessorFixer: {} + PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer: {} + PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer: {} + PhpCsFixer\Fixer\Comment\HashToSlashCommentFixer: {} + PhpCsFixer\Fixer\Comment\NoEmptyCommentFixer: {} + PhpCsFixer\Fixer\Comment\NoTrailingWhitespaceInCommentFixer: {} + PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer: + comment_types: ['hash'] + PhpCsFixer\Fixer\ControlStructure\ElseifFixer: {} + PhpCsFixer\Fixer\ControlStructure\IncludeFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoSuperfluousElseifFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoTrailingCommaInListCallFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoUnneededCurlyBracesFixer: {} + PhpCsFixer\Fixer\ControlStructure\NoUselessElseFixer: {} + PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer: {} + PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer: {} + PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer: {} + PhpCsFixer\Fixer\FunctionNotation\FunctionTypehintSpaceFixer: {} + PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer: {} + PhpCsFixer\Fixer\FunctionNotation\NoSpacesAfterFunctionNameFixer: {} + PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer: {} + PhpCsFixer\Fixer\Import\NoLeadingImportSlashFixer: {} + PhpCsFixer\Fixer\Import\NoUnusedImportsFixer: {} + PhpCsFixer\Fixer\Import\OrderedImportsFixer: {} + PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer: {} + PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveIssetsFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveUnsetsFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\DirConstantFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\FunctionToConstantFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\IsNullFixer: {} + PhpCsFixer\Fixer\LanguageConstruct\SilencedDeprecationErrorFixer: {} + PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer: + syntax: short + PhpCsFixer\Fixer\NamespaceNotation\BlankLineAfterNamespaceFixer: {} + PhpCsFixer\Fixer\NamespaceNotation\NoLeadingNamespaceWhitespaceFixer: {} + PhpCsFixer\Fixer\NamespaceNotation\SingleBlankLineBeforeNamespaceFixer: {} + PhpCsFixer\Fixer\Naming\NoHomoglyphNamesFixer: {} + PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer: + align_double_arrow: false + align_equals: false + PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: + spacing: one + PhpCsFixer\Fixer\Operator\NewWithBracesFixer: {} + PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer: {} + PhpCsFixer\Fixer\Operator\PreIncrementFixer: {} + PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer: {} + PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer: {} + PhpCsFixer\Fixer\Operator\TernaryToNullCoalescingFixer: {} + PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: {} + PhpCsFixer\Fixer\Phpdoc\NoBlankLinesAfterPhpdocFixer: {} + PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocIndentFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocNoAccessFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocNoAliasTagFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocNoEmptyReturnFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocNoPackageFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocNoUselessInheritdocFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocReturnSelfReferenceFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocScalarFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocSeparationFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocSingleLineVarSpacingFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer: {} + PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer: + null_adjustment: always_last + sort_algorithm: none + PhpCsFixer\Fixer\Phpdoc\PhpdocVarWithoutNameFixer: {} + PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer: {} + PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer: {} + PhpCsFixer\Fixer\PhpTag\NoClosingTagFixer: {} + PhpCsFixer\Fixer\PhpUnit\PhpUnitDedicateAssertFixer: {} + PhpCsFixer\Fixer\PhpUnit\PhpUnitFqcnAnnotationFixer: {} + PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer: {} + PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer: {} + PhpCsFixer\Fixer\Semicolon\SpaceAfterSemicolonFixer: {} + PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer: {} + PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer: {} + PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer: {} + PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer: {} + PhpCsFixer\Fixer\Whitespace\LineEndingFixer: {} + PhpCsFixer\Fixer\Whitespace\NoExtraConsecutiveBlankLinesFixer: + - break + - case + - continue + - curly_brace_block + - default + - extra + - parenthesis_brace_block + - return + - square_brace_block + - switch + - throw + - use + PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer: {} + PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer: {} + PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer: {} + PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer: {} + PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer: {} + +parameters: + skip: + PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer: + - *Spec.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 130842f..1e84ce7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,7 +12,7 @@ - + diff --git a/spec/Document/AttributeDocumentSpec.php b/spec/Document/AttributeDocumentSpec.php index 0ecf17a..60b38a2 100644 --- a/spec/Document/AttributeDocumentSpec.php +++ b/spec/Document/AttributeDocumentSpec.php @@ -1,11 +1,9 @@ setTaxons($taxons); + $this->setProductTaxons($taxons); - $this->getTaxons()->shouldReturn($taxons); + $this->getProductTaxons()->shouldReturn($taxons); } function it_has_attributes() diff --git a/spec/Document/TaxonDocumentSpec.php b/spec/Document/TaxonDocumentSpec.php index 911ed6d..97aec66 100644 --- a/spec/Document/TaxonDocumentSpec.php +++ b/spec/Document/TaxonDocumentSpec.php @@ -1,12 +1,10 @@ beConstructedWith($eventBus); + } + + function it_is_initializable() + { + $this->shouldHaveType(ProductPublisher::class); + } + + function it_publishes_product_event( MessageBus $eventBus, OnFlushEventArgs $onFlushEvent, PostFlushEventArgs $postFlushEvent, + ProductInterface $product, EntityManager $entityManager, - UnitOfWork $unitOfWork, - ProductInterface $product - ): void { - $this->beConstructedWith($eventBus); - + UnitOfWork $unitOfWork + ) { $onFlushEvent->getEntityManager()->willReturn($entityManager); $postFlushEvent->getEntityManager()->willReturn($entityManager); $entityManager->getUnitOfWork()->willReturn($unitOfWork); - - $unitOfWork->getScheduledEntityInsertions()->willReturn([]); - $unitOfWork->getScheduledEntityUpdates()->willReturn([]); - $unitOfWork->getScheduledEntityDeletions()->willReturn([]); - - $product->getCode()->willReturn('PRODUCT_CODE'); - } - - function it_publishes_product_created_event_when_product_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductInterface $product - ): void { $unitOfWork->getScheduledEntityInsertions()->willReturn([$product]); $eventBus->handle(ProductCreated::occur($product->getWrappedObject()))->shouldBeCalled(); @@ -61,552 +45,20 @@ function it_publishes_product_created_event_when_product_is_created( $this->postFlush($postFlushEvent); } - function it_publishes_product_updated_event_when_product_translation_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTranslationInterface $productTranslation, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productTranslation]); - - $productTranslation->getTranslatable()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productVariant]); - - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_translation_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantTranslationInterface $productVariantTranslation, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productVariantTranslation]); - - $productVariantTranslation->getTranslatable()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_channel_pricing_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ChannelPricingInterface $productVariantChannelPricing, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productVariantChannelPricing]); - - $productVariantChannelPricing->getProductVariant()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_taxon_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTaxonInterface $productTaxon, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productTaxon]); - - $productTaxon->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_attribute_value_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductAttributeValueInterface $productAttributeValue, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productAttributeValue]); - - $productAttributeValue->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_image_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_image_is_created( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_only_product_created_event_if_there_is_also_product_updated_event_for_the_same_product( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityInsertions()->willReturn([$product, $productVariant]); - - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductCreated::occur($product->getWrappedObject()))->shouldBeCalledTimes(1); - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldNotBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$product]); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_translation_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTranslationInterface $productTranslation, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productTranslation]); - - $productTranslation->getTranslatable()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productVariant]); - - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_translation_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantTranslationInterface $productVariantTranslation, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productVariantTranslation]); - - $productVariantTranslation->getTranslatable()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_channel_pricing_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ChannelPricingInterface $productVariantChannelPricing, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productVariantChannelPricing]); - - $productVariantChannelPricing->getProductVariant()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_taxon_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTaxonInterface $productTaxon, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productTaxon]); - - $productTaxon->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_attribute_value_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductAttributeValueInterface $productAttributeValue, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productAttributeValue]); - - $productAttributeValue->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_image_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_image_is_updated( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_only_one_product_updated_event_for_every_distinct_product( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $firstProductImage, - ProductVariantInterface $firstProductVariant, - ProductVariantInterface $secondProductVariant, - ProductInterface $firstProduct, - ProductInterface $secondProduct - ): void { - $unitOfWork->getScheduledEntityUpdates()->willReturn([ - $firstProductVariant, - $firstProductImage, - $secondProductVariant, - $firstProduct, - $secondProduct, - ]); - - $firstProductImage->getOwner()->willReturn($firstProductVariant); - $firstProductVariant->getProduct()->willReturn($firstProduct); - $firstProduct->getCode()->willReturn('FIRST_PRODUCT_CODE'); - - $secondProductVariant->getProduct()->willReturn($secondProduct); - $secondProduct->getCode()->willReturn('SECOND_PRODUCT_CODE'); - - $eventBus->handle(ProductUpdated::occur($firstProduct->getWrappedObject()))->shouldBeCalledTimes(1); - $eventBus->handle(ProductUpdated::occur($secondProduct->getWrappedObject()))->shouldBeCalledTimes(1); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_deleted_event_when_product_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$product]); - - $eventBus->handle(ProductDeleted::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_translation_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTranslationInterface $productTranslation, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productTranslation]); - - $productTranslation->getTranslatable()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productVariant]); - - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_translation_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantTranslationInterface $productVariantTranslation, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productVariantTranslation]); - - $productVariantTranslation->getTranslatable()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_channel_pricing_is_deleted( + function it_does_not_publish_product_event_if_entity_is_not_a_product( MessageBus $eventBus, OnFlushEventArgs $onFlushEvent, PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ChannelPricingInterface $productVariantChannelPricing, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productVariantChannelPricing]); - - $productVariantChannelPricing->getProductVariant()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_taxon_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductTaxonInterface $productTaxon, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productTaxon]); - - $productTaxon->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_attribute_value_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductAttributeValueInterface $productAttributeValue, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productAttributeValue]); - - $productAttributeValue->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_image_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_product_updated_event_when_product_variant_image_is_deleted( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductImageInterface $productImage, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$productImage]); - - $productImage->getOwner()->willReturn($productVariant); - $productVariant->getProduct()->willReturn($product); - - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldBeCalled(); - - $this->onFlush($onFlushEvent); - $this->postFlush($postFlushEvent); - } - - function it_publishes_only_product_deleted_event_if_there_is_also_product_deleted_event_for_the_same_product( - MessageBus $eventBus, - OnFlushEventArgs $onFlushEvent, - PostFlushEventArgs $postFlushEvent, - UnitOfWork $unitOfWork, - ProductVariantInterface $productVariant, - ProductInterface $product - ): void { - $unitOfWork->getScheduledEntityDeletions()->willReturn([$product, $productVariant]); + EntityManager $entityManager, + UnitOfWork $unitOfWork + ) { + $onFlushEvent->getEntityManager()->willReturn($entityManager); + $postFlushEvent->getEntityManager()->willReturn($entityManager); - $productVariant->getProduct()->willReturn($product); + $entityManager->getUnitOfWork()->willReturn($unitOfWork); + $unitOfWork->getScheduledEntityInsertions()->willReturn([new \stdClass()]); - $eventBus->handle(ProductDeleted::occur($product->getWrappedObject()))->shouldBeCalledTimes(1); - $eventBus->handle(ProductUpdated::occur($product->getWrappedObject()))->shouldNotBeCalled(); + $eventBus->handle(Argument::any())->shouldNotBeCalled(); $this->onFlush($onFlushEvent); $this->postFlush($postFlushEvent); diff --git a/spec/Projection/ProductProjectorSpec.php b/spec/Projection/ProductProjectorSpec.php index 44eb693..0b7d758 100644 --- a/spec/Projection/ProductProjectorSpec.php +++ b/spec/Projection/ProductProjectorSpec.php @@ -1,21 +1,19 @@ findBy(['code' => 'FOO'])->willReturn(new \ArrayIterator([$existingProductDocument])); $newProductDocument = new ProductDocument(); - $productDocumentFactory->create($product, $locale, $channel)->willReturn($newProductDocument); + $productDocumentFactory->createFromSyliusSimpleProductModel($product, $locale, $channel)->willReturn($newProductDocument); $elasticsearchManager->persist($newProductDocument)->shouldBeCalled(); $elasticsearchManager->remove($existingProductDocument)->shouldBeCalled(); @@ -70,7 +68,7 @@ function it_does_not_save_product_document_if_product_does_not_have_channel_defi $productDocumentRepository->findBy(['code' => 'FOO'])->willReturn(new \ArrayIterator([])); - $productDocumentFactory->create(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); + $productDocumentFactory->createFromSyliusSimpleProductModel(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); $elasticsearchManager->persist(Argument::any())->shouldNotBeCalled(); $elasticsearchManager->commit()->shouldBeCalled(); @@ -91,7 +89,7 @@ function it_does_not_save_product_document_if_channel_has_not_locales_defined( $productDocumentRepository->findBy(['code' => 'FOO'])->willReturn(new \ArrayIterator([])); - $productDocumentFactory->create(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); + $productDocumentFactory->createFromSyliusSimpleProductModel(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); $elasticsearchManager->persist(Argument::any())->shouldNotBeCalled(); $elasticsearchManager->commit()->shouldBeCalled(); diff --git a/src/Command/ResetProductIndexCommand.php b/src/Command/ResetProductIndexCommand.php index 48e3b10..39d3b66 100644 --- a/src/Command/ResetProductIndexCommand.php +++ b/src/Command/ResetProductIndexCommand.php @@ -8,11 +8,10 @@ use Sylius\Component\Core\Model\ChannelInterface; use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Core\Repository\ProductRepositoryInterface; -use Sylius\ElasticSearchPlugin\Factory\Document\ProductDocumentFactoryInterface; +use Sylius\ElasticSearchPlugin\Factory\ProductDocumentFactoryInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\LockHandler; final class ResetProductIndexCommand extends Command { @@ -24,7 +23,7 @@ final class ResetProductIndexCommand extends Command /** * @var Manager */ - private $elasticsearchManager; + private $manager; /** * @var ProductDocumentFactoryInterface @@ -42,7 +41,7 @@ public function __construct( ProductDocumentFactoryInterface $productDocumentFactory ) { $this->productRepository = $productRepository; - $this->elasticsearchManager = $manager; + $this->manager = $manager; $this->productDocumentFactory = $productDocumentFactory; parent::__construct('sylius:elastic-search:reset-product-index'); @@ -63,52 +62,43 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output) { - $lockHandler = new LockHandler('sylius-elastic-index-update'); - if ($lockHandler->lock()) { - if (!$input->getOption('force')) { - $output->writeln('WARNING! This command will drop the existing index and rebuild it from scratch. To proceed, run with "--force" option.'); + if (!$input->getOption('force')) { + $output->writeln('WARNING! This command will drop the existing index and rebuild it from scratch. To proceed, run with "--force" option.'); - return; - } - - $output->writeln(sprintf('Dropping and creating "%s" ElasticSearch index', $this->elasticsearchManager->getIndexName())); - $this->elasticsearchManager->dropAndCreateIndex(); - - $productDocumentsCreated = 0; + return; + } - /** @var ProductInterface[] $products */ - $products = $this->productRepository->findAll(); + $this->manager->dropAndCreateIndex(); - $output->writeln(sprintf('Loading %d products into ElasticSearch', count($products))); + $productDocumentsCreated = 0; - foreach ($products as $product) { - $channels = $product->getChannels(); + /** @var ProductInterface[] $products */ + $products = $this->productRepository->findAll(); + foreach ($products as $product) { + $channels = $product->getChannels(); - /** @var ChannelInterface $channel */ - foreach ($channels as $channel) { - $locales = $channel->getLocales(); - foreach ($locales as $locale) { - $productDocument = $this->productDocumentFactory->create( - $product, - $locale, - $channel - ); + /** @var ChannelInterface $channel */ + foreach ($channels as $channel) { + $locales = $channel->getLocales(); + foreach ($locales as $locale) { + $productDocument = $this->productDocumentFactory->createFromSyliusSimpleProductModel( + $product, + $locale, + $channel + ); - $this->elasticsearchManager->persist($productDocument); + $this->manager->persist($productDocument); - ++$productDocumentsCreated; - if (($productDocumentsCreated % 100) === 0) { - $this->elasticsearchManager->commit(); - } + ++$productDocumentsCreated; + if (($productDocumentsCreated % 100) === 0) { + $this->manager->commit(); } } } - - $this->elasticsearchManager->commit(); - $lockHandler->release(); - $output->writeln('Product index was rebuilt!'); - } else { - $output->writeln(sprintf('Command is already running')); } + + $this->manager->commit(); + + $output->writeln('Product index was reset!'); } } diff --git a/src/Command/UpdateProductIndexCommand.php b/src/Command/UpdateProductIndexCommand.php index 05308be..9a7c247 100644 --- a/src/Command/UpdateProductIndexCommand.php +++ b/src/Command/UpdateProductIndexCommand.php @@ -13,11 +13,10 @@ use Sylius\Component\Core\Repository\ProductRepositoryInterface; use Sylius\Component\Locale\Model\LocaleInterface; use Sylius\ElasticSearchPlugin\Document\ProductDocument; -use Sylius\ElasticSearchPlugin\Factory\Document\ProductDocumentFactoryInterface; +use Sylius\ElasticSearchPlugin\Factory\ProductDocumentFactoryInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\LockHandler; final class UpdateProductIndexCommand extends Command { @@ -72,46 +71,30 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): void { - $lockHandler = new LockHandler('sylius-elastic-index-update'); - if ($lockHandler->lock()) { - $processedProductsCodes = []; - $productDocumentsWaitingForCommit = 0; + $processedProductsCodes = []; - $search = $this->productDocumentRepository->createSearch(); - $search->setScroll('10m'); - $search->addSort(new FieldSort('synchronised_at', 'asc')); + $search = $this->productDocumentRepository->createSearch(); + $search->setScroll('10m'); + $search->addSort(new FieldSort('synchronised_at', 'ASC')); - /** @var DocumentIterator|ProductDocument[] $productDocuments */ - $productDocuments = $this->productDocumentRepository->findDocuments($search); + /** @var DocumentIterator|ProductDocument[] $productDocuments */ + $productDocuments = $this->productDocumentRepository->findDocuments($search); - foreach ($productDocuments as $productDocument) { - $productCode = $productDocument->getCode(); + foreach ($productDocuments as $productDocument) { + $productCode = $productDocument->getCode(); - if (isset($processedProductsCodes[$productCode])) { - continue; - } - - $output->writeln(sprintf('Updating product with code "%s"', $productCode)); + if (in_array($productCode, $processedProductsCodes, true)) { + continue; + } - $this->scheduleCreatingNewProductDocuments($productCode); - $this->scheduleRemovingOldProductDocuments($productCode); + $output->writeln(sprintf('Updating product with code "%s"', $productCode)); - ++$productDocumentsWaitingForCommit; - if (($productDocumentsWaitingForCommit % 100) === 0) { - $this->elasticsearchManager->commit(); - $productDocumentsWaitingForCommit = 0; - } + $this->scheduleCreatingNewProductDocuments($productCode); + $this->scheduleRemovingOldProductDocuments($productCode); - $processedProductsCodes[$productCode] = 1; - } + $this->elasticsearchManager->commit(); - if ($productDocumentsWaitingForCommit > 0) { - $this->elasticsearchManager->commit(); - } - $lockHandler->release(); - $output->writeln('Updates done'); - } else { - $output->writeln(sprintf('Command is already running')); + $processedProductsCodes[] = $productCode; } } @@ -132,7 +115,7 @@ private function scheduleCreatingNewProductDocuments(string $productCode): void $locales = $channel->getLocales(); foreach ($locales as $locale) { - $this->elasticsearchManager->persist($this->productDocumentFactory->create( + $this->elasticsearchManager->persist($this->productDocumentFactory->createFromSyliusSimpleProductModel( $product, $locale, $channel diff --git a/src/Controller/PriceView.php b/src/Controller/PriceView.php index 0fb2d36..3a5a9f5 100644 --- a/src/Controller/PriceView.php +++ b/src/Controller/PriceView.php @@ -15,9 +15,4 @@ class PriceView * @var string */ public $currency; - - /** - * @var int - */ - public $original; } diff --git a/src/Controller/ProductView.php b/src/Controller/ProductView.php index 4b4ba8c..b2ea18e 100644 --- a/src/Controller/ProductView.php +++ b/src/Controller/ProductView.php @@ -6,11 +6,6 @@ class ProductView { - /** - * @var int - */ - public $id; - /** * @var string */ @@ -46,11 +41,6 @@ class ProductView */ public $images = []; - /** - * @var PriceView - */ - public $price; - /** * @var string */ @@ -65,9 +55,4 @@ class ProductView * @var array */ public $mainTaxon; - - /** - * @var float - */ - public $rating; } diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php index b15fbfe..846b8cf 100644 --- a/src/Controller/SearchController.php +++ b/src/Controller/SearchController.php @@ -1,6 +1,13 @@ query->has('sort')) { if (null !== $request->get('taxonCode')) { - $request->query->set('sort', ['taxonPositionByCode' => [$request->get('taxonCode') => 'asc']]); + $request->query->set('sort', ['taxonPositionByCode' => [$request->get('taxonCode') => 'ASC']]); } if (null !== $request->get('taxonSlug')) { - $request->query->set('sort', ['taxonPositionBySlug' => [$request->get('taxonSlug') => 'asc']]); + $request->query->set('sort', ['taxonPositionBySlug' => [$request->get('taxonSlug') => 'ASC']]); } } diff --git a/src/Controller/VariantView.php b/src/Controller/VariantView.php index a6feb6b..0b900d1 100644 --- a/src/Controller/VariantView.php +++ b/src/Controller/VariantView.php @@ -6,11 +6,6 @@ class VariantView { - /** - * @var int - */ - public $id; - /** * @var string */ @@ -26,16 +21,6 @@ class VariantView */ public $price; - /** - * @var int - */ - public $stock; - - /** - * @var int - */ - public $isTracked; - /** * @var ImageView[] */ diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 589de07..19ac9de 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -25,6 +25,7 @@ use Sylius\ElasticSearchPlugin\Document\OptionDocument; use Sylius\ElasticSearchPlugin\Document\PriceDocument; use Sylius\ElasticSearchPlugin\Document\ProductDocument; +use Sylius\ElasticSearchPlugin\Document\ProductTaxonDocument; use Sylius\ElasticSearchPlugin\Document\TaxonDocument; use Sylius\ElasticSearchPlugin\Document\VariantDocument; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; @@ -66,6 +67,7 @@ private function buildDocumentClassesNode(ArrayNodeDefinition $rootNode) ->scalarNode('attribute')->defaultValue(AttributeDocument::class)->end() ->scalarNode('image')->defaultValue(ImageDocument::class)->end() ->scalarNode('price')->defaultValue(PriceDocument::class)->end() + ->scalarNode('product_taxon')->defaultValue(ProductTaxonDocument::class)->end() ->scalarNode('taxon')->defaultValue(TaxonDocument::class)->end() ->scalarNode('variant')->defaultValue(VariantDocument::class)->end() ->scalarNode('option')->defaultValue(OptionDocument::class)->end() diff --git a/src/DependencyInjection/SyliusElasticSearchExtension.php b/src/DependencyInjection/SyliusElasticSearchExtension.php index 706e062..249fe10 100644 --- a/src/DependencyInjection/SyliusElasticSearchExtension.php +++ b/src/DependencyInjection/SyliusElasticSearchExtension.php @@ -17,7 +17,7 @@ final class SyliusElasticSearchExtension extends Extension public function load(array $configs, ContainerBuilder $container) { $config = $this->processConfiguration($this->getConfiguration([], $container), $configs); - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $container->setParameter('sylius_elastic_search.attribute_whitelist', $config['attribute_whitelist']); diff --git a/src/Document/AttributeDocument.php b/src/Document/AttributeDocument.php index f875f3f..4beec4a 100644 --- a/src/Document/AttributeDocument.php +++ b/src/Document/AttributeDocument.php @@ -16,7 +16,7 @@ class AttributeDocument * * @ElasticSearch\Property(type="keyword") */ - protected $code; + private $code; /** * @var string @@ -33,7 +33,7 @@ class AttributeDocument * } * ) */ - protected $name; + private $name; /** * @var mixed @@ -50,7 +50,7 @@ class AttributeDocument * } * ) */ - protected $value; + private $value; /** * @return string diff --git a/src/Document/ImageDocument.php b/src/Document/ImageDocument.php index f4f4d0f..5bb8ea8 100644 --- a/src/Document/ImageDocument.php +++ b/src/Document/ImageDocument.php @@ -16,14 +16,14 @@ class ImageDocument * * @ElasticSearch\Property(type="keyword") */ - protected $code; + private $code; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $path; + private $path; /** * @return string diff --git a/src/Document/OptionDocument.php b/src/Document/OptionDocument.php index 62ef3cb..0c65e13 100644 --- a/src/Document/OptionDocument.php +++ b/src/Document/OptionDocument.php @@ -16,7 +16,7 @@ class OptionDocument * * @ElasticSearch\Property(type="keyword") */ - protected $code; + private $code; /** * @var string @@ -33,7 +33,7 @@ class OptionDocument * } * ) */ - protected $name; + private $name; /** * @var string @@ -50,7 +50,7 @@ class OptionDocument * } * ) */ - protected $value; + private $value; /** * @return string @@ -99,4 +99,5 @@ public function setValue(string $value): void { $this->value = $value; } + } diff --git a/src/Document/PriceDocument.php b/src/Document/PriceDocument.php index d834263..eef8bad 100644 --- a/src/Document/PriceDocument.php +++ b/src/Document/PriceDocument.php @@ -16,21 +16,14 @@ class PriceDocument * * @ElasticSearch\Property(type="integer") */ - protected $amount; - - /** - * @var int - * - * @ElasticSearch\Property(type="integer") - */ - protected $originalAmount = 0; + private $amount; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $currency; + private $currency; /** * @return int @@ -48,22 +41,6 @@ public function setAmount(int $amount): void $this->amount = $amount; } - /** - * @return int - */ - public function getOriginalAmount(): int - { - return $this->originalAmount; - } - - /** - * @param int $originalAmount - */ - public function setOriginalAmount(int $originalAmount = 0): void - { - $this->originalAmount = $originalAmount; - } - /** * @return string */ diff --git a/src/Document/ProductDocument.php b/src/Document/ProductDocument.php index 3f09785..28b93a4 100644 --- a/src/Document/ProductDocument.php +++ b/src/Document/ProductDocument.php @@ -12,26 +12,19 @@ */ class ProductDocument { - /** - * @var string - * - * @ElasticSearch\Id() - */ - protected $uuid; - /** * @var mixed * - * @ElasticSearch\Property(type="keyword") + * @ElasticSearch\Id() */ - protected $id; + private $id; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $code; + private $code; /** * @var string @@ -49,128 +42,120 @@ class ProductDocument * } * ) */ - protected $name; + private $name; /** - * @var bool + * @var boolean * * @ElasticSearch\Property(type="boolean") */ - protected $enabled; + private $enabled; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $slug; + private $slug; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $channelCode; + private $channelCode; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $localeCode; + private $localeCode; /** * @var string * * @ElasticSearch\Property(type="text") */ - protected $description; + private $description; /** * @var PriceDocument * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\PriceDocument") */ - protected $price; + private $price; /** * @var TaxonDocument * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\TaxonDocument") */ - protected $mainTaxon; + private $mainTaxon; /** * @var Collection|TaxonDocument[] * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\TaxonDocument", multiple=true) */ - protected $taxons; + private $taxons; + + /** + * @var Collection|ProductTaxonDocument[] + * + * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\ProductTaxonDocument", multiple=true) + */ + private $productTaxons; /** * @var Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\AttributeDocument", multiple=true) */ - protected $attributes; + private $attributes; /** * @var Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\ImageDocument", multiple=true) */ - protected $images; + private $images; /** * @var float */ - protected $averageReviewRating; + private $averageReviewRating; /** * @var \DateTimeInterface * * @ElasticSearch\Property(type="date") */ - protected $createdAt; + private $createdAt; /** * @var Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\VariantDocument", multiple=true) */ - protected $variants; + private $variants; /** * @var \DateTimeInterface * * @ElasticSearch\Property(type="date") */ - protected $synchronisedAt; + private $synchronisedAt; public function __construct() { $this->attributes = new Collection(); $this->taxons = new Collection(); + $this->productTaxons = new Collection(); $this->images = new Collection(); $this->variants = new Collection(); } - /** - * @return string - */ - public function getUuid(): string - { - return $this->uuid; - } - - /** - * @param string $uuid - */ - public function setUuid(string $uuid): void - { - $this->uuid = $uuid; - } - /** * @return mixed */ @@ -182,7 +167,7 @@ public function getId() /** * @param mixed $id */ - public function setId($id): void + public function setId($id) { $this->id = $id; } @@ -347,6 +332,22 @@ public function setTaxons($taxons): void $this->taxons = $taxons; } + /** + * @return Collection + */ + public function getProductTaxons() + { + return $this->productTaxons; + } + + /** + * @param Collection $productTaxons + */ + public function setProductTaxons(Collection $productTaxons) + { + $this->productTaxons = $productTaxons; + } + /** * @return Collection */ @@ -382,7 +383,7 @@ public function setImages(Collection $images): void /** * @return float */ - public function getAverageReviewRating(): ?float + public function getAverageReviewRating(): float { return $this->averageReviewRating; } diff --git a/src/Document/TaxonDocument.php b/src/Document/TaxonDocument.php index 3218d5c..26bfab5 100644 --- a/src/Document/TaxonDocument.php +++ b/src/Document/TaxonDocument.php @@ -8,7 +8,7 @@ use ONGR\ElasticsearchBundle\Collection\Collection; /** - * @ElasticSearch\Nested() + * @ElasticSearch\Object */ class TaxonDocument { @@ -17,35 +17,35 @@ class TaxonDocument * * @ElasticSearch\Property(type="keyword") */ - protected $code; + private $code; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $slug; + private $slug; /** * @var int * * @ElasticSearch\Property(type="integer") */ - protected $position = 0; + private $position = 0; /** * @var ImageDocument[]|Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\ImageDocument", multiple=true) */ - protected $images; + private $images; /** * @var string * * @ElasticSearch\Property(type="text") */ - protected $description; + private $description; public function __construct() { diff --git a/src/Document/VariantDocument.php b/src/Document/VariantDocument.php index 98c385c..37a1e31 100644 --- a/src/Document/VariantDocument.php +++ b/src/Document/VariantDocument.php @@ -12,61 +12,47 @@ */ class VariantDocument { - /** - * @var mixed - * - * @ElasticSearch\Property(type="keyword") - */ - protected $id; - /** * @var Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\ImageDocument", multiple=true) */ - protected $images; + private $images; /** * @var PriceDocument * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\PriceDocument") */ - protected $price; + private $price; /** * @var string * * @ElasticSearch\Property(type="keyword") */ - protected $code; - - /** - * @var string - * - * @ElasticSearch\Property(type="text") - */ - protected $name; + private $code; /** * @var int * * @ElasticSearch\Property(type="integer") */ - protected $stock; + private $stock; /** * @var bool * * @ElasticSearch\Property(type="boolean") */ - protected $isTracked; + private $isTracked; /** * @var Collection * * @ElasticSearch\Embedded(class="Sylius\ElasticSearchPlugin\Document\OptionDocument", multiple=true) */ - protected $options; + private $options; public function __construct() { @@ -74,22 +60,6 @@ public function __construct() $this->options = new Collection(); } - /** - * @return mixed - */ - public function getId() - { - return $this->id; - } - - /** - * @param mixed $id - */ - public function setId($id): void - { - $this->id = $id; - } - /** * @return Collection */ @@ -138,22 +108,6 @@ public function setCode(string $code): void $this->code = $code; } - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - */ - public function setName(string $name): void - { - $this->name = $name; - } - /** * @return int */ @@ -206,4 +160,5 @@ public function setOptions(Collection $options): void { $this->options = $options; } + } diff --git a/src/Event/ProductDeleted.php b/src/Event/ProductDeleted.php deleted file mode 100644 index 56f4d9a..0000000 --- a/src/Event/ProductDeleted.php +++ /dev/null @@ -1,41 +0,0 @@ -product = $product; - } - - /** - * @param ProductInterface $product - * - * @return self - */ - public static function occur(ProductInterface $product) - { - return new self($product); - } - - /** - * @return ProductInterface - */ - public function product(): ProductInterface - { - return $this->product; - } -} diff --git a/src/Event/ProductUpdated.php b/src/Event/ProductUpdated.php deleted file mode 100644 index 8a748d0..0000000 --- a/src/Event/ProductUpdated.php +++ /dev/null @@ -1,41 +0,0 @@ -product = $product; - } - - /** - * @param ProductInterface $product - * - * @return self - */ - public static function occur(ProductInterface $product) - { - return new self($product); - } - - /** - * @return ProductInterface - */ - public function product(): ProductInterface - { - return $this->product; - } -} diff --git a/src/EventListener/ProductPublisher.php b/src/EventListener/ProductPublisher.php index 3983ae5..213fe96 100644 --- a/src/EventListener/ProductPublisher.php +++ b/src/EventListener/ProductPublisher.php @@ -7,17 +7,8 @@ use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PostFlushEventArgs; use SimpleBus\Message\Bus\MessageBus; -use Sylius\Component\Core\Model\ChannelPricingInterface; -use Sylius\Component\Core\Model\ProductImageInterface; use Sylius\Component\Core\Model\ProductInterface; -use Sylius\Component\Core\Model\ProductTaxonInterface; -use Sylius\Component\Core\Model\ProductTranslationInterface; -use Sylius\Component\Core\Model\ProductVariantInterface; -use Sylius\Component\Product\Model\ProductAttributeValueInterface; -use Sylius\Component\Product\Model\ProductVariantTranslationInterface; use Sylius\ElasticSearchPlugin\Event\ProductCreated; -use Sylius\ElasticSearchPlugin\Event\ProductDeleted; -use Sylius\ElasticSearchPlugin\Event\ProductUpdated; final class ProductPublisher { @@ -29,17 +20,7 @@ final class ProductPublisher /** * @var ProductInterface[] */ - private $scheduledInsertions = []; - - /** - * @var ProductInterface[] - */ - private $scheduledUpdates = []; - - /** - * @var ProductInterface[] - */ - private $scheduledDeletions = []; + private $scheduledProducts = []; /** * @param MessageBus $eventBus @@ -52,42 +33,13 @@ public function __construct(MessageBus $eventBus) /** * @param OnFlushEventArgs $event */ - public function onFlush(OnFlushEventArgs $event): void + public function onFlush(OnFlushEventArgs $event) { $scheduledInsertions = $event->getEntityManager()->getUnitOfWork()->getScheduledEntityInsertions(); foreach ($scheduledInsertions as $entity) { - if ($entity instanceof ProductInterface && !isset($this->scheduledInsertions[$entity->getCode()])) { - $this->scheduledInsertions[$entity->getCode()] = $entity; - - continue; - } - - $entity = $this->getProductFromEntity($entity); - if ($entity instanceof ProductInterface && !isset($this->scheduledUpdates[$entity->getCode()])) { - $this->scheduledUpdates[$entity->getCode()] = $entity; - } - } - - $scheduledUpdates = $event->getEntityManager()->getUnitOfWork()->getScheduledEntityUpdates(); - foreach ($scheduledUpdates as $entity) { - $entity = $this->getProductFromEntity($entity); - if ($entity instanceof ProductInterface && !isset($this->scheduledUpdates[$entity->getCode()])) { - $this->scheduledUpdates[$entity->getCode()] = $entity; - } - } - - $scheduledDeletions = $event->getEntityManager()->getUnitOfWork()->getScheduledEntityDeletions(); - foreach ($scheduledDeletions as $entity) { - if ($entity instanceof ProductInterface && !isset($this->scheduledDeletions[$entity->getCode()])) { - $this->scheduledDeletions[$entity->getCode()] = $entity; - - continue; - } - - $entity = $this->getProductFromEntity($entity); - if ($entity instanceof ProductInterface && !isset($this->scheduledUpdates[$entity->getCode()])) { - $this->scheduledUpdates[$entity->getCode()] = $entity; + if ($entity instanceof ProductInterface) { + $this->scheduledProducts[] = $entity; } } } @@ -95,69 +47,12 @@ public function onFlush(OnFlushEventArgs $event): void /** * @param PostFlushEventArgs $event */ - public function postFlush(PostFlushEventArgs $event): void + public function postFlush(PostFlushEventArgs $event) { - foreach ($this->scheduledInsertions as $product) { + foreach ($this->scheduledProducts as $product) { $this->eventBus->handle(ProductCreated::occur($product)); } - $scheduledUpdates = array_diff_key( - $this->scheduledUpdates, - $this->scheduledInsertions, - $this->scheduledDeletions - ); - foreach ($scheduledUpdates as $product) { - $this->eventBus->handle(ProductUpdated::occur($product)); - } - - foreach ($this->scheduledDeletions as $product) { - $this->eventBus->handle(ProductDeleted::occur($product)); - } - - $this->scheduledInsertions = []; - $this->scheduledUpdates = []; - $this->scheduledDeletions = []; - } - - /** - * @param object $entity - * - * @return ProductInterface|null - */ - private function getProductFromEntity($entity): ?ProductInterface - { - if ($entity instanceof ProductInterface) { - return $entity; - } - - if ($entity instanceof ProductTranslationInterface) { - return $this->getProductFromEntity($entity->getTranslatable()); - } - - if ($entity instanceof ProductVariantInterface) { - return $entity->getProduct(); - } - - if ($entity instanceof ProductVariantTranslationInterface) { - return $this->getProductFromEntity($entity->getTranslatable()); - } - - if ($entity instanceof ChannelPricingInterface) { - return $this->getProductFromEntity($entity->getProductVariant()); - } - - if ($entity instanceof ProductTaxonInterface) { - return $entity->getProduct(); - } - - if ($entity instanceof ProductAttributeValueInterface) { - return $entity->getProduct(); - } - - if ($entity instanceof ProductImageInterface) { - return $this->getProductFromEntity($entity->getOwner()); - } - - return null; + $this->scheduledProducts = []; } } diff --git a/src/Factory/Document/AttributeDocumentFactory.php b/src/Factory/Document/AttributeDocumentFactory.php deleted file mode 100644 index 8d4b681..0000000 --- a/src/Factory/Document/AttributeDocumentFactory.php +++ /dev/null @@ -1,55 +0,0 @@ -attributeDocumentClass = $attributeDocumentClass; - } - - public function create( - $data, - LocaleInterface $locale, - ProductAttributeValueInterface $productAttributeValue - ): array { - $productAttributes = []; - - if (is_array($data)) { - foreach ($data as $value) { - $productAttributes = array_merge( - $productAttributes, - $this->create( - $value, - $locale, - $productAttributeValue - ) - ); - } - } else { - /** @var AttributeDocument $productAttribute */ - $productAttribute = new $this->attributeDocumentClass(); - $productAttribute->setCode($productAttributeValue->getCode()); - $productAttribute->setValue($data); - /** @var ProductAttributeTranslationInterface $productAttributeTranslation */ - $productAttributeTranslation = $productAttributeValue->getAttribute()->getTranslation( - $locale->getCode() - ); - $productAttribute->setName($productAttributeTranslation->getName()); - $productAttributes = [$productAttribute]; - } - - return $productAttributes; - } -} diff --git a/src/Factory/Document/AttributeDocumentFactoryInterface.php b/src/Factory/Document/AttributeDocumentFactoryInterface.php deleted file mode 100644 index 26d084f..0000000 --- a/src/Factory/Document/AttributeDocumentFactoryInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -imageDocumentClass = $imageDocumentClass; - } - - public function create(ImageInterface $image): ImageDocument - { - /** @var ImageDocument $imageDocument */ - $imageDocument = new $this->imageDocumentClass(); - $imageDocument->setCode($image->getType()); - $imageDocument->setPath($image->getPath()); - - return $imageDocument; - } -} diff --git a/src/Factory/Document/ImageDocumentFactoryInterface.php b/src/Factory/Document/ImageDocumentFactoryInterface.php deleted file mode 100644 index dd0c165..0000000 --- a/src/Factory/Document/ImageDocumentFactoryInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -optionDocumentClass = $optionDocumentClass; - } - - public function create( - ProductOptionValueInterface $optionValue, - LocaleInterface $locale - ): OptionDocument { - /** @var ProductOptionValueTranslationInterface $optionValueTranslation */ - $optionValueTranslation = $optionValue->getTranslation($locale->getCode()); - - /** @var ProductOptionTranslationInterface $productOptionTranslation */ - $productOptionTranslation = $optionValue->getOption()->getTranslation($locale->getCode()); - - /** @var OptionDocument $option */ - $option = new $this->optionDocumentClass(); - $option->setCode($optionValue->getOptionCode()); - $option->setName($productOptionTranslation->getName()); - $option->setValue($optionValueTranslation->getValue()); - - return $option; - } -} diff --git a/src/Factory/Document/OptionDocumentFactoryInterface.php b/src/Factory/Document/OptionDocumentFactoryInterface.php deleted file mode 100644 index bb94f44..0000000 --- a/src/Factory/Document/OptionDocumentFactoryInterface.php +++ /dev/null @@ -1,17 +0,0 @@ -priceDocumentClass = $priceDocumentClass; - } - - public function create( - ChannelPricingInterface $channelPricing, - CurrencyInterface $currency - ): PriceDocument { - /** @var PriceDocument $price */ - $price = new $this->priceDocumentClass(); - $originalAmount = $channelPricing->getOriginalPrice(); - - $price->setAmount($channelPricing->getPrice()); - $price->setCurrency($currency->getCode()); - $price->setOriginalAmount(null !== $originalAmount && $originalAmount > 0 ? $originalAmount : 0); - - return $price; - } -} diff --git a/src/Factory/Document/PriceDocumentFactoryInterface.php b/src/Factory/Document/PriceDocumentFactoryInterface.php deleted file mode 100644 index a9afd30..0000000 --- a/src/Factory/Document/PriceDocumentFactoryInterface.php +++ /dev/null @@ -1,17 +0,0 @@ -assertClassExtends($productDocumentClass, ProductDocument::class); - $this->productDocumentClass = $productDocumentClass; - - $this->attributeDocumentFactory = $attributeDocumentFactory; - $this->imageDocumentFactory = $imageDocumentFactory; - $this->priceDocumentFactory = $priceDocumentFactory; - $this->taxonDocumentFactory = $taxonDocumentFactory; - $this->variantDocumentFactory = $variantDocumentFactory; - $this->attributeWhitelist = $attributeWhitelist; - } - - /** - * Create a product document from the product object with all it's related documents - * - * @param ProductInterface $product - * @param LocaleInterface $locale - * @param ChannelInterface $channel - * - * @return ProductDocument - */ - public function create( - ProductInterface $product, - LocaleInterface $locale, - ChannelInterface $channel - ): ProductDocument { - /** @var ProductVariantInterface[] $productVariants */ - $productVariants = $product->getVariants()->filter(function (ProductVariantInterface $productVariant) use ($channel): bool { - return $productVariant->hasChannelPricingForChannel($channel); - }); - - /** - * @var ArrayObject - */ - $iterator = $productVariants->getIterator(); - $iterator->uasort( - function (ProductVariantInterface $a, ProductVariantInterface $b) { - return $a->getName() <=> $b->getName(); - } - ); - $variantDocuments = []; - foreach ($iterator as $variant) { - $variantDocuments[] = $this->variantDocumentFactory->create($variant, $channel, $locale); - } - - /** @var ImageDocument[] $imageDocuments */ - $imageDocuments = []; - foreach ($product->getImages() as $productImage) { - foreach ($productVariants as $variant) { - if ($variant->hasImage($productImage)) { - continue 2; - } - } - - $imageDocuments[] = $this->imageDocumentFactory->create($productImage); - } - - /** @var TaxonDocument[] $taxonDocuments */ - $taxonDocuments = []; - foreach ($product->getProductTaxons() as $syliusProductTaxon) { - $taxonDocuments[] = $this->taxonDocumentFactory->create( - $syliusProductTaxon->getTaxon(), - $locale, - $syliusProductTaxon->getPosition() - ); - } - - /** @var ProductTranslationInterface|TranslationInterface $productTranslation */ - $productTranslation = $product->getTranslation($locale->getCode()); - - $attributeDocuments = $this->getAttributeDocuments($product, $locale, $channel); - - /** @var ProductDocument $productDocument */ - $productDocument = new $this->productDocumentClass(); - $productDocument->setUuid(Uuid::uuid4()->toString()); - $productDocument->setId($product->getId()); - $productDocument->setEnabled($product->isEnabled()); - $productDocument->setLocaleCode($locale->getCode()); - $productDocument->setSlug($productTranslation->getSlug()); - $productDocument->setName($productTranslation->getName()); - $productDocument->setDescription($productTranslation->getDescription()); - $productDocument->setChannelCode($channel->getCode()); - $productDocument->setCode($product->getCode()); - $productDocument->setCreatedAt($product->getCreatedAt()); - $productDocument->setSynchronisedAt(new \DateTime('now')); - $productDocument->setAverageReviewRating($product->getAverageRating()); - $productDocument->setVariants(new Collection($variantDocuments)); - $productDocument->setImages(new Collection($imageDocuments)); - $productDocument->setTaxons(new Collection($taxonDocuments)); - $productDocument->setAttributes(new Collection($attributeDocuments)); - - /** - * Set smallest product variant price, used for search by price - */ - $productDocument->setPrice( - $this->priceDocumentFactory->create( - $this->getMinimalPriceFromVariants($productVariants, $channel), - $channel->getBaseCurrency() - ) - ); - - if (null !== $product->getMainTaxon()) { - $productDocument->setMainTaxon( - $this->taxonDocumentFactory->create($product->getMainTaxon(), $locale) - ); - } - - return $productDocument; - } - - /** - * @param ProductVariantInterface[]|DoctrineCollection $variants - * @param ChannelInterface $channel - * - * @return ChannelPricingInterface - */ - private function getMinimalPriceFromVariants($variants, ChannelInterface $channel): ChannelPricingInterface - { - /** @var ChannelPricingInterface $minProductChannelPrice */ - $minProductChannelPrice = $variants->first()->getChannelPricingForChannel($channel); - - foreach ($variants as $variant) { - $channelPrice = $variant->getChannelPricingForChannel($channel); - if ( - ($variant->isTracked() && $variant->getOnHold() - $variant->getOnHold( - ) > 0 && $minProductChannelPrice->getPrice() < $channelPrice->getPrice()) - || (!$variant->isTracked() && $minProductChannelPrice->getPrice() < $channelPrice->getPrice()) - ) { - $minProductChannelPrice = $channelPrice; - } - } - - return $minProductChannelPrice; - } - - /** - * @param string $class - * @param string $parentClass - * - * @throws \InvalidArgumentException - */ - private function assertClassExtends(string $class, string $parentClass) - { - if ($class !== $parentClass && !in_array($parentClass, class_parents($class), true)) { - throw new \InvalidArgumentException(sprintf('Class %s MUST extend class %s!', $class, $parentClass)); - } - } - - /** - * @param ProductInterface $product - * @param LocaleInterface $locale - * @param ChannelInterface $channel - * - * @return array - */ - private function getAttributeDocuments( - ProductInterface $product, - LocaleInterface $locale, - ChannelInterface $channel - ): array { - $productAttributes = $product->getAttributesByLocale( - $locale->getCode(), - $channel->getDefaultLocale()->getCode() - ); - - $attributeDocuments = []; - foreach ($productAttributes as $syliusProductAttributeValue) { - if (in_array($syliusProductAttributeValue->getCode(), $this->attributeWhitelist, true) || empty($this->attributeWhitelist)) { - $attributeDocuments = array_merge( - $attributeDocuments, - $this->attributeDocumentFactory->create( - $syliusProductAttributeValue->getValue(), - $locale, - $syliusProductAttributeValue - ) - ); - } - } - - return $attributeDocuments; - } -} diff --git a/src/Factory/Document/ProductDocumentFactoryInterface.php b/src/Factory/Document/ProductDocumentFactoryInterface.php deleted file mode 100644 index dd0dce5..0000000 --- a/src/Factory/Document/ProductDocumentFactoryInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -taxonDocumentClass = $taxonDocumentClass; - $this->imageDocumentFactory = $imageDocumentFactory; - } - - /** - * @param TaxonInterface $taxon Sylius taxon model - * @param LocaleInterface $localeCode - * @param int|null $position Override the position in the Taxon model by passing your own - * - * @return TaxonDocument - */ - public function create(TaxonInterface $taxon, LocaleInterface $localeCode, ?int $position = null): TaxonDocument - { - /** @var TaxonTranslationInterface $taxonTranslation */ - $taxonTranslation = $taxon->getTranslation($localeCode->getCode()); - - /** @var TaxonDocument $taxonDocument */ - $taxonDocument = new $this->taxonDocumentClass(); - $taxonDocument->setCode($taxon->getCode()); - $taxonDocument->setSlug($taxonTranslation->getSlug()); - if (is_int($position)) { - $taxonDocument->setPosition($position); - } else { - $taxonDocument->setPosition($taxon->getPosition()); - } - - $taxonDocument->setDescription($taxonTranslation->getDescription()); - - /** @var ImageDocument[] $images */ - $images = []; - foreach ($taxon->getImages() as $image) { - $images[] = $this->imageDocumentFactory->create($image); - } - $taxonDocument->setImages(new Collection($images)); - - return $taxonDocument; - } -} diff --git a/src/Factory/Document/TaxonDocumentFactoryInterface.php b/src/Factory/Document/TaxonDocumentFactoryInterface.php deleted file mode 100644 index 6227b79..0000000 --- a/src/Factory/Document/TaxonDocumentFactoryInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -variantDocumentClass = $variantDocumentClass; - $this->priceDocumentFactory = $priceDocumentFactory; - $this->imageDocumentFactory = $imageDocumentFactory; - $this->optionDocumentFactory = $optionDocumentFactory; - } - - public function create( - ProductVariantInterface $productVariant, - ChannelInterface $channel, - LocaleInterface $locale - ): VariantDocument { - $options = []; - foreach ($productVariant->getOptionValues() as $optionValue) { - $options[] = $this->optionDocumentFactory->create($optionValue, $locale); - } - - /** @var ChannelPricingInterface $channelPricing */ - $channelPricing = $productVariant->getChannelPricingForChannel($channel); - - $price = $this->priceDocumentFactory->create( - $channelPricing, - $channel->getBaseCurrency() - ); - - /** @var ProductVariantTranslationInterface $productVariantTranslation */ - $productVariantTranslation = $productVariant->getTranslation($locale->getCode()); - - /** @var VariantDocument $variant */ - $variant = new $this->variantDocumentClass(); - $variant->setId($productVariant->getId()); - $variant->setCode($productVariant->getCode()); - - if (!$productVariantTranslation->getName()) { - $variant->setName($productVariant->getProduct()->getTranslation($locale->getCode())->getName()); - } else { - $variant->setName($productVariantTranslation->getName()); - } - - $variant->setPrice($price); - $variant->setStock($productVariant->getOnHand() - $productVariant->getOnHold()); - $variant->setIsTracked($productVariant->isTracked()); - $variant->setOptions(new Collection($options)); - if ($productVariant->getImages()->count() > 0) { - /** @var ImageDocument[] $images */ - $images = []; - foreach ($productVariant->getImages() as $image) { - $images[] = $this->imageDocumentFactory->create($image); - } - $variant->setImages(new Collection($images)); - } - - return $variant; - } -} diff --git a/src/Factory/Document/VariantDocumentFactoryInterface.php b/src/Factory/Document/VariantDocumentFactoryInterface.php deleted file mode 100644 index c3254f2..0000000 --- a/src/Factory/Document/VariantDocumentFactoryInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -productListViewClass = $productListViewClass; - $this->productViewClass = $productViewClass; - $this->productVariantViewClass = $productVariantViewClass; - $this->attributeViewClass = $attributeViewClass; - $this->imageViewClass = $imageViewClass; - $this->priceViewClass = $priceViewClass; - $this->taxonViewClass = $taxonViewClass; - } - - /** - * {@inheritdoc} - */ - public function createFromSearchResponse(SearchResponse $response): ProductListView - { - $result = $response->getResult(); - $filters = $response->getFilters(); - - /** @var ProductListView $productListView */ - $productListView = new $this->productListViewClass(); - $productListView->filters = $filters; - - $pager = $filters['paginator']->getSerializableData()['pager']; - $productListView->page = $pager['current_page']; - $productListView->total = $pager['total_items']; - $productListView->pages = $pager['num_pages']; - $productListView->limit = $pager['limit']; - - /** @var ProductDocument $product */ - foreach ($result as $product) { - $productListView->items[] = $this->getProductView($product); - } - - return $productListView; - } - - /** - * @param Collection|ImageDocument[] $images - * - * @return ImageView[] - */ - private function getImageViews(Collection $images): array - { - $imageViews = []; - foreach ($images as $image) { - /** @var ImageView $imageView */ - $imageView = new $this->imageViewClass(); - $imageView->code = $image->getCode(); - $imageView->path = $image->getPath(); - - $imageViews[] = $imageView; - } - - return $imageViews; - } - - /** - * @param Collection|TaxonDocument[] $taxons - * @param TaxonDocument|null $mainTaxonDocument - * - * @return TaxonView - */ - private function getTaxonView(Collection $taxons, ?TaxonDocument $mainTaxonDocument): TaxonView - { - /** @var TaxonView $taxonView */ - $taxonView = new $this->taxonViewClass(); - - $taxonView->main = null === $mainTaxonDocument ? null : $mainTaxonDocument->getCode(); - foreach ($taxons as $taxon) { - $taxonView->others[] = $taxon->getCode(); - } - - return $taxonView; - } - - /** - * @param Collection|AttributeDocument[] $attributes - * - * @return AttributeView[] - */ - private function getAttributeViews(Collection $attributes): array - { - $attributeValueViews = []; - foreach ($attributes as $attribute) { - /** @var AttributeView $attributeView */ - $attributeView = new $this->attributeViewClass(); - $attributeView->code = $attribute->getCode(); - $attributeView->value = $attribute->getValue(); - $attributeView->name = $attribute->getName(); - - $attributeValueViews[$attribute->getCode()] = $attributeView; - } - - return $attributeValueViews; - } - - /** - * @param PriceDocument $price - * - * @return PriceView - */ - private function getPriceView(PriceDocument $price): PriceView - { - /** @var PriceView $priceView */ - $priceView = new $this->priceViewClass(); - $priceView->current = $price->getAmount(); - $priceView->currency = $price->getCurrency(); - $priceView->original = $price->getOriginalAmount(); - - return $priceView; - } - - /** - * @param VariantDocument[]|Collection $variants - * - * @return array - */ - private function getVariantViews(Collection $variants): array - { - $variantViews = []; - foreach ($variants as $variant) { - /** @var VariantView $variantView */ - $variantView = new $this->productVariantViewClass(); - $variantView->id = $variant->getId(); - $variantView->price = $this->getPriceView($variant->getPrice()); - $variantView->code = $variant->getCode(); - $variantView->name = $variant->getName(); - $variantView->stock = $variant->getStock(); - $variantView->isTracked = $variant->getIsTracked(); - - if ($variant->getImages()->count() > 0) { - $variantView->images = $this->getImageViews($variant->getImages()); - } - $variantViews[] = $variantView; - } - - return $variantViews; - } - - /** - * @param ProductDocument $product - * - * @return ProductView - */ - private function getProductView(ProductDocument $product): ProductView - { - /** @var ProductView $productView */ - $productView = new $this->productViewClass(); - $productView->id = $product->getId(); - $productView->slug = $product->getSlug(); - $productView->name = $product->getName(); - $productView->code = $product->getCode(); - $productView->rating = $product->getAverageReviewRating(); - $productView->localeCode = $product->getLocaleCode(); - $productView->channelCode = $product->getChannelCode(); - if ($product->getImages()->count() > 0) { - $productView->images = $this->getImageViews($product->getImages()); - } - $productView->taxons = $this->getTaxonView($product->getTaxons(), $product->getMainTaxon()); - $productView->attributes = $this->getAttributeViews($product->getAttributes()); - $productView->variants = $this->getVariantViews($product->getVariants()); - $productView->price = $this->getPriceView($product->getPrice()); - - return $productView; - } -} diff --git a/src/Factory/View/ProductListViewFactoryInterface.php b/src/Factory/View/ProductListViewFactoryInterface.php deleted file mode 100644 index a1f543c..0000000 --- a/src/Factory/View/ProductListViewFactoryInterface.php +++ /dev/null @@ -1,18 +0,0 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Sylius\ElasticSearchPlugin\Filter\Widget; @@ -28,15 +35,8 @@ class InStock extends AbstractRange */ public function getState(Request $request) { - $state = new FilterState(); - $value = $request->get($this->getRequestField()); - - if (isset($value) && $value !== '') { - $value = is_array($value) ? array_values($value) : $value; - $state->setActive(true); - $state->setValue($value); - } - + $state = parent::getState($request); + if (!$state->isActive()) { return $state; } @@ -46,7 +46,6 @@ public function getState(Request $request) $argumentCount = count($values); if ($argumentCount === 0) { $state->setActive(false); - return $state; } @@ -59,7 +58,6 @@ public function getState(Request $request) $normalized[$gt] = $values[0]; } if ($argumentCount === 2) { - $normalized[$gt] = $values[0]; $normalized[$lt] = $values[1]; } @@ -108,4 +106,5 @@ public function getViewData(DocumentIterator $result, ViewData $data) return $data; } + } diff --git a/src/Filter/Widget/MultiDynamicAggregateOverride.php b/src/Filter/Widget/MultiDynamicAggregateOverride.php index 7daeed2..aee4602 100644 --- a/src/Filter/Widget/MultiDynamicAggregateOverride.php +++ b/src/Filter/Widget/MultiDynamicAggregateOverride.php @@ -4,13 +4,13 @@ namespace Sylius\ElasticSearchPlugin\Filter\Widget; +use ONGR\FilterManagerBundle\Filter\Widget\Dynamic\MultiDynamicAggregate; +use ONGR\ElasticsearchDSL\Aggregation\Bucketing\TermsAggregation; use ONGR\ElasticsearchDSL\Aggregation\Bucketing\FilterAggregation; use ONGR\ElasticsearchDSL\Aggregation\Bucketing\NestedAggregation; -use ONGR\ElasticsearchDSL\Aggregation\Bucketing\TermsAggregation; use ONGR\ElasticsearchDSL\Query\MatchAllQuery; use ONGR\ElasticsearchDSL\Search; use ONGR\FilterManagerBundle\Filter\FilterState; -use ONGR\FilterManagerBundle\Filter\Widget\Dynamic\MultiDynamicAggregate; /** * Class MultiDynamicAggregateOverride implements the size option handling in the preProcessSearch method to be able @@ -18,6 +18,8 @@ * to change that globally - only via the query options for the aggregation object. * All other multi dynamic aggregates are extending from this class in the plugin. Size option is implemented in other * types of filters by the FilterManagerBundle + * + * @package Sylius\ElasticSearchPlugin\Filter\Widget */ class MultiDynamicAggregateOverride extends MultiDynamicAggregate { @@ -26,7 +28,7 @@ class MultiDynamicAggregateOverride extends MultiDynamicAggregate */ public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null) { - [$path, $field] = explode('>', $this->getDocumentField()); + list($path, $field) = explode('>', $this->getDocumentField()); $filter = !empty($filter = $relatedSearch->getPostFilters()) ? $filter : new MatchAllQuery(); $aggregation = new NestedAggregation($state->getName(), $path); $nameAggregation = new TermsAggregation('name', $this->getNameField()); diff --git a/src/Filter/Widget/MultiDynamicAggregateWithoutView.php b/src/Filter/Widget/MultiDynamicAggregateWithoutView.php index 22f0211..d4a0a6b 100644 --- a/src/Filter/Widget/MultiDynamicAggregateWithoutView.php +++ b/src/Filter/Widget/MultiDynamicAggregateWithoutView.php @@ -25,4 +25,6 @@ public function getViewData(DocumentIterator $result, ViewData $data): ViewData { return $data; } + + } diff --git a/src/Filter/Widget/OptionMultiDynamicAggregate.php b/src/Filter/Widget/OptionMultiDynamicAggregate.php index d69fc1f..a1d106d 100644 --- a/src/Filter/Widget/OptionMultiDynamicAggregate.php +++ b/src/Filter/Widget/OptionMultiDynamicAggregate.php @@ -10,17 +10,16 @@ use ONGR\ElasticsearchDSL\Aggregation\Bucketing\NestedAggregation; use ONGR\ElasticsearchDSL\Aggregation\Bucketing\TermsAggregation; use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery; -use ONGR\ElasticsearchDSL\Query\Joining\NestedQuery; use ONGR\ElasticsearchDSL\Query\MatchAllQuery; -use ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery; +use ONGR\ElasticsearchDSL\Query\Joining\NestedQuery; use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery; use ONGR\ElasticsearchDSL\Search; use ONGR\FilterManagerBundle\Filter\FilterState; use ONGR\FilterManagerBundle\Filter\ViewData; -use ONGR\FilterManagerBundle\Search\SearchRequest; class OptionMultiDynamicAggregate extends MultiDynamicAggregateOverride { + /** * Fetches buckets from search results. * @@ -45,46 +44,6 @@ protected function fetchAggregation(DocumentIterator $result, $filterName, $valu return $data; } - /** - * {@inheritdoc} - */ - public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null) - { - if ($state && $state->isActive()) { - $search->addPostFilter($this->getFilterQuery($state->getValue())); - } - } - - /** - * Forms $unsortedChoices array with all possible choices. - * 0 is assigned to the document count of the choices. - * - * @param DocumentIterator $result - * @param ViewData $data - * - * @return array - */ - protected function formInitialUnsortedChoices($result, $data) - { - $unsortedChoices = []; - $urlParameters = array_merge( - $data->getResetUrlParameters(), - $data->getState()->getUrlParameters() - ); - - foreach ($result->getAggregation($data->getName())->getAggregation($data->getName())->getAggregation('name') as $nameBucket) { - $groupName = $nameBucket['key']; - - foreach ($nameBucket->getAggregation('value') as $bucket) { - $bucketArray = ['key' => $bucket['key'], 'doc_count' => 0]; - $choice = $this->createChoice($data, $bucket['key'], '', $bucketArray, $urlParameters); - $unsortedChoices[$groupName][$bucket['key']] = $choice; - } - } - - return $unsortedChoices; - } - /** * {@inheritdoc} */ @@ -118,6 +77,12 @@ public function getViewData(DocumentIterator $result, ViewData $data) } } + if ($this->getShowZeroChoices() && !empty($unsortedChoices)) { + foreach ($unsortedChoices as $name => $choices) { + $this->addViewDataItem($data, $name, $unsortedChoices[$name]); + } + } + /** @var ViewData\AggregateViewData $data */ $data->sortItems(); @@ -129,7 +94,7 @@ public function getViewData(DocumentIterator $result, ViewData $data) */ public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null) { - [$parent, $child, $field] = explode('>', $this->getDocumentField()); + list($parent, $child, $field) = explode('>', $this->getDocumentField()); $filter = !empty($filter = $relatedSearch->getPostFilters()) ? $filter : new MatchAllQuery(); $parentAggregation = new NestedAggregation($state->getName(), $parent); $childAggregation = new NestedAggregation($state->getName(), $child); @@ -146,7 +111,7 @@ public function preProcessSearch(Search $search, Search $relatedSearch, FilterSt } if ($this->getOption('size')) { - $valueAggregation->addParameter('size', $this->getOption('size')); + $valueAggregation->addParameter('size',$this->getOption('size')); } if ($state->isActive()) { @@ -184,8 +149,9 @@ public function preProcessSearch(Search $search, Search $relatedSearch, FilterSt */ private function getFilterQuery($terms) { - [$parent, $child, $field] = explode('>', $this->getDocumentField()); + list($parent, $child, $field) = explode('>', $this->getDocumentField()); $boolQuery = new BoolQuery(); + foreach ($terms as $groupName => $values) { $innerBoolQuery = new BoolQuery(); @@ -193,20 +159,15 @@ private function getFilterQuery($terms) $nestedBoolQuery = new BoolQuery(); $nestedBoolQuery->add(new TermQuery($field, $value)); $nestedBoolQuery->add(new TermQuery($this->getNameField(), $groupName)); - - $inStockBoolQuery = new BoolQuery(); - - $inStockBoolQuery->add(new RangeQuery('variants.stock', ['gte' => 1]), BoolQuery::SHOULD); - $inStockBoolQuery->add(new TermQuery('variants.is_tracked', false), BoolQuery::SHOULD); - - $childBoolQuery = new BoolQuery(); - $childBoolQuery->add($inStockBoolQuery, BoolQuery::MUST); - $childBoolQuery->add(new NestedQuery($child, $nestedBoolQuery), BoolQuery::MUST); - - $nestedQuery = new NestedQuery($parent, $childBoolQuery); - $innerBoolQuery->add( - $nestedQuery, + new NestedQuery( + $parent, + + new NestedQuery( + $child, + $nestedBoolQuery + ) + ), BoolQuery::SHOULD ); diff --git a/src/Filter/Widget/Pager.php b/src/Filter/Widget/Pager.php index d8b1730..ab133cd 100644 --- a/src/Filter/Widget/Pager.php +++ b/src/Filter/Widget/Pager.php @@ -40,7 +40,7 @@ public function getState(Request $request): FilterState $state->setUrlParameters([]); $page = (int) $state->getValue(); $state->setValue($page < 1 ? 1 : $page); - $state->addOption('limit', (int) $request->get('limit', (int) $this->getOption('limit', 10))); + $state->addOption('limit', (int) $request->get('limit', 10)); return $state; } diff --git a/src/Filter/Widget/SingleNestedTermChoice.php b/src/Filter/Widget/SingleNestedTermChoice.php deleted file mode 100644 index 9b344a6..0000000 --- a/src/Filter/Widget/SingleNestedTermChoice.php +++ /dev/null @@ -1,35 +0,0 @@ -', $this->getDocumentField()); - - if ($state && $state->isActive()) { - $search->addPostFilter( - new NestedQuery( - $path, - new TermQuery($field, $state->getValue()) - ) - ); - } - } -} diff --git a/src/Filter/Widget/Sort.php b/src/Filter/Widget/Sort.php index 8f8ec6a..cb5ff42 100644 --- a/src/Filter/Widget/Sort.php +++ b/src/Filter/Widget/Sort.php @@ -4,9 +4,10 @@ namespace Sylius\ElasticSearchPlugin\Filter\Widget; -use ONGR\ElasticsearchBundle\Result\DocumentIterator; +use ONGR\ElasticsearchDSL\Query\Joining\NestedQuery; use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery; use ONGR\ElasticsearchDSL\Search; +use ONGR\ElasticsearchBundle\Result\DocumentIterator; use ONGR\ElasticsearchDSL\Sort\FieldSort; use ONGR\FilterManagerBundle\Filter\FilterState; use ONGR\FilterManagerBundle\Filter\Helper\ViewDataFactoryInterface; @@ -114,8 +115,8 @@ private function addAttributeFieldToSort(Search $search, array $settings): void private function addPositionFieldToSort(Search $search, string $identifier, array $settings): void { foreach ($settings as $taxonIdentifier => $sortingOrder) { - $fieldSort = new FieldSort('taxons.position', $sortingOrder, ['nested_path' => 'taxons']); - $fieldSort->setNestedFilter(new TermQuery(sprintf('taxons.%s', $identifier), $taxonIdentifier)); + $fieldSort = new FieldSort('product_taxons.position', $sortingOrder, ['nested_path' => 'product_taxons']); + $fieldSort->setNestedFilter(new TermQuery(sprintf('product_taxons.%s', $identifier), $taxonIdentifier)); $search->addSort($fieldSort); } diff --git a/src/Projection/ProductProjector.php b/src/Projection/ProductProjector.php index 4f70578..5e41726 100644 --- a/src/Projection/ProductProjector.php +++ b/src/Projection/ProductProjector.php @@ -12,9 +12,7 @@ use Sylius\Component\Locale\Model\LocaleInterface; use Sylius\ElasticSearchPlugin\Document\ProductDocument; use Sylius\ElasticSearchPlugin\Event\ProductCreated; -use Sylius\ElasticSearchPlugin\Event\ProductDeleted; -use Sylius\ElasticSearchPlugin\Event\ProductUpdated; -use Sylius\ElasticSearchPlugin\Factory\Document\ProductDocumentFactoryInterface; +use Sylius\ElasticSearchPlugin\Factory\ProductDocumentFactoryInterface; final class ProductProjector { @@ -57,35 +55,6 @@ public function handleProductCreated(ProductCreated $event): void $this->elasticsearchManager->commit(); } - /** - * We create a new product documents with updated data and remove old once - * - * @param ProductUpdated $event - */ - public function handleProductUpdated(ProductUpdated $event): void - { - $product = $event->product(); - - $this->scheduleCreatingNewProductDocuments($product); - $this->scheduleRemovingOldProductDocuments($product); - - $this->elasticsearchManager->commit(); - } - - /** - * We remove deleted product - * - * @param ProductDeleted $event - */ - public function handleProductDeleted(ProductDeleted $event): void - { - $product = $event->product(); - - $this->scheduleRemovingOldProductDocuments($product); - - $this->elasticsearchManager->commit(); - } - private function scheduleCreatingNewProductDocuments(ProductInterface $product): void { /** @var ChannelInterface[] $channels */ @@ -94,13 +63,11 @@ private function scheduleCreatingNewProductDocuments(ProductInterface $product): /** @var LocaleInterface[] $locales */ $locales = $channel->getLocales(); foreach ($locales as $locale) { - $this->elasticsearchManager->persist( - $this->productDocumentFactory->create( - $product, - $locale, - $channel - ) - ); + $this->elasticsearchManager->persist($this->productDocumentFactory->createFromSyliusSimpleProductModel( + $product, + $locale, + $channel + )); } } } diff --git a/src/Resources/config/app/config.yml b/src/Resources/config/app/config.yml index 62127aa..3a93418 100644 --- a/src/Resources/config/app/config.yml +++ b/src/Resources/config/app/config.yml @@ -40,13 +40,13 @@ ongr_filter_manager: request_field: enabled document_field: enabled taxonCode: - type: sylius_elastic_search.choice_nested + type: choice request_field: taxonCode - document_field: taxons>taxons.code + document_field: taxons.code taxonSlug: - type: sylius_elastic_search.choice_nested + type: choice request_field: taxonSlug - document_field: taxons>taxons.slug + document_field: taxons.slug priceRange: type: range request_field: price @@ -68,7 +68,7 @@ ongr_filter_manager: document_field: ~ request_field: page options: - limit: 9 + limit: 10 max_pages: 20 attributes: type: sylius_elastic_search.multi_dynamic_aggregate @@ -113,4 +113,3 @@ ongr_filter_manager: slug: slug code: code price: price.amount - date: created_at diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index ec4ce9a..7b98263 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -4,7 +4,6 @@ - @@ -15,15 +14,24 @@ + + %sylius_elastic_search.document.product.class% + %sylius_elastic_search.document.attribute.class% + %sylius_elastic_search.document.image.class% + %sylius_elastic_search.document.price.class% + %sylius_elastic_search.document.product_taxon.class% + %sylius_elastic_search.document.taxon.class% + %sylius_elastic_search.document.variant.class% + %sylius_elastic_search.document.option.class% + %sylius_elastic_search.attribute_whitelist% + - - - + %sylius_elastic_search.view.product_list.class% %sylius_elastic_search.view.product.class% %sylius_elastic_search.view.product_variant.class% @@ -56,9 +64,5 @@ - - - - diff --git a/src/Resources/config/services/factories.xml b/src/Resources/config/services/factories.xml deleted file mode 100644 index e1d0f21..0000000 --- a/src/Resources/config/services/factories.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - %sylius_elastic_search.document.product.class% - - - - - - %sylius_elastic_search.attribute_whitelist% - - - - %sylius_elastic_search.document.taxon.class% - - - - - %sylius_elastic_search.document.attribute.class% - - - - %sylius_elastic_search.document.price.class% - - - - %sylius_elastic_search.document.image.class% - - - - %sylius_elastic_search.document.option.class% - - - - %sylius_elastic_search.document.variant.class% - - - - - - - diff --git a/src/SyliusElasticSearchPlugin.php b/src/SyliusElasticSearchPlugin.php index 959317c..26f63d5 100644 --- a/src/SyliusElasticSearchPlugin.php +++ b/src/SyliusElasticSearchPlugin.php @@ -5,6 +5,8 @@ namespace Sylius\ElasticSearchPlugin; use Sylius\Bundle\CoreBundle\Application\SyliusPluginTrait; +use Sylius\ElasticSearchPlugin\DependencyInjection\Compiler\RegisterFilterTypePass; +use Sylius\ElasticSearchPlugin\DependencyInjection\Compiler\RegisterSearchCriteriaApplicatorPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/tests/Application/app/AppKernel.php b/tests/Application/app/AppKernel.php index b2ae53c..5e28a17 100644 --- a/tests/Application/app/AppKernel.php +++ b/tests/Application/app/AppKernel.php @@ -1,7 +1,5 @@ load($this->getRootDir() . '/config/config_' . $this->getEnvironment() . '.yml'); } - - /** - * {@inheritdoc} - */ - public function getCacheDir(): string - { - return sprintf('%s/%s/cache', sys_get_temp_dir(), md5(__DIR__)); - } - - /** - * {@inheritdoc} - */ - public function getLogDir(): string - { - return sprintf('%s/%s/logs', sys_get_temp_dir(), md5(__DIR__)); - } } diff --git a/tests/Application/app/config/config.yml b/tests/Application/app/config/config.yml index 3d664a6..406df07 100644 --- a/tests/Application/app/config/config.yml +++ b/tests/Application/app/config/config.yml @@ -31,7 +31,7 @@ framework: doctrine: dbal: driver: "pdo_sqlite" - path: "%kernel.root_dir%/../var/db.sql" + path: "%kernel.cache_dir%/db.sql" charset: UTF8 fos_rest: diff --git a/tests/Application/bin/console b/tests/Application/bin/console index 7a7836d..a908aaa 100755 --- a/tests/Application/bin/console +++ b/tests/Application/bin/console @@ -12,7 +12,8 @@ use Symfony\Component\Debug\Debug; set_time_limit(0); -require __DIR__ . '/../../../vendor/autoload.php'; +/** @var Composer\Autoload\ClassLoader $loader */ +$loader = require __DIR__.'/../app/autoload.php'; $input = new ArgvInput(); $env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); diff --git a/tests/Application/var/.gitkeep b/tests/Application/var/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/DataFixtures/ORM/shop.yml b/tests/DataFixtures/ORM/shop.yml index dfd099f..175d5c5 100644 --- a/tests/DataFixtures/ORM/shop.yml +++ b/tests/DataFixtures/ORM/shop.yml @@ -106,44 +106,6 @@ Sylius\Component\Product\Model\ProductAttributeTranslation: name: "Available from" translatable: "@available_from" -Sylius\Component\Product\Model\ProductAttribute: - mug_collection: - fallbackLocale: "en_GB" - currentLocale: "en_GB" - code: "MUG_COLLECTION_CODE" - type: "text" - storage_type: "text" - translations: - - "@mug_collection_en_gb_translation" - - "@mug_collection_de_de_translation" - mug_material: - fallbackLocale: "en_GB" - currentLocale: "en_GB" - code: "MUG_MATERIAL_CODE" - type: "text" - storage_type: "text" - translations: - - "@mug_material_en_gb_translation" - - "@mug_material_de_de_translation" - production_year: - fallbackLocale: "en_GB" - currentLocale: "en_GB" - code: "PRODUCTION_YEAR" - type: "text" - storage_type: "text" - translations: - - "@production_year_en_gb_translation" - - "@production_year_de_de_translation" - available_from: - fallbackLocale: "en_GB" - currentLocale: "en_GB" - code: "AVAILABLE_FROM" - type: "date" - storage_type: "date" - translations: - - "@available_from_en_gb_translation" - - "@available_from_de_de_translation" - Sylius\Component\Product\Model\ProductAttributeValue: en_gb_mug_holiday_collection_value: subject: "@mug" @@ -185,16 +147,6 @@ Sylius\Component\Product\Model\ProductAttributeValue: attribute: "@production_year" localeCode: "de_DE" text: "2020" - en_gb_hat_holiday_collection_value: - subject: "@hat" - attribute: "@mug_collection" - localeCode: "en_GB" - text: "HOLIDAY COLLECTION" - de_de_hat_holiday_collection_value: - subject: "@hat" - attribute: "@mug_collection" - localeCode: "de_DE" - text: "FEIERTAGSKOLLEKTION" en_gb_production_year_value_hat: subject: "@hat" attribute: "@production_year" @@ -216,6 +168,44 @@ Sylius\Component\Product\Model\ProductAttributeValue: localeCode: "de_DE" date: "<(new \\DateTime('2010-01-01 00:00:00', new \\DateTimeZone('UTC')))>" +Sylius\Component\Product\Model\ProductAttribute: + mug_collection: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "MUG_COLLECTION_CODE" + type: "text" + storage_type: "text" + translations: + - "@mug_collection_en_gb_translation" + - "@mug_collection_de_de_translation" + mug_material: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "MUG_MATERIAL_CODE" + type: "text" + storage_type: "text" + translations: + - "@mug_material_en_gb_translation" + - "@mug_material_de_de_translation" + production_year: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "PRODUCTION_YEAR" + type: "text" + storage_type: "text" + translations: + - "@production_year_en_gb_translation" + - "@production_year_de_de_translation" + available_from: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "AVAILABLE_FROM" + type: "date" + storage_type: "date" + translations: + - "@available_from_en_gb_translation" + - "@available_from_de_de_translation" + Sylius\Component\Core\Model\Product: mug: code: "LOGAN_MUG_CODE" @@ -245,8 +235,8 @@ Sylius\Component\Core\Model\Product: attributes: - "@en_gb_production_year_value_hat" - "@de_de_production_year_value_hat" - - "@en_gb_hat_holiday_collection_value" - - "@de_de_hat_holiday_collection_value" + - "@en_gb_mug_holiday_collection_value" + - "@de_de_mug_holiday_collection_value" - "@en_gb_available_from_value_hat" - "@de_de_available_from_value_hat" variants: ["@hat_variant"] @@ -305,52 +295,6 @@ Sylius\Component\Core\Model\ChannelPricing: channelCode: "WEB_GB" price: 1500 -Sylius\Component\Product\Model\ProductVariantTranslation: - en_gb_mug_variant_big_translation: - locale: "en_GB" - name: "Logan Mug" - translatable: "@mug_variant_big" - de_de_mug_variant_big_translation: - locale: "de_DE" - name: "Logan Becher" - translatable: "@mug_variant_big" - en_gb_mug_variant_small_translation: - locale: "en_GB" - name: "Gnome Mug" - translatable: "@mug_variant_small" - de_de_mug_variant_small_translation: - locale: "de_DE" - name: "Gnome Becher" - translatable: "@mug_variant_small" - en_gb_hat_variant_translation: - locale: "en_GB" - name: "Logan Hat" - translatable: "@hat_variant" - de_de_hat_variant_translation: - locale: "de_DE" - name: "Logan Hut" - translatable: "@hat_variant" - small_t_shirt_translation: - locale: "en_GB" - name: "Small Logan T-Shirt" - translatable: "@t_shirt_small" - medium_t_shirt_translation: - locale: "en_GB" - name: "Medium Logan T-Shirt" - translatable: "@t_shirt_medium" - large_t_shirt_translation: - locale: "en_GB" - name: "Large Logan T-Shirt" - translatable: "@t_shirt_large" - extra_large_t_shirt_translation: - locale: "en_GB" - name: "Extra Large Logan T-Shirt" - translatable: "@t_shirt_extra_large" - small_disabled_t_shirt_translation: - locale: "en_GB" - name: "Small Disabled T-Shirt" - translatable: "@disabled_t_shirt_small" - Sylius\Component\Core\Model\ProductVariant: mug_variant_big: code: "LOGAN_MUG_BIG_CODE" @@ -462,66 +406,112 @@ Sylius\Component\Core\Model\ProductVariant: channelPricings: - "@gb_small_disabled_t_shirt_web_channel_pricing" +Sylius\Component\Product\Model\ProductVariantTranslation: + en_gb_mug_variant_big_translation: + locale: "en_GB" + name: "Logan Mug" + translatable: "@mug_variant_big" + de_de_mug_variant_big_translation: + locale: "de_DE" + name: "Logan Becher" + translatable: "@mug_variant_big" + en_gb_mug_variant_small_translation: + locale: "en_GB" + name: "Gnome Mug" + translatable: "@mug_variant_small" + de_de_mug_variant_small_translation: + locale: "de_DE" + name: "Gnome Becher" + translatable: "@mug_variant_small" + en_gb_hat_variant_translation: + locale: "en_GB" + name: "Logan Hat" + translatable: "@hat_variant" + de_de_hat_variant_translation: + locale: "de_DE" + name: "Logan Hut" + translatable: "@hat_variant" + small_t_shirt_translation: + locale: "en_GB" + name: "Small Logan T-Shirt" + translatable: "@t_shirt_small" + medium_t_shirt_translation: + locale: "en_GB" + name: "Medium Logan T-Shirt" + translatable: "@t_shirt_medium" + large_t_shirt_translation: + locale: "en_GB" + name: "Large Logan T-Shirt" + translatable: "@t_shirt_large" + extra_large_t_shirt_translation: + locale: "en_GB" + name: "Extra Large Logan T-Shirt" + translatable: "@t_shirt_extra_large" + small_disabled_t_shirt_translation: + locale: "en_GB" + name: "Small Disabled T-Shirt" + translatable: "@disabled_t_shirt_small" + Sylius\Component\Taxonomy\Model\TaxonTranslation: en_gb_category_translation: slug: "categories" locale: "en_GB" name: "Categories" - description: 'Lorem ipsum' + description: translatable: "@category_taxon" en_gb_mug_taxon_translation: slug: "categories/mugs" locale: "en_GB" name: "Mugs" - description: 'Lorem ipsum' + description: translatable: "@mug_taxon" en_gb_t_shirt_taxon_translation: slug: "categories/t-shirts" locale: "en_GB" name: "T-Shirts" - description: 'Lorem ipsum' + description: translatable: "@t_shirt_taxon" en_gb_brand_translation: slug: "brands" locale: "en_GB" name: "Brands" - description: 'Lorem ipsum' + description: translatable: "@brand_taxon" en_gb_hat_taxon_translation: slug: "categories/hats" locale: "en_GB" name: "Hats" - description: 'Lorem ipsum' + description: translatable: "@hat_taxon" de_de_category_translation: slug: "kategorien" locale: "de_DE" name: "Kategorien" - description: 'Lorem ipsum' + description: translatable: "@category_taxon" de_de_mug_taxon_translation: slug: "kategorien/1tassen" locale: "de_DE" name: "Tassen" - description: 'Lorem ipsum' + description: translatable: "@mug_taxon" de_de_t_shirt_taxon_translation: slug: "kategorien/1t-shirts" locale: "de_DE" name: "T-Shirts" - description: 'Lorem ipsum' + description: translatable: "@t_shirt_taxon" de_de_brand_translation: slug: "marken" locale: "de_DE" name: "Marken" - description: 'Lorem ipsum' + description: translatable: "@brand_taxon" de_de_hat_taxon_translation: slug: "kategorien/hut" locale: "de_DE" name: "Hut" - description: 'Lorem ipsum' + description: translatable: "@hat_taxon" Sylius\Component\Core\Model\Taxon: diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index d34e812..f063e0e 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -1,6 +1,5 @@ AttributeDocument::class, 'image' => ImageDocument::class, 'price' => PriceDocument::class, + 'product_taxon' => ProductTaxonDocument::class, 'taxon' => TaxonDocument::class, 'variant' => VariantDocument::class, 'option' => OptionDocument::class, diff --git a/tests/DependencyInjection/SyliusElasticSearchExtensionTest.php b/tests/DependencyInjection/SyliusElasticSearchExtensionTest.php index e95c07d..0cb3498 100644 --- a/tests/DependencyInjection/SyliusElasticSearchExtensionTest.php +++ b/tests/DependencyInjection/SyliusElasticSearchExtensionTest.php @@ -15,11 +15,10 @@ use Sylius\ElasticSearchPlugin\DependencyInjection\SyliusElasticSearchExtension; use Sylius\ElasticSearchPlugin\Document\AttributeDocument; use Sylius\ElasticSearchPlugin\Document\ImageDocument; -use Sylius\ElasticSearchPlugin\Document\OptionDocument; use Sylius\ElasticSearchPlugin\Document\PriceDocument; use Sylius\ElasticSearchPlugin\Document\ProductDocument; +use Sylius\ElasticSearchPlugin\Document\ProductTaxonDocument; use Sylius\ElasticSearchPlugin\Document\TaxonDocument; -use Sylius\ElasticSearchPlugin\Document\VariantDocument; final class SyliusElasticSearchExtensionTest extends AbstractExtensionTestCase { @@ -42,9 +41,8 @@ public function it_defines_document_classes_parameters() $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.attribute.class', AttributeDocument::class); $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.image.class', ImageDocument::class); $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.price.class', PriceDocument::class); + $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.product_taxon.class', ProductTaxonDocument::class); $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.taxon.class', TaxonDocument::class); - $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.variant.class', VariantDocument::class); - $this->assertContainerBuilderHasParameter('sylius_elastic_search.document.option.class', OptionDocument::class); } /** diff --git a/tests/Event/ProductCreatedTest.php b/tests/Event/ProductCreatedTest.php index fe578a4..65246e8 100644 --- a/tests/Event/ProductCreatedTest.php +++ b/tests/Event/ProductCreatedTest.php @@ -1,7 +1,5 @@ prophesize(ProductInterface::class); diff --git a/tests/Factory/ProductDocumentFactoryTest.php b/tests/Factory/ProductDocumentFactoryTest.php index 28c93fa..a40e749 100644 --- a/tests/Factory/ProductDocumentFactoryTest.php +++ b/tests/Factory/ProductDocumentFactoryTest.php @@ -1,122 +1,150 @@ productRepository = static::$kernel->getContainer()->get('doctrine.orm.entity_manager')->getRepository( - Product::class - ) - ; - $this->localeRepository = static::$kernel->getContainer()->get('doctrine.orm.entity_manager')->getRepository( - Locale::class - ) - ; - $this->channelRepository = static::$kernel->getContainer()->get('doctrine.orm.entity_manager')->getRepository( - Channel::class - ) - ; - } +use Sylius\ElasticSearchPlugin\Exception\UnsupportedFactoryMethodException; +use Sylius\ElasticSearchPlugin\Factory\ProductDocumentFactory; +final class ProductDocumentFactoryTest extends \PHPUnit_Framework_TestCase +{ /** * @test */ public function it_creates_product_document_from_sylius_product_model() { - /** @var ChannelInterface $syliusChannel */ - $syliusChannel = $this->channelRepository->findOneByCode('WEB_GB'); - /** @var Locale $syliusLocale */ - $syliusLocale = $this->localeRepository->findOneBy(['code' => 'en_GB']); $createdAt = \DateTime::createFromFormat(\DateTime::W3C, '2017-04-18T16:12:55+02:00'); - - /** @var Product $syliusProduct */ - $syliusProduct = $this->productRepository->findOneByChannelAndSlug( - $syliusChannel, - $syliusLocale->getCode(), - 'logan-mug' - ); + $syliusProductAttributeValue = new ProductAttributeValue(); + $syliusProductAttribute = new ProductAttribute(); + $syliusProductAttribute->setCurrentLocale('en_US'); + $syliusProductAttribute->setCode('color'); + $syliusProductAttribute->setName('Color'); + $syliusProductAttributeValue->setLocaleCode('en_US'); + $syliusProductAttribute->setType(TextAttributeType::TYPE); + $syliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $syliusProductAttributeValue->setAttribute($syliusProductAttribute); + $syliusProductAttributeValue->setValue('red'); + + $syliusTaxon = new Taxon(); + $syliusTaxon->setCurrentLocale('en_US'); + $syliusTaxon->setCode('TREE'); + $syliusTaxon->setSlug('tree'); + $syliusTaxon->setDescription('Lorem ipsum'); + $syliusTaxon->setPosition(0); + + $syliusProductTaxon = new ProductTaxon(); + $syliusProductTaxon->setPosition(1); + + $syliusLocale = new Locale(); + $syliusLocale->setCode('en_US'); + + $syliusProductVariant = new ProductVariant(); + $syliusProductVariant->setCode('red_banana'); + $syliusProductVariant->setPosition(1); + + $syliusProduct = new Product(); + $channelPrice = new ChannelPricing(); + $syliusChannel = new Channel(); + $currency = new Currency(); + $currency->setCode('USD'); + + $syliusProductTaxon->setProduct($syliusProduct); + $syliusProductTaxon->setTaxon($syliusTaxon); + $syliusProductTaxon->setPosition(1); + $channelPrice->setPrice(1000); + $channelPrice->setChannelCode('mobile'); + + $syliusChannel->setCode('mobile'); + $syliusChannel->setDefaultLocale($syliusLocale); + $syliusChannel->addLocale($syliusLocale); + $syliusChannel->addCurrency($currency); + $syliusChannel->setBaseCurrency($currency); + + $syliusProductVariant->addChannelPricing($channelPrice); + $syliusProduct->addVariant($syliusProductVariant); + $syliusProduct->addChannel($syliusChannel); + $syliusProduct->setMainTaxon($syliusTaxon); + $syliusProduct->addProductTaxon($syliusProductTaxon); $syliusProduct->setCreatedAt($createdAt); + $syliusProduct->setCurrentLocale('en_US'); + $syliusProduct->setName('Banana'); + $syliusProduct->setSlug('/banana'); + $syliusProduct->setDescription('Lorem ipsum'); + $syliusProduct->setCode('banana'); + $syliusProduct->addAttribute($syliusProductAttributeValue); $factory = new ProductDocumentFactory( ProductDocument::class, - new AttributeDocumentFactory(AttributeDocument::class), - new ImageDocumentFactory(ImageDocument::class), - new PriceDocumentFactory(PriceDocument::class), - new TaxonDocumentFactory(TaxonDocument::class, new ImageDocumentFactory(ImageDocument::class)), - new VariantDocumentFactory( - VariantDocument::class, - new PriceDocumentFactory(PriceDocument::class), - new ImageDocumentFactory(ImageDocument::class), - new OptionDocumentFactory(OptionDocument::class) - ), - ['MUG_COLLECTION_CODE', 'MUG_MATERIAL_CODE', 'PRODUCTION_YEAR'] + AttributeDocument::class, + ImageDocument::class, + PriceDocument::class, + ProductTaxonDocument::class, + TaxonDocument::class, + VariantDocument::class, + OptionDocument::class, + ['color'] ); /** @var ProductDocument $product */ - $product = $factory->create( + $product = $factory->createFromSyliusSimpleProductModel( $syliusProduct, $syliusLocale, $syliusChannel ); - $taxon = $this->makeMainTaxon(); + $taxon = new TaxonDocument(); + $taxon->setCode('TREE'); + $taxon->setPosition(0); + $taxon->setSlug('tree'); + $taxon->setDescription('Lorem ipsum'); - $productTaxons = $this->makeProductTaxons(); + $productTaxon = new ProductTaxonDocument(); + $productTaxon->setCode('TREE'); + $productTaxon->setSlug('tree'); + $productTaxon->setPosition(1); - $productAttributes = $this->makeProductAttributes(); + $productAttribute = new AttributeDocument(); + $productAttribute->setCode('color'); + $productAttribute->setName('Color'); + $productAttribute->setValue('red'); - $this->assertEquals($product->getCode(), $product->getCode()); - $this->assertEquals($product->getName(), $product->getName()); - $this->assertEquals('en_GB', $product->getLocaleCode()); - $this->assertEquals(new Collection($productAttributes), $product->getAttributes()); + $this->assertEquals('banana', $product->getCode()); + $this->assertEquals('Banana', $product->getName()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals( + new Collection([ + $productAttribute + ]), + $product->getAttributes() + ); $this->assertEquals(1000, $product->getPrice()->getAmount()); - $this->assertEquals('GBP', $product->getPrice()->getCurrency()); - $this->assertEquals('en_GB', $product->getLocaleCode()); - $this->assertEquals('WEB_GB', $product->getChannelCode()); - $this->assertEquals('logan-mug', $product->getSlug()); - $this->assertEquals('Logan Mug', $product->getName()); + $this->assertEquals('USD', $product->getPrice()->getCurrency()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals('mobile', $product->getChannelCode()); + $this->assertEquals('/banana', $product->getSlug()); + $this->assertEquals('Banana', $product->getName()); $this->assertEquals($createdAt, $product->getCreatedAt()); - $this->assertEquals('Logan Mug', $product->getDescription()); + $this->assertEquals('Lorem ipsum', $product->getDescription()); $this->assertEquals($taxon, $product->getMainTaxon()); - $this->assertEquals(new Collection($productTaxons), $product->getTaxons()); + $this->assertEquals(new Collection([$productTaxon]), $product->getProductTaxons()); $this->assertEquals(0.0, $product->getAverageReviewRating()); } @@ -125,134 +153,289 @@ public function it_creates_product_document_from_sylius_product_model() */ public function it_creates_product_document_only_with_whitelisted_attributes() { - /** @var ChannelInterface $syliusChannel */ - $syliusChannel = $this->channelRepository->findOneByCode('WEB_GB'); - /** @var Locale $syliusLocale */ - $syliusLocale = $this->localeRepository->findOneBy(['code' => 'en_GB']); $createdAt = \DateTime::createFromFormat(\DateTime::W3C, '2017-04-18T16:12:55+02:00'); - - /** @var Product $syliusProduct */ - $syliusProduct = $this->productRepository->findOneByChannelAndSlug( - $syliusChannel, - $syliusLocale->getCode(), - 'logan-mug' - ); + $firstSyliusProductAttributeValue = new ProductAttributeValue(); + $firstSyliusProductAttribute = new ProductAttribute(); + $firstSyliusProductAttribute->setCurrentLocale('en_US'); + $firstSyliusProductAttribute->setCode('material'); + $firstSyliusProductAttribute->setName('Material'); + $firstSyliusProductAttributeValue->setLocaleCode('en_US'); + $firstSyliusProductAttribute->setType(TextAttributeType::TYPE); + $firstSyliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $firstSyliusProductAttributeValue->setAttribute($firstSyliusProductAttribute); + $firstSyliusProductAttributeValue->setValue('wood'); + + $secondSyliusProductAttributeValue = new ProductAttributeValue(); + $secondSyliusProductAttribute = new ProductAttribute(); + $secondSyliusProductAttribute->setCurrentLocale('en_US'); + $secondSyliusProductAttribute->setCode('size'); + $secondSyliusProductAttribute->setName('Size'); + $secondSyliusProductAttributeValue->setLocaleCode('en_US'); + $secondSyliusProductAttribute->setType(TextAttributeType::TYPE); + $secondSyliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $secondSyliusProductAttributeValue->setAttribute($secondSyliusProductAttribute); + $secondSyliusProductAttributeValue->setValue('M'); + + $syliusTaxon = new Taxon(); + $syliusTaxon->setCurrentLocale('en_US'); + $syliusTaxon->setCode('TREE'); + $syliusTaxon->setSlug('tree'); + $syliusTaxon->setDescription('Lorem ipsum'); + $syliusTaxon->setPosition(0); + + $syliusProductTaxon = new ProductTaxon(); + $syliusProductTaxon->setPosition(1); + + $syliusLocale = new Locale(); + $syliusLocale->setCode('en_US'); + + $syliusProductVariant = new ProductVariant(); + $syliusProductVariant->setCode('red_banana'); + $syliusProductVariant->setPosition(1); + + $syliusProduct = new Product(); + $channelPrice = new ChannelPricing(); + $syliusChannel = new Channel(); + $currency = new Currency(); + $currency->setCode('USD'); + + $syliusProductTaxon->setProduct($syliusProduct); + $syliusProductTaxon->setTaxon($syliusTaxon); + $syliusProductTaxon->setPosition(1); + $channelPrice->setPrice(1000); + $channelPrice->setChannelCode('mobile'); + + $syliusChannel->setCode('mobile'); + $syliusChannel->setDefaultLocale($syliusLocale); + $syliusChannel->addLocale($syliusLocale); + $syliusChannel->addCurrency($currency); + $syliusChannel->setBaseCurrency($currency); + + $syliusProductVariant->addChannelPricing($channelPrice); + $syliusProduct->addVariant($syliusProductVariant); + $syliusProduct->addChannel($syliusChannel); + $syliusProduct->setMainTaxon($syliusTaxon); + $syliusProduct->addProductTaxon($syliusProductTaxon); $syliusProduct->setCreatedAt($createdAt); + $syliusProduct->setCurrentLocale('en_US'); + $syliusProduct->setName('Banana'); + $syliusProduct->setSlug('/banana'); + $syliusProduct->setDescription('Lorem ipsum'); + $syliusProduct->setCode('banana'); + $syliusProduct->addAttribute($firstSyliusProductAttributeValue); + $syliusProduct->addAttribute($secondSyliusProductAttributeValue); $factory = new ProductDocumentFactory( ProductDocument::class, - new AttributeDocumentFactory(AttributeDocument::class), - new ImageDocumentFactory(ImageDocument::class), - new PriceDocumentFactory(PriceDocument::class), - new TaxonDocumentFactory(TaxonDocument::class, new ImageDocumentFactory(ImageDocument::class)), - new VariantDocumentFactory( - VariantDocument::class, - new PriceDocumentFactory(PriceDocument::class), - new ImageDocumentFactory(ImageDocument::class), - new OptionDocumentFactory(OptionDocument::class) - ), - ['PRODUCTION_YEAR'] + AttributeDocument::class, + ImageDocument::class, + PriceDocument::class, + ProductTaxonDocument::class, + TaxonDocument::class, + VariantDocument::class, + OptionDocument::class, + ['material'] ); /** @var ProductDocument $product */ - $product = $factory->create( + $product = $factory->createFromSyliusSimpleProductModel( $syliusProduct, $syliusLocale, $syliusChannel ); - $taxon = $this->makeMainTaxon(); + $taxon = new TaxonDocument(); + $taxon->setCode('TREE'); + $taxon->setPosition(0); + $taxon->setSlug('tree'); + $taxon->setDescription('Lorem ipsum'); + + $productTaxon = new ProductTaxonDocument(); + $productTaxon->setCode('TREE'); + $productTaxon->setSlug('tree'); + $productTaxon->setPosition(1); - $productTaxons = $this->makeProductTaxons(); + $firstProductAttribute = new AttributeDocument(); + $firstProductAttribute->setCode('material'); + $firstProductAttribute->setName('Material'); + $firstProductAttribute->setValue('wood'); - $productAttribute = $this->makeProductionYearAttribute(); + $secondProductAttribute = new AttributeDocument(); + $secondProductAttribute->setCode('size'); + $secondProductAttribute->setName('Size'); + $secondProductAttribute->setValue('M'); - $this->assertEquals($product->getCode(), $product->getCode()); - $this->assertEquals($product->getName(), $product->getName()); - $this->assertEquals('en_GB', $product->getLocaleCode()); + $this->assertEquals('banana', $product->getCode()); + $this->assertEquals('Banana', $product->getName()); + $this->assertEquals('en_US', $product->getLocaleCode()); $this->assertEquals( - new Collection([$productAttribute]), + new Collection([ + $firstProductAttribute, + ]), $product->getAttributes() ); + $this->assertEquals(1000, $product->getPrice()->getAmount()); - $this->assertEquals('GBP', $product->getPrice()->getCurrency()); - $this->assertEquals('en_GB', $product->getLocaleCode()); - $this->assertEquals('WEB_GB', $product->getChannelCode()); - $this->assertEquals('logan-mug', $product->getSlug()); - $this->assertEquals('Logan Mug', $product->getName()); + $this->assertEquals('USD', $product->getPrice()->getCurrency()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals('mobile', $product->getChannelCode()); + $this->assertEquals('/banana', $product->getSlug()); + $this->assertEquals('Banana', $product->getName()); $this->assertEquals($createdAt, $product->getCreatedAt()); - $this->assertEquals('Logan Mug', $product->getDescription()); + $this->assertEquals('Lorem ipsum', $product->getDescription()); $this->assertEquals($taxon, $product->getMainTaxon()); - $this->assertEquals(new Collection($productTaxons), $product->getTaxons()); + $this->assertEquals(new Collection([$taxon]), $product->getTaxons()); + $this->assertEquals(new Collection([$productTaxon]), $product->getProductTaxons()); $this->assertEquals(0.0, $product->getAverageReviewRating()); } /** - * @return TaxonDocument + * @test */ - private function makeMainTaxon(): TaxonDocument + public function it_creates_product_document_with_all_taxon_parents() { + $createdAt = \DateTime::createFromFormat(\DateTime::W3C, '2017-04-18T16:12:55+02:00'); + $firstSyliusProductAttributeValue = new ProductAttributeValue(); + $firstSyliusProductAttribute = new ProductAttribute(); + $firstSyliusProductAttribute->setCurrentLocale('en_US'); + $firstSyliusProductAttribute->setCode('material'); + $firstSyliusProductAttribute->setName('Material'); + $firstSyliusProductAttributeValue->setLocaleCode('en_US'); + $firstSyliusProductAttribute->setType(TextAttributeType::TYPE); + $firstSyliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $firstSyliusProductAttributeValue->setAttribute($firstSyliusProductAttribute); + $firstSyliusProductAttributeValue->setValue('wood'); + + $secondSyliusProductAttributeValue = new ProductAttributeValue(); + $secondSyliusProductAttribute = new ProductAttribute(); + $secondSyliusProductAttribute->setCurrentLocale('en_US'); + $secondSyliusProductAttribute->setCode('size'); + $secondSyliusProductAttribute->setName('Size'); + $secondSyliusProductAttributeValue->setLocaleCode('en_US'); + $secondSyliusProductAttribute->setType(TextAttributeType::TYPE); + $secondSyliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $secondSyliusProductAttributeValue->setAttribute($secondSyliusProductAttribute); + $secondSyliusProductAttributeValue->setValue('M'); + + $syliusParentTaxon = new Taxon(); + $syliusParentTaxon->setCurrentLocale('en_US'); + $syliusParentTaxon->setCode('ROOT'); + $syliusParentTaxon->setSlug('root'); + $syliusParentTaxon->setDescription('Lorem ipsum'); + $syliusParentTaxon->setPosition(0); + + $syliusTaxon = new Taxon(); + $syliusTaxon->setCurrentLocale('en_US'); + $syliusTaxon->setCode('TREE'); + $syliusTaxon->setSlug('tree'); + $syliusTaxon->setDescription('Lorem ipsum'); + $syliusTaxon->setParent($syliusParentTaxon); + $syliusTaxon->setPosition(0); + + $syliusLocale = new Locale(); + $syliusLocale->setCode('en_US'); + + $syliusProductVariant = new ProductVariant(); + $syliusProductVariant->setCode('red_banana'); + $syliusProductVariant->setPosition(1); + + $syliusProduct = new Product(); + $channelPrice = new ChannelPricing(); + $syliusChannel = new Channel(); + $currency = new Currency(); + $currency->setCode('USD'); + + $syliusProductTaxon = new ProductTaxon(); + $syliusProductTaxon->setProduct($syliusProduct); + $syliusProductTaxon->setTaxon($syliusTaxon); + $syliusProductTaxon->setPosition(1); + $channelPrice->setPrice(1000); + $channelPrice->setChannelCode('mobile'); + + $syliusChannel->setCode('mobile'); + $syliusChannel->setDefaultLocale($syliusLocale); + $syliusChannel->addLocale($syliusLocale); + $syliusChannel->addCurrency($currency); + $syliusChannel->setBaseCurrency($currency); + + $syliusProductVariant->addChannelPricing($channelPrice); + $syliusProduct->addVariant($syliusProductVariant); + $syliusProduct->addChannel($syliusChannel); + $syliusProduct->setMainTaxon($syliusTaxon); + $syliusProduct->addProductTaxon($syliusProductTaxon); + $syliusProduct->setCreatedAt($createdAt); + $syliusProduct->setCurrentLocale('en_US'); + $syliusProduct->setName('Banana'); + $syliusProduct->setSlug('/banana'); + $syliusProduct->setDescription('Lorem ipsum'); + $syliusProduct->setCode('banana'); + $syliusProduct->addAttribute($firstSyliusProductAttributeValue); + $syliusProduct->addAttribute($secondSyliusProductAttributeValue); + + $factory = new ProductDocumentFactory( + ProductDocument::class, + AttributeDocument::class, + ImageDocument::class, + PriceDocument::class, + ProductTaxonDocument::class, + TaxonDocument::class, + VariantDocument::class, + OptionDocument::class, + ['material'] + ); + /** @var ProductDocument $product */ + $product = $factory->createFromSyliusSimpleProductModel( + $syliusProduct, + $syliusLocale, + $syliusChannel + ); + $taxon = new TaxonDocument(); - $taxon->setCode('MUG'); + $taxon->setCode('TREE'); $taxon->setPosition(0); - $taxon->setSlug('categories/mugs'); + $taxon->setSlug('tree'); $taxon->setDescription('Lorem ipsum'); - return $taxon; - } - - /** - * @return array - */ - private function makeProductTaxons(): array - { - $productTaxons = []; - $productTaxon = new TaxonDocument(); - $productTaxon->setCode('MUG'); - $productTaxon->setSlug('categories/mugs'); - $productTaxon->setPosition(0); - $productTaxon->setDescription('Lorem ipsum'); - $productTaxons[] = $productTaxon; - $productTaxon = new TaxonDocument(); - $productTaxon->setCode('BRAND'); - $productTaxon->setSlug('brands'); - $productTaxon->setPosition(3); - $productTaxon->setDescription('Lorem ipsum'); - $productTaxons[] = $productTaxon; - - return $productTaxons; - } - - /** - * @return AttributeDocument - */ - private function makeProductionYearAttribute(): AttributeDocument - { - $productAttribute = new AttributeDocument(); - $productAttribute->setCode('PRODUCTION_YEAR'); - $productAttribute->setName('Production year'); - $productAttribute->setValue('2015'); - - return $productAttribute; - } - - private function makeProductAttributes(): array - { - $productAttributes = []; - - $productAttribute = new AttributeDocument(); - $productAttribute->setCode('MUG_COLLECTION_CODE'); - $productAttribute->setName('Mug collection'); - $productAttribute->setValue('HOLIDAY COLLECTION'); - $productAttributes[] = $productAttribute; - - $productAttribute = new AttributeDocument(); - $productAttribute->setCode('MUG_MATERIAL_CODE'); - $productAttribute->setName('Mug material'); - $productAttribute->setValue('Wood'); - $productAttributes[] = $productAttribute; - - $productAttributes[] = $this->makeProductionYearAttribute(); + $rootTaxon = new TaxonDocument(); + $rootTaxon->setCode('ROOT'); + $rootTaxon->setPosition(0); + $rootTaxon->setSlug('root'); + $rootTaxon->setDescription('Lorem ipsum'); + + $productTaxon = new ProductTaxonDocument(); + $productTaxon->setCode('TREE'); + $productTaxon->setSlug('tree'); + $productTaxon->setPosition(1); + + $firstProductAttribute = new AttributeDocument(); + $firstProductAttribute->setCode('material'); + $firstProductAttribute->setName('Material'); + $firstProductAttribute->setValue('wood'); + + $secondProductAttribute = new AttributeDocument(); + $secondProductAttribute->setCode('size'); + $secondProductAttribute->setName('Size'); + $secondProductAttribute->setValue('M'); + + $this->assertEquals('banana', $product->getCode()); + $this->assertEquals('Banana', $product->getName()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals( + new Collection([ + $firstProductAttribute, + ]), + $product->getAttributes() + ); - return $productAttributes; + $this->assertEquals(1000, $product->getPrice()->getAmount()); + $this->assertEquals('USD', $product->getPrice()->getCurrency()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals('mobile', $product->getChannelCode()); + $this->assertEquals('/banana', $product->getSlug()); + $this->assertEquals('Banana', $product->getName()); + $this->assertEquals($createdAt, $product->getCreatedAt()); + $this->assertEquals('Lorem ipsum', $product->getDescription()); + $this->assertEquals($taxon, $product->getMainTaxon()); + $this->assertEquals(new Collection([$taxon, $rootTaxon]), $product->getTaxons()); + $this->assertEquals(new Collection([$productTaxon]), $product->getProductTaxons()); } } diff --git a/tests/Responses/Expected/WEB_DE/de_DE/product_list_page.json b/tests/Responses/Expected/WEB_DE/de_DE/product_list_page.json index fb6f6d9..69aab8f 100644 --- a/tests/Responses/Expected/WEB_DE/de_DE/product_list_page.json +++ b/tests/Responses/Expected/WEB_DE/de_DE/product_list_page.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "slug": "logan-becher", @@ -13,60 +12,39 @@ "main": "MUG", "others": [ "MUG", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 2, - "code": "LOGAN_MUG_SMALL_CODE", - "name": "Gnome Becher", - "price": { - "current": 1250, - "currency": "EUR", - "original": 0 - }, - "stock": 0, - "isTracked": true, - "images": [] - }, - { - "id": 1, - "code": "LOGAN_MUG_BIG_CODE", + "variants": { + "LOGAN_MUG_CODE": { + "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "price": { "current": 1250, - "currency": "EUR", - "original": 0 + "currency": "EUR" }, - "stock": 0, - "isTracked": false, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Produktionsjahr", "value": "2015" }, - "MUG_COLLECTION_CODE": { + { "code": "MUG_COLLECTION_CODE", "name": "Becher Sammlung", "value": "FEIERTAGSKOLLEKTION" }, - "MUG_MATERIAL_CODE": { + { "code": "MUG_MATERIAL_CODE", "name": "Becher Material", "value": "Holz" } - }, + ], "images": [], - "price": { - "current": 1250, - "currency": "EUR", - "original": 0 - }, "channelCode": "WEB_DE", "localeCode": "de_DE" } @@ -86,10 +64,12 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "channel", @@ -99,6 +79,7 @@ "default": false, "urlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE" }, "label": "WEB_DE", @@ -109,6 +90,7 @@ "default": false, "urlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE", "channel": "WEB_GB" }, @@ -131,10 +113,12 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", + "stock": "1", "locale": "de_DE" }, "name": "enabled", @@ -144,6 +128,7 @@ "default": false, "urlParameters": { "channel": "WEB_DE", + "stock": "1", "locale": "de_DE" }, "label": 1, @@ -162,15 +147,57 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "taxonCode", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "BRAND" + }, + "label": "BRAND", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "CATEGORY" + }, + "label": "CATEGORY", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "MUG" + }, + "label": "MUG", + "count": 1 + } + ] }, "taxonSlug": { "state": { @@ -183,15 +210,57 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "taxonSlug", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien" + }, + "label": "kategorien", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien\/1tassen" + }, + "label": "kategorien\/1tassen", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_DE", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "marken" + }, + "label": "marken", + "count": 1 + } + ] }, "priceRange": { "state": { @@ -204,11 +273,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "priceRange", @@ -221,7 +292,9 @@ "value": { "gte": "1" }, - "urlParameters": [], + "urlParameters": { + "stock": "1" + }, "name": "inStock", "options": [] }, @@ -229,6 +302,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { @@ -252,11 +326,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", - "enabled": true + "enabled": true, + "stock": "1" }, "name": "locale", "choices": [ @@ -265,7 +341,8 @@ "default": false, "urlParameters": { "channel": "WEB_DE", - "enabled": true + "enabled": true, + "stock": "1" }, "label": "de_DE", "count": 1 @@ -279,28 +356,30 @@ "urlParameters": [], "name": "paginator", "options": { - "limit": 9 + "limit": 10 } }, "tags": [], "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "paginator", "currentPage": 1, "totalItems": 1, "maxPages": 20, - "itemsPerPage": 9, + "itemsPerPage": 10, "numPages": 1, "options": [], - "limit": 9 + "limit": 10 }, "search": { "state": { @@ -313,11 +392,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "search" @@ -333,11 +414,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "attributes", @@ -348,6 +431,7 @@ "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Material", @@ -358,6 +442,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [ @@ -376,6 +461,7 @@ "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Sammlung", @@ -386,6 +472,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Sammlung": [ @@ -404,6 +491,7 @@ "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Produktionsjahr", @@ -414,6 +502,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Produktionsjahr": [ @@ -439,11 +528,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "attributesByCode" @@ -459,11 +550,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "options", @@ -474,6 +567,7 @@ "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Bechergr\u00f6\u00dfe", @@ -484,6 +578,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "Bechergr\u00f6\u00dfe": [ @@ -500,6 +595,7 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "Bechergr\u00f6\u00dfe": [ @@ -525,11 +621,13 @@ "urlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_DE", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "sort" diff --git a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page.json b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page.json index 0a9161f..2e2885f 100644 --- a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page.json +++ b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 3, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "slug": "logan-becher", @@ -13,117 +12,86 @@ "main": "MUG", "others": [ "MUG", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 2, - "code": "LOGAN_MUG_SMALL_CODE", - "name": "Gnome Becher", - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, - "stock": 0, - "isTracked": true, - "images": [] - }, - { - "id": 1, - "code": "LOGAN_MUG_BIG_CODE", + "variants": { + "LOGAN_MUG_CODE": { + "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "price": { "current": 1000, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 0, - "isTracked": false, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Produktionsjahr", "value": "2015" }, - "MUG_COLLECTION_CODE": { + { "code": "MUG_COLLECTION_CODE", "name": "Becher Sammlung", "value": "FEIERTAGSKOLLEKTION" }, - "MUG_MATERIAL_CODE": { + { "code": "MUG_MATERIAL_CODE", "name": "Becher Material", "value": "Holz" } - }, + ], "images": [], - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "de_DE" }, { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hut", "slug": "logan-hut", "taxons": { "others": [ "HAT", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 3, + "variants": { + "LOGAN_HAT_CODE": { "code": "LOGAN_HAT_CODE", "name": "Logan Hut", "price": { "current": 1500, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 2, - "isTracked": true, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Produktionsjahr", "value": "2010" }, - "MUG_COLLECTION_CODE": { + { "code": "MUG_COLLECTION_CODE", "name": "Becher Sammlung", "value": "FEIERTAGSKOLLEKTION" }, - "AVAILABLE_FROM": { + { "code": "AVAILABLE_FROM", "name": "Verf\u00fcgbar ab", "value": "2010-01-01T00:00:00+0000" } - }, + ], "images": [], - "price": { - "current": 1500, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "de_DE" }, { - "id": 3, "code": "LOGAN_T_SHIRT_CODE", "name": "Logan T-Shirt", "slug": "logan-t-shirt", @@ -131,76 +99,29 @@ "main": "T_SHIRTS", "others": [ "T_SHIRTS", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 7, - "code": "EXTRA_LARGE_LOGAN_T_SHIRT_CODE", - "name": "Extra Large Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 6, - "code": "LARGE_LOGAN_T_SHIRT_CODE", - "name": "Large Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 5, - "code": "MEDIUM_LOGAN_T_SHIRT_CODE", - "name": "Medium Logan T-Shirt", + "variants": { + "LOGAN_T_SHIRT_CODE": { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", "price": { "current": 2000, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 4, - "code": "SMALL_LOGAN_T_SHIRT_CODE", - "name": "Small Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Produktionsjahr", "value": "2020" } - }, + ], "images": [], - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "de_DE" } @@ -220,10 +141,12 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "channel", @@ -233,6 +156,7 @@ "default": false, "urlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE", "channel": "WEB_DE" }, @@ -244,6 +168,7 @@ "default": false, "urlParameters": { "enabled": true, + "stock": "1", "locale": "de_DE" }, "label": "WEB_GB", @@ -265,10 +190,12 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "de_DE" }, "name": "enabled", @@ -278,6 +205,7 @@ "default": false, "urlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "de_DE", "enabled": 0 }, @@ -289,6 +217,7 @@ "default": false, "urlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "de_DE" }, "label": 1, @@ -307,15 +236,83 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "taxonCode", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "HAT" + }, + "label": "HAT", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "MUG" + }, + "label": "MUG", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "T_SHIRTS" + }, + "label": "T_SHIRTS", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "BRAND" + }, + "label": "BRAND", + "count": 3 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonCode": "CATEGORY" + }, + "label": "CATEGORY", + "count": 3 + } + ] }, "taxonSlug": { "state": { @@ -328,15 +325,83 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "taxonSlug", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien\/1t-shirts" + }, + "label": "kategorien\/1t-shirts", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien\/1tassen" + }, + "label": "kategorien\/1tassen", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien\/hut" + }, + "label": "kategorien\/hut", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "kategorien" + }, + "label": "kategorien", + "count": 3 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "de_DE", + "taxonSlug": "marken" + }, + "label": "marken", + "count": 3 + } + ] }, "priceRange": { "state": { @@ -349,11 +414,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "priceRange", @@ -366,7 +433,9 @@ "value": { "gte": "1" }, - "urlParameters": [], + "urlParameters": { + "stock": "1" + }, "name": "inStock", "options": [] }, @@ -374,6 +443,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { @@ -397,11 +467,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", - "enabled": true + "enabled": true, + "stock": "1" }, "name": "locale", "choices": [ @@ -410,7 +482,8 @@ "default": false, "urlParameters": { "channel": "WEB_GB", - "enabled": true + "enabled": true, + "stock": "1" }, "label": "de_DE", "count": 3 @@ -421,6 +494,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "label": "en_GB", @@ -435,28 +509,30 @@ "urlParameters": [], "name": "paginator", "options": { - "limit": 9 + "limit": 10 } }, "tags": [], "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "paginator", "currentPage": 1, "totalItems": 3, "maxPages": 20, - "itemsPerPage": 9, + "itemsPerPage": 10, "numPages": 1, "options": [], - "limit": 9 + "limit": 10 }, "search": { "state": { @@ -469,11 +545,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "search" @@ -489,11 +567,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "attributes", @@ -504,6 +584,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Material", @@ -514,6 +595,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [ @@ -532,6 +614,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Sammlung", @@ -542,6 +625,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Sammlung": [ @@ -560,6 +644,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Produktionsjahr", @@ -570,6 +655,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Produktionsjahr": [ @@ -586,6 +672,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Produktionsjahr": [ @@ -602,6 +689,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Produktionsjahr": [ @@ -620,6 +708,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Verf\u00fcgbar ab", @@ -630,6 +719,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Verf\u00fcgbar ab": [ @@ -655,11 +745,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "attributesByCode" @@ -675,11 +767,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "options", @@ -690,6 +784,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Bechergr\u00f6\u00dfe", @@ -700,6 +795,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "Bechergr\u00f6\u00dfe": [ @@ -716,6 +812,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "Bechergr\u00f6\u00dfe": [ @@ -734,6 +831,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Hutgr\u00f6\u00dfe", @@ -744,6 +842,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "Hutgr\u00f6\u00dfe": [ @@ -762,6 +861,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "T-Shirt Gr\u00f6\u00dfe", @@ -772,6 +872,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "T-Shirt Gr\u00f6\u00dfe": [ @@ -788,6 +889,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "T-Shirt Gr\u00f6\u00dfe": [ @@ -804,6 +906,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "T-Shirt Gr\u00f6\u00dfe": [ @@ -820,6 +923,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "options": { "T-Shirt Gr\u00f6\u00dfe": [ @@ -845,11 +949,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "sort" diff --git a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_mug_material_wood_attribute.json b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_mug_material_wood_attribute.json index 4cdcf2e..db3bd97 100644 --- a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_mug_material_wood_attribute.json +++ b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_mug_material_wood_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "de_DE" } @@ -50,6 +48,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [ @@ -60,6 +59,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "attributes", @@ -70,6 +70,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Material", @@ -80,6 +81,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [] @@ -96,6 +98,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Becher Sammlung", @@ -106,6 +109,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [ @@ -127,6 +131,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "Produktionsjahr", @@ -137,6 +142,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "attributes": { "Becher Material": [ diff --git a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_phrase.json b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_phrase.json index 9931865..c40a0ac 100644 --- a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_phrase.json +++ b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_phrase.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hut", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "de_DE" } @@ -41,12 +39,14 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE", "search": "hut" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "name": "search" diff --git a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_production_year_2015_attribute.json b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_production_year_2015_attribute.json index be394e7..8607936 100644 --- a/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_production_year_2015_attribute.json +++ b/tests/Responses/Expected/WEB_GB/de_DE/product_list_page_filtered_by_production_year_2015_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Becher", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "de_DE" } diff --git a/tests/Responses/Expected/WEB_GB/en_GB/first_product_list_page_limited_to_two.json b/tests/Responses/Expected/WEB_GB/en_GB/first_product_list_page_limited_to_two.json index 807f989..a7e60ea 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/first_product_list_page_limited_to_two.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/first_product_list_page_limited_to_two.json @@ -5,7 +5,6 @@ "pages": 2, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,12 +12,10 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "slug": "@string@", @@ -26,7 +23,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -53,11 +49,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "paginator", diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page.json index 578591e..98e5f7e 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 3, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "logan-mug", @@ -13,117 +12,86 @@ "main": "MUG", "others": [ "MUG", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 2, - "code": "LOGAN_MUG_SMALL_CODE", - "name": "Gnome Mug", - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, - "stock": 0, - "isTracked": true, - "images": [] - }, - { - "id": 1, - "code": "LOGAN_MUG_BIG_CODE", + "variants": { + "LOGAN_MUG_CODE": { + "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "price": { "current": 1000, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 0, - "isTracked": false, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Production year", "value": "2015" }, - "MUG_COLLECTION_CODE": { + { "code": "MUG_COLLECTION_CODE", "name": "Mug collection", "value": "HOLIDAY COLLECTION" }, - "MUG_MATERIAL_CODE": { + { "code": "MUG_MATERIAL_CODE", "name": "Mug material", "value": "Wood" } - }, + ], "images": [], - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "slug": "logan-hat", "taxons": { "others": [ "HAT", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 3, + "variants": { + "LOGAN_HAT_CODE": { "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "price": { "current": 1500, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 2, - "isTracked": true, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Production year", "value": "2010" }, - "MUG_COLLECTION_CODE": { + { "code": "MUG_COLLECTION_CODE", "name": "Mug collection", "value": "HOLIDAY COLLECTION" }, - "AVAILABLE_FROM": { + { "code": "AVAILABLE_FROM", "name": "Available from", "value": "2010-01-01T00:00:00+0000" } - }, + ], "images": [], - "price": { - "current": 1500, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 3, "code": "LOGAN_T_SHIRT_CODE", "name": "Logan T-Shirt", "slug": "logan-t-shirt", @@ -131,76 +99,29 @@ "main": "T_SHIRTS", "others": [ "T_SHIRTS", + "CATEGORY", "BRAND" ] }, - "variants": [ - { - "id": 7, - "code": "EXTRA_LARGE_LOGAN_T_SHIRT_CODE", - "name": "Extra Large Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 6, - "code": "LARGE_LOGAN_T_SHIRT_CODE", - "name": "Large Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 5, - "code": "MEDIUM_LOGAN_T_SHIRT_CODE", - "name": "Medium Logan T-Shirt", + "variants": { + "LOGAN_T_SHIRT_CODE": { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", "price": { "current": 2000, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 1, - "isTracked": true, - "images": [] - }, - { - "id": 4, - "code": "SMALL_LOGAN_T_SHIRT_CODE", - "name": "Small Logan T-Shirt", - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, - "stock": 1, - "isTracked": true, "images": [] } - ], - "attributes": { - "PRODUCTION_YEAR": { + }, + "attributes": [ + { "code": "PRODUCTION_YEAR", "name": "Production year", "value": "2020" } - }, + ], "images": [], - "price": { - "current": 2000, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -220,10 +141,12 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "channel", @@ -233,6 +156,7 @@ "default": false, "urlParameters": { "enabled": true, + "stock": "1", "locale": "en_GB" }, "label": "WEB_GB", @@ -254,10 +178,12 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "en_GB" }, "name": "enabled", @@ -267,6 +193,7 @@ "default": false, "urlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "en_GB", "enabled": 0 }, @@ -278,6 +205,7 @@ "default": false, "urlParameters": { "channel": "WEB_GB", + "stock": "1", "locale": "en_GB" }, "label": 1, @@ -296,15 +224,83 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "taxonCode", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonCode": "HAT" + }, + "label": "HAT", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonCode": "MUG" + }, + "label": "MUG", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonCode": "T_SHIRTS" + }, + "label": "T_SHIRTS", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonCode": "BRAND" + }, + "label": "BRAND", + "count": 3 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonCode": "CATEGORY" + }, + "label": "CATEGORY", + "count": 3 + } + ] }, "taxonSlug": { "state": { @@ -317,15 +313,83 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "taxonSlug", - "choices": [] + "choices": [ + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonSlug": "categories\/hats" + }, + "label": "categories\/hats", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonSlug": "categories\/mugs" + }, + "label": "categories\/mugs", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonSlug": "categories\/t-shirts" + }, + "label": "categories\/t-shirts", + "count": 1 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonSlug": "brands" + }, + "label": "brands", + "count": 3 + }, + { + "active": false, + "default": false, + "urlParameters": { + "channel": "WEB_GB", + "enabled": true, + "stock": "1", + "locale": "en_GB", + "taxonSlug": "categories" + }, + "label": "categories", + "count": 3 + } + ] }, "priceRange": { "state": { @@ -338,11 +402,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "priceRange", @@ -355,7 +421,9 @@ "value": { "gte": "1" }, - "urlParameters": [], + "urlParameters": { + "stock": "1" + }, "name": "inStock", "options": [] }, @@ -363,6 +431,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { @@ -386,11 +455,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", - "enabled": true + "enabled": true, + "stock": "1" }, "name": "locale", "choices": [ @@ -400,6 +471,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "de_DE" }, "label": "de_DE", @@ -410,7 +482,8 @@ "default": false, "urlParameters": { "channel": "WEB_GB", - "enabled": true + "enabled": true, + "stock": "1" }, "label": "en_GB", "count": 3 @@ -424,28 +497,30 @@ "urlParameters": [], "name": "paginator", "options": { - "limit": 9 + "limit": 10 } }, "tags": [], "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "paginator", "currentPage": 1, "totalItems": 3, "maxPages": 20, - "itemsPerPage": 9, + "itemsPerPage": 10, "numPages": 1, "options": [], - "limit": 9 + "limit": 10 }, "search": { "state": { @@ -458,11 +533,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "search" @@ -478,11 +555,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "attributes", @@ -493,6 +572,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Available from", @@ -503,6 +583,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Available from": [ @@ -521,6 +602,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Mug collection", @@ -531,6 +613,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug collection": [ @@ -549,6 +632,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Mug material", @@ -559,6 +643,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug material": [ @@ -577,6 +662,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Production year", @@ -587,6 +673,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Production year": [ @@ -603,6 +690,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Production year": [ @@ -619,6 +707,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Production year": [ @@ -644,11 +733,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "attributesByCode" @@ -664,11 +755,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "options", @@ -679,6 +772,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Hat size", @@ -689,6 +783,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "Hat size": [ @@ -707,6 +802,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Mug size", @@ -717,6 +813,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "Mug size": [ @@ -733,6 +830,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "Mug size": [ @@ -751,6 +849,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "T-Shirt size", @@ -761,6 +860,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "T-Shirt size": [ @@ -777,6 +877,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "T-Shirt size": [ @@ -793,6 +894,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "T-Shirt size": [ @@ -809,6 +911,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "options": { "T-Shirt size": [ @@ -834,11 +937,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "sort" diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_mug_material_wood_attribute.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_mug_material_wood_attribute.json index bdecdd6..ecdb0a2 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_mug_material_wood_attribute.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_mug_material_wood_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -50,6 +48,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug material": [ @@ -60,6 +59,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "attributes", @@ -70,6 +70,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Mug collection", @@ -80,6 +81,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug material": [ @@ -101,6 +103,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Mug material", @@ -111,6 +114,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug material": [] @@ -127,6 +131,7 @@ "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "Production year", @@ -137,6 +142,7 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "attributes": { "Mug material": [ diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_partial_phrase.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_partial_phrase.json index 39f6c42..58b8c52 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_partial_phrase.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_partial_phrase.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 2, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,12 +12,10 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "slug": "@string@", @@ -26,7 +23,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_phrase.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_phrase.json index 603aefe..6cfb58f 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_phrase.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_phrase.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -41,12 +39,14 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB", "search": "hat" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "search" diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_price_range.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_price_range.json index 51f3e28..4cdb751 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_price_range.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_price_range.json @@ -1,81 +1,48 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 2, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", "taxons": "@array@", - "variants": [ - { - "id": 2, - "code": "LOGAN_MUG_SMALL_CODE", - "name": "Gnome Mug", - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, - "stock": 0, - "isTracked": true, - "images": [] - }, - { - "id": 1, - "code": "LOGAN_MUG_BIG_CODE", + "variants": { + "LOGAN_MUG_CODE": { + "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "price": { "current": 1000, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 0, - "isTracked": false, - "images": [] + "images": "@array@" } - ], + }, "attributes": "@array@", "images": "@array@", - "price": { - "current": 1000, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 2, "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "slug": "@string@", "taxons": "@array@", - "variants": [ - { - "id": 3, + "variants": { + "LOGAN_HAT_CODE": { "code": "LOGAN_HAT_CODE", "name": "Logan Hat", "price": { "current": 1500, - "currency": "GBP", - "original": 0 + "currency": "GBP" }, - "stock": 2, - "isTracked": true, - "images": [] + "images": "@array@" } - ], + }, "attributes": "@array@", "images": "@array@", - "price": { - "current": 1500, - "currency": "GBP", - "original": 0 - }, "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -102,12 +69,14 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "price": "1000;1500", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "priceRange", diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_attribute.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_attribute.json index be3a023..51532ad 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_attribute.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_and_mug_material_wood_attribute.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_and_mug_material_wood_attribute.json index be3a023..51532ad 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_and_mug_material_wood_attribute.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_and_mug_material_wood_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 1, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } diff --git a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_attribute.json b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_attribute.json index 20bcdf6..cb2e10d 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_attribute.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/product_list_page_filtered_by_production_year_2015_or_2020_attribute.json @@ -1,11 +1,10 @@ { "page": 1, - "limit": 9, + "limit": 10, "total": 2, "pages": 1, "items": [ { - "id": 1, "code": "LOGAN_MUG_CODE", "name": "Logan Mug", "slug": "@string@", @@ -13,12 +12,10 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" }, { - "id": 3, "code": "LOGAN_T_SHIRT_CODE", "name": "Logan T-Shirt", "slug": "@string@", @@ -26,7 +23,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } diff --git a/tests/Responses/Expected/WEB_GB/en_GB/second_product_list_page_limited_to_two.json b/tests/Responses/Expected/WEB_GB/en_GB/second_product_list_page_limited_to_two.json index c7fb91d..46dc613 100644 --- a/tests/Responses/Expected/WEB_GB/en_GB/second_product_list_page_limited_to_two.json +++ b/tests/Responses/Expected/WEB_GB/en_GB/second_product_list_page_limited_to_two.json @@ -5,7 +5,6 @@ "pages": 2, "items": [ { - "id": 3, "code": "LOGAN_T_SHIRT_CODE", "name": "Logan T-Shirt", "slug": "@string@", @@ -13,7 +12,6 @@ "variants": "@array@", "attributes": "@array@", "images": "@array@", - "price": "@array@", "channelCode": "WEB_GB", "localeCode": "en_GB" } @@ -40,11 +38,13 @@ "urlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "resetUrlParameters": { "channel": "WEB_GB", "enabled": true, + "stock": "1", "locale": "en_GB" }, "name": "paginator",