1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use EventEspresso\core\services\helpers\datetime\HelperInterface; |
4
|
|
|
use EventEspresso\core\exceptions\InvalidDataTypeException; |
5
|
|
|
use EventEspresso\core\exceptions\InvalidInterfaceException; |
6
|
|
|
use EventEspresso\core\services\loaders\LoaderFactory; |
7
|
|
|
|
8
|
|
|
defined('EVENT_ESPRESSO_VERSION') || exit('NO direct script access allowed'); |
9
|
|
|
|
10
|
|
|
|
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* EEH_DTT_Helper |
14
|
|
|
* This is a helper utility class containing a variety for date time formatting helpers for Event Espresso. |
15
|
|
|
* |
16
|
|
|
* @package Event Espresso |
17
|
|
|
* @subpackage /helpers/EEH_DTT_Helper.helper.php |
18
|
|
|
* @author Darren Ethier |
19
|
|
|
*/ |
20
|
|
|
class EEH_DTT_Helper |
21
|
|
|
{ |
22
|
|
|
|
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* return the timezone set for the WP install |
26
|
|
|
* |
27
|
|
|
* @return string valid timezone string for PHP DateTimeZone() class |
28
|
|
|
* @throws InvalidArgumentException |
29
|
|
|
* @throws InvalidDataTypeException |
30
|
|
|
* @throws InvalidInterfaceException |
31
|
|
|
*/ |
32
|
|
|
public static function get_timezone() |
33
|
|
|
{ |
34
|
|
|
return EEH_DTT_Helper::get_valid_timezone_string(); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* get_valid_timezone_string |
40
|
|
|
* ensures that a valid timezone string is returned |
41
|
|
|
* |
42
|
|
|
* @param string $timezone_string |
43
|
|
|
* @return string |
44
|
|
|
* @throws InvalidArgumentException |
45
|
|
|
* @throws InvalidDataTypeException |
46
|
|
|
* @throws InvalidInterfaceException |
47
|
|
|
*/ |
48
|
|
|
public static function get_valid_timezone_string($timezone_string = '') |
49
|
|
|
{ |
50
|
|
|
return self::getHelperAdapter()->getValidTimezoneString($timezone_string); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* This only purpose for this static method is to validate that the incoming timezone is a valid php timezone. |
56
|
|
|
* |
57
|
|
|
* @static |
58
|
|
|
* @param string $timezone_string Timezone string to check |
59
|
|
|
* @param bool $throw_error |
60
|
|
|
* @return bool |
61
|
|
|
* @throws InvalidArgumentException |
62
|
|
|
* @throws InvalidDataTypeException |
63
|
|
|
* @throws InvalidInterfaceException |
64
|
|
|
*/ |
65
|
|
|
public static function validate_timezone($timezone_string, $throw_error = true) |
66
|
|
|
{ |
67
|
|
|
return self::getHelperAdapter()->validateTimezone($timezone_string, $throw_error); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* This returns a string that can represent the provided gmt offset in format that can be passed into |
73
|
|
|
* DateTimeZone. This is NOT a string that can be passed as a value on the WordPress timezone_string option. |
74
|
|
|
* |
75
|
|
|
* @param float|string $gmt_offset |
76
|
|
|
* @return string |
77
|
|
|
* @throws InvalidArgumentException |
78
|
|
|
* @throws InvalidDataTypeException |
79
|
|
|
* @throws InvalidInterfaceException |
80
|
|
|
*/ |
81
|
|
|
public static function get_timezone_string_from_gmt_offset($gmt_offset = '') |
82
|
|
|
{ |
83
|
|
|
return self::getHelperAdapter()->getTimezoneStringFromGmtOffset($gmt_offset); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Gets the site's GMT offset based on either the timezone string |
89
|
|
|
* (in which case teh gmt offset will vary depending on the location's |
90
|
|
|
* observance of daylight savings time) or the gmt_offset wp option |
91
|
|
|
* |
92
|
|
|
* @return int seconds offset |
93
|
|
|
* @throws InvalidArgumentException |
94
|
|
|
* @throws InvalidDataTypeException |
95
|
|
|
* @throws InvalidInterfaceException |
96
|
|
|
*/ |
97
|
|
|
public static function get_site_timezone_gmt_offset() |
98
|
|
|
{ |
99
|
|
|
return self::getHelperAdapter()->getSiteTimezoneGmtOffset(); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Depending on PHP version, |
105
|
|
|
* there might not be valid current timezone strings to match these gmt_offsets in its timezone tables. |
106
|
|
|
* To get around that, for these fringe timezones we bump them to a known valid offset. |
107
|
|
|
* This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset. |
108
|
|
|
* |
109
|
|
|
* @deprecated 4.9.54.rc Developers this was always meant to only be an internally used method. This will be |
110
|
|
|
* removed in a future version of EE. |
111
|
|
|
* @param int $gmt_offset |
112
|
|
|
* @return int |
113
|
|
|
* @throws InvalidArgumentException |
114
|
|
|
* @throws InvalidDataTypeException |
115
|
|
|
* @throws InvalidInterfaceException |
116
|
|
|
*/ |
117
|
|
|
public static function adjust_invalid_gmt_offsets($gmt_offset = 0) |
118
|
|
|
{ |
119
|
|
|
return self::getHelperAdapter()->adjustInvalidGmtOffsets($gmt_offset); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* get_timezone_string_from_abbreviations_list |
125
|
|
|
* |
126
|
|
|
* @deprecated 4.9.54.rc Developers, this was never intended to be public. This is a soft deprecation for now. |
127
|
|
|
* If you are using this, you'll want to work out an alternate way of getting the value. |
128
|
|
|
* @param int $gmt_offset |
129
|
|
|
* @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset. |
130
|
|
|
* @return string |
131
|
|
|
* @throws EE_Error |
132
|
|
|
* @throws InvalidArgumentException |
133
|
|
|
* @throws InvalidDataTypeException |
134
|
|
|
* @throws InvalidInterfaceException |
135
|
|
|
*/ |
136
|
|
|
public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true) |
137
|
|
|
{ |
138
|
|
|
$gmt_offset = (int) $gmt_offset; |
139
|
|
|
/** @var array[] $abbreviations */ |
140
|
|
|
$abbreviations = DateTimeZone::listAbbreviations(); |
141
|
|
View Code Duplication |
foreach ($abbreviations as $abbreviation) { |
142
|
|
|
foreach ($abbreviation as $timezone) { |
143
|
|
|
if ((int) $timezone['offset'] === $gmt_offset && (bool) $timezone['dst'] === false) { |
144
|
|
|
try { |
145
|
|
|
$offset = self::get_timezone_offset(new DateTimeZone($timezone['timezone_id'])); |
146
|
|
|
if ($offset !== $gmt_offset) { |
147
|
|
|
continue; |
148
|
|
|
} |
149
|
|
|
return $timezone['timezone_id']; |
150
|
|
|
} catch (Exception $e) { |
151
|
|
|
continue; |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
//if $coerce is true, let's see if we can get a timezone string after the offset is adjusted |
157
|
|
|
if ($coerce === true) { |
158
|
|
|
$timezone_string = self::get_timezone_string_from_abbreviations_list( |
|
|
|
|
159
|
|
|
self::adjust_invalid_gmt_offsets($gmt_offset), |
|
|
|
|
160
|
|
|
false |
161
|
|
|
); |
162
|
|
|
if ($timezone_string) { |
163
|
|
|
return $timezone_string; |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
throw new EE_Error( |
167
|
|
|
sprintf( |
168
|
|
|
esc_html__( |
169
|
|
|
'The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used', |
170
|
|
|
'event_espresso' |
171
|
|
|
), |
172
|
|
|
$gmt_offset / HOUR_IN_SECONDS, |
173
|
|
|
'<a href="http://www.php.net/manual/en/timezones.php">', |
174
|
|
|
'</a>' |
175
|
|
|
) |
176
|
|
|
); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Get Timezone Transitions |
182
|
|
|
* |
183
|
|
|
* @param DateTimeZone $date_time_zone |
184
|
|
|
* @param int|null $time |
185
|
|
|
* @param bool $first_only |
186
|
|
|
* @return array |
187
|
|
|
* @throws InvalidArgumentException |
188
|
|
|
* @throws InvalidDataTypeException |
189
|
|
|
* @throws InvalidInterfaceException |
190
|
|
|
*/ |
191
|
|
|
public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true) |
192
|
|
|
{ |
193
|
|
|
return self::getHelperAdapter()->getTimezoneTransitions($date_time_zone, $time, $first_only); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Get Timezone Offset for given timezone object. |
199
|
|
|
* |
200
|
|
|
* @param DateTimeZone $date_time_zone |
201
|
|
|
* @param null $time |
202
|
|
|
* @return mixed |
203
|
|
|
* @throws InvalidArgumentException |
204
|
|
|
* @throws InvalidDataTypeException |
205
|
|
|
* @throws InvalidInterfaceException |
206
|
|
|
*/ |
207
|
|
|
public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null) |
208
|
|
|
{ |
209
|
|
|
return self::getHelperAdapter()->getTimezoneOffset($date_time_zone, $time); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Prints a select input for the given timezone string. |
215
|
|
|
* @param string $timezone_string |
216
|
|
|
* @deprecatd 4.9.54.rc Soft deprecation. Consider using \EEH_DTT_Helper::wp_timezone_choice instead. |
217
|
|
|
* @throws InvalidArgumentException |
218
|
|
|
* @throws InvalidDataTypeException |
219
|
|
|
* @throws InvalidInterfaceException |
220
|
|
|
*/ |
221
|
|
|
public static function timezone_select_input($timezone_string = '') |
222
|
|
|
{ |
223
|
|
|
self::getHelperAdapter()->timezoneSelectInput($timezone_string); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* This method will take an incoming unix timestamp and add the offset to it for the given timezone_string. |
229
|
|
|
* If no unix timestamp is given then time() is used. If no timezone is given then the set timezone string for |
230
|
|
|
* the site is used. |
231
|
|
|
* This is used typically when using a Unix timestamp any core WP functions that expect their specially |
232
|
|
|
* computed timestamp (i.e. date_i18n() ) |
233
|
|
|
* |
234
|
|
|
* @param int $unix_timestamp if 0, then time() will be used. |
235
|
|
|
* @param string $timezone_string timezone_string. If empty, then the current set timezone for the |
236
|
|
|
* site will be used. |
237
|
|
|
* @return int $unix_timestamp with the offset applied for the given timezone. |
238
|
|
|
* @throws InvalidArgumentException |
239
|
|
|
* @throws InvalidDataTypeException |
240
|
|
|
* @throws InvalidInterfaceException |
241
|
|
|
*/ |
242
|
|
|
public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '') |
243
|
|
|
{ |
244
|
|
|
return self::getHelperAdapter()->getTimestampWithOffset($unix_timestamp, $timezone_string); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* _set_date_time_field |
250
|
|
|
* modifies EE_Base_Class EE_Datetime_Field objects |
251
|
|
|
* |
252
|
|
|
* @param EE_Base_Class $obj EE_Base_Class object |
253
|
|
|
* @param DateTime $DateTime PHP DateTime object |
254
|
|
|
* @param string $datetime_field_name the datetime fieldname to be manipulated |
255
|
|
|
* @return EE_Base_Class |
256
|
|
|
* @throws EE_Error |
257
|
|
|
*/ |
258
|
|
|
protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name) |
259
|
|
|
{ |
260
|
|
|
// grab current datetime format |
261
|
|
|
$current_format = $obj->get_format(); |
262
|
|
|
// set new full timestamp format |
263
|
|
|
$obj->set_date_format(EE_Datetime_Field::mysql_date_format); |
264
|
|
|
$obj->set_time_format(EE_Datetime_Field::mysql_time_format); |
265
|
|
|
// set the new date value using a full timestamp format so that no data is lost |
266
|
|
|
$obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format)); |
267
|
|
|
// reset datetime formats |
268
|
|
|
$obj->set_date_format($current_format[0]); |
269
|
|
|
$obj->set_time_format($current_format[1]); |
270
|
|
|
return $obj; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* date_time_add |
276
|
|
|
* helper for doing simple datetime calculations on a given datetime from EE_Base_Class |
277
|
|
|
* and modifying it IN the EE_Base_Class so you don't have to do anything else. |
278
|
|
|
* |
279
|
|
|
* @param EE_Base_Class $obj EE_Base_Class object |
280
|
|
|
* @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
281
|
|
|
* @param string $period what you are adding. The options are (years, months, days, hours, |
282
|
|
|
* minutes, seconds) defaults to years |
283
|
|
|
* @param integer $value what you want to increment the time by |
284
|
|
|
* @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it |
285
|
|
|
* (chaining) |
286
|
|
|
* @throws EE_Error |
287
|
|
|
* @throws Exception |
288
|
|
|
*/ |
289
|
|
View Code Duplication |
public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
290
|
|
|
{ |
291
|
|
|
//get the raw UTC date. |
292
|
|
|
$DateTime = $obj->get_DateTime_object($datetime_field_name); |
293
|
|
|
$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value); |
294
|
|
|
return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* date_time_subtract |
300
|
|
|
* same as date_time_add except subtracting value instead of adding. |
301
|
|
|
* |
302
|
|
|
* @param EE_Base_Class $obj |
303
|
|
|
* @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
304
|
|
|
* @param string $period |
305
|
|
|
* @param int $value |
306
|
|
|
* @return EE_Base_Class |
307
|
|
|
* @throws EE_Error |
308
|
|
|
* @throws Exception |
309
|
|
|
*/ |
310
|
|
View Code Duplication |
public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
311
|
|
|
{ |
312
|
|
|
//get the raw UTC date |
313
|
|
|
$DateTime = $obj->get_DateTime_object($datetime_field_name); |
314
|
|
|
$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-'); |
315
|
|
|
return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters |
321
|
|
|
* |
322
|
|
|
* @param DateTime $DateTime DateTime object |
323
|
|
|
* @param string $period a value to indicate what interval is being used in the calculation. The options are |
324
|
|
|
* 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
325
|
|
|
* @param int|string $value What you want to increment the date by |
326
|
|
|
* @param string $operand What operand you wish to use for the calculation |
327
|
|
|
* @return DateTime return whatever type came in. |
328
|
|
|
* @throws Exception |
329
|
|
|
* @throws EE_Error |
330
|
|
|
*/ |
331
|
|
|
protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+') |
332
|
|
|
{ |
333
|
|
|
if (! $DateTime instanceof DateTime) { |
334
|
|
|
throw new EE_Error( |
335
|
|
|
sprintf( |
336
|
|
|
esc_html__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'), |
337
|
|
|
print_r($DateTime, true) |
338
|
|
|
) |
339
|
|
|
); |
340
|
|
|
} |
341
|
|
|
switch ($period) { |
342
|
|
|
case 'years' : |
343
|
|
|
$value = 'P' . $value . 'Y'; |
344
|
|
|
break; |
345
|
|
|
case 'months' : |
346
|
|
|
$value = 'P' . $value . 'M'; |
347
|
|
|
break; |
348
|
|
|
case 'weeks' : |
349
|
|
|
$value = 'P' . $value . 'W'; |
350
|
|
|
break; |
351
|
|
|
case 'days' : |
352
|
|
|
$value = 'P' . $value . 'D'; |
353
|
|
|
break; |
354
|
|
|
case 'hours' : |
355
|
|
|
$value = 'PT' . $value . 'H'; |
356
|
|
|
break; |
357
|
|
|
case 'minutes' : |
358
|
|
|
$value = 'PT' . $value . 'M'; |
359
|
|
|
break; |
360
|
|
|
case 'seconds' : |
361
|
|
|
$value = 'PT' . $value . 'S'; |
362
|
|
|
break; |
363
|
|
|
} |
364
|
|
|
switch ($operand) { |
365
|
|
|
case '+': |
366
|
|
|
$DateTime->add(new DateInterval($value)); |
367
|
|
|
break; |
368
|
|
|
case '-': |
369
|
|
|
$DateTime->sub(new DateInterval($value)); |
370
|
|
|
break; |
371
|
|
|
} |
372
|
|
|
return $DateTime; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters |
378
|
|
|
* |
379
|
|
|
* @param int $timestamp Unix timestamp |
380
|
|
|
* @param string $period a value to indicate what interval is being used in the calculation. The options are |
381
|
|
|
* 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
382
|
|
|
* @param integer $value What you want to increment the date by |
383
|
|
|
* @param string $operand What operand you wish to use for the calculation |
384
|
|
|
* @return int |
385
|
|
|
* @throws EE_Error |
386
|
|
|
*/ |
387
|
|
|
protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+') |
388
|
|
|
{ |
389
|
|
|
if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) { |
390
|
|
|
throw new EE_Error( |
391
|
|
|
sprintf( |
392
|
|
|
esc_html__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'), |
393
|
|
|
print_r($timestamp, true) |
394
|
|
|
) |
395
|
|
|
); |
396
|
|
|
} |
397
|
|
|
switch ($period) { |
398
|
|
|
case 'years' : |
399
|
|
|
$value = YEAR_IN_SECONDS * $value; |
400
|
|
|
break; |
401
|
|
|
case 'months' : |
402
|
|
|
$value = YEAR_IN_SECONDS / 12 * $value; |
403
|
|
|
break; |
404
|
|
|
case 'weeks' : |
405
|
|
|
$value = WEEK_IN_SECONDS * $value; |
406
|
|
|
break; |
407
|
|
|
case 'days' : |
408
|
|
|
$value = DAY_IN_SECONDS * $value; |
409
|
|
|
break; |
410
|
|
|
case 'hours' : |
411
|
|
|
$value = HOUR_IN_SECONDS * $value; |
412
|
|
|
break; |
413
|
|
|
case 'minutes' : |
414
|
|
|
$value = MINUTE_IN_SECONDS * $value; |
415
|
|
|
break; |
416
|
|
|
} |
417
|
|
|
switch ($operand) { |
418
|
|
|
case '+': |
419
|
|
|
$timestamp += $value; |
420
|
|
|
break; |
421
|
|
|
case '-': |
422
|
|
|
$timestamp -= $value; |
423
|
|
|
break; |
424
|
|
|
} |
425
|
|
|
return $timestamp; |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming |
431
|
|
|
* parameters and returns the new timestamp or DateTime. |
432
|
|
|
* |
433
|
|
|
* @param int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp |
434
|
|
|
* @param string $period a value to indicate what interval is being used in the |
435
|
|
|
* calculation. The options are 'years', 'months', 'days', 'hours', |
436
|
|
|
* 'minutes', 'seconds'. Defaults to years. |
437
|
|
|
* @param integer $value What you want to increment the date by |
438
|
|
|
* @param string $operand What operand you wish to use for the calculation |
439
|
|
|
* @return mixed string|DateTime return whatever type came in. |
440
|
|
|
* @throws Exception |
441
|
|
|
* @throws EE_Error |
442
|
|
|
*/ |
443
|
|
|
public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+') |
444
|
|
|
{ |
445
|
|
|
if ($DateTime_or_timestamp instanceof DateTime) { |
446
|
|
|
return EEH_DTT_Helper::_modify_datetime_object( |
447
|
|
|
$DateTime_or_timestamp, |
448
|
|
|
$period, |
449
|
|
|
$value, |
450
|
|
|
$operand |
451
|
|
|
); |
452
|
|
|
} |
453
|
|
|
if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) { |
454
|
|
|
return EEH_DTT_Helper::_modify_timestamp( |
455
|
|
|
$DateTime_or_timestamp, |
456
|
|
|
$period, |
457
|
|
|
$value, |
458
|
|
|
$operand |
459
|
|
|
); |
460
|
|
|
} |
461
|
|
|
//error |
462
|
|
|
return $DateTime_or_timestamp; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* The purpose of this helper method is to receive an incoming format string in php date/time format |
468
|
|
|
* and spit out the js and moment.js equivalent formats. |
469
|
|
|
* Note, if no format string is given, then it is assumed the user wants what is set for WP. |
470
|
|
|
* Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date- |
471
|
|
|
* time picker. |
472
|
|
|
* |
473
|
|
|
* @see http://stackoverflow.com/posts/16725290/ for the code inspiration. |
474
|
|
|
* @param string $date_format_string |
475
|
|
|
* @param string $time_format_string |
476
|
|
|
* @return array |
477
|
|
|
* array( |
478
|
|
|
* 'js' => array ( |
479
|
|
|
* 'date' => //date format |
480
|
|
|
* 'time' => //time format |
481
|
|
|
* ), |
482
|
|
|
* 'moment' => //date and time format. |
483
|
|
|
* ) |
484
|
|
|
*/ |
485
|
|
|
public static function convert_php_to_js_and_moment_date_formats( |
486
|
|
|
$date_format_string = null, |
487
|
|
|
$time_format_string = null |
488
|
|
|
) { |
489
|
|
|
if ($date_format_string === null) { |
490
|
|
|
$date_format_string = (string) get_option('date_format'); |
491
|
|
|
} |
492
|
|
|
if ($time_format_string === null) { |
493
|
|
|
$time_format_string = (string) get_option('time_format'); |
494
|
|
|
} |
495
|
|
|
$date_format = self::_php_to_js_moment_converter($date_format_string); |
496
|
|
|
$time_format = self::_php_to_js_moment_converter($time_format_string); |
497
|
|
|
return array( |
498
|
|
|
'js' => array( |
499
|
|
|
'date' => $date_format['js'], |
500
|
|
|
'time' => $time_format['js'], |
501
|
|
|
), |
502
|
|
|
'moment' => $date_format['moment'] . ' ' . $time_format['moment'], |
503
|
|
|
); |
504
|
|
|
} |
505
|
|
|
|
506
|
|
|
|
507
|
|
|
/** |
508
|
|
|
* This converts incoming format string into js and moment variations. |
509
|
|
|
* |
510
|
|
|
* @param string $format_string incoming php format string |
511
|
|
|
* @return array js and moment formats. |
512
|
|
|
*/ |
513
|
|
|
protected static function _php_to_js_moment_converter($format_string) |
514
|
|
|
{ |
515
|
|
|
/** |
516
|
|
|
* This is a map of symbols for formats. |
517
|
|
|
* The index is the php symbol, the equivalent values are in the array. |
518
|
|
|
* |
519
|
|
|
* @var array |
520
|
|
|
*/ |
521
|
|
|
$symbols_map = array( |
522
|
|
|
// Day |
523
|
|
|
//01 |
524
|
|
|
'd' => array( |
525
|
|
|
'js' => 'dd', |
526
|
|
|
'moment' => 'DD', |
527
|
|
|
), |
528
|
|
|
//Mon |
529
|
|
|
'D' => array( |
530
|
|
|
'js' => 'D', |
531
|
|
|
'moment' => 'ddd', |
532
|
|
|
), |
533
|
|
|
//1,2,...31 |
534
|
|
|
'j' => array( |
535
|
|
|
'js' => 'd', |
536
|
|
|
'moment' => 'D', |
537
|
|
|
), |
538
|
|
|
//Monday |
539
|
|
|
'l' => array( |
540
|
|
|
'js' => 'DD', |
541
|
|
|
'moment' => 'dddd', |
542
|
|
|
), |
543
|
|
|
//ISO numeric representation of the day of the week (1-6) |
544
|
|
|
'N' => array( |
545
|
|
|
'js' => '', |
546
|
|
|
'moment' => 'E', |
547
|
|
|
), |
548
|
|
|
//st,nd.rd |
549
|
|
|
'S' => array( |
550
|
|
|
'js' => '', |
551
|
|
|
'moment' => 'o', |
552
|
|
|
), |
553
|
|
|
//numeric representation of day of week (0-6) |
554
|
|
|
'w' => array( |
555
|
|
|
'js' => '', |
556
|
|
|
'moment' => 'd', |
557
|
|
|
), |
558
|
|
|
//day of year starting from 0 (0-365) |
559
|
|
|
'z' => array( |
560
|
|
|
'js' => 'o', |
561
|
|
|
'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1 |
562
|
|
|
), |
563
|
|
|
// Week |
564
|
|
|
//ISO-8601 week number of year (weeks starting on monday) |
565
|
|
|
'W' => array( |
566
|
|
|
'js' => '', |
567
|
|
|
'moment' => 'w', |
568
|
|
|
), |
569
|
|
|
// Month |
570
|
|
|
// January...December |
571
|
|
|
'F' => array( |
572
|
|
|
'js' => 'MM', |
573
|
|
|
'moment' => 'MMMM', |
574
|
|
|
), |
575
|
|
|
//01...12 |
576
|
|
|
'm' => array( |
577
|
|
|
'js' => 'mm', |
578
|
|
|
'moment' => 'MM', |
579
|
|
|
), |
580
|
|
|
//Jan...Dec |
581
|
|
|
'M' => array( |
582
|
|
|
'js' => 'M', |
583
|
|
|
'moment' => 'MMM', |
584
|
|
|
), |
585
|
|
|
//1-12 |
586
|
|
|
'n' => array( |
587
|
|
|
'js' => 'm', |
588
|
|
|
'moment' => 'M', |
589
|
|
|
), |
590
|
|
|
//number of days in given month |
591
|
|
|
't' => array( |
592
|
|
|
'js' => '', |
593
|
|
|
'moment' => '', |
594
|
|
|
), |
595
|
|
|
// Year |
596
|
|
|
//whether leap year or not 1/0 |
597
|
|
|
'L' => array( |
598
|
|
|
'js' => '', |
599
|
|
|
'moment' => '', |
600
|
|
|
), |
601
|
|
|
//ISO-8601 year number |
602
|
|
|
'o' => array( |
603
|
|
|
'js' => '', |
604
|
|
|
'moment' => 'GGGG', |
605
|
|
|
), |
606
|
|
|
//1999...2003 |
607
|
|
|
'Y' => array( |
608
|
|
|
'js' => 'yy', |
609
|
|
|
'moment' => 'YYYY', |
610
|
|
|
), |
611
|
|
|
//99...03 |
612
|
|
|
'y' => array( |
613
|
|
|
'js' => 'y', |
614
|
|
|
'moment' => 'YY', |
615
|
|
|
), |
616
|
|
|
// Time |
617
|
|
|
// am/pm |
618
|
|
|
'a' => array( |
619
|
|
|
'js' => 'tt', |
620
|
|
|
'moment' => 'a', |
621
|
|
|
), |
622
|
|
|
// AM/PM |
623
|
|
|
'A' => array( |
624
|
|
|
'js' => 'TT', |
625
|
|
|
'moment' => 'A', |
626
|
|
|
), |
627
|
|
|
// Swatch Internet Time?!? |
628
|
|
|
'B' => array( |
629
|
|
|
'js' => '', |
630
|
|
|
'moment' => '', |
631
|
|
|
), |
632
|
|
|
//1...12 |
633
|
|
|
'g' => array( |
634
|
|
|
'js' => 'h', |
635
|
|
|
'moment' => 'h', |
636
|
|
|
), |
637
|
|
|
//0...23 |
638
|
|
|
'G' => array( |
639
|
|
|
'js' => 'H', |
640
|
|
|
'moment' => 'H', |
641
|
|
|
), |
642
|
|
|
//01...12 |
643
|
|
|
'h' => array( |
644
|
|
|
'js' => 'hh', |
645
|
|
|
'moment' => 'hh', |
646
|
|
|
), |
647
|
|
|
//00...23 |
648
|
|
|
'H' => array( |
649
|
|
|
'js' => 'HH', |
650
|
|
|
'moment' => 'HH', |
651
|
|
|
), |
652
|
|
|
//00..59 |
653
|
|
|
'i' => array( |
654
|
|
|
'js' => 'mm', |
655
|
|
|
'moment' => 'mm', |
656
|
|
|
), |
657
|
|
|
//seconds... 00...59 |
658
|
|
|
's' => array( |
659
|
|
|
'js' => 'ss', |
660
|
|
|
'moment' => 'ss', |
661
|
|
|
), |
662
|
|
|
//microseconds |
663
|
|
|
'u' => array( |
664
|
|
|
'js' => '', |
665
|
|
|
'moment' => '', |
666
|
|
|
), |
667
|
|
|
); |
668
|
|
|
$jquery_ui_format = ''; |
669
|
|
|
$moment_format = ''; |
670
|
|
|
$escaping = false; |
671
|
|
|
$format_string_length = strlen($format_string); |
672
|
|
|
for ($i = 0; $i < $format_string_length; $i++) { |
673
|
|
|
$char = $format_string[ $i ]; |
674
|
|
|
if ($char === '\\') { // PHP date format escaping character |
675
|
|
|
$i++; |
676
|
|
|
if ($escaping) { |
677
|
|
|
$jquery_ui_format .= $format_string[ $i ]; |
678
|
|
|
$moment_format .= $format_string[ $i ]; |
679
|
|
|
} else { |
680
|
|
|
$jquery_ui_format .= '\'' . $format_string[ $i ]; |
681
|
|
|
$moment_format .= $format_string[ $i ]; |
682
|
|
|
} |
683
|
|
|
$escaping = true; |
684
|
|
|
} else { |
685
|
|
|
if ($escaping) { |
686
|
|
|
$jquery_ui_format .= "'"; |
687
|
|
|
$moment_format .= "'"; |
688
|
|
|
$escaping = false; |
689
|
|
|
} |
690
|
|
|
if (isset($symbols_map[ $char ])) { |
691
|
|
|
$jquery_ui_format .= $symbols_map[ $char ]['js']; |
692
|
|
|
$moment_format .= $symbols_map[ $char ]['moment']; |
693
|
|
|
} else { |
694
|
|
|
$jquery_ui_format .= $char; |
695
|
|
|
$moment_format .= $char; |
696
|
|
|
} |
697
|
|
|
} |
698
|
|
|
} |
699
|
|
|
return array('js' => $jquery_ui_format, 'moment' => $moment_format); |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
|
703
|
|
|
/** |
704
|
|
|
* This takes an incoming format string and validates it to ensure it will work fine with PHP. |
705
|
|
|
* |
706
|
|
|
* @param string $format_string Incoming format string for php date(). |
707
|
|
|
* @return mixed bool|array If all is okay then TRUE is returned. Otherwise an array of validation |
708
|
|
|
* errors is returned. So for client code calling, check for is_array() to |
709
|
|
|
* indicate failed validations. |
710
|
|
|
*/ |
711
|
|
|
public static function validate_format_string($format_string) |
712
|
|
|
{ |
713
|
|
|
$error_msg = array(); |
714
|
|
|
//time format checks |
715
|
|
|
switch (true) { |
716
|
|
|
case strpos($format_string, 'h') !== false : |
717
|
|
|
case strpos($format_string, 'g') !== false : |
718
|
|
|
/** |
719
|
|
|
* if the time string has a lowercase 'h' which == 12 hour time format and there |
720
|
|
|
* is not any ante meridiem format ('a' or 'A'). Then throw an error because its |
721
|
|
|
* too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am. |
722
|
|
|
*/ |
723
|
|
|
if (stripos($format_string, 'A') === false) { |
724
|
|
|
$error_msg[] = esc_html__( |
725
|
|
|
'There is a time format for 12 hour time but no "a" or "A" to indicate am/pm. Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".', |
726
|
|
|
'event_espresso' |
727
|
|
|
); |
728
|
|
|
} |
729
|
|
|
break; |
730
|
|
|
} |
731
|
|
|
return empty($error_msg) ? true : $error_msg; |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
|
735
|
|
|
/** |
736
|
|
|
* If the the first date starts at midnight on one day, and the next date ends at midnight on the |
737
|
|
|
* very next day then this method will return true. |
738
|
|
|
* If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true. |
739
|
|
|
* If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false. |
740
|
|
|
* If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true. |
741
|
|
|
* |
742
|
|
|
* @param mixed $date_1 |
743
|
|
|
* @param mixed $date_2 |
744
|
|
|
* @return bool |
745
|
|
|
*/ |
746
|
|
|
public static function dates_represent_one_24_hour_date($date_1, $date_2) |
747
|
|
|
{ |
748
|
|
|
|
749
|
|
|
if ( |
750
|
|
|
(! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) |
751
|
|
|
|| ($date_1->format(EE_Datetime_Field::mysql_time_format) !== '00:00:00' |
752
|
|
|
|| $date_2->format( |
753
|
|
|
EE_Datetime_Field::mysql_time_format |
754
|
|
|
) !== '00:00:00') |
755
|
|
|
) { |
756
|
|
|
return false; |
757
|
|
|
} |
758
|
|
|
return $date_2->format('U') - $date_1->format('U') === 86400; |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
|
762
|
|
|
/** |
763
|
|
|
* This returns the appropriate query interval string that can be used in sql queries involving mysql Date |
764
|
|
|
* Functions. |
765
|
|
|
* |
766
|
|
|
* @param string $timezone_string A timezone string in a valid format to instantiate a DateTimeZone object. |
767
|
|
|
* @param string $field_for_interval The Database field that is the interval is applied to in the query. |
768
|
|
|
* @return string |
769
|
|
|
*/ |
770
|
|
|
public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval) |
771
|
|
|
{ |
772
|
|
|
try { |
773
|
|
|
/** need to account for timezone offset on the selects */ |
774
|
|
|
$DateTimeZone = new DateTimeZone($timezone_string); |
775
|
|
|
} catch (Exception $e) { |
776
|
|
|
$DateTimeZone = null; |
777
|
|
|
} |
778
|
|
|
/** |
779
|
|
|
* Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds. |
780
|
|
|
* Hence we do the calc for DateTimeZone::getOffset. |
781
|
|
|
*/ |
782
|
|
|
$offset = $DateTimeZone instanceof DateTimeZone |
783
|
|
|
? $DateTimeZone->getOffset(new DateTime('now')) / HOUR_IN_SECONDS |
784
|
|
|
: (float) get_option('gmt_offset'); |
785
|
|
|
$query_interval = $offset < 0 |
786
|
|
|
? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)' |
787
|
|
|
: 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)'; |
788
|
|
|
return $query_interval; |
789
|
|
|
} |
790
|
|
|
|
791
|
|
|
|
792
|
|
|
/** |
793
|
|
|
* Retrieves the site's default timezone and returns it formatted so it's ready for display |
794
|
|
|
* to users. If you want to customize how its displayed feel free to fetch the 'timezone_string' |
795
|
|
|
* and 'gmt_offset' WordPress options directly; or use the filter |
796
|
|
|
* FHEE__EEH_DTT_Helper__get_timezone_string_for_display |
797
|
|
|
* (although note that we remove any HTML that may be added) |
798
|
|
|
* |
799
|
|
|
* @return string |
800
|
|
|
*/ |
801
|
|
|
public static function get_timezone_string_for_display() |
802
|
|
|
{ |
803
|
|
|
$pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', ''); |
804
|
|
|
if (! empty($pretty_timezone)) { |
805
|
|
|
return esc_html($pretty_timezone); |
806
|
|
|
} |
807
|
|
|
$timezone_string = get_option('timezone_string'); |
808
|
|
|
if ($timezone_string) { |
809
|
|
|
static $mo_loaded = false; |
810
|
|
|
// Load translations for continents and cities just like wp_timezone_choice does |
811
|
|
|
if (! $mo_loaded) { |
812
|
|
|
$locale = get_locale(); |
813
|
|
|
$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo'; |
814
|
|
|
load_textdomain('continents-cities', $mofile); |
815
|
|
|
$mo_loaded = true; |
816
|
|
|
} |
817
|
|
|
//well that was easy. |
818
|
|
|
$parts = explode('/', $timezone_string); |
819
|
|
|
//remove the continent |
820
|
|
|
unset($parts[0]); |
821
|
|
|
$t_parts = array(); |
822
|
|
|
foreach ($parts as $part) { |
823
|
|
|
$t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities'); |
824
|
|
|
} |
825
|
|
|
return implode(' - ', $t_parts); |
826
|
|
|
} |
827
|
|
|
//they haven't set the timezone string, so let's return a string like "UTC+1" |
828
|
|
|
$gmt_offset = get_option('gmt_offset'); |
829
|
|
|
$prefix = (int) $gmt_offset >= 0 ? '+' : ''; |
830
|
|
|
$parts = explode('.', (string) $gmt_offset); |
831
|
|
|
if (count($parts) === 1) { |
832
|
|
|
$parts[1] = '00'; |
833
|
|
|
} else { |
834
|
|
|
//convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25) |
835
|
|
|
//to minutes, eg 30 or 15, respectively |
836
|
|
|
$hour_fraction = (float) ('0.' . $parts[1]); |
837
|
|
|
$parts[1] = (string) $hour_fraction * 60; |
838
|
|
|
} |
839
|
|
|
return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts)); |
840
|
|
|
} |
841
|
|
|
|
842
|
|
|
|
843
|
|
|
|
844
|
|
|
/** |
845
|
|
|
* So PHP does this awesome thing where if you are trying to get a timestamp |
846
|
|
|
* for a month using a string like "February" or "February 2017", |
847
|
|
|
* and you don't specify a day as part of your string, |
848
|
|
|
* then PHP will use whatever the current day of the month is. |
849
|
|
|
* IF the current day of the month happens to be the 30th or 31st, |
850
|
|
|
* then PHP gets really confused by a date like February 30, |
851
|
|
|
* so instead of saying |
852
|
|
|
* "Hey February only has 28 days (this year)... |
853
|
|
|
* ...you must have meant the last day of the month!" |
854
|
|
|
* PHP does the next most logical thing, and bumps the date up to March 2nd, |
855
|
|
|
* because someone requesting February 30th obviously meant March 1st! |
856
|
|
|
* The way around this is to always set the day to the first, |
857
|
|
|
* so that the month will stay on the month you wanted. |
858
|
|
|
* this method will add that "1" into your date regardless of the format. |
859
|
|
|
* |
860
|
|
|
* @param string $month |
861
|
|
|
* @return string |
862
|
|
|
*/ |
863
|
|
|
public static function first_of_month_timestamp($month = '') |
864
|
|
|
{ |
865
|
|
|
$month = (string) $month; |
866
|
|
|
$year = ''; |
867
|
|
|
// check if the incoming string has a year in it or not |
868
|
|
|
if (preg_match('/\b\d{4}\b/', $month, $matches)) { |
869
|
|
|
$year = $matches[0]; |
870
|
|
|
// ten remove that from the month string as well as any spaces |
871
|
|
|
$month = trim(str_replace($year, '', $month)); |
872
|
|
|
// add a space before the year |
873
|
|
|
$year = " {$year}"; |
874
|
|
|
} |
875
|
|
|
// return timestamp for something like "February 1 2017" |
876
|
|
|
return strtotime("{$month} 1{$year}"); |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
|
880
|
|
|
/** |
881
|
|
|
* This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone. So it may be midnight |
882
|
|
|
* for this sites timezone, but the timestamp could be some other time GMT. |
883
|
|
|
*/ |
884
|
|
|
public static function tomorrow() |
885
|
|
|
{ |
886
|
|
|
//The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive |
887
|
|
|
//before adding to the timestamp. Why? Because we want tomorrow to be for midnight the next day in THIS timezone |
888
|
|
|
//not an offset from midnight in UTC. So if we're starting with UTC 00:00:00, then we want to make sure the |
889
|
|
|
//final timestamp is equivalent to midnight in this timezone as represented in GMT. |
890
|
|
|
return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1); |
891
|
|
|
} |
892
|
|
|
|
893
|
|
|
|
894
|
|
|
/** |
895
|
|
|
* ** |
896
|
|
|
* Gives a nicely-formatted list of timezone strings. |
897
|
|
|
* Copied from the core wp function by the same name so we could customize to remove UTC offsets. |
898
|
|
|
* |
899
|
|
|
* @since 4.9.40.rc.008 |
900
|
|
|
* @staticvar bool $mo_loaded |
901
|
|
|
* @staticvar string $locale_loaded |
902
|
|
|
* @param string $selected_zone Selected timezone. |
903
|
|
|
* @param string $locale Optional. Locale to load the timezones in. Default current site locale. |
904
|
|
|
* @return string |
905
|
|
|
*/ |
906
|
|
|
public static function wp_timezone_choice($selected_zone, $locale = null) |
907
|
|
|
{ |
908
|
|
|
static $mo_loaded = false, $locale_loaded = null; |
909
|
|
|
$continents = array( |
910
|
|
|
'Africa', |
911
|
|
|
'America', |
912
|
|
|
'Antarctica', |
913
|
|
|
'Arctic', |
914
|
|
|
'Asia', |
915
|
|
|
'Atlantic', |
916
|
|
|
'Australia', |
917
|
|
|
'Europe', |
918
|
|
|
'Indian', |
919
|
|
|
'Pacific', |
920
|
|
|
); |
921
|
|
|
// Load translations for continents and cities. |
922
|
|
|
if (! $mo_loaded || $locale !== $locale_loaded) { |
923
|
|
|
$locale_loaded = $locale ? $locale : get_locale(); |
924
|
|
|
$mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo'; |
925
|
|
|
unload_textdomain('continents-cities'); |
926
|
|
|
load_textdomain('continents-cities', $mofile); |
927
|
|
|
$mo_loaded = true; |
928
|
|
|
} |
929
|
|
|
$zone_data = array(); |
930
|
|
|
foreach (timezone_identifiers_list() as $zone) { |
931
|
|
|
$zone = explode('/', $zone); |
932
|
|
|
if (! in_array($zone[0], $continents, true)) { |
933
|
|
|
continue; |
934
|
|
|
} |
935
|
|
|
// This determines what gets set and translated - we don't translate Etc/* strings here, they are done later |
936
|
|
|
$exists = array( |
937
|
|
|
0 => isset($zone[0]) && $zone[0], |
938
|
|
|
1 => isset($zone[1]) && $zone[1], |
939
|
|
|
2 => isset($zone[2]) && $zone[2], |
940
|
|
|
); |
941
|
|
|
$exists[3] = $exists[0] && $zone[0] !== 'Etc'; |
942
|
|
|
$exists[4] = $exists[1] && $exists[3]; |
943
|
|
|
$exists[5] = $exists[2] && $exists[3]; |
944
|
|
|
$zone_data[] = array( |
945
|
|
|
'continent' => $exists[0] ? $zone[0] : '', |
946
|
|
|
'city' => $exists[1] ? $zone[1] : '', |
947
|
|
|
'subcity' => $exists[2] ? $zone[2] : '', |
948
|
|
|
't_continent' => $exists[3] |
949
|
|
|
? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') |
950
|
|
|
: '', |
951
|
|
|
't_city' => $exists[4] |
952
|
|
|
? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') |
953
|
|
|
: '', |
954
|
|
|
't_subcity' => $exists[5] |
955
|
|
|
? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') |
956
|
|
|
: '', |
957
|
|
|
); |
958
|
|
|
} |
959
|
|
|
usort($zone_data, '_wp_timezone_choice_usort_callback'); |
960
|
|
|
$structure = array(); |
961
|
|
|
if (empty($selected_zone)) { |
962
|
|
|
$structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>'; |
963
|
|
|
} |
964
|
|
|
foreach ($zone_data as $key => $zone) { |
965
|
|
|
// Build value in an array to join later |
966
|
|
|
$value = array($zone['continent']); |
967
|
|
|
if (empty($zone['city'])) { |
968
|
|
|
// It's at the continent level (generally won't happen) |
969
|
|
|
$display = $zone['t_continent']; |
970
|
|
|
} else { |
971
|
|
|
// It's inside a continent group |
972
|
|
|
// Continent optgroup |
973
|
|
|
if (! isset($zone_data[ $key - 1 ]) || $zone_data[ $key - 1 ]['continent'] !== $zone['continent']) { |
974
|
|
|
$label = $zone['t_continent']; |
975
|
|
|
$structure[] = '<optgroup label="' . esc_attr($label) . '">'; |
976
|
|
|
} |
977
|
|
|
// Add the city to the value |
978
|
|
|
$value[] = $zone['city']; |
979
|
|
|
$display = $zone['t_city']; |
980
|
|
|
if (! empty($zone['subcity'])) { |
981
|
|
|
// Add the subcity to the value |
982
|
|
|
$value[] = $zone['subcity']; |
983
|
|
|
$display .= ' - ' . $zone['t_subcity']; |
984
|
|
|
} |
985
|
|
|
} |
986
|
|
|
// Build the value |
987
|
|
|
$value = implode('/', $value); |
988
|
|
|
$selected = $value === $selected_zone ? ' selected="selected"' : ''; |
989
|
|
|
$structure[] = '<option value="' . esc_attr($value) . '"' . $selected . '>' |
990
|
|
|
. esc_html($display) |
991
|
|
|
. '</option>'; |
992
|
|
|
// Close continent optgroup |
993
|
|
|
if (! empty($zone['city']) |
994
|
|
|
&& ( |
995
|
|
|
! isset($zone_data[ $key + 1 ]) |
996
|
|
|
|| (isset($zone_data[ $key + 1 ]) && $zone_data[ $key + 1 ]['continent'] !== $zone['continent']) |
997
|
|
|
) |
998
|
|
|
) { |
999
|
|
|
$structure[] = '</optgroup>'; |
1000
|
|
|
} |
1001
|
|
|
} |
1002
|
|
|
return implode("\n", $structure); |
1003
|
|
|
} |
1004
|
|
|
|
1005
|
|
|
|
1006
|
|
|
/** |
1007
|
|
|
* Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0 |
1008
|
|
|
* |
1009
|
|
|
* @param int|WP_User $user_id |
1010
|
|
|
* @return string |
1011
|
|
|
*/ |
1012
|
|
|
public static function get_user_locale($user_id = 0) |
1013
|
|
|
{ |
1014
|
|
|
if (function_exists('get_user_locale')) { |
1015
|
|
|
return get_user_locale($user_id); |
1016
|
|
|
} |
1017
|
|
|
return get_locale(); |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
|
1021
|
|
|
/** |
1022
|
|
|
* Return the appropriate helper adapter for DTT related things. |
1023
|
|
|
* |
1024
|
|
|
* @return HelperInterface |
1025
|
|
|
* @throws InvalidArgumentException |
1026
|
|
|
* @throws InvalidDataTypeException |
1027
|
|
|
* @throws InvalidInterfaceException |
1028
|
|
|
*/ |
1029
|
|
|
private static function getHelperAdapter() { |
1030
|
|
|
$dtt_helper_fqcn = PHP_VERSION_ID < 50600 |
1031
|
|
|
? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper' |
1032
|
|
|
: 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper'; |
1033
|
|
|
return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn); |
1034
|
|
|
} |
1035
|
|
|
|
1036
|
|
|
|
1037
|
|
|
/** |
1038
|
|
|
* Helper function for setting the timezone on a DateTime object. |
1039
|
|
|
* This is implemented to standardize a workaround for a PHP bug outlined in |
1040
|
|
|
* https://events.codebasehq.com/projects/event-espresso/tickets/11407 and |
1041
|
|
|
* https://events.codebasehq.com/projects/event-espresso/tickets/11233 |
1042
|
|
|
* |
1043
|
|
|
* @param DateTime $datetime |
1044
|
|
|
* @param DateTimeZone $timezone |
1045
|
|
|
*/ |
1046
|
|
|
public static function setTimezone(DateTime $datetime, DateTimeZone $timezone) |
1047
|
|
|
{ |
1048
|
|
|
$datetime->setTimezone($timezone); |
1049
|
|
|
$datetime->getTimestamp(); |
1050
|
|
|
} |
1051
|
|
|
} |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.