integration_documentation:plugin:en:integration:shopware_6:extension

integration_documentation:plugin:en:integration:shopware_6:extension

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
integration_documentation:plugin:en:integration:shopware_6:extension [2022/06/21 14:14]
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 362: Line 355:
  
 Additionally:​ Additionally:​
 +`src/​Subscriber/​ProductSubscriber.php`
 ```php ```php
 // ... // ...
Line 383: Line 377:
     return count($images) ? current($images)->​getUrl() : '';​     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>​
 +<!-- ... -->
 ``` ```
  
Line 400: Line 573:
  
 use FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder as OriginalProductCriteriaBuilder;​ use FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder as OriginalProductCriteriaBuilder;​
-use FINDOLOGIC\FinSearch\Utils\Utils;​ 
  
 class ProductCriteriaBuilder extends OriginalProductCriteriaBuilder class ProductCriteriaBuilder extends OriginalProductCriteriaBuilder
Line 406: Line 578:
     public function withProductAssociations():​ OriginalProductCriteriaBuilder     public function withProductAssociations():​ OriginalProductCriteriaBuilder
     {     {
-        ​Utils::addProductAssociations($this->​criteria);+        ​parent::withProductAssociations();
  
         $this->​criteria->​addAssociations([         $this->​criteria->​addAssociations([
Line 417: Line 589:
     public function withVariantAssociations():​ OriginalProductCriteriaBuilder     public function withVariantAssociations():​ OriginalProductCriteriaBuilder
     {     {
-        ​Utils::addVariantAssociations($this->​criteria);+        ​parent::withVariantAssociations();
  
         $this->​criteria->​addAssociations([         $this->​criteria->​addAssociations([
Line 444: Line 616:
             decorates="​FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder"​             decorates="​FINDOLOGIC\FinSearch\Export\Search\ProductCriteriaBuilder"​
             public="​true"​             public="​true"​
-        > +            decoration-on-invalid="ignore
-            <​argument type="service" ​id="​fin_search.sales_channel_context"​ /> +            ​autowire="true
-            ​<​argument type="service" ​id="​Shopware\Core\System\SystemConfig\SystemConfigService"​ /> +        />
-        ​</service>+
         ​         ​
         <!-- ... -->         <!-- ... -->
Line 454: Line 625:
 </​container>​ </​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>​