Completed
Push — master ( 759854...e46a01 )
by Martin
13:10 queued 03:41
created

Workflow::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 5
1
<?php
2
3
namespace Yep\WorkflowLogger;
4
5
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yep\WorkflowLogger\LoggerInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Yep\WorkflowLogger\Exception\LevelIsNotDefinedException;
7
use Yep\WorkflowLogger\Formatter\FormatterInterface;
8
9
/**
10
 * Class Workflow
11
 *
12
 * @package Yep\WorkflowLogger
13
 * @author  Martin Zeman (Zemistr) <[email protected]>
14
 */
15
class Workflow implements LoggerInterface
16
{
17
    const EMERGENCY = 'emergency';
18
    const ALERT = 'alert';
19
    const CRITICAL = 'critical';
20
    const ERROR = 'error';
21
    const WARNING = 'warning';
22
    const NOTICE = 'notice';
23
    const INFO = 'info';
24
    const DEBUG = 'debug';
25
26
    /**
27
     * Logging levels from syslog protocol defined in RFC 5424
28
     *
29
     * @var array|string[] $levels Logging levels
30
     */
31
    protected static $levels = [
32
      self::DEBUG => 'DEBUG',
33
      self::INFO => 'INFO',
34
      self::NOTICE => 'NOTICE',
35
      self::WARNING => 'WARNING',
36
      self::ERROR => 'ERROR',
37
      self::CRITICAL => 'CRITICAL',
38
      self::ALERT => 'ALERT',
39
      self::EMERGENCY => 'EMERGENCY',
40
    ];
41
42
    /**
43
     * @var int|string
44
     */
45
    private $level;
46
47
    /**
48
     * @var FormatterInterface
49
     */
50
    protected $formatter;
51
52
    /**
53
     * @var Logger
54
     */
55
    protected $logger;
56
57
    /**
58
     * @var string
59
     */
60
    protected $name;
61
62
    /**
63
     * @var array|Record[]
64
     */
65
    protected $records = [];
66
67
    /**
68
     * @var \DateTimeZone
69
     */
70
    protected $timezone;
71
72
    /**
73
     * Workflow constructor.
74
     *
75
     * @param LoggerInterface    $logger    Main logger
76
     * @param FormatterInterface $formatter Workflow records formatter
77
     * @param \DateTimeZone      $timezone  Current timezone
78
     * @param string             $name      Workflow name
79
     * @param int|string         $level     Workflow level code
80
     */
81
    public function __construct(
82
      LoggerInterface $logger,
83
      FormatterInterface $formatter,
84
      \DateTimeZone $timezone,
85
      $name,
86
      $level
87
    ) {
88
        $this->logger = $logger;
0 ignored issues
show
Documentation Bug introduced by
$logger is of type Psr\Log\LoggerInterface, but the property $logger was declared to be of type Yep\WorkflowLogger\Logger. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
89
        $this->formatter = $formatter;
90
        $this->timezone = $timezone;
91
        $this->name = (string)$name;
92
        $this->level = $level;
93
    }
94
95
    /**
96
     * @return \DateTime
97
     */
98
    protected function getCurrentDateTime()
99
    {
100
        $time = new \DateTime(null, $this->timezone);
101
        $time->setTimezone($this->timezone);
102
103
        return $time;
104
    }
105
106
    /**
107
     * @return string
108
     */
109
    public function getName()
110
    {
111
        return $this->name;
112
    }
113
114
    /**
115
     * @return int|string
116
     */
117
    public function getLevel()
118
    {
119
        return $this->level;
120
    }
121
122
    /**
123
     * Gets the name of the logging level.
124
     *
125
     * @param string $level
126
     * @return string
127
     * @throws LevelIsNotDefinedException
128
     */
129
    public function getLevelName($level)
130
    {
131
        if (!isset(static::$levels[$level])) {
132
            throw LevelIsNotDefinedException::create($level, static::$levels);
133
        }
134
135
        return static::$levels[$level];
136
    }
137
138
    /**
139
     * Logs with a workflow level and with all workflow records
140
     *
141
     * @param  string $message The log message
142
     * @param  array  $context The log context
143
     * @return void
144
     */
145
    public function finish($message = '', array $context = [])
146
    {
147
        $message .= $message === '' ? '' : "\n\n";
148
        $message .= "Workflow: {$this->getName()}\n";
149
150
        foreach ($this->records as $record) {
151
            $message .= $this->formatter->format($record);
152
        }
153
154
        $this->logger->log($this->level, $message, $context);
155
    }
156
157
    /**
158
     * Logs workflow record with an arbitrary level.
159
     *
160
     * @param  int    $level   The logging level
161
     * @param  string $message The log message
162
     * @param  array  $context The log context
163
     * @return void
164
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
165
     */
166
    public function log($level, $message, array $context = [])
167
    {
168
        $this->records[] = new Record(
169
          $this->getCurrentDateTime(),
170
          $message,
171
          $this->getLevelName($level),
172
          $context
173
        );
174
    }
175
176
    /**
177
     * System is unusable.
178
     *
179
     * @param  string $message The log message
180
     * @param  array  $context The log context
181
     * @return void
182
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
183
     */
184
    public function emergency($message, array $context = [])
185
    {
186
        $this->log(self::EMERGENCY, $message, $context);
0 ignored issues
show
Bug introduced by
self::EMERGENCY of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
        $this->log(/** @scrutinizer ignore-type */ self::EMERGENCY, $message, $context);
Loading history...
187
    }
188
189
    /**
190
     * Action must be taken immediately.
191
     *
192
     * Example: Entire website down, database unavailable, etc. This should
193
     * trigger the SMS alerts and wake you up.
194
     *
195
     * @param  string $message The log message
196
     * @param  array  $context The log context
197
     * @return void
198
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
199
     */
200
    public function alert($message, array $context = [])
201
    {
202
        $this->log(self::ALERT, $message, $context);
0 ignored issues
show
Bug introduced by
self::ALERT of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
        $this->log(/** @scrutinizer ignore-type */ self::ALERT, $message, $context);
Loading history...
203
    }
204
205
    /**
206
     * Critical conditions.
207
     *
208
     * Example: Application component unavailable, unexpected exception.
209
     *
210
     * @param  string $message The log message
211
     * @param  array  $context The log context
212
     * @return void
213
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
214
     */
215
    public function critical($message, array $context = [])
216
    {
217
        $this->log(self::CRITICAL, $message, $context);
0 ignored issues
show
Bug introduced by
self::CRITICAL of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

217
        $this->log(/** @scrutinizer ignore-type */ self::CRITICAL, $message, $context);
Loading history...
218
    }
219
220
    /**
221
     * Runtime errors that do not require immediate action but should typically
222
     * be logged and monitored.
223
     *
224
     * @param  string $message The log message
225
     * @param  array  $context The log context
226
     * @return void
227
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
228
     */
229
    public function error($message, array $context = [])
230
    {
231
        $this->log(self::ERROR, $message, $context);
0 ignored issues
show
Bug introduced by
self::ERROR of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

231
        $this->log(/** @scrutinizer ignore-type */ self::ERROR, $message, $context);
Loading history...
232
    }
233
234
    /**
235
     * Exceptional occurrences that are not errors.
236
     *
237
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
238
     * that are not necessarily wrong.
239
     *
240
     * @param  string $message The log message
241
     * @param  array  $context The log context
242
     * @return void
243
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
244
     */
245
    public function warning($message, array $context = [])
246
    {
247
        $this->log(self::WARNING, $message, $context);
0 ignored issues
show
Bug introduced by
self::WARNING of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
        $this->log(/** @scrutinizer ignore-type */ self::WARNING, $message, $context);
Loading history...
248
    }
249
250
    /**
251
     * Normal but significant events.
252
     *
253
     * @param  string $message The log message
254
     * @param  array  $context The log context
255
     * @return void
256
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
257
     */
258
    public function notice($message, array $context = [])
259
    {
260
        $this->log(self::NOTICE, $message, $context);
0 ignored issues
show
Bug introduced by
self::NOTICE of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

260
        $this->log(/** @scrutinizer ignore-type */ self::NOTICE, $message, $context);
Loading history...
261
    }
262
263
    /**
264
     * Interesting events.
265
     *
266
     * Example: User logs in, SQL logs.
267
     *
268
     * @param  string $message The log message
269
     * @param  array  $context The log context
270
     * @return void
271
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
272
     */
273
    public function info($message, array $context = [])
274
    {
275
        $this->log(self::INFO, $message, $context);
0 ignored issues
show
Bug introduced by
self::INFO of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

275
        $this->log(/** @scrutinizer ignore-type */ self::INFO, $message, $context);
Loading history...
276
    }
277
278
    /**
279
     * Detailed debug information.
280
     *
281
     * @param  string $message The log message
282
     * @param  array  $context The log context
283
     * @return void
284
     * @throws \Yep\WorkflowLogger\Exception\LevelIsNotDefinedException
285
     */
286
    public function debug($message, array $context = [])
287
    {
288
        $this->log(self::DEBUG, $message, $context);
0 ignored issues
show
Bug introduced by
self::DEBUG of type string is incompatible with the type integer expected by parameter $level of Yep\WorkflowLogger\Workflow::log(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

288
        $this->log(/** @scrutinizer ignore-type */ self::DEBUG, $message, $context);
Loading history...
289
    }
290
}
291