This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Robo\Common; |
||
4 | |||
5 | use Robo\Robo; |
||
6 | use Robo\TaskInfo; |
||
7 | use Consolidation\Log\ConsoleLogLevel; |
||
8 | use Psr\Log\LoggerAwareTrait; |
||
9 | use Psr\Log\LogLevel; |
||
10 | use Robo\Contract\ProgressIndicatorAwareInterface; |
||
11 | |||
12 | /** |
||
13 | * Task input/output methods. TaskIO is 'used' in BaseTask, so any |
||
14 | * task that extends this class has access to all of the methods here. |
||
15 | * printTaskInfo, printTaskSuccess, and printTaskError are the three |
||
16 | * primary output methods that tasks are encouraged to use. Tasks should |
||
17 | * avoid using the IO trait output methods. |
||
18 | */ |
||
19 | trait TaskIO |
||
20 | { |
||
21 | use LoggerAwareTrait; |
||
22 | use ConfigAwareTrait; |
||
23 | use VerbosityThresholdTrait; |
||
24 | |||
25 | /** |
||
26 | * @return null|\Psr\Log\LoggerInterface |
||
27 | */ |
||
28 | public function logger() |
||
29 | { |
||
30 | // $this->logger should always be set in Robo core tasks. |
||
31 | if ($this->logger) { |
||
32 | return $this->logger; |
||
33 | } |
||
34 | |||
35 | // TODO: Remove call to Robo::logger() once maintaining backwards |
||
36 | // compatibility with legacy external Robo tasks is no longer desired. |
||
37 | if (!Robo::logger()) { |
||
38 | return null; |
||
39 | } |
||
40 | |||
41 | static $gaveDeprecationWarning = false; |
||
42 | if (!$gaveDeprecationWarning) { |
||
43 | 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); |
||
44 | $gaveDeprecationWarning = true; |
||
45 | } |
||
46 | return Robo::logger(); |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Print information about a task in progress. |
||
51 | * |
||
52 | * With the Symfony Console logger, NOTICE is displayed at VERBOSITY_VERBOSE |
||
53 | * and INFO is displayed at VERBOSITY_VERY_VERBOSE. |
||
54 | * |
||
55 | * Robo overrides the default such that NOTICE is displayed at |
||
56 | * VERBOSITY_NORMAL and INFO is displayed at VERBOSITY_VERBOSE. |
||
57 | * |
||
58 | * n.b. We should probably have printTaskNotice for our ordinary |
||
59 | * output, and use printTaskInfo for less interesting messages. |
||
60 | * |
||
61 | * @param string $text |
||
62 | * @param null|array $context |
||
63 | */ |
||
64 | protected function printTaskInfo($text, $context = null) |
||
65 | { |
||
66 | // The 'note' style is used for both 'notice' and 'info' log levels; |
||
67 | // However, 'notice' is printed at VERBOSITY_NORMAL, whereas 'info' |
||
68 | // is only printed at VERBOSITY_VERBOSE. |
||
69 | $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context)); |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * Provide notification that some part of the task succeeded. |
||
74 | * |
||
75 | * With the Symfony Console logger, success messages are remapped to NOTICE, |
||
76 | * and displayed in VERBOSITY_VERBOSE. When used with the Robo logger, |
||
77 | * success messages are displayed at VERBOSITY_NORMAL. |
||
78 | * |
||
79 | * @param string $text |
||
80 | * @param null|array $context |
||
81 | */ |
||
82 | protected function printTaskSuccess($text, $context = null) |
||
83 | { |
||
84 | // Not all loggers will recognize ConsoleLogLevel::SUCCESS. |
||
85 | // We therefore log as LogLevel::NOTICE, and apply a '_level' |
||
86 | // override in the context so that this message will be |
||
87 | // logged as SUCCESS if that log level is recognized. |
||
88 | $context['_level'] = ConsoleLogLevel::SUCCESS; |
||
89 | $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context)); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Provide notification that there is something wrong, but |
||
94 | * execution can continue. |
||
95 | * |
||
96 | * Warning messages are displayed at VERBOSITY_NORMAL. |
||
97 | * |
||
98 | * @param string $text |
||
99 | * @param null|array $context |
||
100 | */ |
||
101 | protected function printTaskWarning($text, $context = null) |
||
102 | { |
||
103 | $this->printTaskOutput(LogLevel::WARNING, $text, $this->getTaskContext($context)); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Provide notification that some operation in the task failed, |
||
108 | * and the task cannot continue. |
||
109 | * |
||
110 | * Error messages are displayed at VERBOSITY_NORMAL. |
||
111 | * |
||
112 | * @param string $text |
||
113 | * @param null|array $context |
||
114 | */ |
||
115 | protected function printTaskError($text, $context = null) |
||
116 | { |
||
117 | $this->printTaskOutput(LogLevel::ERROR, $text, $this->getTaskContext($context)); |
||
118 | } |
||
119 | |||
120 | /** |
||
121 | * Provide debugging notification. These messages are only |
||
122 | * displayed if the log level is VERBOSITY_DEBUG. |
||
123 | * |
||
124 | * @param string$text |
||
125 | * @param null|array $context |
||
126 | */ |
||
127 | protected function printTaskDebug($text, $context = null) |
||
128 | { |
||
129 | $this->printTaskOutput(LogLevel::DEBUG, $text, $this->getTaskContext($context)); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * @param string $level |
||
134 | * One of the \Psr\Log\LogLevel constant |
||
135 | * @param string $text |
||
136 | * @param null|array $context |
||
137 | */ |
||
138 | protected function printTaskOutput($level, $text, $context) |
||
139 | { |
||
140 | if (!$this->verbosityMeetsThreshold()) { |
||
141 | return; |
||
142 | } |
||
143 | $logger = $this->logger(); |
||
144 | if (!$logger) { |
||
145 | return; |
||
146 | } |
||
147 | // Hide the progress indicator, if it is visible. |
||
148 | $inProgress = $this->hideTaskProgress(); |
||
149 | $logger->log($level, $text, $this->getTaskContext($context)); |
||
150 | // After we have printed our log message, redraw the progress indicator. |
||
151 | $this->showTaskProgress($inProgress); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * @return bool |
||
156 | */ |
||
157 | protected function hideTaskProgress() |
||
158 | { |
||
159 | $inProgress = false; |
||
160 | if ($this instanceof ProgressIndicatorAwareInterface) { |
||
161 | $inProgress = $this->inProgress(); |
||
162 | } |
||
163 | |||
164 | // If a progress indicator is running on this task, then we mush |
||
165 | // hide it before we print anything, or its display will be overwritten. |
||
166 | if ($inProgress) { |
||
167 | $inProgress = $this->hideProgressIndicator(); |
||
0 ignored issues
–
show
|
|||
168 | } |
||
169 | return $inProgress; |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * @param bool $inProgress |
||
174 | */ |
||
175 | protected function showTaskProgress($inProgress) |
||
176 | { |
||
177 | if ($inProgress) { |
||
178 | $this->restoreProgressIndicator($inProgress); |
||
0 ignored issues
–
show
It seems like
restoreProgressIndicator() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the
Loading history...
|
|||
179 | } |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Format a quantity of bytes. |
||
184 | * |
||
185 | * @param int $size |
||
186 | * @param int $precision |
||
187 | * |
||
188 | * @return string |
||
189 | */ |
||
190 | protected function formatBytes($size, $precision = 2) |
||
191 | { |
||
192 | if ($size === 0) { |
||
193 | return 0; |
||
194 | } |
||
195 | $base = log($size, 1024); |
||
196 | $suffixes = array('', 'k', 'M', 'G', 'T'); |
||
197 | return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Get the formatted task name for use in task output. |
||
202 | * This is placed in the task context under 'name', and |
||
203 | * used as the log label by Robo\Common\RoboLogStyle, |
||
204 | * which is inserted at the head of log messages by |
||
205 | * Robo\Common\CustomLogStyle::formatMessage(). |
||
206 | * |
||
207 | * @param null|object $task |
||
208 | * |
||
209 | * @return string |
||
210 | */ |
||
211 | protected function getPrintedTaskName($task = null) |
||
212 | { |
||
213 | if (!$task) { |
||
214 | $task = $this; |
||
215 | } |
||
216 | return TaskInfo::formatTaskName($task); |
||
0 ignored issues
–
show
It seems like
$task can also be of type this<Robo\Common\TaskIO> ; however, Robo\TaskInfo::formatTaskName() does only seem to accept object , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
217 | } |
||
218 | |||
219 | /** |
||
220 | * @param null|array $context |
||
221 | * |
||
222 | * @return array |
||
223 | * Context information. |
||
224 | */ |
||
225 | protected function getTaskContext($context = null) |
||
226 | { |
||
227 | if (!$context) { |
||
228 | $context = []; |
||
229 | } |
||
230 | if (!is_array($context)) { |
||
231 | $context = ['task' => $context]; |
||
232 | } |
||
233 | if (!array_key_exists('task', $context)) { |
||
234 | $context['task'] = $this; |
||
235 | } |
||
236 | |||
237 | return $context + TaskInfo::getTaskContext($context['task']); |
||
238 | } |
||
239 | } |
||
240 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.