diff --git a/src/Plugin.php b/src/Plugin.php index 1894ce421d..eacc59985a 100755 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -254,7 +254,7 @@ public static function editions(): array /** * @inheritDoc */ - public string $schemaVersion = '5.1.0.2'; + public string $schemaVersion = '5.1.0.3'; /** * @inheritdoc diff --git a/src/elements/Variant.php b/src/elements/Variant.php index e84c2a6593..9758491a38 100755 --- a/src/elements/Variant.php +++ b/src/elements/Variant.php @@ -888,6 +888,20 @@ public static function gqlScopesByContext(mixed $context): array return ['productTypes.' . $context->uid]; } + /** + * @inheritdoc + */ + public function getSupportedSites(): array + { + $owner = $this->getOwner(); + + if (!$owner) { + return [Craft::$app->getSites()->getPrimarySite()->id]; + } + + return $this->getOwner()->getSupportedSites(); + } + /** * @inheritdoc * @throws Exception diff --git a/src/migrations/m240923_132625_remove_orphaned_variants_sites.php b/src/migrations/m240923_132625_remove_orphaned_variants_sites.php new file mode 100644 index 0000000000..ce7bac534d --- /dev/null +++ b/src/migrations/m240923_132625_remove_orphaned_variants_sites.php @@ -0,0 +1,63 @@ +select(['elementId', 'siteId']) + ->from('{{%elements_sites}}' . ' es') + ->innerJoin('{{%commerce_products}}' . ' p', '[[es.elementId]] = [[p.id]]') + ->collect(); + + // Group them by product ID + $siteIdsByProductId = $allProductsSites->groupBy('elementId')->map(function($row) { + return collect($row)->pluck('siteId')->toArray(); + } + ); + + // Find all existing combinations of variant and site IDs + $allVariantsSites = (new Query()) + ->select(['es.id', 'elementId', 'siteId', 'primaryOwnerId']) + ->from('{{%elements_sites}}' . ' es') + ->innerJoin('{{%commerce_variants}}' . ' v', '[[es.elementId]] = [[v.id]]') + ->collect(); + + // Find all variants that are not associated with any of their product's sites + $orphanedVariantsSites = array_values($allVariantsSites->filter(function($row) use ($siteIdsByProductId) { + return !in_array($row['siteId'], $siteIdsByProductId[$row['primaryOwnerId']]); + })->map(fn($row) => $row['id'])->toArray()); + + if (empty($orphanedVariantsSites)) { + return true; + } + + // Bulk delete the orphaned variants' site rows (if any) 1000 at a time + foreach (array_chunk($orphanedVariantsSites, 1000) as $chunk) { + $this->delete('{{%elements_sites}}', ['id' => $chunk]); + } + + return true; + } + + /** + * @inheritdoc + */ + public function safeDown(): bool + { + echo "m240923_132625_remove_orphaned_variants_sites cannot be reverted.\n"; + return false; + } +}