Last active
December 7, 2020 17:20
-
-
Save dfelton/cca78ea6068de78babfd82ab6cd486ef to your computer and use it in GitHub Desktop.
Magento Delete All Products
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace VendorName\ModuleName\Console\Command; | |
use Magento\Catalog\Model\Product; | |
use Magento\Catalog\Model\ProductFactory; | |
use Magento\Catalog\Model\ResourceModel\Product as ProductResource; | |
use Magento\Framework\App\State; | |
use Magento\Framework\Filesystem\Io\File as IoFile; | |
use Symfony\Component\Console\Input\InputInterface; | |
use Symfony\Component\Console\Input\InputOption; | |
use Symfony\Component\Console\Output\OutputInterface; | |
class DeleteAllProducts extends \Symfony\Component\Console\Command\Command | |
{ | |
private const BATCH_SIZE_DEFAULT = 100; | |
private const BATCH_SIZE_MIN = 1; | |
private const BATCH_SIZE_MAX = 1000; | |
// Presence of this file kills the script. | |
private const KILL_SWITCH_FILE = '/tmp/kill-product-delete-all'; | |
private IoFile $io; | |
private ProductFactory $productFactory; | |
private ProductResource $productResource; | |
private State $state; | |
public function __construct( | |
IoFile $io, | |
ProductFactory $productFactory, | |
ProductResource $productResource, | |
State $state | |
) | |
{ | |
$this->io = $io; | |
$this->productFactory = $productFactory; | |
$this->productResource = $productResource; | |
$this->state = $state; | |
parent::__construct(); | |
} | |
protected function configure(): void | |
{ | |
$this->setName('catalog:product:delete-all'); | |
$this->addOption( | |
'batchSize', | |
'b', | |
InputOption::VALUE_OPTIONAL, | |
(string) __( | |
'Batch Size (%1 - %2); Default: %3', | |
self::BATCH_SIZE_MIN, | |
self::BATCH_SIZE_MAX, | |
self::BATCH_SIZE_DEFAULT | |
), | |
); | |
} | |
protected function execute(InputInterface $input, OutputInterface $output): int | |
{ | |
$exitCode = 0; | |
$this->state->emulateAreaCode( | |
'adminhtml', | |
function (int $exitCode, InputInterface $input, OutputInterface $output) | |
{ | |
$exitCode = $this->deleteProducts($input, $output); | |
}, | |
[$exitCode, $input, $output] | |
); | |
return $exitCode; | |
} | |
private function deleteProducts(InputInterface $input, OutputInterface $output): int | |
{ | |
$remaining = $this->getRemainingSkuCount(); | |
/** @var Product $product */ | |
foreach ($this->getBatch($input) as $product) { | |
try { | |
$this->productResource->delete($product); | |
$remaining--; | |
$output->writeln((string) __( | |
'SKU "%1" deleted. %2 remaining SKUs to go', | |
$product->getSku(), | |
$remaining | |
)); | |
} catch (\Exception $e) { | |
$output->writeln("Error deleting SKU: {$product->getSku()}"); | |
$output->writeln($e->getMessage()); | |
$output->writeln($e->getTraceAsString()); | |
return 1; | |
} | |
} | |
if ($this->killSwitch()) { | |
$output->writeln('Kill Switch Detected. Exiting'); | |
return 1; | |
} | |
$output->writeln((string) __('Batch complete. "%1" remaining SKUs', $remaining)); | |
return 0; | |
} | |
private function killSwitch(): bool | |
{ | |
return (bool) $this->io->fileExists('/tmp/kill-product-delete-all'); | |
} | |
private function getRemainingSkuCount(): int | |
{ | |
$c = $this->productResource->getConnection(); | |
return (int) $c->fetchOne($c->select() | |
->from($c->getTableName('catalog_product_entity'), 'count(entity_id)')); | |
} | |
private function getBatch(InputInterface $input): \Generator | |
{ | |
$c = $this->productResource->getConnection(); | |
$sql = $c->select() | |
->from($c->getTableName('catalog_product_entity'), ['entity_id', 'sku']) | |
->limit($this->getBatchSize($input)); | |
foreach ($c->fetchAll($sql) as $data) { | |
if ($this->killSwitch()) { | |
break; | |
} | |
yield $this->productFactory->create(['data' => $data]); | |
} | |
} | |
private function getBatchSize(InputInterface $input): int | |
{ | |
$size = (int) $input->getOption('batchSize'); | |
if ($size < self::BATCH_SIZE_MIN || $size > self::BATCH_SIZE_MAX) { | |
$size = self::BATCH_SIZE_DEFAULT; | |
} | |
return $this->killSwitch() ? 0 : $size; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Delete products in a loop until all are gone, accepting default batch size (50). Pass "-b 123" to change batch size. | |
DONE=0; while [ $DONE -eq 0 ]; do ./bin/magento catalog:product:delete-all ; DONE=$?; done; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment