Feat: Updating ShopifyExportImporter and WipeCatalogCommand to handle images
This commit is contained in:
@@ -124,30 +124,49 @@ class WipeCatalogCommand extends Command
|
||||
* same way regardless. media_variant and product_option_value_
|
||||
* product_variant DO cascade at the DB level (see their own
|
||||
* migrations), so deleting the variant itself is enough for those two.
|
||||
*
|
||||
* Deliberately NOT chunkById() — that re-queries "id > lastSeenId"
|
||||
* every iteration, but deleting rows inside the loop shrinks the
|
||||
* table out from under it: any product whose id fell in a range
|
||||
* chunkById() had already stepped past could be silently skipped and
|
||||
* never actually deleted at all. Caught in practice — the first real
|
||||
* run of this command left orphaned Media rows (Spatie's own
|
||||
* deleteAllMedia(), fired from Product's `deleting` event, never ran
|
||||
* for the skipped products) whose 'image' ImportMapping rows then
|
||||
* caused a LATER Shopify re-import to silently reuse those now-
|
||||
* orphaned Media objects instead of importing fresh ones — see
|
||||
* MigrateImport\Shopify\ShopifyExportImporter::resolveOrImportImage()'s
|
||||
* own docblock for that half of the same incident. Always re-querying
|
||||
* the first N remaining rows (never advancing an id cursor) guarantees
|
||||
* every product is actually visited exactly once, however many are
|
||||
* deleted out from under the query as it goes.
|
||||
*/
|
||||
private function wipe(): void
|
||||
{
|
||||
ImportMapping::where('source_type', 'product')->delete();
|
||||
ImportMapping::where('source_type', 'variant')->delete();
|
||||
ImportMapping::whereIn('source_type', ['product', 'variant', 'image'])->delete();
|
||||
|
||||
// Model-by-model, not a bulk query — see class docblock on why
|
||||
// this must go through Eloquent for Spatie's media cleanup to
|
||||
// fire on both Product and ProductVariant.
|
||||
Product::with(['variants', 'associations', 'inverseAssociations'])
|
||||
->chunkById(100, function ($products) {
|
||||
foreach ($products as $product) {
|
||||
$product->associations()->delete();
|
||||
$product->inverseAssociations()->delete();
|
||||
$product->productOptions()->detach();
|
||||
while (true) {
|
||||
$products = Product::with(['variants', 'associations', 'inverseAssociations'])
|
||||
->limit(100)
|
||||
->get();
|
||||
|
||||
foreach ($product->variants as $variant) {
|
||||
$variant->prices()->delete();
|
||||
$variant->delete();
|
||||
}
|
||||
if ($products->isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$product->delete();
|
||||
foreach ($products as $product) {
|
||||
$product->associations()->delete();
|
||||
$product->inverseAssociations()->delete();
|
||||
$product->productOptions()->detach();
|
||||
|
||||
foreach ($product->variants as $variant) {
|
||||
$variant->prices()->delete();
|
||||
$variant->delete();
|
||||
}
|
||||
});
|
||||
|
||||
$product->delete();
|
||||
}
|
||||
}
|
||||
|
||||
Product::removeAllFromSearch();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user