PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Helpers/global/date.php +48 -26 10.10.2 → 11.1.0 View file →
@@ -1,10 +1,11 @@
1 1 <?php
2 +defined('ABSPATH') || die('Restricted Access');
2 3
3 4 function acym_replaceDateTags(string $value): string
4 5 {
5 6 $replace = ['{year}', '{month}', '{weekday}', '{day}'];
6 - $replaceBy = [date('Y'), date('m'), date('N'), date('d')];
7 + $replaceBy = [gmdate('Y'), gmdate('m'), gmdate('N'), gmdate('d')];
7 8 $value = str_replace($replace, $replaceBy, $value);
8 9
9 10 $results = [];
10 11 if (preg_match_all('#{(year|month|weekday|day)\|(add|remove):([^}]*)}#Uis', $value, $results)) {
@@ -10,9 +11,9 @@
10 11 if (preg_match_all('#{(year|month|weekday|day)\|(add|remove):([^}]*)}#Uis', $value, $results)) {
11 12 foreach ($results[0] as $i => $oneMatch) {
12 13 $format = str_replace(['year', 'month', 'weekday', 'day'], ['Y', 'm', 'N', 'd'], $results[1][$i]);
13 14 $delay = str_replace(['add', 'remove'], ['+', '-'], $results[2][$i]).intval($results[3][$i]).' '.str_replace('weekday', 'day', $results[1][$i]);
14 - $value = str_replace($oneMatch, date($format, strtotime($delay)), $value);
15 + $value = str_replace($oneMatch, gmdate($format, strtotime($delay)), $value);
15 16 }
16 17 }
17 18
18 19 return $value;
@@ -19,10 +20,12 @@
19 20 }
20 21
21 22 function acym_dateField(string $name, $value = '', string $class = '', string $attributes = '', string $relativeDefault = '-'): string
22 23 {
24 + // Open container
23 25 $result = '<div class="grid-x margin-y date_rs_selection_popup">';
24 26
27 + // Choice of relative / specific date
25 28 $result .= '<div class="cell grid-x">';
26 29 $result .= acym_switchFilter(
27 30 [
28 31 'relative' => acym_translation('ACYM_RELATIVE_DATE'),
@@ -33,8 +36,9 @@
33 36 'date_rs_selection'
34 37 );
35 38 $result .= '</div>';
36 39
40 + // Relative date options
37 41 $result .= '<div class="cell date_rs_selection_choice date_rs_selection_relative grid-x grid-margin-x align-center">
38 42 <div class="cell medium-4">
39 43 <input type="number" class="relativenumber" value="0">
40 44 </div>
@@ -64,12 +68,13 @@
64 68 );
65 69 $result .= '</div>
66 70 </div>';
67 71
72 + // Specific date option
68 73 $result .= '<div class="cell date_rs_selection_choice date_rs_selection_specific grid-x align-center acym_vcenter" style="display: none;">
69 74 <span class="cell shrink margin-right-1">'.acym_translation('ACYM_CHOOSE_DATE').'</span>
70 75 <div class="cell shrink">
71 - <input type="text" name="specific_'.acym_escape($name).'" class="acy_date_picker" data-acym-translate="0" readonly>
76 + <input type="datetime-local" name="specific_'.esc_attr($name).'" class="acy_date_picker">
72 77 </div>
73 78 </div>
74 79 <div class="cell grid-x grid-margin-x">
75 80 <div class="cell auto"></div>
@@ -77,10 +82,12 @@
77 82 <button type="button" class="cell medium-4 button acym__button__set__time" data-close>'.acym_translation('ACYM_APPLY').'</button>
78 83 <div class="cell auto"></div>
79 84 </div>';
80 85
86 + // Close container
81 87 $result .= '</div>';
82 88
89 + // Input in which the value is
83 90 $id = 'acym_'.preg_replace('#[^a-z0-9_]#i', '', $name);
84 91 if (is_numeric($value)) {
85 92 $months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
86 93
@@ -92,21 +99,27 @@
92 99 $shownValue = str_replace($months, $replaceValues, acym_date($value, 'd F Y H:i'));
93 100 } else {
94 101 $shownValue = $value;
95 102 }
96 - $result = '<input data-rs="'.acym_escape($id).'" type="hidden" name="'.acym_escape($name).'" value="'.acym_escape($value).'">'.acym_modal(
97 - '<input data-open="'.acym_escape($id).'" class="rs_date_field '.$class.'" '.$attributes.' type="text" value="'.acym_escape($shownValue).'" readonly>',
98 - $result,
99 - $id,
100 - [],
101 - [],
102 - false,
103 - false
104 - );
103 + $hiddenField = '<input data-rs="'.esc_attr($id).'" type="hidden" name="'.esc_attr($name).'" value="'.esc_attr($value).'">';
104 + ob_start();
105 + acym_modal(
106 + '<input data-open="'.esc_attr($id).'" class="rs_date_field '.esc_attr($class).'" '.$attributes.' type="text" value="'.esc_attr($shownValue).'" readonly>',
107 + $result,
108 + $id,
109 + [],
110 + [],
111 + false,
112 + false
113 + );
114 + $result = $hiddenField.ob_get_clean();
105 115
106 116 return $result;
107 117 }
108 118
119 +/**
120 + * Function to display the time based on the database value as int
121 + */
109 122 function acym_getDate($time = 0, string $format = '%d %B %Y %H:%M')
110 123 {
111 124 if (empty($time)) return '';
112 125
@@ -119,12 +132,13 @@
119 132 ['l', 'd', 'F', 'm', 'Y', 'y', 'H', 'i', 's', 'D', 'h', 'a', 'w'],
120 133 $format
121 134 );
122 135
136 + //Not sure why but sometimes it fails... so lets try to catch the error...
123 137 try {
124 138 return acym_date($time, $format, false);
125 139 } catch (Exception $e) {
126 - return date($format, $time);
140 + return gmdate($format, $time);
127 141 }
128 142 }
129 143
130 144 function acym_replaceDate(string $mydate, bool $display = false): string
@@ -227,9 +241,9 @@
227 241 $return[] = '<div class="medium-3 margin-left-0 margin-right-0 cell">'.acym_select(
228 242 $days,
229 243 $name,
230 244 empty($defaultDate[2]) || $defaultDate[2] === '00' ? '' : $defaultDate[2],
231 - $attributes,
245 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_DAY')]),
232 246 'value',
233 247 'text',
234 248 $name.'-'.$one
235 249 ).'</div>';
@@ -243,9 +257,9 @@
243 257 $return[] = '<div class="medium-5 cell">'.acym_select(
244 258 $month,
245 259 $name,
246 260 empty($defaultDate[1]) || $defaultDate[1] === '00' ? '' : $defaultDate[1],
247 - $attributes,
261 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_MONTH')]),
248 262 'value',
249 263 'text',
250 264 $name.'-'.$one
251 265 ).'</div>';
@@ -259,9 +273,9 @@
259 273 $return[] = '<div class="medium-4 margin-right-0 cell">'.acym_select(
260 274 $year,
261 275 $name,
262 276 empty($defaultDate[0]) || $defaultDate[0] === '0000' ? '' : $defaultDate[0],
263 - $attributes,
277 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_YEAR')]),
264 278 'value',
265 279 'text',
266 280 $name.'-'.$one
267 281 ).'</div>';
@@ -281,18 +295,23 @@
281 295 }
282 296
283 297 function acym_getTimeFromUTCDate(?string $date): int
284 298 {
299 + // Accept null/empty inputs gracefully and return 0 when no valid date is provided to avoid error.
285 300 if (empty($date)) {
286 301 return 0;
287 302 }
288 303
289 - $timestamp = strtotime($date);
304 + // Stored dates are UTC: parse them as UTC so the resulting timestamp is independent of the server timezone
305 + $timestamp = strtotime($date.' UTC');
290 306 if ($timestamp === false) {
307 + $timestamp = strtotime($date);
308 + }
309 + if ($timestamp === false) {
291 310 return 0;
292 311 }
293 312
294 - return $timestamp + date('Z');
313 + return $timestamp;
295 314 }
296 315
297 316 function acym_getTimeFromCMSDate($date)
298 317 {
@@ -303,16 +322,16 @@
303 322 {
304 323 return acym_getTimeFromCMSDate($date);
305 324 }
306 325
307 -function acym_date($time = 'now', $format = null, bool $useTz = true, bool $translate = true): string
326 +function acym_date($date = 'now', $format = null, bool $useTz = true, bool $translate = true): string
308 327 {
309 - if ($time === 'now') {
310 - $time = time();
328 + if ($date === 'now') {
329 + $date = time();
311 330 }
312 331
313 - if (is_numeric($time)) {
314 - $time = acym_dateTimeCMS($time);
332 + if (is_numeric($date)) {
333 + $date = acym_dateTimeCMS($date);
315 334 }
316 335
317 336 if (!$format || (strpos($format, 'ACYM_DATE_FORMAT') !== false && acym_translation($format) == $format)) {
318 337 $format = 'ACYM_DATE_FORMAT_LC1';
@@ -320,10 +339,11 @@
320 339 if (strpos($format, 'ACYM_DATE') !== false) {
321 340 $format = acym_translation($format);
322 341 }
323 342
343 + //Don't use timezone
324 344 if ($useTz === false) {
325 - $date = new DateTime($time);
345 + $date = new DateTime($date);
326 346
327 347 if ($translate) {
328 348 return acym_translateDate($date->format($format));
329 349 } else {
@@ -329,8 +349,9 @@
329 349 } else {
330 350 return $date->format($format);
331 351 }
332 352 } else {
353 + //We replace the . with : WordPress give format like UTC+5.45, but we want something like UTC+5:45
333 354 $cmsOffset = str_replace('.', ':', acym_getCMSConfig('offset'));
334 355
335 356 $timezone = new DateTimeZone($cmsOffset);
336 357
@@ -337,12 +358,13 @@
337 358 if (!is_numeric($cmsOffset)) {
338 359 $cmsOffset = $timezone->getOffset(new DateTime());
339 360 }
340 361
362 + // $date is a UTC date string: apply the CMS timezone offset then format in UTC so the server timezone never shifts the displayed result
341 363 if ($translate) {
342 - return acym_translateDate(date($format, strtotime($time) + $cmsOffset));
364 + return acym_translateDate(gmdate($format, strtotime($date.' UTC') + $cmsOffset));
343 365 } else {
344 - return date($format, strtotime($time) + $cmsOffset);
366 + return gmdate($format, strtotime($date.' UTC') + $cmsOffset);
345 367 }
346 368 }
347 369 }
348 370