GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — 3.0 ( 5276e1...94e02b )
by Vermeulen
01:25
created

Dates::getMonth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BFW\Helpers;
4
5
use \DateTime;
6
use \Exception;
7
8
/**
9
 * Class to have shortcuts to DateTime(Zone) methods and to display a date
10
 * with words and not only numbers (today, yesterday, since... etc).
11
 */
12
class Dates extends DateTime
13
{
14
    /**
15
     * @var string[] $humanReadableI18n Words used in method to transform
16
     *  date difference to human readable.
17
     */
18
    protected static $humanReadableI18n = [
19
        'now'          => 'now',
20
        'today_past'   => '{time} ago',
21
        'today_future' => 'in {time}',
22
        'yesterday'    => 'yesterday',
23
        'tomorrow'     => 'tomorrow',
24
        'others'       => 'the {date}',
25
        'time_part'    => ' at {time}'
26
    ];
27
28
    /**
29
     * @var string[] $humanReadableFormats Date and time formats used in
30
     *  method to transform date difference to human readable.
31
     */
32
    protected static $humanReadableFormats = [
33
        'dateSameYear'      => 'm-d',
34
        'dateDifferentYear' => 'Y-m-d',
35
        'time'              => 'H:i'
36
    ];
37
38
    /**
39
     * Return the value of the humanReadableI18n property
40
     * 
41
     * @return string[]
42
     */
43
    public static function getHumanReadableI18n(): array
44
    {
45
        return self::$humanReadableI18n;
46
    }
47
48
    /**
49
     * Define a new value for a key of the humanReadableI18n property
50
     * 
51
     * @param string $key The key in humanReadableI18n
52
     * @param string $value The new value for the key
53
     * 
54
     * @return void
55
     */
56
    public static function setHumanReadableI18nKey(string $key, string $value)
57
    {
58
        self::$humanReadableI18n[$key] = $value;
59
    }
60
61
    /**
62
     * Define a new value to the property humanReadableI18n
63
     * 
64
     * @param string[] $value The new value for the property
65
     * 
66
     * @return void
67
     */
68
    public static function setHumanReadableI18n(array $value)
69
    {
70
        self::$humanReadableI18n = $value;
71
    }
72
73
    /**
74
     * Return the value of the humanReadableFormats property
75
     * 
76
     * @return string[]
77
     */
78
    public static function getHumanReadableFormats(): array
79
    {
80
        return self::$humanReadableFormats;
81
    }
82
83
    /**
84
     * Define a new value for a key of the humanReadableFormats property
85
     * 
86
     * @param string $key The key in humanReadableFormats
87
     * @param string $value The new value for the key
88
     * 
89
     * @return void
90
     */
91
    public static function setHumanReadableFormatsKey(
92
        string $key,
93
        string $value
94
    ) {
95
        self::$humanReadableFormats[$key] = $value;
96
    }
97
98
    /**
99
     * Define a new value to the property humanReadableFormats
100
     * 
101
     * @param string[] $value The new value for the property
102
     * 
103
     * @return void
104
     */
105
    public static function setHumanReadableFormats(array $value)
106
    {
107
        self::$humanReadableFormats = $value;
108
    }
109
110
    /**
111
     * Return the date. Format is Y-m-d H:i:sO
112
     * 
113
     * @return string
114
     */
115
    public function getDate(): string
116
    {
117
        return parent::format('Y-m-d H:i:sO');
118
    }
119
120
    /**
121
     * Return a numeric representation of a year, 4 digits.
122
     * 
123
     * @return int
124
     */
125
    public function getYear(): int
126
    {
127
        return (int) parent::format('Y');
128
    }
129
130
    /**
131
     * Return the numeric representation of a month, without leading zeros.
132
     * The returned int format can not have leading zeros.
133
     * 
134
     * @return int
135
     */
136
    public function getMonth(): int
137
    {
138
        return (int) parent::format('m');
139
    }
140
141
    /**
142
     * Return the day of the month without leading zeros.
143
     * The returned int format can not have leading zeros.
144
     * 
145
     * @return int
146
     */
147
    public function getDay(): int
148
    {
149
        return (int) parent::format('d');
150
    }
151
152
    /**
153
     * Return 24-hour format without leading zeros.
154
     * The returned int format can not have leading zeros.
155
     * 
156
     * @return int
157
     */
158
    public function getHour(): int
159
    {
160
        return (int) parent::format('H');
161
    }
162
163
    /**
164
     * Return minutes, without leading zeros.
165
     * The returned int format can not have leading zeros.
166
     * 
167
     * @return int
168
     */
169
    public function getMinute(): int
170
    {
171
        return (int) parent::format('i');
172
    }
173
174
    /**
175
     * Return second, without leading zeros.
176
     * The returned int format can not have leading zeros.
177
     * 
178
     * @return int
179
     */
180
    public function getSecond(): int
181
    {
182
        return (int) parent::format('s');
183
    }
184
185
    /**
186
     * Return the difference to Greenwich time (GMT)
187
     * with colon between hours and minutes
188
     * 
189
     * @return string
190
     */
191
    public function getZone(): string
192
    {
193
        return parent::format('P');
194
    }
195
    
196
    /**
197
     * Return date's SQL format (postgresql format).
198
     * The return can be an array or a string.
199
     * 
200
     * @param boolean $returnArray (default false) True to return an array.
201
     * @param boolean $withZone (default false) True to include the timezone
202
     *  into the time returned data.
203
     * 
204
     * @return string[]|string
205
     */
206
    public function getSqlFormat(
207
        bool $returnArray = false,
208
        bool $withZone = false
209
    ) {
210
        $date = $this->format('Y-m-d');
211
        $time = $this->format('H:i:s');
212
        
213
        if ($withZone === true) {
214
            $time .= $this->format('O');
215
        }
216
217
        if ($returnArray) {
218
            return [$date, $time];
219
        }
220
221
        return $date.' '.$time;
222
    }
223
224
    /**
225
     * List all timezone existing in current php version
226
     * 
227
     * @return string[]
228
     */
229
    public function lstTimeZone(): array
230
    {
231
        return parent::getTimezone()->listIdentifiers();
232
    }
233
234
    /**
235
     * List all continent define in php DateTimeZone.
236
     * 
237
     * @return string[]
238
     */
239
    public function lstTimeZoneContinent(): array
240
    {
241
        return [
242
            'Africa',
243
            'America',
244
            'Antartica',
245
            'Arctic',
246
            'Asia',
247
            'Atlantic',
248
            'Australia',
249
            'Europe',
250
            'Indian',
251
            'Pacific'
252
        ];
253
    }
254
255
    /**
256
     * List all available country for a continent
257
     * 
258
     * @param string $continent The continent for which we want
259
     *  the countries list
260
     * 
261
     * @return string[]
262
     */
263
    public function lstTimeZoneCountries(string $continent): array
264
    {
265
        $allCountries = $this->lstTimeZone();
266
        $countries    = [];
267
268
        foreach ($allCountries as $country) {
269
            if (strpos($country, $continent) !== false) {
270
                $countries[] = $country;
271
            }
272
        }
273
274
        return $countries;
275
    }
276
277
    /**
278
     * Transform a date to a human readable format
279
     * 
280
     * @param boolean $returnDateAndTime (default true) True to return date and
281
     *  time concatenated with a space. False to have only date.
282
     * 
283
     * @return string
284
     */
285
    public function humanReadable(bool $returnDateAndTime = true): string
286
    {
287
        $current = new Dates;
288
        $diff    = parent::diff($current);
289
        
290
        $parsedTxt = new class {
291
            public $date = '';
292
            public $time = '';
293
        };
294
295
        if ($current == $this) {
296
            //Now
297
            $this->humanDateNow($parsedTxt);
298
        } elseif (
299
            $this->humanDateIsYesterdayOrTomorrow($diff, $current) === true
0 ignored issues
show
Bug introduced by
It seems like $diff can also be of type false; however, parameter $diff of BFW\Helpers\Dates::human...IsYesterdayOrTomorrow() does only seem to accept DateInterval, maybe add an additional type check? ( Ignorable by Annotation )

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

299
            $this->humanDateIsYesterdayOrTomorrow(/** @scrutinizer ignore-type */ $diff, $current) === true
Loading history...
300
        ) {
301
            if ($diff->invert === 0) {
302
                $this->humanDateYesterday($parsedTxt); //Yesterday
303
            } else {
304
                $this->humanDateTomorrow($parsedTxt); //Tomorrow
305
            }
306
        } elseif ($diff->days === 0) {
307
            //Today
308
            $this->humanDateToday($parsedTxt, $diff);
0 ignored issues
show
Bug introduced by
It seems like $diff can also be of type false; however, parameter $diff of BFW\Helpers\Dates::humanDateToday() does only seem to accept DateInterval, maybe add an additional type check? ( Ignorable by Annotation )

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

308
            $this->humanDateToday($parsedTxt, /** @scrutinizer ignore-type */ $diff);
Loading history...
309
        } else {
310
            $this->humanDateOther($parsedTxt, $current);
311
        }
312
313
        $txtReturned = $parsedTxt->date;
314
        if ($returnDateAndTime === true && $parsedTxt->time !== '') {
315
            $txtReturned .= $parsedTxt->time;
316
        }
317
318
        return $txtReturned;
319
    }
320
    
321
    protected function humanDateIsYesterdayOrTomorrow(
322
        \DateInterval $diff,
323
        \DateTime $current
324
    ): bool {
325
        //To check the range from 24h to 48h
326
        if (($diff->d === 1 && $diff->m === 0 && $diff->y === 0) === false) {
327
            return false;
328
        }
329
        
330
        /**
331
         * With $diff->d === 1, we know if we are in range from 24h to 48h.
332
         * But yesterday or tomorrow day can finish into the range.
333
         * 
334
         * Example :
335
         * 
336
         *    [---03/10---][---04/10---][---05/10---]
337
         * ---|----|-------|----|-------|----|------
338
         *       -48h         -24h         $this
339
         *         [ $diff->d=1 ]
340
         * 
341
         * Like we can see, the $diff->d=1 is not only on the 04/10, but also
342
         * on 03/10 because the range is from 24h to 48h before the date.
343
         * So we need a check to not display "yesterday" for the 03/10.
344
         */
345
        
346
        $twoDays = clone $current;
347
        if ($diff->invert === 0) {
348
            $twoDays->modify('-2 days');
349
        } else {
350
            $twoDays->modify('+2 days');
351
        }
352
        
353
        if ($this->format('d') === $twoDays->format('d')) {
354
            return false;
355
        }
356
        
357
        return true;
358
    }
359
    
360
    /**
361
     * Format date to human readable when the date is now
362
     * 
363
     * @param object $parsedTxt Texts returned by humanReadable method
364
     * 
365
     * @return void
366
     */
367
    protected function humanDateNow($parsedTxt)
368
    {
369
        $currentClass    = get_called_class();
370
        $parsedTxt->date = $currentClass::$humanReadableI18n['now'];
0 ignored issues
show
Bug introduced by
The property humanReadableI18n does not exist on string.
Loading history...
371
    }
372
    
373
    /**
374
     * Format date to human readable when date is today
375
     * 
376
     * @param object $parsedTxt Texts returned by humanReadable method
377
     * @param \DateInterval $diff Interval between now and date to read
378
     * 
379
     * @return void
380
     */
381
    protected function humanDateToday($parsedTxt, \DateInterval $diff)
382
    {
383
        $textKey = 'today_past';
384
        if ($diff->invert === 1) {
385
            $textKey = 'today_future';
386
        }
387
        
388
        $time = '';
389
        if ($diff->h === 0 && $diff->i === 0) {
390
            $time .= $diff->s.'s';
391
        } elseif ($diff->h === 0) {
392
            $time .= $diff->i.'min';
393
        } else {
394
            $time .= $diff->h.'h';
395
        }
396
        
397
        $currentClass    = get_called_class();
398
        $parsedTxt->date = $currentClass::$humanReadableI18n[$textKey];
0 ignored issues
show
Bug introduced by
The property humanReadableI18n does not exist on string.
Loading history...
399
        
400
        $this->humanParseDateAndTimeText($parsedTxt, '', $time);
401
    }
402
    
403
    /**
404
     * Format date to human readable when date is yesterday
405
     * 
406
     * @param object $parsedTxt Texts returned by humanReadable method
407
     * 
408
     * @return void
409
     */
410
    protected function humanDateYesterday($parsedTxt)
411
    {
412
        $currentClass    = get_called_class();
413
        $parsedTxt->date = $currentClass::$humanReadableI18n['yesterday'];
0 ignored issues
show
Bug introduced by
The property humanReadableI18n does not exist on string.
Loading history...
414
        $parsedTxt->time = $currentClass::$humanReadableI18n['time_part'];
415
        
416
        $time = $this->format($currentClass::$humanReadableFormats['time']);
0 ignored issues
show
Bug introduced by
The property humanReadableFormats does not exist on string.
Loading history...
417
        
418
        $this->humanParseDateAndTimeText($parsedTxt, '', $time);
419
    }
420
    
421
    /**
422
     * Format date to human readable when date is tomorrow
423
     * 
424
     * @param object $parsedTxt Texts returned by humanReadable method
425
     * 
426
     * @return void
427
     */
428
    protected function humanDateTomorrow($parsedTxt)
429
    {
430
        $currentClass    = get_called_class();
431
        $parsedTxt->date = $currentClass::$humanReadableI18n['tomorrow'];
0 ignored issues
show
Bug introduced by
The property humanReadableI18n does not exist on string.
Loading history...
432
        $parsedTxt->time = $currentClass::$humanReadableI18n['time_part'];
433
        
434
        $time = $this->format($currentClass::$humanReadableFormats['time']);
0 ignored issues
show
Bug introduced by
The property humanReadableFormats does not exist on string.
Loading history...
435
        
436
        $this->humanParseDateAndTimeText($parsedTxt, '', $time);
437
    }
438
    
439
    /**
440
     * Format date to human readable when date is not now, today or yesterday
441
     * 
442
     * @param object $parsedTxt Texts returned by humanReadable method
443
     * @param \DateTime $current DateTime object for now
444
     * 
445
     * @return void
446
     */
447
    protected function humanDateOther($parsedTxt, \DateTime $current)
448
    {
449
        $currentClass = get_called_class();
450
        
451
        $dateFormat = $currentClass::$humanReadableFormats['dateDifferentYear'];
0 ignored issues
show
Bug introduced by
The property humanReadableFormats does not exist on string.
Loading history...
452
        if ($current->format('Y') === $this->format('Y')) {
453
            $dateFormat = $currentClass::$humanReadableFormats['dateSameYear'];
454
        }
455
        
456
        $parsedTxt->date = $currentClass::$humanReadableI18n['others'];
0 ignored issues
show
Bug introduced by
The property humanReadableI18n does not exist on string.
Loading history...
457
        $parsedTxt->time = $currentClass::$humanReadableI18n['time_part'];
458
        
459
        $date = $this->format($dateFormat);
460
        $time = $this->format($currentClass::$humanReadableFormats['time']);
461
        
462
        $this->humanParseDateAndTimeText($parsedTxt, $date, $time);
463
    }
464
    
465
    /**
466
     * Replace the expression "{date}" by the $date value and the expression
467
     * "{time}" by the $time value into properties "date" and "time" of the
468
     * $parsedTxt object.
469
     * 
470
     * @param object $parsedTxt Texts returned by humanReadable method
471
     * @param string $date The date value used to replace "{date}" into texts
472
     * @param string $time The time value used to replace "{time}" into texts
473
     * 
474
     * @return void
475
     */
476
    protected function humanParseDateAndTimeText(
477
        $parsedTxt,
478
        string $date,
479
        string $time
480
    ) {
481
        $parsedTxt->date = str_replace('{date}', $date, $parsedTxt->date);
482
        $parsedTxt->date = str_replace('{time}', $time, $parsedTxt->date);
483
        
484
        $parsedTxt->time = str_replace('{date}', $date, $parsedTxt->time);
485
        $parsedTxt->time = str_replace('{time}', $time, $parsedTxt->time);
486
    }
487
}
488