-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce new feed generation system
- Loading branch information
Showing
27 changed files
with
945 additions
and
8 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Webgriffe\SyliusClerkPlugin\Command; | ||
|
||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface; | ||
use Sylius\Component\Core\Model\ChannelInterface; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Command\LockableTrait; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Style\SymfonyStyle; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
use Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Generator\FeedGeneratorInterface; | ||
use Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\ValueObject\Feed; | ||
|
||
/** | ||
* @psalm-suppress PropertyNotSetInConstructor | ||
*/ | ||
#[AsCommand(name: 'webgriffe:clerk:feed:generate', description: 'Generate feeds for Clerk.io data sync')] | ||
class V2FeedGeneratorCommand extends Command | ||
{ | ||
use LockableTrait; | ||
|
||
private SymfonyStyle $io; | ||
|
||
/** | ||
* @param ChannelRepositoryInterface<ChannelInterface> $channelRepository | ||
*/ | ||
public function __construct( | ||
private readonly ChannelRepositoryInterface $channelRepository, | ||
private readonly FeedGeneratorInterface $productsFeedGenerator, | ||
private readonly Filesystem $filesystem, | ||
private readonly string $feedsStorageDirectory, | ||
) { | ||
parent::__construct(); | ||
} | ||
|
||
protected function configure(): void | ||
{ | ||
} | ||
|
||
protected function initialize(InputInterface $input, OutputInterface $output): void | ||
{ | ||
$this->io = new SymfonyStyle($input, $output); | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$this->io->writeln('Starting Clerk.io feed generation...'); | ||
if (!$this->lock()) { | ||
$this->io->error('The command is already running in another process, quitting.'); | ||
|
||
return Command::FAILURE; | ||
} | ||
|
||
$this->filesystem->mkdir($this->feedsStorageDirectory); | ||
/** @var ChannelInterface[] $channels */ | ||
$channels = $this->channelRepository->findAll(); | ||
foreach ($channels as $channel) { | ||
foreach ($channel->getLocales() as $locale) { | ||
$productsFeed = $this->productsFeedGenerator->generate($channel, (string) $locale->getCode()); | ||
$feedFilePath = $this->getFeedFilePath($productsFeed); | ||
|
||
$this->io->writeln(sprintf('Writing feed to file: %s', $feedFilePath)); | ||
$this->filesystem->dumpFile($feedFilePath, $productsFeed->getContent()); | ||
} | ||
} | ||
|
||
$this->io->success('Clerk.io feed generation completed successfully.'); | ||
|
||
return Command::SUCCESS; | ||
} | ||
|
||
private function getFeedFilePath(Feed $productsFeed): string | ||
{ | ||
return sprintf( | ||
'%s/%s', | ||
rtrim($this->feedsStorageDirectory, '/'), | ||
ltrim($productsFeed->getFileName(), '/'), | ||
); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
src/DataSyncInfrastructure/Doctrine/ORM/Event/QueryBuilderEvent.php
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Doctrine\ORM\Event; | ||
|
||
use Doctrine\ORM\QueryBuilder; | ||
use Sylius\Component\Core\Model\ChannelInterface; | ||
|
||
final readonly class QueryBuilderEvent | ||
{ | ||
public function __construct( | ||
private QueryBuilder $queryBuilder, | ||
private ChannelInterface $channel, | ||
private string $localeCode, | ||
private ?\DateTimeInterface $modifiedAfter = null, | ||
private ?int $limit = null, | ||
private ?int $offset = null, | ||
) { | ||
} | ||
|
||
public function getQueryBuilder(): QueryBuilder | ||
{ | ||
return $this->queryBuilder; | ||
} | ||
|
||
public function getChannel(): ChannelInterface | ||
{ | ||
return $this->channel; | ||
} | ||
|
||
public function getLocaleCode(): string | ||
{ | ||
return $this->localeCode; | ||
} | ||
|
||
public function getModifiedAfter(): ?\DateTimeInterface | ||
{ | ||
return $this->modifiedAfter; | ||
} | ||
|
||
public function getLimit(): ?int | ||
{ | ||
return $this->limit; | ||
} | ||
|
||
public function getOffset(): ?int | ||
{ | ||
return $this->offset; | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
src/DataSyncInfrastructure/Doctrine/ORM/ProductsQueryBuilder.php
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Doctrine\ORM; | ||
|
||
use Psr\EventDispatcher\EventDispatcherInterface; | ||
use Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository; | ||
use Sylius\Component\Core\Model\ChannelInterface; | ||
use Sylius\Component\Core\Model\ProductInterface; | ||
use Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Doctrine\ORM\Event\QueryBuilderEvent; | ||
use Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Enum\Resource; | ||
use Webgriffe\SyliusClerkPlugin\DataSyncInfrastructure\Model\QueryBuilderInterface; | ||
|
||
/** | ||
* @implements QueryBuilderInterface<ProductInterface> | ||
*/ | ||
final readonly class ProductsQueryBuilder implements QueryBuilderInterface | ||
{ | ||
public function __construct( | ||
private ProductRepository $productRepository, | ||
private EventDispatcherInterface $eventDispatcher, | ||
) { | ||
} | ||
|
||
public function getResource(): Resource | ||
{ | ||
return Resource::PRODUCTS; | ||
} | ||
|
||
public function getResult( | ||
ChannelInterface $channel, | ||
string $localeCode, | ||
?\DateTimeInterface $modifiedAfter = null, | ||
?int $limit = null, | ||
?int $offset = null, | ||
): array { | ||
$queryBuilder = $this->productRepository->createQueryBuilder('p'); | ||
|
||
$queryBuilder | ||
->andWhere(':channel MEMBER OF p.channels') | ||
->setParameter('channel', $channel) | ||
; | ||
$queryBuilder | ||
->leftJoin('p.translations', 't', 'WITH', 't.locale = :localeCode') | ||
->setParameter('localeCode', $localeCode) | ||
; | ||
|
||
if ($modifiedAfter !== null) { | ||
$queryBuilder | ||
->andWhere('p.updatedAt > :modifiedAfter') | ||
->setParameter('modifiedAfter', $modifiedAfter) | ||
; | ||
} | ||
|
||
if ($limit !== null) { | ||
$queryBuilder->setMaxResults($limit); | ||
} | ||
|
||
if ($offset !== null) { | ||
$queryBuilder->setFirstResult($offset); | ||
} | ||
|
||
$this->eventDispatcher->dispatch(new QueryBuilderEvent( | ||
$queryBuilder, | ||
$channel, | ||
$localeCode, | ||
$modifiedAfter, | ||
$limit, | ||
$offset, | ||
)); | ||
|
||
/** @var ProductInterface[] $result */ | ||
$result = $queryBuilder->getQuery()->getResult(); | ||
|
||
return $result; | ||
} | ||
} |
Oops, something went wrong.