123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Deploy\Console;
- use Psr\Log\AbstractLogger;
- use Psr\Log\LogLevel;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- use Symfony\Component\Console\Helper\FormatterHelper;
- use Magento\Framework\Filesystem;
- use Magento\Framework\App\Filesystem\DirectoryList;
- use Magento\Framework\Filesystem\Directory\ReadInterface;
- /**
- * PSR logger implementation for CLI
- */
- class ConsoleLogger extends AbstractLogger
- {
- /**
- * Type for informational message
- */
- const INFO = 'info';
- /**
- * Type for error message
- */
- const ERROR = 'error';
- /**
- * Public static files directory read interface
- *
- * @var ReadInterface
- */
- private $tmpDir;
- /**
- * Console output interface
- *
- * @var OutputInterface
- */
- private $output;
- /**
- * Helper for preparing data of specific formats (date, percentage, etc)
- *
- * @var FormatterHelper
- */
- private $formatterHelper;
- /**
- * Maximum progress bar row string length
- *
- * @var int
- */
- private $initialMaxBarSize = 0;
- /**
- * Number of rendered lines
- *
- * Used for clearing previously rendered progress bars
- *
- * @var int
- */
- private $renderedLines = 0;
- /**
- * Time of previous rendering tick
- *
- * @var int
- */
- private $lastTimeRefreshed = 0;
- /**
- * @var array
- */
- private $verbosityLevelMap = [
- LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::INFO => OutputInterface::VERBOSITY_VERBOSE,
- LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG
- ];
- /**
- * @var array
- */
- private $formatLevelMap = [
- LogLevel::EMERGENCY => self::ERROR,
- LogLevel::ALERT => self::ERROR,
- LogLevel::CRITICAL => self::ERROR,
- LogLevel::ERROR => self::ERROR,
- LogLevel::WARNING => self::INFO,
- LogLevel::NOTICE => self::INFO,
- LogLevel::INFO => self::INFO,
- LogLevel::DEBUG => self::INFO
- ];
- /**
- * Running deployment processes info
- *
- * @var array[]
- */
- private $processes = [];
- /**
- * @param Filesystem $filesystem
- * @param OutputInterface $output
- * @param FormatterHelper $formatterHelper
- * @param array $verbosityLevelMap
- * @param array $formatLevelMap
- */
- public function __construct(
- Filesystem $filesystem,
- OutputInterface $output,
- FormatterHelper $formatterHelper,
- array $verbosityLevelMap = [],
- array $formatLevelMap = []
- ) {
- $this->tmpDir = $filesystem->getDirectoryWrite(DirectoryList::TMP_MATERIALIZATION_DIR);
- $this->output = $output;
- $this->formatterHelper = $formatterHelper;
- $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
- $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
- }
- /**
- * @inheritdoc
- */
- public function log($level, $message, array $context = [])
- {
- if (!isset($this->verbosityLevelMap[$level])) {
- $level = self::INFO;
- }
- // Write to the error output if necessary and available
- if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
- $output = $this->output->getErrorOutput();
- } else {
- $output = $this->output;
- }
- if (isset($context['process'])) {
- $this->registerProcess($context);
- } else {
- $this->refresh($output);
- }
- if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
- $output->writeln(sprintf('<%1$s>%2$s</%1$s>', $this->formatLevelMap[$level], $message));
- }
- }
- /**
- * Add deployment process to rendering stack
- *
- * @param array $context
- * @return void
- */
- private function registerProcess(array $context)
- {
- $name = isset($context['process']) ? $context['process'] : 'main';
- if (!isset($this->processes[$name])) {
- $context['start'] = time();
- $context['elapsed'] = 0;
- $this->processes[$name] = $context;
- }
- }
- /**
- * Refresh CLI output
- *
- * @param OutputInterface $output
- * @return void
- */
- private function refresh(OutputInterface $output)
- {
- if (!count($this->processes) || (time() - $this->lastTimeRefreshed < 1)) {
- return;
- }
- $this->cleanUp();
- $bars = [];
- $maxBarSize = 0;
- foreach ($this->processes as $name => & $process) {
- $this->updateProcessInfo($name, $process);
- $bar = $this->renderProgressBar($output, $process);
- $maxBarSize = strlen($bar) > $maxBarSize ? strlen($bar) : $maxBarSize;
- $bars[] = $bar;
- }
- if (!$this->initialMaxBarSize) {
- $this->initialMaxBarSize = $maxBarSize + 10;
- }
- if ($bars) {
- $this->renderedLines = count($bars);
- $bar = '';
- foreach ($bars as &$bar) {
- if ($this->initialMaxBarSize > strlen($bar)) {
- $bar .= str_pad(" ", ($this->initialMaxBarSize - strlen($bar)));
- }
- }
- $bar = trim($bar);
- $output->writeln(implode("\n", $bars));
- }
- }
- /**
- * Update process information
- *
- * @param string $deployedPackagePath
- * @param array $process
- * @return void
- */
- private function updateProcessInfo($deployedPackagePath, array & $process)
- {
- $packageDeploymentInfo = $this->getPackageDeploymentInfo($deployedPackagePath . '/info.json');
- if ($packageDeploymentInfo) {
- $process['done'] = $packageDeploymentInfo['count'];
- } else {
- $process['done'] = 0;
- }
- if ($process['done'] > $process['count']) {
- $process['count'] = $process['done'];
- }
- if ($process['done'] !== $process['count']) {
- $process['elapsed'] = $this->formatterHelper->formatTime(time() - $process['start']);
- }
- $process['percent'] = floor(
- ($process['count'] ? (float)$process['done'] / $process['count'] : 0) * 100
- );
- }
- /**
- * Clear rendered lines
- *
- * @return void
- */
- private function cleanUp()
- {
- $this->lastTimeRefreshed = time();
- // Erase previous lines
- if ($this->renderedLines > 0) {
- for ($i = 0; $i < $this->renderedLines; ++$i) {
- $this->output->write("\x1B[1A\x1B[2K", false, OutputInterface::OUTPUT_RAW);
- }
- }
- $this->renderedLines = 0;
- }
- /**
- * Generate progress bar part
- *
- * @param OutputInterface $output
- * @param array $process
- * @return string
- */
- private function renderProgressBar(OutputInterface $output, array $process)
- {
- $title = "{$process['process']}";
- $titlePad = str_pad(' ', (40 - strlen($title)));
- $count = "{$process['done']}/{$process['count']}";
- $countPad = str_pad(' ', (20 - strlen($count)));
- $percent = "{$process['percent']}% ";
- $percentPad = str_pad(' ', (7 - strlen($percent)));
- return "{$title}{$titlePad}"
- . "{$count}{$countPad}"
- . "{$this->renderBar($output, $process)} "
- . "{$percent}%{$percentPad}"
- . "{$process['elapsed']} ";
- }
- /**
- * Generate progress bar row
- *
- * @param OutputInterface $output
- * @param array $process
- * @return string
- */
- private function renderBar(OutputInterface $output, array $process)
- {
- $completeBars = floor(
- $process['count'] > 0 ? ($process['done'] / $process['count']) * 28 : $process['done'] % 28
- );
- $display = str_repeat('=', $completeBars);
- if ($completeBars < 28) {
- $emptyBars = 28 - $completeBars
- - $this->formatterHelper->strlenWithoutDecoration($output->getFormatter(), '>');
- $display .= '>' . str_repeat('-', $emptyBars);
- }
- return $display;
- }
- /**
- * Retrieve package deployment process information
- *
- * @param string $relativePath
- * @return string|false
- */
- private function getPackageDeploymentInfo($relativePath)
- {
- if ($this->tmpDir->isFile($relativePath)) {
- $info = $this->tmpDir->readFile($relativePath);
- $info = json_decode($info, true);
- } else {
- $info = [];
- }
- return $info;
- }
- }
|