Completed
Branch BUG-11108-ticket-reserved-coun... (144d27)
by
unknown
14:21 queued 17s
created

AbstractHelper::timezoneSelectInput()   F

Complexity

Conditions 16
Paths 672

Size

Total Lines 93
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 68
nc 672
nop 1
dl 0
loc 93
rs 2.3966
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace EventEspresso\core\services\helpers\datetime;
3
4
use DateTime;
5
use DateTimeZone;
6
use DomainException;
7
use EE_Datetime_Field;
8
use EE_Error;
9
use Exception;
10
11
abstract class AbstractHelper implements HelperInterface
12
{
13
14
15
    /**
16
     * Ensures that a valid timezone string is returned.
17
     *
18
     * @param string $timezone_string  When not provided then attempt to use the timezone_string set in the WP Time
19
     *                                 settings (or derive from set UTC offset).
20
     * @return string
21
     * @throws EE_Error
22
     */
23
    public function getValidTimezoneString($timezone_string = '')
24
    {
25
        $timezone_string = ! empty($timezone_string) ? $timezone_string : (string) get_option('timezone_string');
26
        $timezone_string = ! empty($timezone_string)
27
            ? $timezone_string
28
            : $this->getTimezoneStringFromGmtOffset();
29
        $this->validateTimezone($timezone_string);
30
        return $timezone_string;
31
    }
32
33
34
35
    /**
36
     * The only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
37
     *
38
     * @param string $timezone_string
39
     * @param bool   $throw_error
40
     * @return bool
41
     * @throws EE_Error
42
     */
43
    public function validateTimezone($timezone_string, $throw_error = true)
44
    {
45
        // easiest way to test a timezone string is just see if it throws an error when you try to create a
46
        // DateTimeZone object with it
47
        try {
48
            new DateTimeZone($timezone_string);
49
        } catch (Exception $e) {
50
            // sometimes we take exception to exceptions
51
            if (! $throw_error) {
52
                return false;
53
            }
54
            throw new EE_Error(
55
                sprintf(
56
                    esc_html__(
57
                        'The timezone given (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
58
                        'event_espresso'
59
                    ),
60
                    $timezone_string,
61
                    '<a href="http://www.php.net/manual/en/timezones.php">',
62
                    '</a>'
63
                )
64
            );
65
        }
66
        return true;
67
    }
68
69
70
    /**
71
     * Gets the site's GMT offset based on either the timezone string
72
     * (in which case the gmt offset will vary depending on the location's
73
     * observance of daylight savings time) or the gmt_offset wp option
74
     *
75
     * @return int  seconds offset
76
     */
77
    public function getSiteTimezoneGmtOffset()
78
    {
79
        $timezone_string = (string)get_option('timezone_string');
80
        if ($timezone_string) {
81
            try {
82
                $timezone = new DateTimeZone($timezone_string);
83
                return $timezone->getOffset(new DateTime()); //in WordPress DateTime defaults to UTC
84
            } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
85
            }
86
        }
87
        $offset = get_option('gmt_offset');
88
        return (int) ($offset * HOUR_IN_SECONDS);
89
    }
90
91
92
    /**
93
     * Get Timezone offset for given timezone object
94
     *
95
     * @param DateTimeZone $date_time_zone
96
     * @param null|int     $time
97
     * @return int
98
     * @throws DomainException
99
     */
100
    public function getTimezoneOffset(DateTimeZone $date_time_zone, $time = null)
101
    {
102
        $transition = $this->getTimezoneTransitions($date_time_zone, $time);
103
        if (! isset($transition['offset'])) {
104
            throw new DomainException(
105
                sprintf(
106
                    esc_html__('An invalid timezone transition was received %1$s', 'event_espresso'),
107
                    print_r($transition, true)
108
                )
109
            );
110
        }
111
        return $transition['offset'];
112
    }
113
114
115
    /**
116
     * Provide a timezone select input
117
     *
118
     * @param string $timezone_string
119
     * @return string
120
     * @throws EE_Error
121
     */
122
    public function timezoneSelectInput($timezone_string = '')
