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 ( 572920...bfe862 )
by Vermeulen
02:24
created

Dates::humanReadable()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 30
rs 5.3846
cc 8
eloc 18
nc 8
nop 1
1
<?php
2
3
namespace BFW;
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
        'since'     => 'since',
21
        'in'        => 'in',
22
        'yesterday' => 'yesterday',
23
        'the'       => 'the',
24
        'at'        => 'at'
25
    ];
26
27
    /**
28
     * @var string[] $humanReadableFormats Date and time formats used in
29
     *  method to transform date difference to human readable.
30
     */
31
    protected static $humanReadableFormats = [
32
        'dateSameYear'      => 'm-d',
33
        'dateDifferentYear' => 'Y-m-d',
34
        'time'              => 'H:i'
35
    ];
36
37
    /**
38
     * Return the value of the humanReadableI18n property
39
     * 
40
     * @return string[]
41
     */
42
    public static function getHumanReadableI18n()
43
    {
44
        return self::$humanReadableI18n;
45
    }
46
47
    /**
48
     * Define a new value for a key of the humanReadableI18n property
49
     * 
50
     * @param string $key The key in humanReadableI18n
51
     * @param string $value The new value for the key
52
     * 
53
     * @return void
54
     */
55
    public static function setHumanReadableI18nKey($key, $value)
56
    {
57
        self::$humanReadableI18n[$key] = $value;
58
    }
59
60
    /**
61
     * Define a new value to the property humanReadableI18n
62
     * 
63
     * @param string[] $value The new value for the property
64
     * 
65
     * @return void
66
     */
67
    public static function setHumanReadableI18n($value)
68
    {
69
        self::$humanReadableI18n = $value;
70
    }
71
72
    /**
73
     * Return the value of the humanReadableFormats property
74
     * 
75
     * @return string[]
76
     */
77
    public static function getHumanReadableFormats()
78
    {
79
        return self::$humanReadableFormats;
80
    }
81
82
    /**
83
     * Define a new value for a key of the humanReadableFormats property
84
     * 
85
     * @param string $key The key in humanReadableFormats
86
     * @param string $value The new value for the key
87
     * 
88
     * @return void
89
     */
90
    public static function setHumanReadableFormatsKey($key, $value)
91
    {
92
        self::$humanReadableFormats[$key] = $value;
93
    }
94
95
    /**
96
     * Define a new value to the property humanReadableFormats
97
     * 
98
     * @param string[] $value The new value for the property
99
     * 
100
     * @return void
101
     */
102
    public static function setHumanReadableFormats($value)
103
    {
104
        self::$humanReadableFormats = $value;
105
    }
106
107
    /**
108
     * Return the date. Format is Y-m-d H:i:sO
109
     * 
110
     * @return string
111
     */
112
    public function getDate()
113
    {
114
        return parent::format('Y-m-d H:i:sO');
115
    }
116
117
    /**
118
     * Return a numeric representation of a year, 4 digits.
119
     * 
120
     * @return int
121
     */
122
    public function getYear()
123
    {
124
        return (int) parent::format('Y');
125
    }
126
127
    /**
128
     * Return the numeric representation of a month, without leading zeros.
129
     * The returned int format can not have leading zeros.
130
     * 
131
     * @return int
132
     */
133
    public function getMonth()
134
    {
135
        return (int) parent::format('m');
136
    }
137
138
    /**
139
     * Return the day of the month without leading zeros.
140
     * The returned int format can not have leading zeros.
141
     * 
142
     * @return int
143
     */
144
    public function getDay()
145
    {
146
        return (int) parent::format('d');
147
    }
148
149
    /**
150
     * Return 24-hour format without leading zeros.
151
     * The returned int format can not have leading zeros.
152
     * 
153
     * @return int
154
     */
155
    public function getHour()
156
    {
157
        return (int) parent::format('H');
158
    }
159
160
    /**
161
     * Return minutes, without leading zeros.
162
     * The returned int format can not have leading zeros.
163
     * 
164
     * @return int
165
     */
166
    public function getMinute()
167
    {
168
        return (int) parent::format('i');
169
    }
170
171
    /**
172
     * Return second, without leading zeros.
173
     * The returned int format can not have leading zeros.
174
     * 
175
     * @return int
176
     */
177
    public function getSecond()
178
    {
179
        return (int) parent::format('s');
180
    }
181
182
    /**
183
     * Return the difference to Greenwich time (GMT)
184
     * with colon between hours and minutes
185
     * 
186
     * @return string
187
     */
