Passed
Push — master ( fc3908...7f24ff )
by
unknown
01:22 queued 10s
created

QueueItemTrait::logProcessingException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Charcoal\Queue;
4
5
use DateInterval;
6
use DateTime;
7
use DateTimeInterface;
8
use Exception;
9
use InvalidArgumentException;
10
11
/**
12
 *
13
 */
14
trait QueueItemTrait
15
{
16
    /**
17
     * The queue ID.
18
     *
19
     * @var mixed $queueId
20
     */
21
    private $queueId;
22
23
    /**
24
     * Whether the item has been processed.
25
     *
26
     * @var boolean $processed
27
     */
28
    private $processed = false;
29
30
    /**
31
     * When the item was queued.
32
     *
33
     * @var DateTimeInterface|null $queuedDate
34
     */
35
    private $queuedDate;
36
37
    /**
38
     * When the item should be processed.
39
     *
40
     * The date/time at which this queue item job should be ran.
41
     * If NULL, 0, or a past date/time, then it should be performed immediately.
42
     *
43
     * @var DateTimeInterface|null $processingDate
44
     */
45
    private $processingDate;
46
47
    /**
48
     * When the item was processed.
49
     *
50
     * @var DateTimeInterface|null $processedDate
51
     */
52
    private $processedDate;
53
54
    /**
55
     * When the item should be considered expired.
56
     *
57
     * The date/time at which this queue item job should expire and be prevented to fire.
58
     * If NULL, 0, or a future date/time, then it should be allowed to be performed.
59
     *
60
     * @var DateTimeInterface|null $lexpiryDate
61
     */
62
    private $expiryDate;
63
64
    /**
65
     * Default amount of seconds before expiry after processing date.
66
     *
67
     * @var integer $defaultExpiryInSeconde
68
     */
69
    private $defaultExpiryInSeconds = 86400;
70
71
    /**
72
     * The status of the queue item.
73
     *
74
     * @var string
75
     */
76
    private $status;
77
78
    /**
79
     * Process the item.
80
     *
81
     * @param  callable $alwaysCallback  An optional callback routine executed after the item is processed.
82
     * @param  callable $successCallback An optional callback routine executed when the item is resolved.
83
     * @param  callable $failureCallback An optional callback routine executed when the item is rejected.
84
     * @return boolean|null Returns TRUE i this item was successfully processed,
85
     *     FALSE on failure or if an error occurs, NULL if this item is already processed.
86
     */
87
    abstract public function process(
88
        callable $alwaysCallback = null,
89
        callable $successCallback = null,
90
        callable $failureCallback = null
91
    );
92
93
    /**
94
     * @param Exception $e Exception to log.
95
     * @return void
96
     */
97
    protected function logProcessingException(Exception $e)
98
    {
99
        $this->logger->error(
0 ignored issues
show
Bug introduced by
The property logger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
100
            sprintf('Could not process a queue item: %s', $e->getMessage()),
101
            [
102
                'manager' => get_called_class(),
103
                'queueId' => $this->queueId(),
104
                'itemId'  => $this->id(),
0 ignored issues
show
Bug introduced by
It seems like id() 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 Idable provides a method equalsId that in turn relies on the method getId(). 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.

Loading history...
105
            ]
106
        );
107
    }
108
109
    /**
110
     * Set the queue item's data.
111
     *
112
     * @param array $data The queue item data to set.
113
     * @return self
114
     */
115
    public function setQueueItemData(array $data)
116
    {
117
        if (isset($data['queue_id'])) {
118
            $this->setQueueId($data['queue_id']);
119
        }
120
121
        if (isset($data['processed'])) {
122
            $this->setProcessed($data['processed']);
123
        }
124
125
        if (isset($data['queued_date'])) {
126
            $this->setQueuedDate($data['queue_date']);
127
        }
128
129
        if (isset($data['processed_date'])) {
130
            $this->setProcessedDate($data['processed_date']);
131
        }
132
133
        return $this;
134
    }
135
136
    /**
137
     * Set the queue's ID.
138
     *
139
     * @param mixed $id The unique queue identifier.
140
     * @return self
141
     */
142
    public function setQueueId($id)
143
    {
144
        $this->queueId = $id;
145
        return $this;
146
    }
147
148
    /**
149
     * Get the queue's ID.
150
     *
151
     * @return mixed
152
     */
153
    public function queueId()
154
    {
155
        return $this->queueId;
156
    }
157
158
    /**
159
     * Set the item's processed status.
160
     *
161
     * @param boolean $processed Whether the item has been processed.
162
     * @return self
163
     */
164
    public function setProcessed($processed)
165
    {
166
        $this->processed = !!$processed;
167
        return $this;
168
    }
169
170
    /**
171
     * Determine if the item has been processed.
172
     *
173
     * @return boolean
174
     */
175
    public function processed()
176
    {
177
        return $this->processed;
178
    }
179
180
    /**
181
     * Set the date/time the item was queued at.
182
     *
183
     * @param  null|string|DateTimeInterface $ts A date/time string or object.
184
     * @throws InvalidArgumentException If the date/time is invalid.
185
     * @return self
186
     */
187 View Code Duplication
    public function setQueuedDate($ts)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188
    {
189
        if ($ts === null) {
190
            $this->queuedDate = null;
191
            return $this;
192
        }
193
194
        if (is_string($ts)) {
195
            try {
196
                $ts = new DateTime($ts);
197
            } catch (Exception $e) {
198
                throw new InvalidArgumentException(
199
                    sprintf('Can not set queued date: %s', $e->getMessage())
200
                );
201
            }
202
        }
203
204
        if (!($ts instanceof DateTimeInterface)) {
205
            throw new InvalidArgumentException(
206
                'Invalid "Queued Date" value. Must be a date/time string or a DateTime object.'
207
            );
208
        }
209
210
        $this->queuedDate = $ts;
211
212
        return $this;
213
    }
214
215
    /**
216
     * Retrieve the date/time the item was queued at.
217
     *
218
     * @return null|\DateTimeInterface
219
     */
220
    public function queuedDate()
221
    {
222
        return $this->queuedDate;
223
    }
224
225
    /**
226
     * Set the date/time the item should be processed at.
227
     *
228
     * @param  null|string|\DateTimeInterface $ts A date/time string or object.
229
     * @throws InvalidArgumentException If the date/time is invalid.
230
     * @return self
231
     */
232 View Code Duplication
    public function setProcessingDate($ts)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
233
    {
234
        if ($ts === null) {
235
            $this->processingDate = null;
236
            return $this;
237
        }
238
239
        if (is_string($ts)) {
240
            try {
241
                $ts = new DateTime($ts);
242
            } catch (Exception $e) {
243
                throw new InvalidArgumentException(
244
                    sprintf('%s (%s)', $e->getMessage(), $ts)
245
                );
246
            }
247
        }
248
249
        if (!($ts instanceof DateTimeInterface)) {
250
            throw new InvalidArgumentException(
251
                'Invalid "Processing Date" value. Must be a date/time string or a DateTime object.'
252
            );
253
        }
254
255
        $this->processingDate = $ts;
256
257
        return $this;
258
    }
259
260
    /**
261
     * Retrieve the date/time the item should be processed at.
262
     *
263
     * @return null|\DateTimeInterface
264
     */
265
    public function processingDate()
266
    {
267
        return $this->processingDate;
268
    }
269
270
    /**
271
     * Set the date/time the item was processed at.
272
     *
273
     * @param  null|string|\DateTimeInterface $ts A date/time string or object.
274
     * @throws InvalidArgumentException If the date/time is invalid.
275
     * @return self
276
     */
277 View Code Duplication
    public function setProcessedDate($ts)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278
    {
279
        if ($ts === null) {
280
            $this->processedDate = null;
281
            return $this;
282
        }
283
284
        if (is_string($ts)) {
285
            try {
286
                $ts = new DateTime($ts);
287
            } catch (Exception $e) {
288
                throw new InvalidArgumentException(
289
                    sprintf('%s (%s)', $e->getMessage(), $ts)
290
                );
291
            }
292
        }
293
294
        if (!($ts instanceof DateTimeInterface)) {
295
            throw new InvalidArgumentException(
296
                'Invalid "Processed Date" value. Must be a date/time string or a DateTime object.'
297
            );
298
        }
299
300
        $this->processedDate = $ts;
301
302
        return $this;
303
    }
304
305
    /**
306
     * Retrieve the date/time the item was processed at.
307
     *
308
     * @return null|\DateTimeInterface
309
     */
310
    public function processedDate()
311
    {
312
        return $this->processedDate;
313
    }
314
315
    /**
316
     * Retrieve the date/time the item should be expired at.
317
     *
318
     * @return null|\DateTimeInterface
319
     */
320
    public function expiryDate()
321
    {
322
        return $this->expiryDate;
323
    }
324
325
    /**
326
     * Set the date/time the item will expire at.
327
     *
328
     * @param  null|string|\DateTimeInterface $ts A date/time string or object.
329
     * @throws InvalidArgumentException If the date/time is invalid.
330
     * @return self
331
     */
332 View Code Duplication
    public function setExpiryDate($ts)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
333
    {
334
        if ($ts === null) {
335
            $this->expiryDate = null;
336
            return $this;
337
        }
338
339
        if (is_string($ts)) {
340
            try {
341
                $ts = new DateTime($ts);
342
            } catch (Exception $e) {
343
                throw new InvalidArgumentException(
344
                    sprintf('%s (%s)', $e->getMessage(), $ts)
345
                );
346
            }
347
        }
348
349
        if (!($ts instanceof DateTimeInterface)) {
350
            throw new InvalidArgumentException(
351
                'Invalid "Expiry Date" value. Must be a date/time string or a DateTime object.'
352
            );
353
        }
354
355
        $this->expiryDate = $ts;
356
357
        return $this;
358
    }
359
360
    /**
361
     * @return string
362
     */
363
    public function status()
364
    {
365
        return $this->status;
366
    }
367
368
    /**
369
     * @param string $status Status for QueueItemTrait.
370
     * @return self
371
     */
372
    public function setStatus($status)
373
    {
374
        $this->status = $status;
375
376
        return $this;
377
    }
378
379
    /**
380
     * Hook called before saving the item.
381
     *
382
     * Presets the item as _to-be_ processed and queued now.
383
     *
384
     * @return self
385
     */
386
    protected function preSaveQueueItem()
387
    {
388
        $this->setProcessed(false);
389
        $this->setQueuedDate('now');
390
391
        if (!$this->expiryDate()) {
392
            $this->generateExpiry();
393
        }
394
395
        return $this;
396
    }
397
398
    /**
399
     * Generate an expiry date based on the default interval and the scheduled processing date.
400
     *
401
     * @return self
402
     */
403
    protected function generateExpiry()
404
    {
405
        $date = (clone $this['processingDate'] ?? new DateTime());
406
        $date->add(new DateInterval('PT'.$this->defaultExpiryInSeconds.'S'));
407
408
        return $this->setExpiryDate($date);
409
    }
410
}
411