cancel
Showing results for 
Search instead for 
Did you mean: 

Error after upgrading to 2.3.0

   Did you know you can see the translated content as per your choice?

Translation is in progress. Please check again after few minutes.

Error after upgrading to 2.3.0

Hi I have updated the magento 2 and the website broke after the update the Error I am getting after trying to open the frontend: Screenshot 2019-01-15 at 11.10.26.png

I am using Claue Theme 1.7.8

Cant find anything on the google about this error. the code below is from my Data.php file. 

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Swatches\Helper;

use Magento\Catalog\Api\Data\ProductInterface as Product;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Helper\Image;
use Magento\Catalog\Model\Product as ModelProduct;
use Magento\Catalog\Model\Product\Image\UrlBuilder;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory as SwatchCollectionFactory;
use Magento\Swatches\Model\Swatch;
use Magento\Swatches\Model\SwatchAttributesProvider;
use Magento\Swatches\Model\SwatchAttributeType;

/**
 * Class Helper Data
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Data
{
    /**
     * When we init media gallery empty image types contain this value.
     */
    const EMPTY_IMAGE_VALUE = 'no_selection';

    /**
     * Default store ID
     */
    const DEFAULT_STORE_ID = 0;

    /**
     * @var CollectionFactory
     */
    protected $productCollectionFactory;

    /**
     * @var ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var SwatchCollectionFactory
     */
    protected $swatchCollectionFactory;

    /**
     * Product metadata pool
     *
     * @var \Magento\Framework\EntityManager\MetadataPool
     */
    private $metadataPool;

    /**
     * @var SwatchAttributesProvider
     */
    private $swatchAttributesProvider;

    /**
     * Data key which should populated to Attribute entity from "additional_data" field
     *
     * @var array
     */
    protected $eavAttributeAdditionalDataKeys = [
        Swatch::SWATCH_INPUT_TYPE_KEY,
        'update_product_preview_image',
        'use_product_image_for_swatch'
    ];

    /**
     * Serializer to/from JSON.
     *
     * @var Json
     */
    private $serializer;

    /**
     * @var SwatchAttributeType
     */
    private $swatchTypeChecker;

    /**
     * @var UrlBuilder
     */
    private $imageUrlBuilder;

    /**
     * @param CollectionFactory $productCollectionFactory
     * @param ProductRepositoryInterface $productRepository
     * @param StoreManagerInterface $storeManager
     * @param SwatchCollectionFactory $swatchCollectionFactory
     * @param UrlBuilder $urlBuilder
     * @param Json|null $serializer
     * @param SwatchAttributesProvider $swatchAttributesProvider
     * @param SwatchAttributeType|null $swatchTypeChecker
     */
    public function __construct(
        CollectionFactory $productCollectionFactory,
        ProductRepositoryInterface $productRepository,
        StoreManagerInterface $storeManager,
        SwatchCollectionFactory $swatchCollectionFactory,
        UrlBuilder $urlBuilder,
        Json $serializer = null,
        SwatchAttributesProvider $swatchAttributesProvider = null,
        SwatchAttributeType $swatchTypeChecker = null
    ) {
        $this->productCollectionFactory = $productCollectionFactory;
        $this->productRepository = $productRepository;
        $this->storeManager = $storeManager;
        $this->swatchCollectionFactory = $swatchCollectionFactory;
        $this->serializer = $serializer ?: ObjectManager::getInstance()->create(Json::class);
        $this->swatchAttributesProvider = $swatchAttributesProvider
            ?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class);
        $this->swatchTypeChecker = $swatchTypeChecker
            ?: ObjectManager::getInstance()->create(SwatchAttributeType::class);
        $this->imageUrlBuilder = $urlBuilder;
    }

    /**
     * @param Attribute $attribute
     * @return $this
     */
    public function assembleAdditionalDataEavAttribute(Attribute $attribute)
    {
        $initialAdditionalData = [];
        $additionalData = (string)$attribute->getData('additional_data');
        if (!empty($additionalData)) {
            $additionalData = $this->serializer->unserialize($additionalData);
            if (is_array($additionalData)) {
                $initialAdditionalData = $additionalData;
            }
        }

        $dataToAdd = [];
        foreach ($this->eavAttributeAdditionalDataKeys as $key) {
            $dataValue = $attribute->getData($key);
            if (null !== $dataValue) {
                $dataToAdd[$key] = $dataValue;
            }
        }
        $additionalData = array_merge($initialAdditionalData, $dataToAdd);
        $attribute->setData('additional_data', $this->serializer->serialize($additionalData));
        return $this;
    }

    /**
     * Check is media attribute available
     *
     * @param ModelProduct $product
     * @param string $attributeCode
     * @return bool
     */
    private function isMediaAvailable(ModelProduct $product, string $attributeCode): bool
    {
        $isAvailable = false;

        $mediaGallery = $product->getMediaGalleryEntries();
        foreach ($mediaGallery as $mediaEntry) {
            if (in_array($attributeCode, $mediaEntry->getTypes(), true)) {
                $isAvailable = !$mediaEntry->isDisabled();
                break;
            }
        }

        return $isAvailable;
    }

    /**
     * @param string $attributeCode swatch_image|image
     * @param ModelProduct $configurableProduct
     * @param array $requiredAttributes
     * @return bool|Product
     */
    private function loadFirstVariation($attributeCode, ModelProduct $configurableProduct, array $requiredAttributes)
    {
        if ($this->isProductHasSwatch($configurableProduct)) {
            $usedProducts = $configurableProduct->getTypeInstance()->getUsedProducts($configurableProduct);

            foreach ($usedProducts as $simpleProduct) {
                if (!array_diff_assoc($requiredAttributes, $simpleProduct->getData())
                    && $this->isMediaAvailable($simpleProduct, $attributeCode)
                ) {
                    return $simpleProduct;
                }
            }
        }

        return false;
    }

    /**
     * @param Product $configurableProduct
     * @param array $requiredAttributes
     * @return bool|Product
     */
    public function loadFirstVariationWithSwatchImage(Product $configurableProduct, array $requiredAttributes)
    {
        return $this->loadFirstVariation('swatch_image', $configurableProduct, $requiredAttributes);
    }

    /**
     * @param Product $configurableProduct
     * @param array $requiredAttributes
     * @return bool|Product
     */
    public function loadFirstVariationWithImage(Product $configurableProduct, array $requiredAttributes)
    {
        return $this->loadFirstVariation('image', $configurableProduct, $requiredAttributes);
    }

    /**
     * Load Variation Product using fallback
     *
     * @param Product $parentProduct
     * @param array $attributes
     * @return bool|Product
     */
    public function loadVariationByFallback(Product $parentProduct, array $attributes)
    {
        if (!$this->isProductHasSwatch($parentProduct)) {
            return false;
        }

        $productCollection = $this->productCollectionFactory->create();

        $productLinkedFiled = $this->getMetadataPool()
            ->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
            ->getLinkField();
        $parentId = $parentProduct->getData($productLinkedFiled);

        $this->addFilterByParent($productCollection, $parentId);

        $configurableAttributes = $this->getAttributesFromConfigurable($parentProduct);
        $allAttributesArray = [];
        foreach ($configurableAttributes as $attribute) {
            if (!empty($attribute['default_value'])) {
                $allAttributesArray[$attribute['attribute_code']] = $attribute['default_value'];
            }
        }

        $resultAttributesToFilter = array_merge(
            $attributes,
            array_diff_key($allAttributesArray, $attributes)
        );

        $this->addFilterByAttributes($productCollection, $resultAttributesToFilter);

        $variationProduct = $productCollection->getFirstItem();
        if ($variationProduct && $variationProduct->getId()) {
            return $this->productRepository->getById($variationProduct->getId());
        }

        return false;
    }

    /**
     * @param ProductCollection $productCollection
     * @param array $attributes
     * @return void
     */
    private function addFilterByAttributes(ProductCollection $productCollection, array $attributes)
    {
        foreach ($attributes as $code => $option) {
            $productCollection->addAttributeToFilter($code, ['eq' => $option]);
        }
    }

    /**
     * @param ProductCollection $productCollection
     * @param integer $parentId
     * @return void
     */
    private function addFilterByParent(ProductCollection $productCollection, $parentId)
    {
        $tableProductRelation = $productCollection->getTable('catalog_product_relation');
        $productCollection
            ->getSelect()
            ->join(
                ['pr' => $tableProductRelation],
                'e.entity_id = pr.child_id'
            )
            ->where('pr.parent_id = ?', $parentId);
    }

    /**
     * Method getting full media gallery for current Product
     * Array structure: [
     *  ['image'] => 'http://url/pub/media/catalog/product/2/0/blabla.jpg',
     *  ['mediaGallery'] => [
     *      galleryImageId1 => simpleProductImage1.jpg,
     *      galleryImageId2 => simpleProductImage2.jpg,
     *      ...,
     *      ]
     * ]
     * @param ModelProduct $product
     * @return array
     */
    public function getProductMediaGallery(ModelProduct $product)
    {
        $baseImage = null;
        $gallery = [];

        $mediaGallery = $product->getMediaGalleryEntries();
        foreach ($mediaGallery as $mediaEntry) {
            if ($mediaEntry->isDisabled()) {
                continue;
            }

            if (in_array('image', $mediaEntry->getTypes(), true) || !$baseImage) {
                $baseImage = $mediaEntry->getFile();
            }

            $gallery[$mediaEntry->getId()] = $this->getAllSizeImages($mediaEntry->getFile());
        }

        if (!$baseImage) {
            return [];
        }

        $resultGallery = $this->getAllSizeImages($baseImage);
        $resultGallery['gallery'] = $gallery;

        return $resultGallery;
    }

    /**
     * @param string $imageFile
     * @return array
     */
    private function getAllSizeImages($imageFile)
    {
        return [
            'large' => $this->imageUrlBuilder->getUrl($imageFile, 'product_swatch_image_large'),
            'medium' => $this->imageUrlBuilder->getUrl($imageFile, 'product_swatch_image_medium'),
            'small' => $this->imageUrlBuilder->getUrl($imageFile, 'product_swatch_image_small')
        ];
    }

    /**
     * Retrieve collection of Swatch attributes
     *
     * @param Product $product
     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute[]
     */
    private function getSwatchAttributes(Product $product)
    {
        $swatchAttributes = $this->swatchAttributesProvider->provide($product);
        return $swatchAttributes;
    }

    /**
     * Retrieve collection of Eav Attributes from Configurable product
     *
     * @param Product $product
     * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute[]
     */
    public function getAttributesFromConfigurable(Product $product)
    {
        $result = [];
        $typeInstance = $product->getTypeInstance();
        if ($typeInstance instanceof Configurable) {
            $configurableAttributes = $typeInstance->getConfigurableAttributes($product);
            /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $configurableAttribute */
            foreach ($configurableAttributes as $configurableAttribute) {
                /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
                $attribute = $configurableAttribute->getProductAttribute();
                $result[] = $attribute;
            }
        }
        return $result;
    }

    /**
     * Retrieve all visible Swatch attributes for current product.
     *
     * @param Product $product
     * @return array
     */
    public function getSwatchAttributesAsArray(Product $product)
    {
        $result = [];
        $swatchAttributes = $this->getSwatchAttributes($product);
        foreach ($swatchAttributes as $swatchAttribute) {
            $swatchAttribute->setStoreId($this->storeManager->getStore()->getId());
            $attributeData = $swatchAttribute->getData();
            foreach ($swatchAttribute->getSource()->getAllOptions(false) as $option) {
                $attributeData['options'][$option['value']] = $option['label'];
            }
            $result[$attributeData['attribute_id']] = $attributeData;
        }

        return $result;
    }

    /**
     * @var array
     */
    private $swatchesCache = [];

    /**
     * Get swatch options by option id's according to fallback logic
     *
     * @param array $optionIds
     * @return array
     */
    public function getSwatchesByOptionsId(array $optionIds)
    {
        $swatches = $this->getCachedSwatches($optionIds);

        if (count($swatches) !== count($optionIds)) {
            $swatchOptionIds = array_diff($optionIds, array_keys($swatches));
            /** @var \Magento\Swatches\Model\ResourceModel\Swatch\Collection $swatchCollection */
            $swatchCollection = $this->swatchCollectionFactory->create();
            $swatchCollection->addFilterByOptionsIds($swatchOptionIds);

            $swatches = [];
            $fallbackValues = [];
            $currentStoreId = $this->storeManager->getStore()->getId();
            foreach ($swatchCollection as $item) {
                if ($item['type'] != Swatch::SWATCH_TYPE_TEXTUAL) {
                    $swatches[$item['option_id']] = $item->getData();
                } elseif ($item['store_id'] == $currentStoreId && $item['value'] != '') {
                    $fallbackValues[$item['option_id']][$currentStoreId] = $item->getData();
                } elseif ($item['store_id'] == self::DEFAULT_STORE_ID) {
                    $fallbackValues[$item['option_id']][self::DEFAULT_STORE_ID] = $item->getData();
                }
            }

            if (!empty($fallbackValues)) {
                $swatches = $this->addFallbackOptions($fallbackValues, $swatches);
            }
            $this->setCachedSwatches($swatchOptionIds, $swatches);
        }

        return array_filter($this->getCachedSwatches($optionIds));
    }

    /**
     * Get cached swatches
     *
     * @param array $optionIds
     * @return array
     */
    private function getCachedSwatches(array $optionIds)
    {
        return array_intersect_key($this->swatchesCache, array_combine($optionIds, $optionIds));
    }

    /**
     * Cache swatch. If no swathes found for specific option id - set null for prevent double call
     *
     * @param array $optionIds
     * @param array $swatches
     * @return void
     */
    private function setCachedSwatches(array $optionIds, array $swatches)
    {
        foreach ($optionIds as $optionId) {
            $this->swatchesCache[$optionId] = isset($swatches[$optionId]) ? $swatches[$optionId] : null;
        }
    }

    /**
     * @param array $fallbackValues
     * @param array $swatches
     * @return array
     */
    private function addFallbackOptions(array $fallbackValues, array $swatches)
    {
        $currentStoreId = $this->storeManager->getStore()->getId();
        foreach ($fallbackValues as $optionId => $optionsArray) {
            if (isset($optionsArray[$currentStoreId]['type'], $swatches[$optionId]['type'])
                && $swatches[$optionId]['type'] === $optionsArray[$currentStoreId]['type']
            ) {
                $swatches[$optionId] = $optionsArray[$currentStoreId];
            } elseif (isset($optionsArray[self::DEFAULT_STORE_ID])) {
                $swatches[$optionId] = $optionsArray[self::DEFAULT_STORE_ID];
            }
        }

        return $swatches;
    }

    /**
     * Check if the Product has Swatch attributes
     *
     * @param Product $product
     * @return bool
     */
    public function isProductHasSwatch(Product $product)
    {
        return !empty($this->getSwatchAttributes($product));
    }

    /**
     * Check if an attribute is Swatch
     *
     * @param Attribute $attribute
     * @return bool
     */
    public function isSwatchAttribute(Attribute $attribute)
    {
        return $this->swatchTypeChecker->isSwatchAttribute($attribute);
    }

    /**
     * Is attribute Visual Swatch
     *
     * @param Attribute $attribute
     * @return bool
     */
    public function isVisualSwatch(Attribute $attribute)
    {
        return $this->swatchTypeChecker->isVisualSwatch($attribute);
    }

    /**
     * Is attribute Textual Swatch
     *
     * @param Attribute $attribute
     * @return bool
     */
    public function isTextSwatch(Attribute $attribute)
    {
        return $this->swatchTypeChecker->isTextSwatch($attribute);
    }

    /**
     * Get product metadata pool.
     *
     * @return \Magento\Framework\EntityManager\MetadataPool
     * @deprecared
     */
    protected function getMetadataPool()
    {
        if (!$this->metadataPool) {
            $this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
                ->get(\Magento\Framework\EntityManager\MetadataPool::class);
        }
        return $this->metadataPool;
    }
}

 

