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 +72 -36 10.1.4 → 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,16 +132,17 @@
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 -function acym_replaceDate($mydate, $display = false)
144 +function acym_replaceDate(string $mydate, bool $display = false): string
131 145 {
132 146 if (strpos($mydate, '[time]') === false) {
133 147 if (is_numeric($mydate) && $display) {
134 148 return acym_date($mydate, 'Y-m-d H:i:s');
@@ -136,9 +150,11 @@
136 150
137 151 return $mydate;
138 152 }
139 153
140 - if ($mydate == '[time]' && $display) return acym_translation('ACYM_NOW');
154 + if ($mydate === '[time]' && $display) {
155 + return acym_translation('ACYM_NOW');
156 + }
141 157
142 158 $mydate = str_replace('[time]', time(), $mydate);
143 159 $operators = ['+', '-'];
144 160 foreach ($operators as $oneOperator) {
@@ -186,9 +202,9 @@
186 202
187 203 $days = [
188 204 '' => acym_translation('ACYM_DAY'),
189 205 ];
190 - for ($i = 1 ; $i <= 31 ; $i++) {
206 + for ($i = 1; $i <= 31; $i++) {
191 207 $days[$i < 10 ? '0'.$i : $i] = $i < 10 ? '0'.$i : $i;
192 208 }
193 209
194 210 $month = [
@@ -209,9 +225,10 @@
209 225
210 226 $year = [
211 227 '' => acym_translation('ACYM_YEAR'),
212 228 ];
213 - for ($i = 1900 ; $i <= (acym_date('now', 'Y') + 10) ; $i++) {
229 + $currentYear = (int)acym_date('now', 'Y');
230 + for ($i = 1900; $i <= $currentYear + 10; $i++) {
214 231 $year[$i] = $i;
215 232 }
216 233
217 234 $formatToDisplay = explode('%', $format);
@@ -220,13 +237,13 @@
220 237 unset($formatToDisplay[0]);
221 238 foreach ($formatToDisplay as $one) {
222 239 if ($one === 'd') {
223 240 if ($returnHtml) {
224 - $return[] = '<div class="medium-3 margin-left-0 cell">'.acym_select(
241 + $return[] = '<div class="medium-3 margin-left-0 margin-right-0 cell">'.acym_select(
225 242 $days,
226 243 $name,
227 244 empty($defaultDate[2]) || $defaultDate[2] === '00' ? '' : $defaultDate[2],
228 - $attributes,
245 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_DAY')]),
229 246 'value',
230 247 'text',
231 248 $name.'-'.$one
232 249 ).'</div>';
@@ -240,9 +257,9 @@
240 257 $return[] = '<div class="medium-5 cell">'.acym_select(
241 258 $month,
242 259 $name,
243 260 empty($defaultDate[1]) || $defaultDate[1] === '00' ? '' : $defaultDate[1],
244 - $attributes,
261 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_MONTH')]),
245 262 'value',
246 263 'text',
247 264 $name.'-'.$one
248 265 ).'</div>';
@@ -256,9 +273,9 @@
256 273 $return[] = '<div class="medium-4 margin-right-0 cell">'.acym_select(
257 274 $year,
258 275 $name,
259 276 empty($defaultDate[0]) || $defaultDate[0] === '0000' ? '' : $defaultDate[0],
260 - $attributes,
277 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_YEAR')]),
261 278 'value',
262 279 'text',
263 280 $name.'-'.$one
264 281 ).'</div>';
@@ -276,11 +293,25 @@
276 293 return implode(' ', $return);
277 294 }
278 295 }
279 296
280 -function acym_getTimeFromUTCDate($date)
297 +function acym_getTimeFromUTCDate(?string $date): int
281 298 {
282 - return strtotime($date) + date('Z');
299 + // Accept null/empty inputs gracefully and return 0 when no valid date is provided to avoid error.
300 + if (empty($date)) {
301 + return 0;
302 + }
303 +
304 + // Stored dates are UTC: parse them as UTC so the resulting timestamp is independent of the server timezone
305 + $timestamp = strtotime($date.' UTC');
306 + if ($timestamp === false) {
307 + $timestamp = strtotime($date);
308 + }
309 + if ($timestamp === false) {
310 + return 0;
311 + }
312 +
313 + return $timestamp;
283 314 }
284 315
285 316 function acym_getTimeFromCMSDate($date)
286 317 {
@@ -291,25 +322,28 @@
291 322 {
292 323 return acym_getTimeFromCMSDate($date);
293 324 }
294 325
295 -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
296 327 {
297 - if ($time === 'now') {
298 - $time = time();
328 + if ($date === 'now') {
329 + $date = time();
299 330 }
300 331
301 - if (is_numeric($time)) {
302 - $time = acym_dateTimeCMS((int)$time);
332 + if (is_numeric($date)) {
333 + $date = acym_dateTimeCMS($date);
303 334 }
304 335
305 336 if (!$format || (strpos($format, 'ACYM_DATE_FORMAT') !== false && acym_translation($format) == $format)) {
306 337 $format = 'ACYM_DATE_FORMAT_LC1';
307 338 }
308 - if (strpos($format, 'ACYM_DATE') !== false) $format = acym_translation($format);
339 + if (strpos($format, 'ACYM_DATE') !== false) {
340 + $format = acym_translation($format);
341 + }
309 342
343 + //Don't use timezone
310 344 if ($useTz === false) {
311 - $date = new DateTime($time);
345 + $date = new DateTime($date);
312 346
313 347 if ($translate) {
314 348 return acym_translateDate($date->format($format));
315 349 } else {
@@ -315,20 +349,22 @@
315 349 } else {
316 350 return $date->format($format);
317 351 }
318 352 } else {
353 + //We replace the . with : WordPress give format like UTC+5.45, but we want something like UTC+5:45
319 354 $cmsOffset = str_replace('.', ':', acym_getCMSConfig('offset'));
320 355
321 356 $timezone = new DateTimeZone($cmsOffset);
322 357
323 358 if (!is_numeric($cmsOffset)) {
324 - $cmsOffset = $timezone->getOffset(new DateTime);
359 + $cmsOffset = $timezone->getOffset(new DateTime());
325 360 }
326 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
327 363 if ($translate) {
328 - return acym_translateDate(date($format, strtotime($time) + $cmsOffset));
364 + return acym_translateDate(gmdate($format, strtotime($date.' UTC') + $cmsOffset));
329 365 } else {
330 - return date($format, strtotime($time) + $cmsOffset);
366 + return gmdate($format, strtotime($date.' UTC') + $cmsOffset);
331 367 }
332 368 }
333 369 }
334 370
@@ -357,14 +393,14 @@
357 393 ];
358 394
359 395 foreach ($map as $english => $translationKey) {
360 396 $translation = acym_translation($translationKey);
361 - if ($translation == $translationKey) {
397 + if ($translation === $translationKey) {
362 398 continue;
363 399 }
364 400
365 - $date = preg_replace('#'.preg_quote($english).'( |,|$)#i', $translation.'$1', $date);
366 - $date = preg_replace('#'.preg_quote(substr($english, 0, 3)).'( |,|$)#i', mb_substr($translation, 0, 3).'$1', $date);
401 + $date = preg_replace('#'.preg_quote($english).'#i', $translation, $date);
402 + $date = preg_replace('#'.preg_quote(substr($english, 0, 3)).'#i', mb_substr($translation, 0, 3), $date);
367 403 }
368 404
369 405 return $date;
370 406 }