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 ( de1771...791612 )
by Vermeulen
04:28
created

Dates::humanReadable()   D

Complexity

Conditions 9
Paths 10

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 33
rs 4.909
cc 9
eloc 21
nc 10
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
     * @const ERR_MODIFY_PATTERN_NOT_MATCH Exception code if the pattern used
16
     * into the method modify() not match with the regex.
17
     */
18
    const ERR_MODIFY_PATTERN_NOT_MATCH = 1306001;
19
    
20
    /**
21
     * @const ERR_MODIFY_UNKNOWN_MODIFIER Exception code if the modifier used
22
     * into the method modify() is unknown.
23
     */
24
    const ERR_MODIFY_UNKNOWN_MODIFIER = 1306002;
25
    
26
    /**
27
     * @var string[] $humanReadableI18n Words used in method to transform
28
     *  date difference to human readable.
29
     */
30
    protected static $humanReadableI18n = [
31
        'now'       => 'now',
32
        'since'     => 'since',
33
        'in'        => 'in',
34
        'yesterday' => 'yesterday',
35
        'tomorrow'  => 'tomorrow',
36
        'the'       => 'the',
37
        'at'        => 'at'
38
    ];
39
40
    /**
41
     * @var string[] $humanReadableFormats Date and time formats used in
42
     *  method to transform date difference to human readable.
43
     */
44
    protected static $humanReadableFormats = [
45
        'dateSameYear'      => 'm-d',
46
        'dateDifferentYear' => 'Y-m-d',
47
        'time'              => 'H:i'
48
    ];
49
    
50
    /**
51
     * @var string[] $modifyNewKeywords Add new keywords which can be used
52
     *  with the modify method. The key is the new keyword and the value the
53
     *  corresponding keyword into DateTime::modify method.
54
     */
55
    protected static $modifyNewKeywords = [];
56
57
    /**
58
     * Return the value of the humanReadableI18n property
59
     * 
60
     * @return string[]
61
     */
62
    public static function getHumanReadableI18n()
63
    {
64
        return self::$humanReadableI18n;
65
    }
66
67
    /**
68
     * Define a new value for a key of the humanReadableI18n property
69
     * 
70
     * @param string $key The key in humanReadableI18n
71
     * @param string $value The new value for the key
72
     * 
73
     * @return void
74
     */
75
    public static function setHumanReadableI18nKey($key, $value)
76
    {
77
        self::$humanReadableI18n[$key] = $value;
78
    }
79
80
    /**
81
     * Define a new value to the property humanReadableI18n
82
     * 
83
     * @param string[] $value The new value for the property
84
     * 
85
     * @return void
86
     */
87
    public static function setHumanReadableI18n($value)
88
    {
89
        self::$humanReadableI18n = $value;
90
    }
91
92
    /**
93
     * Return the value of the humanReadableFormats property
94
     * 
95
     * @return string[]
96
     */
97
    public static function getHumanReadableFormats()
98
    {
99
        return self::$humanReadableFormats;
100
    }
101
102
    /**
103
     * Define a new value for a key of the humanReadableFormats property
104
     * 
105
     * @param string $key The key in humanReadableFormats
106
     * @param string $value The new value for the key
107
     * 
108
     * @return void
109
     */
110
    public static function setHumanReadableFormatsKey($key, $value)
111
    {
112
        self::$humanReadableFormats[$key] = $value;
113
    }
114
115
    /**
116
     * Define a new value to the property humanReadableFormats
117
     * 
118
     * @param string[] $value The new value for the property
119
     * 
120
     * @return void
121
     */
122
    public static function setHumanReadableFormats($value)
123
    {
124
        self::$humanReadableFormats = $value;
125
    }
126
    
127
    /**
128
     * Return the value of the modifyNewKeywords property
129
     * 
130
     * @return string[]
131
     */
132
    public static function getModifyNewKeywords()
133
    {
134
        return self::$modifyNewKeywords;
135
    }
136
    
