integration_documentation:plugin:en:integration:shopware_6:extension
Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
integration_documentation:plugin:en:integration:shopware_6:extension [2022/06/21 13:46] tobi |
integration_documentation:plugin:en:integration:shopware_6:extension [2022/12/13 13:42] (current) tobi |
||
---|---|---|---|
Line 15: | Line 15: | ||
</markdown> | </markdown> | ||
- | <note tip>Please make sure to use the same major version as the base Findologic plugin. This means that ''2.x'' is compatible with ''2.x'' and ''3.x'' is compatible with ''3.x'', etc.</note> | + | <note tip>Please make sure to use the same major version as the base Findologic plugin. This means that ''3.x'' is compatible with ''3.x'' and ''4.x'' is compatible with ''4.x'', etc.</note> |
<markdown> | <markdown> | ||
Line 25: | Line 25: | ||
By default the extension plugin decorates the `AttributeAdapter` and `DefaultPropertiesAdapter`, which are responsible to generate the attributes and properties of a product. | By default the extension plugin decorates the `AttributeAdapter` and `DefaultPropertiesAdapter`, which are responsible to generate the attributes and properties of a product. | ||
- | Any adapter in `FINDOLOGIC\FinSearch\Export\Adapters` can be decorated. | + | Any adapter in `FINDOLOGIC\Shopware6Common\Export\Adapters` can be decorated. The original files are located within `vendor/findologic/shopware6-common/src/Export/Adapters`. |
`src/Resources/config/services.xml` | `src/Resources/config/services.xml` | ||
Line 38: | Line 38: | ||
<service | <service | ||
id="FINDOLOGIC\ExtendFinSearch\Export\Adapters\AttributeAdapter" | id="FINDOLOGIC\ExtendFinSearch\Export\Adapters\AttributeAdapter" | ||
- | decorates="FINDOLOGIC\FinSearch\Export\Adapters\AttributeAdapter" | + | decorates="FINDOLOGIC\Shopware6Common\Export\Adapters\AttributeAdapter" |
public="true" | public="true" | ||
decoration-on-invalid="ignore" | decoration-on-invalid="ignore" | ||
+ | autowire="true" | ||
> | > | ||
- | <argument type="service" id="service_container" /> | + | <argument key="$dynamicProductGroupService" type="service" id="FINDOLOGIC\FinSearch\Export\Services\DynamicProductGroupService" /> |
- | <argument type="service" id="FINDOLOGIC\FinSearch\Struct\Config" /> | + | <argument key="$catUrlBuilderService" type="service" id="FINDOLOGIC\FinSearch\Export\Services\CatUrlBuilderService" /> |
- | <argument type="service" id="Shopware\Core\Framework\Adapter\Translation\Translator" /> | + | <argument key="$translator" type="service" id="Shopware\Core\Framework\Adapter\Translation\Translator" /> |
- | <argument type="service" id="fin_search.sales_channel_context" /> | + | |
- | <argument type="service" id="FINDOLOGIC\FinSearch\Export\UrlBuilderService" /> | + | |
- | <argument type="service" id="fin_search.export_context" /> | + | |
</service> | </service> | ||
<service | <service | ||
id="FINDOLOGIC\ExtendFinSearch\Export\Adapters\DefaultPropertiesAdapter" | id="FINDOLOGIC\ExtendFinSearch\Export\Adapters\DefaultPropertiesAdapter" | ||
- | decorates="FINDOLOGIC\FinSearch\Export\Adapters\DefaultPropertiesAdapter" | + | decorates="FINDOLOGIC\Shopware6Common\Export\Adapters\DefaultPropertiesAdapter" |
public="true" | public="true" | ||
decoration-on-invalid="ignore" | decoration-on-invalid="ignore" | ||
+ | autowire="true" | ||
> | > | ||
- | <argument type="service" id="FINDOLOGIC\FinSearch\Struct\Config" /> | + | <argument key="$translator" type="service" id="Shopware\Core\Framework\Adapter\Translation\Translator" /> |
- | <argument type="service" id="fin_search.sales_channel_context" /> | + | |
- | <argument type="service" id="Shopware\Core\Framework\Adapter\Translation\Translator" /> | + | |
</service> | </service> | ||
Line 78: | Line 75: | ||
use FINDOLOGIC\Export\Data\Attribute; | use FINDOLOGIC\Export\Data\Attribute; | ||
- | use FINDOLOGIC\FinSearch\Export\Adapters\AttributeAdapter as OriginalAttributeAdapter; | + | use FINDOLOGIC\Shopware6Common\Export\Adapters\AttributeAdapter as OriginalAttributeAdapter; |
- | use Shopware\Core\Content\Product\ProductEntity; | + | use Vin\ShopwareSdk\Data\Entity\Product\ProductEntity; |
class AttributeAdapter extends OriginalAttributeAdapter | class AttributeAdapter extends OriginalAttributeAdapter | ||
Line 110: | Line 107: | ||
use FINDOLOGIC\Export\Data\Property; | use FINDOLOGIC\Export\Data\Property; | ||
- | use FINDOLOGIC\FinSearch\Export\Adapters\DefaultPropertiesAdapter as OriginalDefaultPropertiesAdapter; | + | use FINDOLOGIC\Shopware6Common\Export\Adapters\DefaultPropertiesAdapter as OriginalDefaultPropertiesAdapter; |
- | use Shopware\Core\Content\Product\ProductEntity; | + | use Vin\ShopwareSdk\Data\Entity\Product\ProductEntity; |
class DefaultPropertiesAdapter extends OriginalDefaultPropertiesAdapter | class DefaultPropertiesAdapter extends OriginalDefaultPropertiesAdapter | ||
Line 210: | Line 207: | ||
use FINDOLOGIC\Export\Data\Property; | use FINDOLOGIC\Export\Data\Property; | ||
- | use FINDOLOGIC\FinSearch\Export\Adapters\AdapterFactory; | + | use FINDOLOGIC\Shopware6Common\Export\Adapters\AdapterFactory; |
- | use FINDOLOGIC\FinSearch\Export\Events\AfterItemBuildEvent; | + | use FINDOLOGIC\Shopware6Common\Export\Events\AfterItemBuildEvent; |
- | use FINDOLOGIC\FinSearch\Export\Events\AfterVariantAdaptEvent; | + | use FINDOLOGIC\Shopware6Common\Export\Events\AfterVariantAdaptEvent; |
- | use FINDOLOGIC\FinSearch\Export\Events\BeforeItemAdaptEvent; | + | use FINDOLOGIC\Shopware6Common\Export\Events\BeforeItemAdaptEvent; |
- | use Shopware\Core\Content\Product\ProductEntity; | + | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
+ | use Vin\ShopwareSdk\Data\Entity\Product\ProductEntity; | ||
class ProductSubscriber implements EventSubscriberInterface | class ProductSubscriber implements EventSubscriberInterface | ||
Line 232: | Line 229: | ||
{ | { | ||
return [ | return [ | ||
- | BeforeItemAdaptEvent::NAME => 'beforeItemAdapt', | ||
AfterVariantAdaptEvent::NAME => 'afterVariantAdapted', | AfterVariantAdaptEvent::NAME => 'afterVariantAdapted', | ||
AfterItemBuildEvent::NAME => 'afterItemCompleted' | AfterItemBuildEvent::NAME => 'afterItemCompleted' | ||
]; | ]; | ||
- | } | ||
- | |||
- | public function beforeItemAdapt() | ||
- | { | ||
- | $this->variantData = []; | ||
} | } | ||
Line 263: | Line 254: | ||
); | ); | ||
} | } | ||
+ | | ||
+ | $this->variantData = []; | ||
} | } | ||
} | } | ||
Line 282: | Line 275: | ||
> | > | ||
<tag name="kernel.event_subscriber" /> | <tag name="kernel.event_subscriber" /> | ||
- | <argument type="service" id="FINDOLOGIC\FinSearch\Export\Adapters\AdapterFactory" /> | + | <argument type="service" id="FINDOLOGIC\Shopware6Common\Export\Adapters\AdapterFactory" /> |
</service> | </service> | ||
Line 294: | Line 287: | ||
```php | ```php | ||
//... | //... | ||
+ | |||
public function afterVariantAdapted(AfterVariantAdaptEvent $event) | public function afterVariantAdapted(AfterVariantAdaptEvent $event) | ||
{ | { | ||
Line 300: | Line 294: | ||
$this->variantData[] = [ | $this->variantData[] = [ | ||
'name' => $this->getName($product), | 'name' => $this->getName($product), | ||
- | 'image' => $this->getImageUrl($product), | + | 'url' => $this->getUrl($product), |
'price' => $this->getPrice($product) | 'price' => $this->getPrice($product) | ||
]; | ]; | ||
} | } | ||
+ | |||
//... | //... | ||
+ | |||
private function getName(ProductEntity $productEntity): string | private function getName(ProductEntity $productEntity): string | ||
{ | { | ||
Line 312: | Line 308: | ||
} | } | ||
- | private function getImageUrl(ProductEntity $productEntity): string | + | private function getUrl(ProductEntity $productEntity): string |
{ | { | ||
- | $images = $this->adapterFactory->getUrlAdapter()->adapt($productEntity); | + | $url = $this->adapterFactory->getUrlAdapter()->adapt($productEntity); |
- | return $images ? $images->getValues()[''] : ''; | + | return $url ? $url->getValues()[''] : ''; |
} | } | ||
Line 329: | Line 325: | ||
return count($prices) ? current($prices)->getValues()[''] : ''; | return count($prices) ? current($prices)->getValues()[''] : ''; | ||
} | } | ||
+ | |||
//... | //... | ||
``` | ``` | ||
+ | |||
+ | This will export the `name`, `url` and `price` of each variant, the JSON would be like: | ||
+ | ```json | ||
+ | [ | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Gray - Orange Logo)", | ||
+ | "url": "https://store.com/Findologic-T-Shirt-Gray-Orange-Logo/411dc735cade4c8789421f9c2aaec51f", | ||
+ | "price": 59.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/ad99a6257e1546f08dbe9886a48e4230", | ||
+ | "price": 55.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Black - White Logo)", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/7c18c5ff8aa548e1bdba6b738ac42f71", | ||
+ | "price": 49.99 | ||
+ | } | ||
+ | ] | ||
+ | ``` | ||
+ | |||
+ | ### Add images | ||
+ | |||
+ | For variant images, you will need to add the relevant variant associations as shown [here](#add_product_or_variant_associations). (`cover` and `media`) | ||
+ | |||
+ | Additionally: | ||
+ | `src/Subscriber/ProductSubscriber.php` | ||
+ | ```php | ||
+ | // ... | ||
+ | |||
+ | public function afterVariantAdapted(AfterVariantAdaptEvent $event) | ||
+ | { | ||
+ | $product = $event->getProduct(); | ||
+ | |||
+ | $this->variantData[] = [ | ||
+ | // ... | ||
+ | 'image' => $this->getImageUrl($product) | ||
+ | ]; | ||
+ | } | ||
+ | |||
+ | // ... | ||
+ | |||
+ | private function getImageUrl(ProductEntity $productEntity): string | ||
+ | { | ||
+ | $images = $this->adapterFactory->getImagesAdapter()->adapt($productEntity); | ||
+ | |||
+ | return count($images) ? current($images)->getUrl() : ''; | ||
+ | } | ||
+ | ``` | ||
+ | |||
+ | ### Deal with variant-specific data | ||
+ | |||
+ | `src/Subscriber/ProductSubscriber.php` | ||
+ | ```php | ||
+ | // ... | ||
+ | |||
+ | private const VARIANT_PROPERTY = 'color'; | ||
+ | |||
+ | //... | ||
+ | |||
+ | public function afterVariantAdapted(AfterVariantAdaptEvent $event) | ||
+ | { | ||
+ | $product = $event->getProduct(); | ||
+ | |||
+ | foreach ($product->properties as $variantProperty) { | ||
+ | // Ignore all properties except the property we want to export our variants off. | ||
+ | if ( | ||
+ | !$variantProperty->group || | ||
+ | $variantProperty->group->getTranslation('name') !== self::VARIANT_PROPERTY) | ||
+ | { | ||
+ | continue; | ||
+ | } | ||
+ | |||
+ | $propertyName = $variantProperty->getTranslation('name'); | ||
+ | |||
+ | $this->variantData[$propertyName] = [ | ||
+ | 'name' => $this->getName($product), | ||
+ | 'url' => $this->getUrl($product), | ||
+ | 'price' => $this->getPrice($product), | ||
+ | 'image' => $this->getImageUrl($product), | ||
+ | self::VARIANT_PROPERTY => $propertyName | ||
+ | ]; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ... | ||
+ | ``` | ||
+ | |||
+ | After this implementation, the JSON would be like: | ||
+ | |||
+ | ```json | ||
+ | { | ||
+ | "Gray": { | ||
+ | "name": "Findologic T-Shirt (Gray - Orange Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt-Gray-Orange-Logo/411dc735cade4c8789421f9c2aaec51f", | ||
+ | "color": "Gray" | ||
+ | }, | ||
+ | "Black": { | ||
+ | "name": "Findologic T-Shirt (Black - White Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/7c18c5ff8aa548e1bdba6b738ac42f71", | ||
+ | "color": "Black" | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | |||
+ | ### Usergroup-specific variants | ||
+ | |||
+ | `src/Subscriber/ProductSubscriber.php` | ||
+ | ```php | ||
+ | //... | ||
+ | |||
+ | public function afterVariantAdapted(AfterVariantAdaptEvent $event) | ||
+ | { | ||
+ | $product = $event->getProduct(); | ||
+ | |||
+ | $basicVariantData = [ | ||
+ | 'name' => $this->getName($product), | ||
+ | 'url' => $this->getUrl($product), | ||
+ | 'image' => $this->getImageUrl($product) | ||
+ | ]; | ||
+ | |||
+ | foreach ($this->adapterFactory->getPriceAdapter()->adapt($product) as $price) { | ||
+ | $values = $price->getValues(); | ||
+ | |||
+ | $variantData = array_merge( | ||
+ | $basicVariantData, | ||
+ | [ | ||
+ | 'price' => current($values) | ||
+ | ] | ||
+ | ); | ||
+ | |||
+ | $this->variantData[array_key_first($values)][] = json_encode($variantData); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public function afterItemCompleted(AfterItemBuildEvent $event) | ||
+ | { | ||
+ | $variantData = []; | ||
+ | foreach ($this->variantData as $usergroup => $userGroupVariantData) { | ||
+ | $variantData[$usergroup] = json_encode($userGroupVariantData); | ||
+ | } | ||
+ | |||
+ | $item = $event->getItem(); | ||
+ | |||
+ | if (count($this->variantData)) { | ||
+ | $item->addProperty( | ||
+ | new Property('variants', $variantData) | ||
+ | ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //... | ||
+ | ``` | ||
+ | |||
+ | </markdown> | ||
+ | |||
+ | <note tip>''variants'' **must** be exported for **all** usergroups. If a usergroup is not exported, this usergroup will not have any ''variants'' data.</note> | ||
+ | |||
+ | <markdown> | ||
+ | |||
+ | An XML export with usergroup in properties may look like: | ||
+ | |||
+ | ```xml | ||
+ | <!-- ... --> | ||
+ | <allProperties> | ||
+ | <property usergroup="JyInVwMCBQtTdQ1RAwkmCSRXUVkGBCZ6B1YgDyFXVnc="> | ||
+ | <key> | ||
+ | <![CDATA[ variants ]]> | ||
+ | </key> | ||
+ | <value> | ||
+ | <![CDATA[ | ||
+ | [ | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Gray - Orange Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt-Gray-Orange-Logo/411dc735cade4c8789421f9c2aaec51f", | ||
+ | "price": 59.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/ad99a6257e1546f08dbe9886a48e4230", | ||
+ | "price": 55.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Black - White Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/7c18c5ff8aa548e1bdba6b738ac42f71", | ||
+ | "price": 49.99 | ||
+ | } | ||
+ | ] | ||
+ | ]]> | ||
+ | </value> | ||
+ | </property> | ||
+ | <property usergroup="dX1WUgsgCyVUIHcPcXYFUw1xUlBZUwcAB1FUcgNQCwA="> | ||
+ | <key> | ||
+ | <![CDATA[ variants ]]> | ||
+ | </key> | ||
+ | <value> | ||
+ | <![CDATA[ | ||
+ | [ | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Gray - Orange Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt-Gray-Orange-Logo/411dc735cade4c8789421f9c2aaec51f", | ||
+ | "price": 599.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/ad99a6257e1546f08dbe9886a48e4230", | ||
+ | "price": 559.99 | ||
+ | }, | ||
+ | { | ||
+ | "name": "Findologic T-Shirt (Black - White Logo)", | ||
+ | "image": "https://store.com/some/path/to/image_800x800.jpg", | ||
+ | "url": "https://store.com/Findologic-T-Shirt/7c18c5ff8aa548e1bdba6b738ac42f71", | ||
+ | "price": 499.99 | ||
+ | } | ||
+ | ] | ||
+ | ]]> | ||
+ | </value> | ||
+ | </property> | ||
+ | </allProperties> | ||
+ | <!-- ... --> | ||
+ | ``` | ||
+ | |||
+ | ## Add product or variant associations | ||
+ | |||
+ | Sometimes the plugin doesn't add the associations needed in the extension. This may cause the associated field to always return `null. It's also the case if third party plugins extend the product entity with an additional table. Other examples include image URLs or color codes from variant properties. | ||
+ | |||
+ | Decorate `FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder`: | ||
+ | |||
+ | `src/Export/Search/ProductCriteriaBuilder.php` | ||
+ | ```php | ||
+ | <?php | ||
+ | |||
+ | declare(strict_types=1); | ||
+ | |||
+ | namespace FINDOLOGIC\ExtendFinSearch\Export\Search; | ||
+ | |||
+ | use FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder as OriginalProductCriteriaBuilder; | ||
+ | |||
+ | class ProductCriteriaBuilder extends OriginalProductCriteriaBuilder | ||
+ | { | ||
+ | public function withProductAssociations(): OriginalProductCriteriaBuilder | ||
+ | { | ||
+ | parent::withProductAssociations(); | ||
+ | |||
+ | $this->criteria->addAssociations([ | ||
+ | // Additional associations | ||
+ | ]); | ||
+ | |||
+ | return $this; | ||
+ | } | ||
+ | |||
+ | public function withVariantAssociations(): OriginalProductCriteriaBuilder | ||
+ | { | ||
+ | parent::withVariantAssociations(); | ||
+ | |||
+ | $this->criteria->addAssociations([ | ||
+ | 'cover', | ||
+ | 'media' | ||
+ | ]); | ||
+ | |||
+ | return $this; | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | |||
+ | `src/Resources/config/services.xml` | ||
+ | ```xml | ||
+ | <?xml version="1.0" ?> | ||
+ | <container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
+ | xmlns="http://symfony.com/schema/dic/services" | ||
+ | xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> | ||
+ | |||
+ | <services> | ||
+ | |||
+ | <!-- ... --> | ||
+ | |||
+ | <service | ||
+ | id="FINDOLOGIC\ExtendFinSearch\Export\Search\ProductCriteriaBuilder" | ||
+ | decorates="FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder" | ||
+ | public="true" | ||
+ | decoration-on-invalid="ignore" | ||
+ | autowire="true" | ||
+ | /> | ||
+ | | ||
+ | <!-- ... --> | ||
+ | |||
+ | </services> | ||
+ | </container> | ||
+ | ``` | ||
+ | |||
+ | ## Cookie Consent for Direct Integration | ||
+ | |||
+ | In case it's required by the integration, you are required to add a cookie consent. Please see the Shopware 6 documentation about [Adding a cookie to the cookie manager]( https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-cookie-to-manager). | ||
+ | |||
+ | There is also an [example](https://github.com/findologic/plugin-shopware-6-extension/commit/cf1a0b68a8f590f8eaf818dc038b5903edfbfd80) available in our GitHub repository. | ||
+ | |||
+ | ## Add custom sorting options for API Integration | ||
+ | |||
+ | The Findologic base plugin already provides sorting options for the most common use-cases. The plugin uses `SortingHandler` to send the currently selected sorting option via API parameters to the Findologic Search-API (see [all available SortingHandlers](https://github.com/findologic/plugin-shopware-6/tree/develop/src/Core/Content/Product/SalesChannel/Listing/SortingHandler)). | ||
+ | |||
+ | Therefore to handle custom sorting options, create a custom `SortingHandler` in the extension plugin, and override the responsible `SortingHandlerService` to include the created `SortingHandler`. | ||
+ | |||
+ | ### Prerequisites | ||
+ | |||
+ | Before a custom sorting can be used, make sure to export the value for the custom sort in the `<sort>` field in the export. See the [XML Format documentation](:xml_export_documentation:xml_format#sorts) for further details. | ||
+ | |||
+ | ### Implementation | ||
+ | |||
+ | **Step 1: Create a `SortingHandler`** | ||
+ | |||
+ | Create the folder structure `Core/Content/Product/SalesChannel/Listing/SortingHandler` in the extension plugin, and add a custom sorting handler class. In this example it will be `ThirdPartySortingHandler`: | ||
+ | |||
+ | ```php | ||
+ | use FINDOLOGIC\Api\Requests\SearchNavigation\SearchNavigationRequest; | ||
+ | use FINDOLOGIC\FinSearch\Core\Content\Product\SalesChannel\Listing\SortingHandler\SortingHandlerInterface; | ||
+ | use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting; | ||
+ | |||
+ | class ThirdPartySortingHandler implements SortingHandlerInterface | ||
+ | { | ||
+ | public function supportsSorting(FieldSorting $fieldSorting): bool | ||
+ | { | ||
+ | // Enter your custom sort here. | ||
+ | // To get the name of the sort, select the sort in the storefront and | ||
+ | // add a dd($fieldSorting) here and refresh the page. | ||
+ | return $fieldSorting->getField() === 'product.third_party_extension.field'; | ||
+ | } | ||
+ | |||
+ | public function generateSorting(FieldSorting $fieldSorting, SearchNavigationRequest $searchNavigationRequest): void | ||
+ | { | ||
+ | $searchNavigationRequest->setOrder('shopsort ' . $fieldSorting->getDirection()); | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | |||
+ | **Step 2: Decorate the `SortingHandlerService`** | ||
+ | |||
+ | The `SortingHandlerService` holds all available sorting options. Therefore, you want to add your custom sort to this service. The service can be found in `Findologic/Request/Handler`. Simply override the `getSortingHandlers` method to include your own custom sorting handler. | ||
+ | |||
+ | ```php | ||
+ | namespace FINDOLOGIC\ExtendFinSearch\Findologic\Request\Handler; | ||
+ | |||
+ | use FINDOLOGIC\ExtendFinSearch\Core\Content\Product\SalesChannel\Listing\SortingHandler\ThirdPartySortingHandler; | ||
+ | use FINDOLOGIC\FinSearch\Core\Content\Product\SalesChannel\Listing\SortingHandler\SortingHandlerInterface; | ||
+ | use FINDOLOGIC\FinSearch\Findologic\Request\Handler\SortingHandlerService as OriginalSortingHandlerService; | ||
+ | |||
+ | class SortingHandlerService extends OriginalSortingHandlerService | ||
+ | { | ||
+ | /** | ||
+ | * @return SortingHandlerInterface[] | ||
+ | */ | ||
+ | protected function getSortingHandlers(): array | ||
+ | { | ||
+ | return array_merge( | ||
+ | parent::getSortingHandlers(), | ||
+ | [ | ||
+ | new ThirdPartySortingHandler() | ||
+ | ] | ||
+ | ); | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | |||
+ | **Step 3: Add the decorated service to the services.xml** | ||
+ | |||
+ | As a last step, simply decorate in your `src/Resources/config/services.xml` the service of the main plugin: | ||
+ | |||
+ | ```xml | ||
+ | <?xml version="1.0" ?> | ||
+ | <container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
+ | xmlns="http://symfony.com/schema/dic/services" | ||
+ | xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> | ||
+ | |||
+ | <services> | ||
+ | |||
+ | <service | ||
+ | id="FINDOLOGIC\ExtendFinSearch\Findologic\Request\Handler\SortingHandlerService" | ||
+ | decorates="FINDOLOGIC\FinSearch\Findologic\Request\Handler\SortingHandlerService" | ||
+ | decoration-on-invalid="ignore" | ||
+ | /> | ||
+ | |||
+ | </services> | ||
+ | </container> | ||
+ | ``` | ||
+ | |||
+ | Once this step is done, selecting your relevant sorting option will send the order parameter to the Findologic API. | ||
</markdown> | </markdown> |