From 097d473ac74b7fc866e5831291eb8035fb135e11 Mon Sep 17 00:00:00 2001 From: Roshyo Date: Fri, 13 May 2022 12:24:53 +0200 Subject: [PATCH 1/5] Add a command to delete old gift cards --- composer.json | 4 +- src/Command/Cli/DeleteOldGiftCardsCommand.php | 88 +++++++++++++++++++ src/Doctrine/ORM/GiftCardRepository.php | 10 +++ .../GiftCardRepositoryInterface.php | 2 + src/Resources/config/services.xml | 1 + src/Resources/config/services/commands.xml | 16 ++++ 6 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/Command/Cli/DeleteOldGiftCardsCommand.php create mode 100644 src/Resources/config/services/commands.xml diff --git a/composer.json b/composer.json index df61039f..e0347462 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,6 @@ "phpunit/phpunit": "^9.5", "psalm/plugin-phpunit": "^0.16.0", "psalm/plugin-symfony": "^2.1", - "roave/security-advisories": "dev-latest", "setono/code-quality-pack": "^2.1", "setono/sylius-behat-pack": "^0.1", "setono/sylius-catalog-promotion-plugin": "^0.2.0", @@ -69,7 +68,8 @@ "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": false, "ergebnis/composer-normalize": true, - "symfony/thanks": true + "symfony/thanks": true, + "composer/package-versions-deprecated": true }, "sort-packages": true }, diff --git a/src/Command/Cli/DeleteOldGiftCardsCommand.php b/src/Command/Cli/DeleteOldGiftCardsCommand.php new file mode 100644 index 00000000..de0ad863 --- /dev/null +++ b/src/Command/Cli/DeleteOldGiftCardsCommand.php @@ -0,0 +1,88 @@ +giftCardRepository = $giftCardRepository; + $this->giftCardManager = $giftCardManager; + } + + protected function configure(): void + { + $this->setDescription('Deletes gift cards older than the provided date.'); + $this->addOption( + 'date', + null, + InputOption::VALUE_OPTIONAL, + 'The date to delete gift cards older than.', + null + ); + $this->addOption( + 'period', + null, + InputOption::VALUE_OPTIONAL, + 'The period to delete gift cards older than.', + null + ); + } + + public function run(InputInterface $input, OutputInterface $output): int + { + $date = $input->getOption('date'); + $period = $input->getOption('period'); + + if (null === $date && null === $period) { + $output->writeln('You must provide a date or a period.'); + + return 0; + } + + if (null !== $date && null !== $period) { + $output->writeln('You must provide a date or a period, not both.'); + + return 0; + } + + try { + $thresholdDate = new \DateTimeImmutable($date ?? $period); + } catch (\Exception $e) { + $output->writeln('The provided date or period is not valid.'); + + return 0; + } + + $giftCards = $this->giftCardRepository->findCreatedBefore($thresholdDate); + foreach ($giftCards as $giftCard) { + $this->giftCardManager->remove($giftCard); + } + + $this->giftCardManager->flush(); + + $output->writeln(\sprintf('Deleted %d gift cards.', \count($giftCards))); + + return 1; + } +} diff --git a/src/Doctrine/ORM/GiftCardRepository.php b/src/Doctrine/ORM/GiftCardRepository.php index 9a1cdf16..65ea576d 100644 --- a/src/Doctrine/ORM/GiftCardRepository.php +++ b/src/Doctrine/ORM/GiftCardRepository.php @@ -69,4 +69,14 @@ public function createAccountListQueryBuilder(CustomerInterface $customer): Quer return $qb; } + + public function findCreatedBefore(\DateTimeInterface $date): array + { + $qb = $this->createQueryBuilder('gc'); + + $qb->andWhere('gc.createdAt < :date'); + $qb->setParameter('date', $date->format('Y-m-d H:i:s')); + + return $qb->getQuery()->getResult(); + } } diff --git a/src/Repository/GiftCardRepositoryInterface.php b/src/Repository/GiftCardRepositoryInterface.php index 978eaf01..dd2cb0c0 100644 --- a/src/Repository/GiftCardRepositoryInterface.php +++ b/src/Repository/GiftCardRepositoryInterface.php @@ -27,4 +27,6 @@ public function findOneByOrderItemUnit(OrderItemUnitInterface $orderItemUnit): ? public function findEnabled(): array; public function createAccountListQueryBuilder(CustomerInterface $customer): QueryBuilder; + + public function findCreatedBefore(\DateTimeInterface $date): array; } diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 5ee4542a..16942698 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + diff --git a/src/Resources/config/services/commands.xml b/src/Resources/config/services/commands.xml new file mode 100644 index 00000000..cbedeac0 --- /dev/null +++ b/src/Resources/config/services/commands.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + From 6b6ef8eb5fa36d763a6f6e73604025210ebd8b2b Mon Sep 17 00:00:00 2001 From: Roshyo Date: Fri, 13 May 2022 12:33:34 +0200 Subject: [PATCH 2/5] Fix documentation and use real date period --- src/Command/Cli/DeleteOldGiftCardsCommand.php | 17 ++++++++++++++++- src/Doctrine/ORM/GiftCardRepository.php | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Command/Cli/DeleteOldGiftCardsCommand.php b/src/Command/Cli/DeleteOldGiftCardsCommand.php index de0ad863..231d8cba 100644 --- a/src/Command/Cli/DeleteOldGiftCardsCommand.php +++ b/src/Command/Cli/DeleteOldGiftCardsCommand.php @@ -33,6 +33,16 @@ public function __construct( protected function configure(): void { $this->setDescription('Deletes gift cards older than the provided date.'); + $this->setHelp(<<<'EOF' +The %command.name% command deletes gift cards older than the provided date. + +Date option accepts any date format accepted by PHP's DateTime class. +Such as "2020-01-01" or "2020-01-01 12:00:00" or "-3 years". + +Period option accepts any period format accepted by PHP's DateInterval class. +Such as "P1Y" or "P1Y2M". +EOF + ); $this->addOption( 'date', null, @@ -67,7 +77,12 @@ public function run(InputInterface $input, OutputInterface $output): int } try { - $thresholdDate = new \DateTimeImmutable($date ?? $period); + if (null !== $date) { + $thresholdDate = new \DateTimeImmutable($date); + } else { + $thresholdDate = new \DateTimeImmutable('now'); + $thresholdDate = $thresholdDate->sub(new \DateInterval($period)); + } } catch (\Exception $e) { $output->writeln('The provided date or period is not valid.'); diff --git a/src/Doctrine/ORM/GiftCardRepository.php b/src/Doctrine/ORM/GiftCardRepository.php index 65ea576d..0eeaa106 100644 --- a/src/Doctrine/ORM/GiftCardRepository.php +++ b/src/Doctrine/ORM/GiftCardRepository.php @@ -75,7 +75,7 @@ public function findCreatedBefore(\DateTimeInterface $date): array $qb = $this->createQueryBuilder('gc'); $qb->andWhere('gc.createdAt < :date'); - $qb->setParameter('date', $date->format('Y-m-d H:i:s')); + $qb->setParameter('date', $date); return $qb->getQuery()->getResult(); } From 59a37b74d9e55b4addc7a11ab5895d512a3c04fa Mon Sep 17 00:00:00 2001 From: Roshyo Date: Fri, 13 May 2022 12:34:44 +0200 Subject: [PATCH 3/5] Fix dependency --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index e0347462..fcfb3b5a 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "knplabs/knp-snappy-bundle": "^1.7", "sylius/resource-bundle": "^1.6", "symfony/config": "^4.4 || ^5.0", + "symfony/console": "^4.4 || ^5.0", "symfony/dependency-injection": "^4.4 || ^5.0", "symfony/event-dispatcher": "^4.4 || ^5.0", "symfony/form": "^4.4 || ^5.0", From 5ad9f84533984425a299bfe8d20b500d415e063e Mon Sep 17 00:00:00 2001 From: Roshyo Date: Fri, 13 May 2022 12:47:23 +0200 Subject: [PATCH 4/5] Disable GC instead of deleting them Add a limit to the search to avoid memory limit --- psalm.xml | 3 ++ ...and.php => DisableOldGiftCardsCommand.php} | 32 +++++++++++-------- src/Doctrine/ORM/GiftCardRepository.php | 7 +++- .../GiftCardRepositoryInterface.php | 5 ++- src/Resources/config/services/commands.xml | 4 +-- 5 files changed, 34 insertions(+), 17 deletions(-) rename src/Command/Cli/{DeleteOldGiftCardsCommand.php => DisableOldGiftCardsCommand.php} (71%) diff --git a/psalm.xml b/psalm.xml index 023833c3..81d00bad 100644 --- a/psalm.xml +++ b/psalm.xml @@ -14,6 +14,9 @@ + + + tests/Application/var/cache/test/ApplicationTests_Setono_SyliusGiftCardPlugin_Application_KernelTestDebugContainer.xml diff --git a/src/Command/Cli/DeleteOldGiftCardsCommand.php b/src/Command/Cli/DisableOldGiftCardsCommand.php similarity index 71% rename from src/Command/Cli/DeleteOldGiftCardsCommand.php rename to src/Command/Cli/DisableOldGiftCardsCommand.php index 231d8cba..2eabf107 100644 --- a/src/Command/Cli/DeleteOldGiftCardsCommand.php +++ b/src/Command/Cli/DisableOldGiftCardsCommand.php @@ -11,9 +11,9 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -final class DeleteOldGiftCardsCommand extends Command +final class DisableOldGiftCardsCommand extends Command { - protected static $defaultName = 'setono:sylius-gift-card:delete-old-gift-cards'; + protected static $defaultName = 'setono:sylius-gift-card:disable-old-gift-cards'; private GiftCardRepositoryInterface $giftCardRepository; @@ -32,9 +32,10 @@ public function __construct( protected function configure(): void { - $this->setDescription('Deletes gift cards older than the provided date.'); - $this->setHelp(<<<'EOF' -The %command.name% command deletes gift cards older than the provided date. + $this->setDescription('Disable gift cards older than the provided date.'); + $this->setHelp( + <<<'EOF' +The %command.name% command disables gift cards older than the provided date. Date option accepts any date format accepted by PHP's DateTime class. Such as "2020-01-01" or "2020-01-01 12:00:00" or "-3 years". @@ -47,14 +48,14 @@ protected function configure(): void 'date', null, InputOption::VALUE_OPTIONAL, - 'The date to delete gift cards older than.', + 'The date to disable gift cards older than.', null ); $this->addOption( 'period', null, InputOption::VALUE_OPTIONAL, - 'The period to delete gift cards older than.', + 'The period to disable gift cards older than.', null ); } @@ -89,14 +90,19 @@ public function run(InputInterface $input, OutputInterface $output): int return 0; } - $giftCards = $this->giftCardRepository->findCreatedBefore($thresholdDate); - foreach ($giftCards as $giftCard) { - $this->giftCardManager->remove($giftCard); - } + $disabledGiftCardsAmount = 0; + do { + $giftCards = $this->giftCardRepository->findEnabledCreatedBefore($thresholdDate); + foreach ($giftCards as $giftCard) { + $giftCard->disable(); + } + + $this->giftCardManager->flush(); - $this->giftCardManager->flush(); + $disabledGiftCardsAmount += count($giftCards); + } while (count($giftCards) > 0); - $output->writeln(\sprintf('Deleted %d gift cards.', \count($giftCards))); + $output->writeln(\sprintf('Disabled %d gift cards.', $disabledGiftCardsAmount)); return 1; } diff --git a/src/Doctrine/ORM/GiftCardRepository.php b/src/Doctrine/ORM/GiftCardRepository.php index 0eeaa106..17e4178e 100644 --- a/src/Doctrine/ORM/GiftCardRepository.php +++ b/src/Doctrine/ORM/GiftCardRepository.php @@ -70,12 +70,17 @@ public function createAccountListQueryBuilder(CustomerInterface $customer): Quer return $qb; } - public function findCreatedBefore(\DateTimeInterface $date): array + public function findEnabledCreatedBefore(\DateTimeInterface $date, ?int $limit = 100): array { $qb = $this->createQueryBuilder('gc'); $qb->andWhere('gc.createdAt < :date'); $qb->setParameter('date', $date); + $qb->andWhere('gc.enabled = true'); + + if (null !== $limit) { + $qb->setMaxResults($limit); + } return $qb->getQuery()->getResult(); } diff --git a/src/Repository/GiftCardRepositoryInterface.php b/src/Repository/GiftCardRepositoryInterface.php index dd2cb0c0..6bb491d1 100644 --- a/src/Repository/GiftCardRepositoryInterface.php +++ b/src/Repository/GiftCardRepositoryInterface.php @@ -28,5 +28,8 @@ public function findEnabled(): array; public function createAccountListQueryBuilder(CustomerInterface $customer): QueryBuilder; - public function findCreatedBefore(\DateTimeInterface $date): array; + /** + * @return GiftCardInterface[] + */ + public function findEnabledCreatedBefore(\DateTimeInterface $date, ?int $limit = 100): array; } diff --git a/src/Resources/config/services/commands.xml b/src/Resources/config/services/commands.xml index cbedeac0..4180bd7d 100644 --- a/src/Resources/config/services/commands.xml +++ b/src/Resources/config/services/commands.xml @@ -5,8 +5,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + From 25841d20bf43f705ac96a50d170d47446870aec4 Mon Sep 17 00:00:00 2001 From: Roshyo Date: Fri, 13 May 2022 13:37:06 +0200 Subject: [PATCH 5/5] Remove name from constructor --- src/Command/Cli/DisableOldGiftCardsCommand.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Command/Cli/DisableOldGiftCardsCommand.php b/src/Command/Cli/DisableOldGiftCardsCommand.php index 2eabf107..faf9d6e8 100644 --- a/src/Command/Cli/DisableOldGiftCardsCommand.php +++ b/src/Command/Cli/DisableOldGiftCardsCommand.php @@ -21,10 +21,9 @@ final class DisableOldGiftCardsCommand extends Command public function __construct( GiftCardRepositoryInterface $giftCardRepository, - ObjectManager $giftCardManager, - ?string $name = null + ObjectManager $giftCardManager ) { - parent::__construct($name); + parent::__construct(); $this->giftCardRepository = $giftCardRepository; $this->giftCardManager = $giftCardManager;