188
    public function getZone()
189
    {
190
        return parent::format('P');
191
    }
192
193
    /**
194
     * Override modify DateTime method to allow personal keywords
195
     * 
196
     * @param string $modify A date/time string
197
     * 
198
     * @return \BFW\Dates
199
     */
200
    public function modify($modify)
201
    {
202
        $originalDate = clone $this;
203
        @parent::modify($modify); //Yeurk, but for personnal pattern, no choice
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
204
205
        //If the keyword used is ok with DateTime::modify method
206
        if ($originalDate != $this) {
207
            return $this;
208
        }
209
210
        $this->modifyWithOthersKeywords($modify);
211
212
        return $this;
213
    }
214
215
    /**
216
     * Get DateTime equivalent keyword for a personal keyword
217
     * 
218
     * @return \stdClass
219
     */
220
    protected function getNewKeywordsForModify()
221
    {
222
        //Personal keywords list
223
        $search = [
224
            'an', 'ans',
225
            'mois',
226
            'jour', 'jours',
227
            'heure', 'heures',
228
            'minutes',
229
            'seconde', 'secondes'
230
        ];
231
232
        //Keywords equivalent into \DateTime::modify function (same order)
233
        $replace = [
234
            'year', 'year',
235
            'month',
236
            'day', 'day',
237
            'hour', 'hour',
238
            'minute',
239
            'second', 'second'
240
        ];
241
        
242
        return (object) [
243
            'search'  => $search,
244
            'replace' => $replace
245
        ];
246
    }
247
    
248
    /**
249
     * Use personal keyword on modify method
250
     * 
251
     * @param string $modify A date/time string
252
     * 
253
     * @throws Exception If bad pattern or unknown keyword
254
     */
255
    protected function modifyWithOthersKeywords($modify)
256
    {
257
        $keywords = $this->getNewKeywordsForModify();
258
        $match    = [];
259
        
260
        //Regex on the $modify parameter to get the used keyword
261
        if (preg_match('#(\+|\-)([0-9]+) ([a-z]+)#i', $modify, $match) !== 1) {
262
            throw new Exception('Dates::modify pattern not match.');
263
        }
264
        
265
        $keyword = str_replace(
266
            $keywords->search,
267
            $keywords->replace,
268
            strtolower($match[3])
269
        );
270
        
271
        $originalDate = clone $this;
272
        //Yeurk, but I preferer sends an Exception, not an error
273
        @parent::modify($match[1].$match[2].' '.$keyword);
2 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (modify() instead of modifyWithOthersKeywords()). Are you sure this is correct? If so, you might want to change this to $this->modify().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
274
        
275
        //If no change on object, The keyword is unknown
276
        if ($originalDate == $this) {
277
            throw new Exception(
278
                'Dates::modify Parameter '.$match[3].' is unknown.'
279
            );
280
        }
281
    }
282
    
283
    /**
284
     * Return date's SQL format (postgresql format).
285
     * The return can be an array or a string.
286
     * 
287
     * @param boolean $returnArray (default false) True to return an array.
288
     * 
289
     * @return string[]|string
290
     */
291
    public function getSqlFormat($returnArray = false)
292
    {
293
        $date = $this->format('Y-m-d');
294
        $time = $this->format('H:i:s');
295
296
        if ($returnArray) {
297
            return [$date, $time];
298
        }
299
300
        return $date.' '.$time;
301
    }
302
303
    /**
304
     * List all timezone existing in current php version
305
     * 
306
     * @return string[]
307
     */
308
    public function lstTimeZone()
309
    {
310
        return parent::getTimezone()->listIdentifiers();
311
    }
312
313
    /**
314
     * List all continent define in php DateTimeZone.
315
     * 
316
     * @return string[]
317
     */
318
    public function lstTimeZoneContinent()
319
    {
320
        return [
321
            'africa',
322
            'america',
323
            'antartica',
324
            'arctic',
325
            'asia',
326
            'atlantic',
327
            'australia',
328
            'europe',
329
            'indian',
330
            'pacific'
331
        ];
332
    }
333
334
    /**
335
     * List all available country for a continent
336
     * 
337
     * @param string $continent The continent for which we want
338
     *  the countries list
339
     * 
340
     * @return string[]
341
     */
342
    public function lstTimeZonePays($continent)
343
    {
344
        $allCountries = $this->lstTimeZone();
345
        $countries    = [];
346
347
        foreach ($allCountries as $country) {
348
            if (strpos($country, $continent) !== false) {
349
                $countries[] = $country;
350
            }
351
        }
352
353
        return $countries;
354
    }