123
    {
124
        // get WP date time format
125
        $datetime_format = get_option('date_format') . ' ' . get_option('time_format');
126
        // if passed a value, then use that, else get WP option
127
        $timezone_string = ! empty($timezone_string) ? $timezone_string : (string)get_option('timezone_string');
128
        // check if the timezone is valid but don't throw any errors if it isn't
129
        $timezone_string = $this->validateTimezone($timezone_string, false)
130
            ? $timezone_string
131
            : '';
132
        $gmt_offset      = get_option('gmt_offset');
133
        $check_zone_info = true;
134
        if (empty($timezone_string)) {
135
            // Create a UTC+- zone if no timezone string exists
136
            $timezone_string = 'UTC';
137
            $check_zone_info = false;
138
            if ($gmt_offset > 0) {
139
                $timezone_string = 'UTC+' . $gmt_offset;
140
            } elseif ($gmt_offset < 0) {
141
                $timezone_string = 'UTC' . $gmt_offset;
142
            }
143
        }
144
        ?>
145
        <p>
146
            <label for="timezone_string"><?php _e('timezone'); ?></label>
147
            <select id="timezone_string" name="timezone_string">
148
                <?php echo wp_timezone_choice($timezone_string); ?>
149
            </select>
150
            <br/>
151
            <span class="description"><?php _e('Choose a city in the same timezone as the event.'); ?></span>
152
        </p>
153
154
        <p>
155
        <span><?php
156
            printf(
157
                __('%1$sUTC%2$s time is %3$s'),
158
                '<abbr title="Coordinated Universal Time">',
159
                '</abbr>',
160
                '<code>' . date_i18n($datetime_format, false, true) . '</code>'
161
            );
162
            ?></span>
163
        <?php if (! empty($timezone_string) || ! empty($gmt_offset)) : ?>
164
        <br/><span><?php printf(__('Local time is %1$s'), '<code>' . date_i18n($datetime_format) . '</code>'); ?></span>
165
    <?php endif; ?>
166
167
        <?php if ($check_zone_info && $timezone_string) : ?>
168
        <br/>
169
        <span>
170
                <?php
171
                // Set TZ so localtime works.
172
                date_default_timezone_set($timezone_string);
173
                $now = localtime(time(), true);
174
                if ($now['tm_isdst']) {
175
                    _e('This timezone is currently in daylight saving time.');
176
                } else {
177
                    _e('This timezone is currently in standard time.');
178
                }
179
                ?>
180
            <br/>
181
            <?php
182
            if (function_exists('timezone_transitions_get')) {
183
                $found                   = false;
184
                $date_time_zone_selected = new DateTimeZone($timezone_string);
185
                $tz_offset               = timezone_offset_get($date_time_zone_selected, date_create());
186
                $right_now               = time();
187
                $tr['isdst']             = false;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$tr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $tr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
188
                foreach (timezone_transitions_get($date_time_zone_selected) as $tr) {
189
                    if ($tr['ts'] > $right_now) {
190
                        $found = true;
191
                        break;
192
                    }
193
                }
194
                if ($found) {
195
                    $message = $tr['isdst']
196
                        ? __(' Daylight saving time begins on: %s.')
197
                        : __(' Standard time begins  on: %s.');
198
                    // Add the difference between the current offset and the new offset to ts to get the correct
199
                    // transition time from date_i18n().
200
                    printf(
201
                        $message,
202
                        '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >'
203
                    );
204
                } else {
205
                    _e('This timezone does not observe daylight saving time.');
206
                }
207
            }
208
            // Set back to UTC.
209
            date_default_timezone_set('UTC');
210
            ?>
211
        </span></p>
212
    <?php
213
    endif;
214
    }
215
216
217
    /**
218
     * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
219
     * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
220
     * the site is used.
221
     * This is used typically when using a Unix timestamp any core WP functions that expect their specially
222
     * computed timestamp (i.e. date_i18n() )
223
     *
224
     * @param int    $unix_timestamp  if 0, then time() will be used.
225
     * @param string $timezone_string timezone_string. If empty, then the current set timezone for the
226
     *                                site will be used.
227
     * @return int      unix_timestamp value with the offset applied for the given timezone.
228
     * @throws EE_Error
229
     */
230
    public function getTimestampWithOffset($unix_timestamp = 0, $timezone_string = '')
231
    {
232
        $unix_timestamp  = $unix_timestamp === 0 ? time() : (int) $unix_timestamp;
233
        $timezone_string = $this->getValidTimezoneString($timezone_string);
234
        $TimeZone        = new DateTimeZone($timezone_string);
235
        $DateTime        = new DateTime('@' . $unix_timestamp, $TimeZone);
236
        $offset          = timezone_offset_get($TimeZone, $DateTime);
237
        return (int) $DateTime->format('U') + (int) $offset;
238
    }
239
240
241
    /**
242
     * Get Timezone Transitions
243
     *
244
     * @param DateTimeZone $date_time_zone
245
     * @param int|null     $time
246
     * @param bool         $first_only
247
     * @return array|mixed
248
     */
249
    public function getTimezoneTransitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
250
    {
251
        $time        = is_int($time) || $time === null ? $time : (int) strtotime($time);
252
        $time        = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
253
        $transitions = $date_time_zone->getTransitions($time);
254
        return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
255
    }
256
257
258
259
    /**
260
     * Default to just returning the provided $gmt_offset.  Children can override if adjustment needed.
261
     *
262
     * @param int $gmt_offset
263
     * @return int
264
     */
265
    public function adjustInvalidGmtOffsets($gmt_offset = 0)
266
    {
267
        return $gmt_offset;
268
    }
269
270
271
272
    /**
273
     * This receives an incoming gmt_offset and santizes it.  If the provide value is an empty string, then this will
274
     * attempt to get the offset from the timezone string.  If this returns a string, then a timezone string was
275
     * successfully derived from existing timezone_string in the db.  If not, then a float is returned for the provided
276
     * offset.
277
     * @param  float|string $gmt_offset
278
     * @return float|string
279
     */
280
    protected function sanitizeInitialIncomingGmtOffsetForGettingTimezoneString($gmt_offset)
281
    {
282
        //if there is no incoming gmt_offset, then because WP hooks in on timezone_string, we need to see if that is
283
        //set because it will override `gmt_offset` via `pre_get_option` filter.  If that's set, then let's just use
284
        //that!  Otherwise we'll leave timezone_string at the default of 'UTC' before doing other logic.
285
        if ($gmt_offset === '') {
286
            //autoloaded so no need to set to a variable.  There will not be multiple hits to the db.
287
            if (get_option('timezone_string')) {
288
                return (string) get_option('timezone_string');
289
            }
290
        }
291
        $gmt_offset = $gmt_offset !== '' ? $gmt_offset : (string) get_option('gmt_offset');
292
        $gmt_offset = (float) $gmt_offset;
293
        //if $gmt_offset is 0 or is still an empty string, then just return UTC
294
        if ($gmt_offset === (float) 0) {
295
            return 'UTC';
296
        }
297
        return $gmt_offset;
298
    }
299
}
300