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:
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; } }
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;
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+