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 +104 -56 10.0.1 → 11.1.0 View file →
@@ -1,10 +1,11 @@
1 1 <?php
2 +defined('ABSPATH') || die('Restricted Access');
2 3
3 -function acym_replaceDateTags($value)
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;
@@ -17,12 +18,14 @@
17 18
18 19 return $value;
19 20 }
20 21
21 -function acym_dateField($name, $value = '', $class = '', $attributes = '', $relativeDefault = '-')
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,22 +99,28 @@
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
109 -function acym_getDate($time = 0, $format = '%d %B %Y %H:%M')
119 +/**
120 + * Function to display the time based on the database value as int
121 + */
122 +function acym_getDate($time = 0, string $format = '%d %B %Y %H:%M')
110 123 {
111 124 if (empty($time)) return '';
112 125
113 126 if (is_numeric($format)) {
@@ -119,24 +132,29 @@
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 - if (is_numeric($mydate) && $display) return acym_date($mydate, 'Y-m-d H:i:s');
147 + if (is_numeric($mydate) && $display) {
148 + return acym_date($mydate, 'Y-m-d H:i:s');
149 + }
134 150
135 151 return $mydate;
136 152 }
137 153
138 - if ($mydate == '[time]' && $display) return acym_translation('ACYM_NOW');
154 + if ($mydate === '[time]' && $display) {
155 + return acym_translation('ACYM_NOW');
156 + }
139 157
140 158 $mydate = str_replace('[time]', time(), $mydate);
141 159 $operators = ['+', '-'];
142 160 foreach ($operators as $oneOperator) {
@@ -160,9 +178,9 @@
160 178
161 179 return $mydate;
162 180 }
163 181
164 -function acym_secondsToTime($seconds)
182 +function acym_secondsToTime(int $seconds): string
165 183 {
166 184 $dtF = new \DateTime('@0');
167 185 $dtT = new \DateTime("@$seconds");
168 186
@@ -168,9 +186,9 @@
168 186
169 187 return $dtF->diff($dtT)->format('%a day(s) %h h, %i min');
170 188 }
171 189
172 -function acym_displayDateFormat($format, $name = 'date', $default = '', $attributes = [], $inputMode = true)
190 +function acym_displayDateFormat(string $format, string $name = 'date', string $default = '', array $attributes = [], bool $returnHtml = true): string
173 191 {
174 192 if (empty($attributes)) {
175 193 $attributes = [
176 194 'class' => 'acym__custom__fields__select__form acym__select',
@@ -177,13 +195,19 @@
177 195 ];
178 196 }
179 197
180 198 $return = [];
181 - if ($inputMode) $return[] = '<div class="cell grid-x grid-margin-x">';
182 - $days = ['' => acym_translation('ACYM_DAY')];
183 - for ($i = 1 ; $i <= 31 ; $i++) {
199 + if ($returnHtml) {
200 + $return[] = '<div class="cell grid-x grid-margin-x">';
201 + }
202 +
203 + $days = [
204 + '' => acym_translation('ACYM_DAY'),
205 + ];
206 + for ($i = 1; $i <= 31; $i++) {
184 207 $days[$i < 10 ? '0'.$i : $i] = $i < 10 ? '0'.$i : $i;
185 208 }
209 +
186 210 $month = [
187 211 '' => acym_translation('ACYM_MONTH'),
188 212 '01' => acym_translation('ACYM_JANUARY'),
189 213 '02' => acym_translation('ACYM_FEBRUARY'),
@@ -197,25 +221,29 @@
197 221 '10' => acym_translation('ACYM_OCTOBER'),
198 222 '11' => acym_translation('ACYM_NOVEMBER'),
199 223 '12' => acym_translation('ACYM_DECEMBER'),
200 224 ];
201 - $year = ['' => acym_translation('ACYM_YEAR')];
202 - for ($i = 1900 ; $i <= (acym_date('now', 'Y') + 10) ; $i++) {
225 +
226 + $year = [
227 + '' => acym_translation('ACYM_YEAR'),
228 + ];
229 + $currentYear = (int)acym_date('now', 'Y');
230 + for ($i = 1900; $i <= $currentYear + 10; $i++) {
203 231 $year[$i] = $i;
204 232 }
233 +
205 234 $formatToDisplay = explode('%', $format);
206 235 $defaultDate = empty($default) ? [] : explode('-', $default);
207 236
208 - $i = 0;
209 237 unset($formatToDisplay[0]);
210 238 foreach ($formatToDisplay as $one) {
211 - if ($one == 'd') {
212 - if ($inputMode) {
213 - $return[] = '<div class="medium-3 margin-left-0 cell">'.acym_select(
239 + if ($one === 'd') {
240 + if ($returnHtml) {
241 + $return[] = '<div class="medium-3 margin-left-0 margin-right-0 cell">'.acym_select(
214 242 $days,
215 243 $name,
216 244 empty($defaultDate[2]) || $defaultDate[2] === '00' ? '' : $defaultDate[2],
217 - $attributes,
245 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_DAY')]),
218 246 'value',
219 247 'text',
220 248 $name.'-'.$one
221 249 ).'</div>';
@@ -222,15 +250,16 @@
222 250 } elseif (!empty($defaultDate[2]) && $defaultDate[2] !== '00') {
223 251 $return[] = $defaultDate[2];
224 252 }
225 253 }
226 - if ($one == 'm') {
227 - if ($inputMode) {
254 +
255 + if ($one === 'm') {
256 + if ($returnHtml) {
228 257 $return[] = '<div class="medium-5 cell">'.acym_select(
229 258 $month,
230 259 $name,
231 260 empty($defaultDate[1]) || $defaultDate[1] === '00' ? '' : $defaultDate[1],
232 - $attributes,
261 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_MONTH')]),
233 262 'value',
234 263 'text',
235 264 $name.'-'.$one
236 265 ).'</div>';
@@ -237,15 +266,16 @@
237 266 } elseif (!empty($defaultDate[1]) && $defaultDate[1] !== '00') {
238 267 $return[] = $month[$defaultDate[1]];
239 268 }
240 269 }
241 - if ($one == 'y') {
242 - if ($inputMode) {
270 +
271 + if ($one === 'y') {
272 + if ($returnHtml) {
243 273 $return[] = '<div class="medium-4 margin-right-0 cell">'.acym_select(
244 274 $year,
245 275 $name,
246 276 empty($defaultDate[0]) || $defaultDate[0] === '0000' ? '' : $defaultDate[0],
247 - $attributes,
277 + array_merge($attributes, ['aria-label' => acym_translation('ACYM_YEAR')]),
248 278 'value',
249 279 'text',
250 280 $name.'-'.$one
251 281 ).'</div>';
@@ -252,12 +282,11 @@
252 282 } elseif (!empty($defaultDate[0]) && $defaultDate[0] !== '0000') {
253 283 $return[] = $defaultDate[0];
254 284 }
255 285 }
256 - $i++;
257 286 }
258 287
259 - if ($inputMode) {
288 + if ($returnHtml) {
260 289 $return[] = '</div>';
261 290
262 291 return implode('', $return);
263 292 } else {
@@ -264,11 +293,25 @@
264 293 return implode(' ', $return);
265 294 }
266 295 }
267 296
268 -function acym_getTimeFromUTCDate($date)
297 +function acym_getTimeFromUTCDate(?string $date): int
269 298 {
270 - 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;
271 314 }
272 315
273 316 function acym_getTimeFromCMSDate($date)
274 317 {
@@ -279,25 +322,28 @@
279 322 {
280 323 return acym_getTimeFromCMSDate($date);
281 324 }
282 325
283 -function acym_date($time = 'now', $format = null, $useTz = true, $translate = true)
326 +function acym_date($date = 'now', $format = null, bool $useTz = true, bool $translate = true): string
284 327 {
285 - if ($time === 'now') {
286 - $time = time();
328 + if ($date === 'now') {
329 + $date = time();
287 330 }
288 331
289 - if (is_numeric($time)) {
290 - $time = acym_dateTimeCMS((int)$time);
332 + if (is_numeric($date)) {
333 + $date = acym_dateTimeCMS($date);
291 334 }
292 335
293 336 if (!$format || (strpos($format, 'ACYM_DATE_FORMAT') !== false && acym_translation($format) == $format)) {
294 337 $format = 'ACYM_DATE_FORMAT_LC1';
295 338 }
296 - if (strpos($format, 'ACYM_DATE') !== false) $format = acym_translation($format);
339 + if (strpos($format, 'ACYM_DATE') !== false) {
340 + $format = acym_translation($format);
341 + }
297 342
343 + //Don't use timezone
298 344 if ($useTz === false) {
299 - $date = new DateTime($time);
345 + $date = new DateTime($date);
300 346
301 347 if ($translate) {
302 348 return acym_translateDate($date->format($format));
303 349 } else {
@@ -303,25 +349,27 @@
303 349 } else {
304 350 return $date->format($format);
305 351 }
306 352 } else {
353 + //We replace the . with : WordPress give format like UTC+5.45, but we want something like UTC+5:45
307 354 $cmsOffset = str_replace('.', ':', acym_getCMSConfig('offset'));
308 355
309 356 $timezone = new DateTimeZone($cmsOffset);
310 357
311 358 if (!is_numeric($cmsOffset)) {
312 - $cmsOffset = $timezone->getOffset(new DateTime);
359 + $cmsOffset = $timezone->getOffset(new DateTime());
313 360 }
314 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
315 363 if ($translate) {
316 - return acym_translateDate(date($format, strtotime($time) + $cmsOffset));
364 + return acym_translateDate(gmdate($format, strtotime($date.' UTC') + $cmsOffset));
317 365 } else {
318 - return date($format, strtotime($time) + $cmsOffset);
366 + return gmdate($format, strtotime($date.' UTC') + $cmsOffset);
319 367 }
320 368 }
321 369 }
322 370
323 -function acym_translateDate($date)
371 +function acym_translateDate(string $date): string
324 372 {
325 373 $map = [
326 374 'January' => 'ACYM_JANUARY',
327 375 'February' => 'ACYM_FEBRUARY',
@@ -345,19 +393,19 @@
345 393 ];
346 394
347 395 foreach ($map as $english => $translationKey) {
348 396 $translation = acym_translation($translationKey);
349 - if ($translation == $translationKey) {
397 + if ($translation === $translationKey) {
350 398 continue;
351 399 }
352 400
353 - $date = preg_replace('#'.preg_quote($english).'( |,|$)#i', $translation.'$1', $date);
354 - $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);
355 403 }
356 404
357 405 return $date;
358 406 }
359 407
360 -function acym_isDateValid($date)
408 +function acym_isDateValid($date): bool
361 409 {
362 410 return $date !== '0000-00-00 00:00:00' && !empty($date);
363 411 }