137
    /**
138
     * Define a new value to the property modifyNewKeywords
139
     * 
140
     * @param string[] $value The new value for the property
141
     * 
142
     * @return void
143
     */
144
    public static function setModifyNewKeywords($value)
145
    {
146
        self::$modifyNewKeywords = $value;
147
    }
148
149
    /**
150
     * Return the date. Format is Y-m-d H:i:sO
151
     * 
152
     * @return string
153
     */
154
    public function getDate()
155
    {
156
        return parent::format('Y-m-d H:i:sO');
157
    }
158
159
    /**
160
     * Return a numeric representation of a year, 4 digits.
161
     * 
162
     * @return int
163
     */
164
    public function getYear()
165
    {
166
        return (int) parent::format('Y');
167
    }
168
169
    /**
170
     * Return the numeric representation of a month, without leading zeros.
171
     * The returned int format can not have leading zeros.
172
     * 
173
     * @return int
174
     */
175
    public function getMonth()
176
    {
177
        return (int) parent::format('m');
178
    }
179
180
    /**
181
     * Return the day of the month without leading zeros.
182
     * The returned int format can not have leading zeros.
183
     * 
184
     * @return int
185
     */
186
    public function getDay()
187
    {
188
        return (int) parent::format('d');
189
    }
190
191
    /**
192
     * Return 24-hour format without leading zeros.
193
     * The returned int format can not have leading zeros.
194
     * 
195
     * @return int
196
     */
197
    public function getHour()
198
    {
199
        return (int) parent::format('H');
200
    }
201
202
    /**
203
     * Return minutes, without leading zeros.
204
     * The returned int format can not have leading zeros.
205
     * 
206
     * @return int
207
     */
208
    public function getMinute()
209
    {
210
        return (int) parent::format('i');
211
    }
212
213
    /**
214
     * Return second, without leading zeros.
215
     * The returned int format can not have leading zeros.
216
     * 
217
     * @return int
218
     */
219
    public function getSecond()
220
    {
221
        return (int) parent::format('s');
222
    }
223
224
    /**
225
     * Return the difference to Greenwich time (GMT)
226
     * with colon between hours and minutes
227
     * 
228
     * @return string
229
     */
230
    public function getZone()
231
    {
232
        return parent::format('P');
1 ignored issue
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (format() instead of getZone()). Are you sure this is correct? If so, you might want to change this to $this->format().

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...
233
    }
234
235
    /**
236
     * Override modify DateTime method to allow personal keywords
237
     * 
238
     * @param string $modify A date/time string
239
     * 
240
     * @return \BFW\Dates
241
     */
242
    public function modify($modify)
243
    {
244
        $originalDate = clone $this;
245
        @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...
246
        //Maybe with try/catch for PHP7, but for 5.6, no idea to avoid that.
247
248
        //If the keyword used is ok with DateTime::modify method
249
        if ($originalDate != $this) {
250
            return $this;
251
        }
252
253
        $this->modifyWithOthersKeywords($modify);
254
255
        return $this;
256
    }
257
258
    /**
259
     * Get DateTime equivalent keyword for a personal keyword declared into
260
     * the property modifyNewKeywords.
261
     * 
262
     * @return \stdClass
263
     */
264
    protected function obtainNewKeywordsForModify()
265
    {
266
        $search  = [];
267
        $replace = [];
268
        
269
        foreach (self::$modifyNewKeywords as $searchKey => $replaceKey) {
270
            $search[]  = $searchKey;
271
            $replace[] = $replaceKey;
272
        }
273
        
274
        return (object) [
275
            'search'  => $search,
276
            'replace' => $replace
277
        ];
278
    }
279
    
280
    /**
281
     * Use personal keyword on modify method
282
     * 
283
     * @param string $modify A date/time string
284
     * 
285
     * @throws Exception If bad pattern or unknown keyword
286
     */
287
    protected function modifyWithOthersKeywords($modify)
