mirror of
https://github.com/bdnugget/magento2.git
synced 2026-11-07 09:17:35 +00:00
317 lines
9.0 KiB
PHP
317 lines
9.0 KiB
PHP
<?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
|
|
*/
|
|
public const INFO = 'info';
|
|
|
|
/**
|
|
* Type for error message
|
|
*/
|
|
public 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 = []): void
|
|
{
|
|
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
|
|
- FormatterHelper::width($this->formatterHelper->removeDecoration($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;
|
|
}
|
|
}
|