Search code examples
apishopwareshopware6

Shopware6: setExtensions() bug


I have used an event Subscriber for Product. Using Store-API I want to search for products. So I get an Error when I send this API request :

POST : http://localhost/store-api/search?search=Logo

Error :

            "code": "0",
            "status": "500",
            "title": "Internal Server Error",
            "detail": "Shopware\\Core\\Framework\\Struct\\Struct::getExtension(): Return value must be of type ?Shopware\\Core\\Framework\\Struct\\Struct, array returned",
            "meta": {
                "trace": [
                    {
                        "file": "/var/www/html/vendor/shopware/core/System/SalesChannel/Api/StructEncoder.php",
                        "line": 254,
                        "function": "getExtension",
                        "class": "Shopware\\Core\\Framework\\Struct\\Struct",
                        "type": "->",
                        "args": [
                            "mediaLogos"
                        ]
                    }
                  ]

Subscriber File:

class ProductSubscriber implements EventSubscriberInterface
{    
   private EntityRepositoryInterface $productRepository;
   private EntityRepositoryInterface $mediaRepository;
   public function __construct(
        EntityRepositoryInterface $productRepository,
        EntityRepositoryInterface $mediaRepository
    ) {
        $this->productRepository = $productRepository;
        $this->mediaRepository = $mediaRepository;
    }
    public static function getSubscribedEvents(): array
    {
        return [
            'sales_channel.' . ProductEvents::PRODUCT_LOADED_EVENT => 'salesChannelLoaded',
        ];
    }

    public function salesChannelLoaded(SalesChannelEntityLoadedEvent $event): void
    {
        /** @var SalesChannelProductEntity $product */
        $products = $event->getEntities();

        foreach ($products as $product) {
            $id = $product->getParentId() ? $product->getParentId() : $product->getId();
            $criteria = new Criteria([$id]);
            $criteria->addAssociation('medialogos');
            
            $productEntity = $this->productRepository->search(
                                $criteria, 
                                \Shopware\Core\Framework\Context::createDefaultContext()
                            )->first();
            $prodExtensions = $productEntity->getExtensions();
            if (isset($prodExtensions['medialogos']) && !empty($prodExtensions['medialogos'])) {
                $mediaLogos = $prodExtensions['medialogos']->getElements();
                foreach ($mediaLogos as &$mLogo) {
                    if ($mLogo->logo) {
                        $mediaEntity = $this->mediaRepository->search(
                            (new Criteria([$mLogo->logo])), 
                            \Shopware\Core\Framework\Context::createDefaultContext()
                        )->first();
                        $mLogo->logo = $mediaEntity;
                    }
                }
                $prodExtensions['medialogos'] = $mediaLogos;
                $product->setExtensions($prodExtensions);
            }
        }
    }
}

How can I solve this bug ? Could you help me please ?


Solution

  • The argument for setExtensions should be Struct[] but you are giving array[]. You want to wrap $mediaLogos in an ArrayStruct.

    $prodExtensions['medialogos'] = new ArrayStruct($mediaLogos);
    

    Alternatively you might not even want to call getElements on $prodExtensions['medialogos'] since I assume it's an instance of EntityCollection which is in turn a subclass of Struct that also implements IteratorAggregate.

    So you could simply iterate like that and wouldn't even have to set the extension again:

    foreach ($prodExtensions['medialogos'] as $mLogo) {
        // ...
        $mLogo->logo = $mediaEntity;
        // ...
    }