<?php
namespace App\EventListener;
use App\Entity\Central\Client\Client;
use App\Entity\Central\Command\Command;
use App\Entity\Client\PointOfSale\PointOfSale;
use App\Entity\Client\Store\Store;
use App\Service\AppManager;
use App\Service\Logger;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class CommandListener implements EventSubscriberInterface
{
private $kernel;
private $appManager;
private $logger;
public function __construct(KernelInterface $kernel, AppManager $appManager, Logger $logger)
{
$this->appManager = $appManager;
$this->kernel = $kernel;
$this->logger = $logger;
}
public function onConsoleCommand(ConsoleCommandEvent $event)
{
if ($event->getCommand() === null) {
return;
}
$symfonyCommand = $event->getCommand();
if ($this->ignoreCommand($symfonyCommand->getName())) {
return;
}
$argv = $_SERVER['argv'];
unset($argv[0]);
$command = new Command();
$command->setCommand('php ' . $this->kernel->getProjectDir() . '/bin/console ' . implode(" ", $argv));
$command->setOptions($event->getInput()->getOptions());
$command->setArguments($event->getInput()->getArguments());
$this->appManager->beginTransaction();
$this->appManager->persist($command);
$this->appManager->flush();
$this->appManager->commit();
$event->getCommand()->setHelp($command->getId());
}
public function onConsoleError(ConsoleErrorEvent $event)
{
$this->logger->logException($event->getError());
if ($event->getCommand() === null) {
return;
}
$this->endCommand($event->getCommand(), $event->getError()->getMessage(), Command::COMMAND_ERROR);
}
public function onConsoleTerminate(ConsoleTerminateEvent $event)
{
if ($event->getCommand() === null) {
return;
}
$this->endCommand($event->getCommand(), $event->getExitCode(), Command::COMMAND_SUCCESS);
}
public function endCommand(SymfonyCommand $symfonyCommand, string $exitCode, string $resultCode)
{
if ($this->ignoreCommand($symfonyCommand->getName())) {
return;
}
$commandId = $symfonyCommand->getHelp();
if ($commandId === '') {
return;
}
try {
$finishAt = new \DateTime();
$command = $this->appManager->getRepository(Command::class)->find($commandId);
if (!$command instanceof Command) {
return;
}
if ($command->getResultCode() !== Command::COMMAND_RUNNING && $resultCode === Command::COMMAND_SUCCESS){
return;
}
$diff = ($realDiff = $finishAt->getTimestamp() - $command->getCreatedAt()->getTimestamp()) < 0 ? 0 : $realDiff;
$command->setTotalExecutionTimeInSeconds($diff);
$command->setFinishAt($finishAt);
$command->setResultCode($resultCode);
$command->setResult($exitCode);
$this->appManager->persist($command);
$this->appManager->flush();
$this->appManager->commit();
} catch (\Exception $exception) {
}
}
public static function getSubscribedEvents()
{
return [
ConsoleEvents::COMMAND => ['onConsoleCommand', 0],
ConsoleEvents::ERROR => ['onConsoleError', -128],
ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128],
];
}
public function ignoreCommand(string $commandName)
{
if (in_array($commandName, [
'swiftmailer:spool:send',
'doctrine:database:create',
'doctrine:schema:update',
'doctrine:schema:drop',
'doctrine:schemas:update',
'doctrine:database:drop',
'to:postgres',
'cache:clear',
'assets:install'
])) {
return true;
}
return false;
}
}