-
Notifications
You must be signed in to change notification settings - Fork 305
/
Copy pathTaskIO.php
268 lines (245 loc) · 8.02 KB
/
TaskIO.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
<?php
namespace Robo\Common;
use Robo\Robo;
use Robo\TaskInfo;
use Consolidation\Log\ConsoleLogLevel;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Robo\Contract\ProgressIndicatorAwareInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Task input/output methods. TaskIO is 'used' in BaseTask, so any
* task that extends this class has access to all of the methods here.
* printTaskInfo, printTaskSuccess, and printTaskError are the three
* primary output methods that tasks are encouraged to use. Tasks should
* avoid using the IO trait output methods.
*/
trait TaskIO
{
use ConfigAwareTrait;
use VerbosityThresholdTrait;
use OutputAwareTrait;
protected $logger;
protected $output;
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
$this->resetLoggerOutput();
}
public function setOutput(OutputInterface $output)
{
$this->output = $output;
$this->resetLoggerOutput();
}
private function resetLoggerOutput()
{
if (isset($this->output) && isset($this->logger) && ($this->logger instanceof \Robo\Log\Logger)) {
$this->logger->setErrorStream(null);
$this->logger->setOutputStream($this->output);
}
}
/**
* @return null|\Psr\Log\LoggerInterface
*
* @deprecated
*/
public function logger()
{
// $this->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 Tasks 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
*
* @deprecated
*/
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 bool $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
* 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']);
}
}