288
    {
289
        $keywords = $this->obtainNewKeywordsForModify();
290
        $match    = [];
291
        
292
        //Regex on the $modify parameter to get the used keyword
293
        if (preg_match('#(\+|\-)([0-9]+) ([a-z]+)#i', $modify, $match) !== 1) {
294
            throw new Exception(
295
                'Dates::modify pattern not match.',
296
                $this::ERR_MODIFY_PATTERN_NOT_MATCH
297
            );
298
        }
299
        
300
        $keyword = str_replace(
301
            $keywords->search,
302
            $keywords->replace,
303
            strtolower($match[3])
304
        );
305
        
306
        $originalDate = clone $this;
307
        //Yeurk, but I preferer sends an Exception, not an error.
308
        //Maybe easier PHP7 (try/catch ?), but no idea for 5.6.
309
        @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...
310
        
311
        //If no change on object, The keyword is unknown
312
        if ($originalDate == $this) {
313
            throw new Exception(
314
                'Dates::modify Parameter '.$match[3].' is unknown.',
315
                $this::ERR_MODIFY_UNKNOWN_MODIFIER
316
            );
317
        }
318
    }
319
    
320
    /**
321
     * Return date's SQL format (postgresql format).
322
     * The return can be an array or a string.
323
     * 
324
     * @param boolean $returnArray (default false) True to return an array.
325
     * 
326
     * @return string[]|string
327
     */
328
    public function getSqlFormat($returnArray = false)
329
    {
330
        $date = $this->format('Y-m-d');
331
        $time = $this->format('H:i:s');
332
333
        if ($returnArray) {
334
            return [$date, $time];
335
        }
336
337
        return $date.' '.$time;
338
    }
339
340
    /**
341
     * List all timezone existing in current php version
342
     * 
343
     * @return string[]
344
     */
345
    public function lstTimeZone()
346
    {
347
        return parent::getTimezone()->listIdentifiers();
348
    }
349
350
    /**
351
     * List all continent define in php DateTimeZone.
352
     * 
353
     * @return string[]
354
     */
355
    public function lstTimeZoneContinent()
356
    {
357
        return [
358
            'Africa',
359
            'America',
360
            'Antartica',
361
            'Arctic',
362
            'Asia',
363
            'Atlantic',
364
            'Australia',
365
            'Europe',
366
            'Indian',
367
            'Pacific'
368
        ];
369
    }
370
371
    /**
372
     * List all available country for a continent
373
     * 
374
     * @param string $continent The continent for which we want
375
     *  the countries list
376
     * 
377
     * @return string[]
378
     */
379
    public function lstTimeZoneCountries($continent)
380
    {
381
        $allCountries = $this->lstTimeZone();
382
        $countries    = [];
383
384
        foreach ($allCountries as $country) {
385
            if (strpos($country, $continent) !== false) {
386
                $countries[] = $country;
387
            }
388
        }
389
390
        return $countries;
391
    }
392
393
    /**
394
     * Transform a date to a human readable format
395
     * 
396
     * @param boolean $returnDateAndTime (default true) True to return date and
397
     *  time concatenated with a space. False to have only date.
398
     * 
399
     * @return string
400
     */
401
    public function humanReadable($returnDateAndTime = true)
402
    {
403
        $current = new Dates;
404
        $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...
405
        
406
        $parsedTxt = (object) [
407
            'date' => '',
408
            'time' => ''
409
        ];
410
411
        if ($current == $this) {
412
            //Now
413
            $this->humanDateNow($parsedTxt);
414
        } elseif ($diff->d === 1 && $diff->m === 0 && $diff->y === 0) {
415
            if ($diff->invert === 0) {
416
                $this->humanDateYesterday($parsedTxt); //Yesterday
417
            } else {
418
                $this->humanDateTomorrow($parsedTxt); //Tomorrow
419
            }
420
        } elseif ($diff->days === 0) {
421
            //Today
422
            $this->humanDateToday($parsedTxt, $diff);
423
        } else {
424
            $this->humanDateOther($parsedTxt, $current);
425
        }
426
427
        $txtReturned = $parsedTxt->date;
428
        if ($returnDateAndTime === true && $parsedTxt->time !== '') {
429
            $txtReturned .= ' '.$parsedTxt->time;
430
        }
431
432
        return $txtReturned;
433
    }