2 REPLIES 2

Re: Error after upgrading to 2.3.0

I may be have a similar problem. Migrate 1.9.4 site to 2.3.0

php bin/magento indexer:status

[...]

| Catalog Search       | Reindex required | Schedule  idle (835 in backlog)

 [...]

[...]

php bin/magento indexer:reindex

[...]

Catalog Search indexer process unknown error:

Item (Magento\Eav\Model\Entity\Attribute\Option) with the same ID "35" already exists.

 

1.

Where to find "Magento\Eav\Model\Entity\Attribute\Option"

2. 

If database duplicate; - what table?

 

Possible solution?

Is it safe to delete tables after "catalog search_fulltext_cl" ??

catalog search_fulltext_scope1

catalog search_fulltext_scope2

[...]

catalog search_fulltext_scope10

 

Found this in another forum - is this something for me?

ALTER TABLE `xxxx`.`catalogsearch_fulltext_scope1` DROP PRIMARY KEY, ADD PRIMARY KEY (`entity_id`, `attribute_id`) USING BTREE;
ALTER TABLE `xxxx`.`catalogsearch_fulltext_scope1` DROP INDEX `FTI_FULLTEXT_DATA_INDEX`, ADD FULLTEXT `FTI_FULLTEXT_DATA_INDEX` (`data_index`);
ALTER TABLE `xxxx`.`catalog_eav_attribute` DROP PRIMARY KEY, ADD PRIMARY KEY (`attribute_id`) USING BTREE;
ALTER TABLE `xxxx`.`catalog_eav_attribute` DROP INDEX `CATALOG_EAV_ATTRIBUTE_USED_IN_PRODUCT_LISTING`, ADD INDEX `CATALOG_EAV_ATTRIBUTE_USED_IN_PRODUCT_LISTING` (`used_in_product_listing`) USING BTREE;
ALTER TABLE `xxxx`.`catalog_eav_attribute` DROP INDEX `CATALOG_EAV_ATTRIBUTE_USED_FOR_SORT_BY`, ADD INDEX `CATALOG_EAV_ATTRIBUTE_USED_FOR_SORT_BY` (`used_for_sort_by`) USING BTREE;

Re: Error after upgrading to 2.3.0

I too had this problem after installing Claue Theme 1.7.8 at Magento 2.3.x.

Claue Theme has released a Patch for Magento 2.3.x, if you follow readme for this release, it will solve the problem.

But make sure that you have applied patch for Magento 2.2+ before applying patch for Magento 2.3+