Skip to content

Commit

Permalink
Add symfony command to remove expired anonymous wishlists
Browse files Browse the repository at this point in the history
To reduce database table size generated by guest customers
  • Loading branch information
lusimeon committed Jun 10, 2024
1 parent 911dbb3 commit 45946f1
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 0 deletions.
11 changes: 11 additions & 0 deletions doc/01-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,14 @@ framework:
```

All commands from the plugin implement the `WishlistSyncCommandInterface` interface, so there is no need for other configuration.

## Removing anonymous wishlists after expiration period

You can remove anonymous wishlists that have not been updated for a specified period of time. To do so, you need to add `bitbag:remove-anonymous-wishlists` Symfony console command to your cron jobs.

You can specify the expiration period in your parameters file to override the default value of 30 days:

```yaml
parameters:
bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period: 30 days # Remove all anonymous wishlists that were updated more than 30 days ago.
```
55 changes: 55 additions & 0 deletions src/Console/RemoveAnonymousWishlistsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on [email protected].
*/

declare(strict_types=1);

namespace BitBag\SyliusWishlistPlugin\Console;

use BitBag\SyliusWishlistPlugin\Remover\AnonymousWishlistsRemoverInterface;
use SyliusLabs\Polyfill\Symfony\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
* @final
*/
class RemoveAnonymousWishlistsCommand extends ContainerAwareCommand
{
protected static $defaultName = 'bitbag:remove-anonymous-wishlists';

protected function configure(): void
{
$this
->setDescription('Removes anonymous wishlists that have been idle for a period set in `bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period` configuration key.')
;
}

protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var string $expirationTime */
$expirationTime = $this->getContainer()->getParameter('bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period');

if (empty($expirationTime)) {
$output->writeln('<error>`bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period` configuration key is not set, so no wishlists will be removed.</error>');

return 0;
}

$output->writeln(sprintf(
'Command will remove anonymous wishlists that have been idle for <info>%s</info>.',
(string) $expirationTime,
));

/** @var AnonymousWishlistsRemoverInterface $anonymousWishlistsRemover */
$anonymousWishlistsRemover = $this->getContainer()->get('bitbag_sylius_wishlist_plugin.services.anonymous_wishlists_remover');
$anonymousWishlistsRemover->remove();

return 0;
}
}
1 change: 1 addition & 0 deletions src/DependencyInjection/BitBagSyliusWishlistExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function load(array $config, ContainerBuilder $container): void
$this->registerResources('bitbag_sylius_wishlist_plugin', 'doctrine/orm', $config['resources'], $container);
$loader->load('services.yml');
$container->setParameter('bitbag_sylius_wishlist_plugin.parameters.wishlist_cookie_token', $config['wishlist_cookie_token']);
$container->setParameter('bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period', $config['anonymous_wishlist_expiration_period']);
$container->setParameter('bitbag_sylius_wishlist_plugin.parameters.allowed_mime_types', $config['allowed_mime_types']);
}

Expand Down
13 changes: 13 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ public function getConfigTreeBuilder(): TreeBuilder
})
->end()
->end()
->scalarNode('anonymous_wishlist_expiration_period')
->defaultValue('30 days')
->cannotBeEmpty()
->validate()
->always(function ($value) {
if (!is_string($value)) {
throw new InvalidConfigurationException('anonymous_wishlist_expiration_period must be string');
}

return $value;
})
->end()
->end()
->arrayNode('allowed_mime_types')
->defaultValue([
'text/csv',
Expand Down
32 changes: 32 additions & 0 deletions src/Remover/AnonymousWishlistsRemover.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on [email protected].
*/

declare(strict_types=1);

namespace BitBag\SyliusWishlistPlugin\Remover;

use BitBag\SyliusWishlistPlugin\Repository\WishlistRepositoryInterface;
use Doctrine\Persistence\ObjectManager;

final class AnonymousWishlistsRemover implements AnonymousWishlistsRemoverInterface
{
public function __construct(
private WishlistRepositoryInterface $wishlistRepository,
private ObjectManager $wishlistManager,
private ?string $expirationPeriod,
) {
}

public function remove(): void
{
$this->wishlistRepository->deleteAllAnonymousUntil(
new \DateTime('-' . $this->expirationPeriod),
);
}
}
17 changes: 17 additions & 0 deletions src/Remover/AnonymousWishlistsRemoverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on [email protected].
*/

declare(strict_types=1);

namespace BitBag\SyliusWishlistPlugin\Remover;

interface AnonymousWishlistsRemoverInterface
{
public function remove(): void;
}
12 changes: 12 additions & 0 deletions src/Repository/WishlistRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,16 @@ public function findOneByShopUserAndName(ShopUserInterface $shopUser, string $na
->getOneOrNullResult()
;
}

public function deleteAllAnonymousUntil(\DateTime $until): int
{
return $this->createQueryBuilder('o')
->delete(WishlistInterface::class, 'o')
->where('o.shopUser IS NULL')
->andWhere('o.updatedAt < :until')
->setParameter('until', $until)
->getQuery()
->execute()
;
}
}
5 changes: 5 additions & 0 deletions src/Repository/WishlistRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ public function findAllByAnonymousAndChannel(?string $token, ChannelInterface $c
public function findOneByTokenAndName(string $token, string $name): ?WishlistInterface;

public function findOneByShopUserAndName(ShopUserInterface $shopUser, string $name): ?WishlistInterface;

/**
* @return int Number of deleted wishlists.
*/
public function deleteAllAnonymousUntil(\DateTime $until): int;
}
13 changes: 13 additions & 0 deletions src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ imports:
- { resource: "services/**/*.yml" }

services:
bitbag_sylius_wishlist_plugin.console.remove_anonymous_wishlists_command:
class: BitBag\SyliusWishlistPlugin\Console\RemoveAnonymousWishlistsCommand
tags:
- { name: console.command }

bitbag_sylius_wishlist_plugin.controller.action.base_wishlist_products_action:
abstract: true
class: BitBag\SyliusWishlistPlugin\Controller\Action\BaseWishlistProductsAction
Expand Down Expand Up @@ -348,6 +353,14 @@ services:
- '@request_stack'
- "@translator"

bitbag_sylius_wishlist_plugin.services.anonymous_wishlists_remover:
public: true
class: BitBag\SyliusWishlistPlugin\Remover\AnonymousWishlistsRemover
arguments:
- "@bitbag_sylius_wishlist_plugin.repository.wishlist"
- "@bitbag_sylius_wishlist_plugin.manager.wishlist"
- "%bitbag_sylius_wishlist_plugin.parameters.anonymous_wishlist_expiration_period%"

bitbag_sylius_wishlist_plugin.checker.wishlist_name_checker:
class: BitBag\SyliusWishlistPlugin\Checker\WishlistNameChecker

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Sylius\Component\Locale\Model\Locale:
locale:
createdAt: '<dateTimeBetween("-200 days", "now")>'
code: 'en_US'
Sylius\Component\Currency\Model\Currency:
dollar:
code: 'USD'
Sylius\Component\Core\Model\Channel:
channel_us:
code: 'US'
name: 'name'
defaultLocale: '@locale'
locales: [ '@locale' ]
taxCalculationStrategy: 'order_items_based'
baseCurrency: '@dollar'
enabled: true
Sylius\Component\Core\Model\Customer:
customer_oliver:
firstName: 'John'
lastName: 'Nowak'
email: '[email protected]'
emailCanonical: '[email protected]'
Sylius\Component\Core\Model\ShopUser:
user_oliver:
plainPassword: '123password'
roles: [ 'ROLE_USER' ]
enabled: 'true'
customer: '@customer_oliver'
username: '[email protected]'
usernameCanonical: '[email protected]'
BitBag\SyliusWishlistPlugin\Entity\Wishlist:
wishlist_one:
name: 'Wishlist One'
channel: '@channel_us'
token: 'token'
updatedAt: '<date_create_from_format("Y-m-d H:i:s", "2023-01-01 00:00:00")>'
wishlist_two:
name: 'Wishlist Two'
channel: '@channel_us'
token: 'token'
updatedAt: '<date_create_from_format("Y-m-d H:i:s", "2024-01-02 00:00:00")>'
olivier_wishlist:
name: 'Olivier Wishlist'
shopUser: '@user_oliver'
channel: '@channel_us'
updatedAt: '<date_create_from_format("Y-m-d H:i:s", "2023-01-01 00:00:00")>'
16 changes: 16 additions & 0 deletions tests/Integration/Repository/WishlistRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,20 @@ public function testItFindsOneWishlistByShopUserAndName(): void
$missingResult = $this->repository->findOneByShopUserAndName($shopUser, 'Bruce Wishlist');
$this->assertNull($missingResult);
}

public function testItDeleteAllAnonymousUntilWishlists(): void
{
$this->loadFixturesFromFile('test_it_delete_all_anonymous_until_wishlists.yaml');

/** @var int $result */
$result = $this->repository->deleteAllAnonymousUntil(new \DateTime('2024-01-01 00:00:00'));

$this->assertIsInt($result);
$this->assertSame(1, $result);

$wishlists = $this->repository->findAll();
$this->assertCount(2, $wishlists);
$this->assertSame('Wishlist Two', $wishlists[0]->getName());
$this->assertSame('Olivier Wishlist', $wishlists[1]->getName());
}
}

0 comments on commit 45946f1

Please sign in to comment.