Completed
Push — master ( a5f7f0...257179 )
by Harald
05:14 queued 01:09
created

DateTime::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
  * osCommerce Online Merchant
4
  *
5
  * @copyright (c) 2016 osCommerce; https://www.oscommerce.com
6
  * @license GPL; https://www.oscommerce.com/gpllicense.txt
7
  */
8
9
namespace OSC\OM;
10
11
use OSC\OM\OSCOM;
12
13
class DateTime
14
{
15
    protected $datetime = false;
16
17
    protected $raw_pattern_date = 'Y-m-d';
18
    protected $raw_pattern_time = 'H:i:s';
19
20
    public function __construct($datetime, $use_raw_pattern = false, $strict = false)
21
    {
22
        if ($use_raw_pattern === false) {
23
            $pattern = DATE_TIME_FORMAT;
24
        } else {
25
            $pattern = $this->raw_pattern_date . ' ' . $this->raw_pattern_time;
26
        }
27
28
        // format time as 00:00:00 if it is missing from the date
29
        $new_datetime = strtotime($datetime);
30
31
        if ($new_datetime !== false) {
32
            $new_datetime = date($pattern, $new_datetime);
33
34
            $this->datetime = \DateTime::createFromFormat($pattern, $new_datetime);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DateTime::createFromFor...pattern, $new_datetime) can also be of type object<DateTime>. However, the property $datetime is declared as type boolean. Maybe add an additional type 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 mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
35
36
            $strict_log = false;
37
        }
38
39
        if ($this->datetime === false) {
40
            $strict_log = true;
41
        } else {
42
            $errors = \DateTime::getLastErrors();
43
44
            if (($errors['warning_count'] > 0) || ($errors['error_count'] > 0)) {
45
                $this->datetime = false;
46
47
                $strict_log = true;
48
            }
49
        }
50
51
        if (($strict === true) && ($strict_log === true)) {
0 ignored issues
show
Bug introduced by
The variable $strict_log does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
52
            trigger_error('DateTime: ' . $datetime . ' (' . $new_datetime . ') cannot be formatted to ' . $pattern);
53
        }
54
    }
55
56
    public function isValid()
57
    {
58
        return $this->datetime instanceof \DateTime;
59
    }
60
61
    public function get($pattern = null)
62
    {
63
        if (isset($pattern)) {
64
            return $this->datetime->format($pattern);
0 ignored issues
show
Bug introduced by
The method format cannot be called on $this->datetime (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
65
        }
66
67
        return $this->datetime;
68
    }
69
70
    public function getShort($with_time = false)
71
    {
72
        $pattern = ($with_time === false) ? DATE_FORMAT_SHORT : DATE_TIME_FORMAT;
73
74
        return strftime($pattern, $this->getTimestamp());
75
    }
76
77
    public function getLong()
78
    {
79
        return strftime(DATE_FORMAT_LONG, $this->getTimestamp());
80
    }
81
82
    public static function toShort($raw_datetime, $with_time = false, $strict = true)
83
    {
84
        $result = '';
85
86
        $date = new DateTime($raw_datetime, true, $strict);
87
88
        if ($date->isValid()) {
89
            $pattern = ($with_time === false) ? DATE_FORMAT_SHORT : DATE_TIME_FORMAT;
90
91
            $result = strftime($pattern, $date->getTimestamp());
92
        }
93
94
        return $result;
95
    }
96
97
    public static function toLong($raw_datetime, $strict = true)
98
    {
99
        $result = '';
100
101
        $date = new DateTime($raw_datetime, true, $strict);
102
103
        if ($date->isValid()) {
104
            $result = strftime(DATE_FORMAT_LONG, $date->getTimestamp());
105
        }
106
107
        return $result;
108
    }
109
110
    public function getRaw($with_time = true)
111
    {
112
        $pattern = $this->raw_pattern_date;
113
114
        if ($with_time === true) {
115
            $pattern .= ' ' . $this->raw_pattern_time;
116
        }
117
118
        return $this->datetime->format($pattern);
0 ignored issues
show
Bug introduced by
The method format cannot be called on $this->datetime (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
119
    }
120
121
    public function getTimestamp()
122
    {
123
        return $this->datetime->getTimestamp();
0 ignored issues
show
Bug introduced by
The method getTimestamp cannot be called on $this->datetime (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
124
    }
125
126
    public static function getTimeZones()
127
    {
128
        $time_zones_array = [];
129
130
        foreach (\DateTimeZone::listIdentifiers() as $id) {
131
            $tz_string = str_replace('_', ' ', $id);
132
133
            $id_array = explode('/', $tz_string, 2);
134
135
            $time_zones_array[$id_array[0]][$id] = isset($id_array[1]) ? $id_array[1] : $id_array[0];
136
        }
137
138
        $result = [];
139
140
        foreach ($time_zones_array as $zone => $zones_array) {
141
            foreach ($zones_array as $key => $value) {
142
                $result[] = [
143
                    'id' => $key,
144
                    'text' => $value,
145
                    'group' => $zone
146
                ];
147
            }
148
        }
149
150
        return $result;
151
    }
152
153
    public static function setTimeZone($time_zone = null)
154
    {
155
        if (!isset($time_zone)) {
156
            $time_zone = OSCOM::configExists('time_zone') ? OSCOM::getConfig('time_zone') : date_default_timezone_get();
157
        }
158
159
        return date_default_timezone_set($time_zone);
160
    }
161
}
162