logger should always be set in Robo core tasks. if ($this->logger) { return $this->logger; } // TODO: Remove call to Robo::logger() once maintaining backwards // compatibility with legacy external Robo tasks is no longer desired. if (!Robo::logger()) { return null; } static $gaveDeprecationWarning = false; if (!$gaveDeprecationWarning) { trigger_error('No logger set for ' . get_class($this) . '. Use $this->task(Foo::class) rather than new Foo() in loadTasks to ensure the builder can initialize task the task, or use $this->collectionBuilder()->taskFoo() if creating one task from within another.', E_USER_DEPRECATED); $gaveDeprecationWarning = true; } return Robo::logger(); } /** * Print information about a task in progress. * * With the Symfony Console logger, NOTICE is displayed at VERBOSITY_VERBOSE * and INFO is displayed at VERBOSITY_VERY_VERBOSE. * * Robo overrides the default such that NOTICE is displayed at * VERBOSITY_NORMAL and INFO is displayed at VERBOSITY_VERBOSE. * * n.b. We should probably have printTaskNotice for our ordinary * output, and use printTaskInfo for less interesting messages. * * @param string $text * @param null|array $context */ protected function printTaskInfo($text, $context = null) { // The 'note' style is used for both 'notice' and 'info' log levels; // However, 'notice' is printed at VERBOSITY_NORMAL, whereas 'info' // is only printed at VERBOSITY_VERBOSE. $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context)); } /** * Provide notification that some part of the task succeeded. * * With the Symfony Console logger, success messages are remapped to NOTICE, * and displayed in VERBOSITY_VERBOSE. When used with the Robo logger, * success messages are displayed at VERBOSITY_NORMAL. * * @param string $text * @param null|array $context */ protected function printTaskSuccess($text, $context = null) { // Not all loggers will recognize ConsoleLogLevel::SUCCESS. // We therefore log as LogLevel::NOTICE, and apply a '_level' // override in the context so that this message will be // logged as SUCCESS if that log level is recognized. $context['_level'] = ConsoleLogLevel::SUCCESS; $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context)); } /** * Provide notification that there is something wrong, but * execution can continue. * * Warning messages are displayed at VERBOSITY_NORMAL. * * @param string $text * @param null|array $context */ protected function printTaskWarning($text, $context = null) { $this->printTaskOutput(LogLevel::WARNING, $text, $this->getTaskContext($context)); } /** * Provide notification that some operation in the task failed, * and the task cannot continue. * * Error messages are displayed at VERBOSITY_NORMAL. * * @param string $text * @param null|array $context */ protected function printTaskError($text, $context = null) { $this->printTaskOutput(LogLevel::ERROR, $text, $this->getTaskContext($context)); } /** * Provide debugging notification. These messages are only * displayed if the log level is VERBOSITY_DEBUG. * * @param string$text * @param null|array $context */ protected function printTaskDebug($text, $context = null) { $this->printTaskOutput(LogLevel::DEBUG, $text, $this->getTaskContext($context)); } /** * @param string $level * One of the \Psr\Log\LogLevel constant * @param string $text * @param null|array $context */ protected function printTaskOutput($level, $text, $context) { if (!$this->verbosityMeetsThreshold()) { return; } $logger = $this->logger(); if (!$logger) { return; } // Hide the progress indicator, if it is visible. $inProgress = $this->hideTaskProgress(); $logger->log($level, $text, $this->getTaskContext($context)); // After we have printed our log message, redraw the progress indicator. $this->showTaskProgress($inProgress); } /** * @return bool */ protected function hideTaskProgress() { $inProgress = false; if ($this instanceof ProgressIndicatorAwareInterface) { $inProgress = $this->inProgress(); } // If a progress indicator is running on this task, then we mush // hide it before we print anything, or its display will be overwritten. if ($inProgress) { $inProgress = $this->hideProgressIndicator(); } return $inProgress; } /** * @param $inProgress */ protected function showTaskProgress($inProgress) { if ($inProgress) { $this->restoreProgressIndicator($inProgress); } } /** * Format a quantity of bytes. * * @param int $size * @param int $precision * * @return string */ protected function formatBytes($size, $precision = 2) { if ($size === 0) { return 0; } $base = log($size, 1024); $suffixes = array('', 'k', 'M', 'G', 'T'); return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; } /** * Get the formatted task name for use in task output. * This is placed in the task context under 'name', and * used as the log label by Robo\Common\RoboLogStyle, * which is inserted at the head of log messages by * Robo\Common\CustomLogStyle::formatMessage(). * * @param null|object $task * * @return string */ protected function getPrintedTaskName($task = null) { if (!$task) { $task = $this; } return TaskInfo::formatTaskName($task); } /** * @param null|array $context * * @return array with context information */ protected function getTaskContext($context = null) { if (!$context) { $context = []; } if (!is_array($context)) { $context = ['task' => $context]; } if (!array_key_exists('task', $context)) { $context['task'] = $this; } return $context + TaskInfo::getTaskContext($context['task']); } }