Last active
May 25, 2022 01:45
-
-
Save Nemo64/d3c45bbc46badb9a2ee0e9bc284d8b7c to your computer and use it in GitHub Desktop.
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
<?php | |
namespace App\Command; | |
use App\Entity\Order; | |
use App\Service\TickService; | |
use Doctrine\DBAL\LockMode; | |
use Doctrine\ORM\EntityManagerInterface; | |
use Symfony\Component\Console; | |
use Symfony\Component\Workflow\WorkflowInterface; | |
class OrderTickCommand extends Console\Command\Command | |
{ | |
public function __construct( | |
private WorkflowInterface $orderStateMachine, | |
private EntityManagerInterface $entityManager, | |
private TickService $tickService, | |
) { | |
parent::__construct(); | |
} | |
public function configure() | |
{ | |
$this->setName('order:tick'); | |
$this->addArgument('ids', Console\Input\InputArgument::OPTIONAL | Console\Input\InputArgument::IS_ARRAY, 'limit to some ids'); | |
} | |
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) | |
{ | |
// fetch id list to process | |
$ids = $input->getArgument('ids'); | |
if (empty($ids)) { | |
$statesToCheck = $this->getStatesToCheck(); | |
$output->writeln(sprintf( | |
'Checking orders in states: <info>%s</info>', | |
implode(', ', $statesToCheck) | |
)); | |
$qb = $this->entityManager->createQueryBuilder() | |
->select('order.id AS id') | |
->from(Order::class, 'order') | |
->where('order.status IN (:states)') | |
->setParameter('states', $statesToCheck); | |
$ids = array_column($qb->getQuery()->getArrayResult(), 'id'); | |
} | |
// go through all id's and execute the tick | |
$progress = new Console\Helper\ProgressBar($output, count($ids)); | |
$progress->setFormat('debug'); | |
foreach ($ids as $index => $id) { | |
$this->entityManager->clear(); // prevent memory leaks | |
$progress->setProgress($index); | |
$transition = $this->entityManager->wrapInTransaction(function () use ($id) { | |
$order = $this->entityManager->find(Order::class, $id, LockMode::PESSIMISTIC_WRITE); | |
return $this->tickService->tick($order); | |
}); | |
if ($transition) { | |
$output->writeln(sprintf( | |
'executed <info>%s</info> on order <info>%s</info> to <info>%s</info>', | |
$transition->getName(), | |
$id, | |
implode(', ', $transition->getTos()) | |
)); | |
} | |
} | |
$progress->finish(); | |
return 0; | |
} | |
/** | |
* Builds a list of states that can have transitions with "on_tick" enabled. | |
*/ | |
private function getStatesToCheck(): array | |
{ | |
$result = []; | |
foreach ($this->orderStateMachine->getDefinition()->getTransitions() as $transition) { | |
$tickEnabled = $this->orderStateMachine->getMetadataStore()->getTransitionMetadata($transition)['on_tick'] ?? false; | |
if (!$tickEnabled) { | |
continue; | |
} | |
foreach ($transition->getFroms() as $from) { | |
$result[$from] = $from; | |
} | |
} | |
return array_values($result); | |
} | |
} |
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
<?php | |
namespace App\Service; | |
use Symfony\Component\Workflow; | |
class TickService | |
{ | |
public function __construct( | |
private Workflow\Registry $registry | |
) { | |
} | |
public function tick(object $subject, string $workflowName = null): ?Workflow\Transition | |
{ | |
$workflow = $this->registry->get($subject, $workflowName); | |
foreach ($workflow->getEnabledTransitions($subject) as $transition) { | |
$tickEnabled = $workflow->getMetadataStore()->getTransitionMetadata($transition)['on_tick'] ?? false; | |
if (!$tickEnabled) { | |
continue; | |
} | |
$workflow->apply($subject, $transition); | |
return $transition; | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment