/src/Console/CoreCommand.php
PHP | 445 lines | 263 code | 84 blank | 98 comment | 16 complexity | b936dea256d390f426e9b848def13412 MD5 | raw file
- <?php
- namespace CPTeam\Console;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Formatter\OutputFormatterStyle as OFS;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Question\ConfirmationQuestion;
- use Symfony\Component\Console\Question\Question;
- use Tracy\Debugger;
- /**
- * Class Core
- *
- * Obal pro konzolove prikazy
- *
- * @package CPTeam\Symfony\Console
- *
- * @release 0.1.64
- */
- abstract class CoreCommand extends Command
- {
- const TABLE_SIZE = 60;
- const PRETTY = 'pretty';
- /** @var callable[] */
- public static $onException = [];
-
- /** @var callable[] */
- public static $onError = [];
-
- /** @var callable[] */
- private $beforeRun = [];
-
- /** @var callable[] */
- private $afterRun = [];
-
- /** @var InputInterface */
- private $input;
- /** @var OutputInterface */
- private $output;
- private $tableSize = self::TABLE_SIZE;
- protected $timer = 0;
- private $state = 0;
-
- private $configureInit = false;
- const STATE_NONE = 0;
- const STATE_PREPARE = 1;
- const STATE_PROCESS = 2;
- const STATE_COMPLETED = 3;
- const STATE_TERMINATED = 10;
- const STATE_ERROR = 20;
- abstract protected function runCmd(InputInterface $input, OutputInterface $output);
- protected function configure()
- {
- parent::configure();
- $this->addOption(
- self::PRETTY,
- null,
- InputOption::VALUE_NONE,
- 'Output without system logs, etc.'
- );
-
- $this->addOption(
- "output",
- "o",
- InputOption::VALUE_REQUIRED,
- "Output path",
- false
- );
-
- $this->configureInit = true;
- }
- /**
- * @param \Symfony\Component\Console\Input\InputInterface $input
- * @param \Symfony\Component\Console\Output\OutputInterface $output
- *
- * @return int
- */
- final protected function execute(InputInterface $input, OutputInterface $output): ?int
- {
- if ($this->configureInit === false) {
- throw new LogicException("You missed run parent::configure().");
- }
-
- $styles = [
- 'system' => new OFS('cyan', 'default', []),
- 'task' => new OFS('magenta', 'default', []),
- 'verbose' => new OFS('yellow', 'default', []),
- 'success' => new OFS('green', 'default', []),
- 'debug' => new OFS('default', 'blue', []),
- 'error' => new OFS('red', 'default', ["bold"]),
- 'cyan' => new OFS('cyan', 'default', ["bold"]),
- 'magenta' => new OFS('magenta', 'default', ["bold"]),
- 'green' => new OFS('green', 'default', ["bold"]),
- 'blue' => new OFS('blue', 'default', ["bold"]),
- 'yellow' => new OFS('yellow', 'default', ["bold"]),
- 'red' => new OFS('red', 'default', []),
-
- 'darkCyan' => new OFS('cyan', 'default', []),
- 'darkMagenta' => new OFS('magenta', 'default', []),
- 'darkGreen' => new OFS('green', 'default', []),
- 'darkBlue' => new OFS('blue', 'default', []),
- 'darkYellow' => new OFS('yellow', 'default', []),
- 'darkRed' => new OFS('red', 'default', []),
- ];
-
- if ($input->getOption("output")) {
- $output = new FileOutput($output, $input->getOption("output"));
- }
- foreach ($styles as $name => $style) {
- $output->getFormatter()->setStyle($name, $style);
- }
- $this->input = $input;
- $this->output = $output;
-
-
- $pretty = $this->getInput()->getOption(self::PRETTY);
- if ($pretty === false) {
- try {
- $this->state = self::STATE_PREPARE;
- $output->writeln("<yellow>" . str_repeat("=", $this->getTableSize() + strlen($this->getName()) + 3) . "</yellow>");
- $this->logSystem("<task>" . $this->getName() . "</task> at " . date("d.m.Y H:i:s"));
- $this->logHr();
- $this->timer = 0 - microtime(true);
- $result = 1;
- try {
-
- foreach ($this->beforeRun as $call) {
- $call($input, $output);
- }
-
- $this->state = self::STATE_PROCESS;
- $result = $this->runCmd($input, $output);
- $this->state = self::STATE_COMPLETED;
-
- foreach ($this->afterRun as $call) {
- $call($input, $output);
- }
- } catch (TerminateException $e) {
- $this->state = self::STATE_TERMINATED;
- $this->logHr();
- $this->logError("<red>Script terminated</red>");
- $this->logError($e->getMessage());
- }
- $this->timer += microtime(true);
- $this->logHr();
- $this->logSystem("Task <magenta>" . $this->getName() . "</magenta> complete" . ($this->isTerminated() ? " (<red>Terminated</red>)" : ""));
- $this->logSystem(
- $this->table("Execution time", "<yellow>" . number_format(round($this->timer * 1000, 3), 3, ',', ' ') . " ms</yellow>")
- );
- $pid = getmypid();
- $this->logSystem(
- $this->table("Memory allocated (php)", "<yellow>" . round(memory_get_usage() / 1024 / 1024, 2) . " MB</yellow>")
- );
- $this->logSystem(
- $this->table("Memory usage (process)", "<yellow>" . round((int)`ps -p $pid v | awk 'END{print $8}'` / 1024, 2) . " MB</yellow>")
- );
- $output->writeln("<yellow>" . str_repeat("=", $this->getTableSize() + strlen($this->getName()) + 3) . "</yellow>");
- return $result;
- } catch (\Exception $e) {
-
- /** @var callable $callback */
- foreach (self::$onException as $callback) {
- if (is_callable($callback)) {
- $callback($e);
- }
- }
-
- $this->logError($e);
- return 1;
- } catch (\Error $e) {
-
- /** @var callable $callback */
- foreach (self::$onError as $callback) {
- if (is_callable($callback)) {
- $callback($e);
- }
- }
-
- $this->logError($e);
- return 1;
- }
- } else {
- $this->runCmd($input, $output);
- }
-
-
- }
- /**
- * @param $msg
- *
- * @throws TerminateException
- */
- protected function terminate($msg)
- {
- throw new TerminateException($msg);
- }
- protected function setDebug()
- {
- Debugger::$productionMode = Debugger::DEVELOPMENT;
- }
- /**
- * @param string $msg
- * @param int $verbosity
- */
- protected function log($msg = "", $verbosity = OutputInterface::VERBOSITY_NORMAL)
- {
- if ($this->output->getVerbosity() >= $verbosity) {
- if (is_string($msg) || is_numeric($msg)) {
- $this->output->writeln('[<task>' . $this->getName() . '</task>] ' . $msg);
- } else {
- //$d = dump($msg, true);
- $x = Debugger::dump($msg, true);
- foreach (explode("\n", $x) as $msg) {
- $this->log($msg);
- }
- }
- }
- }
- /**
- * @param $msg
- */
- protected function logVerbose($msg)
- {
- $this->log("<verbose>$msg</verbose>", OutputInterface::VERBOSITY_VERBOSE);
- }
- /**
- * @param $msg
- */
- protected function logDebug($msg)
- {
- $this->log("<debug>$msg</debug>", OutputInterface::VERBOSITY_DEBUG);
- }
- /**
- * @param $msg
- */
- protected function logError($msg)
- {
- if ($msg instanceof \Error || $msg instanceof \Exception) {
- $class = get_class($msg);
- $this->log(
- "<error>\n\n[Exception]: $class" . "\n" .
- "{$msg->getMessage()}</error>" . "\n\n" .
- "<red>{$msg->getTraceAsString()}</red>"
- );
- } else {
- $this->log("<error>$msg</error>", OutputInterface::VERBOSITY_NORMAL);
- }
- }
- /**
- * @param $msg
- */
- protected function logSuccess($msg)
- {
- $this->log("<success>$msg</success>", OutputInterface::VERBOSITY_NORMAL);
- }
- protected function logHr()
- {
- $this->logSystem(str_repeat("-", $this->getTableSize()));
- }
- /**
- * @param $left
- * @param $right
- * @param string $spaceChar
- *
- * @return string
- */
- protected function table($left, $right, $spaceChar = " ")
- {
- return $left .
- str_repeat(
- $spaceChar,
- max(1, $this->getTableSize() - mb_strlen(strip_tags($left)) - mb_strlen(strip_tags($right)))
- ) .
- $right;
- }
- /**
- * @param $msg
- */
- private function logSystem(string $msg): void
- {
- $this->log("<system>$msg</system>", OutputInterface::VERBOSITY_QUIET);
- }
- /**
- * @return InputInterface
- */
- protected function getInput(): InputInterface
- {
- return $this->input;
- }
- /**
- * @return OutputInterface
- */
- protected function getOutput(): OutputInterface
- {
- return $this->output;
- }
- /**
- * @param $size
- *
- * @return $this
- */
- protected function setTableSize($size)
- {
- $this->tableSize = $size;
- return $this;
- }
- /**
- * @return int
- */
- protected function getTableSize()
- {
- if ($this->tableSize === null) {
- $this->tableSize = self::TABLE_SIZE;
- }
- return $this->tableSize;
- }
- /**
- * @param $name
- * @param $quest
- * @param null $default
- *
- * @return mixed
- * @throws \Symfony\Component\Console\Exception\InvalidArgumentException
- * @throws \Symfony\Component\Console\Exception\LogicException
- */
- protected function get($name, $quest, $default = null)
- {
- $option = $this->getInput()->getOption($name);
- if ($option) {
- return $option;
- }
- $q = new Question($quest, $default);
- $helper = $this->questionHelper();
- return $helper->ask($this->getInput(), $this->getOutput(), $q);
- }
- /**
- * @param $name
- * @param $quest
- * @param bool $default
- *
- * @return mixed
- * @throws \Symfony\Component\Console\Exception\InvalidArgumentException
- * @throws \Symfony\Component\Console\Exception\LogicException
- */
- protected function confirm($name, $quest, $default = false)
- {
- $option = $this->getInput()->getOption($name);
- if ($option) {
- return $option;
- }
- $q = new ConfirmationQuestion($quest, $default);
- $helper = $this->questionHelper();
- return $helper->ask($this->getInput(), $this->getOutput(), $q);
- }
- /**
- * @return mixed
- * @throws \Symfony\Component\Console\Exception\InvalidArgumentException
- * @throws \Symfony\Component\Console\Exception\LogicException
- */
- protected function questionHelper()
- {
- return $this->getHelper("question");
- }
-
- public function isTerminated(): bool
- {
- return $this->state === self::STATE_TERMINATED;
- }
-
- /**
- * @param \callable[] $beforeRun
- */
- public function addBeforeRun(callable $beforeRun)
- {
- $this->beforeRun[] = $beforeRun;
- }
-
- /**
- * @param \callable[] $afterRun
- */
- public function addAfterRun(callable $afterRun)
- {
- $this->afterRun[] = $afterRun;
- }
-
- }