355
356
    /**
357
     * Transform a date to a human readable format
358
     * 
359
     * @param boolean $returnDateAndTime (default true) True to return date and
360
     *  time concatenated with a space. False to have only date.
361
     * 
362
     * @return string
363
     */
364
    public function humanReadable($returnDateAndTime = true)
365
    {
366
        $current = new Dates;
367
        $diff    = parent::diff($current);
1 ignored issue
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (diff() instead of humanReadable()). Are you sure this is correct? If so, you might want to change this to $this->diff().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
368
369
        $parsedTxt = (object) [
370
            'date' => '',
371
            'time' => ''
372
        ];
373
374
        if ($current == $this) {
375
            //Now
376
            $this->humanDateNow($parsedTxt);
377
        } elseif ($diff->d === 1 && $diff->m === 0 && $diff->y === 0) {
378
            //Yesterday
379
            $this->humanDateYesterday($parsedTxt);
380
        } elseif ($diff->days === 0) {
381
            //Today
382
            $this->humanDateToday($parsedTxt, $diff);
383
        } else {
384
            $this->humanDateOther($parsedTxt, $current);
385
        }
386
387
        $txtReturned = $parsedTxt->date;
388
        if ($returnDateAndTime === true && $parsedTxt->time !== '') {
389
            $txtReturned .= ' '.$parsedTxt->time;
390
        }
391
392
        return $txtReturned;
393
    }
394
    
395
    /**
396
     * Format date to human readable when the date is now
397
     * 
398
     * @param \stdClass &$parsedTxt Texts returned by humanReadable method
399
     * 
400
     * @return void
401
     */
402
    protected function humanDateNow(&$parsedTxt)
403
    {
404
        $currentClass    = get_called_class();
405
        $parsedTxt->date = $currentClass::$humanReadableI18n['now'];
406
    }
407
    
408
    /**
409
     * Format date to human readable when date is today
410
     * 
411
     * @param \stdClass &$parsedTxt Texts returned by humanReadable method
412
     * @param \DateInterval $diff Interval between now and date to read
413
     * 
414
     * @return void
415
     */
416
    protected function humanDateToday(&$parsedTxt, $diff)
417
    {
418
        $textKey = 'since';
419
        if ($diff->invert === 1) {
420
            $textKey = 'in';
421
        }
422
        
423
        $currentClass    = get_called_class();
424
        $parsedTxt->date = $currentClass::$humanReadableI18n[$textKey].' ';
425
426
        if ($diff->h === 0 && $diff->i === 0) {
427
            $parsedTxt->date .= $diff->s.'s';
428
        } elseif ($diff->h === 0) {
429
            $parsedTxt->date .= $diff->i.'min';
430
        } else {
431
            $parsedTxt->date .= $diff->h.'h';
432
        }
433
    }
434
    
435
    /**
436
     * Format date to human readable when date is yesterday
437
     * 
438
     * @param \stdClass &$parsedTxt Texts returned by humanReadable method
439
     * 
440
     * @return void
441
     */
442
    protected function humanDateYesterday(&$parsedTxt)
443
    {
444
        $currentClass    = get_called_class();
445
        $parsedTxt->date = $currentClass::$humanReadableI18n['yesterday'];
446
        $parsedTxt->time = $currentClass::$humanReadableI18n['at']
447
            .' '
448
            .$this->format(
449
                $currentClass::$humanReadableFormats['time']
450
            );
451
    }
452
    
453
    /**
454
     * Format date to human readable when date is not now, today or yesterday
455
     * 
456
     * @param \stdClass &$parsedTxt Texts returned by humanReadable method
457
     * @param \DateTime $current DateTime object for now
458
     * 
459
     * @return void
460
     */
461
    protected function humanDateOther(&$parsedTxt, $current)
462
    {
463
        $currentClass = get_called_class();
464
        
465
        $dateFormat = $currentClass::$humanReadableFormats['dateDifferentYear'];
466
        if ($current->format('Y') === $this->format('Y')) {
467
            $dateFormat = $currentClass::$humanReadableFormats['dateSameYear'];
468
        }
469
470
        $parsedTxt->date = $currentClass::$humanReadableI18n['the']
471
            .' '
472
            .$this->format($dateFormat);
473
474
        $parsedTxt->time = $currentClass::$humanReadableI18n['at']
475
            .' '
476
            .$this->format(
477
                $currentClass::$humanReadableFormats['time']
478
            );
479
    }
480
}
481