1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19

20
/**
21
 * Writes a build event to the console.
22
 *
23
 * Currently, it only writes which targets are being executed, and
24
 * any messages that get logged.
25
 *
26
 * @author    Andreas Aderhold <andi@binarycloud.com>
27
 * @copyright 2001,2002 THYRELL. All rights reserved
28
 * @see       BuildEvent
29
 * @package   phing.listener
30
 */
31
class DefaultLogger implements StreamRequiredBuildLogger
32
{
33

34
    /**
35
     *  Size of the left column in output. The default char width is 12.
36
     *
37
     * @var int
38
     */
39
    public const LEFT_COLUMN_SIZE = 12;
40

41
    /**
42
     *  The message output level that should be used. The default is
43
     *  <code>Project::MSG_VERBOSE</code>.
44
     *
45
     * @var int
46
     */
47
    protected $msgOutputLevel = Project::MSG_ERR;
48

49
    /**
50
     *  Time that the build started
51
     *
52
     * @var int
53
     */
54
    protected $startTime;
55

56
    /**
57
     * @var OutputStream Stream to use for standard output.
58
     */
59
    protected $out;
60

61
    /**
62
     * @var OutputStream Stream to use for error output.
63
     */
64
    protected $err;
65

66
    protected $emacsMode = false;
67

68
    /**
69
     *  Construct a new default logger.
70
     */
71 1
    public function __construct()
72
    {
73
    }
74

75
    /**
76
     *  Set the msgOutputLevel this logger is to respond to.
77
     *
78
     *  Only messages with a message level lower than or equal to the given
79
     *  level are output to the log.
80
     *
81
     *  <p> Constants for the message levels are in Project.php. The order of
82
     *  the levels, from least to most verbose, is:
83
     *
84
     *  <ul>
85
     *    <li>Project::MSG_ERR</li>
86
     *    <li>Project::MSG_WARN</li>
87
     *    <li>Project::MSG_INFO</li>
88
     *    <li>Project::MSG_VERBOSE</li>
89
     *    <li>Project::MSG_DEBUG</li>
90
     *  </ul>
91
     *
92
     *  The default message level for DefaultLogger is Project::MSG_ERR.
93
     *
94
     * @param int $level The logging level for the logger.
95
     * @see   BuildLogger#setMessageOutputLevel()
96
     */
97 1
    public function setMessageOutputLevel($level)
98
    {
99 1
        $this->msgOutputLevel = (int) $level;
100
    }
101

102
    /**
103
     * Sets the output stream.
104
     *
105
     * @param OutputStream $output
106
     * @see   BuildLogger#setOutputStream()
107
     */
108 1
    public function setOutputStream(OutputStream $output)
109
    {
110 1
        $this->out = $output;
111
    }
112

113
    /**
114
     * Sets the error stream.
115
     *
116
     * @param OutputStream $err
117
     * @see   BuildLogger#setErrorStream()
118
     */
119 1
    public function setErrorStream(OutputStream $err)
120
    {
121 1
        $this->err = $err;
122
    }
123

124
    /**
125
     * Sets this logger to produce emacs (and other editor) friendly output.
126
     *
127
     * @param bool $emacsMode <code>true</code> if output is to be unadorned so that
128
     *                  emacs and other editors can parse files names, etc.
129
     */
130 0
    public function setEmacsMode($emacsMode)
131
    {
132 0
        $this->emacsMode = $emacsMode;
133
    }
134

135
    /**
136
     *  Sets the start-time when the build started. Used for calculating
137
     *  the build-time.
138
     *
139
     * @param BuildEvent $event
140
     */
141 0
    public function buildStarted(BuildEvent $event)
142
    {
143 0
        $this->startTime = Phing::currentTimeMillis();
144 0
        if ($this->msgOutputLevel >= Project::MSG_INFO) {
145 0
            $this->printMessage(
146 0
                "Buildfile: " . $event->getProject()->getProperty("phing.file"),
147 0
                $this->out,
148 0
                Project::MSG_INFO
149
            );
150
        }
151
    }
152

153
    /**
154
     *  Prints whether the build succeeded or failed, and any errors that
155
     *  occurred during the build. Also outputs the total build-time.
156
     *
157
     * @param BuildEvent $event
158
     * @see   BuildEvent::getException()
159
     */
160 1
    public function buildFinished(BuildEvent $event)
161
    {
162 1
        $msg = PHP_EOL . $this->getBuildSuccessfulMessage() . PHP_EOL;
163 1
        $error = $event->getException();
164

165 1
        if ($error !== null) {
166 1
            $msg = PHP_EOL . $this->getBuildFailedMessage() . PHP_EOL;
167

168 1
            self::throwableMessage($msg, $error, Project::MSG_VERBOSE <= $this->msgOutputLevel);
169
        }
170 1
        $msg .= PHP_EOL . "Total time: " . static::formatTime(Phing::currentTimeMillis() - $this->startTime) . PHP_EOL;
171

172 1
        $error === null
173 1
            ? $this->printMessage($msg, $this->out, Project::MSG_VERBOSE)
174 1
            : $this->printMessage($msg, $this->err, Project::MSG_ERR);
175
    }
176

177 1
    public static function throwableMessage(&$msg, $error, $verbose)
178
    {
179 1
        while ($error instanceof BuildException) {
180 1
            $cause = $error->getPrevious();
181 1
            if ($cause === null) {
182 1
                break;
183
            }
184 1
            $msg1 = trim($error);
185 1
            $msg2 = trim($cause);
186 1
            if (StringHelper::endsWith($msg2, $msg1)) {
187 1
                $msg .= StringHelper::substring($msg1, 0, strlen($msg1) - strlen($msg2) - 1);
188 1
                $error = $cause;
189
            } else {
190 0
                break;
191
            }
192
        }
193 1
        $msg .= $verbose || !$error instanceof BuildException
194 1
            ? $error->getMessage() . PHP_EOL . $error->getTraceAsString() . PHP_EOL
195 1
            : $error->getLocation() . ' ' . $error->getMessage() . PHP_EOL;
196
    }
197

198
    /**
199
     * Get the message to return when a build failed.
200
     *
201
     * @return string The classic "BUILD FAILED"
202
     */
203 1
    protected function getBuildFailedMessage()
204
    {
205 1
        return "BUILD FAILED";
206
    }
207

208
    /**
209
     * Get the message to return when a build succeeded.
210
     *
211
     * @return string The classic "BUILD FINISHED"
212
     */
213 1
    protected function getBuildSuccessfulMessage()
214
    {
215 1
        return "BUILD FINISHED";
216
    }
217

218
    /**
219
     *  Prints the current target name
220
     *
221
     * @param BuildEvent $event
222
     * @see   BuildEvent::getTarget()
223
     */
224 1
    public function targetStarted(BuildEvent $event)
225
    {
226
        if (
227 1
            Project::MSG_INFO <= $this->msgOutputLevel
228 1
            && $event->getTarget()->getName() != ''
229
        ) {
230 1
            $showLongTargets = $event->getProject()->getProperty("phing.showlongtargets");
231 1
            $msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ($showLongTargets ? ' [' . $event->getTarget()->getDescription() . ']' : '') . ':' . PHP_EOL;
232 1
            $this->printMessage($msg, $this->out, $event->getPriority());
233
        }
234
    }
235

236
    /**
237
     *  Fired when a target has finished. We don't need specific action on this
238
     *  event. So the methods are empty.
239
     *
240
     * @param BuildEvent $event
241
     * @see   BuildEvent::getException()
242
     */
243 1
    public function targetFinished(BuildEvent $event)
244
    {
245
    }
246

247
    /**
248
     *  Fired when a task is started. We don't need specific action on this
249
     *  event. So the methods are empty.
250
     *
251
     * @param BuildEvent $event
252
     * @see   BuildEvent::getTask()
253
     */
254 1
    public function taskStarted(BuildEvent $event)
255
    {
256
    }
257

258
    /**
259
     *  Fired when a task has finished. We don't need specific action on this
260
     *  event. So the methods are empty.
261
     *
262
     * @param BuildEvent $event The BuildEvent
263
     * @see   BuildEvent::getException()
264
     */
265 1
    public function taskFinished(BuildEvent $event)
266
    {
267
    }
268

269
    /**
270
     *  Print a message to the stdout.
271
     *
272
     * @param BuildEvent $event
273
     * @see   BuildEvent::getMessage()
274
     */
275 1
    public function messageLogged(BuildEvent $event)
276
    {
277 1
        $priority = $event->getPriority();
278 1
        if ($priority <= $this->msgOutputLevel) {
279 1
            $msg = "";
280 1
            if ($event->getTask() !== null && !$this->emacsMode) {
281 1
                $name = $event->getTask();
282 1
                $name = $name->getTaskName();
283 1
                $msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT);
284
            }
285

286 1
            $msg .= $event->getMessage();
287

288 1
            if ($priority != Project::MSG_ERR) {
289 1
                $this->printMessage($msg, $this->out, $priority);
290
            } else {
291 0
                $this->printMessage($msg, $this->err, $priority);
292
            }
293
        }
294
    }