434
    
435
    /**
436
     * Format date to human readable when the date is now
437
     * 
438
     * @param \stdClass $parsedTxt Texts returned by humanReadable method
439
     * 
440
     * @return void
441
     */
442
    protected function humanDateNow($parsedTxt)
443
    {
444
        $currentClass    = get_called_class();
445
        $parsedTxt->date = $currentClass::$humanReadableI18n['now'];
446
    }
447
    
448
    /**
449
     * Format date to human readable when date is today
450
     * 
451
     * @param \stdClass $parsedTxt Texts returned by humanReadable method
452
     * @param \DateInterval $diff Interval between now and date to read
453
     * 
454
     * @return void
455
     */
456
    protected function humanDateToday($parsedTxt, $diff)
457
    {
458
        $textKey = 'since';
459
        if ($diff->invert === 1) {
460
            $textKey = 'in';
461
        }
462
        
463
        $currentClass    = get_called_class();
464
        $parsedTxt->date = $currentClass::$humanReadableI18n[$textKey].' ';
465
466
        if ($diff->h === 0 && $diff->i === 0) {
467
            $parsedTxt->date .= $diff->s.'s';
468
        } elseif ($diff->h === 0) {
469
            $parsedTxt->date .= $diff->i.'min';
470
        } else {
471
            $parsedTxt->date .= $diff->h.'h';
472
        }
473
    }
474
    
475
    /**
476
     * Format date to human readable when date is yesterday
477
     * 
478
     * @param \stdClass $parsedTxt Texts returned by humanReadable method
479
     * 
480
     * @return void
481
     */
482 View Code Duplication
    protected function humanDateYesterday($parsedTxt)
1 ignored issue
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...
483
    {
484
        $currentClass    = get_called_class();
485
        $parsedTxt->date = $currentClass::$humanReadableI18n['yesterday'];
486
        $parsedTxt->time = $currentClass::$humanReadableI18n['at']
487
            .' '
488
            .$this->format(
489
                $currentClass::$humanReadableFormats['time']
490
            );
491
    }
492
    
493
    /**
494
     * Format date to human readable when date is tomorrow
495
     * 
496
     * @param \stdClass $parsedTxt Texts returned by humanReadable method
497
     * 
498
     * @return void
499
     */
500 View Code Duplication
    protected function humanDateTomorrow($parsedTxt)
1 ignored issue
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...
501
    {
502
        $currentClass    = get_called_class();
503
        $parsedTxt->date = $currentClass::$humanReadableI18n['tomorrow'];
504
        $parsedTxt->time = $currentClass::$humanReadableI18n['at']
505
            .' '
506
            .$this->format(
507
                $currentClass::$humanReadableFormats['time']
508
            );
509
    }
510
    
511
    /**
512
     * Format date to human readable when date is not now, today or yesterday
513
     * 
514
     * @param \stdClass $parsedTxt Texts returned by humanReadable method
515
     * @param \DateTime $current DateTime object for now
516
     * 
517
     * @return void
518
     */
519
    protected function humanDateOther($parsedTxt, $current)
520
    {
521
        $currentClass = get_called_class();
522
        
523
        $dateFormat = $currentClass::$humanReadableFormats['dateDifferentYear'];
524
        if ($current->format('Y') === $this->format('Y')) {
525
            $dateFormat = $currentClass::$humanReadableFormats['dateSameYear'];
526
        }
527
528
        $parsedTxt->date = $currentClass::$humanReadableI18n['the']
529
            .' '
530
            .$this->format($dateFormat);
531
532
        $parsedTxt->time = $currentClass::$humanReadableI18n['at']
533
            .' '
534
            .$this->format(
535
                $currentClass::$humanReadableFormats['time']
536
            );
537
    }
538
}
539