36 private $tableMetaDataClass = [
37 'catalog_category_entity_datetime' => CategoryInterface::class,
38 'catalog_category_entity_decimal' => CategoryInterface::class,
39 'catalog_category_entity_int' => CategoryInterface::class,
40 'catalog_category_entity_text' => CategoryInterface::class,
41 'catalog_category_entity_varchar' => CategoryInterface::class,
43 'catalog_product_entity_datetime' => ProductInterface::class,
44 'catalog_product_entity_decimal' => ProductInterface::class,
45 'catalog_product_entity_int' => ProductInterface::class,
46 'catalog_product_entity_text' => ProductInterface::class,
47 'catalog_product_entity_varchar' => ProductInterface::class,
62 private $groupedStoreViews = [];
67 private $processedAttributeValues = [];
72 private $batchQueryGenerator;
77 private $metaDataPool;
82 private $linkFields = [];
87 private $moduleDataSetup;
100 $this->batchQueryGenerator = $batchQueryGenerator;
101 $this->metaDataPool = $metadataPool;
102 $this->moduleDataSetup = $moduleDataSetup;
110 foreach (array_keys($this->tableMetaDataClass) as
$tableName) {
121 foreach ($this->fetchAttributeValues(
$tableName) as $attributeValueItems) {
122 $this->processAttributeValues($attributeValueItems,
$tableName);
132 private function processAttributeValues(array $attributeValueItems,
$tableName)
134 $this->resetProcessedAttributeValues();
136 foreach ($attributeValueItems as $attributeValueItem) {
137 if ($this->isProcessedAttributeValue($attributeValueItem,
$tableName)) {
141 $insertions = $this->generateAttributeValueInsertions($attributeValueItem,
$tableName);
142 if (!empty($insertions)) {
143 $this->executeInsertions($insertions,
$tableName);
146 $this->markAttributeValueProcessed($attributeValueItem,
$tableName);
157 private function fetchAttributeValues(
$tableName)
160 $multipleStoresInWebsite = array_values(
162 array_filter($this->getGroupedStoreViews(),
function ($storeViews) {
163 return is_array($storeViews) && count($storeViews) > 1;
170 if (count($multipleStoresInWebsite) < 1) {
174 $connection = $this->moduleDataSetup->getConnection();
175 $batchSelectIterator = $this->batchQueryGenerator->generate(
180 [
'cpei' => $this->moduleDataSetup->getTable(
$tableName)],
185 'cea' => $this->moduleDataSetup->getTable(
'catalog_eav_attribute'),
187 'cpei.attribute_id = cea.attribute_id',
192 'st' => $this->moduleDataSetup->getTable(
'store'),
194 'st.store_id = cpei.store_id',
199 self::ATTRIBUTE_WEBSITE
202 'cpei.store_id IN (?)',
203 $multipleStoresInWebsite
208 foreach ($batchSelectIterator as
$select) {
216 private function getGroupedStoreViews()
218 if (!empty($this->groupedStoreViews)) {
219 return $this->groupedStoreViews;
222 $connection = $this->moduleDataSetup->getConnection();
226 $this->moduleDataSetup->getTable(
'store'),
232 $this->groupedStoreViews = [];
234 foreach ($storeViews as $storeView) {
235 if ($storeView[
'store_id'] != 0) {
236 $this->groupedStoreViews[$storeView[
'website_id']][] = $storeView[
'store_id'];
240 return $this->groupedStoreViews;
248 private function isProcessedAttributeValue(array $attributeValue,
$tableName)
251 $this->getAttributeValueKey(
252 $attributeValue[$this->getTableLinkField(
$tableName)],
253 $attributeValue[
'attribute_id'],
254 $attributeValue[
'website_id']
256 $this->processedAttributeValues
264 private function resetProcessedAttributeValues()
266 $this->processedAttributeValues = [];
274 private function markAttributeValueProcessed(array $attributeValue,
$tableName)
276 $this->processedAttributeValues[] = $this->getAttributeValueKey(
277 $attributeValue[$this->getTableLinkField(
$tableName)],
278 $attributeValue[
'attribute_id'],
279 $attributeValue[
'website_id']
289 private function getAttributeValueKey($entityId, $attributeId,
$websiteId)
292 self::MASK_ATTRIBUTE_VALUE,
304 private function generateAttributeValueInsertions(
305 array $attributeValue,
308 $groupedStoreViews = $this->getGroupedStoreViews();
309 if (empty($groupedStoreViews[$attributeValue[
'website_id']])) {
313 $currentStoreViewIds = $groupedStoreViews[$attributeValue[
'website_id']];
316 foreach ($currentStoreViewIds as
$index => $storeViewId) {
318 ':attribute_id' .
$index => $attributeValue[
'attribute_id'],
319 ':store_id' .
$index => $storeViewId,
320 ':entity_id' .
$index => $attributeValue[$this->getTableLinkField(
$tableName)],
321 ':value' .
$index => $attributeValue[
'value'],
333 private function executeInsertions(array $insertions,
$tableName)
337 %s(attribute_id, store_id, %s, `value`) 340 ON duplicate KEY UPDATE `value` = VALUES(`value`)',
343 $this->prepareInsertValuesStatement($insertions)
346 $this->moduleDataSetup->getConnection()->query($rawQuery, $this->getPlaceholderValues($insertions));
355 private function getPlaceholderValues(array $insertions)
357 $placeholderValues = [];
358 foreach ($insertions as $insertion) {
359 $placeholderValues = array_merge(
365 return $placeholderValues;
374 private function prepareInsertValuesStatement(array $insertions)
378 foreach ($insertions as $insertion) {
379 $statement .= sprintf(
'(%s),', implode(
',', array_keys($insertion)));
382 return rtrim($statement,
',');
390 private function getTableLinkField(
$tableName)
392 if (!isset($this->tableMetaDataClass[
$tableName])) {
393 throw new LocalizedException(
395 'Specified table: %s is not defined in tables list',
402 $this->linkFields[
$tableName] = $this->metaDataPool
403 ->getMetadata($this->tableMetaDataClass[
$tableName])
416 UpgradeWidgetData::class,
const GLOBAL_STORE_VIEW_ID
const MASK_ATTRIBUTE_VALUE
__construct(Generator $batchQueryGenerator, MetadataPool $metadataPool, ModuleDataSetupInterface $moduleDataSetup)