295

296
    /**
297
     *  Formats a time micro integer to human readable format.
298
     *
299
     * @param  integer The time stamp
300
     * @return string
301
     */
302 1
    public static function formatTime($micros)
303
    {
304 1
        $seconds = $micros;
305 1
        $minutes = (int) floor($seconds / 60);
306 1
        if ($minutes >= 1) {
307 0
            return sprintf(
308 0
                "%1.0f minute%s %0.2f second%s",
309 0
                $minutes,
310 0
                ($minutes === 1 ? " " : "s "),
311 0
                $seconds - floor($seconds / 60) * 60,
312 0
                ($seconds % 60 === 1 ? "" : "s")
313
            );
314
        }
315

316 1
        return sprintf("%0.4f second%s", $seconds, ($seconds % 60 === 1 ? "" : "s"));
317
    }
318

319
    /**
320
     * Prints a message to console.
321
     *
322
     * @param  string $message The message to print.
323
     *                                         Should not be
324
     *                                         <code>null</code>.
325
     * @param  OutputStream|resource $stream The stream to use for message printing.
326
     * @param  int $priority The priority of the message.
327
     *                                         (Ignored in this
328
     *                                         implementation.)
329
     * @throws IOException
330
     * @return void
331
     */
332 1
    protected function printMessage($message, OutputStream $stream, $priority)
333
    {
334 1
        $stream->write($message . PHP_EOL);
335
    }
336
}

Read our documentation on viewing source code .

Loading