custom/plugins/shopware6-sapoci/src/Subscriber/LineItemAddedSubscriber.php line 71

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Orcamultimedia\OciPunchout\Subscriber;
  4. use Orcamultimedia\OciPunchout\Service\OciService;
  5. use Orcamultimedia\OciPunchout\Struct\OciCartData;
  6. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  8. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository;
  9. use Shopware\Core\System\SystemConfig\SystemConfigService;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. class LineItemAddedSubscriber implements EventSubscriberInterface
  12. {
  13.     public const CONFIG_KEYS = [
  14.         'extcategoryid',
  15.         'leadtime',
  16.         'manufactmat',
  17.         'manufactcode',
  18.         'matgroup',
  19.         'matnr',
  20.         'unit',
  21.         'unitmapping',
  22.         'vendor',
  23.         'extschematype',
  24.         'customfield1',
  25.         'customfield2',
  26.         'customfield3',
  27.         'customfield4',
  28.         'customfield5',
  29.         'orderitemid',
  30.         'extproductcatalogid',
  31.         'descriptionlong',
  32.         'currencyid',
  33.         'tax',
  34.         'classificationid',
  35.         'classificationgroupid',
  36.         'deliverydate',
  37.         'sourceproductcatalogid',
  38.         'previewurl',
  39.         'ordertext',
  40.         'gwg',
  41.         'kontierung',
  42.         'standard'
  43.     ];
  44.     private SalesChannelRepository $productRepository;
  45.     private OciService $ociService;
  46.     private SystemConfigService $systemConfigService;
  47.     public function __construct(
  48.         SalesChannelRepository $productRepository,
  49.         OciService             $ociService,
  50.         SystemConfigService    $systemConfigService
  51.     )
  52.     {
  53.         $this->productRepository $productRepository;
  54.         $this->ociService $ociService;
  55.         $this->systemConfigService $systemConfigService;
  56.     }
  57.     public static function getSubscribedEvents(): array
  58.     {
  59.         return [
  60.             BeforeLineItemAddedEvent::class => 'addPayloadValues',
  61.         ];
  62.     }
  63.     public function addPayloadValues(BeforeLineItemAddedEvent $event): void
  64.     {
  65.         if (!$this->ociService->isPunchout()) {
  66.             return;
  67.         }
  68.         $lineItem $event->getLineItem();
  69.         $context $event->getSalesChannelContext();
  70.         $config $this->systemConfigService->get('OciPunchout.config'$context->getSalesChannel()->getId());
  71.         // Get customer-specific configuration
  72.         $customer $context->getCustomer();
  73.         $customerConfig = [];
  74.         if ($customer && $customer->getCustomFields()) {
  75.             foreach (self::CONFIG_KEYS as $key) {
  76.                 $customerFieldKey 'oci_' $key// Assuming custom fields are prefixed with 'oci_'
  77.                 if (isset($customer->getCustomFields()[$customerFieldKey])) {
  78.                     $customerConfig[$key] = $customer->getCustomFields()[$customerFieldKey];
  79.                 }
  80.             }
  81.         }
  82.         $criteria = new Criteria([$lineItem->getReferencedId()]);
  83.         $criteria->addAssociation('manufacturer');
  84.         $criteria->addAssociation('categories');
  85.         $product $this->productRepository->search($criteria$context)->first();
  86.         $extensionData = new OciCartData();
  87.         if ($product) {
  88.             $cartDataArray $this->getCartDataArray($config$customerConfig$product);
  89.             $this->mapUnitField($cartDataArray$lineItem$config$customerConfig);
  90.             $extensionData->assign($cartDataArray);
  91.         }
  92.         $lineItem->addExtension(OciCartData::EXTENSION_NAME$extensionData);
  93.     }
  94.     private function getCartDataArray(array $config, array $customerConfig$product): array
  95.     {
  96.         $cartDataArray = [];
  97.         foreach (self::CONFIG_KEYS as $key) {
  98.             if($key === 'unitmapping') {
  99.                 continue;
  100.             }
  101.             // Use customer-specific configuration if available
  102.             $configValue $customerConfig[$key] ?? $config[$key] ?? '';
  103.             // Split the configValue into multiple attributes if it contains pipes
  104.             if (str_contains($configValue'|')) {
  105.                 $attributes explode('|'$configValue);
  106.                 foreach ($attributes as $attribute) {
  107.                     $data $this->fetchProductAttributeData($attribute$product);
  108.                     if ($data !== null) {
  109.                         $cartDataArray[$key] = $data;
  110.                         break; // Break the loop once data is found
  111.                     }
  112.                 }
  113.             } else {
  114.                 // Handle single attribute or static value
  115.                 $cartDataArray[$key] = $this->fetchProductAttributeData($configValue$product);
  116.             }
  117.             // If configuration of leadtime is an attribute
  118.             if ($key === 'leadtime') {
  119.                 $deliveryTime $product->getDeliveryTime();
  120.                 $minimumLeadTime $this->systemConfigService->get('OciPunchout.config.minimumLeadTime');
  121.                 $maximumLeadTime $this->systemConfigService->get('OciPunchout.config.maximumLeadTime');
  122.                 $threshold $this->systemConfigService->get('OciPunchout.config.leadtimeStockThreshold');
  123.                 if (str_starts_with($configValue'@')){
  124.                     $stock $cartDataArray[$key];
  125.                     if ($stock && is_numeric($stock) && $minimumLeadTime && $maximumLeadTime && $threshold !== null) {
  126.                         $cartDataArray[$key] = $stock $threshold $minimumLeadTime $maximumLeadTime;
  127.                     }
  128.                 }elseif ($deliveryTime && !is_numeric($cartDataArray[$key])) {
  129.                     $unit strtolower($deliveryTime->getUnit());
  130.                     $maxTime = (int)$deliveryTime->getMax();
  131.                     # If maximum time is 0, use $maximumLeadTime if set
  132.                     if ($maxTime === && $maximumLeadTime) {
  133.                         $maxTime = (int)$maximumLeadTime;
  134.                     }
  135.                     $conversionFactor = match($unit) {
  136.                         'hour' => 24,
  137.                         'day' => 1,
  138.                         'week' => 7,
  139.                         'month' => 30,
  140.                         'year' => 365,
  141.                         default => 1,
  142.                     };
  143.                     $cartDataArray[$key] = round($maxTime $conversionFactor);
  144.                 }
  145.             }
  146.         }
  147.         $cartDataArray['description'] = $product->getDescription();
  148.         return $cartDataArray;
  149.     }
  150.     private function fetchProductAttributeData($attribute$product)
  151.     {
  152.         if (str_starts_with($attribute'@')) {
  153.             $attribute str_replace('@'''$attribute);
  154.             if (str_starts_with($attribute'manufacturer.')) {
  155.                 return $this->fetchManufacturerData($attribute$product);
  156.             } elseif (str_starts_with($attribute'categories.')) {
  157.                 return $this->fetchCategoryData($attribute$product);
  158.             } else {
  159.                 return $this->fetchCustomFieldOrProductData($attribute$product);
  160.             }
  161.         } else {
  162.             return $attribute;  // Static value
  163.         }
  164.     }
  165.     private function fetchManufacturerData($attribute$product)
  166.     {
  167.         $manufacturer $product->getManufacturer();
  168.         if (!$manufacturer) {
  169.             return null;
  170.         }
  171.         $attribute str_replace('manufacturer.'''$attribute);
  172.         return $manufacturer->getVars()[$attribute] ?? $manufacturer->getCustomFields()[$attribute] ?? null;
  173.     }
  174.     private function fetchCategoryData($attribute$product)
  175.     {
  176.         $categories $product->getCategories();
  177.         if (!$categories) {
  178.             return null;
  179.         }
  180.         $attribute str_replace('categories.'''$attribute);
  181.         $firstCategory $categories->first();
  182.         return $firstCategory $firstCategory->getVars()[$attribute] ?? $firstCategory->getCustomFields()[$attribute] ?? null null;
  183.     }
  184.     private function fetchCustomFieldOrProductData($attribute$product)
  185.     {
  186.         $value $product->getCustomFields()[$attribute] ?? $product->getVars()[$attribute] ?? null;
  187.         if ($value === null && is_array($product->getTranslated())) {
  188.             $translatedCustomFields $product->getTranslated()['customFields'] ?? null;
  189.             if (is_array($translatedCustomFields) && isset($translatedCustomFields[$attribute])) {
  190.                 $value $translatedCustomFields[$attribute];
  191.             }
  192.         }
  193.         return $value;
  194.     }
  195.     private function mapUnitField(array &$cartDataArray$lineItem, array $config, array $customerConfig): void
  196.     {
  197.         // Check if customer has a specific unit mapping
  198.         $unitMapping $customerConfig['unitmapping'] ?? $config['unitmapping'] ?? null;
  199.         if ($unitMapping) {
  200.             $mapping json_decode($unitMappingtrue);
  201.             if (!is_array($mapping)) {
  202.                 $mapping $this->parseUnitMapping($unitMapping);
  203.             }
  204.             $normalizedMapping array_change_key_case($mappingCASE_LOWER);
  205.             $unit $cartDataArray['unit'] ?? $lineItem->getPayload()['unit'] ?? null;
  206.             if ($unit instanceof \Shopware\Core\System\Unit\UnitEntity) {
  207.                 $unitCode $unit->getShortCode() ?? $unit->getName() ?? null;
  208.             } else {
  209.                 $unitCode is_string($unit) ? $unit null;
  210.             }
  211.             if ($unitCode && isset($mapping[$unitCode])) {
  212.                 $normalizedUnit strtolower($unitCode);
  213.                 if (isset($normalizedMapping[$normalizedUnit])) {
  214.                     $cartDataArray['unit'] = $normalizedMapping[$normalizedUnit];
  215.                 }
  216.             }
  217.         }
  218.     }
  219.     private function parseUnitMapping(string $unitMapping): array
  220.     {
  221.         $mapping = [];
  222.         $lines explode("\n"trim($unitMapping));
  223.         $pattern '/\s*(.*?)\s*(?:=>|→|->|:|=|-|>)\s*(.*)\s*/i';
  224.         foreach ($lines as $line) {
  225.             if (preg_match($pattern$line$matches) && count($matches) === 3) {
  226.                 $fromUnit trim($matches[1]);
  227.                 $toUnit trim($matches[2]);
  228.                 if (!empty($fromUnit) && !empty($toUnit)) {
  229.                     $mapping[$fromUnit] = $toUnit;
  230.                 }
  231.             }
  232.         }
  233.         return $mapping;
  234.     }
  235. }