@@ -5,81 +5,81 @@ |
||
5 | 5 | class EE_Two_Column_Layout extends EE_Form_Section_Layout_Base |
6 | 6 | { |
7 | 7 | |
8 | - /** |
|
9 | - * Should be used to start teh form section (Eg a table tag, or a div tag, etc.) |
|
10 | - * |
|
11 | - * @param array $additional_args |
|
12 | - * @return string |
|
13 | - */ |
|
14 | - public function layout_form_begin($additional_args = array()) |
|
15 | - { |
|
16 | - return $this->display_form_wide_errors() |
|
17 | - . EEH_HTML::table( |
|
18 | - '', |
|
19 | - $this->_form_section->html_id(), |
|
20 | - $this->_form_section->html_class(), |
|
21 | - $this->_form_section->html_style() |
|
22 | - ) . EEH_HTML::tbody(); |
|
23 | - } |
|
8 | + /** |
|
9 | + * Should be used to start teh form section (Eg a table tag, or a div tag, etc.) |
|
10 | + * |
|
11 | + * @param array $additional_args |
|
12 | + * @return string |
|
13 | + */ |
|
14 | + public function layout_form_begin($additional_args = array()) |
|
15 | + { |
|
16 | + return $this->display_form_wide_errors() |
|
17 | + . EEH_HTML::table( |
|
18 | + '', |
|
19 | + $this->_form_section->html_id(), |
|
20 | + $this->_form_section->html_class(), |
|
21 | + $this->_form_section->html_style() |
|
22 | + ) . EEH_HTML::tbody(); |
|
23 | + } |
|
24 | 24 | |
25 | 25 | |
26 | 26 | |
27 | - /** |
|
28 | - * Should be used to end the form section (eg a /table tag, or a /div tag, etc) |
|
29 | - * |
|
30 | - * @param array $additional_args |
|
31 | - * @return string |
|
32 | - */ |
|
33 | - public function layout_form_end($additional_args = array()) |
|
34 | - { |
|
35 | - return EEH_HTML::tbodyx() . EEH_HTML::tablex($this->_form_section->html_id()); |
|
36 | - } |
|
27 | + /** |
|
28 | + * Should be used to end the form section (eg a /table tag, or a /div tag, etc) |
|
29 | + * |
|
30 | + * @param array $additional_args |
|
31 | + * @return string |
|
32 | + */ |
|
33 | + public function layout_form_end($additional_args = array()) |
|
34 | + { |
|
35 | + return EEH_HTML::tbodyx() . EEH_HTML::tablex($this->_form_section->html_id()); |
|
36 | + } |
|
37 | 37 | |
38 | 38 | |
39 | 39 | |
40 | - /** |
|
41 | - * Lays out the row for the input, including label and errors |
|
42 | - * |
|
43 | - * @param EE_Form_Input_Base $input |
|
44 | - * @return string |
|
45 | - */ |
|
46 | - public function layout_input($input) |
|
47 | - { |
|
48 | - $html = ''; |
|
49 | - if ($input instanceof EE_Hidden_Input) { |
|
50 | - $html .= $input->get_html_for_input(); |
|
51 | - } else { |
|
52 | - $html_for_input = $input->get_html_for_input(); |
|
53 | - $html_for_input .= $input->get_html_for_errors() != '' |
|
54 | - ? EEH_HTML::nl() . $input->get_html_for_errors() |
|
55 | - : ''; |
|
56 | - $html_for_input .= $input->get_html_for_help() != '' ? EEH_HTML::nl() . $input->get_html_for_help() : ''; |
|
57 | - $html .= EEH_HTML::tr( |
|
58 | - EEH_HTML::th($input->get_html_for_label()) . |
|
59 | - EEH_HTML::td($html_for_input) |
|
60 | - ); |
|
61 | - } |
|
62 | - return $html; |
|
63 | - } |
|
40 | + /** |
|
41 | + * Lays out the row for the input, including label and errors |
|
42 | + * |
|
43 | + * @param EE_Form_Input_Base $input |
|
44 | + * @return string |
|
45 | + */ |
|
46 | + public function layout_input($input) |
|
47 | + { |
|
48 | + $html = ''; |
|
49 | + if ($input instanceof EE_Hidden_Input) { |
|
50 | + $html .= $input->get_html_for_input(); |
|
51 | + } else { |
|
52 | + $html_for_input = $input->get_html_for_input(); |
|
53 | + $html_for_input .= $input->get_html_for_errors() != '' |
|
54 | + ? EEH_HTML::nl() . $input->get_html_for_errors() |
|
55 | + : ''; |
|
56 | + $html_for_input .= $input->get_html_for_help() != '' ? EEH_HTML::nl() . $input->get_html_for_help() : ''; |
|
57 | + $html .= EEH_HTML::tr( |
|
58 | + EEH_HTML::th($input->get_html_for_label()) . |
|
59 | + EEH_HTML::td($html_for_input) |
|
60 | + ); |
|
61 | + } |
|
62 | + return $html; |
|
63 | + } |
|
64 | 64 | |
65 | 65 | |
66 | 66 | |
67 | - /** |
|
68 | - * Lays out a row for the subsection |
|
69 | - * |
|
70 | - * @param EE_Form_Section_Proper $form_section |
|
71 | - * @return string |
|
72 | - */ |
|
73 | - public function layout_subsection($form_section) |
|
74 | - { |
|
75 | - $html = ''; |
|
76 | - if ($form_section instanceof EE_Form_Section_HTML) { |
|
77 | - $html .= $form_section->get_html(); |
|
78 | - } else { |
|
79 | - $html .= EEH_HTML::tr( |
|
80 | - EEH_HTML::td($form_section->get_html(), '', '', '', 'colspan="2"') |
|
81 | - ); |
|
82 | - } |
|
83 | - return $html; |
|
84 | - } |
|
67 | + /** |
|
68 | + * Lays out a row for the subsection |
|
69 | + * |
|
70 | + * @param EE_Form_Section_Proper $form_section |
|
71 | + * @return string |
|
72 | + */ |
|
73 | + public function layout_subsection($form_section) |
|
74 | + { |
|
75 | + $html = ''; |
|
76 | + if ($form_section instanceof EE_Form_Section_HTML) { |
|
77 | + $html .= $form_section->get_html(); |
|
78 | + } else { |
|
79 | + $html .= EEH_HTML::tr( |
|
80 | + EEH_HTML::td($form_section->get_html(), '', '', '', 'colspan="2"') |
|
81 | + ); |
|
82 | + } |
|
83 | + return $html; |
|
84 | + } |
|
85 | 85 | } |
@@ -327,7 +327,7 @@ discard block |
||
327 | 327 | /** |
328 | 328 | * Get Timezone Transitions |
329 | 329 | * @param \DateTimeZone $date_time_zone |
330 | - * @param null $time |
|
330 | + * @param integer|null $time |
|
331 | 331 | * @param bool $first_only |
332 | 332 | * @return array|mixed |
333 | 333 | */ |
@@ -343,7 +343,7 @@ discard block |
||
343 | 343 | /** |
344 | 344 | * Get Timezone Offset for given timezone object. |
345 | 345 | * @param \DateTimeZone $date_time_zone |
346 | - * @param null $time |
|
346 | + * @param integer|null $time |
|
347 | 347 | * @return mixed |
348 | 348 | * @throws \DomainException |
349 | 349 | */ |
@@ -1075,7 +1075,7 @@ discard block |
||
1075 | 1075 | * this method will add that "1" into your date regardless of the format. |
1076 | 1076 | * |
1077 | 1077 | * @param string $month |
1078 | - * @return string |
|
1078 | + * @return integer |
|
1079 | 1079 | */ |
1080 | 1080 | public static function first_of_month_timestamp($month = '') |
1081 | 1081 | { |
@@ -1227,7 +1227,7 @@ discard block |
||
1227 | 1227 | /** |
1228 | 1228 | * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0 |
1229 | 1229 | * |
1230 | - * @param int|WP_User $user_id |
|
1230 | + * @param integer $user_id |
|
1231 | 1231 | * @return string |
1232 | 1232 | */ |
1233 | 1233 | public static function get_user_locale($user_id = 0) |
@@ -1,6 +1,6 @@ discard block |
||
1 | 1 | <?php |
2 | 2 | if (! defined('EVENT_ESPRESSO_VERSION')) { |
3 | - exit('NO direct script access allowed'); |
|
3 | + exit('NO direct script access allowed'); |
|
4 | 4 | } |
5 | 5 | |
6 | 6 | /** |
@@ -26,364 +26,364 @@ discard block |
||
26 | 26 | { |
27 | 27 | |
28 | 28 | |
29 | - /** |
|
30 | - * return the timezone set for the WP install |
|
31 | - * |
|
32 | - * @return string valid timezone string for PHP DateTimeZone() class |
|
33 | - */ |
|
34 | - public static function get_timezone() |
|
35 | - { |
|
36 | - return EEH_DTT_Helper::get_valid_timezone_string(); |
|
37 | - } |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * get_valid_timezone_string |
|
42 | - * ensures that a valid timezone string is returned |
|
43 | - * |
|
44 | - * @access protected |
|
45 | - * @param string $timezone_string |
|
46 | - * @return string |
|
47 | - * @throws \EE_Error |
|
48 | - */ |
|
49 | - public static function get_valid_timezone_string($timezone_string = '') |
|
50 | - { |
|
51 | - // if passed a value, then use that, else get WP option |
|
52 | - $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string'); |
|
53 | - // value from above exists, use that, else get timezone string from gmt_offset |
|
54 | - $timezone_string = ! empty($timezone_string) ? $timezone_string : EEH_DTT_Helper::get_timezone_string_from_gmt_offset(); |
|
55 | - EEH_DTT_Helper::validate_timezone($timezone_string); |
|
56 | - return $timezone_string; |
|
57 | - } |
|
58 | - |
|
59 | - |
|
60 | - /** |
|
61 | - * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone. |
|
62 | - * |
|
63 | - * @static |
|
64 | - * @access public |
|
65 | - * @param string $timezone_string Timezone string to check |
|
66 | - * @param bool $throw_error |
|
67 | - * @return bool |
|
68 | - * @throws \EE_Error |
|
69 | - */ |
|
70 | - public static function validate_timezone($timezone_string, $throw_error = true) |
|
71 | - { |
|
72 | - // easiest way to test a timezone string is just see if it throws an error when you try to create a DateTimeZone object with it |
|
73 | - try { |
|
74 | - new DateTimeZone($timezone_string); |
|
75 | - } catch (Exception $e) { |
|
76 | - // sometimes we take exception to exceptions |
|
77 | - if (! $throw_error) { |
|
78 | - return false; |
|
79 | - } |
|
80 | - throw new EE_Error( |
|
81 | - sprintf( |
|
82 | - __('The timezone given (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used', |
|
83 | - 'event_espresso'), |
|
84 | - $timezone_string, |
|
85 | - '<a href="http://www.php.net/manual/en/timezones.php">', |
|
86 | - '</a>' |
|
87 | - ) |
|
88 | - ); |
|
89 | - } |
|
90 | - return true; |
|
91 | - } |
|
92 | - |
|
93 | - |
|
94 | - /** |
|
95 | - * _create_timezone_object_from_timezone_name |
|
96 | - * |
|
97 | - * @access protected |
|
98 | - * @param string $gmt_offset |
|
99 | - * @return string |
|
100 | - */ |
|
101 | - public static function get_timezone_string_from_gmt_offset($gmt_offset = '') |
|
102 | - { |
|
103 | - $timezone_string = 'UTC'; |
|
104 | - //if there is no incoming gmt_offset, then because WP hooks in on timezone_string, we need to see if that is |
|
105 | - //set because it will override `gmt_offset` via `pre_get_option` filter. If that's set, then let's just use |
|
106 | - //that! Otherwise we'll leave timezone_string at the default of 'UTC' before doing other logic. |
|
107 | - if ($gmt_offset === '') { |
|
108 | - //autoloaded so no need to set to a variable. There will not be multiple hits to the db. |
|
109 | - if (get_option('timezone_string')) { |
|
110 | - return get_option('timezone_string'); |
|
111 | - } |
|
112 | - } |
|
113 | - $gmt_offset = $gmt_offset !== '' ? $gmt_offset : get_option('gmt_offset'); |
|
114 | - $gmt_offset = (float) $gmt_offset; |
|
115 | - |
|
116 | - //if $gmt_offset is 0, then just return UTC |
|
117 | - if ($gmt_offset === (float) 0) { |
|
118 | - return $timezone_string; |
|
119 | - } |
|
120 | - |
|
121 | - |
|
122 | - if ($gmt_offset !== '') { |
|
123 | - // convert GMT offset to seconds |
|
124 | - $gmt_offset = $gmt_offset * HOUR_IN_SECONDS; |
|
125 | - // although we don't know the TZ abbreviation, we know the UTC offset |
|
126 | - $timezone_string = timezone_name_from_abbr(null, $gmt_offset); |
|
127 | - //only use this timezone_string IF it's current offset matches the given offset |
|
128 | - try { |
|
129 | - $offset = self::get_timezone_offset(new DateTimeZone($timezone_string)); |
|
130 | - if ($offset !== $gmt_offset) { |
|
131 | - $timezone_string = false; |
|
132 | - } |
|
133 | - } catch (Exception $e) { |
|
134 | - $timezone_string = false; |
|
135 | - } |
|
136 | - } |
|
137 | - // better have a valid timezone string by now, but if not, sigh... loop thru the timezone_abbreviations_list()... |
|
138 | - $timezone_string = $timezone_string !== false |
|
139 | - ? $timezone_string |
|
140 | - : EEH_DTT_Helper::get_timezone_string_from_abbreviations_list($gmt_offset); |
|
141 | - return $timezone_string; |
|
142 | - } |
|
143 | - |
|
144 | - /** |
|
145 | - * Gets the site's GMT offset based on either the timezone string |
|
146 | - * (in which case teh gmt offset will vary depending on the location's |
|
147 | - * observance of daylight savings time) or the gmt_offset wp option |
|
148 | - * |
|
149 | - * @return int seconds offset |
|
150 | - */ |
|
151 | - public static function get_site_timezone_gmt_offset() |
|
152 | - { |
|
153 | - $timezone_string = get_option('timezone_string'); |
|
154 | - if ($timezone_string) { |
|
155 | - try { |
|
156 | - $timezone = new DateTimeZone($timezone_string); |
|
157 | - return $timezone->getOffset(new DateTime()); //in WordPress DateTime defaults to UTC |
|
158 | - } catch (Exception $e) { |
|
159 | - } |
|
160 | - } |
|
161 | - $offset = get_option('gmt_offset'); |
|
162 | - return (int)($offset * HOUR_IN_SECONDS); |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - /** |
|
167 | - * Depending on PHP version, there might not bevalid current timezone strings to match these gmt_offsets in its |
|
168 | - * timezone tables. |
|
169 | - * To get around that, for these fringe timezones we bump them to a known valid offset. |
|
170 | - * |
|
171 | - * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset. |
|
172 | - * |
|
173 | - * @access public |
|
174 | - * @param int $gmt_offset |
|
175 | - * @return int |
|
176 | - */ |
|
177 | - public static function adjust_invalid_gmt_offsets($gmt_offset = 0) |
|
178 | - { |
|
179 | - //make sure $gmt_offset is int |
|
180 | - $gmt_offset = (int)$gmt_offset; |
|
181 | - switch ($gmt_offset) { |
|
182 | - //-12 |
|
183 | - case -43200: |
|
184 | - $gmt_offset = -39600; |
|
185 | - break; |
|
186 | - //-11.5 |
|
187 | - case -41400: |
|
188 | - $gmt_offset = -39600; |
|
189 | - break; |
|
190 | - //-10.5 |
|
191 | - case -37800: |
|
192 | - $gmt_offset = -39600; |
|
193 | - break; |
|
194 | - //-8.5 |
|
195 | - case -30600: |
|
196 | - $gmt_offset = -28800; |
|
197 | - break; |
|
198 | - //-7.5 |
|
199 | - case -27000: |
|
200 | - $gmt_offset = -25200; |
|
201 | - break; |
|
202 | - //-6.5 |
|
203 | - case -23400: |
|
204 | - $gmt_offset = -21600; |
|
205 | - break; |
|
206 | - //-5.5 |
|
207 | - case -19800: |
|
208 | - $gmt_offset = -18000; |
|
209 | - break; |
|
210 | - //-4.5 |
|
211 | - case -16200: |
|
212 | - $gmt_offset = -14400; |
|
213 | - break; |
|
214 | - //-3.5 |
|
215 | - case -12600: |
|
216 | - $gmt_offset = -10800; |
|
217 | - break; |
|
218 | - //-2.5 |
|
219 | - case -9000: |
|
220 | - $gmt_offset = -7200; |
|
221 | - break; |
|
222 | - //-1.5 |
|
223 | - case -5400: |
|
224 | - $gmt_offset = -3600; |
|
225 | - break; |
|
226 | - //-0.5 |
|
227 | - case -1800: |
|
228 | - $gmt_offset = 0; |
|
229 | - break; |
|
230 | - //.5 |
|
231 | - case 1800: |
|
232 | - $gmt_offset = 3600; |
|
233 | - break; |
|
234 | - //1.5 |
|
235 | - case 5400: |
|
236 | - $gmt_offset = 7200; |
|
237 | - break; |
|
238 | - //2.5 |
|
239 | - case 9000: |
|
240 | - $gmt_offset = 10800; |
|
241 | - break; |
|
242 | - //3.5 |
|
243 | - case 12600: |
|
244 | - $gmt_offset = 14400; |
|
245 | - break; |
|
246 | - |
|
247 | - //7.5 |
|
248 | - case 27000: |
|
249 | - $gmt_offset = 28800; |
|
250 | - break; |
|
251 | - //8.5 |
|
252 | - case 30600: |
|
253 | - $gmt_offset = 31500; |
|
254 | - break; |
|
255 | - //10.5 |
|
256 | - case 37800: |
|
257 | - $gmt_offset = 39600; |
|
258 | - break; |
|
259 | - //11.5 |
|
260 | - case 41400: |
|
261 | - $gmt_offset = 43200; |
|
262 | - break; |
|
263 | - //12.75 |
|
264 | - case 45900: |
|
265 | - $gmt_offset = 46800; |
|
266 | - break; |
|
267 | - //13.75 |
|
268 | - case 49500: |
|
269 | - $gmt_offset = 50400; |
|
270 | - break; |
|
271 | - } |
|
272 | - return $gmt_offset; |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - /** |
|
277 | - * get_timezone_string_from_abbreviations_list |
|
278 | - * |
|
279 | - * @access public |
|
280 | - * @param int $gmt_offset |
|
281 | - * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset. |
|
282 | - * @return string |
|
283 | - * @throws \EE_Error |
|
284 | - */ |
|
285 | - public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true) |
|
286 | - { |
|
287 | - $abbreviations = timezone_abbreviations_list(); |
|
288 | - foreach ($abbreviations as $abbreviation) { |
|
289 | - foreach ($abbreviation as $city) { |
|
290 | - if ($city['offset'] === $gmt_offset && $city['dst'] === false) { |
|
291 | - try { |
|
292 | - $offset = self::get_timezone_offset(new DateTimeZone($city['timezone_id'])); |
|
293 | - if ($offset !== $gmt_offset) { |
|
294 | - continue; |
|
295 | - } else { |
|
296 | - return $city['timezone_id']; |
|
297 | - } |
|
298 | - } catch (Exception $e) { |
|
299 | - continue; |
|
300 | - } |
|
301 | - } |
|
302 | - } |
|
303 | - } |
|
304 | - //if $coerce is true, let's see if we can get a timezone string after the offset is adjusted |
|
305 | - if ($coerce == true) { |
|
306 | - $timezone_string = self::get_timezone_string_from_abbreviations_list( |
|
307 | - self::adjust_invalid_gmt_offsets($gmt_offset), |
|
308 | - false |
|
309 | - ); |
|
310 | - if ($timezone_string) { |
|
311 | - return $timezone_string; |
|
312 | - } |
|
313 | - } |
|
314 | - throw new EE_Error( |
|
315 | - sprintf( |
|
316 | - __('The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used', |
|
317 | - 'event_espresso'), |
|
318 | - $gmt_offset, |
|
319 | - '<a href="http://www.php.net/manual/en/timezones.php">', |
|
320 | - '</a>' |
|
321 | - ) |
|
322 | - ); |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * Get Timezone Transitions |
|
329 | - * @param \DateTimeZone $date_time_zone |
|
330 | - * @param null $time |
|
331 | - * @param bool $first_only |
|
332 | - * @return array|mixed |
|
333 | - */ |
|
334 | - public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true) |
|
335 | - { |
|
336 | - $time = is_int($time) || $time === null ? $time : strtotime($time); |
|
337 | - $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time(); |
|
338 | - $transitions = $date_time_zone->getTransitions($time); |
|
339 | - return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions; |
|
340 | - } |
|
341 | - |
|
342 | - |
|
343 | - /** |
|
344 | - * Get Timezone Offset for given timezone object. |
|
345 | - * @param \DateTimeZone $date_time_zone |
|
346 | - * @param null $time |
|
347 | - * @return mixed |
|
348 | - * @throws \DomainException |
|
349 | - */ |
|
350 | - public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null) |
|
351 | - { |
|
352 | - $transitions = self::get_timezone_transitions($date_time_zone, $time); |
|
353 | - if (! isset($transitions['offset'])) { |
|
354 | - throw new DomainException(); |
|
355 | - } |
|
356 | - return $transitions['offset']; |
|
357 | - } |
|
358 | - |
|
359 | - |
|
360 | - /** |
|
361 | - * @access public |
|
362 | - * @param string $timezone_string |
|
363 | - */ |
|
364 | - public static function timezone_select_input($timezone_string = '') |
|
365 | - { |
|
366 | - // get WP date time format |
|
367 | - $datetime_format = get_option('date_format') . ' ' . get_option('time_format'); |
|
368 | - // if passed a value, then use that, else get WP option |
|
369 | - $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string'); |
|
370 | - // check if the timezone is valid but don't throw any errors if it isn't |
|
371 | - $timezone_string = EEH_DTT_Helper::validate_timezone($timezone_string, false); |
|
372 | - $gmt_offset = get_option('gmt_offset'); |
|
373 | - |
|
374 | - $check_zone_info = true; |
|
375 | - if (empty($timezone_string)) { |
|
376 | - // Create a UTC+- zone if no timezone string exists |
|
377 | - $check_zone_info = false; |
|
378 | - if ($gmt_offset > 0) { |
|
379 | - $timezone_string = 'UTC+' . $gmt_offset; |
|
380 | - } elseif ($gmt_offset < 0) { |
|
381 | - $timezone_string = 'UTC' . $gmt_offset; |
|
382 | - } else { |
|
383 | - $timezone_string = 'UTC'; |
|
384 | - } |
|
385 | - } |
|
386 | - ?> |
|
29 | + /** |
|
30 | + * return the timezone set for the WP install |
|
31 | + * |
|
32 | + * @return string valid timezone string for PHP DateTimeZone() class |
|
33 | + */ |
|
34 | + public static function get_timezone() |
|
35 | + { |
|
36 | + return EEH_DTT_Helper::get_valid_timezone_string(); |
|
37 | + } |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * get_valid_timezone_string |
|
42 | + * ensures that a valid timezone string is returned |
|
43 | + * |
|
44 | + * @access protected |
|
45 | + * @param string $timezone_string |
|
46 | + * @return string |
|
47 | + * @throws \EE_Error |
|
48 | + */ |
|
49 | + public static function get_valid_timezone_string($timezone_string = '') |
|
50 | + { |
|
51 | + // if passed a value, then use that, else get WP option |
|
52 | + $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string'); |
|
53 | + // value from above exists, use that, else get timezone string from gmt_offset |
|
54 | + $timezone_string = ! empty($timezone_string) ? $timezone_string : EEH_DTT_Helper::get_timezone_string_from_gmt_offset(); |
|
55 | + EEH_DTT_Helper::validate_timezone($timezone_string); |
|
56 | + return $timezone_string; |
|
57 | + } |
|
58 | + |
|
59 | + |
|
60 | + /** |
|
61 | + * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone. |
|
62 | + * |
|
63 | + * @static |
|
64 | + * @access public |
|
65 | + * @param string $timezone_string Timezone string to check |
|
66 | + * @param bool $throw_error |
|
67 | + * @return bool |
|
68 | + * @throws \EE_Error |
|
69 | + */ |
|
70 | + public static function validate_timezone($timezone_string, $throw_error = true) |
|
71 | + { |
|
72 | + // easiest way to test a timezone string is just see if it throws an error when you try to create a DateTimeZone object with it |
|
73 | + try { |
|
74 | + new DateTimeZone($timezone_string); |
|
75 | + } catch (Exception $e) { |
|
76 | + // sometimes we take exception to exceptions |
|
77 | + if (! $throw_error) { |
|
78 | + return false; |
|
79 | + } |
|
80 | + throw new EE_Error( |
|
81 | + sprintf( |
|
82 | + __('The timezone given (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used', |
|
83 | + 'event_espresso'), |
|
84 | + $timezone_string, |
|
85 | + '<a href="http://www.php.net/manual/en/timezones.php">', |
|
86 | + '</a>' |
|
87 | + ) |
|
88 | + ); |
|
89 | + } |
|
90 | + return true; |
|
91 | + } |
|
92 | + |
|
93 | + |
|
94 | + /** |
|
95 | + * _create_timezone_object_from_timezone_name |
|
96 | + * |
|
97 | + * @access protected |
|
98 | + * @param string $gmt_offset |
|
99 | + * @return string |
|
100 | + */ |
|
101 | + public static function get_timezone_string_from_gmt_offset($gmt_offset = '') |
|
102 | + { |
|
103 | + $timezone_string = 'UTC'; |
|
104 | + //if there is no incoming gmt_offset, then because WP hooks in on timezone_string, we need to see if that is |
|
105 | + //set because it will override `gmt_offset` via `pre_get_option` filter. If that's set, then let's just use |
|
106 | + //that! Otherwise we'll leave timezone_string at the default of 'UTC' before doing other logic. |
|
107 | + if ($gmt_offset === '') { |
|
108 | + //autoloaded so no need to set to a variable. There will not be multiple hits to the db. |
|
109 | + if (get_option('timezone_string')) { |
|
110 | + return get_option('timezone_string'); |
|
111 | + } |
|
112 | + } |
|
113 | + $gmt_offset = $gmt_offset !== '' ? $gmt_offset : get_option('gmt_offset'); |
|
114 | + $gmt_offset = (float) $gmt_offset; |
|
115 | + |
|
116 | + //if $gmt_offset is 0, then just return UTC |
|
117 | + if ($gmt_offset === (float) 0) { |
|
118 | + return $timezone_string; |
|
119 | + } |
|
120 | + |
|
121 | + |
|
122 | + if ($gmt_offset !== '') { |
|
123 | + // convert GMT offset to seconds |
|
124 | + $gmt_offset = $gmt_offset * HOUR_IN_SECONDS; |
|
125 | + // although we don't know the TZ abbreviation, we know the UTC offset |
|
126 | + $timezone_string = timezone_name_from_abbr(null, $gmt_offset); |
|
127 | + //only use this timezone_string IF it's current offset matches the given offset |
|
128 | + try { |
|
129 | + $offset = self::get_timezone_offset(new DateTimeZone($timezone_string)); |
|
130 | + if ($offset !== $gmt_offset) { |
|
131 | + $timezone_string = false; |
|
132 | + } |
|
133 | + } catch (Exception $e) { |
|
134 | + $timezone_string = false; |
|
135 | + } |
|
136 | + } |
|
137 | + // better have a valid timezone string by now, but if not, sigh... loop thru the timezone_abbreviations_list()... |
|
138 | + $timezone_string = $timezone_string !== false |
|
139 | + ? $timezone_string |
|
140 | + : EEH_DTT_Helper::get_timezone_string_from_abbreviations_list($gmt_offset); |
|
141 | + return $timezone_string; |
|
142 | + } |
|
143 | + |
|
144 | + /** |
|
145 | + * Gets the site's GMT offset based on either the timezone string |
|
146 | + * (in which case teh gmt offset will vary depending on the location's |
|
147 | + * observance of daylight savings time) or the gmt_offset wp option |
|
148 | + * |
|
149 | + * @return int seconds offset |
|
150 | + */ |
|
151 | + public static function get_site_timezone_gmt_offset() |
|
152 | + { |
|
153 | + $timezone_string = get_option('timezone_string'); |
|
154 | + if ($timezone_string) { |
|
155 | + try { |
|
156 | + $timezone = new DateTimeZone($timezone_string); |
|
157 | + return $timezone->getOffset(new DateTime()); //in WordPress DateTime defaults to UTC |
|
158 | + } catch (Exception $e) { |
|
159 | + } |
|
160 | + } |
|
161 | + $offset = get_option('gmt_offset'); |
|
162 | + return (int)($offset * HOUR_IN_SECONDS); |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + /** |
|
167 | + * Depending on PHP version, there might not bevalid current timezone strings to match these gmt_offsets in its |
|
168 | + * timezone tables. |
|
169 | + * To get around that, for these fringe timezones we bump them to a known valid offset. |
|
170 | + * |
|
171 | + * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset. |
|
172 | + * |
|
173 | + * @access public |
|
174 | + * @param int $gmt_offset |
|
175 | + * @return int |
|
176 | + */ |
|
177 | + public static function adjust_invalid_gmt_offsets($gmt_offset = 0) |
|
178 | + { |
|
179 | + //make sure $gmt_offset is int |
|
180 | + $gmt_offset = (int)$gmt_offset; |
|
181 | + switch ($gmt_offset) { |
|
182 | + //-12 |
|
183 | + case -43200: |
|
184 | + $gmt_offset = -39600; |
|
185 | + break; |
|
186 | + //-11.5 |
|
187 | + case -41400: |
|
188 | + $gmt_offset = -39600; |
|
189 | + break; |
|
190 | + //-10.5 |
|
191 | + case -37800: |
|
192 | + $gmt_offset = -39600; |
|
193 | + break; |
|
194 | + //-8.5 |
|
195 | + case -30600: |
|
196 | + $gmt_offset = -28800; |
|
197 | + break; |
|
198 | + //-7.5 |
|
199 | + case -27000: |
|
200 | + $gmt_offset = -25200; |
|
201 | + break; |
|
202 | + //-6.5 |
|
203 | + case -23400: |
|
204 | + $gmt_offset = -21600; |
|
205 | + break; |
|
206 | + //-5.5 |
|
207 | + case -19800: |
|
208 | + $gmt_offset = -18000; |
|
209 | + break; |
|
210 | + //-4.5 |
|
211 | + case -16200: |
|
212 | + $gmt_offset = -14400; |
|
213 | + break; |
|
214 | + //-3.5 |
|
215 | + case -12600: |
|
216 | + $gmt_offset = -10800; |
|
217 | + break; |
|
218 | + //-2.5 |
|
219 | + case -9000: |
|
220 | + $gmt_offset = -7200; |
|
221 | + break; |
|
222 | + //-1.5 |
|
223 | + case -5400: |
|
224 | + $gmt_offset = -3600; |
|
225 | + break; |
|
226 | + //-0.5 |
|
227 | + case -1800: |
|
228 | + $gmt_offset = 0; |
|
229 | + break; |
|
230 | + //.5 |
|
231 | + case 1800: |
|
232 | + $gmt_offset = 3600; |
|
233 | + break; |
|
234 | + //1.5 |
|
235 | + case 5400: |
|
236 | + $gmt_offset = 7200; |
|
237 | + break; |
|
238 | + //2.5 |
|
239 | + case 9000: |
|
240 | + $gmt_offset = 10800; |
|
241 | + break; |
|
242 | + //3.5 |
|
243 | + case 12600: |
|
244 | + $gmt_offset = 14400; |
|
245 | + break; |
|
246 | + |
|
247 | + //7.5 |
|
248 | + case 27000: |
|
249 | + $gmt_offset = 28800; |
|
250 | + break; |
|
251 | + //8.5 |
|
252 | + case 30600: |
|
253 | + $gmt_offset = 31500; |
|
254 | + break; |
|
255 | + //10.5 |
|
256 | + case 37800: |
|
257 | + $gmt_offset = 39600; |
|
258 | + break; |
|
259 | + //11.5 |
|
260 | + case 41400: |
|
261 | + $gmt_offset = 43200; |
|
262 | + break; |
|
263 | + //12.75 |
|
264 | + case 45900: |
|
265 | + $gmt_offset = 46800; |
|
266 | + break; |
|
267 | + //13.75 |
|
268 | + case 49500: |
|
269 | + $gmt_offset = 50400; |
|
270 | + break; |
|
271 | + } |
|
272 | + return $gmt_offset; |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + /** |
|
277 | + * get_timezone_string_from_abbreviations_list |
|
278 | + * |
|
279 | + * @access public |
|
280 | + * @param int $gmt_offset |
|
281 | + * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset. |
|
282 | + * @return string |
|
283 | + * @throws \EE_Error |
|
284 | + */ |
|
285 | + public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true) |
|
286 | + { |
|
287 | + $abbreviations = timezone_abbreviations_list(); |
|
288 | + foreach ($abbreviations as $abbreviation) { |
|
289 | + foreach ($abbreviation as $city) { |
|
290 | + if ($city['offset'] === $gmt_offset && $city['dst'] === false) { |
|
291 | + try { |
|
292 | + $offset = self::get_timezone_offset(new DateTimeZone($city['timezone_id'])); |
|
293 | + if ($offset !== $gmt_offset) { |
|
294 | + continue; |
|
295 | + } else { |
|
296 | + return $city['timezone_id']; |
|
297 | + } |
|
298 | + } catch (Exception $e) { |
|
299 | + continue; |
|
300 | + } |
|
301 | + } |
|
302 | + } |
|
303 | + } |
|
304 | + //if $coerce is true, let's see if we can get a timezone string after the offset is adjusted |
|
305 | + if ($coerce == true) { |
|
306 | + $timezone_string = self::get_timezone_string_from_abbreviations_list( |
|
307 | + self::adjust_invalid_gmt_offsets($gmt_offset), |
|
308 | + false |
|
309 | + ); |
|
310 | + if ($timezone_string) { |
|
311 | + return $timezone_string; |
|
312 | + } |
|
313 | + } |
|
314 | + throw new EE_Error( |
|
315 | + sprintf( |
|
316 | + __('The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used', |
|
317 | + 'event_espresso'), |
|
318 | + $gmt_offset, |
|
319 | + '<a href="http://www.php.net/manual/en/timezones.php">', |
|
320 | + '</a>' |
|
321 | + ) |
|
322 | + ); |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * Get Timezone Transitions |
|
329 | + * @param \DateTimeZone $date_time_zone |
|
330 | + * @param null $time |
|
331 | + * @param bool $first_only |
|
332 | + * @return array|mixed |
|
333 | + */ |
|
334 | + public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true) |
|
335 | + { |
|
336 | + $time = is_int($time) || $time === null ? $time : strtotime($time); |
|
337 | + $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time(); |
|
338 | + $transitions = $date_time_zone->getTransitions($time); |
|
339 | + return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions; |
|
340 | + } |
|
341 | + |
|
342 | + |
|
343 | + /** |
|
344 | + * Get Timezone Offset for given timezone object. |
|
345 | + * @param \DateTimeZone $date_time_zone |
|
346 | + * @param null $time |
|
347 | + * @return mixed |
|
348 | + * @throws \DomainException |
|
349 | + */ |
|
350 | + public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null) |
|
351 | + { |
|
352 | + $transitions = self::get_timezone_transitions($date_time_zone, $time); |
|
353 | + if (! isset($transitions['offset'])) { |
|
354 | + throw new DomainException(); |
|
355 | + } |
|
356 | + return $transitions['offset']; |
|
357 | + } |
|
358 | + |
|
359 | + |
|
360 | + /** |
|
361 | + * @access public |
|
362 | + * @param string $timezone_string |
|
363 | + */ |
|
364 | + public static function timezone_select_input($timezone_string = '') |
|
365 | + { |
|
366 | + // get WP date time format |
|
367 | + $datetime_format = get_option('date_format') . ' ' . get_option('time_format'); |
|
368 | + // if passed a value, then use that, else get WP option |
|
369 | + $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string'); |
|
370 | + // check if the timezone is valid but don't throw any errors if it isn't |
|
371 | + $timezone_string = EEH_DTT_Helper::validate_timezone($timezone_string, false); |
|
372 | + $gmt_offset = get_option('gmt_offset'); |
|
373 | + |
|
374 | + $check_zone_info = true; |
|
375 | + if (empty($timezone_string)) { |
|
376 | + // Create a UTC+- zone if no timezone string exists |
|
377 | + $check_zone_info = false; |
|
378 | + if ($gmt_offset > 0) { |
|
379 | + $timezone_string = 'UTC+' . $gmt_offset; |
|
380 | + } elseif ($gmt_offset < 0) { |
|
381 | + $timezone_string = 'UTC' . $gmt_offset; |
|
382 | + } else { |
|
383 | + $timezone_string = 'UTC'; |
|
384 | + } |
|
385 | + } |
|
386 | + ?> |
|
387 | 387 | |
388 | 388 | <p> |
389 | 389 | <label for="timezone_string"><?php _e('timezone'); ?></label> |
@@ -396,13 +396,13 @@ discard block |
||
396 | 396 | |
397 | 397 | <p> |
398 | 398 | <span><?php |
399 | - printf( |
|
400 | - __('%1$sUTC%2$s time is %3$s'), |
|
401 | - '<abbr title="Coordinated Universal Time">', |
|
402 | - '</abbr>', |
|
403 | - '<code>' . date_i18n($datetime_format, false, true) . '</code>' |
|
404 | - ); |
|
405 | - ?></span> |
|
399 | + printf( |
|
400 | + __('%1$sUTC%2$s time is %3$s'), |
|
401 | + '<abbr title="Coordinated Universal Time">', |
|
402 | + '</abbr>', |
|
403 | + '<code>' . date_i18n($datetime_format, false, true) . '</code>' |
|
404 | + ); |
|
405 | + ?></span> |
|
406 | 406 | <?php if (! empty($timezone_string) || ! empty($gmt_offset)) : ?> |
407 | 407 | <br/><span><?php printf(__('Local time is %1$s'), '<code>' . date_i18n($datetime_format) . '</code>'); ?></span> |
408 | 408 | <?php endif; ?> |
@@ -411,693 +411,693 @@ discard block |
||
411 | 411 | <br/> |
412 | 412 | <span> |
413 | 413 | <?php |
414 | - // Set TZ so localtime works. |
|
415 | - date_default_timezone_set($timezone_string); |
|
416 | - $now = localtime(time(), true); |
|
417 | - if ($now['tm_isdst']) { |
|
418 | - _e('This timezone is currently in daylight saving time.'); |
|
419 | - } else { |
|
420 | - _e('This timezone is currently in standard time.'); |
|
421 | - } |
|
422 | - ?> |
|
414 | + // Set TZ so localtime works. |
|
415 | + date_default_timezone_set($timezone_string); |
|
416 | + $now = localtime(time(), true); |
|
417 | + if ($now['tm_isdst']) { |
|
418 | + _e('This timezone is currently in daylight saving time.'); |
|
419 | + } else { |
|
420 | + _e('This timezone is currently in standard time.'); |
|
421 | + } |
|
422 | + ?> |
|
423 | 423 | <br/> |
424 | 424 | <?php |
425 | - if (function_exists('timezone_transitions_get')) { |
|
426 | - $found = false; |
|
427 | - $date_time_zone_selected = new DateTimeZone($timezone_string); |
|
428 | - $tz_offset = timezone_offset_get($date_time_zone_selected, date_create()); |
|
429 | - $right_now = time(); |
|
430 | - $tr['isdst'] = false; |
|
431 | - foreach (timezone_transitions_get($date_time_zone_selected) as $tr) { |
|
432 | - if ($tr['ts'] > $right_now) { |
|
433 | - $found = true; |
|
434 | - break; |
|
435 | - } |
|
436 | - } |
|
437 | - |
|
438 | - if ($found) { |
|
439 | - $message = $tr['isdst'] ? |
|
440 | - __(' Daylight saving time begins on: %s.') : |
|
441 | - __(' Standard time begins on: %s.'); |
|
442 | - // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n(). |
|
443 | - printf($message, |
|
444 | - '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >'); |
|
445 | - } else { |
|
446 | - _e('This timezone does not observe daylight saving time.'); |
|
447 | - } |
|
448 | - } |
|
449 | - // Set back to UTC. |
|
450 | - date_default_timezone_set('UTC'); |
|
451 | - ?> |
|
425 | + if (function_exists('timezone_transitions_get')) { |
|
426 | + $found = false; |
|
427 | + $date_time_zone_selected = new DateTimeZone($timezone_string); |
|
428 | + $tz_offset = timezone_offset_get($date_time_zone_selected, date_create()); |
|
429 | + $right_now = time(); |
|
430 | + $tr['isdst'] = false; |
|
431 | + foreach (timezone_transitions_get($date_time_zone_selected) as $tr) { |
|
432 | + if ($tr['ts'] > $right_now) { |
|
433 | + $found = true; |
|
434 | + break; |
|
435 | + } |
|
436 | + } |
|
437 | + |
|
438 | + if ($found) { |
|
439 | + $message = $tr['isdst'] ? |
|
440 | + __(' Daylight saving time begins on: %s.') : |
|
441 | + __(' Standard time begins on: %s.'); |
|
442 | + // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n(). |
|
443 | + printf($message, |
|
444 | + '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >'); |
|
445 | + } else { |
|
446 | + _e('This timezone does not observe daylight saving time.'); |
|
447 | + } |
|
448 | + } |
|
449 | + // Set back to UTC. |
|
450 | + date_default_timezone_set('UTC'); |
|
451 | + ?> |
|
452 | 452 | </span></p> |
453 | 453 | <?php |
454 | - endif; |
|
455 | - } |
|
456 | - |
|
457 | - |
|
458 | - /** |
|
459 | - * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string. |
|
460 | - * If no unix timestamp is given then time() is used. If no timezone is given then the set timezone string for |
|
461 | - * the site is used. |
|
462 | - * This is used typically when using a Unix timestamp any core WP functions that expect their specially |
|
463 | - * computed timestamp (i.e. date_i18n() ) |
|
464 | - * |
|
465 | - * @param int $unix_timestamp if 0, then time() will be used. |
|
466 | - * @param string $timezone_string timezone_string. If empty, then the current set timezone for the |
|
467 | - * site will be used. |
|
468 | - * @return int $unix_timestamp with the offset applied for the given timezone. |
|
469 | - */ |
|
470 | - public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '') |
|
471 | - { |
|
472 | - $unix_timestamp = $unix_timestamp === 0 ? time() : (int)$unix_timestamp; |
|
473 | - $timezone_string = self::get_valid_timezone_string($timezone_string); |
|
474 | - $TimeZone = new DateTimeZone($timezone_string); |
|
475 | - |
|
476 | - $DateTime = new DateTime('@' . $unix_timestamp, $TimeZone); |
|
477 | - $offset = timezone_offset_get($TimeZone, $DateTime); |
|
478 | - return (int)$DateTime->format('U') + (int)$offset; |
|
479 | - } |
|
480 | - |
|
481 | - |
|
482 | - /** |
|
483 | - * _set_date_time_field |
|
484 | - * modifies EE_Base_Class EE_Datetime_Field objects |
|
485 | - * |
|
486 | - * @param EE_Base_Class $obj EE_Base_Class object |
|
487 | - * @param DateTime $DateTime PHP DateTime object |
|
488 | - * @param string $datetime_field_name the datetime fieldname to be manipulated |
|
489 | - * @return EE_Base_Class |
|
490 | - */ |
|
491 | - protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name) |
|
492 | - { |
|
493 | - // grab current datetime format |
|
494 | - $current_format = $obj->get_format(); |
|
495 | - // set new full timestamp format |
|
496 | - $obj->set_date_format(EE_Datetime_Field::mysql_date_format); |
|
497 | - $obj->set_time_format(EE_Datetime_Field::mysql_time_format); |
|
498 | - // set the new date value using a full timestamp format so that no data is lost |
|
499 | - $obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format)); |
|
500 | - // reset datetime formats |
|
501 | - $obj->set_date_format($current_format[0]); |
|
502 | - $obj->set_time_format($current_format[1]); |
|
503 | - return $obj; |
|
504 | - } |
|
505 | - |
|
506 | - |
|
507 | - /** |
|
508 | - * date_time_add |
|
509 | - * helper for doing simple datetime calculations on a given datetime from EE_Base_Class |
|
510 | - * and modifying it IN the EE_Base_Class so you don't have to do anything else. |
|
511 | - * |
|
512 | - * @param EE_Base_Class $obj EE_Base_Class object |
|
513 | - * @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
|
514 | - * @param string $period what you are adding. The options are (years, months, days, hours, |
|
515 | - * minutes, seconds) defaults to years |
|
516 | - * @param integer $value what you want to increment the time by |
|
517 | - * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it |
|
518 | - * (chaining) |
|
519 | - */ |
|
520 | - public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
|
521 | - { |
|
522 | - //get the raw UTC date. |
|
523 | - $DateTime = $obj->get_DateTime_object($datetime_field_name); |
|
524 | - $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value); |
|
525 | - return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
|
526 | - } |
|
527 | - |
|
528 | - |
|
529 | - /** |
|
530 | - * date_time_subtract |
|
531 | - * same as date_time_add except subtracting value instead of adding. |
|
532 | - * |
|
533 | - * @param \EE_Base_Class $obj |
|
534 | - * @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
|
535 | - * @param string $period |
|
536 | - * @param int $value |
|
537 | - * @return \EE_Base_Class |
|
538 | - */ |
|
539 | - public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
|
540 | - { |
|
541 | - //get the raw UTC date |
|
542 | - $DateTime = $obj->get_DateTime_object($datetime_field_name); |
|
543 | - $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-'); |
|
544 | - return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
|
545 | - } |
|
546 | - |
|
547 | - |
|
548 | - /** |
|
549 | - * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters |
|
550 | - * |
|
551 | - * @param DateTime $DateTime DateTime object |
|
552 | - * @param string $period a value to indicate what interval is being used in the calculation. The options are |
|
553 | - * 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
|
554 | - * @param integer $value What you want to increment the date by |
|
555 | - * @param string $operand What operand you wish to use for the calculation |
|
556 | - * @return \DateTime return whatever type came in. |
|
557 | - * @throws \EE_Error |
|
558 | - */ |
|
559 | - protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+') |
|
560 | - { |
|
561 | - if (! $DateTime instanceof DateTime) { |
|
562 | - throw new EE_Error( |
|
563 | - sprintf( |
|
564 | - __('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'), |
|
565 | - print_r($DateTime, true) |
|
566 | - ) |
|
567 | - ); |
|
568 | - } |
|
569 | - switch ($period) { |
|
570 | - case 'years' : |
|
571 | - $value = 'P' . $value . 'Y'; |
|
572 | - break; |
|
573 | - case 'months' : |
|
574 | - $value = 'P' . $value . 'M'; |
|
575 | - break; |
|
576 | - case 'weeks' : |
|
577 | - $value = 'P' . $value . 'W'; |
|
578 | - break; |
|
579 | - case 'days' : |
|
580 | - $value = 'P' . $value . 'D'; |
|
581 | - break; |
|
582 | - case 'hours' : |
|
583 | - $value = 'PT' . $value . 'H'; |
|
584 | - break; |
|
585 | - case 'minutes' : |
|
586 | - $value = 'PT' . $value . 'M'; |
|
587 | - break; |
|
588 | - case 'seconds' : |
|
589 | - $value = 'PT' . $value . 'S'; |
|
590 | - break; |
|
591 | - } |
|
592 | - switch ($operand) { |
|
593 | - case '+': |
|
594 | - $DateTime->add(new DateInterval($value)); |
|
595 | - break; |
|
596 | - case '-': |
|
597 | - $DateTime->sub(new DateInterval($value)); |
|
598 | - break; |
|
599 | - } |
|
600 | - return $DateTime; |
|
601 | - } |
|
602 | - |
|
603 | - |
|
604 | - /** |
|
605 | - * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters |
|
606 | - * |
|
607 | - * @param int $timestamp Unix timestamp |
|
608 | - * @param string $period a value to indicate what interval is being used in the calculation. The options are |
|
609 | - * 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
|
610 | - * @param integer $value What you want to increment the date by |
|
611 | - * @param string $operand What operand you wish to use for the calculation |
|
612 | - * @return \DateTime return whatever type came in. |
|
613 | - * @throws \EE_Error |
|
614 | - */ |
|
615 | - protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+') |
|
616 | - { |
|
617 | - if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) { |
|
618 | - throw new EE_Error( |
|
619 | - sprintf( |
|
620 | - __('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'), |
|
621 | - print_r($timestamp, true) |
|
622 | - ) |
|
623 | - ); |
|
624 | - } |
|
625 | - switch ($period) { |
|
626 | - case 'years' : |
|
627 | - $value = YEAR_IN_SECONDS * $value; |
|
628 | - break; |
|
629 | - case 'months' : |
|
630 | - $value = YEAR_IN_SECONDS / 12 * $value; |
|
631 | - break; |
|
632 | - case 'weeks' : |
|
633 | - $value = WEEK_IN_SECONDS * $value; |
|
634 | - break; |
|
635 | - case 'days' : |
|
636 | - $value = DAY_IN_SECONDS * $value; |
|
637 | - break; |
|
638 | - case 'hours' : |
|
639 | - $value = HOUR_IN_SECONDS * $value; |
|
640 | - break; |
|
641 | - case 'minutes' : |
|
642 | - $value = MINUTE_IN_SECONDS * $value; |
|
643 | - break; |
|
644 | - } |
|
645 | - switch ($operand) { |
|
646 | - case '+': |
|
647 | - $timestamp += $value; |
|
648 | - break; |
|
649 | - case '-': |
|
650 | - $timestamp -= $value; |
|
651 | - break; |
|
652 | - } |
|
653 | - return $timestamp; |
|
654 | - } |
|
655 | - |
|
656 | - |
|
657 | - /** |
|
658 | - * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming |
|
659 | - * parameters and returns the new timestamp or DateTime. |
|
660 | - * |
|
661 | - * @param int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp |
|
662 | - * @param string $period a value to indicate what interval is being used in the |
|
663 | - * calculation. The options are 'years', 'months', 'days', 'hours', |
|
664 | - * 'minutes', 'seconds'. Defaults to years. |
|
665 | - * @param integer $value What you want to increment the date by |
|
666 | - * @param string $operand What operand you wish to use for the calculation |
|
667 | - * @return mixed string|DateTime return whatever type came in. |
|
668 | - */ |
|
669 | - public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+') |
|
670 | - { |
|
671 | - if ($DateTime_or_timestamp instanceof DateTime) { |
|
672 | - return EEH_DTT_Helper::_modify_datetime_object($DateTime_or_timestamp, $period, $value, $operand); |
|
673 | - } else if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) { |
|
674 | - return EEH_DTT_Helper::_modify_timestamp($DateTime_or_timestamp, $period, $value, $operand); |
|
675 | - } else { |
|
676 | - //error |
|
677 | - return $DateTime_or_timestamp; |
|
678 | - } |
|
679 | - } |
|
680 | - |
|
681 | - |
|
682 | - /** |
|
683 | - * The purpose of this helper method is to receive an incoming format string in php date/time format |
|
684 | - * and spit out the js and moment.js equivalent formats. |
|
685 | - * Note, if no format string is given, then it is assumed the user wants what is set for WP. |
|
686 | - * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date- |
|
687 | - * time picker. |
|
688 | - * |
|
689 | - * @see http://stackoverflow.com/posts/16725290/ for the code inspiration. |
|
690 | - * @param null $date_format_string |
|
691 | - * @param null $time_format_string |
|
692 | - * @return array |
|
693 | - * array( |
|
694 | - * 'js' => array ( |
|
695 | - * 'date' => //date format |
|
696 | - * 'time' => //time format |
|
697 | - * ), |
|
698 | - * 'moment' => //date and time format. |
|
699 | - * ) |
|
700 | - */ |
|
701 | - public static function convert_php_to_js_and_moment_date_formats( |
|
702 | - $date_format_string = null, |
|
703 | - $time_format_string = null |
|
704 | - ) { |
|
705 | - if ($date_format_string === null) { |
|
706 | - $date_format_string = get_option('date_format'); |
|
707 | - } |
|
708 | - |
|
709 | - if ($time_format_string === null) { |
|
710 | - $time_format_string = get_option('time_format'); |
|
711 | - } |
|
712 | - |
|
713 | - $date_format = self::_php_to_js_moment_converter($date_format_string); |
|
714 | - $time_format = self::_php_to_js_moment_converter($time_format_string); |
|
715 | - |
|
716 | - return array( |
|
717 | - 'js' => array( |
|
718 | - 'date' => $date_format['js'], |
|
719 | - 'time' => $time_format['js'], |
|
720 | - ), |
|
721 | - 'moment' => $date_format['moment'] . ' ' . $time_format['moment'], |
|
722 | - ); |
|
723 | - } |
|
724 | - |
|
725 | - |
|
726 | - /** |
|
727 | - * This converts incoming format string into js and moment variations. |
|
728 | - * |
|
729 | - * @param string $format_string incoming php format string |
|
730 | - * @return array js and moment formats. |
|
731 | - */ |
|
732 | - protected static function _php_to_js_moment_converter($format_string) |
|
733 | - { |
|
734 | - /** |
|
735 | - * This is a map of symbols for formats. |
|
736 | - * The index is the php symbol, the equivalent values are in the array. |
|
737 | - * |
|
738 | - * @var array |
|
739 | - */ |
|
740 | - $symbols_map = array( |
|
741 | - // Day |
|
742 | - //01 |
|
743 | - 'd' => array( |
|
744 | - 'js' => 'dd', |
|
745 | - 'moment' => 'DD', |
|
746 | - ), |
|
747 | - //Mon |
|
748 | - 'D' => array( |
|
749 | - 'js' => 'D', |
|
750 | - 'moment' => 'ddd', |
|
751 | - ), |
|
752 | - //1,2,...31 |
|
753 | - 'j' => array( |
|
754 | - 'js' => 'd', |
|
755 | - 'moment' => 'D', |
|
756 | - ), |
|
757 | - //Monday |
|
758 | - 'l' => array( |
|
759 | - 'js' => 'DD', |
|
760 | - 'moment' => 'dddd', |
|
761 | - ), |
|
762 | - //ISO numeric representation of the day of the week (1-6) |
|
763 | - 'N' => array( |
|
764 | - 'js' => '', |
|
765 | - 'moment' => 'E', |
|
766 | - ), |
|
767 | - //st,nd.rd |
|
768 | - 'S' => array( |
|
769 | - 'js' => '', |
|
770 | - 'moment' => 'o', |
|
771 | - ), |
|
772 | - //numeric representation of day of week (0-6) |
|
773 | - 'w' => array( |
|
774 | - 'js' => '', |
|
775 | - 'moment' => 'd', |
|
776 | - ), |
|
777 | - //day of year starting from 0 (0-365) |
|
778 | - 'z' => array( |
|
779 | - 'js' => 'o', |
|
780 | - 'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1 |
|
781 | - ), |
|
782 | - // Week |
|
783 | - //ISO-8601 week number of year (weeks starting on monday) |
|
784 | - 'W' => array( |
|
785 | - 'js' => '', |
|
786 | - 'moment' => 'w', |
|
787 | - ), |
|
788 | - // Month |
|
789 | - // January...December |
|
790 | - 'F' => array( |
|
791 | - 'js' => 'MM', |
|
792 | - 'moment' => 'MMMM', |
|
793 | - ), |
|
794 | - //01...12 |
|
795 | - 'm' => array( |
|
796 | - 'js' => 'mm', |
|
797 | - 'moment' => 'MM', |
|
798 | - ), |
|
799 | - //Jan...Dec |
|
800 | - 'M' => array( |
|
801 | - 'js' => 'M', |
|
802 | - 'moment' => 'MMM', |
|
803 | - ), |
|
804 | - //1-12 |
|
805 | - 'n' => array( |
|
806 | - 'js' => 'm', |
|
807 | - 'moment' => 'M', |
|
808 | - ), |
|
809 | - //number of days in given month |
|
810 | - 't' => array( |
|
811 | - 'js' => '', |
|
812 | - 'moment' => '', |
|
813 | - ), |
|
814 | - // Year |
|
815 | - //whether leap year or not 1/0 |
|
816 | - 'L' => array( |
|
817 | - 'js' => '', |
|
818 | - 'moment' => '', |
|
819 | - ), |
|
820 | - //ISO-8601 year number |
|
821 | - 'o' => array( |
|
822 | - 'js' => '', |
|
823 | - 'moment' => 'GGGG', |
|
824 | - ), |
|
825 | - //1999...2003 |
|
826 | - 'Y' => array( |
|
827 | - 'js' => 'yy', |
|
828 | - 'moment' => 'YYYY', |
|
829 | - ), |
|
830 | - //99...03 |
|
831 | - 'y' => array( |
|
832 | - 'js' => 'y', |
|
833 | - 'moment' => 'YY', |
|
834 | - ), |
|
835 | - // Time |
|
836 | - // am/pm |
|
837 | - 'a' => array( |
|
838 | - 'js' => 'tt', |
|
839 | - 'moment' => 'a', |
|
840 | - ), |
|
841 | - // AM/PM |
|
842 | - 'A' => array( |
|
843 | - 'js' => 'TT', |
|
844 | - 'moment' => 'A', |
|
845 | - ), |
|
846 | - // Swatch Internet Time?!? |
|
847 | - 'B' => array( |
|
848 | - 'js' => '', |
|
849 | - 'moment' => '', |
|
850 | - ), |
|
851 | - //1...12 |
|
852 | - 'g' => array( |
|
853 | - 'js' => 'h', |
|
854 | - 'moment' => 'h', |
|
855 | - ), |
|
856 | - //0...23 |
|
857 | - 'G' => array( |
|
858 | - 'js' => 'H', |
|
859 | - 'moment' => 'H', |
|
860 | - ), |
|
861 | - //01...12 |
|
862 | - 'h' => array( |
|
863 | - 'js' => 'hh', |
|
864 | - 'moment' => 'hh', |
|
865 | - ), |
|
866 | - //00...23 |
|
867 | - 'H' => array( |
|
868 | - 'js' => 'HH', |
|
869 | - 'moment' => 'HH', |
|
870 | - ), |
|
871 | - //00..59 |
|
872 | - 'i' => array( |
|
873 | - 'js' => 'mm', |
|
874 | - 'moment' => 'mm', |
|
875 | - ), |
|
876 | - //seconds... 00...59 |
|
877 | - 's' => array( |
|
878 | - 'js' => 'ss', |
|
879 | - 'moment' => 'ss', |
|
880 | - ), |
|
881 | - //microseconds |
|
882 | - 'u' => array( |
|
883 | - 'js' => '', |
|
884 | - 'moment' => '', |
|
885 | - ), |
|
886 | - ); |
|
887 | - $jquery_ui_format = ""; |
|
888 | - $moment_format = ""; |
|
889 | - $escaping = false; |
|
890 | - for ($i = 0; $i < strlen($format_string); $i++) { |
|
891 | - $char = $format_string[$i]; |
|
892 | - if ($char === '\\') { // PHP date format escaping character |
|
893 | - $i++; |
|
894 | - if ($escaping) { |
|
895 | - $jquery_ui_format .= $format_string[$i]; |
|
896 | - $moment_format .= $format_string[$i]; |
|
897 | - } else { |
|
898 | - $jquery_ui_format .= '\'' . $format_string[$i]; |
|
899 | - $moment_format .= $format_string[$i]; |
|
900 | - } |
|
901 | - $escaping = true; |
|
902 | - } else { |
|
903 | - if ($escaping) { |
|
904 | - $jquery_ui_format .= "'"; |
|
905 | - $moment_format .= "'"; |
|
906 | - $escaping = false; |
|
907 | - } |
|
908 | - if (isset($symbols_map[$char])) { |
|
909 | - $jquery_ui_format .= $symbols_map[$char]['js']; |
|
910 | - $moment_format .= $symbols_map[$char]['moment']; |
|
911 | - } else { |
|
912 | - $jquery_ui_format .= $char; |
|
913 | - $moment_format .= $char; |
|
914 | - } |
|
915 | - } |
|
916 | - } |
|
917 | - return array('js' => $jquery_ui_format, 'moment' => $moment_format); |
|
918 | - } |
|
919 | - |
|
920 | - |
|
921 | - /** |
|
922 | - * This takes an incoming format string and validates it to ensure it will work fine with PHP. |
|
923 | - * |
|
924 | - * @param string $format_string Incoming format string for php date(). |
|
925 | - * @return mixed bool|array If all is okay then TRUE is returned. Otherwise an array of validation |
|
926 | - * errors is returned. So for client code calling, check for is_array() to |
|
927 | - * indicate failed validations. |
|
928 | - */ |
|
929 | - public static function validate_format_string($format_string) |
|
930 | - { |
|
931 | - $error_msg = array(); |
|
932 | - //time format checks |
|
933 | - switch (true) { |
|
934 | - case strpos($format_string, 'h') !== false : |
|
935 | - case strpos($format_string, 'g') !== false : |
|
936 | - /** |
|
937 | - * if the time string has a lowercase 'h' which == 12 hour time format and there |
|
938 | - * is not any ante meridiem format ('a' or 'A'). Then throw an error because its |
|
939 | - * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am. |
|
940 | - */ |
|
941 | - if (strpos(strtoupper($format_string), 'A') === false) { |
|
942 | - $error_msg[] = __('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".', |
|
943 | - 'event_espresso'); |
|
944 | - } |
|
945 | - break; |
|
946 | - |
|
947 | - } |
|
948 | - |
|
949 | - return empty($error_msg) ? true : $error_msg; |
|
950 | - } |
|
951 | - |
|
952 | - |
|
953 | - /** |
|
954 | - * If the the first date starts at midnight on one day, and the next date ends at midnight on the |
|
955 | - * very next day then this method will return true. |
|
956 | - * If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true. |
|
957 | - * If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false. |
|
958 | - * If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true. |
|
959 | - * |
|
960 | - * @param mixed $date_1 |
|
961 | - * @param mixed $date_2 |
|
962 | - * @return bool |
|
963 | - */ |
|
964 | - public static function dates_represent_one_24_hour_date($date_1, $date_2) |
|
965 | - { |
|
966 | - |
|
967 | - if ( |
|
968 | - (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) || |
|
969 | - ($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00') |
|
970 | - ) { |
|
971 | - return false; |
|
972 | - } |
|
973 | - return $date_2->format('U') - $date_1->format('U') == 86400 ? true : false; |
|
974 | - } |
|
975 | - |
|
976 | - |
|
977 | - /** |
|
978 | - * This returns the appropriate query interval string that can be used in sql queries involving mysql Date |
|
979 | - * Functions. |
|
980 | - * |
|
981 | - * @param string $timezone_string A timezone string in a valid format to instantiate a DateTimeZone object. |
|
982 | - * @param string $field_for_interval The Database field that is the interval is applied to in the query. |
|
983 | - * @return string |
|
984 | - */ |
|
985 | - public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval) |
|
986 | - { |
|
987 | - try { |
|
988 | - /** need to account for timezone offset on the selects */ |
|
989 | - $DateTimeZone = new DateTimeZone($timezone_string); |
|
990 | - } catch (Exception $e) { |
|
991 | - $DateTimeZone = null; |
|
992 | - } |
|
993 | - |
|
994 | - /** |
|
995 | - * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds. |
|
996 | - * Hence we do the calc for DateTimeZone::getOffset. |
|
997 | - */ |
|
998 | - $offset = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset'); |
|
999 | - $query_interval = $offset < 0 |
|
1000 | - ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)' |
|
1001 | - : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)'; |
|
1002 | - return $query_interval; |
|
1003 | - } |
|
1004 | - |
|
1005 | - /** |
|
1006 | - * Retrieves the site's default timezone and returns it formatted so it's ready for display |
|
1007 | - * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string' |
|
1008 | - * and 'gmt_offset' WordPress options directly; or use the filter |
|
1009 | - * FHEE__EEH_DTT_Helper__get_timezone_string_for_display |
|
1010 | - * (although note that we remove any HTML that may be added) |
|
1011 | - * |
|
1012 | - * @return string |
|
1013 | - */ |
|
1014 | - public static function get_timezone_string_for_display() |
|
1015 | - { |
|
1016 | - $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', ''); |
|
1017 | - if (! empty($pretty_timezone)) { |
|
1018 | - return esc_html($pretty_timezone); |
|
1019 | - } |
|
1020 | - $timezone_string = get_option('timezone_string'); |
|
1021 | - if ($timezone_string) { |
|
1022 | - static $mo_loaded = false; |
|
1023 | - // Load translations for continents and cities just like wp_timezone_choice does |
|
1024 | - if (! $mo_loaded) { |
|
1025 | - $locale = get_locale(); |
|
1026 | - $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo'; |
|
1027 | - load_textdomain('continents-cities', $mofile); |
|
1028 | - $mo_loaded = true; |
|
1029 | - } |
|
1030 | - //well that was easy. |
|
1031 | - $parts = explode('/', $timezone_string); |
|
1032 | - //remove the continent |
|
1033 | - unset($parts[0]); |
|
1034 | - $t_parts = array(); |
|
1035 | - foreach ($parts as $part) { |
|
1036 | - $t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities'); |
|
1037 | - } |
|
1038 | - return implode(' - ', $t_parts); |
|
1039 | - } |
|
1040 | - //they haven't set the timezone string, so let's return a string like "UTC+1" |
|
1041 | - $gmt_offset = get_option('gmt_offset'); |
|
1042 | - if (intval($gmt_offset) >= 0) { |
|
1043 | - $prefix = '+'; |
|
1044 | - } else { |
|
1045 | - $prefix = ''; |
|
1046 | - } |
|
1047 | - $parts = explode('.', (string)$gmt_offset); |
|
1048 | - if (count($parts) === 1) { |
|
1049 | - $parts[1] = '00'; |
|
1050 | - } else { |
|
1051 | - //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25) |
|
1052 | - //to minutes, eg 30 or 15, respectively |
|
1053 | - $hour_fraction = (float)('0.' . $parts[1]); |
|
1054 | - $parts[1] = (string)$hour_fraction * 60; |
|
1055 | - } |
|
1056 | - return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts)); |
|
1057 | - } |
|
1058 | - |
|
1059 | - |
|
1060 | - |
|
1061 | - /** |
|
1062 | - * So PHP does this awesome thing where if you are trying to get a timestamp |
|
1063 | - * for a month using a string like "February" or "February 2017", |
|
1064 | - * and you don't specify a day as part of your string, |
|
1065 | - * then PHP will use whatever the current day of the month is. |
|
1066 | - * IF the current day of the month happens to be the 30th or 31st, |
|
1067 | - * then PHP gets really confused by a date like February 30, |
|
1068 | - * so instead of saying |
|
1069 | - * "Hey February only has 28 days (this year)... |
|
1070 | - * ...you must have meant the last day of the month!" |
|
1071 | - * PHP does the next most logical thing, and bumps the date up to March 2nd, |
|
1072 | - * because someone requesting February 30th obviously meant March 1st! |
|
1073 | - * The way around this is to always set the day to the first, |
|
1074 | - * so that the month will stay on the month you wanted. |
|
1075 | - * this method will add that "1" into your date regardless of the format. |
|
1076 | - * |
|
1077 | - * @param string $month |
|
1078 | - * @return string |
|
1079 | - */ |
|
1080 | - public static function first_of_month_timestamp($month = '') |
|
1081 | - { |
|
1082 | - $month = (string)$month; |
|
1083 | - $year = ''; |
|
1084 | - // check if the incoming string has a year in it or not |
|
1085 | - if (preg_match('/\b\d{4}\b/', $month, $matches)) { |
|
1086 | - $year = $matches[0]; |
|
1087 | - // ten remove that from the month string as well as any spaces |
|
1088 | - $month = trim(str_replace($year, '', $month)); |
|
1089 | - // add a space before the year |
|
1090 | - $year = " {$year}"; |
|
1091 | - } |
|
1092 | - // return timestamp for something like "February 1 2017" |
|
1093 | - return strtotime("{$month} 1{$year}"); |
|
1094 | - } |
|
454 | + endif; |
|
455 | + } |
|
456 | + |
|
457 | + |
|
458 | + /** |
|
459 | + * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string. |
|
460 | + * If no unix timestamp is given then time() is used. If no timezone is given then the set timezone string for |
|
461 | + * the site is used. |
|
462 | + * This is used typically when using a Unix timestamp any core WP functions that expect their specially |
|
463 | + * computed timestamp (i.e. date_i18n() ) |
|
464 | + * |
|
465 | + * @param int $unix_timestamp if 0, then time() will be used. |
|
466 | + * @param string $timezone_string timezone_string. If empty, then the current set timezone for the |
|
467 | + * site will be used. |
|
468 | + * @return int $unix_timestamp with the offset applied for the given timezone. |
|
469 | + */ |
|
470 | + public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '') |
|
471 | + { |
|
472 | + $unix_timestamp = $unix_timestamp === 0 ? time() : (int)$unix_timestamp; |
|
473 | + $timezone_string = self::get_valid_timezone_string($timezone_string); |
|
474 | + $TimeZone = new DateTimeZone($timezone_string); |
|
475 | + |
|
476 | + $DateTime = new DateTime('@' . $unix_timestamp, $TimeZone); |
|
477 | + $offset = timezone_offset_get($TimeZone, $DateTime); |
|
478 | + return (int)$DateTime->format('U') + (int)$offset; |
|
479 | + } |
|
480 | + |
|
481 | + |
|
482 | + /** |
|
483 | + * _set_date_time_field |
|
484 | + * modifies EE_Base_Class EE_Datetime_Field objects |
|
485 | + * |
|
486 | + * @param EE_Base_Class $obj EE_Base_Class object |
|
487 | + * @param DateTime $DateTime PHP DateTime object |
|
488 | + * @param string $datetime_field_name the datetime fieldname to be manipulated |
|
489 | + * @return EE_Base_Class |
|
490 | + */ |
|
491 | + protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name) |
|
492 | + { |
|
493 | + // grab current datetime format |
|
494 | + $current_format = $obj->get_format(); |
|
495 | + // set new full timestamp format |
|
496 | + $obj->set_date_format(EE_Datetime_Field::mysql_date_format); |
|
497 | + $obj->set_time_format(EE_Datetime_Field::mysql_time_format); |
|
498 | + // set the new date value using a full timestamp format so that no data is lost |
|
499 | + $obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format)); |
|
500 | + // reset datetime formats |
|
501 | + $obj->set_date_format($current_format[0]); |
|
502 | + $obj->set_time_format($current_format[1]); |
|
503 | + return $obj; |
|
504 | + } |
|
505 | + |
|
1095 | 506 | |
1096 | 507 | /** |
1097 | - * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone. So it may be midnight |
|
1098 | - * for this sites timezone, but the timestamp could be some other time GMT. |
|
1099 | - */ |
|
1100 | - public static function tomorrow() |
|
508 | + * date_time_add |
|
509 | + * helper for doing simple datetime calculations on a given datetime from EE_Base_Class |
|
510 | + * and modifying it IN the EE_Base_Class so you don't have to do anything else. |
|
511 | + * |
|
512 | + * @param EE_Base_Class $obj EE_Base_Class object |
|
513 | + * @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
|
514 | + * @param string $period what you are adding. The options are (years, months, days, hours, |
|
515 | + * minutes, seconds) defaults to years |
|
516 | + * @param integer $value what you want to increment the time by |
|
517 | + * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it |
|
518 | + * (chaining) |
|
519 | + */ |
|
520 | + public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
|
521 | + { |
|
522 | + //get the raw UTC date. |
|
523 | + $DateTime = $obj->get_DateTime_object($datetime_field_name); |
|
524 | + $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value); |
|
525 | + return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
|
526 | + } |
|
527 | + |
|
528 | + |
|
529 | + /** |
|
530 | + * date_time_subtract |
|
531 | + * same as date_time_add except subtracting value instead of adding. |
|
532 | + * |
|
533 | + * @param \EE_Base_Class $obj |
|
534 | + * @param string $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated |
|
535 | + * @param string $period |
|
536 | + * @param int $value |
|
537 | + * @return \EE_Base_Class |
|
538 | + */ |
|
539 | + public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1) |
|
540 | + { |
|
541 | + //get the raw UTC date |
|
542 | + $DateTime = $obj->get_DateTime_object($datetime_field_name); |
|
543 | + $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-'); |
|
544 | + return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name); |
|
545 | + } |
|
546 | + |
|
547 | + |
|
548 | + /** |
|
549 | + * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters |
|
550 | + * |
|
551 | + * @param DateTime $DateTime DateTime object |
|
552 | + * @param string $period a value to indicate what interval is being used in the calculation. The options are |
|
553 | + * 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
|
554 | + * @param integer $value What you want to increment the date by |
|
555 | + * @param string $operand What operand you wish to use for the calculation |
|
556 | + * @return \DateTime return whatever type came in. |
|
557 | + * @throws \EE_Error |
|
558 | + */ |
|
559 | + protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+') |
|
560 | + { |
|
561 | + if (! $DateTime instanceof DateTime) { |
|
562 | + throw new EE_Error( |
|
563 | + sprintf( |
|
564 | + __('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'), |
|
565 | + print_r($DateTime, true) |
|
566 | + ) |
|
567 | + ); |
|
568 | + } |
|
569 | + switch ($period) { |
|
570 | + case 'years' : |
|
571 | + $value = 'P' . $value . 'Y'; |
|
572 | + break; |
|
573 | + case 'months' : |
|
574 | + $value = 'P' . $value . 'M'; |
|
575 | + break; |
|
576 | + case 'weeks' : |
|
577 | + $value = 'P' . $value . 'W'; |
|
578 | + break; |
|
579 | + case 'days' : |
|
580 | + $value = 'P' . $value . 'D'; |
|
581 | + break; |
|
582 | + case 'hours' : |
|
583 | + $value = 'PT' . $value . 'H'; |
|
584 | + break; |
|
585 | + case 'minutes' : |
|
586 | + $value = 'PT' . $value . 'M'; |
|
587 | + break; |
|
588 | + case 'seconds' : |
|
589 | + $value = 'PT' . $value . 'S'; |
|
590 | + break; |
|
591 | + } |
|
592 | + switch ($operand) { |
|
593 | + case '+': |
|
594 | + $DateTime->add(new DateInterval($value)); |
|
595 | + break; |
|
596 | + case '-': |
|
597 | + $DateTime->sub(new DateInterval($value)); |
|
598 | + break; |
|
599 | + } |
|
600 | + return $DateTime; |
|
601 | + } |
|
602 | + |
|
603 | + |
|
604 | + /** |
|
605 | + * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters |
|
606 | + * |
|
607 | + * @param int $timestamp Unix timestamp |
|
608 | + * @param string $period a value to indicate what interval is being used in the calculation. The options are |
|
609 | + * 'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years. |
|
610 | + * @param integer $value What you want to increment the date by |
|
611 | + * @param string $operand What operand you wish to use for the calculation |
|
612 | + * @return \DateTime return whatever type came in. |
|
613 | + * @throws \EE_Error |
|
614 | + */ |
|
615 | + protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+') |
|
616 | + { |
|
617 | + if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) { |
|
618 | + throw new EE_Error( |
|
619 | + sprintf( |
|
620 | + __('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'), |
|
621 | + print_r($timestamp, true) |
|
622 | + ) |
|
623 | + ); |
|
624 | + } |
|
625 | + switch ($period) { |
|
626 | + case 'years' : |
|
627 | + $value = YEAR_IN_SECONDS * $value; |
|
628 | + break; |
|
629 | + case 'months' : |
|
630 | + $value = YEAR_IN_SECONDS / 12 * $value; |
|
631 | + break; |
|
632 | + case 'weeks' : |
|
633 | + $value = WEEK_IN_SECONDS * $value; |
|
634 | + break; |
|
635 | + case 'days' : |
|
636 | + $value = DAY_IN_SECONDS * $value; |
|
637 | + break; |
|
638 | + case 'hours' : |
|
639 | + $value = HOUR_IN_SECONDS * $value; |
|
640 | + break; |
|
641 | + case 'minutes' : |
|
642 | + $value = MINUTE_IN_SECONDS * $value; |
|
643 | + break; |
|
644 | + } |
|
645 | + switch ($operand) { |
|
646 | + case '+': |
|
647 | + $timestamp += $value; |
|
648 | + break; |
|
649 | + case '-': |
|
650 | + $timestamp -= $value; |
|
651 | + break; |
|
652 | + } |
|
653 | + return $timestamp; |
|
654 | + } |
|
655 | + |
|
656 | + |
|
657 | + /** |
|
658 | + * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming |
|
659 | + * parameters and returns the new timestamp or DateTime. |
|
660 | + * |
|
661 | + * @param int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp |
|
662 | + * @param string $period a value to indicate what interval is being used in the |
|
663 | + * calculation. The options are 'years', 'months', 'days', 'hours', |
|
664 | + * 'minutes', 'seconds'. Defaults to years. |
|
665 | + * @param integer $value What you want to increment the date by |
|
666 | + * @param string $operand What operand you wish to use for the calculation |
|
667 | + * @return mixed string|DateTime return whatever type came in. |
|
668 | + */ |
|
669 | + public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+') |
|
670 | + { |
|
671 | + if ($DateTime_or_timestamp instanceof DateTime) { |
|
672 | + return EEH_DTT_Helper::_modify_datetime_object($DateTime_or_timestamp, $period, $value, $operand); |
|
673 | + } else if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) { |
|
674 | + return EEH_DTT_Helper::_modify_timestamp($DateTime_or_timestamp, $period, $value, $operand); |
|
675 | + } else { |
|
676 | + //error |
|
677 | + return $DateTime_or_timestamp; |
|
678 | + } |
|
679 | + } |
|
680 | + |
|
681 | + |
|
682 | + /** |
|
683 | + * The purpose of this helper method is to receive an incoming format string in php date/time format |
|
684 | + * and spit out the js and moment.js equivalent formats. |
|
685 | + * Note, if no format string is given, then it is assumed the user wants what is set for WP. |
|
686 | + * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date- |
|
687 | + * time picker. |
|
688 | + * |
|
689 | + * @see http://stackoverflow.com/posts/16725290/ for the code inspiration. |
|
690 | + * @param null $date_format_string |
|
691 | + * @param null $time_format_string |
|
692 | + * @return array |
|
693 | + * array( |
|
694 | + * 'js' => array ( |
|
695 | + * 'date' => //date format |
|
696 | + * 'time' => //time format |
|
697 | + * ), |
|
698 | + * 'moment' => //date and time format. |
|
699 | + * ) |
|
700 | + */ |
|
701 | + public static function convert_php_to_js_and_moment_date_formats( |
|
702 | + $date_format_string = null, |
|
703 | + $time_format_string = null |
|
704 | + ) { |
|
705 | + if ($date_format_string === null) { |
|
706 | + $date_format_string = get_option('date_format'); |
|
707 | + } |
|
708 | + |
|
709 | + if ($time_format_string === null) { |
|
710 | + $time_format_string = get_option('time_format'); |
|
711 | + } |
|
712 | + |
|
713 | + $date_format = self::_php_to_js_moment_converter($date_format_string); |
|
714 | + $time_format = self::_php_to_js_moment_converter($time_format_string); |
|
715 | + |
|
716 | + return array( |
|
717 | + 'js' => array( |
|
718 | + 'date' => $date_format['js'], |
|
719 | + 'time' => $time_format['js'], |
|
720 | + ), |
|
721 | + 'moment' => $date_format['moment'] . ' ' . $time_format['moment'], |
|
722 | + ); |
|
723 | + } |
|
724 | + |
|
725 | + |
|
726 | + /** |
|
727 | + * This converts incoming format string into js and moment variations. |
|
728 | + * |
|
729 | + * @param string $format_string incoming php format string |
|
730 | + * @return array js and moment formats. |
|
731 | + */ |
|
732 | + protected static function _php_to_js_moment_converter($format_string) |
|
733 | + { |
|
734 | + /** |
|
735 | + * This is a map of symbols for formats. |
|
736 | + * The index is the php symbol, the equivalent values are in the array. |
|
737 | + * |
|
738 | + * @var array |
|
739 | + */ |
|
740 | + $symbols_map = array( |
|
741 | + // Day |
|
742 | + //01 |
|
743 | + 'd' => array( |
|
744 | + 'js' => 'dd', |
|
745 | + 'moment' => 'DD', |
|
746 | + ), |
|
747 | + //Mon |
|
748 | + 'D' => array( |
|
749 | + 'js' => 'D', |
|
750 | + 'moment' => 'ddd', |
|
751 | + ), |
|
752 | + //1,2,...31 |
|
753 | + 'j' => array( |
|
754 | + 'js' => 'd', |
|
755 | + 'moment' => 'D', |
|
756 | + ), |
|
757 | + //Monday |
|
758 | + 'l' => array( |
|
759 | + 'js' => 'DD', |
|
760 | + 'moment' => 'dddd', |
|
761 | + ), |
|
762 | + //ISO numeric representation of the day of the week (1-6) |
|
763 | + 'N' => array( |
|
764 | + 'js' => '', |
|
765 | + 'moment' => 'E', |
|
766 | + ), |
|
767 | + //st,nd.rd |
|
768 | + 'S' => array( |
|
769 | + 'js' => '', |
|
770 | + 'moment' => 'o', |
|
771 | + ), |
|
772 | + //numeric representation of day of week (0-6) |
|
773 | + 'w' => array( |
|
774 | + 'js' => '', |
|
775 | + 'moment' => 'd', |
|
776 | + ), |
|
777 | + //day of year starting from 0 (0-365) |
|
778 | + 'z' => array( |
|
779 | + 'js' => 'o', |
|
780 | + 'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1 |
|
781 | + ), |
|
782 | + // Week |
|
783 | + //ISO-8601 week number of year (weeks starting on monday) |
|
784 | + 'W' => array( |
|
785 | + 'js' => '', |
|
786 | + 'moment' => 'w', |
|
787 | + ), |
|
788 | + // Month |
|
789 | + // January...December |
|
790 | + 'F' => array( |
|
791 | + 'js' => 'MM', |
|
792 | + 'moment' => 'MMMM', |
|
793 | + ), |
|
794 | + //01...12 |
|
795 | + 'm' => array( |
|
796 | + 'js' => 'mm', |
|
797 | + 'moment' => 'MM', |
|
798 | + ), |
|
799 | + //Jan...Dec |
|
800 | + 'M' => array( |
|
801 | + 'js' => 'M', |
|
802 | + 'moment' => 'MMM', |
|
803 | + ), |
|
804 | + //1-12 |
|
805 | + 'n' => array( |
|
806 | + 'js' => 'm', |
|
807 | + 'moment' => 'M', |
|
808 | + ), |
|
809 | + //number of days in given month |
|
810 | + 't' => array( |
|
811 | + 'js' => '', |
|
812 | + 'moment' => '', |
|
813 | + ), |
|
814 | + // Year |
|
815 | + //whether leap year or not 1/0 |
|
816 | + 'L' => array( |
|
817 | + 'js' => '', |
|
818 | + 'moment' => '', |
|
819 | + ), |
|
820 | + //ISO-8601 year number |
|
821 | + 'o' => array( |
|
822 | + 'js' => '', |
|
823 | + 'moment' => 'GGGG', |
|
824 | + ), |
|
825 | + //1999...2003 |
|
826 | + 'Y' => array( |
|
827 | + 'js' => 'yy', |
|
828 | + 'moment' => 'YYYY', |
|
829 | + ), |
|
830 | + //99...03 |
|
831 | + 'y' => array( |
|
832 | + 'js' => 'y', |
|
833 | + 'moment' => 'YY', |
|
834 | + ), |
|
835 | + // Time |
|
836 | + // am/pm |
|
837 | + 'a' => array( |
|
838 | + 'js' => 'tt', |
|
839 | + 'moment' => 'a', |
|
840 | + ), |
|
841 | + // AM/PM |
|
842 | + 'A' => array( |
|
843 | + 'js' => 'TT', |
|
844 | + 'moment' => 'A', |
|
845 | + ), |
|
846 | + // Swatch Internet Time?!? |
|
847 | + 'B' => array( |
|
848 | + 'js' => '', |
|
849 | + 'moment' => '', |
|
850 | + ), |
|
851 | + //1...12 |
|
852 | + 'g' => array( |
|
853 | + 'js' => 'h', |
|
854 | + 'moment' => 'h', |
|
855 | + ), |
|
856 | + //0...23 |
|
857 | + 'G' => array( |
|
858 | + 'js' => 'H', |
|
859 | + 'moment' => 'H', |
|
860 | + ), |
|
861 | + //01...12 |
|
862 | + 'h' => array( |
|
863 | + 'js' => 'hh', |
|
864 | + 'moment' => 'hh', |
|
865 | + ), |
|
866 | + //00...23 |
|
867 | + 'H' => array( |
|
868 | + 'js' => 'HH', |
|
869 | + 'moment' => 'HH', |
|
870 | + ), |
|
871 | + //00..59 |
|
872 | + 'i' => array( |
|
873 | + 'js' => 'mm', |
|
874 | + 'moment' => 'mm', |
|
875 | + ), |
|
876 | + //seconds... 00...59 |
|
877 | + 's' => array( |
|
878 | + 'js' => 'ss', |
|
879 | + 'moment' => 'ss', |
|
880 | + ), |
|
881 | + //microseconds |
|
882 | + 'u' => array( |
|
883 | + 'js' => '', |
|
884 | + 'moment' => '', |
|
885 | + ), |
|
886 | + ); |
|
887 | + $jquery_ui_format = ""; |
|
888 | + $moment_format = ""; |
|
889 | + $escaping = false; |
|
890 | + for ($i = 0; $i < strlen($format_string); $i++) { |
|
891 | + $char = $format_string[$i]; |
|
892 | + if ($char === '\\') { // PHP date format escaping character |
|
893 | + $i++; |
|
894 | + if ($escaping) { |
|
895 | + $jquery_ui_format .= $format_string[$i]; |
|
896 | + $moment_format .= $format_string[$i]; |
|
897 | + } else { |
|
898 | + $jquery_ui_format .= '\'' . $format_string[$i]; |
|
899 | + $moment_format .= $format_string[$i]; |
|
900 | + } |
|
901 | + $escaping = true; |
|
902 | + } else { |
|
903 | + if ($escaping) { |
|
904 | + $jquery_ui_format .= "'"; |
|
905 | + $moment_format .= "'"; |
|
906 | + $escaping = false; |
|
907 | + } |
|
908 | + if (isset($symbols_map[$char])) { |
|
909 | + $jquery_ui_format .= $symbols_map[$char]['js']; |
|
910 | + $moment_format .= $symbols_map[$char]['moment']; |
|
911 | + } else { |
|
912 | + $jquery_ui_format .= $char; |
|
913 | + $moment_format .= $char; |
|
914 | + } |
|
915 | + } |
|
916 | + } |
|
917 | + return array('js' => $jquery_ui_format, 'moment' => $moment_format); |
|
918 | + } |
|
919 | + |
|
920 | + |
|
921 | + /** |
|
922 | + * This takes an incoming format string and validates it to ensure it will work fine with PHP. |
|
923 | + * |
|
924 | + * @param string $format_string Incoming format string for php date(). |
|
925 | + * @return mixed bool|array If all is okay then TRUE is returned. Otherwise an array of validation |
|
926 | + * errors is returned. So for client code calling, check for is_array() to |
|
927 | + * indicate failed validations. |
|
928 | + */ |
|
929 | + public static function validate_format_string($format_string) |
|
930 | + { |
|
931 | + $error_msg = array(); |
|
932 | + //time format checks |
|
933 | + switch (true) { |
|
934 | + case strpos($format_string, 'h') !== false : |
|
935 | + case strpos($format_string, 'g') !== false : |
|
936 | + /** |
|
937 | + * if the time string has a lowercase 'h' which == 12 hour time format and there |
|
938 | + * is not any ante meridiem format ('a' or 'A'). Then throw an error because its |
|
939 | + * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am. |
|
940 | + */ |
|
941 | + if (strpos(strtoupper($format_string), 'A') === false) { |
|
942 | + $error_msg[] = __('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".', |
|
943 | + 'event_espresso'); |
|
944 | + } |
|
945 | + break; |
|
946 | + |
|
947 | + } |
|
948 | + |
|
949 | + return empty($error_msg) ? true : $error_msg; |
|
950 | + } |
|
951 | + |
|
952 | + |
|
953 | + /** |
|
954 | + * If the the first date starts at midnight on one day, and the next date ends at midnight on the |
|
955 | + * very next day then this method will return true. |
|
956 | + * If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true. |
|
957 | + * If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false. |
|
958 | + * If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true. |
|
959 | + * |
|
960 | + * @param mixed $date_1 |
|
961 | + * @param mixed $date_2 |
|
962 | + * @return bool |
|
963 | + */ |
|
964 | + public static function dates_represent_one_24_hour_date($date_1, $date_2) |
|
965 | + { |
|
966 | + |
|
967 | + if ( |
|
968 | + (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) || |
|
969 | + ($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00') |
|
970 | + ) { |
|
971 | + return false; |
|
972 | + } |
|
973 | + return $date_2->format('U') - $date_1->format('U') == 86400 ? true : false; |
|
974 | + } |
|
975 | + |
|
976 | + |
|
977 | + /** |
|
978 | + * This returns the appropriate query interval string that can be used in sql queries involving mysql Date |
|
979 | + * Functions. |
|
980 | + * |
|
981 | + * @param string $timezone_string A timezone string in a valid format to instantiate a DateTimeZone object. |
|
982 | + * @param string $field_for_interval The Database field that is the interval is applied to in the query. |
|
983 | + * @return string |
|
984 | + */ |
|
985 | + public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval) |
|
986 | + { |
|
987 | + try { |
|
988 | + /** need to account for timezone offset on the selects */ |
|
989 | + $DateTimeZone = new DateTimeZone($timezone_string); |
|
990 | + } catch (Exception $e) { |
|
991 | + $DateTimeZone = null; |
|
992 | + } |
|
993 | + |
|
994 | + /** |
|
995 | + * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds. |
|
996 | + * Hence we do the calc for DateTimeZone::getOffset. |
|
997 | + */ |
|
998 | + $offset = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset'); |
|
999 | + $query_interval = $offset < 0 |
|
1000 | + ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)' |
|
1001 | + : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)'; |
|
1002 | + return $query_interval; |
|
1003 | + } |
|
1004 | + |
|
1005 | + /** |
|
1006 | + * Retrieves the site's default timezone and returns it formatted so it's ready for display |
|
1007 | + * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string' |
|
1008 | + * and 'gmt_offset' WordPress options directly; or use the filter |
|
1009 | + * FHEE__EEH_DTT_Helper__get_timezone_string_for_display |
|
1010 | + * (although note that we remove any HTML that may be added) |
|
1011 | + * |
|
1012 | + * @return string |
|
1013 | + */ |
|
1014 | + public static function get_timezone_string_for_display() |
|
1015 | + { |
|
1016 | + $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', ''); |
|
1017 | + if (! empty($pretty_timezone)) { |
|
1018 | + return esc_html($pretty_timezone); |
|
1019 | + } |
|
1020 | + $timezone_string = get_option('timezone_string'); |
|
1021 | + if ($timezone_string) { |
|
1022 | + static $mo_loaded = false; |
|
1023 | + // Load translations for continents and cities just like wp_timezone_choice does |
|
1024 | + if (! $mo_loaded) { |
|
1025 | + $locale = get_locale(); |
|
1026 | + $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo'; |
|
1027 | + load_textdomain('continents-cities', $mofile); |
|
1028 | + $mo_loaded = true; |
|
1029 | + } |
|
1030 | + //well that was easy. |
|
1031 | + $parts = explode('/', $timezone_string); |
|
1032 | + //remove the continent |
|
1033 | + unset($parts[0]); |
|
1034 | + $t_parts = array(); |
|
1035 | + foreach ($parts as $part) { |
|
1036 | + $t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities'); |
|
1037 | + } |
|
1038 | + return implode(' - ', $t_parts); |
|
1039 | + } |
|
1040 | + //they haven't set the timezone string, so let's return a string like "UTC+1" |
|
1041 | + $gmt_offset = get_option('gmt_offset'); |
|
1042 | + if (intval($gmt_offset) >= 0) { |
|
1043 | + $prefix = '+'; |
|
1044 | + } else { |
|
1045 | + $prefix = ''; |
|
1046 | + } |
|
1047 | + $parts = explode('.', (string)$gmt_offset); |
|
1048 | + if (count($parts) === 1) { |
|
1049 | + $parts[1] = '00'; |
|
1050 | + } else { |
|
1051 | + //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25) |
|
1052 | + //to minutes, eg 30 or 15, respectively |
|
1053 | + $hour_fraction = (float)('0.' . $parts[1]); |
|
1054 | + $parts[1] = (string)$hour_fraction * 60; |
|
1055 | + } |
|
1056 | + return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts)); |
|
1057 | + } |
|
1058 | + |
|
1059 | + |
|
1060 | + |
|
1061 | + /** |
|
1062 | + * So PHP does this awesome thing where if you are trying to get a timestamp |
|
1063 | + * for a month using a string like "February" or "February 2017", |
|
1064 | + * and you don't specify a day as part of your string, |
|
1065 | + * then PHP will use whatever the current day of the month is. |
|
1066 | + * IF the current day of the month happens to be the 30th or 31st, |
|
1067 | + * then PHP gets really confused by a date like February 30, |
|
1068 | + * so instead of saying |
|
1069 | + * "Hey February only has 28 days (this year)... |
|
1070 | + * ...you must have meant the last day of the month!" |
|
1071 | + * PHP does the next most logical thing, and bumps the date up to March 2nd, |
|
1072 | + * because someone requesting February 30th obviously meant March 1st! |
|
1073 | + * The way around this is to always set the day to the first, |
|
1074 | + * so that the month will stay on the month you wanted. |
|
1075 | + * this method will add that "1" into your date regardless of the format. |
|
1076 | + * |
|
1077 | + * @param string $month |
|
1078 | + * @return string |
|
1079 | + */ |
|
1080 | + public static function first_of_month_timestamp($month = '') |
|
1081 | + { |
|
1082 | + $month = (string)$month; |
|
1083 | + $year = ''; |
|
1084 | + // check if the incoming string has a year in it or not |
|
1085 | + if (preg_match('/\b\d{4}\b/', $month, $matches)) { |
|
1086 | + $year = $matches[0]; |
|
1087 | + // ten remove that from the month string as well as any spaces |
|
1088 | + $month = trim(str_replace($year, '', $month)); |
|
1089 | + // add a space before the year |
|
1090 | + $year = " {$year}"; |
|
1091 | + } |
|
1092 | + // return timestamp for something like "February 1 2017" |
|
1093 | + return strtotime("{$month} 1{$year}"); |
|
1094 | + } |
|
1095 | + |
|
1096 | + /** |
|
1097 | + * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone. So it may be midnight |
|
1098 | + * for this sites timezone, but the timestamp could be some other time GMT. |
|
1099 | + */ |
|
1100 | + public static function tomorrow() |
|
1101 | 1101 | { |
1102 | 1102 | //The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive |
1103 | 1103 | //before adding to the timestamp. Why? Because we want tomorrow to be for midnight the next day in THIS timezone |
@@ -1107,135 +1107,135 @@ discard block |
||
1107 | 1107 | } |
1108 | 1108 | |
1109 | 1109 | |
1110 | - /** |
|
1111 | - * ** |
|
1112 | - * Gives a nicely-formatted list of timezone strings. |
|
1113 | - * Copied from the core wp function by the same name so we could customize to remove UTC offsets. |
|
1114 | - * |
|
1115 | - * @since 4.9.40.rc.008 |
|
1116 | - * @staticvar bool $mo_loaded |
|
1117 | - * @staticvar string $locale_loaded |
|
1118 | - * @param string $selected_zone Selected timezone. |
|
1119 | - * @param string $locale Optional. Locale to load the timezones in. Default current site locale. |
|
1120 | - * @return string |
|
1121 | - */ |
|
1122 | - public static function wp_timezone_choice($selected_zone, $locale = null) |
|
1123 | - { |
|
1124 | - static $mo_loaded = false, $locale_loaded = null; |
|
1125 | - |
|
1126 | - $continents = array( |
|
1127 | - 'Africa', |
|
1128 | - 'America', |
|
1129 | - 'Antarctica', |
|
1130 | - 'Arctic', |
|
1131 | - 'Asia', |
|
1132 | - 'Atlantic', |
|
1133 | - 'Australia', |
|
1134 | - 'Europe', |
|
1135 | - 'Indian', |
|
1136 | - 'Pacific', |
|
1137 | - ); |
|
1138 | - |
|
1139 | - // Load translations for continents and cities. |
|
1140 | - if (! $mo_loaded || $locale !== $locale_loaded) { |
|
1141 | - $locale_loaded = $locale ? $locale : get_locale(); |
|
1142 | - $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo'; |
|
1143 | - unload_textdomain('continents-cities'); |
|
1144 | - load_textdomain('continents-cities', $mofile); |
|
1145 | - $mo_loaded = true; |
|
1146 | - } |
|
1147 | - |
|
1148 | - $zonen = array(); |
|
1149 | - foreach (timezone_identifiers_list() as $zone) { |
|
1150 | - $zone = explode('/', $zone); |
|
1151 | - if (! in_array($zone[0], $continents)) { |
|
1152 | - continue; |
|
1153 | - } |
|
1154 | - |
|
1155 | - // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later |
|
1156 | - $exists = array( |
|
1157 | - 0 => (isset($zone[0]) && $zone[0]), |
|
1158 | - 1 => (isset($zone[1]) && $zone[1]), |
|
1159 | - 2 => (isset($zone[2]) && $zone[2]), |
|
1160 | - ); |
|
1161 | - $exists[3] = ($exists[0] && 'Etc' !== $zone[0]); |
|
1162 | - $exists[4] = ($exists[1] && $exists[3]); |
|
1163 | - $exists[5] = ($exists[2] && $exists[3]); |
|
1164 | - |
|
1165 | - $zonen[] = array( |
|
1166 | - 'continent' => ($exists[0] ? $zone[0] : ''), |
|
1167 | - 'city' => ($exists[1] ? $zone[1] : ''), |
|
1168 | - 'subcity' => ($exists[2] ? $zone[2] : ''), |
|
1169 | - 't_continent' => ($exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : ''), |
|
1170 | - 't_city' => ($exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : ''), |
|
1171 | - 't_subcity' => ($exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : ''), |
|
1172 | - ); |
|
1173 | - } |
|
1174 | - usort($zonen, '_wp_timezone_choice_usort_callback'); |
|
1175 | - |
|
1176 | - $structure = array(); |
|
1177 | - |
|
1178 | - if (empty($selected_zone)) { |
|
1179 | - $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>'; |
|
1180 | - } |
|
1181 | - |
|
1182 | - foreach ($zonen as $key => $zone) { |
|
1183 | - // Build value in an array to join later |
|
1184 | - $value = array($zone['continent']); |
|
1185 | - |
|
1186 | - if (empty($zone['city'])) { |
|
1187 | - // It's at the continent level (generally won't happen) |
|
1188 | - $display = $zone['t_continent']; |
|
1189 | - } else { |
|
1190 | - // It's inside a continent group |
|
1191 | - |
|
1192 | - // Continent optgroup |
|
1193 | - if (! isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) { |
|
1194 | - $label = $zone['t_continent']; |
|
1195 | - $structure[] = '<optgroup label="' . esc_attr($label) . '">'; |
|
1196 | - } |
|
1197 | - |
|
1198 | - // Add the city to the value |
|
1199 | - $value[] = $zone['city']; |
|
1200 | - |
|
1201 | - $display = $zone['t_city']; |
|
1202 | - if (! empty($zone['subcity'])) { |
|
1203 | - // Add the subcity to the value |
|
1204 | - $value[] = $zone['subcity']; |
|
1205 | - $display .= ' - ' . $zone['t_subcity']; |
|
1206 | - } |
|
1207 | - } |
|
1208 | - |
|
1209 | - // Build the value |
|
1210 | - $value = join('/', $value); |
|
1211 | - $selected = ''; |
|
1212 | - if ($value === $selected_zone) { |
|
1213 | - $selected = 'selected="selected" '; |
|
1214 | - } |
|
1215 | - $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>"; |
|
1216 | - |
|
1217 | - // Close continent optgroup |
|
1218 | - if (! empty($zone['city']) && (! isset($zonen[$key + 1]) || (isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent']))) { |
|
1219 | - $structure[] = '</optgroup>'; |
|
1220 | - } |
|
1221 | - } |
|
1222 | - |
|
1223 | - return join("\n", $structure); |
|
1224 | - } |
|
1225 | - |
|
1226 | - |
|
1227 | - /** |
|
1228 | - * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0 |
|
1229 | - * |
|
1230 | - * @param int|WP_User $user_id |
|
1231 | - * @return string |
|
1232 | - */ |
|
1233 | - public static function get_user_locale($user_id = 0) |
|
1234 | - { |
|
1235 | - if (function_exists('get_user_locale')) { |
|
1236 | - return get_user_locale($user_id); |
|
1237 | - } |
|
1238 | - return get_locale(); |
|
1239 | - } |
|
1110 | + /** |
|
1111 | + * ** |
|
1112 | + * Gives a nicely-formatted list of timezone strings. |
|
1113 | + * Copied from the core wp function by the same name so we could customize to remove UTC offsets. |
|
1114 | + * |
|
1115 | + * @since 4.9.40.rc.008 |
|
1116 | + * @staticvar bool $mo_loaded |
|
1117 | + * @staticvar string $locale_loaded |
|
1118 | + * @param string $selected_zone Selected timezone. |
|
1119 | + * @param string $locale Optional. Locale to load the timezones in. Default current site locale. |
|
1120 | + * @return string |
|
1121 | + */ |
|
1122 | + public static function wp_timezone_choice($selected_zone, $locale = null) |
|
1123 | + { |
|
1124 | + static $mo_loaded = false, $locale_loaded = null; |
|
1125 | + |
|
1126 | + $continents = array( |
|
1127 | + 'Africa', |
|
1128 | + 'America', |
|
1129 | + 'Antarctica', |
|
1130 | + 'Arctic', |
|
1131 | + 'Asia', |
|
1132 | + 'Atlantic', |
|
1133 | + 'Australia', |
|
1134 | + 'Europe', |
|
1135 | + 'Indian', |
|
1136 | + 'Pacific', |
|
1137 | + ); |
|
1138 | + |
|
1139 | + // Load translations for continents and cities. |
|
1140 | + if (! $mo_loaded || $locale !== $locale_loaded) { |
|
1141 | + $locale_loaded = $locale ? $locale : get_locale(); |
|
1142 | + $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo'; |
|
1143 | + unload_textdomain('continents-cities'); |
|
1144 | + load_textdomain('continents-cities', $mofile); |
|
1145 | + $mo_loaded = true; |
|
1146 | + } |
|
1147 | + |
|
1148 | + $zonen = array(); |
|
1149 | + foreach (timezone_identifiers_list() as $zone) { |
|
1150 | + $zone = explode('/', $zone); |
|
1151 | + if (! in_array($zone[0], $continents)) { |
|
1152 | + continue; |
|
1153 | + } |
|
1154 | + |
|
1155 | + // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later |
|
1156 | + $exists = array( |
|
1157 | + 0 => (isset($zone[0]) && $zone[0]), |
|
1158 | + 1 => (isset($zone[1]) && $zone[1]), |
|
1159 | + 2 => (isset($zone[2]) && $zone[2]), |
|
1160 | + ); |
|
1161 | + $exists[3] = ($exists[0] && 'Etc' !== $zone[0]); |
|
1162 | + $exists[4] = ($exists[1] && $exists[3]); |
|
1163 | + $exists[5] = ($exists[2] && $exists[3]); |
|
1164 | + |
|
1165 | + $zonen[] = array( |
|
1166 | + 'continent' => ($exists[0] ? $zone[0] : ''), |
|
1167 | + 'city' => ($exists[1] ? $zone[1] : ''), |
|
1168 | + 'subcity' => ($exists[2] ? $zone[2] : ''), |
|
1169 | + 't_continent' => ($exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : ''), |
|
1170 | + 't_city' => ($exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : ''), |
|
1171 | + 't_subcity' => ($exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : ''), |
|
1172 | + ); |
|
1173 | + } |
|
1174 | + usort($zonen, '_wp_timezone_choice_usort_callback'); |
|
1175 | + |
|
1176 | + $structure = array(); |
|
1177 | + |
|
1178 | + if (empty($selected_zone)) { |
|
1179 | + $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>'; |
|
1180 | + } |
|
1181 | + |
|
1182 | + foreach ($zonen as $key => $zone) { |
|
1183 | + // Build value in an array to join later |
|
1184 | + $value = array($zone['continent']); |
|
1185 | + |
|
1186 | + if (empty($zone['city'])) { |
|
1187 | + // It's at the continent level (generally won't happen) |
|
1188 | + $display = $zone['t_continent']; |
|
1189 | + } else { |
|
1190 | + // It's inside a continent group |
|
1191 | + |
|
1192 | + // Continent optgroup |
|
1193 | + if (! isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) { |
|
1194 | + $label = $zone['t_continent']; |
|
1195 | + $structure[] = '<optgroup label="' . esc_attr($label) . '">'; |
|
1196 | + } |
|
1197 | + |
|
1198 | + // Add the city to the value |
|
1199 | + $value[] = $zone['city']; |
|
1200 | + |
|
1201 | + $display = $zone['t_city']; |
|
1202 | + if (! empty($zone['subcity'])) { |
|
1203 | + // Add the subcity to the value |
|
1204 | + $value[] = $zone['subcity']; |
|
1205 | + $display .= ' - ' . $zone['t_subcity']; |
|
1206 | + } |
|
1207 | + } |
|
1208 | + |
|
1209 | + // Build the value |
|
1210 | + $value = join('/', $value); |
|
1211 | + $selected = ''; |
|
1212 | + if ($value === $selected_zone) { |
|
1213 | + $selected = 'selected="selected" '; |
|
1214 | + } |
|
1215 | + $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>"; |
|
1216 | + |
|
1217 | + // Close continent optgroup |
|
1218 | + if (! empty($zone['city']) && (! isset($zonen[$key + 1]) || (isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent']))) { |
|
1219 | + $structure[] = '</optgroup>'; |
|
1220 | + } |
|
1221 | + } |
|
1222 | + |
|
1223 | + return join("\n", $structure); |
|
1224 | + } |
|
1225 | + |
|
1226 | + |
|
1227 | + /** |
|
1228 | + * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0 |
|
1229 | + * |
|
1230 | + * @param int|WP_User $user_id |
|
1231 | + * @return string |
|
1232 | + */ |
|
1233 | + public static function get_user_locale($user_id = 0) |
|
1234 | + { |
|
1235 | + if (function_exists('get_user_locale')) { |
|
1236 | + return get_user_locale($user_id); |
|
1237 | + } |
|
1238 | + return get_locale(); |
|
1239 | + } |
|
1240 | 1240 | |
1241 | 1241 | }// end class EEH_DTT_Helper |
@@ -1,5 +1,5 @@ discard block |
||
1 | 1 | <?php |
2 | -if (! defined('EVENT_ESPRESSO_VERSION')) { |
|
2 | +if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
|
3 | 3 | exit('NO direct script access allowed'); |
4 | 4 | } |
5 | 5 | |
@@ -74,7 +74,7 @@ discard block |
||
74 | 74 | new DateTimeZone($timezone_string); |
75 | 75 | } catch (Exception $e) { |
76 | 76 | // sometimes we take exception to exceptions |
77 | - if (! $throw_error) { |
|
77 | + if ( ! $throw_error) { |
|
78 | 78 | return false; |
79 | 79 | } |
80 | 80 | throw new EE_Error( |
@@ -159,7 +159,7 @@ discard block |
||
159 | 159 | } |
160 | 160 | } |
161 | 161 | $offset = get_option('gmt_offset'); |
162 | - return (int)($offset * HOUR_IN_SECONDS); |
|
162 | + return (int) ($offset * HOUR_IN_SECONDS); |
|
163 | 163 | } |
164 | 164 | |
165 | 165 | |
@@ -177,7 +177,7 @@ discard block |
||
177 | 177 | public static function adjust_invalid_gmt_offsets($gmt_offset = 0) |
178 | 178 | { |
179 | 179 | //make sure $gmt_offset is int |
180 | - $gmt_offset = (int)$gmt_offset; |
|
180 | + $gmt_offset = (int) $gmt_offset; |
|
181 | 181 | switch ($gmt_offset) { |
182 | 182 | //-12 |
183 | 183 | case -43200: |
@@ -350,7 +350,7 @@ discard block |
||
350 | 350 | public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null) |
351 | 351 | { |
352 | 352 | $transitions = self::get_timezone_transitions($date_time_zone, $time); |
353 | - if (! isset($transitions['offset'])) { |
|
353 | + if ( ! isset($transitions['offset'])) { |
|
354 | 354 | throw new DomainException(); |
355 | 355 | } |
356 | 356 | return $transitions['offset']; |
@@ -364,7 +364,7 @@ discard block |
||
364 | 364 | public static function timezone_select_input($timezone_string = '') |
365 | 365 | { |
366 | 366 | // get WP date time format |
367 | - $datetime_format = get_option('date_format') . ' ' . get_option('time_format'); |
|
367 | + $datetime_format = get_option('date_format').' '.get_option('time_format'); |
|
368 | 368 | // if passed a value, then use that, else get WP option |
369 | 369 | $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string'); |
370 | 370 | // check if the timezone is valid but don't throw any errors if it isn't |
@@ -376,9 +376,9 @@ discard block |
||
376 | 376 | // Create a UTC+- zone if no timezone string exists |
377 | 377 | $check_zone_info = false; |
378 | 378 | if ($gmt_offset > 0) { |
379 | - $timezone_string = 'UTC+' . $gmt_offset; |
|
379 | + $timezone_string = 'UTC+'.$gmt_offset; |
|
380 | 380 | } elseif ($gmt_offset < 0) { |
381 | - $timezone_string = 'UTC' . $gmt_offset; |
|
381 | + $timezone_string = 'UTC'.$gmt_offset; |
|
382 | 382 | } else { |
383 | 383 | $timezone_string = 'UTC'; |
384 | 384 | } |
@@ -400,11 +400,11 @@ discard block |
||
400 | 400 | __('%1$sUTC%2$s time is %3$s'), |
401 | 401 | '<abbr title="Coordinated Universal Time">', |
402 | 402 | '</abbr>', |
403 | - '<code>' . date_i18n($datetime_format, false, true) . '</code>' |
|
403 | + '<code>'.date_i18n($datetime_format, false, true).'</code>' |
|
404 | 404 | ); |
405 | 405 | ?></span> |
406 | - <?php if (! empty($timezone_string) || ! empty($gmt_offset)) : ?> |
|
407 | - <br/><span><?php printf(__('Local time is %1$s'), '<code>' . date_i18n($datetime_format) . '</code>'); ?></span> |
|
406 | + <?php if ( ! empty($timezone_string) || ! empty($gmt_offset)) : ?> |
|
407 | + <br/><span><?php printf(__('Local time is %1$s'), '<code>'.date_i18n($datetime_format).'</code>'); ?></span> |
|
408 | 408 | <?php endif; ?> |
409 | 409 | |
410 | 410 | <?php if ($check_zone_info && $timezone_string) : ?> |
@@ -437,11 +437,10 @@ discard block |
||
437 | 437 | |
438 | 438 | if ($found) { |
439 | 439 | $message = $tr['isdst'] ? |
440 | - __(' Daylight saving time begins on: %s.') : |
|
441 | - __(' Standard time begins on: %s.'); |
|
440 | + __(' Daylight saving time begins on: %s.') : __(' Standard time begins on: %s.'); |
|
442 | 441 | // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n(). |
443 | 442 | printf($message, |
444 | - '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >'); |
|
443 | + '<code >'.date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])).'</code >'); |
|
445 | 444 | } else { |
446 | 445 | _e('This timezone does not observe daylight saving time.'); |
447 | 446 | } |
@@ -469,13 +468,13 @@ discard block |
||
469 | 468 | */ |
470 | 469 | public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '') |
471 | 470 | { |
472 | - $unix_timestamp = $unix_timestamp === 0 ? time() : (int)$unix_timestamp; |
|
471 | + $unix_timestamp = $unix_timestamp === 0 ? time() : (int) $unix_timestamp; |
|
473 | 472 | $timezone_string = self::get_valid_timezone_string($timezone_string); |
474 | 473 | $TimeZone = new DateTimeZone($timezone_string); |
475 | 474 | |
476 | - $DateTime = new DateTime('@' . $unix_timestamp, $TimeZone); |
|
475 | + $DateTime = new DateTime('@'.$unix_timestamp, $TimeZone); |
|
477 | 476 | $offset = timezone_offset_get($TimeZone, $DateTime); |
478 | - return (int)$DateTime->format('U') + (int)$offset; |
|
477 | + return (int) $DateTime->format('U') + (int) $offset; |
|
479 | 478 | } |
480 | 479 | |
481 | 480 | |
@@ -558,7 +557,7 @@ discard block |
||
558 | 557 | */ |
559 | 558 | protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+') |
560 | 559 | { |
561 | - if (! $DateTime instanceof DateTime) { |
|
560 | + if ( ! $DateTime instanceof DateTime) { |
|
562 | 561 | throw new EE_Error( |
563 | 562 | sprintf( |
564 | 563 | __('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'), |
@@ -568,25 +567,25 @@ discard block |
||
568 | 567 | } |
569 | 568 | switch ($period) { |
570 | 569 | case 'years' : |
571 | - $value = 'P' . $value . 'Y'; |
|
570 | + $value = 'P'.$value.'Y'; |
|
572 | 571 | break; |
573 | 572 | case 'months' : |
574 | - $value = 'P' . $value . 'M'; |
|
573 | + $value = 'P'.$value.'M'; |
|
575 | 574 | break; |
576 | 575 | case 'weeks' : |
577 | - $value = 'P' . $value . 'W'; |
|
576 | + $value = 'P'.$value.'W'; |
|
578 | 577 | break; |
579 | 578 | case 'days' : |
580 | - $value = 'P' . $value . 'D'; |
|
579 | + $value = 'P'.$value.'D'; |
|
581 | 580 | break; |
582 | 581 | case 'hours' : |
583 | - $value = 'PT' . $value . 'H'; |
|
582 | + $value = 'PT'.$value.'H'; |
|
584 | 583 | break; |
585 | 584 | case 'minutes' : |
586 | - $value = 'PT' . $value . 'M'; |
|
585 | + $value = 'PT'.$value.'M'; |
|
587 | 586 | break; |
588 | 587 | case 'seconds' : |
589 | - $value = 'PT' . $value . 'S'; |
|
588 | + $value = 'PT'.$value.'S'; |
|
590 | 589 | break; |
591 | 590 | } |
592 | 591 | switch ($operand) { |
@@ -614,7 +613,7 @@ discard block |
||
614 | 613 | */ |
615 | 614 | protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+') |
616 | 615 | { |
617 | - if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) { |
|
616 | + if ( ! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) { |
|
618 | 617 | throw new EE_Error( |
619 | 618 | sprintf( |
620 | 619 | __('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'), |
@@ -718,7 +717,7 @@ discard block |
||
718 | 717 | 'date' => $date_format['js'], |
719 | 718 | 'time' => $time_format['js'], |
720 | 719 | ), |
721 | - 'moment' => $date_format['moment'] . ' ' . $time_format['moment'], |
|
720 | + 'moment' => $date_format['moment'].' '.$time_format['moment'], |
|
722 | 721 | ); |
723 | 722 | } |
724 | 723 | |
@@ -737,7 +736,7 @@ discard block |
||
737 | 736 | * |
738 | 737 | * @var array |
739 | 738 | */ |
740 | - $symbols_map = array( |
|
739 | + $symbols_map = array( |
|
741 | 740 | // Day |
742 | 741 | //01 |
743 | 742 | 'd' => array( |
@@ -895,7 +894,7 @@ discard block |
||
895 | 894 | $jquery_ui_format .= $format_string[$i]; |
896 | 895 | $moment_format .= $format_string[$i]; |
897 | 896 | } else { |
898 | - $jquery_ui_format .= '\'' . $format_string[$i]; |
|
897 | + $jquery_ui_format .= '\''.$format_string[$i]; |
|
899 | 898 | $moment_format .= $format_string[$i]; |
900 | 899 | } |
901 | 900 | $escaping = true; |
@@ -965,7 +964,7 @@ discard block |
||
965 | 964 | { |
966 | 965 | |
967 | 966 | if ( |
968 | - (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) || |
|
967 | + ( ! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) || |
|
969 | 968 | ($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00') |
970 | 969 | ) { |
971 | 970 | return false; |
@@ -997,8 +996,8 @@ discard block |
||
997 | 996 | */ |
998 | 997 | $offset = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset'); |
999 | 998 | $query_interval = $offset < 0 |
1000 | - ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)' |
|
1001 | - : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)'; |
|
999 | + ? 'DATE_SUB('.$field_for_interval.', INTERVAL '.$offset * -1.' HOUR)' |
|
1000 | + : 'DATE_ADD('.$field_for_interval.', INTERVAL '.$offset.' HOUR)'; |
|
1002 | 1001 | return $query_interval; |
1003 | 1002 | } |
1004 | 1003 | |
@@ -1014,16 +1013,16 @@ discard block |
||
1014 | 1013 | public static function get_timezone_string_for_display() |
1015 | 1014 | { |
1016 | 1015 | $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', ''); |
1017 | - if (! empty($pretty_timezone)) { |
|
1016 | + if ( ! empty($pretty_timezone)) { |
|
1018 | 1017 | return esc_html($pretty_timezone); |
1019 | 1018 | } |
1020 | 1019 | $timezone_string = get_option('timezone_string'); |
1021 | 1020 | if ($timezone_string) { |
1022 | 1021 | static $mo_loaded = false; |
1023 | 1022 | // Load translations for continents and cities just like wp_timezone_choice does |
1024 | - if (! $mo_loaded) { |
|
1023 | + if ( ! $mo_loaded) { |
|
1025 | 1024 | $locale = get_locale(); |
1026 | - $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo'; |
|
1025 | + $mofile = WP_LANG_DIR.'/continents-cities-'.$locale.'.mo'; |
|
1027 | 1026 | load_textdomain('continents-cities', $mofile); |
1028 | 1027 | $mo_loaded = true; |
1029 | 1028 | } |
@@ -1044,16 +1043,16 @@ discard block |
||
1044 | 1043 | } else { |
1045 | 1044 | $prefix = ''; |
1046 | 1045 | } |
1047 | - $parts = explode('.', (string)$gmt_offset); |
|
1046 | + $parts = explode('.', (string) $gmt_offset); |
|
1048 | 1047 | if (count($parts) === 1) { |
1049 | 1048 | $parts[1] = '00'; |
1050 | 1049 | } else { |
1051 | 1050 | //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25) |
1052 | 1051 | //to minutes, eg 30 or 15, respectively |
1053 | - $hour_fraction = (float)('0.' . $parts[1]); |
|
1054 | - $parts[1] = (string)$hour_fraction * 60; |
|
1052 | + $hour_fraction = (float) ('0.'.$parts[1]); |
|
1053 | + $parts[1] = (string) $hour_fraction * 60; |
|
1055 | 1054 | } |
1056 | - return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts)); |
|
1055 | + return sprintf(__('UTC%1$s', 'event_espresso'), $prefix.implode(':', $parts)); |
|
1057 | 1056 | } |
1058 | 1057 | |
1059 | 1058 | |
@@ -1079,7 +1078,7 @@ discard block |
||
1079 | 1078 | */ |
1080 | 1079 | public static function first_of_month_timestamp($month = '') |
1081 | 1080 | { |
1082 | - $month = (string)$month; |
|
1081 | + $month = (string) $month; |
|
1083 | 1082 | $year = ''; |
1084 | 1083 | // check if the incoming string has a year in it or not |
1085 | 1084 | if (preg_match('/\b\d{4}\b/', $month, $matches)) { |
@@ -1103,7 +1102,7 @@ discard block |
||
1103 | 1102 | //before adding to the timestamp. Why? Because we want tomorrow to be for midnight the next day in THIS timezone |
1104 | 1103 | //not an offset from midnight in UTC. So if we're starting with UTC 00:00:00, then we want to make sure the |
1105 | 1104 | //final timestamp is equivalent to midnight in this timezone as represented in GMT. |
1106 | - return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset()*-1); |
|
1105 | + return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1); |
|
1107 | 1106 | } |
1108 | 1107 | |
1109 | 1108 | |
@@ -1137,9 +1136,9 @@ discard block |
||
1137 | 1136 | ); |
1138 | 1137 | |
1139 | 1138 | // Load translations for continents and cities. |
1140 | - if (! $mo_loaded || $locale !== $locale_loaded) { |
|
1139 | + if ( ! $mo_loaded || $locale !== $locale_loaded) { |
|
1141 | 1140 | $locale_loaded = $locale ? $locale : get_locale(); |
1142 | - $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo'; |
|
1141 | + $mofile = WP_LANG_DIR.'/continents-cities-'.$locale_loaded.'.mo'; |
|
1143 | 1142 | unload_textdomain('continents-cities'); |
1144 | 1143 | load_textdomain('continents-cities', $mofile); |
1145 | 1144 | $mo_loaded = true; |
@@ -1148,12 +1147,12 @@ discard block |
||
1148 | 1147 | $zonen = array(); |
1149 | 1148 | foreach (timezone_identifiers_list() as $zone) { |
1150 | 1149 | $zone = explode('/', $zone); |
1151 | - if (! in_array($zone[0], $continents)) { |
|
1150 | + if ( ! in_array($zone[0], $continents)) { |
|
1152 | 1151 | continue; |
1153 | 1152 | } |
1154 | 1153 | |
1155 | 1154 | // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later |
1156 | - $exists = array( |
|
1155 | + $exists = array( |
|
1157 | 1156 | 0 => (isset($zone[0]) && $zone[0]), |
1158 | 1157 | 1 => (isset($zone[1]) && $zone[1]), |
1159 | 1158 | 2 => (isset($zone[2]) && $zone[2]), |
@@ -1176,7 +1175,7 @@ discard block |
||
1176 | 1175 | $structure = array(); |
1177 | 1176 | |
1178 | 1177 | if (empty($selected_zone)) { |
1179 | - $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>'; |
|
1178 | + $structure[] = '<option selected="selected" value="">'.__('Select a city').'</option>'; |
|
1180 | 1179 | } |
1181 | 1180 | |
1182 | 1181 | foreach ($zonen as $key => $zone) { |
@@ -1190,19 +1189,19 @@ discard block |
||
1190 | 1189 | // It's inside a continent group |
1191 | 1190 | |
1192 | 1191 | // Continent optgroup |
1193 | - if (! isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) { |
|
1192 | + if ( ! isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) { |
|
1194 | 1193 | $label = $zone['t_continent']; |
1195 | - $structure[] = '<optgroup label="' . esc_attr($label) . '">'; |
|
1194 | + $structure[] = '<optgroup label="'.esc_attr($label).'">'; |
|
1196 | 1195 | } |
1197 | 1196 | |
1198 | 1197 | // Add the city to the value |
1199 | 1198 | $value[] = $zone['city']; |
1200 | 1199 | |
1201 | 1200 | $display = $zone['t_city']; |
1202 | - if (! empty($zone['subcity'])) { |
|
1201 | + if ( ! empty($zone['subcity'])) { |
|
1203 | 1202 | // Add the subcity to the value |
1204 | 1203 | $value[] = $zone['subcity']; |
1205 | - $display .= ' - ' . $zone['t_subcity']; |
|
1204 | + $display .= ' - '.$zone['t_subcity']; |
|
1206 | 1205 | } |
1207 | 1206 | } |
1208 | 1207 | |
@@ -1212,10 +1211,10 @@ discard block |
||
1212 | 1211 | if ($value === $selected_zone) { |
1213 | 1212 | $selected = 'selected="selected" '; |
1214 | 1213 | } |
1215 | - $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>"; |
|
1214 | + $structure[] = '<option '.$selected.'value="'.esc_attr($value).'">'.esc_html($display)."</option>"; |
|
1216 | 1215 | |
1217 | 1216 | // Close continent optgroup |
1218 | - if (! empty($zone['city']) && (! isset($zonen[$key + 1]) || (isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent']))) { |
|
1217 | + if ( ! empty($zone['city']) && ( ! isset($zonen[$key + 1]) || (isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent']))) { |
|
1219 | 1218 | $structure[] = '</optgroup>'; |
1220 | 1219 | } |
1221 | 1220 | } |
@@ -135,11 +135,11 @@ discard block |
||
135 | 135 | |
136 | 136 | |
137 | 137 | |
138 | - /** |
|
139 | - * _setup_data |
|
140 | - * |
|
141 | - * @throws EE_Error |
|
142 | - */ |
|
138 | + /** |
|
139 | + * _setup_data |
|
140 | + * |
|
141 | + * @throws EE_Error |
|
142 | + */ |
|
143 | 143 | protected function _setup_data() { |
144 | 144 | |
145 | 145 | $this->reg_info = array(); |
@@ -157,7 +157,7 @@ discard block |
||
157 | 157 | $this->ip_address = isset( $session_data['ip_address'] ) ? $session_data['ip_address'] : ''; |
158 | 158 | $this->user_agent = isset( $session_data['user_agent'] ) ? $session_data['user_agent'] : ''; |
159 | 159 | $this->init_access = $this->last_access = ''; |
160 | - //get all non-trashed registrations |
|
160 | + //get all non-trashed registrations |
|
161 | 161 | $this->reg_objs = $this->txn->registrations(array(array('REG_deleted' => false))); |
162 | 162 | $this->_assemble_data(); |
163 | 163 |
@@ -1,6 +1,6 @@ discard block |
||
1 | 1 | <?php |
2 | 2 | |
3 | -if (!defined('EVENT_ESPRESSO_VERSION') ) |
|
3 | +if ( ! defined('EVENT_ESPRESSO_VERSION')) |
|
4 | 4 | exit('NO direct script access allowed'); |
5 | 5 | |
6 | 6 | /** |
@@ -44,25 +44,25 @@ discard block |
||
44 | 44 | * @param array $data |
45 | 45 | * @throws EE_Error |
46 | 46 | */ |
47 | - public function __construct( $data ) { |
|
47 | + public function __construct($data) { |
|
48 | 48 | |
49 | 49 | //test for valid params |
50 | - if ( ! ( $data[0] instanceof EE_Transaction )) |
|
51 | - throw new EE_Error( __('Incoming data for the Gateways data handler must have an EE_Transaction object as the value for the first array index.', 'event_espresso') ); |
|
50 | + if ( ! ($data[0] instanceof EE_Transaction)) |
|
51 | + throw new EE_Error(__('Incoming data for the Gateways data handler must have an EE_Transaction object as the value for the first array index.', 'event_espresso')); |
|
52 | 52 | |
53 | - if ( empty( $data[1] ) || ! $data[1] instanceof EE_Payment ) |
|
54 | - $pmt_obj = $this->_get_empty_payment_obj( $data[0] ); |
|
53 | + if (empty($data[1]) || ! $data[1] instanceof EE_Payment) |
|
54 | + $pmt_obj = $this->_get_empty_payment_obj($data[0]); |
|
55 | 55 | |
56 | - if ( ! empty( $data[2] ) ) { |
|
56 | + if ( ! empty($data[2])) { |
|
57 | 57 | $filtered_reg_status = $data[2]; |
58 | 58 | } |
59 | 59 | |
60 | 60 | $data = array( |
61 | 61 | 'txn_obj' => $data[0], |
62 | 62 | 'pmt_obj' => isset($pmt_obj) ? $pmt_obj : $data[1], |
63 | - 'filtered_reg_status' => isset( $filtered_reg_status ) ? $filtered_reg_status : null |
|
63 | + 'filtered_reg_status' => isset($filtered_reg_status) ? $filtered_reg_status : null |
|
64 | 64 | ); |
65 | - parent::__construct( $data ); |
|
65 | + parent::__construct($data); |
|
66 | 66 | } |
67 | 67 | |
68 | 68 | |
@@ -76,18 +76,18 @@ discard block |
||
76 | 76 | * |
77 | 77 | * @return array The prepped data for db |
78 | 78 | */ |
79 | - static public function convert_data_for_persistent_storage( $data ) { |
|
79 | + static public function convert_data_for_persistent_storage($data) { |
|
80 | 80 | $prepped_data = array(); |
81 | 81 | |
82 | - if ( $data[0] instanceof EE_Transaction ) { |
|
82 | + if ($data[0] instanceof EE_Transaction) { |
|
83 | 83 | $prepped_data['Transaction'] = $data[0]->ID(); |
84 | 84 | } |
85 | 85 | |
86 | - if ( isset( $data[1] ) && $data[1] instanceof EE_Payment ) { |
|
86 | + if (isset($data[1]) && $data[1] instanceof EE_Payment) { |
|
87 | 87 | $prepped_data['Payment'] = $data[1]->ID(); |
88 | 88 | } |
89 | 89 | |
90 | - if ( ! empty( $data[2] ) ) { |
|
90 | + if ( ! empty($data[2])) { |
|
91 | 91 | $prepped_data['filter'] = $data[2]; |
92 | 92 | } |
93 | 93 | |
@@ -107,11 +107,11 @@ discard block |
||
107 | 107 | * |
108 | 108 | * @return array |
109 | 109 | */ |
110 | - static public function convert_data_from_persistent_storage( $data ) { |
|
110 | + static public function convert_data_from_persistent_storage($data) { |
|
111 | 111 | $prepped_data = array( |
112 | - 0 => isset( $data['Transaction'] ) ? EEM_Transaction::instance()->get_one_by_ID( $data['Transaction'] ) : null, |
|
113 | - 1 => isset( $data['Payment'] ) ? EEM_Payment::instance()->get_one_by_ID( $data['Payment'] ) : null, |
|
114 | - 2 => isset( $data['filter'] ) ? $data['filter'] : null |
|
112 | + 0 => isset($data['Transaction']) ? EEM_Transaction::instance()->get_one_by_ID($data['Transaction']) : null, |
|
113 | + 1 => isset($data['Payment']) ? EEM_Payment::instance()->get_one_by_ID($data['Payment']) : null, |
|
114 | + 2 => isset($data['filter']) ? $data['filter'] : null |
|
115 | 115 | ); |
116 | 116 | return $prepped_data; |
117 | 117 | } |
@@ -122,8 +122,8 @@ discard block |
||
122 | 122 | * @param \EE_Transaction $txn |
123 | 123 | * @return \EE_Payment |
124 | 124 | */ |
125 | - private function _get_empty_payment_obj( EE_Transaction $txn ) { |
|
126 | - $PMT = EE_Payment::new_instance( array( |
|
125 | + private function _get_empty_payment_obj(EE_Transaction $txn) { |
|
126 | + $PMT = EE_Payment::new_instance(array( |
|
127 | 127 | 'STS_ID' => EEM_Payment::status_id_pending, |
128 | 128 | 'PAY_timestamp' => time(), |
129 | 129 | 'PMD_ID' => $txn->payment_method_ID(), |
@@ -153,9 +153,9 @@ discard block |
||
153 | 153 | |
154 | 154 | |
155 | 155 | //other data from the session (if possible) |
156 | - $this->user_id = isset( $session_data['user_id'] ) ? $session_data['user_id'] : ''; |
|
157 | - $this->ip_address = isset( $session_data['ip_address'] ) ? $session_data['ip_address'] : ''; |
|
158 | - $this->user_agent = isset( $session_data['user_agent'] ) ? $session_data['user_agent'] : ''; |
|
156 | + $this->user_id = isset($session_data['user_id']) ? $session_data['user_id'] : ''; |
|
157 | + $this->ip_address = isset($session_data['ip_address']) ? $session_data['ip_address'] : ''; |
|
158 | + $this->user_agent = isset($session_data['user_agent']) ? $session_data['user_agent'] : ''; |
|
159 | 159 | $this->init_access = $this->last_access = ''; |
160 | 160 | //get all non-trashed registrations |
161 | 161 | $this->reg_objs = $this->txn->registrations(array(array('REG_deleted' => false))); |
@@ -15,753 +15,753 @@ |
||
15 | 15 | class EE_Datetime_Field extends EE_Model_Field_Base |
16 | 16 | { |
17 | 17 | |
18 | - /** |
|
19 | - * The pattern we're looking for is if only the characters 0-9 are found and there are only |
|
20 | - * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 ) |
|
21 | - * |
|
22 | - * @type string unix_timestamp_regex |
|
23 | - */ |
|
24 | - const unix_timestamp_regex = '/[0-9]{10,}/'; |
|
25 | - |
|
26 | - /** |
|
27 | - * @type string mysql_timestamp_format |
|
28 | - */ |
|
29 | - const mysql_timestamp_format = 'Y-m-d H:i:s'; |
|
30 | - |
|
31 | - /** |
|
32 | - * @type string mysql_date_format |
|
33 | - */ |
|
34 | - const mysql_date_format = 'Y-m-d'; |
|
35 | - |
|
36 | - /** |
|
37 | - * @type string mysql_time_format |
|
38 | - */ |
|
39 | - const mysql_time_format = 'H:i:s'; |
|
40 | - |
|
41 | - /** |
|
42 | - * Const for using in the default value. If the field's default is set to this, |
|
43 | - * then we will return the time of calling `get_default_value()`, not |
|
44 | - * just the current time at construction |
|
45 | - */ |
|
46 | - const now = 'now'; |
|
47 | - |
|
48 | - /** |
|
49 | - * The following properties hold the default formats for date and time. |
|
50 | - * Defaults are set via the constructor and can be overridden on class instantiation. |
|
51 | - * However they can also be overridden later by the set_format() method |
|
52 | - * (and corresponding set_date_format, set_time_format methods); |
|
53 | - */ |
|
54 | - /** |
|
55 | - * @type string $_date_format |
|
56 | - */ |
|
57 | - protected $_date_format = ''; |
|
58 | - |
|
59 | - /** |
|
60 | - * @type string $_time_format |
|
61 | - */ |
|
62 | - protected $_time_format = ''; |
|
63 | - |
|
64 | - /** |
|
65 | - * @type string $_pretty_date_format |
|
66 | - */ |
|
67 | - protected $_pretty_date_format = ''; |
|
68 | - |
|
69 | - /** |
|
70 | - * @type string $_pretty_time_format |
|
71 | - */ |
|
72 | - protected $_pretty_time_format = ''; |
|
73 | - |
|
74 | - /** |
|
75 | - * @type DateTimeZone $_DateTimeZone |
|
76 | - */ |
|
77 | - protected $_DateTimeZone; |
|
78 | - |
|
79 | - /** |
|
80 | - * @type DateTimeZone $_UTC_DateTimeZone |
|
81 | - */ |
|
82 | - protected $_UTC_DateTimeZone; |
|
83 | - |
|
84 | - /** |
|
85 | - * @type DateTimeZone $_blog_DateTimeZone |
|
86 | - */ |
|
87 | - protected $_blog_DateTimeZone; |
|
88 | - |
|
89 | - |
|
90 | - /** |
|
91 | - * This property holds how we want the output returned when getting a datetime string. It is set for the |
|
92 | - * set_date_time_output() method. By default this is empty. When empty, we are assuming that we want both date |
|
93 | - * and time returned via getters. |
|
94 | - * |
|
95 | - * @var mixed (null|string) |
|
96 | - */ |
|
97 | - protected $_date_time_output; |
|
98 | - |
|
99 | - |
|
100 | - /** |
|
101 | - * timezone string |
|
102 | - * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone |
|
103 | - * incoming strings|timestamps are in. This can also be used before a get to set what timezone you want strings |
|
104 | - * coming out of the object to be in. Default timezone is the current WP timezone option setting |
|
105 | - * |
|
106 | - * @var string |
|
107 | - */ |
|
108 | - protected $_timezone_string; |
|
109 | - |
|
110 | - |
|
111 | - /** |
|
112 | - * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related |
|
113 | - * offsets for comparison purposes). |
|
114 | - * |
|
115 | - * @var int |
|
116 | - */ |
|
117 | - protected $_blog_offset; |
|
118 | - |
|
119 | - |
|
120 | - |
|
121 | - /** |
|
122 | - * @param string $table_column |
|
123 | - * @param string $nice_name |
|
124 | - * @param bool $nullable |
|
125 | - * @param string $default_value |
|
126 | - * @param string $timezone_string |
|
127 | - * @param string $date_format |
|
128 | - * @param string $time_format |
|
129 | - * @param string $pretty_date_format |
|
130 | - * @param string $pretty_time_format |
|
131 | - * @throws EE_Error |
|
132 | - * @throws InvalidArgumentException |
|
133 | - */ |
|
134 | - public function __construct( |
|
135 | - $table_column, |
|
136 | - $nice_name, |
|
137 | - $nullable, |
|
138 | - $default_value, |
|
139 | - $timezone_string = '', |
|
140 | - $date_format = '', |
|
141 | - $time_format = '', |
|
142 | - $pretty_date_format = '', |
|
143 | - $pretty_time_format = '' |
|
144 | - ) { |
|
145 | - |
|
146 | - $this->_date_format = ! empty($date_format) ? $date_format : get_option('date_format'); |
|
147 | - $this->_time_format = ! empty($time_format) ? $time_format : get_option('time_format'); |
|
148 | - $this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format'); |
|
149 | - $this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format'); |
|
150 | - |
|
151 | - parent::__construct($table_column, $nice_name, $nullable, $default_value); |
|
152 | - $this->set_timezone($timezone_string); |
|
153 | - $this->setSchemaFormat('date-time'); |
|
154 | - } |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * @return DateTimeZone |
|
159 | - * @throws \EE_Error |
|
160 | - */ |
|
161 | - public function get_UTC_DateTimeZone() |
|
162 | - { |
|
163 | - return $this->_UTC_DateTimeZone instanceof DateTimeZone |
|
164 | - ? $this->_UTC_DateTimeZone |
|
165 | - : $this->_create_timezone_object_from_timezone_string('UTC'); |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @return DateTimeZone |
|
171 | - * @throws \EE_Error |
|
172 | - */ |
|
173 | - public function get_blog_DateTimeZone() |
|
174 | - { |
|
175 | - return $this->_blog_DateTimeZone instanceof DateTimeZone |
|
176 | - ? $this->_blog_DateTimeZone |
|
177 | - : $this->_create_timezone_object_from_timezone_string(''); |
|
178 | - } |
|
179 | - |
|
180 | - |
|
181 | - /** |
|
182 | - * this prepares any incoming date data and make sure its converted to a utc unix timestamp |
|
183 | - * |
|
184 | - * @param string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix |
|
185 | - * timestamp |
|
186 | - * @return DateTime |
|
187 | - */ |
|
188 | - public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
189 | - { |
|
190 | - return $this->_get_date_object($value_inputted_for_field_on_model_object); |
|
191 | - } |
|
192 | - |
|
193 | - |
|
194 | - /** |
|
195 | - * This returns the format string to be used by getters depending on what the $_date_time_output property is set at. |
|
196 | - * getters need to know whether we're just returning the date or the time or both. By default we return both. |
|
197 | - * |
|
198 | - * @param bool $pretty If we're returning the pretty formats or standard format string. |
|
199 | - * @return string The final assembled format string. |
|
200 | - */ |
|
201 | - protected function _get_date_time_output($pretty = false) |
|
202 | - { |
|
203 | - |
|
204 | - switch ($this->_date_time_output) { |
|
205 | - case 'time' : |
|
206 | - return $pretty ? $this->_pretty_time_format : $this->_time_format; |
|
207 | - break; |
|
208 | - |
|
209 | - case 'date' : |
|
210 | - return $pretty ? $this->_pretty_date_format : $this->_date_format; |
|
211 | - break; |
|
212 | - |
|
213 | - default : |
|
214 | - return $pretty |
|
215 | - ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format |
|
216 | - : $this->_date_format . ' ' . $this->_time_format; |
|
217 | - } |
|
218 | - } |
|
219 | - |
|
220 | - |
|
221 | - /** |
|
222 | - * This just sets the $_date_time_output property so we can flag how date and times are formatted before being |
|
223 | - * returned (using the format properties) |
|
224 | - * |
|
225 | - * @param string $what acceptable values are 'time' or 'date'. |
|
226 | - * Any other value will be set but will always result |
|
227 | - * in both 'date' and 'time' being returned. |
|
228 | - * @return void |
|
229 | - */ |
|
230 | - public function set_date_time_output($what = null) |
|
231 | - { |
|
232 | - $this->_date_time_output = $what; |
|
233 | - } |
|
234 | - |
|
235 | - |
|
236 | - /** |
|
237 | - * See $_timezone property for description of what the timezone property is for. This SETS the timezone internally |
|
238 | - * for being able to reference what timezone we are running conversions on when converting TO the internal timezone |
|
239 | - * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). |
|
240 | - * We also set some other properties in this method. |
|
241 | - * |
|
242 | - * @param string $timezone_string A valid timezone string as described by @link |
|
243 | - * http://www.php.net/manual/en/timezones.php |
|
244 | - * @return void |
|
245 | - * @throws \EE_Error |
|
246 | - */ |
|
247 | - public function set_timezone($timezone_string) |
|
248 | - { |
|
249 | - if (empty($timezone_string) && $this->_timezone_string !== null) { |
|
250 | - // leave the timezone AS-IS if we already have one and |
|
251 | - // the function arg didn't provide one |
|
252 | - return; |
|
253 | - } |
|
254 | - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string); |
|
255 | - $this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC'; |
|
256 | - $this->_DateTimeZone = $this->_create_timezone_object_from_timezone_string($this->_timezone_string); |
|
257 | - } |
|
258 | - |
|
259 | - |
|
260 | - /** |
|
261 | - * _create_timezone_object_from_timezone_name |
|
262 | - * |
|
263 | - * @access protected |
|
264 | - * @param string $timezone_string |
|
265 | - * @return \DateTimeZone |
|
266 | - * @throws \EE_Error |
|
267 | - */ |
|
268 | - protected function _create_timezone_object_from_timezone_string($timezone_string = '') |
|
269 | - { |
|
270 | - return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string)); |
|
271 | - } |
|
272 | - |
|
273 | - |
|
274 | - /** |
|
275 | - * This just returns whatever is set for the current timezone. |
|
276 | - * |
|
277 | - * @access public |
|
278 | - * @return string timezone string |
|
279 | - */ |
|
280 | - public function get_timezone() |
|
281 | - { |
|
282 | - return $this->_timezone_string; |
|
283 | - } |
|
284 | - |
|
285 | - |
|
286 | - /** |
|
287 | - * set the $_date_format property |
|
288 | - * |
|
289 | - * @access public |
|
290 | - * @param string $format a new date format (corresponding to formats accepted by PHP date() function) |
|
291 | - * @param bool $pretty Whether to set pretty format or not. |
|
292 | - * @return void |
|
293 | - */ |
|
294 | - public function set_date_format($format, $pretty = false) |
|
295 | - { |
|
296 | - if ($pretty) { |
|
297 | - $this->_pretty_date_format = $format; |
|
298 | - } else { |
|
299 | - $this->_date_format = $format; |
|
300 | - } |
|
301 | - } |
|
302 | - |
|
303 | - |
|
304 | - /** |
|
305 | - * return the $_date_format property value. |
|
306 | - * |
|
307 | - * @param bool $pretty Whether to get pretty format or not. |
|
308 | - * @return string |
|
309 | - */ |
|
310 | - public function get_date_format($pretty = false) |
|
311 | - { |
|
312 | - return $pretty ? $this->_pretty_date_format : $this->_date_format; |
|
313 | - } |
|
314 | - |
|
315 | - |
|
316 | - /** |
|
317 | - * set the $_time_format property |
|
318 | - * |
|
319 | - * @access public |
|
320 | - * @param string $format a new time format (corresponding to formats accepted by PHP date() function) |
|
321 | - * @param bool $pretty Whether to set pretty format or not. |
|
322 | - * @return void |
|
323 | - */ |
|
324 | - public function set_time_format($format, $pretty = false) |
|
325 | - { |
|
326 | - if ($pretty) { |
|
327 | - $this->_pretty_time_format = $format; |
|
328 | - } else { |
|
329 | - $this->_time_format = $format; |
|
330 | - } |
|
331 | - } |
|
332 | - |
|
333 | - |
|
334 | - /** |
|
335 | - * return the $_time_format property value. |
|
336 | - * |
|
337 | - * @param bool $pretty Whether to get pretty format or not. |
|
338 | - * @return string |
|
339 | - */ |
|
340 | - public function get_time_format($pretty = false) |
|
341 | - { |
|
342 | - return $pretty ? $this->_pretty_time_format : $this->_time_format; |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * set the $_pretty_date_format property |
|
348 | - * |
|
349 | - * @access public |
|
350 | - * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function) |
|
351 | - * @return void |
|
352 | - */ |
|
353 | - public function set_pretty_date_format($format) |
|
354 | - { |
|
355 | - $this->_pretty_date_format = $format; |
|
356 | - } |
|
357 | - |
|
358 | - |
|
359 | - /** |
|
360 | - * set the $_pretty_time_format property |
|
361 | - * |
|
362 | - * @access public |
|
363 | - * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function) |
|
364 | - * @return void |
|
365 | - */ |
|
366 | - public function set_pretty_time_format($format) |
|
367 | - { |
|
368 | - $this->_pretty_time_format = $format; |
|
369 | - } |
|
370 | - |
|
371 | - |
|
372 | - /** |
|
373 | - * Only sets the time portion of the datetime. |
|
374 | - * |
|
375 | - * @param string|DateTime $time_to_set_string like 8am OR a DateTime object. |
|
376 | - * @param DateTime $current current DateTime object for the datetime field |
|
377 | - * @return DateTime |
|
378 | - */ |
|
379 | - public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current) |
|
380 | - { |
|
381 | - // if $time_to_set_string is datetime object, then let's use it to set the parse array. |
|
382 | - // Otherwise parse the string. |
|
383 | - if ($time_to_set_string instanceof DateTime) { |
|
384 | - $parsed = array( |
|
385 | - 'hour' => $time_to_set_string->format('H'), |
|
386 | - 'minute' => $time_to_set_string->format('i'), |
|
387 | - 'second' => $time_to_set_string->format('s'), |
|
388 | - ); |
|
389 | - } else { |
|
390 | - //parse incoming string |
|
391 | - $parsed = date_parse_from_format($this->_time_format, $time_to_set_string); |
|
392 | - } |
|
393 | - |
|
394 | - //make sure $current is in the correct timezone. |
|
395 | - $current->setTimezone($this->_DateTimeZone); |
|
396 | - |
|
397 | - return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']); |
|
398 | - } |
|
399 | - |
|
400 | - |
|
401 | - /** |
|
402 | - * Only sets the date portion of the datetime. |
|
403 | - * |
|
404 | - * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object. |
|
405 | - * @param DateTime $current current DateTime object for the datetime field |
|
406 | - * @return DateTime |
|
407 | - */ |
|
408 | - public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current) |
|
409 | - { |
|
410 | - // if $time_to_set_string is datetime object, then let's use it to set the parse array. |
|
411 | - // Otherwise parse the string. |
|
412 | - if ($date_to_set_string instanceof DateTime) { |
|
413 | - $parsed = array( |
|
414 | - 'year' => $date_to_set_string->format('Y'), |
|
415 | - 'month' => $date_to_set_string->format('m'), |
|
416 | - 'day' => $date_to_set_string->format('d'), |
|
417 | - ); |
|
418 | - } else { |
|
419 | - //parse incoming string |
|
420 | - $parsed = date_parse_from_format($this->_date_format, $date_to_set_string); |
|
421 | - } |
|
422 | - |
|
423 | - //make sure $current is in the correct timezone |
|
424 | - $current->setTimezone($this->_DateTimeZone); |
|
425 | - |
|
426 | - return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']); |
|
427 | - } |
|
428 | - |
|
429 | - |
|
430 | - /** |
|
431 | - * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone). When the |
|
432 | - * datetime gets to this stage it should ALREADY be in UTC time |
|
433 | - * |
|
434 | - * @param DateTime $DateTime |
|
435 | - * @return string formatted date time for given timezone |
|
436 | - * @throws \EE_Error |
|
437 | - */ |
|
438 | - public function prepare_for_get($DateTime) |
|
439 | - { |
|
440 | - return $this->_prepare_for_display($DateTime); |
|
441 | - } |
|
442 | - |
|
443 | - |
|
444 | - /** |
|
445 | - * This differs from prepare_for_get in that it considers whether the internal $_timezone differs |
|
446 | - * from the set wp timezone. If so, then it returns the datetime string formatted via |
|
447 | - * _pretty_date_format, and _pretty_time_format. However, it also appends a timezone |
|
448 | - * abbreviation to the date_string. |
|
449 | - * |
|
450 | - * @param mixed $DateTime |
|
451 | - * @param null $schema |
|
452 | - * @return string |
|
453 | - * @throws \EE_Error |
|
454 | - */ |
|
455 | - public function prepare_for_pretty_echoing($DateTime, $schema = null) |
|
456 | - { |
|
457 | - return $this->_prepare_for_display($DateTime, $schema ? $schema : true); |
|
458 | - } |
|
459 | - |
|
460 | - |
|
461 | - /** |
|
462 | - * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 |
|
463 | - * timezone). |
|
464 | - * |
|
465 | - * @param DateTime $DateTime |
|
466 | - * @param bool|string $schema |
|
467 | - * @return string |
|
468 | - * @throws \EE_Error |
|
469 | - */ |
|
470 | - protected function _prepare_for_display($DateTime, $schema = false) |
|
471 | - { |
|
472 | - if (! $DateTime instanceof DateTime) { |
|
473 | - if ($this->_nullable) { |
|
474 | - return ''; |
|
475 | - } else { |
|
476 | - if (WP_DEBUG) { |
|
477 | - throw new EE_Error( |
|
478 | - sprintf( |
|
479 | - __( |
|
480 | - 'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.', |
|
481 | - 'event_espresso' |
|
482 | - ), |
|
483 | - $this->_nicename |
|
484 | - ) |
|
485 | - ); |
|
486 | - } else { |
|
487 | - $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now); |
|
488 | - EE_Error::add_error( |
|
489 | - sprintf( |
|
490 | - __( |
|
491 | - 'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable. When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.', |
|
492 | - 'event_espresso' |
|
493 | - ), |
|
494 | - $this->_nicename |
|
495 | - ) |
|
496 | - ); |
|
497 | - } |
|
498 | - } |
|
499 | - } |
|
500 | - $format_string = $this->_get_date_time_output($schema); |
|
501 | - //make sure datetime_value is in the correct timezone (in case that's been updated). |
|
502 | - $DateTime->setTimezone($this->_DateTimeZone); |
|
503 | - if ($schema) { |
|
504 | - if ($this->_display_timezone()) { |
|
505 | - //must be explicit because schema could equal true. |
|
506 | - if ($schema === 'no_html') { |
|
507 | - $timezone_string = ' (' . $DateTime->format('T') . ')'; |
|
508 | - } else { |
|
509 | - $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>'; |
|
510 | - } |
|
511 | - } else { |
|
512 | - $timezone_string = ''; |
|
513 | - } |
|
514 | - |
|
515 | - return $DateTime->format($format_string) . $timezone_string; |
|
516 | - } else { |
|
517 | - return $DateTime->format($format_string); |
|
518 | - } |
|
519 | - } |
|
520 | - |
|
521 | - |
|
522 | - /** |
|
523 | - * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 |
|
524 | - * timezone). |
|
525 | - * |
|
526 | - * @param mixed $datetime_value u |
|
527 | - * @return string mysql timestamp in UTC |
|
528 | - * @throws \EE_Error |
|
529 | - */ |
|
530 | - public function prepare_for_use_in_db($datetime_value) |
|
531 | - { |
|
532 | - //we allow an empty value or DateTime object, but nothing else. |
|
533 | - if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) { |
|
534 | - throw new EE_Error( |
|
535 | - sprintf( |
|
536 | - __( |
|
537 | - 'The incoming value being prepared for setting in the database must either be empty or a php |
|
18 | + /** |
|
19 | + * The pattern we're looking for is if only the characters 0-9 are found and there are only |
|
20 | + * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 ) |
|
21 | + * |
|
22 | + * @type string unix_timestamp_regex |
|
23 | + */ |
|
24 | + const unix_timestamp_regex = '/[0-9]{10,}/'; |
|
25 | + |
|
26 | + /** |
|
27 | + * @type string mysql_timestamp_format |
|
28 | + */ |
|
29 | + const mysql_timestamp_format = 'Y-m-d H:i:s'; |
|
30 | + |
|
31 | + /** |
|
32 | + * @type string mysql_date_format |
|
33 | + */ |
|
34 | + const mysql_date_format = 'Y-m-d'; |
|
35 | + |
|
36 | + /** |
|
37 | + * @type string mysql_time_format |
|
38 | + */ |
|
39 | + const mysql_time_format = 'H:i:s'; |
|
40 | + |
|
41 | + /** |
|
42 | + * Const for using in the default value. If the field's default is set to this, |
|
43 | + * then we will return the time of calling `get_default_value()`, not |
|
44 | + * just the current time at construction |
|
45 | + */ |
|
46 | + const now = 'now'; |
|
47 | + |
|
48 | + /** |
|
49 | + * The following properties hold the default formats for date and time. |
|
50 | + * Defaults are set via the constructor and can be overridden on class instantiation. |
|
51 | + * However they can also be overridden later by the set_format() method |
|
52 | + * (and corresponding set_date_format, set_time_format methods); |
|
53 | + */ |
|
54 | + /** |
|
55 | + * @type string $_date_format |
|
56 | + */ |
|
57 | + protected $_date_format = ''; |
|
58 | + |
|
59 | + /** |
|
60 | + * @type string $_time_format |
|
61 | + */ |
|
62 | + protected $_time_format = ''; |
|
63 | + |
|
64 | + /** |
|
65 | + * @type string $_pretty_date_format |
|
66 | + */ |
|
67 | + protected $_pretty_date_format = ''; |
|
68 | + |
|
69 | + /** |
|
70 | + * @type string $_pretty_time_format |
|
71 | + */ |
|
72 | + protected $_pretty_time_format = ''; |
|
73 | + |
|
74 | + /** |
|
75 | + * @type DateTimeZone $_DateTimeZone |
|
76 | + */ |
|
77 | + protected $_DateTimeZone; |
|
78 | + |
|
79 | + /** |
|
80 | + * @type DateTimeZone $_UTC_DateTimeZone |
|
81 | + */ |
|
82 | + protected $_UTC_DateTimeZone; |
|
83 | + |
|
84 | + /** |
|
85 | + * @type DateTimeZone $_blog_DateTimeZone |
|
86 | + */ |
|
87 | + protected $_blog_DateTimeZone; |
|
88 | + |
|
89 | + |
|
90 | + /** |
|
91 | + * This property holds how we want the output returned when getting a datetime string. It is set for the |
|
92 | + * set_date_time_output() method. By default this is empty. When empty, we are assuming that we want both date |
|
93 | + * and time returned via getters. |
|
94 | + * |
|
95 | + * @var mixed (null|string) |
|
96 | + */ |
|
97 | + protected $_date_time_output; |
|
98 | + |
|
99 | + |
|
100 | + /** |
|
101 | + * timezone string |
|
102 | + * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone |
|
103 | + * incoming strings|timestamps are in. This can also be used before a get to set what timezone you want strings |
|
104 | + * coming out of the object to be in. Default timezone is the current WP timezone option setting |
|
105 | + * |
|
106 | + * @var string |
|
107 | + */ |
|
108 | + protected $_timezone_string; |
|
109 | + |
|
110 | + |
|
111 | + /** |
|
112 | + * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related |
|
113 | + * offsets for comparison purposes). |
|
114 | + * |
|
115 | + * @var int |
|
116 | + */ |
|
117 | + protected $_blog_offset; |
|
118 | + |
|
119 | + |
|
120 | + |
|
121 | + /** |
|
122 | + * @param string $table_column |
|
123 | + * @param string $nice_name |
|
124 | + * @param bool $nullable |
|
125 | + * @param string $default_value |
|
126 | + * @param string $timezone_string |
|
127 | + * @param string $date_format |
|
128 | + * @param string $time_format |
|
129 | + * @param string $pretty_date_format |
|
130 | + * @param string $pretty_time_format |
|
131 | + * @throws EE_Error |
|
132 | + * @throws InvalidArgumentException |
|
133 | + */ |
|
134 | + public function __construct( |
|
135 | + $table_column, |
|
136 | + $nice_name, |
|
137 | + $nullable, |
|
138 | + $default_value, |
|
139 | + $timezone_string = '', |
|
140 | + $date_format = '', |
|
141 | + $time_format = '', |
|
142 | + $pretty_date_format = '', |
|
143 | + $pretty_time_format = '' |
|
144 | + ) { |
|
145 | + |
|
146 | + $this->_date_format = ! empty($date_format) ? $date_format : get_option('date_format'); |
|
147 | + $this->_time_format = ! empty($time_format) ? $time_format : get_option('time_format'); |
|
148 | + $this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format'); |
|
149 | + $this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format'); |
|
150 | + |
|
151 | + parent::__construct($table_column, $nice_name, $nullable, $default_value); |
|
152 | + $this->set_timezone($timezone_string); |
|
153 | + $this->setSchemaFormat('date-time'); |
|
154 | + } |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * @return DateTimeZone |
|
159 | + * @throws \EE_Error |
|
160 | + */ |
|
161 | + public function get_UTC_DateTimeZone() |
|
162 | + { |
|
163 | + return $this->_UTC_DateTimeZone instanceof DateTimeZone |
|
164 | + ? $this->_UTC_DateTimeZone |
|
165 | + : $this->_create_timezone_object_from_timezone_string('UTC'); |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @return DateTimeZone |
|
171 | + * @throws \EE_Error |
|
172 | + */ |
|
173 | + public function get_blog_DateTimeZone() |
|
174 | + { |
|
175 | + return $this->_blog_DateTimeZone instanceof DateTimeZone |
|
176 | + ? $this->_blog_DateTimeZone |
|
177 | + : $this->_create_timezone_object_from_timezone_string(''); |
|
178 | + } |
|
179 | + |
|
180 | + |
|
181 | + /** |
|
182 | + * this prepares any incoming date data and make sure its converted to a utc unix timestamp |
|
183 | + * |
|
184 | + * @param string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix |
|
185 | + * timestamp |
|
186 | + * @return DateTime |
|
187 | + */ |
|
188 | + public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
189 | + { |
|
190 | + return $this->_get_date_object($value_inputted_for_field_on_model_object); |
|
191 | + } |
|
192 | + |
|
193 | + |
|
194 | + /** |
|
195 | + * This returns the format string to be used by getters depending on what the $_date_time_output property is set at. |
|
196 | + * getters need to know whether we're just returning the date or the time or both. By default we return both. |
|
197 | + * |
|
198 | + * @param bool $pretty If we're returning the pretty formats or standard format string. |
|
199 | + * @return string The final assembled format string. |
|
200 | + */ |
|
201 | + protected function _get_date_time_output($pretty = false) |
|
202 | + { |
|
203 | + |
|
204 | + switch ($this->_date_time_output) { |
|
205 | + case 'time' : |
|
206 | + return $pretty ? $this->_pretty_time_format : $this->_time_format; |
|
207 | + break; |
|
208 | + |
|
209 | + case 'date' : |
|
210 | + return $pretty ? $this->_pretty_date_format : $this->_date_format; |
|
211 | + break; |
|
212 | + |
|
213 | + default : |
|
214 | + return $pretty |
|
215 | + ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format |
|
216 | + : $this->_date_format . ' ' . $this->_time_format; |
|
217 | + } |
|
218 | + } |
|
219 | + |
|
220 | + |
|
221 | + /** |
|
222 | + * This just sets the $_date_time_output property so we can flag how date and times are formatted before being |
|
223 | + * returned (using the format properties) |
|
224 | + * |
|
225 | + * @param string $what acceptable values are 'time' or 'date'. |
|
226 | + * Any other value will be set but will always result |
|
227 | + * in both 'date' and 'time' being returned. |
|
228 | + * @return void |
|
229 | + */ |
|
230 | + public function set_date_time_output($what = null) |
|
231 | + { |
|
232 | + $this->_date_time_output = $what; |
|
233 | + } |
|
234 | + |
|
235 | + |
|
236 | + /** |
|
237 | + * See $_timezone property for description of what the timezone property is for. This SETS the timezone internally |
|
238 | + * for being able to reference what timezone we are running conversions on when converting TO the internal timezone |
|
239 | + * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). |
|
240 | + * We also set some other properties in this method. |
|
241 | + * |
|
242 | + * @param string $timezone_string A valid timezone string as described by @link |
|
243 | + * http://www.php.net/manual/en/timezones.php |
|
244 | + * @return void |
|
245 | + * @throws \EE_Error |
|
246 | + */ |
|
247 | + public function set_timezone($timezone_string) |
|
248 | + { |
|
249 | + if (empty($timezone_string) && $this->_timezone_string !== null) { |
|
250 | + // leave the timezone AS-IS if we already have one and |
|
251 | + // the function arg didn't provide one |
|
252 | + return; |
|
253 | + } |
|
254 | + $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string); |
|
255 | + $this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC'; |
|
256 | + $this->_DateTimeZone = $this->_create_timezone_object_from_timezone_string($this->_timezone_string); |
|
257 | + } |
|
258 | + |
|
259 | + |
|
260 | + /** |
|
261 | + * _create_timezone_object_from_timezone_name |
|
262 | + * |
|
263 | + * @access protected |
|
264 | + * @param string $timezone_string |
|
265 | + * @return \DateTimeZone |
|
266 | + * @throws \EE_Error |
|
267 | + */ |
|
268 | + protected function _create_timezone_object_from_timezone_string($timezone_string = '') |
|
269 | + { |
|
270 | + return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string)); |
|
271 | + } |
|
272 | + |
|
273 | + |
|
274 | + /** |
|
275 | + * This just returns whatever is set for the current timezone. |
|
276 | + * |
|
277 | + * @access public |
|
278 | + * @return string timezone string |
|
279 | + */ |
|
280 | + public function get_timezone() |
|
281 | + { |
|
282 | + return $this->_timezone_string; |
|
283 | + } |
|
284 | + |
|
285 | + |
|
286 | + /** |
|
287 | + * set the $_date_format property |
|
288 | + * |
|
289 | + * @access public |
|
290 | + * @param string $format a new date format (corresponding to formats accepted by PHP date() function) |
|
291 | + * @param bool $pretty Whether to set pretty format or not. |
|
292 | + * @return void |
|
293 | + */ |
|
294 | + public function set_date_format($format, $pretty = false) |
|
295 | + { |
|
296 | + if ($pretty) { |
|
297 | + $this->_pretty_date_format = $format; |
|
298 | + } else { |
|
299 | + $this->_date_format = $format; |
|
300 | + } |
|
301 | + } |
|
302 | + |
|
303 | + |
|
304 | + /** |
|
305 | + * return the $_date_format property value. |
|
306 | + * |
|
307 | + * @param bool $pretty Whether to get pretty format or not. |
|
308 | + * @return string |
|
309 | + */ |
|
310 | + public function get_date_format($pretty = false) |
|
311 | + { |
|
312 | + return $pretty ? $this->_pretty_date_format : $this->_date_format; |
|
313 | + } |
|
314 | + |
|
315 | + |
|
316 | + /** |
|
317 | + * set the $_time_format property |
|
318 | + * |
|
319 | + * @access public |
|
320 | + * @param string $format a new time format (corresponding to formats accepted by PHP date() function) |
|
321 | + * @param bool $pretty Whether to set pretty format or not. |
|
322 | + * @return void |
|
323 | + */ |
|
324 | + public function set_time_format($format, $pretty = false) |
|
325 | + { |
|
326 | + if ($pretty) { |
|
327 | + $this->_pretty_time_format = $format; |
|
328 | + } else { |
|
329 | + $this->_time_format = $format; |
|
330 | + } |
|
331 | + } |
|
332 | + |
|
333 | + |
|
334 | + /** |
|
335 | + * return the $_time_format property value. |
|
336 | + * |
|
337 | + * @param bool $pretty Whether to get pretty format or not. |
|
338 | + * @return string |
|
339 | + */ |
|
340 | + public function get_time_format($pretty = false) |
|
341 | + { |
|
342 | + return $pretty ? $this->_pretty_time_format : $this->_time_format; |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * set the $_pretty_date_format property |
|
348 | + * |
|
349 | + * @access public |
|
350 | + * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function) |
|
351 | + * @return void |
|
352 | + */ |
|
353 | + public function set_pretty_date_format($format) |
|
354 | + { |
|
355 | + $this->_pretty_date_format = $format; |
|
356 | + } |
|
357 | + |
|
358 | + |
|
359 | + /** |
|
360 | + * set the $_pretty_time_format property |
|
361 | + * |
|
362 | + * @access public |
|
363 | + * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function) |
|
364 | + * @return void |
|
365 | + */ |
|
366 | + public function set_pretty_time_format($format) |
|
367 | + { |
|
368 | + $this->_pretty_time_format = $format; |
|
369 | + } |
|
370 | + |
|
371 | + |
|
372 | + /** |
|
373 | + * Only sets the time portion of the datetime. |
|
374 | + * |
|
375 | + * @param string|DateTime $time_to_set_string like 8am OR a DateTime object. |
|
376 | + * @param DateTime $current current DateTime object for the datetime field |
|
377 | + * @return DateTime |
|
378 | + */ |
|
379 | + public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current) |
|
380 | + { |
|
381 | + // if $time_to_set_string is datetime object, then let's use it to set the parse array. |
|
382 | + // Otherwise parse the string. |
|
383 | + if ($time_to_set_string instanceof DateTime) { |
|
384 | + $parsed = array( |
|
385 | + 'hour' => $time_to_set_string->format('H'), |
|
386 | + 'minute' => $time_to_set_string->format('i'), |
|
387 | + 'second' => $time_to_set_string->format('s'), |
|
388 | + ); |
|
389 | + } else { |
|
390 | + //parse incoming string |
|
391 | + $parsed = date_parse_from_format($this->_time_format, $time_to_set_string); |
|
392 | + } |
|
393 | + |
|
394 | + //make sure $current is in the correct timezone. |
|
395 | + $current->setTimezone($this->_DateTimeZone); |
|
396 | + |
|
397 | + return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']); |
|
398 | + } |
|
399 | + |
|
400 | + |
|
401 | + /** |
|
402 | + * Only sets the date portion of the datetime. |
|
403 | + * |
|
404 | + * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object. |
|
405 | + * @param DateTime $current current DateTime object for the datetime field |
|
406 | + * @return DateTime |
|
407 | + */ |
|
408 | + public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current) |
|
409 | + { |
|
410 | + // if $time_to_set_string is datetime object, then let's use it to set the parse array. |
|
411 | + // Otherwise parse the string. |
|
412 | + if ($date_to_set_string instanceof DateTime) { |
|
413 | + $parsed = array( |
|
414 | + 'year' => $date_to_set_string->format('Y'), |
|
415 | + 'month' => $date_to_set_string->format('m'), |
|
416 | + 'day' => $date_to_set_string->format('d'), |
|
417 | + ); |
|
418 | + } else { |
|
419 | + //parse incoming string |
|
420 | + $parsed = date_parse_from_format($this->_date_format, $date_to_set_string); |
|
421 | + } |
|
422 | + |
|
423 | + //make sure $current is in the correct timezone |
|
424 | + $current->setTimezone($this->_DateTimeZone); |
|
425 | + |
|
426 | + return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']); |
|
427 | + } |
|
428 | + |
|
429 | + |
|
430 | + /** |
|
431 | + * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone). When the |
|
432 | + * datetime gets to this stage it should ALREADY be in UTC time |
|
433 | + * |
|
434 | + * @param DateTime $DateTime |
|
435 | + * @return string formatted date time for given timezone |
|
436 | + * @throws \EE_Error |
|
437 | + */ |
|
438 | + public function prepare_for_get($DateTime) |
|
439 | + { |
|
440 | + return $this->_prepare_for_display($DateTime); |
|
441 | + } |
|
442 | + |
|
443 | + |
|
444 | + /** |
|
445 | + * This differs from prepare_for_get in that it considers whether the internal $_timezone differs |
|
446 | + * from the set wp timezone. If so, then it returns the datetime string formatted via |
|
447 | + * _pretty_date_format, and _pretty_time_format. However, it also appends a timezone |
|
448 | + * abbreviation to the date_string. |
|
449 | + * |
|
450 | + * @param mixed $DateTime |
|
451 | + * @param null $schema |
|
452 | + * @return string |
|
453 | + * @throws \EE_Error |
|
454 | + */ |
|
455 | + public function prepare_for_pretty_echoing($DateTime, $schema = null) |
|
456 | + { |
|
457 | + return $this->_prepare_for_display($DateTime, $schema ? $schema : true); |
|
458 | + } |
|
459 | + |
|
460 | + |
|
461 | + /** |
|
462 | + * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 |
|
463 | + * timezone). |
|
464 | + * |
|
465 | + * @param DateTime $DateTime |
|
466 | + * @param bool|string $schema |
|
467 | + * @return string |
|
468 | + * @throws \EE_Error |
|
469 | + */ |
|
470 | + protected function _prepare_for_display($DateTime, $schema = false) |
|
471 | + { |
|
472 | + if (! $DateTime instanceof DateTime) { |
|
473 | + if ($this->_nullable) { |
|
474 | + return ''; |
|
475 | + } else { |
|
476 | + if (WP_DEBUG) { |
|
477 | + throw new EE_Error( |
|
478 | + sprintf( |
|
479 | + __( |
|
480 | + 'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.', |
|
481 | + 'event_espresso' |
|
482 | + ), |
|
483 | + $this->_nicename |
|
484 | + ) |
|
485 | + ); |
|
486 | + } else { |
|
487 | + $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now); |
|
488 | + EE_Error::add_error( |
|
489 | + sprintf( |
|
490 | + __( |
|
491 | + 'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable. When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.', |
|
492 | + 'event_espresso' |
|
493 | + ), |
|
494 | + $this->_nicename |
|
495 | + ) |
|
496 | + ); |
|
497 | + } |
|
498 | + } |
|
499 | + } |
|
500 | + $format_string = $this->_get_date_time_output($schema); |
|
501 | + //make sure datetime_value is in the correct timezone (in case that's been updated). |
|
502 | + $DateTime->setTimezone($this->_DateTimeZone); |
|
503 | + if ($schema) { |
|
504 | + if ($this->_display_timezone()) { |
|
505 | + //must be explicit because schema could equal true. |
|
506 | + if ($schema === 'no_html') { |
|
507 | + $timezone_string = ' (' . $DateTime->format('T') . ')'; |
|
508 | + } else { |
|
509 | + $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>'; |
|
510 | + } |
|
511 | + } else { |
|
512 | + $timezone_string = ''; |
|
513 | + } |
|
514 | + |
|
515 | + return $DateTime->format($format_string) . $timezone_string; |
|
516 | + } else { |
|
517 | + return $DateTime->format($format_string); |
|
518 | + } |
|
519 | + } |
|
520 | + |
|
521 | + |
|
522 | + /** |
|
523 | + * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 |
|
524 | + * timezone). |
|
525 | + * |
|
526 | + * @param mixed $datetime_value u |
|
527 | + * @return string mysql timestamp in UTC |
|
528 | + * @throws \EE_Error |
|
529 | + */ |
|
530 | + public function prepare_for_use_in_db($datetime_value) |
|
531 | + { |
|
532 | + //we allow an empty value or DateTime object, but nothing else. |
|
533 | + if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) { |
|
534 | + throw new EE_Error( |
|
535 | + sprintf( |
|
536 | + __( |
|
537 | + 'The incoming value being prepared for setting in the database must either be empty or a php |
|
538 | 538 | DateTime object, instead of: %1$s %2$s', |
539 | - 'event_espresso' |
|
540 | - ), |
|
541 | - '<br />', |
|
542 | - print_r($datetime_value, true) |
|
543 | - ) |
|
544 | - ); |
|
545 | - } |
|
546 | - |
|
547 | - if ($datetime_value instanceof DateTime) { |
|
548 | - if ( ! $datetime_value instanceof DbSafeDateTime) { |
|
549 | - $datetime_value = DbSafeDateTime::createFromDateTime($datetime_value); |
|
550 | - } |
|
551 | - |
|
552 | - return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format( |
|
553 | - EE_Datetime_Field::mysql_timestamp_format |
|
554 | - ); |
|
555 | - } |
|
556 | - |
|
557 | - // if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true |
|
558 | - return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null; |
|
559 | - } |
|
560 | - |
|
561 | - |
|
562 | - /** |
|
563 | - * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is |
|
564 | - * allowed) |
|
565 | - * |
|
566 | - * @param string $datetime_string mysql timestamp in UTC |
|
567 | - * @return mixed null | DateTime |
|
568 | - * @throws \EE_Error |
|
569 | - */ |
|
570 | - public function prepare_for_set_from_db($datetime_string) |
|
571 | - { |
|
572 | - //if $datetime_value is empty, and ! $this->_nullable, just use time() |
|
573 | - if (empty($datetime_string) && $this->_nullable) { |
|
574 | - return null; |
|
575 | - } |
|
576 | - // datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating |
|
577 | - if (empty($datetime_string)) { |
|
578 | - $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone()); |
|
579 | - } else { |
|
580 | - $DateTime = DateTime::createFromFormat( |
|
581 | - EE_Datetime_Field::mysql_timestamp_format, |
|
582 | - $datetime_string, |
|
583 | - $this->get_UTC_DateTimeZone() |
|
584 | - ); |
|
585 | - if ($DateTime instanceof \DateTime) { |
|
586 | - $DateTime = new DbSafeDateTime( |
|
587 | - $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format), |
|
588 | - $this->get_UTC_DateTimeZone() |
|
589 | - ); |
|
590 | - } |
|
591 | - } |
|
592 | - |
|
593 | - if (! $DateTime instanceof DbSafeDateTime) { |
|
594 | - // if still no datetime object, then let's just use now |
|
595 | - $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone()); |
|
596 | - } |
|
597 | - // THEN apply the field's set DateTimeZone |
|
598 | - $DateTime->setTimezone($this->_DateTimeZone); |
|
599 | - |
|
600 | - return $DateTime; |
|
601 | - } |
|
602 | - |
|
603 | - |
|
604 | - /** |
|
605 | - * All this method does is determine if we're going to display the timezone string or not on any output. |
|
606 | - * To determine this we check if the set timezone offset is different than the blog's set timezone offset. |
|
607 | - * If so, then true. |
|
608 | - * |
|
609 | - * @return bool true for yes false for no |
|
610 | - * @throws \EE_Error |
|
611 | - */ |
|
612 | - protected function _display_timezone() |
|
613 | - { |
|
614 | - |
|
615 | - // first let's do a comparison of timezone strings. |
|
616 | - // If they match then we can get out without any further calculations |
|
617 | - $blog_string = get_option('timezone_string'); |
|
618 | - if ($blog_string === $this->_timezone_string) { |
|
619 | - return false; |
|
620 | - } |
|
621 | - // now we need to calc the offset for the timezone string so we can compare with the blog offset. |
|
622 | - $this_offset = $this->get_timezone_offset($this->_DateTimeZone); |
|
623 | - $blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone()); |
|
624 | - // now compare |
|
625 | - return $blog_offset !== $this_offset; |
|
626 | - } |
|
627 | - |
|
628 | - |
|
629 | - /** |
|
630 | - * This method returns a php DateTime object for setting on the EE_Base_Class model. |
|
631 | - * EE passes around DateTime objects because they are MUCH easier to manipulate and deal |
|
632 | - * with. |
|
633 | - * |
|
634 | - * @param int|string|DateTime $date_string This should be the incoming date string. It's assumed to be |
|
635 | - * in the format that is set on the date_field (or DateTime |
|
636 | - * object)! |
|
637 | - * @return DateTime |
|
638 | - */ |
|
639 | - protected function _get_date_object($date_string) |
|
640 | - { |
|
641 | - //first if this is an empty date_string and nullable is allowed, just return null. |
|
642 | - if ($this->_nullable && empty($date_string)) { |
|
643 | - return null; |
|
644 | - } |
|
645 | - |
|
646 | - // if incoming date |
|
647 | - if ($date_string instanceof DateTime) { |
|
648 | - $date_string->setTimezone($this->_DateTimeZone); |
|
649 | - |
|
650 | - return $date_string; |
|
651 | - } |
|
652 | - // if empty date_string and made it here. |
|
653 | - // Return a datetime object for now in the given timezone. |
|
654 | - if (empty($date_string)) { |
|
655 | - return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
656 | - } |
|
657 | - // if $date_string is matches something that looks like a Unix timestamp let's just use it. |
|
658 | - if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) { |
|
659 | - try { |
|
660 | - // This is operating under the assumption that the incoming Unix timestamp |
|
661 | - // is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp'); |
|
662 | - $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
663 | - $DateTime->setTimestamp($date_string); |
|
664 | - |
|
665 | - return $DateTime; |
|
666 | - } catch (Exception $e) { |
|
667 | - // should be rare, but if things got fooled then let's just continue |
|
668 | - } |
|
669 | - } |
|
670 | - //not a unix timestamp. So we will use the set format on this object and set timezone to |
|
671 | - //create the DateTime object. |
|
672 | - $format = $this->_date_format . ' ' . $this->_time_format; |
|
673 | - try { |
|
674 | - $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone); |
|
675 | - if ($DateTime instanceof DateTime) { |
|
676 | - $DateTime = new DbSafeDateTime( |
|
677 | - $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format), |
|
678 | - $this->_DateTimeZone |
|
679 | - ); |
|
680 | - } |
|
681 | - if (! $DateTime instanceof DbSafeDateTime) { |
|
682 | - throw new EE_Error( |
|
683 | - sprintf( |
|
684 | - __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'), |
|
685 | - $date_string, |
|
686 | - $format |
|
687 | - ) |
|
688 | - ); |
|
689 | - } |
|
690 | - } catch (Exception $e) { |
|
691 | - // if we made it here then likely then something went really wrong. |
|
692 | - // Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone. |
|
693 | - $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
694 | - } |
|
695 | - |
|
696 | - return $DateTime; |
|
697 | - } |
|
698 | - |
|
699 | - |
|
700 | - |
|
701 | - /** |
|
702 | - * get_timezone_transitions |
|
703 | - * |
|
704 | - * @param \DateTimeZone $DateTimeZone |
|
705 | - * @param int $time |
|
706 | - * @param bool $first_only |
|
707 | - * @return mixed |
|
708 | - */ |
|
709 | - public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true) |
|
710 | - { |
|
711 | - return EEH_DTT_Helper::get_timezone_transitions($DateTimeZone, $time, $first_only); |
|
712 | - } |
|
713 | - |
|
714 | - |
|
715 | - |
|
716 | - /** |
|
717 | - * get_timezone_offset |
|
718 | - * |
|
719 | - * @param \DateTimeZone $DateTimeZone |
|
720 | - * @param int $time |
|
721 | - * @return mixed |
|
722 | - * @throws \DomainException |
|
723 | - */ |
|
724 | - public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null) |
|
725 | - { |
|
726 | - return EEH_DTT_Helper::get_timezone_offset($DateTimeZone, $time); |
|
727 | - } |
|
728 | - |
|
729 | - |
|
730 | - /** |
|
731 | - * This will take an incoming timezone string and return the abbreviation for that timezone |
|
732 | - * |
|
733 | - * @param string $timezone_string |
|
734 | - * @return string abbreviation |
|
735 | - * @throws \EE_Error |
|
736 | - */ |
|
737 | - public function get_timezone_abbrev($timezone_string) |
|
738 | - { |
|
739 | - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string); |
|
740 | - $dateTime = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string)); |
|
741 | - |
|
742 | - return $dateTime->format('T'); |
|
743 | - } |
|
744 | - |
|
745 | - /** |
|
746 | - * Overrides the parent to allow for having a dynamic "now" value |
|
747 | - * |
|
748 | - * @return mixed |
|
749 | - */ |
|
750 | - public function get_default_value() |
|
751 | - { |
|
752 | - if ($this->_default_value === EE_Datetime_Field::now) { |
|
753 | - return time(); |
|
754 | - } else { |
|
755 | - return parent::get_default_value(); |
|
756 | - } |
|
757 | - } |
|
758 | - |
|
759 | - |
|
760 | - public function getSchemaDescription() |
|
761 | - { |
|
762 | - return sprintf( |
|
763 | - esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'), |
|
764 | - $this->get_nicename() |
|
765 | - ); |
|
766 | - } |
|
539 | + 'event_espresso' |
|
540 | + ), |
|
541 | + '<br />', |
|
542 | + print_r($datetime_value, true) |
|
543 | + ) |
|
544 | + ); |
|
545 | + } |
|
546 | + |
|
547 | + if ($datetime_value instanceof DateTime) { |
|
548 | + if ( ! $datetime_value instanceof DbSafeDateTime) { |
|
549 | + $datetime_value = DbSafeDateTime::createFromDateTime($datetime_value); |
|
550 | + } |
|
551 | + |
|
552 | + return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format( |
|
553 | + EE_Datetime_Field::mysql_timestamp_format |
|
554 | + ); |
|
555 | + } |
|
556 | + |
|
557 | + // if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true |
|
558 | + return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null; |
|
559 | + } |
|
560 | + |
|
561 | + |
|
562 | + /** |
|
563 | + * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is |
|
564 | + * allowed) |
|
565 | + * |
|
566 | + * @param string $datetime_string mysql timestamp in UTC |
|
567 | + * @return mixed null | DateTime |
|
568 | + * @throws \EE_Error |
|
569 | + */ |
|
570 | + public function prepare_for_set_from_db($datetime_string) |
|
571 | + { |
|
572 | + //if $datetime_value is empty, and ! $this->_nullable, just use time() |
|
573 | + if (empty($datetime_string) && $this->_nullable) { |
|
574 | + return null; |
|
575 | + } |
|
576 | + // datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating |
|
577 | + if (empty($datetime_string)) { |
|
578 | + $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone()); |
|
579 | + } else { |
|
580 | + $DateTime = DateTime::createFromFormat( |
|
581 | + EE_Datetime_Field::mysql_timestamp_format, |
|
582 | + $datetime_string, |
|
583 | + $this->get_UTC_DateTimeZone() |
|
584 | + ); |
|
585 | + if ($DateTime instanceof \DateTime) { |
|
586 | + $DateTime = new DbSafeDateTime( |
|
587 | + $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format), |
|
588 | + $this->get_UTC_DateTimeZone() |
|
589 | + ); |
|
590 | + } |
|
591 | + } |
|
592 | + |
|
593 | + if (! $DateTime instanceof DbSafeDateTime) { |
|
594 | + // if still no datetime object, then let's just use now |
|
595 | + $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone()); |
|
596 | + } |
|
597 | + // THEN apply the field's set DateTimeZone |
|
598 | + $DateTime->setTimezone($this->_DateTimeZone); |
|
599 | + |
|
600 | + return $DateTime; |
|
601 | + } |
|
602 | + |
|
603 | + |
|
604 | + /** |
|
605 | + * All this method does is determine if we're going to display the timezone string or not on any output. |
|
606 | + * To determine this we check if the set timezone offset is different than the blog's set timezone offset. |
|
607 | + * If so, then true. |
|
608 | + * |
|
609 | + * @return bool true for yes false for no |
|
610 | + * @throws \EE_Error |
|
611 | + */ |
|
612 | + protected function _display_timezone() |
|
613 | + { |
|
614 | + |
|
615 | + // first let's do a comparison of timezone strings. |
|
616 | + // If they match then we can get out without any further calculations |
|
617 | + $blog_string = get_option('timezone_string'); |
|
618 | + if ($blog_string === $this->_timezone_string) { |
|
619 | + return false; |
|
620 | + } |
|
621 | + // now we need to calc the offset for the timezone string so we can compare with the blog offset. |
|
622 | + $this_offset = $this->get_timezone_offset($this->_DateTimeZone); |
|
623 | + $blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone()); |
|
624 | + // now compare |
|
625 | + return $blog_offset !== $this_offset; |
|
626 | + } |
|
627 | + |
|
628 | + |
|
629 | + /** |
|
630 | + * This method returns a php DateTime object for setting on the EE_Base_Class model. |
|
631 | + * EE passes around DateTime objects because they are MUCH easier to manipulate and deal |
|
632 | + * with. |
|
633 | + * |
|
634 | + * @param int|string|DateTime $date_string This should be the incoming date string. It's assumed to be |
|
635 | + * in the format that is set on the date_field (or DateTime |
|
636 | + * object)! |
|
637 | + * @return DateTime |
|
638 | + */ |
|
639 | + protected function _get_date_object($date_string) |
|
640 | + { |
|
641 | + //first if this is an empty date_string and nullable is allowed, just return null. |
|
642 | + if ($this->_nullable && empty($date_string)) { |
|
643 | + return null; |
|
644 | + } |
|
645 | + |
|
646 | + // if incoming date |
|
647 | + if ($date_string instanceof DateTime) { |
|
648 | + $date_string->setTimezone($this->_DateTimeZone); |
|
649 | + |
|
650 | + return $date_string; |
|
651 | + } |
|
652 | + // if empty date_string and made it here. |
|
653 | + // Return a datetime object for now in the given timezone. |
|
654 | + if (empty($date_string)) { |
|
655 | + return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
656 | + } |
|
657 | + // if $date_string is matches something that looks like a Unix timestamp let's just use it. |
|
658 | + if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) { |
|
659 | + try { |
|
660 | + // This is operating under the assumption that the incoming Unix timestamp |
|
661 | + // is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp'); |
|
662 | + $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
663 | + $DateTime->setTimestamp($date_string); |
|
664 | + |
|
665 | + return $DateTime; |
|
666 | + } catch (Exception $e) { |
|
667 | + // should be rare, but if things got fooled then let's just continue |
|
668 | + } |
|
669 | + } |
|
670 | + //not a unix timestamp. So we will use the set format on this object and set timezone to |
|
671 | + //create the DateTime object. |
|
672 | + $format = $this->_date_format . ' ' . $this->_time_format; |
|
673 | + try { |
|
674 | + $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone); |
|
675 | + if ($DateTime instanceof DateTime) { |
|
676 | + $DateTime = new DbSafeDateTime( |
|
677 | + $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format), |
|
678 | + $this->_DateTimeZone |
|
679 | + ); |
|
680 | + } |
|
681 | + if (! $DateTime instanceof DbSafeDateTime) { |
|
682 | + throw new EE_Error( |
|
683 | + sprintf( |
|
684 | + __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'), |
|
685 | + $date_string, |
|
686 | + $format |
|
687 | + ) |
|
688 | + ); |
|
689 | + } |
|
690 | + } catch (Exception $e) { |
|
691 | + // if we made it here then likely then something went really wrong. |
|
692 | + // Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone. |
|
693 | + $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone); |
|
694 | + } |
|
695 | + |
|
696 | + return $DateTime; |
|
697 | + } |
|
698 | + |
|
699 | + |
|
700 | + |
|
701 | + /** |
|
702 | + * get_timezone_transitions |
|
703 | + * |
|
704 | + * @param \DateTimeZone $DateTimeZone |
|
705 | + * @param int $time |
|
706 | + * @param bool $first_only |
|
707 | + * @return mixed |
|
708 | + */ |
|
709 | + public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true) |
|
710 | + { |
|
711 | + return EEH_DTT_Helper::get_timezone_transitions($DateTimeZone, $time, $first_only); |
|
712 | + } |
|
713 | + |
|
714 | + |
|
715 | + |
|
716 | + /** |
|
717 | + * get_timezone_offset |
|
718 | + * |
|
719 | + * @param \DateTimeZone $DateTimeZone |
|
720 | + * @param int $time |
|
721 | + * @return mixed |
|
722 | + * @throws \DomainException |
|
723 | + */ |
|
724 | + public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null) |
|
725 | + { |
|
726 | + return EEH_DTT_Helper::get_timezone_offset($DateTimeZone, $time); |
|
727 | + } |
|
728 | + |
|
729 | + |
|
730 | + /** |
|
731 | + * This will take an incoming timezone string and return the abbreviation for that timezone |
|
732 | + * |
|
733 | + * @param string $timezone_string |
|
734 | + * @return string abbreviation |
|
735 | + * @throws \EE_Error |
|
736 | + */ |
|
737 | + public function get_timezone_abbrev($timezone_string) |
|
738 | + { |
|
739 | + $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string); |
|
740 | + $dateTime = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string)); |
|
741 | + |
|
742 | + return $dateTime->format('T'); |
|
743 | + } |
|
744 | + |
|
745 | + /** |
|
746 | + * Overrides the parent to allow for having a dynamic "now" value |
|
747 | + * |
|
748 | + * @return mixed |
|
749 | + */ |
|
750 | + public function get_default_value() |
|
751 | + { |
|
752 | + if ($this->_default_value === EE_Datetime_Field::now) { |
|
753 | + return time(); |
|
754 | + } else { |
|
755 | + return parent::get_default_value(); |
|
756 | + } |
|
757 | + } |
|
758 | + |
|
759 | + |
|
760 | + public function getSchemaDescription() |
|
761 | + { |
|
762 | + return sprintf( |
|
763 | + esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'), |
|
764 | + $this->get_nicename() |
|
765 | + ); |
|
766 | + } |
|
767 | 767 | } |
@@ -1164,7 +1164,7 @@ discard block |
||
1164 | 1164 | * Sets deleted |
1165 | 1165 | * |
1166 | 1166 | * @param boolean $deleted |
1167 | - * @return bool |
|
1167 | + * @return boolean|null |
|
1168 | 1168 | * @throws EE_Error |
1169 | 1169 | * @throws RuntimeException |
1170 | 1170 | */ |
@@ -1222,6 +1222,7 @@ discard block |
||
1222 | 1222 | * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
1223 | 1223 | * @param bool $check_approved This is used to indicate whether the caller wants can_checkin to also |
1224 | 1224 | * consider registration status as well as datetime access. |
1225 | + * @param integer $DTT_OR_ID |
|
1225 | 1226 | * @return bool |
1226 | 1227 | * @throws EE_Error |
1227 | 1228 | */ |
@@ -1392,7 +1393,7 @@ discard block |
||
1392 | 1393 | * Returns the latest datetime related to this registration (via the ticket attached to the registration). |
1393 | 1394 | * "Latest" is defined by the `DTT_EVT_start` column. |
1394 | 1395 | * |
1395 | - * @return EE_Datetime|null |
|
1396 | + * @return null|EE_Base_Class |
|
1396 | 1397 | * @throws EE_Error |
1397 | 1398 | */ |
1398 | 1399 | public function get_latest_related_datetime() |
@@ -1688,7 +1689,7 @@ discard block |
||
1688 | 1689 | * This grabs the payment method corresponding to the last payment made for the amount owing on the registration. |
1689 | 1690 | * Note: if there are no payments on the registration there will be no payment method returned. |
1690 | 1691 | * |
1691 | - * @return EE_Payment_Method|null |
|
1692 | + * @return null|EE_Base_Class |
|
1692 | 1693 | */ |
1693 | 1694 | public function payment_method() |
1694 | 1695 | { |
@@ -18,1985 +18,1985 @@ |
||
18 | 18 | { |
19 | 19 | |
20 | 20 | |
21 | - /** |
|
22 | - * Used to reference when a registration has never been checked in. |
|
23 | - * |
|
24 | - * @deprecated use \EE_Checkin::status_checked_never instead |
|
25 | - * @type int |
|
26 | - */ |
|
27 | - const checkin_status_never = 2; |
|
28 | - |
|
29 | - /** |
|
30 | - * Used to reference when a registration has been checked in. |
|
31 | - * |
|
32 | - * @deprecated use \EE_Checkin::status_checked_in instead |
|
33 | - * @type int |
|
34 | - */ |
|
35 | - const checkin_status_in = 1; |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * Used to reference when a registration has been checked out. |
|
40 | - * |
|
41 | - * @deprecated use \EE_Checkin::status_checked_out instead |
|
42 | - * @type int |
|
43 | - */ |
|
44 | - const checkin_status_out = 0; |
|
45 | - |
|
46 | - |
|
47 | - /** |
|
48 | - * extra meta key for tracking reg status os trashed registrations |
|
49 | - * |
|
50 | - * @type string |
|
51 | - */ |
|
52 | - const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status'; |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * extra meta key for tracking if registration has reserved ticket |
|
57 | - * |
|
58 | - * @type string |
|
59 | - */ |
|
60 | - const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket'; |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * @param array $props_n_values incoming values |
|
65 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
66 | - * used.) |
|
67 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
68 | - * date_format and the second value is the time format |
|
69 | - * @return EE_Registration |
|
70 | - * @throws EE_Error |
|
71 | - */ |
|
72 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
73 | - { |
|
74 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
75 | - return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
76 | - } |
|
77 | - |
|
78 | - |
|
79 | - /** |
|
80 | - * @param array $props_n_values incoming values from the database |
|
81 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
82 | - * the website will be used. |
|
83 | - * @return EE_Registration |
|
84 | - */ |
|
85 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
86 | - { |
|
87 | - return new self($props_n_values, true, $timezone); |
|
88 | - } |
|
89 | - |
|
90 | - |
|
91 | - /** |
|
92 | - * Set Event ID |
|
93 | - * |
|
94 | - * @param int $EVT_ID Event ID |
|
95 | - * @throws EE_Error |
|
96 | - * @throws RuntimeException |
|
97 | - */ |
|
98 | - public function set_event($EVT_ID = 0) |
|
99 | - { |
|
100 | - $this->set('EVT_ID', $EVT_ID); |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can |
|
106 | - * be routed to internal methods |
|
107 | - * |
|
108 | - * @param string $field_name |
|
109 | - * @param mixed $field_value |
|
110 | - * @param bool $use_default |
|
111 | - * @throws EE_Error |
|
112 | - * @throws EntityNotFoundException |
|
113 | - * @throws InvalidArgumentException |
|
114 | - * @throws InvalidDataTypeException |
|
115 | - * @throws InvalidInterfaceException |
|
116 | - * @throws ReflectionException |
|
117 | - * @throws RuntimeException |
|
118 | - */ |
|
119 | - public function set($field_name, $field_value, $use_default = false) |
|
120 | - { |
|
121 | - switch ($field_name) { |
|
122 | - case 'REG_code': |
|
123 | - if (! empty($field_value) && $this->reg_code() === null) { |
|
124 | - $this->set_reg_code($field_value, $use_default); |
|
125 | - } |
|
126 | - break; |
|
127 | - case 'STS_ID': |
|
128 | - $this->set_status($field_value, $use_default); |
|
129 | - break; |
|
130 | - default: |
|
131 | - parent::set($field_name, $field_value, $use_default); |
|
132 | - } |
|
133 | - } |
|
134 | - |
|
135 | - |
|
136 | - /** |
|
137 | - * Set Status ID |
|
138 | - * updates the registration status and ALSO... |
|
139 | - * calls reserve_registration_space() if the reg status changes TO approved from any other reg status |
|
140 | - * calls release_registration_space() if the reg status changes FROM approved to any other reg status |
|
141 | - * |
|
142 | - * @param string $new_STS_ID |
|
143 | - * @param boolean $use_default |
|
144 | - * @param Context|null $context |
|
145 | - * @return bool |
|
146 | - * @throws EE_Error |
|
147 | - * @throws EntityNotFoundException |
|
148 | - * @throws InvalidArgumentException |
|
149 | - * @throws ReflectionException |
|
150 | - * @throws RuntimeException |
|
151 | - * @throws InvalidDataTypeException |
|
152 | - * @throws InvalidInterfaceException |
|
153 | - */ |
|
154 | - public function set_status($new_STS_ID = null, $use_default = false, Context $context = null) |
|
155 | - { |
|
156 | - // get current REG_Status |
|
157 | - $old_STS_ID = $this->status_ID(); |
|
158 | - // if status has changed |
|
159 | - if ($old_STS_ID !== $new_STS_ID // and that status has actually changed |
|
160 | - && ! empty($old_STS_ID) // and that old status is actually set |
|
161 | - && ! empty($new_STS_ID) // as well as the new status |
|
162 | - && $this->ID() // ensure registration is in the db |
|
163 | - ) { |
|
164 | - // TO approved |
|
165 | - if ($new_STS_ID === EEM_Registration::status_id_approved) { |
|
166 | - // reserve a space by incrementing ticket and datetime sold values |
|
167 | - $this->_reserve_registration_space(); |
|
168 | - do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context); |
|
169 | - // OR FROM approved |
|
170 | - } elseif ($old_STS_ID === EEM_Registration::status_id_approved) { |
|
171 | - // release a space by decrementing ticket and datetime sold values |
|
172 | - $this->_release_registration_space(); |
|
173 | - do_action( |
|
174 | - 'AHEE__EE_Registration__set_status__from_approved', |
|
175 | - $this, |
|
176 | - $old_STS_ID, |
|
177 | - $new_STS_ID, |
|
178 | - $context |
|
179 | - ); |
|
180 | - } |
|
181 | - // update status |
|
182 | - parent::set('STS_ID', $new_STS_ID, $use_default); |
|
183 | - $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context); |
|
184 | - if($this->statusChangeUpdatesTransaction($context)) { |
|
185 | - $this->updateTransactionAfterStatusChange(); |
|
186 | - } |
|
187 | - do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context); |
|
188 | - return true; |
|
189 | - } |
|
190 | - //even though the old value matches the new value, it's still good to |
|
191 | - //allow the parent set method to have a say |
|
192 | - parent::set('STS_ID', $new_STS_ID, $use_default); |
|
193 | - return true; |
|
194 | - } |
|
195 | - |
|
196 | - |
|
197 | - /** |
|
198 | - * update REGs and TXN when cancelled or declined registrations involved |
|
199 | - * |
|
200 | - * @param string $new_STS_ID |
|
201 | - * @param string $old_STS_ID |
|
202 | - * @param Context|null $context |
|
203 | - * @throws EE_Error |
|
204 | - * @throws InvalidArgumentException |
|
205 | - * @throws InvalidDataTypeException |
|
206 | - * @throws InvalidInterfaceException |
|
207 | - * @throws ReflectionException |
|
208 | - */ |
|
209 | - private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null) |
|
210 | - { |
|
211 | - // these reg statuses should not be considered in any calculations involving monies owing |
|
212 | - $closed_reg_statuses = EEM_Registration::closed_reg_statuses(); |
|
213 | - // true if registration has been cancelled or declined |
|
214 | - $this->updateIfCanceled( |
|
215 | - $closed_reg_statuses, |
|
216 | - $new_STS_ID, |
|
217 | - $old_STS_ID, |
|
218 | - $context |
|
219 | - ); |
|
220 | - $this->updateIfDeclined( |
|
221 | - $closed_reg_statuses, |
|
222 | - $new_STS_ID, |
|
223 | - $old_STS_ID, |
|
224 | - $context |
|
225 | - ); |
|
226 | - } |
|
227 | - |
|
228 | - |
|
229 | - /** |
|
230 | - * update REGs and TXN when cancelled or declined registrations involved |
|
231 | - * |
|
232 | - * @param array $closed_reg_statuses |
|
233 | - * @param string $new_STS_ID |
|
234 | - * @param string $old_STS_ID |
|
235 | - * @param Context|null $context |
|
236 | - * @throws EE_Error |
|
237 | - * @throws InvalidArgumentException |
|
238 | - * @throws InvalidDataTypeException |
|
239 | - * @throws InvalidInterfaceException |
|
240 | - * @throws ReflectionException |
|
241 | - */ |
|
242 | - private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null) |
|
243 | - { |
|
244 | - // true if registration has been cancelled or declined |
|
245 | - if (in_array($new_STS_ID, $closed_reg_statuses, true) |
|
246 | - && ! in_array($old_STS_ID, $closed_reg_statuses, true) |
|
247 | - ) { |
|
248 | - /** @type EE_Registration_Processor $registration_processor */ |
|
249 | - $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
250 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
251 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
252 | - // cancelled or declined registration |
|
253 | - $registration_processor->update_registration_after_being_canceled_or_declined( |
|
254 | - $this, |
|
255 | - $closed_reg_statuses |
|
256 | - ); |
|
257 | - $transaction_processor->update_transaction_after_canceled_or_declined_registration( |
|
258 | - $this, |
|
259 | - $closed_reg_statuses, |
|
260 | - false |
|
261 | - ); |
|
262 | - do_action( |
|
263 | - 'AHEE__EE_Registration__set_status__canceled_or_declined', |
|
264 | - $this, |
|
265 | - $old_STS_ID, |
|
266 | - $new_STS_ID, |
|
267 | - $context |
|
268 | - ); |
|
269 | - return; |
|
270 | - } |
|
271 | - } |
|
272 | - |
|
273 | - |
|
274 | - /** |
|
275 | - * update REGs and TXN when cancelled or declined registrations involved |
|
276 | - * |
|
277 | - * @param array $closed_reg_statuses |
|
278 | - * @param string $new_STS_ID |
|
279 | - * @param string $old_STS_ID |
|
280 | - * @param Context|null $context |
|
281 | - * @throws EE_Error |
|
282 | - * @throws InvalidArgumentException |
|
283 | - * @throws InvalidDataTypeException |
|
284 | - * @throws InvalidInterfaceException |
|
285 | - * @throws ReflectionException |
|
286 | - */ |
|
287 | - private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null) |
|
288 | - { |
|
289 | - // true if reinstating cancelled or declined registration |
|
290 | - if (in_array($old_STS_ID, $closed_reg_statuses, true) |
|
291 | - && ! in_array($new_STS_ID, $closed_reg_statuses, true) |
|
292 | - ) { |
|
293 | - /** @type EE_Registration_Processor $registration_processor */ |
|
294 | - $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
295 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
296 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
297 | - // reinstating cancelled or declined registration |
|
298 | - $registration_processor->update_canceled_or_declined_registration_after_being_reinstated( |
|
299 | - $this, |
|
300 | - $closed_reg_statuses |
|
301 | - ); |
|
302 | - $transaction_processor->update_transaction_after_reinstating_canceled_registration( |
|
303 | - $this, |
|
304 | - $closed_reg_statuses, |
|
305 | - false |
|
306 | - ); |
|
307 | - do_action( |
|
308 | - 'AHEE__EE_Registration__set_status__after_reinstated', |
|
309 | - $this, |
|
310 | - $old_STS_ID, |
|
311 | - $new_STS_ID, |
|
312 | - $context |
|
313 | - ); |
|
314 | - } |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * @param Context|null $context |
|
320 | - * @return bool |
|
321 | - */ |
|
322 | - private function statusChangeUpdatesTransaction(Context $context = null) |
|
323 | - { |
|
324 | - $contexts_that_do_not_update_transaction = (array) apply_filters( |
|
325 | - 'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction', |
|
326 | - array('spco_reg_step_attendee_information_process_registrations'), |
|
327 | - $context, |
|
328 | - $this |
|
329 | - ); |
|
330 | - return ! ( |
|
331 | - $context instanceof Context |
|
332 | - && in_array($context->slug(), $contexts_that_do_not_update_transaction, true) |
|
333 | - ); |
|
334 | - } |
|
335 | - |
|
336 | - |
|
337 | - /** |
|
338 | - * @throws EE_Error |
|
339 | - * @throws EntityNotFoundException |
|
340 | - * @throws InvalidArgumentException |
|
341 | - * @throws InvalidDataTypeException |
|
342 | - * @throws InvalidInterfaceException |
|
343 | - * @throws ReflectionException |
|
344 | - * @throws RuntimeException |
|
345 | - */ |
|
346 | - private function updateTransactionAfterStatusChange() |
|
347 | - { |
|
348 | - /** @type EE_Transaction_Payments $transaction_payments */ |
|
349 | - $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
350 | - $transaction_payments->recalculate_transaction_total($this->transaction(), false); |
|
351 | - $this->transaction()->update_status_based_on_total_paid(true); |
|
352 | - } |
|
353 | - |
|
354 | - |
|
355 | - /** |
|
356 | - * get Status ID |
|
357 | - */ |
|
358 | - public function status_ID() |
|
359 | - { |
|
360 | - return $this->get('STS_ID'); |
|
361 | - } |
|
362 | - |
|
363 | - |
|
364 | - /** |
|
365 | - * increments this registration's related ticket sold and corresponding datetime sold values |
|
366 | - * |
|
367 | - * @return void |
|
368 | - * @throws EE_Error |
|
369 | - * @throws EntityNotFoundException |
|
370 | - */ |
|
371 | - private function _reserve_registration_space() |
|
372 | - { |
|
373 | - // reserved ticket and datetime counts will be decremented as sold counts are incremented |
|
374 | - // so stop tracking that this reg has a ticket reserved |
|
375 | - $this->release_reserved_ticket(); |
|
376 | - $ticket = $this->ticket(); |
|
377 | - $ticket->increase_sold(); |
|
378 | - $ticket->save(); |
|
379 | - // possibly set event status to sold out |
|
380 | - $this->event()->perform_sold_out_status_check(); |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * Gets the ticket this registration is for |
|
386 | - * |
|
387 | - * @param boolean $include_archived whether to include archived tickets or not. |
|
388 | - * |
|
389 | - * @return EE_Ticket|EE_Base_Class |
|
390 | - * @throws EE_Error |
|
391 | - */ |
|
392 | - public function ticket($include_archived = true) |
|
393 | - { |
|
394 | - $query_params = array(); |
|
395 | - if ($include_archived) { |
|
396 | - $query_params['default_where_conditions'] = 'none'; |
|
397 | - } |
|
398 | - return $this->get_first_related('Ticket', $query_params); |
|
399 | - } |
|
400 | - |
|
401 | - |
|
402 | - /** |
|
403 | - * Gets the event this registration is for |
|
404 | - * |
|
405 | - * @return EE_Event |
|
406 | - * @throws EE_Error |
|
407 | - * @throws EntityNotFoundException |
|
408 | - */ |
|
409 | - public function event() |
|
410 | - { |
|
411 | - $event = $this->get_first_related('Event'); |
|
412 | - if (! $event instanceof \EE_Event) { |
|
413 | - throw new EntityNotFoundException('Event ID', $this->event_ID()); |
|
414 | - } |
|
415 | - return $event; |
|
416 | - } |
|
417 | - |
|
418 | - |
|
419 | - /** |
|
420 | - * Gets the "author" of the registration. Note that for the purposes of registrations, the author will correspond |
|
421 | - * with the author of the event this registration is for. |
|
422 | - * |
|
423 | - * @since 4.5.0 |
|
424 | - * @return int |
|
425 | - * @throws EE_Error |
|
426 | - * @throws EntityNotFoundException |
|
427 | - */ |
|
428 | - public function wp_user() |
|
429 | - { |
|
430 | - $event = $this->event(); |
|
431 | - if ($event instanceof EE_Event) { |
|
432 | - return $event->wp_user(); |
|
433 | - } |
|
434 | - return 0; |
|
435 | - } |
|
436 | - |
|
437 | - |
|
438 | - /** |
|
439 | - * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values |
|
440 | - * |
|
441 | - * @return void |
|
442 | - * @throws EE_Error |
|
443 | - */ |
|
444 | - private function _release_registration_space() |
|
445 | - { |
|
446 | - $ticket = $this->ticket(); |
|
447 | - $ticket->decrease_sold(); |
|
448 | - $ticket->save(); |
|
449 | - } |
|
450 | - |
|
451 | - |
|
452 | - /** |
|
453 | - * tracks this registration's ticket reservation in extra meta |
|
454 | - * and can increment related ticket reserved and corresponding datetime reserved values |
|
455 | - * |
|
456 | - * @param bool $update_ticket if true, will increment ticket and datetime reserved count |
|
457 | - * |
|
458 | - * @return void |
|
459 | - * @throws EE_Error |
|
460 | - */ |
|
461 | - public function reserve_ticket($update_ticket = false) |
|
462 | - { |
|
463 | - if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) { |
|
464 | - // PLZ NOTE: although checking $update_ticket first would be more efficient, |
|
465 | - // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
466 | - if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) { |
|
467 | - $ticket = $this->ticket(); |
|
468 | - $ticket->increase_reserved(); |
|
469 | - $ticket->save(); |
|
470 | - } |
|
471 | - } |
|
472 | - } |
|
473 | - |
|
474 | - |
|
475 | - /** |
|
476 | - * stops tracking this registration's ticket reservation in extra meta |
|
477 | - * decrements (subtracts) related ticket reserved and corresponding datetime reserved values |
|
478 | - * |
|
479 | - * @param bool $update_ticket if true, will decrement ticket and datetime reserved count |
|
480 | - * |
|
481 | - * @return void |
|
482 | - * @throws EE_Error |
|
483 | - */ |
|
484 | - public function release_reserved_ticket($update_ticket = false) |
|
485 | - { |
|
486 | - if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) { |
|
487 | - // PLZ NOTE: although checking $update_ticket first would be more efficient, |
|
488 | - // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first |
|
489 | - if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) { |
|
490 | - $ticket = $this->ticket(); |
|
491 | - $ticket->decrease_reserved(); |
|
492 | - $ticket->save(); |
|
493 | - } |
|
494 | - } |
|
495 | - } |
|
496 | - |
|
497 | - |
|
498 | - /** |
|
499 | - * Set Attendee ID |
|
500 | - * |
|
501 | - * @param int $ATT_ID Attendee ID |
|
502 | - * @throws EE_Error |
|
503 | - * @throws RuntimeException |
|
504 | - */ |
|
505 | - public function set_attendee_id($ATT_ID = 0) |
|
506 | - { |
|
507 | - $this->set('ATT_ID', $ATT_ID); |
|
508 | - } |
|
509 | - |
|
510 | - |
|
511 | - /** |
|
512 | - * Set Transaction ID |
|
513 | - * |
|
514 | - * @param int $TXN_ID Transaction ID |
|
515 | - * @throws EE_Error |
|
516 | - * @throws RuntimeException |
|
517 | - */ |
|
518 | - public function set_transaction_id($TXN_ID = 0) |
|
519 | - { |
|
520 | - $this->set('TXN_ID', $TXN_ID); |
|
521 | - } |
|
522 | - |
|
523 | - |
|
524 | - /** |
|
525 | - * Set Session |
|
526 | - * |
|
527 | - * @param string $REG_session PHP Session ID |
|
528 | - * @throws EE_Error |
|
529 | - * @throws RuntimeException |
|
530 | - */ |
|
531 | - public function set_session($REG_session = '') |
|
532 | - { |
|
533 | - $this->set('REG_session', $REG_session); |
|
534 | - } |
|
535 | - |
|
536 | - |
|
537 | - /** |
|
538 | - * Set Registration URL Link |
|
539 | - * |
|
540 | - * @param string $REG_url_link Registration URL Link |
|
541 | - * @throws EE_Error |
|
542 | - * @throws RuntimeException |
|
543 | - */ |
|
544 | - public function set_reg_url_link($REG_url_link = '') |
|
545 | - { |
|
546 | - $this->set('REG_url_link', $REG_url_link); |
|
547 | - } |
|
548 | - |
|
549 | - |
|
550 | - /** |
|
551 | - * Set Attendee Counter |
|
552 | - * |
|
553 | - * @param int $REG_count Primary Attendee |
|
554 | - * @throws EE_Error |
|
555 | - * @throws RuntimeException |
|
556 | - */ |
|
557 | - public function set_count($REG_count = 1) |
|
558 | - { |
|
559 | - $this->set('REG_count', $REG_count); |
|
560 | - } |
|
561 | - |
|
562 | - |
|
563 | - /** |
|
564 | - * Set Group Size |
|
565 | - * |
|
566 | - * @param boolean $REG_group_size Group Registration |
|
567 | - * @throws EE_Error |
|
568 | - * @throws RuntimeException |
|
569 | - */ |
|
570 | - public function set_group_size($REG_group_size = false) |
|
571 | - { |
|
572 | - $this->set('REG_group_size', $REG_group_size); |
|
573 | - } |
|
574 | - |
|
575 | - |
|
576 | - /** |
|
577 | - * is_not_approved - convenience method that returns TRUE if REG status ID == |
|
578 | - * EEM_Registration::status_id_not_approved |
|
579 | - * |
|
580 | - * @return boolean |
|
581 | - */ |
|
582 | - public function is_not_approved() |
|
583 | - { |
|
584 | - return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false; |
|
585 | - } |
|
586 | - |
|
587 | - |
|
588 | - /** |
|
589 | - * is_pending_payment - convenience method that returns TRUE if REG status ID == |
|
590 | - * EEM_Registration::status_id_pending_payment |
|
591 | - * |
|
592 | - * @return boolean |
|
593 | - */ |
|
594 | - public function is_pending_payment() |
|
595 | - { |
|
596 | - return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false; |
|
597 | - } |
|
598 | - |
|
599 | - |
|
600 | - /** |
|
601 | - * is_approved - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved |
|
602 | - * |
|
603 | - * @return boolean |
|
604 | - */ |
|
605 | - public function is_approved() |
|
606 | - { |
|
607 | - return $this->status_ID() == EEM_Registration::status_id_approved ? true : false; |
|
608 | - } |
|
609 | - |
|
610 | - |
|
611 | - /** |
|
612 | - * is_cancelled - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled |
|
613 | - * |
|
614 | - * @return boolean |
|
615 | - */ |
|
616 | - public function is_cancelled() |
|
617 | - { |
|
618 | - return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false; |
|
619 | - } |
|
620 | - |
|
621 | - |
|
622 | - /** |
|
623 | - * is_declined - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined |
|
624 | - * |
|
625 | - * @return boolean |
|
626 | - */ |
|
627 | - public function is_declined() |
|
628 | - { |
|
629 | - return $this->status_ID() == EEM_Registration::status_id_declined ? true : false; |
|
630 | - } |
|
631 | - |
|
632 | - |
|
633 | - /** |
|
634 | - * is_incomplete - convenience method that returns TRUE if REG status ID == |
|
635 | - * EEM_Registration::status_id_incomplete |
|
636 | - * |
|
637 | - * @return boolean |
|
638 | - */ |
|
639 | - public function is_incomplete() |
|
640 | - { |
|
641 | - return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false; |
|
642 | - } |
|
643 | - |
|
644 | - |
|
645 | - /** |
|
646 | - * Set Registration Date |
|
647 | - * |
|
648 | - * @param mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of |
|
649 | - * Date |
|
650 | - * @throws EE_Error |
|
651 | - * @throws RuntimeException |
|
652 | - */ |
|
653 | - public function set_reg_date($REG_date = false) |
|
654 | - { |
|
655 | - $this->set('REG_date', $REG_date); |
|
656 | - } |
|
657 | - |
|
658 | - |
|
659 | - /** |
|
660 | - * Set final price owing for this registration after all ticket/price modifications |
|
661 | - * |
|
662 | - * @access public |
|
663 | - * @param float $REG_final_price |
|
664 | - * @throws EE_Error |
|
665 | - * @throws RuntimeException |
|
666 | - */ |
|
667 | - public function set_final_price($REG_final_price = 0.00) |
|
668 | - { |
|
669 | - $this->set('REG_final_price', $REG_final_price); |
|
670 | - } |
|
671 | - |
|
672 | - |
|
673 | - /** |
|
674 | - * Set amount paid towards this registration's final price |
|
675 | - * |
|
676 | - * @access public |
|
677 | - * @param float $REG_paid |
|
678 | - * @throws EE_Error |
|
679 | - * @throws RuntimeException |
|
680 | - */ |
|
681 | - public function set_paid($REG_paid = 0.00) |
|
682 | - { |
|
683 | - $this->set('REG_paid', $REG_paid); |
|
684 | - } |
|
685 | - |
|
686 | - |
|
687 | - /** |
|
688 | - * Attendee Is Going |
|
689 | - * |
|
690 | - * @param boolean $REG_att_is_going Attendee Is Going |
|
691 | - * @throws EE_Error |
|
692 | - * @throws RuntimeException |
|
693 | - */ |
|
694 | - public function set_att_is_going($REG_att_is_going = false) |
|
695 | - { |
|
696 | - $this->set('REG_att_is_going', $REG_att_is_going); |
|
697 | - } |
|
698 | - |
|
699 | - |
|
700 | - /** |
|
701 | - * Gets the related attendee |
|
702 | - * |
|
703 | - * @return EE_Attendee |
|
704 | - * @throws EE_Error |
|
705 | - */ |
|
706 | - public function attendee() |
|
707 | - { |
|
708 | - return $this->get_first_related('Attendee'); |
|
709 | - } |
|
710 | - |
|
711 | - |
|
712 | - /** |
|
713 | - * get Event ID |
|
714 | - */ |
|
715 | - public function event_ID() |
|
716 | - { |
|
717 | - return $this->get('EVT_ID'); |
|
718 | - } |
|
719 | - |
|
720 | - |
|
721 | - /** |
|
722 | - * get Event ID |
|
723 | - */ |
|
724 | - public function event_name() |
|
725 | - { |
|
726 | - $event = $this->event_obj(); |
|
727 | - if ($event) { |
|
728 | - return $event->name(); |
|
729 | - } else { |
|
730 | - return null; |
|
731 | - } |
|
732 | - } |
|
733 | - |
|
734 | - |
|
735 | - /** |
|
736 | - * Fetches the event this registration is for |
|
737 | - * |
|
738 | - * @return EE_Event |
|
739 | - * @throws EE_Error |
|
740 | - */ |
|
741 | - public function event_obj() |
|
742 | - { |
|
743 | - return $this->get_first_related('Event'); |
|
744 | - } |
|
745 | - |
|
746 | - |
|
747 | - /** |
|
748 | - * get Attendee ID |
|
749 | - */ |
|
750 | - public function attendee_ID() |
|
751 | - { |
|
752 | - return $this->get('ATT_ID'); |
|
753 | - } |
|
754 | - |
|
755 | - |
|
756 | - /** |
|
757 | - * get PHP Session ID |
|
758 | - */ |
|
759 | - public function session_ID() |
|
760 | - { |
|
761 | - return $this->get('REG_session'); |
|
762 | - } |
|
763 | - |
|
764 | - |
|
765 | - /** |
|
766 | - * Gets the string which represents the URL trigger for the receipt template in the message template system. |
|
767 | - * |
|
768 | - * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
769 | - * @return string |
|
770 | - */ |
|
771 | - public function receipt_url($messenger = 'html') |
|
772 | - { |
|
773 | - |
|
774 | - /** |
|
775 | - * The below will be deprecated one version after this. We check first if there is a custom receipt template |
|
776 | - * already in use on old system. If there is then we just return the standard url for it. |
|
777 | - * |
|
778 | - * @since 4.5.0 |
|
779 | - */ |
|
780 | - $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php'; |
|
781 | - $has_custom = EEH_Template::locate_template( |
|
782 | - $template_relative_path, |
|
783 | - array(), |
|
784 | - true, |
|
785 | - true, |
|
786 | - true |
|
787 | - ); |
|
788 | - |
|
789 | - if ($has_custom) { |
|
790 | - return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch')); |
|
791 | - } |
|
792 | - return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt'); |
|
793 | - } |
|
794 | - |
|
795 | - |
|
796 | - /** |
|
797 | - * Gets the string which represents the URL trigger for the invoice template in the message template system. |
|
798 | - * |
|
799 | - * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
800 | - * @return string |
|
801 | - * @throws EE_Error |
|
802 | - */ |
|
803 | - public function invoice_url($messenger = 'html') |
|
804 | - { |
|
805 | - /** |
|
806 | - * The below will be deprecated one version after this. We check first if there is a custom invoice template |
|
807 | - * already in use on old system. If there is then we just return the standard url for it. |
|
808 | - * |
|
809 | - * @since 4.5.0 |
|
810 | - */ |
|
811 | - $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php'; |
|
812 | - $has_custom = EEH_Template::locate_template( |
|
813 | - $template_relative_path, |
|
814 | - array(), |
|
815 | - true, |
|
816 | - true, |
|
817 | - true |
|
818 | - ); |
|
819 | - |
|
820 | - if ($has_custom) { |
|
821 | - if ($messenger == 'html') { |
|
822 | - return $this->invoice_url('launch'); |
|
823 | - } |
|
824 | - $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice'; |
|
825 | - |
|
826 | - $query_args = array('ee' => $route, 'id' => $this->reg_url_link()); |
|
827 | - if ($messenger == 'html') { |
|
828 | - $query_args['html'] = true; |
|
829 | - } |
|
830 | - return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id)); |
|
831 | - } |
|
832 | - return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice'); |
|
833 | - } |
|
834 | - |
|
835 | - |
|
836 | - /** |
|
837 | - * get Registration URL Link |
|
838 | - * |
|
839 | - * @access public |
|
840 | - * @return string |
|
841 | - * @throws EE_Error |
|
842 | - */ |
|
843 | - public function reg_url_link() |
|
844 | - { |
|
845 | - return (string) $this->get('REG_url_link'); |
|
846 | - } |
|
847 | - |
|
848 | - |
|
849 | - /** |
|
850 | - * Echoes out invoice_url() |
|
851 | - * |
|
852 | - * @param string $type 'download','launch', or 'html' (default is 'launch') |
|
853 | - * @return void |
|
854 | - * @throws EE_Error |
|
855 | - */ |
|
856 | - public function e_invoice_url($type = 'launch') |
|
857 | - { |
|
858 | - echo $this->invoice_url($type); |
|
859 | - } |
|
860 | - |
|
861 | - |
|
862 | - /** |
|
863 | - * Echoes out payment_overview_url |
|
864 | - */ |
|
865 | - public function e_payment_overview_url() |
|
866 | - { |
|
867 | - echo $this->payment_overview_url(); |
|
868 | - } |
|
869 | - |
|
870 | - |
|
871 | - /** |
|
872 | - * Gets the URL of the thank you page with this registration REG_url_link added as |
|
873 | - * a query parameter |
|
874 | - * |
|
875 | - * @param bool $clear_session Set to true when you want to clear the session on revisiting the |
|
876 | - * payment overview url. |
|
877 | - * @return string |
|
878 | - * @throws EE_Error |
|
879 | - */ |
|
880 | - public function payment_overview_url($clear_session = false) |
|
881 | - { |
|
882 | - return add_query_arg(array( |
|
883 | - 'e_reg_url_link' => $this->reg_url_link(), |
|
884 | - 'step' => 'payment_options', |
|
885 | - 'revisit' => true, |
|
886 | - 'clear_session' => (bool) $clear_session |
|
887 | - ), EE_Registry::instance()->CFG->core->reg_page_url()); |
|
888 | - } |
|
889 | - |
|
890 | - |
|
891 | - /** |
|
892 | - * Gets the URL of the thank you page with this registration REG_url_link added as |
|
893 | - * a query parameter |
|
894 | - * |
|
895 | - * @return string |
|
896 | - * @throws EE_Error |
|
897 | - */ |
|
898 | - public function edit_attendee_information_url() |
|
899 | - { |
|
900 | - return add_query_arg(array( |
|
901 | - 'e_reg_url_link' => $this->reg_url_link(), |
|
902 | - 'step' => 'attendee_information', |
|
903 | - 'revisit' => true, |
|
904 | - ), EE_Registry::instance()->CFG->core->reg_page_url()); |
|
905 | - } |
|
906 | - |
|
907 | - |
|
908 | - /** |
|
909 | - * Simply generates and returns the appropriate admin_url link to edit this registration |
|
910 | - * |
|
911 | - * @return string |
|
912 | - * @throws EE_Error |
|
913 | - */ |
|
914 | - public function get_admin_edit_url() |
|
915 | - { |
|
916 | - return EEH_URL::add_query_args_and_nonce(array( |
|
917 | - 'page' => 'espresso_registrations', |
|
918 | - 'action' => 'view_registration', |
|
919 | - '_REG_ID' => $this->ID(), |
|
920 | - ), admin_url('admin.php')); |
|
921 | - } |
|
922 | - |
|
923 | - |
|
924 | - /** |
|
925 | - * is_primary_registrant? |
|
926 | - */ |
|
927 | - public function is_primary_registrant() |
|
928 | - { |
|
929 | - return $this->get('REG_count') == 1 ? true : false; |
|
930 | - } |
|
931 | - |
|
932 | - |
|
933 | - /** |
|
934 | - * This returns the primary registration object for this registration group (which may be this object). |
|
935 | - * |
|
936 | - * @return EE_Registration |
|
937 | - * @throws EE_Error |
|
938 | - */ |
|
939 | - public function get_primary_registration() |
|
940 | - { |
|
941 | - if ($this->is_primary_registrant()) { |
|
942 | - return $this; |
|
943 | - } |
|
944 | - |
|
945 | - //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1 |
|
946 | - /** @var EE_Registration $primary_registrant */ |
|
947 | - $primary_registrant = EEM_Registration::instance()->get_one(array( |
|
948 | - array( |
|
949 | - 'TXN_ID' => $this->transaction_ID(), |
|
950 | - 'REG_count' => 1, |
|
951 | - ), |
|
952 | - )); |
|
953 | - return $primary_registrant; |
|
954 | - } |
|
955 | - |
|
956 | - |
|
957 | - /** |
|
958 | - * get Attendee Number |
|
959 | - * |
|
960 | - * @access public |
|
961 | - */ |
|
962 | - public function count() |
|
963 | - { |
|
964 | - return $this->get('REG_count'); |
|
965 | - } |
|
966 | - |
|
967 | - |
|
968 | - /** |
|
969 | - * get Group Size |
|
970 | - */ |
|
971 | - public function group_size() |
|
972 | - { |
|
973 | - return $this->get('REG_group_size'); |
|
974 | - } |
|
975 | - |
|
976 | - |
|
977 | - /** |
|
978 | - * get Registration Date |
|
979 | - */ |
|
980 | - public function date() |
|
981 | - { |
|
982 | - return $this->get('REG_date'); |
|
983 | - } |
|
984 | - |
|
985 | - |
|
986 | - /** |
|
987 | - * gets a pretty date |
|
988 | - * |
|
989 | - * @param string $date_format |
|
990 | - * @param string $time_format |
|
991 | - * @return string |
|
992 | - * @throws EE_Error |
|
993 | - */ |
|
994 | - public function pretty_date($date_format = null, $time_format = null) |
|
995 | - { |
|
996 | - return $this->get_datetime('REG_date', $date_format, $time_format); |
|
997 | - } |
|
998 | - |
|
999 | - |
|
1000 | - /** |
|
1001 | - * final_price |
|
1002 | - * the registration's share of the transaction total, so that the |
|
1003 | - * sum of all the transaction's REG_final_prices equal the transaction's total |
|
1004 | - * |
|
1005 | - * @return float |
|
1006 | - * @throws EE_Error |
|
1007 | - */ |
|
1008 | - public function final_price() |
|
1009 | - { |
|
1010 | - return $this->get('REG_final_price'); |
|
1011 | - } |
|
1012 | - |
|
1013 | - |
|
1014 | - /** |
|
1015 | - * pretty_final_price |
|
1016 | - * final price as formatted string, with correct decimal places and currency symbol |
|
1017 | - * |
|
1018 | - * @return string |
|
1019 | - * @throws EE_Error |
|
1020 | - */ |
|
1021 | - public function pretty_final_price() |
|
1022 | - { |
|
1023 | - return $this->get_pretty('REG_final_price'); |
|
1024 | - } |
|
1025 | - |
|
1026 | - |
|
1027 | - /** |
|
1028 | - * get paid (yeah) |
|
1029 | - * |
|
1030 | - * @return float |
|
1031 | - * @throws EE_Error |
|
1032 | - */ |
|
1033 | - public function paid() |
|
1034 | - { |
|
1035 | - return $this->get('REG_paid'); |
|
1036 | - } |
|
1037 | - |
|
1038 | - |
|
1039 | - /** |
|
1040 | - * pretty_paid |
|
1041 | - * |
|
1042 | - * @return float |
|
1043 | - * @throws EE_Error |
|
1044 | - */ |
|
1045 | - public function pretty_paid() |
|
1046 | - { |
|
1047 | - return $this->get_pretty('REG_paid'); |
|
1048 | - } |
|
1049 | - |
|
1050 | - |
|
1051 | - /** |
|
1052 | - * owes_monies_and_can_pay |
|
1053 | - * whether or not this registration has monies owing and it's' status allows payment |
|
1054 | - * |
|
1055 | - * @param array $requires_payment |
|
1056 | - * @return bool |
|
1057 | - * @throws EE_Error |
|
1058 | - */ |
|
1059 | - public function owes_monies_and_can_pay($requires_payment = array()) |
|
1060 | - { |
|
1061 | - // these reg statuses require payment (if event is not free) |
|
1062 | - $requires_payment = ! empty($requires_payment) |
|
1063 | - ? $requires_payment |
|
1064 | - : EEM_Registration::reg_statuses_that_allow_payment(); |
|
1065 | - if (in_array($this->status_ID(), $requires_payment) && |
|
1066 | - $this->final_price() != 0 && |
|
1067 | - $this->final_price() != $this->paid() |
|
1068 | - ) { |
|
1069 | - return true; |
|
1070 | - } else { |
|
1071 | - return false; |
|
1072 | - } |
|
1073 | - } |
|
1074 | - |
|
1075 | - |
|
1076 | - /** |
|
1077 | - * Prints out the return value of $this->pretty_status() |
|
1078 | - * |
|
1079 | - * @param bool $show_icons |
|
1080 | - * @return void |
|
1081 | - * @throws EE_Error |
|
1082 | - */ |
|
1083 | - public function e_pretty_status($show_icons = false) |
|
1084 | - { |
|
1085 | - echo $this->pretty_status($show_icons); |
|
1086 | - } |
|
1087 | - |
|
1088 | - |
|
1089 | - /** |
|
1090 | - * Returns a nice version of the status for displaying to customers |
|
1091 | - * |
|
1092 | - * @param bool $show_icons |
|
1093 | - * @return string |
|
1094 | - * @throws EE_Error |
|
1095 | - */ |
|
1096 | - public function pretty_status($show_icons = false) |
|
1097 | - { |
|
1098 | - $status = EEM_Status::instance()->localized_status( |
|
1099 | - array($this->status_ID() => esc_html__('unknown', 'event_espresso')), |
|
1100 | - false, |
|
1101 | - 'sentence' |
|
1102 | - ); |
|
1103 | - $icon = ''; |
|
1104 | - switch ($this->status_ID()) { |
|
1105 | - case EEM_Registration::status_id_approved: |
|
1106 | - $icon = $show_icons |
|
1107 | - ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>' |
|
1108 | - : ''; |
|
1109 | - break; |
|
1110 | - case EEM_Registration::status_id_pending_payment: |
|
1111 | - $icon = $show_icons |
|
1112 | - ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>' |
|
1113 | - : ''; |
|
1114 | - break; |
|
1115 | - case EEM_Registration::status_id_not_approved: |
|
1116 | - $icon = $show_icons |
|
1117 | - ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>' |
|
1118 | - : ''; |
|
1119 | - break; |
|
1120 | - case EEM_Registration::status_id_cancelled: |
|
1121 | - $icon = $show_icons |
|
1122 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>' |
|
1123 | - : ''; |
|
1124 | - break; |
|
1125 | - case EEM_Registration::status_id_incomplete: |
|
1126 | - $icon = $show_icons |
|
1127 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>' |
|
1128 | - : ''; |
|
1129 | - break; |
|
1130 | - case EEM_Registration::status_id_declined: |
|
1131 | - $icon = $show_icons |
|
1132 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' |
|
1133 | - : ''; |
|
1134 | - break; |
|
1135 | - case EEM_Registration::status_id_wait_list: |
|
1136 | - $icon = $show_icons |
|
1137 | - ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>' |
|
1138 | - : ''; |
|
1139 | - break; |
|
1140 | - } |
|
1141 | - return $icon . $status[$this->status_ID()]; |
|
1142 | - } |
|
1143 | - |
|
1144 | - |
|
1145 | - /** |
|
1146 | - * get Attendee Is Going |
|
1147 | - */ |
|
1148 | - public function att_is_going() |
|
1149 | - { |
|
1150 | - return $this->get('REG_att_is_going'); |
|
1151 | - } |
|
1152 | - |
|
1153 | - |
|
1154 | - /** |
|
1155 | - * Gets related answers |
|
1156 | - * |
|
1157 | - * @param array $query_params like EEM_Base::get_all |
|
1158 | - * @return EE_Answer[] |
|
1159 | - * @throws EE_Error |
|
1160 | - */ |
|
1161 | - public function answers($query_params = null) |
|
1162 | - { |
|
1163 | - return $this->get_many_related('Answer', $query_params); |
|
1164 | - } |
|
1165 | - |
|
1166 | - |
|
1167 | - /** |
|
1168 | - * Gets the registration's answer value to the specified question |
|
1169 | - * (either the question's ID or a question object) |
|
1170 | - * |
|
1171 | - * @param EE_Question|int $question |
|
1172 | - * @param bool $pretty_value |
|
1173 | - * @return array|string if pretty_value= true, the result will always be a string |
|
1174 | - * (because the answer might be an array of answer values, so passing pretty_value=true |
|
1175 | - * will convert it into some kind of string) |
|
1176 | - * @throws EE_Error |
|
1177 | - */ |
|
1178 | - public function answer_value_to_question($question, $pretty_value = true) |
|
1179 | - { |
|
1180 | - $question_id = EEM_Question::instance()->ensure_is_ID($question); |
|
1181 | - return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value); |
|
1182 | - } |
|
1183 | - |
|
1184 | - |
|
1185 | - /** |
|
1186 | - * question_groups |
|
1187 | - * returns an array of EE_Question_Group objects for this registration |
|
1188 | - * |
|
1189 | - * @return EE_Question_Group[] |
|
1190 | - * @throws EE_Error |
|
1191 | - * @throws EntityNotFoundException |
|
1192 | - */ |
|
1193 | - public function question_groups() |
|
1194 | - { |
|
1195 | - $question_groups = array(); |
|
1196 | - if ($this->event() instanceof EE_Event) { |
|
1197 | - $question_groups = $this->event()->question_groups( |
|
1198 | - array( |
|
1199 | - array( |
|
1200 | - 'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false, |
|
1201 | - ), |
|
1202 | - 'order_by' => array('QSG_order' => 'ASC'), |
|
1203 | - ) |
|
1204 | - ); |
|
1205 | - } |
|
1206 | - return $question_groups; |
|
1207 | - } |
|
1208 | - |
|
1209 | - |
|
1210 | - /** |
|
1211 | - * count_question_groups |
|
1212 | - * returns a count of the number of EE_Question_Group objects for this registration |
|
1213 | - * |
|
1214 | - * @return int |
|
1215 | - * @throws EE_Error |
|
1216 | - * @throws EntityNotFoundException |
|
1217 | - */ |
|
1218 | - public function count_question_groups() |
|
1219 | - { |
|
1220 | - $qg_count = 0; |
|
1221 | - if ($this->event() instanceof EE_Event) { |
|
1222 | - $qg_count = $this->event()->count_related( |
|
1223 | - 'Question_Group', |
|
1224 | - array( |
|
1225 | - array( |
|
1226 | - 'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false, |
|
1227 | - ), |
|
1228 | - ) |
|
1229 | - ); |
|
1230 | - } |
|
1231 | - return $qg_count; |
|
1232 | - } |
|
1233 | - |
|
1234 | - |
|
1235 | - /** |
|
1236 | - * Returns the registration date in the 'standard' string format |
|
1237 | - * (function may be improved in the future to allow for different formats and timezones) |
|
1238 | - * |
|
1239 | - * @return string |
|
1240 | - * @throws EE_Error |
|
1241 | - */ |
|
1242 | - public function reg_date() |
|
1243 | - { |
|
1244 | - return $this->get_datetime('REG_date'); |
|
1245 | - } |
|
1246 | - |
|
1247 | - |
|
1248 | - /** |
|
1249 | - * Gets the datetime-ticket for this registration (ie, it can be used to isolate |
|
1250 | - * the ticket this registration purchased, or the datetime they have registered |
|
1251 | - * to attend) |
|
1252 | - * |
|
1253 | - * @return EE_Datetime_Ticket |
|
1254 | - * @throws EE_Error |
|
1255 | - */ |
|
1256 | - public function datetime_ticket() |
|
1257 | - { |
|
1258 | - return $this->get_first_related('Datetime_Ticket'); |
|
1259 | - } |
|
1260 | - |
|
1261 | - |
|
1262 | - /** |
|
1263 | - * Sets the registration's datetime_ticket. |
|
1264 | - * |
|
1265 | - * @param EE_Datetime_Ticket $datetime_ticket |
|
1266 | - * @return EE_Datetime_Ticket |
|
1267 | - * @throws EE_Error |
|
1268 | - */ |
|
1269 | - public function set_datetime_ticket($datetime_ticket) |
|
1270 | - { |
|
1271 | - return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket'); |
|
1272 | - } |
|
1273 | - |
|
1274 | - /** |
|
1275 | - * Gets deleted |
|
1276 | - * |
|
1277 | - * @return bool |
|
1278 | - * @throws EE_Error |
|
1279 | - */ |
|
1280 | - public function deleted() |
|
1281 | - { |
|
1282 | - return $this->get('REG_deleted'); |
|
1283 | - } |
|
1284 | - |
|
1285 | - /** |
|
1286 | - * Sets deleted |
|
1287 | - * |
|
1288 | - * @param boolean $deleted |
|
1289 | - * @return bool |
|
1290 | - * @throws EE_Error |
|
1291 | - * @throws RuntimeException |
|
1292 | - */ |
|
1293 | - public function set_deleted($deleted) |
|
1294 | - { |
|
1295 | - if ($deleted) { |
|
1296 | - $this->delete(); |
|
1297 | - } else { |
|
1298 | - $this->restore(); |
|
1299 | - } |
|
1300 | - } |
|
1301 | - |
|
1302 | - |
|
1303 | - /** |
|
1304 | - * Get the status object of this object |
|
1305 | - * |
|
1306 | - * @return EE_Status |
|
1307 | - * @throws EE_Error |
|
1308 | - */ |
|
1309 | - public function status_obj() |
|
1310 | - { |
|
1311 | - return $this->get_first_related('Status'); |
|
1312 | - } |
|
1313 | - |
|
1314 | - |
|
1315 | - /** |
|
1316 | - * Returns the number of times this registration has checked into any of the datetimes |
|
1317 | - * its available for |
|
1318 | - * |
|
1319 | - * @return int |
|
1320 | - * @throws EE_Error |
|
1321 | - */ |
|
1322 | - public function count_checkins() |
|
1323 | - { |
|
1324 | - return $this->get_model()->count_related($this, 'Checkin'); |
|
1325 | - } |
|
1326 | - |
|
1327 | - |
|
1328 | - /** |
|
1329 | - * Returns the number of current Check-ins this registration is checked into for any of the datetimes the |
|
1330 | - * registration is for. Note, this is ONLY checked in (does not include checkedout) |
|
1331 | - * |
|
1332 | - * @return int |
|
1333 | - * @throws EE_Error |
|
1334 | - */ |
|
1335 | - public function count_checkins_not_checkedout() |
|
1336 | - { |
|
1337 | - return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1))); |
|
1338 | - } |
|
1339 | - |
|
1340 | - |
|
1341 | - /** |
|
1342 | - * The purpose of this method is simply to check whether this registration can checkin to the given datetime. |
|
1343 | - * |
|
1344 | - * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
1345 | - * @param bool $check_approved This is used to indicate whether the caller wants can_checkin to also |
|
1346 | - * consider registration status as well as datetime access. |
|
1347 | - * @return bool |
|
1348 | - * @throws EE_Error |
|
1349 | - */ |
|
1350 | - public function can_checkin($DTT_OR_ID, $check_approved = true) |
|
1351 | - { |
|
1352 | - $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
1353 | - |
|
1354 | - //first check registration status |
|
1355 | - if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) { |
|
1356 | - return false; |
|
1357 | - } |
|
1358 | - //is there a datetime ticket that matches this dtt_ID? |
|
1359 | - if (! (EEM_Datetime_Ticket::instance()->exists(array( |
|
1360 | - array( |
|
1361 | - 'TKT_ID' => $this->get('TKT_ID'), |
|
1362 | - 'DTT_ID' => $DTT_ID, |
|
1363 | - ), |
|
1364 | - ))) |
|
1365 | - ) { |
|
1366 | - return false; |
|
1367 | - } |
|
1368 | - |
|
1369 | - //final check is against TKT_uses |
|
1370 | - return $this->verify_can_checkin_against_TKT_uses($DTT_ID); |
|
1371 | - } |
|
1372 | - |
|
1373 | - |
|
1374 | - /** |
|
1375 | - * This method verifies whether the user can checkin for the given datetime considering the max uses value set on |
|
1376 | - * the ticket. To do this, a query is done to get the count of the datetime records already checked into. If the |
|
1377 | - * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses, |
|
1378 | - * then return false. Otherwise return true. |
|
1379 | - * |
|
1380 | - * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
1381 | - * @return bool true means can checkin. false means cannot checkin. |
|
1382 | - * @throws EE_Error |
|
1383 | - */ |
|
1384 | - public function verify_can_checkin_against_TKT_uses($DTT_OR_ID) |
|
1385 | - { |
|
1386 | - $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
1387 | - |
|
1388 | - if (! $DTT_ID) { |
|
1389 | - return false; |
|
1390 | - } |
|
1391 | - |
|
1392 | - $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF; |
|
1393 | - |
|
1394 | - // if max uses is not set or equals infinity then return true cause its not a factor for whether user can |
|
1395 | - // check-in or not. |
|
1396 | - if (! $max_uses || $max_uses === EE_INF) { |
|
1397 | - return true; |
|
1398 | - } |
|
1399 | - |
|
1400 | - //does this datetime have a checkin record? If so, then the dtt count has already been verified so we can just |
|
1401 | - //go ahead and toggle. |
|
1402 | - if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) { |
|
1403 | - return true; |
|
1404 | - } |
|
1405 | - |
|
1406 | - //made it here so the last check is whether the number of checkins per unique datetime on this registration |
|
1407 | - //disallows further check-ins. |
|
1408 | - $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array( |
|
1409 | - array( |
|
1410 | - 'REG_ID' => $this->ID(), |
|
1411 | - 'CHK_in' => true, |
|
1412 | - ), |
|
1413 | - ), 'DTT_ID', true); |
|
1414 | - // checkins have already reached their max number of uses |
|
1415 | - // so registrant can NOT checkin |
|
1416 | - if ($count_unique_dtt_checkins >= $max_uses) { |
|
1417 | - EE_Error::add_error( |
|
1418 | - esc_html__( |
|
1419 | - 'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.', |
|
1420 | - 'event_espresso' |
|
1421 | - ), |
|
1422 | - __FILE__, |
|
1423 | - __FUNCTION__, |
|
1424 | - __LINE__ |
|
1425 | - ); |
|
1426 | - return false; |
|
1427 | - } |
|
1428 | - return true; |
|
1429 | - } |
|
1430 | - |
|
1431 | - |
|
1432 | - /** |
|
1433 | - * toggle Check-in status for this registration |
|
1434 | - * Check-ins are toggled in the following order: |
|
1435 | - * never checked in -> checked in |
|
1436 | - * checked in -> checked out |
|
1437 | - * checked out -> checked in |
|
1438 | - * |
|
1439 | - * @param int $DTT_ID include specific datetime to toggle Check-in for. |
|
1440 | - * If not included or null, then it is assumed latest datetime is being toggled. |
|
1441 | - * @param bool $verify If true then can_checkin() is used to verify whether the person |
|
1442 | - * can be checked in or not. Otherwise this forces change in checkin status. |
|
1443 | - * @return bool|int the chk_in status toggled to OR false if nothing got changed. |
|
1444 | - * @throws EE_Error |
|
1445 | - */ |
|
1446 | - public function toggle_checkin_status($DTT_ID = null, $verify = false) |
|
1447 | - { |
|
1448 | - if (empty($DTT_ID)) { |
|
1449 | - $datetime = $this->get_latest_related_datetime(); |
|
1450 | - $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0; |
|
1451 | - // verify the registration can checkin for the given DTT_ID |
|
1452 | - } elseif (! $this->can_checkin($DTT_ID, $verify)) { |
|
1453 | - EE_Error::add_error( |
|
1454 | - sprintf( |
|
1455 | - esc_html__( |
|
1456 | - 'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access', |
|
1457 | - 'event_espresso' |
|
1458 | - ), |
|
1459 | - $this->ID(), |
|
1460 | - $DTT_ID |
|
1461 | - ), |
|
1462 | - __FILE__, |
|
1463 | - __FUNCTION__, |
|
1464 | - __LINE__ |
|
1465 | - ); |
|
1466 | - return false; |
|
1467 | - } |
|
1468 | - $status_paths = array( |
|
1469 | - EE_Checkin::status_checked_never => EE_Checkin::status_checked_in, |
|
1470 | - EE_Checkin::status_checked_in => EE_Checkin::status_checked_out, |
|
1471 | - EE_Checkin::status_checked_out => EE_Checkin::status_checked_in, |
|
1472 | - ); |
|
1473 | - //start by getting the current status so we know what status we'll be changing to. |
|
1474 | - $cur_status = $this->check_in_status_for_datetime($DTT_ID, null); |
|
1475 | - $status_to = $status_paths[$cur_status]; |
|
1476 | - // database only records true for checked IN or false for checked OUT |
|
1477 | - // no record ( null ) means checked in NEVER, but we obviously don't save that |
|
1478 | - $new_status = $status_to === EE_Checkin::status_checked_in ? true : false; |
|
1479 | - // add relation - note Check-ins are always creating new rows |
|
1480 | - // because we are keeping track of Check-ins over time. |
|
1481 | - // Eventually we'll probably want to show a list table |
|
1482 | - // for the individual Check-ins so that they can be managed. |
|
1483 | - $checkin = EE_Checkin::new_instance(array( |
|
1484 | - 'REG_ID' => $this->ID(), |
|
1485 | - 'DTT_ID' => $DTT_ID, |
|
1486 | - 'CHK_in' => $new_status, |
|
1487 | - )); |
|
1488 | - // if the record could not be saved then return false |
|
1489 | - if ($checkin->save() === 0) { |
|
1490 | - if (WP_DEBUG) { |
|
1491 | - global $wpdb; |
|
1492 | - $error = sprintf( |
|
1493 | - esc_html__( |
|
1494 | - 'Registration check in update failed because of the following database error: %1$s%2$s', |
|
1495 | - 'event_espresso' |
|
1496 | - ), |
|
1497 | - '<br />', |
|
1498 | - $wpdb->last_error |
|
1499 | - ); |
|
1500 | - } else { |
|
1501 | - $error = esc_html__( |
|
1502 | - 'Registration check in update failed because of an unknown database error', |
|
1503 | - 'event_espresso' |
|
1504 | - ); |
|
1505 | - } |
|
1506 | - EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
1507 | - return false; |
|
1508 | - } |
|
1509 | - return $status_to; |
|
1510 | - } |
|
1511 | - |
|
1512 | - |
|
1513 | - /** |
|
1514 | - * Returns the latest datetime related to this registration (via the ticket attached to the registration). |
|
1515 | - * "Latest" is defined by the `DTT_EVT_start` column. |
|
1516 | - * |
|
1517 | - * @return EE_Datetime|null |
|
1518 | - * @throws EE_Error |
|
1519 | - */ |
|
1520 | - public function get_latest_related_datetime() |
|
1521 | - { |
|
1522 | - return EEM_Datetime::instance()->get_one( |
|
1523 | - array( |
|
1524 | - array( |
|
1525 | - 'Ticket.Registration.REG_ID' => $this->ID(), |
|
1526 | - ), |
|
1527 | - 'order_by' => array('DTT_EVT_start' => 'DESC'), |
|
1528 | - ) |
|
1529 | - ); |
|
1530 | - } |
|
1531 | - |
|
1532 | - |
|
1533 | - /** |
|
1534 | - * Returns the earliest datetime related to this registration (via the ticket attached to the registration). |
|
1535 | - * "Earliest" is defined by the `DTT_EVT_start` column. |
|
1536 | - * |
|
1537 | - * @throws EE_Error |
|
1538 | - */ |
|
1539 | - public function get_earliest_related_datetime() |
|
1540 | - { |
|
1541 | - return EEM_Datetime::instance()->get_one( |
|
1542 | - array( |
|
1543 | - array( |
|
1544 | - 'Ticket.Registration.REG_ID' => $this->ID(), |
|
1545 | - ), |
|
1546 | - 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
1547 | - ) |
|
1548 | - ); |
|
1549 | - } |
|
1550 | - |
|
1551 | - |
|
1552 | - /** |
|
1553 | - * This method simply returns the check-in status for this registration and the given datetime. |
|
1554 | - * If neither the datetime nor the checkin values are provided as arguments, |
|
1555 | - * then this will return the LATEST check-in status for the registration across all datetimes it belongs to. |
|
1556 | - * |
|
1557 | - * @param int $DTT_ID The ID of the datetime we're checking against |
|
1558 | - * (if empty we'll get the primary datetime for |
|
1559 | - * this registration (via event) and use it's ID); |
|
1560 | - * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id. |
|
1561 | - * |
|
1562 | - * @return int Integer representing Check-in status. |
|
1563 | - * @throws EE_Error |
|
1564 | - */ |
|
1565 | - public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null) |
|
1566 | - { |
|
1567 | - $checkin_query_params = array( |
|
1568 | - 'order_by' => array('CHK_timestamp' => 'DESC'), |
|
1569 | - ); |
|
1570 | - |
|
1571 | - if ($DTT_ID > 0) { |
|
1572 | - $checkin_query_params[0] = array('DTT_ID' => $DTT_ID); |
|
1573 | - } |
|
1574 | - |
|
1575 | - //get checkin object (if exists) |
|
1576 | - $checkin = $checkin instanceof EE_Checkin |
|
1577 | - ? $checkin |
|
1578 | - : $this->get_first_related('Checkin', $checkin_query_params); |
|
1579 | - if ($checkin instanceof EE_Checkin) { |
|
1580 | - if ($checkin->get('CHK_in')) { |
|
1581 | - return EE_Checkin::status_checked_in; //checked in |
|
1582 | - } |
|
1583 | - return EE_Checkin::status_checked_out; //had checked in but is now checked out. |
|
1584 | - } |
|
1585 | - return EE_Checkin::status_checked_never; //never been checked in |
|
1586 | - } |
|
1587 | - |
|
1588 | - |
|
1589 | - /** |
|
1590 | - * This method returns a localized message for the toggled Check-in message. |
|
1591 | - * |
|
1592 | - * @param int $DTT_ID include specific datetime to get the correct Check-in message. If not included or null, |
|
1593 | - * then it is assumed Check-in for primary datetime was toggled. |
|
1594 | - * @param bool $error This just flags that you want an error message returned. This is put in so that the error |
|
1595 | - * message can be customized with the attendee name. |
|
1596 | - * @return string internationalized message |
|
1597 | - * @throws EE_Error |
|
1598 | - */ |
|
1599 | - public function get_checkin_msg($DTT_ID, $error = false) |
|
1600 | - { |
|
1601 | - //let's get the attendee first so we can include the name of the attendee |
|
1602 | - $attendee = $this->get_first_related('Attendee'); |
|
1603 | - if ($attendee instanceof EE_Attendee) { |
|
1604 | - if ($error) { |
|
1605 | - return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name()); |
|
1606 | - } |
|
1607 | - $cur_status = $this->check_in_status_for_datetime($DTT_ID); |
|
1608 | - //what is the status message going to be? |
|
1609 | - switch ($cur_status) { |
|
1610 | - case EE_Checkin::status_checked_never: |
|
1611 | - return sprintf(__("%s has been removed from Check-in records", "event_espresso"), |
|
1612 | - $attendee->full_name()); |
|
1613 | - break; |
|
1614 | - case EE_Checkin::status_checked_in: |
|
1615 | - return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name()); |
|
1616 | - break; |
|
1617 | - case EE_Checkin::status_checked_out: |
|
1618 | - return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name()); |
|
1619 | - break; |
|
1620 | - } |
|
1621 | - } |
|
1622 | - return esc_html__("The check-in status could not be determined.", "event_espresso"); |
|
1623 | - } |
|
1624 | - |
|
1625 | - |
|
1626 | - /** |
|
1627 | - * Returns the related EE_Transaction to this registration |
|
1628 | - * |
|
1629 | - * @return EE_Transaction |
|
1630 | - * @throws EE_Error |
|
1631 | - * @throws EntityNotFoundException |
|
1632 | - */ |
|
1633 | - public function transaction() |
|
1634 | - { |
|
1635 | - $transaction = $this->get_first_related('Transaction'); |
|
1636 | - if (! $transaction instanceof \EE_Transaction) { |
|
1637 | - throw new EntityNotFoundException('Transaction ID', $this->transaction_ID()); |
|
1638 | - } |
|
1639 | - return $transaction; |
|
1640 | - } |
|
1641 | - |
|
1642 | - |
|
1643 | - /** |
|
1644 | - * get Registration Code |
|
1645 | - */ |
|
1646 | - public function reg_code() |
|
1647 | - { |
|
1648 | - return $this->get('REG_code'); |
|
1649 | - } |
|
1650 | - |
|
1651 | - |
|
1652 | - /** |
|
1653 | - * get Transaction ID |
|
1654 | - */ |
|
1655 | - public function transaction_ID() |
|
1656 | - { |
|
1657 | - return $this->get('TXN_ID'); |
|
1658 | - } |
|
1659 | - |
|
1660 | - |
|
1661 | - /** |
|
1662 | - * @return int |
|
1663 | - * @throws EE_Error |
|
1664 | - */ |
|
1665 | - public function ticket_ID() |
|
1666 | - { |
|
1667 | - return $this->get('TKT_ID'); |
|
1668 | - } |
|
1669 | - |
|
1670 | - |
|
1671 | - /** |
|
1672 | - * Set Registration Code |
|
1673 | - * |
|
1674 | - * @access public |
|
1675 | - * @param string $REG_code Registration Code |
|
1676 | - * @param boolean $use_default |
|
1677 | - * @throws EE_Error |
|
1678 | - */ |
|
1679 | - public function set_reg_code($REG_code, $use_default = false) |
|
1680 | - { |
|
1681 | - if (empty($REG_code)) { |
|
1682 | - EE_Error::add_error( |
|
1683 | - esc_html__('REG_code can not be empty.', 'event_espresso'), |
|
1684 | - __FILE__, |
|
1685 | - __FUNCTION__, |
|
1686 | - __LINE__ |
|
1687 | - ); |
|
1688 | - return; |
|
1689 | - } |
|
1690 | - if (! $this->reg_code()) { |
|
1691 | - parent::set('REG_code', $REG_code, $use_default); |
|
1692 | - } else { |
|
1693 | - EE_Error::doing_it_wrong( |
|
1694 | - __CLASS__ . '::' . __FUNCTION__, |
|
1695 | - esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'), |
|
1696 | - '4.6.0' |
|
1697 | - ); |
|
1698 | - } |
|
1699 | - } |
|
1700 | - |
|
1701 | - |
|
1702 | - /** |
|
1703 | - * Returns all other registrations in the same group as this registrant who have the same ticket option. |
|
1704 | - * Note, if you want to just get all registrations in the same transaction (group), use: |
|
1705 | - * $registration->transaction()->registrations(); |
|
1706 | - * |
|
1707 | - * @since 4.5.0 |
|
1708 | - * @return EE_Registration[] or empty array if this isn't a group registration. |
|
1709 | - * @throws EE_Error |
|
1710 | - */ |
|
1711 | - public function get_all_other_registrations_in_group() |
|
1712 | - { |
|
1713 | - if ($this->group_size() < 2) { |
|
1714 | - return array(); |
|
1715 | - } |
|
1716 | - |
|
1717 | - $query[0] = array( |
|
1718 | - 'TXN_ID' => $this->transaction_ID(), |
|
1719 | - 'REG_ID' => array('!=', $this->ID()), |
|
1720 | - 'TKT_ID' => $this->ticket_ID(), |
|
1721 | - ); |
|
1722 | - /** @var EE_Registration[] $registrations */ |
|
1723 | - $registrations = $this->get_model()->get_all($query); |
|
1724 | - return $registrations; |
|
1725 | - } |
|
1726 | - |
|
1727 | - /** |
|
1728 | - * Return the link to the admin details for the object. |
|
1729 | - * |
|
1730 | - * @return string |
|
1731 | - * @throws EE_Error |
|
1732 | - */ |
|
1733 | - public function get_admin_details_link() |
|
1734 | - { |
|
1735 | - EE_Registry::instance()->load_helper('URL'); |
|
1736 | - return EEH_URL::add_query_args_and_nonce( |
|
1737 | - array( |
|
1738 | - 'page' => 'espresso_registrations', |
|
1739 | - 'action' => 'view_registration', |
|
1740 | - '_REG_ID' => $this->ID(), |
|
1741 | - ), |
|
1742 | - admin_url('admin.php') |
|
1743 | - ); |
|
1744 | - } |
|
1745 | - |
|
1746 | - /** |
|
1747 | - * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
1748 | - * |
|
1749 | - * @return string |
|
1750 | - * @throws EE_Error |
|
1751 | - */ |
|
1752 | - public function get_admin_edit_link() |
|
1753 | - { |
|
1754 | - return $this->get_admin_details_link(); |
|
1755 | - } |
|
1756 | - |
|
1757 | - /** |
|
1758 | - * Returns the link to a settings page for the object. |
|
1759 | - * |
|
1760 | - * @return string |
|
1761 | - * @throws EE_Error |
|
1762 | - */ |
|
1763 | - public function get_admin_settings_link() |
|
1764 | - { |
|
1765 | - return $this->get_admin_details_link(); |
|
1766 | - } |
|
1767 | - |
|
1768 | - /** |
|
1769 | - * Returns the link to the "overview" for the object (typically the "list table" view). |
|
1770 | - * |
|
1771 | - * @return string |
|
1772 | - */ |
|
1773 | - public function get_admin_overview_link() |
|
1774 | - { |
|
1775 | - EE_Registry::instance()->load_helper('URL'); |
|
1776 | - return EEH_URL::add_query_args_and_nonce( |
|
1777 | - array( |
|
1778 | - 'page' => 'espresso_registrations', |
|
1779 | - ), |
|
1780 | - admin_url('admin.php') |
|
1781 | - ); |
|
1782 | - } |
|
1783 | - |
|
1784 | - |
|
1785 | - /** |
|
1786 | - * @param array $query_params |
|
1787 | - * |
|
1788 | - * @return \EE_Registration[] |
|
1789 | - * @throws EE_Error |
|
1790 | - */ |
|
1791 | - public function payments($query_params = array()) |
|
1792 | - { |
|
1793 | - return $this->get_many_related('Payment', $query_params); |
|
1794 | - } |
|
1795 | - |
|
1796 | - |
|
1797 | - /** |
|
1798 | - * @param array $query_params |
|
1799 | - * |
|
1800 | - * @return \EE_Registration_Payment[] |
|
1801 | - * @throws EE_Error |
|
1802 | - */ |
|
1803 | - public function registration_payments($query_params = array()) |
|
1804 | - { |
|
1805 | - return $this->get_many_related('Registration_Payment', $query_params); |
|
1806 | - } |
|
1807 | - |
|
1808 | - |
|
1809 | - /** |
|
1810 | - * This grabs the payment method corresponding to the last payment made for the amount owing on the registration. |
|
1811 | - * Note: if there are no payments on the registration there will be no payment method returned. |
|
1812 | - * |
|
1813 | - * @return EE_Payment_Method|null |
|
1814 | - */ |
|
1815 | - public function payment_method() |
|
1816 | - { |
|
1817 | - return EEM_Payment_Method::instance()->get_last_used_for_registration($this); |
|
1818 | - } |
|
1819 | - |
|
1820 | - |
|
1821 | - /** |
|
1822 | - * @return \EE_Line_Item |
|
1823 | - * @throws EntityNotFoundException |
|
1824 | - * @throws EE_Error |
|
1825 | - */ |
|
1826 | - public function ticket_line_item() |
|
1827 | - { |
|
1828 | - $ticket = $this->ticket(); |
|
1829 | - $transaction = $this->transaction(); |
|
1830 | - $line_item = null; |
|
1831 | - $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
1832 | - $transaction->total_line_item(), |
|
1833 | - 'Ticket', |
|
1834 | - array($ticket->ID()) |
|
1835 | - ); |
|
1836 | - foreach ($ticket_line_items as $ticket_line_item) { |
|
1837 | - if ( |
|
1838 | - $ticket_line_item instanceof \EE_Line_Item |
|
1839 | - && $ticket_line_item->OBJ_type() === 'Ticket' |
|
1840 | - && $ticket_line_item->OBJ_ID() === $ticket->ID() |
|
1841 | - ) { |
|
1842 | - $line_item = $ticket_line_item; |
|
1843 | - break; |
|
1844 | - } |
|
1845 | - } |
|
1846 | - if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
1847 | - throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID()); |
|
1848 | - } |
|
1849 | - return $line_item; |
|
1850 | - } |
|
1851 | - |
|
1852 | - |
|
1853 | - /** |
|
1854 | - * Soft Deletes this model object. |
|
1855 | - * |
|
1856 | - * @return boolean | int |
|
1857 | - * @throws RuntimeException |
|
1858 | - * @throws EE_Error |
|
1859 | - */ |
|
1860 | - public function delete() |
|
1861 | - { |
|
1862 | - if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) { |
|
1863 | - $this->set_status(EEM_Registration::status_id_cancelled); |
|
1864 | - } |
|
1865 | - return parent::delete(); |
|
1866 | - } |
|
1867 | - |
|
1868 | - |
|
1869 | - /** |
|
1870 | - * Restores whatever the previous status was on a registration before it was trashed (if possible) |
|
1871 | - * |
|
1872 | - * @throws EE_Error |
|
1873 | - * @throws RuntimeException |
|
1874 | - */ |
|
1875 | - public function restore() |
|
1876 | - { |
|
1877 | - $previous_status = $this->get_extra_meta( |
|
1878 | - EE_Registration::PRE_TRASH_REG_STATUS_KEY, |
|
1879 | - true, |
|
1880 | - EEM_Registration::status_id_cancelled |
|
1881 | - ); |
|
1882 | - if ($previous_status) { |
|
1883 | - $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY); |
|
1884 | - $this->set_status($previous_status); |
|
1885 | - } |
|
1886 | - return parent::restore(); |
|
1887 | - } |
|
1888 | - |
|
1889 | - |
|
1890 | - /** |
|
1891 | - * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price |
|
1892 | - * |
|
1893 | - * @param boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic |
|
1894 | - * depending on whether the reg status changes to or from "Approved" |
|
1895 | - * @return boolean whether the Registration status was updated |
|
1896 | - * @throws EE_Error |
|
1897 | - * @throws RuntimeException |
|
1898 | - */ |
|
1899 | - public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true) |
|
1900 | - { |
|
1901 | - $paid = $this->paid(); |
|
1902 | - $price = $this->final_price(); |
|
1903 | - switch(true) { |
|
1904 | - // overpaid or paid |
|
1905 | - case EEH_Money::compare_floats($paid, $price, '>'): |
|
1906 | - case EEH_Money::compare_floats($paid, $price): |
|
1907 | - $new_status = EEM_Registration::status_id_approved; |
|
1908 | - break; |
|
1909 | - // underpaid |
|
1910 | - case EEH_Money::compare_floats($paid, $price, '<'): |
|
1911 | - $new_status = EEM_Registration::status_id_pending_payment; |
|
1912 | - break; |
|
1913 | - // uhhh Houston... |
|
1914 | - default: |
|
1915 | - throw new RuntimeException( |
|
1916 | - esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso') |
|
1917 | - ); |
|
1918 | - } |
|
1919 | - if ($new_status !== $this->status_ID()) { |
|
1920 | - if ($trigger_set_status_logic) { |
|
1921 | - return $this->set_status($new_status); |
|
1922 | - } |
|
1923 | - parent::set('STS_ID', $new_status); |
|
1924 | - return true; |
|
1925 | - } |
|
1926 | - return false; |
|
1927 | - } |
|
1928 | - |
|
1929 | - |
|
1930 | - /*************************** DEPRECATED ***************************/ |
|
1931 | - |
|
1932 | - |
|
1933 | - /** |
|
1934 | - * @deprecated |
|
1935 | - * @since 4.7.0 |
|
1936 | - * @access public |
|
1937 | - */ |
|
1938 | - public function price_paid() |
|
1939 | - { |
|
1940 | - EE_Error::doing_it_wrong('EE_Registration::price_paid()', |
|
1941 | - esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'), |
|
1942 | - '4.7.0'); |
|
1943 | - return $this->final_price(); |
|
1944 | - } |
|
1945 | - |
|
1946 | - |
|
1947 | - /** |
|
1948 | - * @deprecated |
|
1949 | - * @since 4.7.0 |
|
1950 | - * @access public |
|
1951 | - * @param float $REG_final_price |
|
1952 | - * @throws EE_Error |
|
1953 | - * @throws RuntimeException |
|
1954 | - */ |
|
1955 | - public function set_price_paid($REG_final_price = 0.00) |
|
1956 | - { |
|
1957 | - EE_Error::doing_it_wrong('EE_Registration::set_price_paid()', |
|
1958 | - esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'), |
|
1959 | - '4.7.0'); |
|
1960 | - $this->set_final_price($REG_final_price); |
|
1961 | - } |
|
1962 | - |
|
1963 | - |
|
1964 | - /** |
|
1965 | - * @deprecated |
|
1966 | - * @since 4.7.0 |
|
1967 | - * @return string |
|
1968 | - * @throws EE_Error |
|
1969 | - */ |
|
1970 | - public function pretty_price_paid() |
|
1971 | - { |
|
1972 | - EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()', |
|
1973 | - esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.', |
|
1974 | - 'event_espresso'), '4.7.0'); |
|
1975 | - return $this->pretty_final_price(); |
|
1976 | - } |
|
1977 | - |
|
1978 | - |
|
1979 | - /** |
|
1980 | - * Gets the primary datetime related to this registration via the related Event to this registration |
|
1981 | - * |
|
1982 | - * @deprecated 4.9.17 |
|
1983 | - * @return EE_Datetime |
|
1984 | - * @throws EE_Error |
|
1985 | - * @throws EntityNotFoundException |
|
1986 | - */ |
|
1987 | - public function get_related_primary_datetime() |
|
1988 | - { |
|
1989 | - EE_Error::doing_it_wrong( |
|
1990 | - __METHOD__, |
|
1991 | - esc_html__( |
|
1992 | - 'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()', |
|
1993 | - 'event_espresso' |
|
1994 | - ), |
|
1995 | - '4.9.17', |
|
1996 | - '5.0.0' |
|
1997 | - ); |
|
1998 | - return $this->event()->primary_datetime(); |
|
1999 | - } |
|
21 | + /** |
|
22 | + * Used to reference when a registration has never been checked in. |
|
23 | + * |
|
24 | + * @deprecated use \EE_Checkin::status_checked_never instead |
|
25 | + * @type int |
|
26 | + */ |
|
27 | + const checkin_status_never = 2; |
|
28 | + |
|
29 | + /** |
|
30 | + * Used to reference when a registration has been checked in. |
|
31 | + * |
|
32 | + * @deprecated use \EE_Checkin::status_checked_in instead |
|
33 | + * @type int |
|
34 | + */ |
|
35 | + const checkin_status_in = 1; |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * Used to reference when a registration has been checked out. |
|
40 | + * |
|
41 | + * @deprecated use \EE_Checkin::status_checked_out instead |
|
42 | + * @type int |
|
43 | + */ |
|
44 | + const checkin_status_out = 0; |
|
45 | + |
|
46 | + |
|
47 | + /** |
|
48 | + * extra meta key for tracking reg status os trashed registrations |
|
49 | + * |
|
50 | + * @type string |
|
51 | + */ |
|
52 | + const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status'; |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * extra meta key for tracking if registration has reserved ticket |
|
57 | + * |
|
58 | + * @type string |
|
59 | + */ |
|
60 | + const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket'; |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * @param array $props_n_values incoming values |
|
65 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
66 | + * used.) |
|
67 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
68 | + * date_format and the second value is the time format |
|
69 | + * @return EE_Registration |
|
70 | + * @throws EE_Error |
|
71 | + */ |
|
72 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
73 | + { |
|
74 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
75 | + return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
76 | + } |
|
77 | + |
|
78 | + |
|
79 | + /** |
|
80 | + * @param array $props_n_values incoming values from the database |
|
81 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
82 | + * the website will be used. |
|
83 | + * @return EE_Registration |
|
84 | + */ |
|
85 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
86 | + { |
|
87 | + return new self($props_n_values, true, $timezone); |
|
88 | + } |
|
89 | + |
|
90 | + |
|
91 | + /** |
|
92 | + * Set Event ID |
|
93 | + * |
|
94 | + * @param int $EVT_ID Event ID |
|
95 | + * @throws EE_Error |
|
96 | + * @throws RuntimeException |
|
97 | + */ |
|
98 | + public function set_event($EVT_ID = 0) |
|
99 | + { |
|
100 | + $this->set('EVT_ID', $EVT_ID); |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can |
|
106 | + * be routed to internal methods |
|
107 | + * |
|
108 | + * @param string $field_name |
|
109 | + * @param mixed $field_value |
|
110 | + * @param bool $use_default |
|
111 | + * @throws EE_Error |
|
112 | + * @throws EntityNotFoundException |
|
113 | + * @throws InvalidArgumentException |
|
114 | + * @throws InvalidDataTypeException |
|
115 | + * @throws InvalidInterfaceException |
|
116 | + * @throws ReflectionException |
|
117 | + * @throws RuntimeException |
|
118 | + */ |
|
119 | + public function set($field_name, $field_value, $use_default = false) |
|
120 | + { |
|
121 | + switch ($field_name) { |
|
122 | + case 'REG_code': |
|
123 | + if (! empty($field_value) && $this->reg_code() === null) { |
|
124 | + $this->set_reg_code($field_value, $use_default); |
|
125 | + } |
|
126 | + break; |
|
127 | + case 'STS_ID': |
|
128 | + $this->set_status($field_value, $use_default); |
|
129 | + break; |
|
130 | + default: |
|
131 | + parent::set($field_name, $field_value, $use_default); |
|
132 | + } |
|
133 | + } |
|
134 | + |
|
135 | + |
|
136 | + /** |
|
137 | + * Set Status ID |
|
138 | + * updates the registration status and ALSO... |
|
139 | + * calls reserve_registration_space() if the reg status changes TO approved from any other reg status |
|
140 | + * calls release_registration_space() if the reg status changes FROM approved to any other reg status |
|
141 | + * |
|
142 | + * @param string $new_STS_ID |
|
143 | + * @param boolean $use_default |
|
144 | + * @param Context|null $context |
|
145 | + * @return bool |
|
146 | + * @throws EE_Error |
|
147 | + * @throws EntityNotFoundException |
|
148 | + * @throws InvalidArgumentException |
|
149 | + * @throws ReflectionException |
|
150 | + * @throws RuntimeException |
|
151 | + * @throws InvalidDataTypeException |
|
152 | + * @throws InvalidInterfaceException |
|
153 | + */ |
|
154 | + public function set_status($new_STS_ID = null, $use_default = false, Context $context = null) |
|
155 | + { |
|
156 | + // get current REG_Status |
|
157 | + $old_STS_ID = $this->status_ID(); |
|
158 | + // if status has changed |
|
159 | + if ($old_STS_ID !== $new_STS_ID // and that status has actually changed |
|
160 | + && ! empty($old_STS_ID) // and that old status is actually set |
|
161 | + && ! empty($new_STS_ID) // as well as the new status |
|
162 | + && $this->ID() // ensure registration is in the db |
|
163 | + ) { |
|
164 | + // TO approved |
|
165 | + if ($new_STS_ID === EEM_Registration::status_id_approved) { |
|
166 | + // reserve a space by incrementing ticket and datetime sold values |
|
167 | + $this->_reserve_registration_space(); |
|
168 | + do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context); |
|
169 | + // OR FROM approved |
|
170 | + } elseif ($old_STS_ID === EEM_Registration::status_id_approved) { |
|
171 | + // release a space by decrementing ticket and datetime sold values |
|
172 | + $this->_release_registration_space(); |
|
173 | + do_action( |
|
174 | + 'AHEE__EE_Registration__set_status__from_approved', |
|
175 | + $this, |
|
176 | + $old_STS_ID, |
|
177 | + $new_STS_ID, |
|
178 | + $context |
|
179 | + ); |
|
180 | + } |
|
181 | + // update status |
|
182 | + parent::set('STS_ID', $new_STS_ID, $use_default); |
|
183 | + $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context); |
|
184 | + if($this->statusChangeUpdatesTransaction($context)) { |
|
185 | + $this->updateTransactionAfterStatusChange(); |
|
186 | + } |
|
187 | + do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context); |
|
188 | + return true; |
|
189 | + } |
|
190 | + //even though the old value matches the new value, it's still good to |
|
191 | + //allow the parent set method to have a say |
|
192 | + parent::set('STS_ID', $new_STS_ID, $use_default); |
|
193 | + return true; |
|
194 | + } |
|
195 | + |
|
196 | + |
|
197 | + /** |
|
198 | + * update REGs and TXN when cancelled or declined registrations involved |
|
199 | + * |
|
200 | + * @param string $new_STS_ID |
|
201 | + * @param string $old_STS_ID |
|
202 | + * @param Context|null $context |
|
203 | + * @throws EE_Error |
|
204 | + * @throws InvalidArgumentException |
|
205 | + * @throws InvalidDataTypeException |
|
206 | + * @throws InvalidInterfaceException |
|
207 | + * @throws ReflectionException |
|
208 | + */ |
|
209 | + private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null) |
|
210 | + { |
|
211 | + // these reg statuses should not be considered in any calculations involving monies owing |
|
212 | + $closed_reg_statuses = EEM_Registration::closed_reg_statuses(); |
|
213 | + // true if registration has been cancelled or declined |
|
214 | + $this->updateIfCanceled( |
|
215 | + $closed_reg_statuses, |
|
216 | + $new_STS_ID, |
|
217 | + $old_STS_ID, |
|
218 | + $context |
|
219 | + ); |
|
220 | + $this->updateIfDeclined( |
|
221 | + $closed_reg_statuses, |
|
222 | + $new_STS_ID, |
|
223 | + $old_STS_ID, |
|
224 | + $context |
|
225 | + ); |
|
226 | + } |
|
227 | + |
|
228 | + |
|
229 | + /** |
|
230 | + * update REGs and TXN when cancelled or declined registrations involved |
|
231 | + * |
|
232 | + * @param array $closed_reg_statuses |
|
233 | + * @param string $new_STS_ID |
|
234 | + * @param string $old_STS_ID |
|
235 | + * @param Context|null $context |
|
236 | + * @throws EE_Error |
|
237 | + * @throws InvalidArgumentException |
|
238 | + * @throws InvalidDataTypeException |
|
239 | + * @throws InvalidInterfaceException |
|
240 | + * @throws ReflectionException |
|
241 | + */ |
|
242 | + private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null) |
|
243 | + { |
|
244 | + // true if registration has been cancelled or declined |
|
245 | + if (in_array($new_STS_ID, $closed_reg_statuses, true) |
|
246 | + && ! in_array($old_STS_ID, $closed_reg_statuses, true) |
|
247 | + ) { |
|
248 | + /** @type EE_Registration_Processor $registration_processor */ |
|
249 | + $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
250 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
251 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
252 | + // cancelled or declined registration |
|
253 | + $registration_processor->update_registration_after_being_canceled_or_declined( |
|
254 | + $this, |
|
255 | + $closed_reg_statuses |
|
256 | + ); |
|
257 | + $transaction_processor->update_transaction_after_canceled_or_declined_registration( |
|
258 | + $this, |
|
259 | + $closed_reg_statuses, |
|
260 | + false |
|
261 | + ); |
|
262 | + do_action( |
|
263 | + 'AHEE__EE_Registration__set_status__canceled_or_declined', |
|
264 | + $this, |
|
265 | + $old_STS_ID, |
|
266 | + $new_STS_ID, |
|
267 | + $context |
|
268 | + ); |
|
269 | + return; |
|
270 | + } |
|
271 | + } |
|
272 | + |
|
273 | + |
|
274 | + /** |
|
275 | + * update REGs and TXN when cancelled or declined registrations involved |
|
276 | + * |
|
277 | + * @param array $closed_reg_statuses |
|
278 | + * @param string $new_STS_ID |
|
279 | + * @param string $old_STS_ID |
|
280 | + * @param Context|null $context |
|
281 | + * @throws EE_Error |
|
282 | + * @throws InvalidArgumentException |
|
283 | + * @throws InvalidDataTypeException |
|
284 | + * @throws InvalidInterfaceException |
|
285 | + * @throws ReflectionException |
|
286 | + */ |
|
287 | + private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null) |
|
288 | + { |
|
289 | + // true if reinstating cancelled or declined registration |
|
290 | + if (in_array($old_STS_ID, $closed_reg_statuses, true) |
|
291 | + && ! in_array($new_STS_ID, $closed_reg_statuses, true) |
|
292 | + ) { |
|
293 | + /** @type EE_Registration_Processor $registration_processor */ |
|
294 | + $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
295 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
296 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
297 | + // reinstating cancelled or declined registration |
|
298 | + $registration_processor->update_canceled_or_declined_registration_after_being_reinstated( |
|
299 | + $this, |
|
300 | + $closed_reg_statuses |
|
301 | + ); |
|
302 | + $transaction_processor->update_transaction_after_reinstating_canceled_registration( |
|
303 | + $this, |
|
304 | + $closed_reg_statuses, |
|
305 | + false |
|
306 | + ); |
|
307 | + do_action( |
|
308 | + 'AHEE__EE_Registration__set_status__after_reinstated', |
|
309 | + $this, |
|
310 | + $old_STS_ID, |
|
311 | + $new_STS_ID, |
|
312 | + $context |
|
313 | + ); |
|
314 | + } |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * @param Context|null $context |
|
320 | + * @return bool |
|
321 | + */ |
|
322 | + private function statusChangeUpdatesTransaction(Context $context = null) |
|
323 | + { |
|
324 | + $contexts_that_do_not_update_transaction = (array) apply_filters( |
|
325 | + 'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction', |
|
326 | + array('spco_reg_step_attendee_information_process_registrations'), |
|
327 | + $context, |
|
328 | + $this |
|
329 | + ); |
|
330 | + return ! ( |
|
331 | + $context instanceof Context |
|
332 | + && in_array($context->slug(), $contexts_that_do_not_update_transaction, true) |
|
333 | + ); |
|
334 | + } |
|
335 | + |
|
336 | + |
|
337 | + /** |
|
338 | + * @throws EE_Error |
|
339 | + * @throws EntityNotFoundException |
|
340 | + * @throws InvalidArgumentException |
|
341 | + * @throws InvalidDataTypeException |
|
342 | + * @throws InvalidInterfaceException |
|
343 | + * @throws ReflectionException |
|
344 | + * @throws RuntimeException |
|
345 | + */ |
|
346 | + private function updateTransactionAfterStatusChange() |
|
347 | + { |
|
348 | + /** @type EE_Transaction_Payments $transaction_payments */ |
|
349 | + $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
350 | + $transaction_payments->recalculate_transaction_total($this->transaction(), false); |
|
351 | + $this->transaction()->update_status_based_on_total_paid(true); |
|
352 | + } |
|
353 | + |
|
354 | + |
|
355 | + /** |
|
356 | + * get Status ID |
|
357 | + */ |
|
358 | + public function status_ID() |
|
359 | + { |
|
360 | + return $this->get('STS_ID'); |
|
361 | + } |
|
362 | + |
|
363 | + |
|
364 | + /** |
|
365 | + * increments this registration's related ticket sold and corresponding datetime sold values |
|
366 | + * |
|
367 | + * @return void |
|
368 | + * @throws EE_Error |
|
369 | + * @throws EntityNotFoundException |
|
370 | + */ |
|
371 | + private function _reserve_registration_space() |
|
372 | + { |
|
373 | + // reserved ticket and datetime counts will be decremented as sold counts are incremented |
|
374 | + // so stop tracking that this reg has a ticket reserved |
|
375 | + $this->release_reserved_ticket(); |
|
376 | + $ticket = $this->ticket(); |
|
377 | + $ticket->increase_sold(); |
|
378 | + $ticket->save(); |
|
379 | + // possibly set event status to sold out |
|
380 | + $this->event()->perform_sold_out_status_check(); |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * Gets the ticket this registration is for |
|
386 | + * |
|
387 | + * @param boolean $include_archived whether to include archived tickets or not. |
|
388 | + * |
|
389 | + * @return EE_Ticket|EE_Base_Class |
|
390 | + * @throws EE_Error |
|
391 | + */ |
|
392 | + public function ticket($include_archived = true) |
|
393 | + { |
|
394 | + $query_params = array(); |
|
395 | + if ($include_archived) { |
|
396 | + $query_params['default_where_conditions'] = 'none'; |
|
397 | + } |
|
398 | + return $this->get_first_related('Ticket', $query_params); |
|
399 | + } |
|
400 | + |
|
401 | + |
|
402 | + /** |
|
403 | + * Gets the event this registration is for |
|
404 | + * |
|
405 | + * @return EE_Event |
|
406 | + * @throws EE_Error |
|
407 | + * @throws EntityNotFoundException |
|
408 | + */ |
|
409 | + public function event() |
|
410 | + { |
|
411 | + $event = $this->get_first_related('Event'); |
|
412 | + if (! $event instanceof \EE_Event) { |
|
413 | + throw new EntityNotFoundException('Event ID', $this->event_ID()); |
|
414 | + } |
|
415 | + return $event; |
|
416 | + } |
|
417 | + |
|
418 | + |
|
419 | + /** |
|
420 | + * Gets the "author" of the registration. Note that for the purposes of registrations, the author will correspond |
|
421 | + * with the author of the event this registration is for. |
|
422 | + * |
|
423 | + * @since 4.5.0 |
|
424 | + * @return int |
|
425 | + * @throws EE_Error |
|
426 | + * @throws EntityNotFoundException |
|
427 | + */ |
|
428 | + public function wp_user() |
|
429 | + { |
|
430 | + $event = $this->event(); |
|
431 | + if ($event instanceof EE_Event) { |
|
432 | + return $event->wp_user(); |
|
433 | + } |
|
434 | + return 0; |
|
435 | + } |
|
436 | + |
|
437 | + |
|
438 | + /** |
|
439 | + * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values |
|
440 | + * |
|
441 | + * @return void |
|
442 | + * @throws EE_Error |
|
443 | + */ |
|
444 | + private function _release_registration_space() |
|
445 | + { |
|
446 | + $ticket = $this->ticket(); |
|
447 | + $ticket->decrease_sold(); |
|
448 | + $ticket->save(); |
|
449 | + } |
|
450 | + |
|
451 | + |
|
452 | + /** |
|
453 | + * tracks this registration's ticket reservation in extra meta |
|
454 | + * and can increment related ticket reserved and corresponding datetime reserved values |
|
455 | + * |
|
456 | + * @param bool $update_ticket if true, will increment ticket and datetime reserved count |
|
457 | + * |
|
458 | + * @return void |
|
459 | + * @throws EE_Error |
|
460 | + */ |
|
461 | + public function reserve_ticket($update_ticket = false) |
|
462 | + { |
|
463 | + if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) { |
|
464 | + // PLZ NOTE: although checking $update_ticket first would be more efficient, |
|
465 | + // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
466 | + if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) { |
|
467 | + $ticket = $this->ticket(); |
|
468 | + $ticket->increase_reserved(); |
|
469 | + $ticket->save(); |
|
470 | + } |
|
471 | + } |
|
472 | + } |
|
473 | + |
|
474 | + |
|
475 | + /** |
|
476 | + * stops tracking this registration's ticket reservation in extra meta |
|
477 | + * decrements (subtracts) related ticket reserved and corresponding datetime reserved values |
|
478 | + * |
|
479 | + * @param bool $update_ticket if true, will decrement ticket and datetime reserved count |
|
480 | + * |
|
481 | + * @return void |
|
482 | + * @throws EE_Error |
|
483 | + */ |
|
484 | + public function release_reserved_ticket($update_ticket = false) |
|
485 | + { |
|
486 | + if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) { |
|
487 | + // PLZ NOTE: although checking $update_ticket first would be more efficient, |
|
488 | + // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first |
|
489 | + if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) { |
|
490 | + $ticket = $this->ticket(); |
|
491 | + $ticket->decrease_reserved(); |
|
492 | + $ticket->save(); |
|
493 | + } |
|
494 | + } |
|
495 | + } |
|
496 | + |
|
497 | + |
|
498 | + /** |
|
499 | + * Set Attendee ID |
|
500 | + * |
|
501 | + * @param int $ATT_ID Attendee ID |
|
502 | + * @throws EE_Error |
|
503 | + * @throws RuntimeException |
|
504 | + */ |
|
505 | + public function set_attendee_id($ATT_ID = 0) |
|
506 | + { |
|
507 | + $this->set('ATT_ID', $ATT_ID); |
|
508 | + } |
|
509 | + |
|
510 | + |
|
511 | + /** |
|
512 | + * Set Transaction ID |
|
513 | + * |
|
514 | + * @param int $TXN_ID Transaction ID |
|
515 | + * @throws EE_Error |
|
516 | + * @throws RuntimeException |
|
517 | + */ |
|
518 | + public function set_transaction_id($TXN_ID = 0) |
|
519 | + { |
|
520 | + $this->set('TXN_ID', $TXN_ID); |
|
521 | + } |
|
522 | + |
|
523 | + |
|
524 | + /** |
|
525 | + * Set Session |
|
526 | + * |
|
527 | + * @param string $REG_session PHP Session ID |
|
528 | + * @throws EE_Error |
|
529 | + * @throws RuntimeException |
|
530 | + */ |
|
531 | + public function set_session($REG_session = '') |
|
532 | + { |
|
533 | + $this->set('REG_session', $REG_session); |
|
534 | + } |
|
535 | + |
|
536 | + |
|
537 | + /** |
|
538 | + * Set Registration URL Link |
|
539 | + * |
|
540 | + * @param string $REG_url_link Registration URL Link |
|
541 | + * @throws EE_Error |
|
542 | + * @throws RuntimeException |
|
543 | + */ |
|
544 | + public function set_reg_url_link($REG_url_link = '') |
|
545 | + { |
|
546 | + $this->set('REG_url_link', $REG_url_link); |
|
547 | + } |
|
548 | + |
|
549 | + |
|
550 | + /** |
|
551 | + * Set Attendee Counter |
|
552 | + * |
|
553 | + * @param int $REG_count Primary Attendee |
|
554 | + * @throws EE_Error |
|
555 | + * @throws RuntimeException |
|
556 | + */ |
|
557 | + public function set_count($REG_count = 1) |
|
558 | + { |
|
559 | + $this->set('REG_count', $REG_count); |
|
560 | + } |
|
561 | + |
|
562 | + |
|
563 | + /** |
|
564 | + * Set Group Size |
|
565 | + * |
|
566 | + * @param boolean $REG_group_size Group Registration |
|
567 | + * @throws EE_Error |
|
568 | + * @throws RuntimeException |
|
569 | + */ |
|
570 | + public function set_group_size($REG_group_size = false) |
|
571 | + { |
|
572 | + $this->set('REG_group_size', $REG_group_size); |
|
573 | + } |
|
574 | + |
|
575 | + |
|
576 | + /** |
|
577 | + * is_not_approved - convenience method that returns TRUE if REG status ID == |
|
578 | + * EEM_Registration::status_id_not_approved |
|
579 | + * |
|
580 | + * @return boolean |
|
581 | + */ |
|
582 | + public function is_not_approved() |
|
583 | + { |
|
584 | + return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false; |
|
585 | + } |
|
586 | + |
|
587 | + |
|
588 | + /** |
|
589 | + * is_pending_payment - convenience method that returns TRUE if REG status ID == |
|
590 | + * EEM_Registration::status_id_pending_payment |
|
591 | + * |
|
592 | + * @return boolean |
|
593 | + */ |
|
594 | + public function is_pending_payment() |
|
595 | + { |
|
596 | + return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false; |
|
597 | + } |
|
598 | + |
|
599 | + |
|
600 | + /** |
|
601 | + * is_approved - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved |
|
602 | + * |
|
603 | + * @return boolean |
|
604 | + */ |
|
605 | + public function is_approved() |
|
606 | + { |
|
607 | + return $this->status_ID() == EEM_Registration::status_id_approved ? true : false; |
|
608 | + } |
|
609 | + |
|
610 | + |
|
611 | + /** |
|
612 | + * is_cancelled - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled |
|
613 | + * |
|
614 | + * @return boolean |
|
615 | + */ |
|
616 | + public function is_cancelled() |
|
617 | + { |
|
618 | + return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false; |
|
619 | + } |
|
620 | + |
|
621 | + |
|
622 | + /** |
|
623 | + * is_declined - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined |
|
624 | + * |
|
625 | + * @return boolean |
|
626 | + */ |
|
627 | + public function is_declined() |
|
628 | + { |
|
629 | + return $this->status_ID() == EEM_Registration::status_id_declined ? true : false; |
|
630 | + } |
|
631 | + |
|
632 | + |
|
633 | + /** |
|
634 | + * is_incomplete - convenience method that returns TRUE if REG status ID == |
|
635 | + * EEM_Registration::status_id_incomplete |
|
636 | + * |
|
637 | + * @return boolean |
|
638 | + */ |
|
639 | + public function is_incomplete() |
|
640 | + { |
|
641 | + return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false; |
|
642 | + } |
|
643 | + |
|
644 | + |
|
645 | + /** |
|
646 | + * Set Registration Date |
|
647 | + * |
|
648 | + * @param mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of |
|
649 | + * Date |
|
650 | + * @throws EE_Error |
|
651 | + * @throws RuntimeException |
|
652 | + */ |
|
653 | + public function set_reg_date($REG_date = false) |
|
654 | + { |
|
655 | + $this->set('REG_date', $REG_date); |
|
656 | + } |
|
657 | + |
|
658 | + |
|
659 | + /** |
|
660 | + * Set final price owing for this registration after all ticket/price modifications |
|
661 | + * |
|
662 | + * @access public |
|
663 | + * @param float $REG_final_price |
|
664 | + * @throws EE_Error |
|
665 | + * @throws RuntimeException |
|
666 | + */ |
|
667 | + public function set_final_price($REG_final_price = 0.00) |
|
668 | + { |
|
669 | + $this->set('REG_final_price', $REG_final_price); |
|
670 | + } |
|
671 | + |
|
672 | + |
|
673 | + /** |
|
674 | + * Set amount paid towards this registration's final price |
|
675 | + * |
|
676 | + * @access public |
|
677 | + * @param float $REG_paid |
|
678 | + * @throws EE_Error |
|
679 | + * @throws RuntimeException |
|
680 | + */ |
|
681 | + public function set_paid($REG_paid = 0.00) |
|
682 | + { |
|
683 | + $this->set('REG_paid', $REG_paid); |
|
684 | + } |
|
685 | + |
|
686 | + |
|
687 | + /** |
|
688 | + * Attendee Is Going |
|
689 | + * |
|
690 | + * @param boolean $REG_att_is_going Attendee Is Going |
|
691 | + * @throws EE_Error |
|
692 | + * @throws RuntimeException |
|
693 | + */ |
|
694 | + public function set_att_is_going($REG_att_is_going = false) |
|
695 | + { |
|
696 | + $this->set('REG_att_is_going', $REG_att_is_going); |
|
697 | + } |
|
698 | + |
|
699 | + |
|
700 | + /** |
|
701 | + * Gets the related attendee |
|
702 | + * |
|
703 | + * @return EE_Attendee |
|
704 | + * @throws EE_Error |
|
705 | + */ |
|
706 | + public function attendee() |
|
707 | + { |
|
708 | + return $this->get_first_related('Attendee'); |
|
709 | + } |
|
710 | + |
|
711 | + |
|
712 | + /** |
|
713 | + * get Event ID |
|
714 | + */ |
|
715 | + public function event_ID() |
|
716 | + { |
|
717 | + return $this->get('EVT_ID'); |
|
718 | + } |
|
719 | + |
|
720 | + |
|
721 | + /** |
|
722 | + * get Event ID |
|
723 | + */ |
|
724 | + public function event_name() |
|
725 | + { |
|
726 | + $event = $this->event_obj(); |
|
727 | + if ($event) { |
|
728 | + return $event->name(); |
|
729 | + } else { |
|
730 | + return null; |
|
731 | + } |
|
732 | + } |
|
733 | + |
|
734 | + |
|
735 | + /** |
|
736 | + * Fetches the event this registration is for |
|
737 | + * |
|
738 | + * @return EE_Event |
|
739 | + * @throws EE_Error |
|
740 | + */ |
|
741 | + public function event_obj() |
|
742 | + { |
|
743 | + return $this->get_first_related('Event'); |
|
744 | + } |
|
745 | + |
|
746 | + |
|
747 | + /** |
|
748 | + * get Attendee ID |
|
749 | + */ |
|
750 | + public function attendee_ID() |
|
751 | + { |
|
752 | + return $this->get('ATT_ID'); |
|
753 | + } |
|
754 | + |
|
755 | + |
|
756 | + /** |
|
757 | + * get PHP Session ID |
|
758 | + */ |
|
759 | + public function session_ID() |
|
760 | + { |
|
761 | + return $this->get('REG_session'); |
|
762 | + } |
|
763 | + |
|
764 | + |
|
765 | + /** |
|
766 | + * Gets the string which represents the URL trigger for the receipt template in the message template system. |
|
767 | + * |
|
768 | + * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
769 | + * @return string |
|
770 | + */ |
|
771 | + public function receipt_url($messenger = 'html') |
|
772 | + { |
|
773 | + |
|
774 | + /** |
|
775 | + * The below will be deprecated one version after this. We check first if there is a custom receipt template |
|
776 | + * already in use on old system. If there is then we just return the standard url for it. |
|
777 | + * |
|
778 | + * @since 4.5.0 |
|
779 | + */ |
|
780 | + $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php'; |
|
781 | + $has_custom = EEH_Template::locate_template( |
|
782 | + $template_relative_path, |
|
783 | + array(), |
|
784 | + true, |
|
785 | + true, |
|
786 | + true |
|
787 | + ); |
|
788 | + |
|
789 | + if ($has_custom) { |
|
790 | + return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch')); |
|
791 | + } |
|
792 | + return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt'); |
|
793 | + } |
|
794 | + |
|
795 | + |
|
796 | + /** |
|
797 | + * Gets the string which represents the URL trigger for the invoice template in the message template system. |
|
798 | + * |
|
799 | + * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
800 | + * @return string |
|
801 | + * @throws EE_Error |
|
802 | + */ |
|
803 | + public function invoice_url($messenger = 'html') |
|
804 | + { |
|
805 | + /** |
|
806 | + * The below will be deprecated one version after this. We check first if there is a custom invoice template |
|
807 | + * already in use on old system. If there is then we just return the standard url for it. |
|
808 | + * |
|
809 | + * @since 4.5.0 |
|
810 | + */ |
|
811 | + $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php'; |
|
812 | + $has_custom = EEH_Template::locate_template( |
|
813 | + $template_relative_path, |
|
814 | + array(), |
|
815 | + true, |
|
816 | + true, |
|
817 | + true |
|
818 | + ); |
|
819 | + |
|
820 | + if ($has_custom) { |
|
821 | + if ($messenger == 'html') { |
|
822 | + return $this->invoice_url('launch'); |
|
823 | + } |
|
824 | + $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice'; |
|
825 | + |
|
826 | + $query_args = array('ee' => $route, 'id' => $this->reg_url_link()); |
|
827 | + if ($messenger == 'html') { |
|
828 | + $query_args['html'] = true; |
|
829 | + } |
|
830 | + return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id)); |
|
831 | + } |
|
832 | + return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice'); |
|
833 | + } |
|
834 | + |
|
835 | + |
|
836 | + /** |
|
837 | + * get Registration URL Link |
|
838 | + * |
|
839 | + * @access public |
|
840 | + * @return string |
|
841 | + * @throws EE_Error |
|
842 | + */ |
|
843 | + public function reg_url_link() |
|
844 | + { |
|
845 | + return (string) $this->get('REG_url_link'); |
|
846 | + } |
|
847 | + |
|
848 | + |
|
849 | + /** |
|
850 | + * Echoes out invoice_url() |
|
851 | + * |
|
852 | + * @param string $type 'download','launch', or 'html' (default is 'launch') |
|
853 | + * @return void |
|
854 | + * @throws EE_Error |
|
855 | + */ |
|
856 | + public function e_invoice_url($type = 'launch') |
|
857 | + { |
|
858 | + echo $this->invoice_url($type); |
|
859 | + } |
|
860 | + |
|
861 | + |
|
862 | + /** |
|
863 | + * Echoes out payment_overview_url |
|
864 | + */ |
|
865 | + public function e_payment_overview_url() |
|
866 | + { |
|
867 | + echo $this->payment_overview_url(); |
|
868 | + } |
|
869 | + |
|
870 | + |
|
871 | + /** |
|
872 | + * Gets the URL of the thank you page with this registration REG_url_link added as |
|
873 | + * a query parameter |
|
874 | + * |
|
875 | + * @param bool $clear_session Set to true when you want to clear the session on revisiting the |
|
876 | + * payment overview url. |
|
877 | + * @return string |
|
878 | + * @throws EE_Error |
|
879 | + */ |
|
880 | + public function payment_overview_url($clear_session = false) |
|
881 | + { |
|
882 | + return add_query_arg(array( |
|
883 | + 'e_reg_url_link' => $this->reg_url_link(), |
|
884 | + 'step' => 'payment_options', |
|
885 | + 'revisit' => true, |
|
886 | + 'clear_session' => (bool) $clear_session |
|
887 | + ), EE_Registry::instance()->CFG->core->reg_page_url()); |
|
888 | + } |
|
889 | + |
|
890 | + |
|
891 | + /** |
|
892 | + * Gets the URL of the thank you page with this registration REG_url_link added as |
|
893 | + * a query parameter |
|
894 | + * |
|
895 | + * @return string |
|
896 | + * @throws EE_Error |
|
897 | + */ |
|
898 | + public function edit_attendee_information_url() |
|
899 | + { |
|
900 | + return add_query_arg(array( |
|
901 | + 'e_reg_url_link' => $this->reg_url_link(), |
|
902 | + 'step' => 'attendee_information', |
|
903 | + 'revisit' => true, |
|
904 | + ), EE_Registry::instance()->CFG->core->reg_page_url()); |
|
905 | + } |
|
906 | + |
|
907 | + |
|
908 | + /** |
|
909 | + * Simply generates and returns the appropriate admin_url link to edit this registration |
|
910 | + * |
|
911 | + * @return string |
|
912 | + * @throws EE_Error |
|
913 | + */ |
|
914 | + public function get_admin_edit_url() |
|
915 | + { |
|
916 | + return EEH_URL::add_query_args_and_nonce(array( |
|
917 | + 'page' => 'espresso_registrations', |
|
918 | + 'action' => 'view_registration', |
|
919 | + '_REG_ID' => $this->ID(), |
|
920 | + ), admin_url('admin.php')); |
|
921 | + } |
|
922 | + |
|
923 | + |
|
924 | + /** |
|
925 | + * is_primary_registrant? |
|
926 | + */ |
|
927 | + public function is_primary_registrant() |
|
928 | + { |
|
929 | + return $this->get('REG_count') == 1 ? true : false; |
|
930 | + } |
|
931 | + |
|
932 | + |
|
933 | + /** |
|
934 | + * This returns the primary registration object for this registration group (which may be this object). |
|
935 | + * |
|
936 | + * @return EE_Registration |
|
937 | + * @throws EE_Error |
|
938 | + */ |
|
939 | + public function get_primary_registration() |
|
940 | + { |
|
941 | + if ($this->is_primary_registrant()) { |
|
942 | + return $this; |
|
943 | + } |
|
944 | + |
|
945 | + //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1 |
|
946 | + /** @var EE_Registration $primary_registrant */ |
|
947 | + $primary_registrant = EEM_Registration::instance()->get_one(array( |
|
948 | + array( |
|
949 | + 'TXN_ID' => $this->transaction_ID(), |
|
950 | + 'REG_count' => 1, |
|
951 | + ), |
|
952 | + )); |
|
953 | + return $primary_registrant; |
|
954 | + } |
|
955 | + |
|
956 | + |
|
957 | + /** |
|
958 | + * get Attendee Number |
|
959 | + * |
|
960 | + * @access public |
|
961 | + */ |
|
962 | + public function count() |
|
963 | + { |
|
964 | + return $this->get('REG_count'); |
|
965 | + } |
|
966 | + |
|
967 | + |
|
968 | + /** |
|
969 | + * get Group Size |
|
970 | + */ |
|
971 | + public function group_size() |
|
972 | + { |
|
973 | + return $this->get('REG_group_size'); |
|
974 | + } |
|
975 | + |
|
976 | + |
|
977 | + /** |
|
978 | + * get Registration Date |
|
979 | + */ |
|
980 | + public function date() |
|
981 | + { |
|
982 | + return $this->get('REG_date'); |
|
983 | + } |
|
984 | + |
|
985 | + |
|
986 | + /** |
|
987 | + * gets a pretty date |
|
988 | + * |
|
989 | + * @param string $date_format |
|
990 | + * @param string $time_format |
|
991 | + * @return string |
|
992 | + * @throws EE_Error |
|
993 | + */ |
|
994 | + public function pretty_date($date_format = null, $time_format = null) |
|
995 | + { |
|
996 | + return $this->get_datetime('REG_date', $date_format, $time_format); |
|
997 | + } |
|
998 | + |
|
999 | + |
|
1000 | + /** |
|
1001 | + * final_price |
|
1002 | + * the registration's share of the transaction total, so that the |
|
1003 | + * sum of all the transaction's REG_final_prices equal the transaction's total |
|
1004 | + * |
|
1005 | + * @return float |
|
1006 | + * @throws EE_Error |
|
1007 | + */ |
|
1008 | + public function final_price() |
|
1009 | + { |
|
1010 | + return $this->get('REG_final_price'); |
|
1011 | + } |
|
1012 | + |
|
1013 | + |
|
1014 | + /** |
|
1015 | + * pretty_final_price |
|
1016 | + * final price as formatted string, with correct decimal places and currency symbol |
|
1017 | + * |
|
1018 | + * @return string |
|
1019 | + * @throws EE_Error |
|
1020 | + */ |
|
1021 | + public function pretty_final_price() |
|
1022 | + { |
|
1023 | + return $this->get_pretty('REG_final_price'); |
|
1024 | + } |
|
1025 | + |
|
1026 | + |
|
1027 | + /** |
|
1028 | + * get paid (yeah) |
|
1029 | + * |
|
1030 | + * @return float |
|
1031 | + * @throws EE_Error |
|
1032 | + */ |
|
1033 | + public function paid() |
|
1034 | + { |
|
1035 | + return $this->get('REG_paid'); |
|
1036 | + } |
|
1037 | + |
|
1038 | + |
|
1039 | + /** |
|
1040 | + * pretty_paid |
|
1041 | + * |
|
1042 | + * @return float |
|
1043 | + * @throws EE_Error |
|
1044 | + */ |
|
1045 | + public function pretty_paid() |
|
1046 | + { |
|
1047 | + return $this->get_pretty('REG_paid'); |
|
1048 | + } |
|
1049 | + |
|
1050 | + |
|
1051 | + /** |
|
1052 | + * owes_monies_and_can_pay |
|
1053 | + * whether or not this registration has monies owing and it's' status allows payment |
|
1054 | + * |
|
1055 | + * @param array $requires_payment |
|
1056 | + * @return bool |
|
1057 | + * @throws EE_Error |
|
1058 | + */ |
|
1059 | + public function owes_monies_and_can_pay($requires_payment = array()) |
|
1060 | + { |
|
1061 | + // these reg statuses require payment (if event is not free) |
|
1062 | + $requires_payment = ! empty($requires_payment) |
|
1063 | + ? $requires_payment |
|
1064 | + : EEM_Registration::reg_statuses_that_allow_payment(); |
|
1065 | + if (in_array($this->status_ID(), $requires_payment) && |
|
1066 | + $this->final_price() != 0 && |
|
1067 | + $this->final_price() != $this->paid() |
|
1068 | + ) { |
|
1069 | + return true; |
|
1070 | + } else { |
|
1071 | + return false; |
|
1072 | + } |
|
1073 | + } |
|
1074 | + |
|
1075 | + |
|
1076 | + /** |
|
1077 | + * Prints out the return value of $this->pretty_status() |
|
1078 | + * |
|
1079 | + * @param bool $show_icons |
|
1080 | + * @return void |
|
1081 | + * @throws EE_Error |
|
1082 | + */ |
|
1083 | + public function e_pretty_status($show_icons = false) |
|
1084 | + { |
|
1085 | + echo $this->pretty_status($show_icons); |
|
1086 | + } |
|
1087 | + |
|
1088 | + |
|
1089 | + /** |
|
1090 | + * Returns a nice version of the status for displaying to customers |
|
1091 | + * |
|
1092 | + * @param bool $show_icons |
|
1093 | + * @return string |
|
1094 | + * @throws EE_Error |
|
1095 | + */ |
|
1096 | + public function pretty_status($show_icons = false) |
|
1097 | + { |
|
1098 | + $status = EEM_Status::instance()->localized_status( |
|
1099 | + array($this->status_ID() => esc_html__('unknown', 'event_espresso')), |
|
1100 | + false, |
|
1101 | + 'sentence' |
|
1102 | + ); |
|
1103 | + $icon = ''; |
|
1104 | + switch ($this->status_ID()) { |
|
1105 | + case EEM_Registration::status_id_approved: |
|
1106 | + $icon = $show_icons |
|
1107 | + ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>' |
|
1108 | + : ''; |
|
1109 | + break; |
|
1110 | + case EEM_Registration::status_id_pending_payment: |
|
1111 | + $icon = $show_icons |
|
1112 | + ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>' |
|
1113 | + : ''; |
|
1114 | + break; |
|
1115 | + case EEM_Registration::status_id_not_approved: |
|
1116 | + $icon = $show_icons |
|
1117 | + ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>' |
|
1118 | + : ''; |
|
1119 | + break; |
|
1120 | + case EEM_Registration::status_id_cancelled: |
|
1121 | + $icon = $show_icons |
|
1122 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>' |
|
1123 | + : ''; |
|
1124 | + break; |
|
1125 | + case EEM_Registration::status_id_incomplete: |
|
1126 | + $icon = $show_icons |
|
1127 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>' |
|
1128 | + : ''; |
|
1129 | + break; |
|
1130 | + case EEM_Registration::status_id_declined: |
|
1131 | + $icon = $show_icons |
|
1132 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' |
|
1133 | + : ''; |
|
1134 | + break; |
|
1135 | + case EEM_Registration::status_id_wait_list: |
|
1136 | + $icon = $show_icons |
|
1137 | + ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>' |
|
1138 | + : ''; |
|
1139 | + break; |
|
1140 | + } |
|
1141 | + return $icon . $status[$this->status_ID()]; |
|
1142 | + } |
|
1143 | + |
|
1144 | + |
|
1145 | + /** |
|
1146 | + * get Attendee Is Going |
|
1147 | + */ |
|
1148 | + public function att_is_going() |
|
1149 | + { |
|
1150 | + return $this->get('REG_att_is_going'); |
|
1151 | + } |
|
1152 | + |
|
1153 | + |
|
1154 | + /** |
|
1155 | + * Gets related answers |
|
1156 | + * |
|
1157 | + * @param array $query_params like EEM_Base::get_all |
|
1158 | + * @return EE_Answer[] |
|
1159 | + * @throws EE_Error |
|
1160 | + */ |
|
1161 | + public function answers($query_params = null) |
|
1162 | + { |
|
1163 | + return $this->get_many_related('Answer', $query_params); |
|
1164 | + } |
|
1165 | + |
|
1166 | + |
|
1167 | + /** |
|
1168 | + * Gets the registration's answer value to the specified question |
|
1169 | + * (either the question's ID or a question object) |
|
1170 | + * |
|
1171 | + * @param EE_Question|int $question |
|
1172 | + * @param bool $pretty_value |
|
1173 | + * @return array|string if pretty_value= true, the result will always be a string |
|
1174 | + * (because the answer might be an array of answer values, so passing pretty_value=true |
|
1175 | + * will convert it into some kind of string) |
|
1176 | + * @throws EE_Error |
|
1177 | + */ |
|
1178 | + public function answer_value_to_question($question, $pretty_value = true) |
|
1179 | + { |
|
1180 | + $question_id = EEM_Question::instance()->ensure_is_ID($question); |
|
1181 | + return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value); |
|
1182 | + } |
|
1183 | + |
|
1184 | + |
|
1185 | + /** |
|
1186 | + * question_groups |
|
1187 | + * returns an array of EE_Question_Group objects for this registration |
|
1188 | + * |
|
1189 | + * @return EE_Question_Group[] |
|
1190 | + * @throws EE_Error |
|
1191 | + * @throws EntityNotFoundException |
|
1192 | + */ |
|
1193 | + public function question_groups() |
|
1194 | + { |
|
1195 | + $question_groups = array(); |
|
1196 | + if ($this->event() instanceof EE_Event) { |
|
1197 | + $question_groups = $this->event()->question_groups( |
|
1198 | + array( |
|
1199 | + array( |
|
1200 | + 'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false, |
|
1201 | + ), |
|
1202 | + 'order_by' => array('QSG_order' => 'ASC'), |
|
1203 | + ) |
|
1204 | + ); |
|
1205 | + } |
|
1206 | + return $question_groups; |
|
1207 | + } |
|
1208 | + |
|
1209 | + |
|
1210 | + /** |
|
1211 | + * count_question_groups |
|
1212 | + * returns a count of the number of EE_Question_Group objects for this registration |
|
1213 | + * |
|
1214 | + * @return int |
|
1215 | + * @throws EE_Error |
|
1216 | + * @throws EntityNotFoundException |
|
1217 | + */ |
|
1218 | + public function count_question_groups() |
|
1219 | + { |
|
1220 | + $qg_count = 0; |
|
1221 | + if ($this->event() instanceof EE_Event) { |
|
1222 | + $qg_count = $this->event()->count_related( |
|
1223 | + 'Question_Group', |
|
1224 | + array( |
|
1225 | + array( |
|
1226 | + 'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false, |
|
1227 | + ), |
|
1228 | + ) |
|
1229 | + ); |
|
1230 | + } |
|
1231 | + return $qg_count; |
|
1232 | + } |
|
1233 | + |
|
1234 | + |
|
1235 | + /** |
|
1236 | + * Returns the registration date in the 'standard' string format |
|
1237 | + * (function may be improved in the future to allow for different formats and timezones) |
|
1238 | + * |
|
1239 | + * @return string |
|
1240 | + * @throws EE_Error |
|
1241 | + */ |
|
1242 | + public function reg_date() |
|
1243 | + { |
|
1244 | + return $this->get_datetime('REG_date'); |
|
1245 | + } |
|
1246 | + |
|
1247 | + |
|
1248 | + /** |
|
1249 | + * Gets the datetime-ticket for this registration (ie, it can be used to isolate |
|
1250 | + * the ticket this registration purchased, or the datetime they have registered |
|
1251 | + * to attend) |
|
1252 | + * |
|
1253 | + * @return EE_Datetime_Ticket |
|
1254 | + * @throws EE_Error |
|
1255 | + */ |
|
1256 | + public function datetime_ticket() |
|
1257 | + { |
|
1258 | + return $this->get_first_related('Datetime_Ticket'); |
|
1259 | + } |
|
1260 | + |
|
1261 | + |
|
1262 | + /** |
|
1263 | + * Sets the registration's datetime_ticket. |
|
1264 | + * |
|
1265 | + * @param EE_Datetime_Ticket $datetime_ticket |
|
1266 | + * @return EE_Datetime_Ticket |
|
1267 | + * @throws EE_Error |
|
1268 | + */ |
|
1269 | + public function set_datetime_ticket($datetime_ticket) |
|
1270 | + { |
|
1271 | + return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket'); |
|
1272 | + } |
|
1273 | + |
|
1274 | + /** |
|
1275 | + * Gets deleted |
|
1276 | + * |
|
1277 | + * @return bool |
|
1278 | + * @throws EE_Error |
|
1279 | + */ |
|
1280 | + public function deleted() |
|
1281 | + { |
|
1282 | + return $this->get('REG_deleted'); |
|
1283 | + } |
|
1284 | + |
|
1285 | + /** |
|
1286 | + * Sets deleted |
|
1287 | + * |
|
1288 | + * @param boolean $deleted |
|
1289 | + * @return bool |
|
1290 | + * @throws EE_Error |
|
1291 | + * @throws RuntimeException |
|
1292 | + */ |
|
1293 | + public function set_deleted($deleted) |
|
1294 | + { |
|
1295 | + if ($deleted) { |
|
1296 | + $this->delete(); |
|
1297 | + } else { |
|
1298 | + $this->restore(); |
|
1299 | + } |
|
1300 | + } |
|
1301 | + |
|
1302 | + |
|
1303 | + /** |
|
1304 | + * Get the status object of this object |
|
1305 | + * |
|
1306 | + * @return EE_Status |
|
1307 | + * @throws EE_Error |
|
1308 | + */ |
|
1309 | + public function status_obj() |
|
1310 | + { |
|
1311 | + return $this->get_first_related('Status'); |
|
1312 | + } |
|
1313 | + |
|
1314 | + |
|
1315 | + /** |
|
1316 | + * Returns the number of times this registration has checked into any of the datetimes |
|
1317 | + * its available for |
|
1318 | + * |
|
1319 | + * @return int |
|
1320 | + * @throws EE_Error |
|
1321 | + */ |
|
1322 | + public function count_checkins() |
|
1323 | + { |
|
1324 | + return $this->get_model()->count_related($this, 'Checkin'); |
|
1325 | + } |
|
1326 | + |
|
1327 | + |
|
1328 | + /** |
|
1329 | + * Returns the number of current Check-ins this registration is checked into for any of the datetimes the |
|
1330 | + * registration is for. Note, this is ONLY checked in (does not include checkedout) |
|
1331 | + * |
|
1332 | + * @return int |
|
1333 | + * @throws EE_Error |
|
1334 | + */ |
|
1335 | + public function count_checkins_not_checkedout() |
|
1336 | + { |
|
1337 | + return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1))); |
|
1338 | + } |
|
1339 | + |
|
1340 | + |
|
1341 | + /** |
|
1342 | + * The purpose of this method is simply to check whether this registration can checkin to the given datetime. |
|
1343 | + * |
|
1344 | + * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
1345 | + * @param bool $check_approved This is used to indicate whether the caller wants can_checkin to also |
|
1346 | + * consider registration status as well as datetime access. |
|
1347 | + * @return bool |
|
1348 | + * @throws EE_Error |
|
1349 | + */ |
|
1350 | + public function can_checkin($DTT_OR_ID, $check_approved = true) |
|
1351 | + { |
|
1352 | + $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
1353 | + |
|
1354 | + //first check registration status |
|
1355 | + if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) { |
|
1356 | + return false; |
|
1357 | + } |
|
1358 | + //is there a datetime ticket that matches this dtt_ID? |
|
1359 | + if (! (EEM_Datetime_Ticket::instance()->exists(array( |
|
1360 | + array( |
|
1361 | + 'TKT_ID' => $this->get('TKT_ID'), |
|
1362 | + 'DTT_ID' => $DTT_ID, |
|
1363 | + ), |
|
1364 | + ))) |
|
1365 | + ) { |
|
1366 | + return false; |
|
1367 | + } |
|
1368 | + |
|
1369 | + //final check is against TKT_uses |
|
1370 | + return $this->verify_can_checkin_against_TKT_uses($DTT_ID); |
|
1371 | + } |
|
1372 | + |
|
1373 | + |
|
1374 | + /** |
|
1375 | + * This method verifies whether the user can checkin for the given datetime considering the max uses value set on |
|
1376 | + * the ticket. To do this, a query is done to get the count of the datetime records already checked into. If the |
|
1377 | + * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses, |
|
1378 | + * then return false. Otherwise return true. |
|
1379 | + * |
|
1380 | + * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
1381 | + * @return bool true means can checkin. false means cannot checkin. |
|
1382 | + * @throws EE_Error |
|
1383 | + */ |
|
1384 | + public function verify_can_checkin_against_TKT_uses($DTT_OR_ID) |
|
1385 | + { |
|
1386 | + $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
1387 | + |
|
1388 | + if (! $DTT_ID) { |
|
1389 | + return false; |
|
1390 | + } |
|
1391 | + |
|
1392 | + $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF; |
|
1393 | + |
|
1394 | + // if max uses is not set or equals infinity then return true cause its not a factor for whether user can |
|
1395 | + // check-in or not. |
|
1396 | + if (! $max_uses || $max_uses === EE_INF) { |
|
1397 | + return true; |
|
1398 | + } |
|
1399 | + |
|
1400 | + //does this datetime have a checkin record? If so, then the dtt count has already been verified so we can just |
|
1401 | + //go ahead and toggle. |
|
1402 | + if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) { |
|
1403 | + return true; |
|
1404 | + } |
|
1405 | + |
|
1406 | + //made it here so the last check is whether the number of checkins per unique datetime on this registration |
|
1407 | + //disallows further check-ins. |
|
1408 | + $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array( |
|
1409 | + array( |
|
1410 | + 'REG_ID' => $this->ID(), |
|
1411 | + 'CHK_in' => true, |
|
1412 | + ), |
|
1413 | + ), 'DTT_ID', true); |
|
1414 | + // checkins have already reached their max number of uses |
|
1415 | + // so registrant can NOT checkin |
|
1416 | + if ($count_unique_dtt_checkins >= $max_uses) { |
|
1417 | + EE_Error::add_error( |
|
1418 | + esc_html__( |
|
1419 | + 'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.', |
|
1420 | + 'event_espresso' |
|
1421 | + ), |
|
1422 | + __FILE__, |
|
1423 | + __FUNCTION__, |
|
1424 | + __LINE__ |
|
1425 | + ); |
|
1426 | + return false; |
|
1427 | + } |
|
1428 | + return true; |
|
1429 | + } |
|
1430 | + |
|
1431 | + |
|
1432 | + /** |
|
1433 | + * toggle Check-in status for this registration |
|
1434 | + * Check-ins are toggled in the following order: |
|
1435 | + * never checked in -> checked in |
|
1436 | + * checked in -> checked out |
|
1437 | + * checked out -> checked in |
|
1438 | + * |
|
1439 | + * @param int $DTT_ID include specific datetime to toggle Check-in for. |
|
1440 | + * If not included or null, then it is assumed latest datetime is being toggled. |
|
1441 | + * @param bool $verify If true then can_checkin() is used to verify whether the person |
|
1442 | + * can be checked in or not. Otherwise this forces change in checkin status. |
|
1443 | + * @return bool|int the chk_in status toggled to OR false if nothing got changed. |
|
1444 | + * @throws EE_Error |
|
1445 | + */ |
|
1446 | + public function toggle_checkin_status($DTT_ID = null, $verify = false) |
|
1447 | + { |
|
1448 | + if (empty($DTT_ID)) { |
|
1449 | + $datetime = $this->get_latest_related_datetime(); |
|
1450 | + $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0; |
|
1451 | + // verify the registration can checkin for the given DTT_ID |
|
1452 | + } elseif (! $this->can_checkin($DTT_ID, $verify)) { |
|
1453 | + EE_Error::add_error( |
|
1454 | + sprintf( |
|
1455 | + esc_html__( |
|
1456 | + 'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access', |
|
1457 | + 'event_espresso' |
|
1458 | + ), |
|
1459 | + $this->ID(), |
|
1460 | + $DTT_ID |
|
1461 | + ), |
|
1462 | + __FILE__, |
|
1463 | + __FUNCTION__, |
|
1464 | + __LINE__ |
|
1465 | + ); |
|
1466 | + return false; |
|
1467 | + } |
|
1468 | + $status_paths = array( |
|
1469 | + EE_Checkin::status_checked_never => EE_Checkin::status_checked_in, |
|
1470 | + EE_Checkin::status_checked_in => EE_Checkin::status_checked_out, |
|
1471 | + EE_Checkin::status_checked_out => EE_Checkin::status_checked_in, |
|
1472 | + ); |
|
1473 | + //start by getting the current status so we know what status we'll be changing to. |
|
1474 | + $cur_status = $this->check_in_status_for_datetime($DTT_ID, null); |
|
1475 | + $status_to = $status_paths[$cur_status]; |
|
1476 | + // database only records true for checked IN or false for checked OUT |
|
1477 | + // no record ( null ) means checked in NEVER, but we obviously don't save that |
|
1478 | + $new_status = $status_to === EE_Checkin::status_checked_in ? true : false; |
|
1479 | + // add relation - note Check-ins are always creating new rows |
|
1480 | + // because we are keeping track of Check-ins over time. |
|
1481 | + // Eventually we'll probably want to show a list table |
|
1482 | + // for the individual Check-ins so that they can be managed. |
|
1483 | + $checkin = EE_Checkin::new_instance(array( |
|
1484 | + 'REG_ID' => $this->ID(), |
|
1485 | + 'DTT_ID' => $DTT_ID, |
|
1486 | + 'CHK_in' => $new_status, |
|
1487 | + )); |
|
1488 | + // if the record could not be saved then return false |
|
1489 | + if ($checkin->save() === 0) { |
|
1490 | + if (WP_DEBUG) { |
|
1491 | + global $wpdb; |
|
1492 | + $error = sprintf( |
|
1493 | + esc_html__( |
|
1494 | + 'Registration check in update failed because of the following database error: %1$s%2$s', |
|
1495 | + 'event_espresso' |
|
1496 | + ), |
|
1497 | + '<br />', |
|
1498 | + $wpdb->last_error |
|
1499 | + ); |
|
1500 | + } else { |
|
1501 | + $error = esc_html__( |
|
1502 | + 'Registration check in update failed because of an unknown database error', |
|
1503 | + 'event_espresso' |
|
1504 | + ); |
|
1505 | + } |
|
1506 | + EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
1507 | + return false; |
|
1508 | + } |
|
1509 | + return $status_to; |
|
1510 | + } |
|
1511 | + |
|
1512 | + |
|
1513 | + /** |
|
1514 | + * Returns the latest datetime related to this registration (via the ticket attached to the registration). |
|
1515 | + * "Latest" is defined by the `DTT_EVT_start` column. |
|
1516 | + * |
|
1517 | + * @return EE_Datetime|null |
|
1518 | + * @throws EE_Error |
|
1519 | + */ |
|
1520 | + public function get_latest_related_datetime() |
|
1521 | + { |
|
1522 | + return EEM_Datetime::instance()->get_one( |
|
1523 | + array( |
|
1524 | + array( |
|
1525 | + 'Ticket.Registration.REG_ID' => $this->ID(), |
|
1526 | + ), |
|
1527 | + 'order_by' => array('DTT_EVT_start' => 'DESC'), |
|
1528 | + ) |
|
1529 | + ); |
|
1530 | + } |
|
1531 | + |
|
1532 | + |
|
1533 | + /** |
|
1534 | + * Returns the earliest datetime related to this registration (via the ticket attached to the registration). |
|
1535 | + * "Earliest" is defined by the `DTT_EVT_start` column. |
|
1536 | + * |
|
1537 | + * @throws EE_Error |
|
1538 | + */ |
|
1539 | + public function get_earliest_related_datetime() |
|
1540 | + { |
|
1541 | + return EEM_Datetime::instance()->get_one( |
|
1542 | + array( |
|
1543 | + array( |
|
1544 | + 'Ticket.Registration.REG_ID' => $this->ID(), |
|
1545 | + ), |
|
1546 | + 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
1547 | + ) |
|
1548 | + ); |
|
1549 | + } |
|
1550 | + |
|
1551 | + |
|
1552 | + /** |
|
1553 | + * This method simply returns the check-in status for this registration and the given datetime. |
|
1554 | + * If neither the datetime nor the checkin values are provided as arguments, |
|
1555 | + * then this will return the LATEST check-in status for the registration across all datetimes it belongs to. |
|
1556 | + * |
|
1557 | + * @param int $DTT_ID The ID of the datetime we're checking against |
|
1558 | + * (if empty we'll get the primary datetime for |
|
1559 | + * this registration (via event) and use it's ID); |
|
1560 | + * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id. |
|
1561 | + * |
|
1562 | + * @return int Integer representing Check-in status. |
|
1563 | + * @throws EE_Error |
|
1564 | + */ |
|
1565 | + public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null) |
|
1566 | + { |
|
1567 | + $checkin_query_params = array( |
|
1568 | + 'order_by' => array('CHK_timestamp' => 'DESC'), |
|
1569 | + ); |
|
1570 | + |
|
1571 | + if ($DTT_ID > 0) { |
|
1572 | + $checkin_query_params[0] = array('DTT_ID' => $DTT_ID); |
|
1573 | + } |
|
1574 | + |
|
1575 | + //get checkin object (if exists) |
|
1576 | + $checkin = $checkin instanceof EE_Checkin |
|
1577 | + ? $checkin |
|
1578 | + : $this->get_first_related('Checkin', $checkin_query_params); |
|
1579 | + if ($checkin instanceof EE_Checkin) { |
|
1580 | + if ($checkin->get('CHK_in')) { |
|
1581 | + return EE_Checkin::status_checked_in; //checked in |
|
1582 | + } |
|
1583 | + return EE_Checkin::status_checked_out; //had checked in but is now checked out. |
|
1584 | + } |
|
1585 | + return EE_Checkin::status_checked_never; //never been checked in |
|
1586 | + } |
|
1587 | + |
|
1588 | + |
|
1589 | + /** |
|
1590 | + * This method returns a localized message for the toggled Check-in message. |
|
1591 | + * |
|
1592 | + * @param int $DTT_ID include specific datetime to get the correct Check-in message. If not included or null, |
|
1593 | + * then it is assumed Check-in for primary datetime was toggled. |
|
1594 | + * @param bool $error This just flags that you want an error message returned. This is put in so that the error |
|
1595 | + * message can be customized with the attendee name. |
|
1596 | + * @return string internationalized message |
|
1597 | + * @throws EE_Error |
|
1598 | + */ |
|
1599 | + public function get_checkin_msg($DTT_ID, $error = false) |
|
1600 | + { |
|
1601 | + //let's get the attendee first so we can include the name of the attendee |
|
1602 | + $attendee = $this->get_first_related('Attendee'); |
|
1603 | + if ($attendee instanceof EE_Attendee) { |
|
1604 | + if ($error) { |
|
1605 | + return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name()); |
|
1606 | + } |
|
1607 | + $cur_status = $this->check_in_status_for_datetime($DTT_ID); |
|
1608 | + //what is the status message going to be? |
|
1609 | + switch ($cur_status) { |
|
1610 | + case EE_Checkin::status_checked_never: |
|
1611 | + return sprintf(__("%s has been removed from Check-in records", "event_espresso"), |
|
1612 | + $attendee->full_name()); |
|
1613 | + break; |
|
1614 | + case EE_Checkin::status_checked_in: |
|
1615 | + return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name()); |
|
1616 | + break; |
|
1617 | + case EE_Checkin::status_checked_out: |
|
1618 | + return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name()); |
|
1619 | + break; |
|
1620 | + } |
|
1621 | + } |
|
1622 | + return esc_html__("The check-in status could not be determined.", "event_espresso"); |
|
1623 | + } |
|
1624 | + |
|
1625 | + |
|
1626 | + /** |
|
1627 | + * Returns the related EE_Transaction to this registration |
|
1628 | + * |
|
1629 | + * @return EE_Transaction |
|
1630 | + * @throws EE_Error |
|
1631 | + * @throws EntityNotFoundException |
|
1632 | + */ |
|
1633 | + public function transaction() |
|
1634 | + { |
|
1635 | + $transaction = $this->get_first_related('Transaction'); |
|
1636 | + if (! $transaction instanceof \EE_Transaction) { |
|
1637 | + throw new EntityNotFoundException('Transaction ID', $this->transaction_ID()); |
|
1638 | + } |
|
1639 | + return $transaction; |
|
1640 | + } |
|
1641 | + |
|
1642 | + |
|
1643 | + /** |
|
1644 | + * get Registration Code |
|
1645 | + */ |
|
1646 | + public function reg_code() |
|
1647 | + { |
|
1648 | + return $this->get('REG_code'); |
|
1649 | + } |
|
1650 | + |
|
1651 | + |
|
1652 | + /** |
|
1653 | + * get Transaction ID |
|
1654 | + */ |
|
1655 | + public function transaction_ID() |
|
1656 | + { |
|
1657 | + return $this->get('TXN_ID'); |
|
1658 | + } |
|
1659 | + |
|
1660 | + |
|
1661 | + /** |
|
1662 | + * @return int |
|
1663 | + * @throws EE_Error |
|
1664 | + */ |
|
1665 | + public function ticket_ID() |
|
1666 | + { |
|
1667 | + return $this->get('TKT_ID'); |
|
1668 | + } |
|
1669 | + |
|
1670 | + |
|
1671 | + /** |
|
1672 | + * Set Registration Code |
|
1673 | + * |
|
1674 | + * @access public |
|
1675 | + * @param string $REG_code Registration Code |
|
1676 | + * @param boolean $use_default |
|
1677 | + * @throws EE_Error |
|
1678 | + */ |
|
1679 | + public function set_reg_code($REG_code, $use_default = false) |
|
1680 | + { |
|
1681 | + if (empty($REG_code)) { |
|
1682 | + EE_Error::add_error( |
|
1683 | + esc_html__('REG_code can not be empty.', 'event_espresso'), |
|
1684 | + __FILE__, |
|
1685 | + __FUNCTION__, |
|
1686 | + __LINE__ |
|
1687 | + ); |
|
1688 | + return; |
|
1689 | + } |
|
1690 | + if (! $this->reg_code()) { |
|
1691 | + parent::set('REG_code', $REG_code, $use_default); |
|
1692 | + } else { |
|
1693 | + EE_Error::doing_it_wrong( |
|
1694 | + __CLASS__ . '::' . __FUNCTION__, |
|
1695 | + esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'), |
|
1696 | + '4.6.0' |
|
1697 | + ); |
|
1698 | + } |
|
1699 | + } |
|
1700 | + |
|
1701 | + |
|
1702 | + /** |
|
1703 | + * Returns all other registrations in the same group as this registrant who have the same ticket option. |
|
1704 | + * Note, if you want to just get all registrations in the same transaction (group), use: |
|
1705 | + * $registration->transaction()->registrations(); |
|
1706 | + * |
|
1707 | + * @since 4.5.0 |
|
1708 | + * @return EE_Registration[] or empty array if this isn't a group registration. |
|
1709 | + * @throws EE_Error |
|
1710 | + */ |
|
1711 | + public function get_all_other_registrations_in_group() |
|
1712 | + { |
|
1713 | + if ($this->group_size() < 2) { |
|
1714 | + return array(); |
|
1715 | + } |
|
1716 | + |
|
1717 | + $query[0] = array( |
|
1718 | + 'TXN_ID' => $this->transaction_ID(), |
|
1719 | + 'REG_ID' => array('!=', $this->ID()), |
|
1720 | + 'TKT_ID' => $this->ticket_ID(), |
|
1721 | + ); |
|
1722 | + /** @var EE_Registration[] $registrations */ |
|
1723 | + $registrations = $this->get_model()->get_all($query); |
|
1724 | + return $registrations; |
|
1725 | + } |
|
1726 | + |
|
1727 | + /** |
|
1728 | + * Return the link to the admin details for the object. |
|
1729 | + * |
|
1730 | + * @return string |
|
1731 | + * @throws EE_Error |
|
1732 | + */ |
|
1733 | + public function get_admin_details_link() |
|
1734 | + { |
|
1735 | + EE_Registry::instance()->load_helper('URL'); |
|
1736 | + return EEH_URL::add_query_args_and_nonce( |
|
1737 | + array( |
|
1738 | + 'page' => 'espresso_registrations', |
|
1739 | + 'action' => 'view_registration', |
|
1740 | + '_REG_ID' => $this->ID(), |
|
1741 | + ), |
|
1742 | + admin_url('admin.php') |
|
1743 | + ); |
|
1744 | + } |
|
1745 | + |
|
1746 | + /** |
|
1747 | + * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
1748 | + * |
|
1749 | + * @return string |
|
1750 | + * @throws EE_Error |
|
1751 | + */ |
|
1752 | + public function get_admin_edit_link() |
|
1753 | + { |
|
1754 | + return $this->get_admin_details_link(); |
|
1755 | + } |
|
1756 | + |
|
1757 | + /** |
|
1758 | + * Returns the link to a settings page for the object. |
|
1759 | + * |
|
1760 | + * @return string |
|
1761 | + * @throws EE_Error |
|
1762 | + */ |
|
1763 | + public function get_admin_settings_link() |
|
1764 | + { |
|
1765 | + return $this->get_admin_details_link(); |
|
1766 | + } |
|
1767 | + |
|
1768 | + /** |
|
1769 | + * Returns the link to the "overview" for the object (typically the "list table" view). |
|
1770 | + * |
|
1771 | + * @return string |
|
1772 | + */ |
|
1773 | + public function get_admin_overview_link() |
|
1774 | + { |
|
1775 | + EE_Registry::instance()->load_helper('URL'); |
|
1776 | + return EEH_URL::add_query_args_and_nonce( |
|
1777 | + array( |
|
1778 | + 'page' => 'espresso_registrations', |
|
1779 | + ), |
|
1780 | + admin_url('admin.php') |
|
1781 | + ); |
|
1782 | + } |
|
1783 | + |
|
1784 | + |
|
1785 | + /** |
|
1786 | + * @param array $query_params |
|
1787 | + * |
|
1788 | + * @return \EE_Registration[] |
|
1789 | + * @throws EE_Error |
|
1790 | + */ |
|
1791 | + public function payments($query_params = array()) |
|
1792 | + { |
|
1793 | + return $this->get_many_related('Payment', $query_params); |
|
1794 | + } |
|
1795 | + |
|
1796 | + |
|
1797 | + /** |
|
1798 | + * @param array $query_params |
|
1799 | + * |
|
1800 | + * @return \EE_Registration_Payment[] |
|
1801 | + * @throws EE_Error |
|
1802 | + */ |
|
1803 | + public function registration_payments($query_params = array()) |
|
1804 | + { |
|
1805 | + return $this->get_many_related('Registration_Payment', $query_params); |
|
1806 | + } |
|
1807 | + |
|
1808 | + |
|
1809 | + /** |
|
1810 | + * This grabs the payment method corresponding to the last payment made for the amount owing on the registration. |
|
1811 | + * Note: if there are no payments on the registration there will be no payment method returned. |
|
1812 | + * |
|
1813 | + * @return EE_Payment_Method|null |
|
1814 | + */ |
|
1815 | + public function payment_method() |
|
1816 | + { |
|
1817 | + return EEM_Payment_Method::instance()->get_last_used_for_registration($this); |
|
1818 | + } |
|
1819 | + |
|
1820 | + |
|
1821 | + /** |
|
1822 | + * @return \EE_Line_Item |
|
1823 | + * @throws EntityNotFoundException |
|
1824 | + * @throws EE_Error |
|
1825 | + */ |
|
1826 | + public function ticket_line_item() |
|
1827 | + { |
|
1828 | + $ticket = $this->ticket(); |
|
1829 | + $transaction = $this->transaction(); |
|
1830 | + $line_item = null; |
|
1831 | + $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
1832 | + $transaction->total_line_item(), |
|
1833 | + 'Ticket', |
|
1834 | + array($ticket->ID()) |
|
1835 | + ); |
|
1836 | + foreach ($ticket_line_items as $ticket_line_item) { |
|
1837 | + if ( |
|
1838 | + $ticket_line_item instanceof \EE_Line_Item |
|
1839 | + && $ticket_line_item->OBJ_type() === 'Ticket' |
|
1840 | + && $ticket_line_item->OBJ_ID() === $ticket->ID() |
|
1841 | + ) { |
|
1842 | + $line_item = $ticket_line_item; |
|
1843 | + break; |
|
1844 | + } |
|
1845 | + } |
|
1846 | + if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
1847 | + throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID()); |
|
1848 | + } |
|
1849 | + return $line_item; |
|
1850 | + } |
|
1851 | + |
|
1852 | + |
|
1853 | + /** |
|
1854 | + * Soft Deletes this model object. |
|
1855 | + * |
|
1856 | + * @return boolean | int |
|
1857 | + * @throws RuntimeException |
|
1858 | + * @throws EE_Error |
|
1859 | + */ |
|
1860 | + public function delete() |
|
1861 | + { |
|
1862 | + if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) { |
|
1863 | + $this->set_status(EEM_Registration::status_id_cancelled); |
|
1864 | + } |
|
1865 | + return parent::delete(); |
|
1866 | + } |
|
1867 | + |
|
1868 | + |
|
1869 | + /** |
|
1870 | + * Restores whatever the previous status was on a registration before it was trashed (if possible) |
|
1871 | + * |
|
1872 | + * @throws EE_Error |
|
1873 | + * @throws RuntimeException |
|
1874 | + */ |
|
1875 | + public function restore() |
|
1876 | + { |
|
1877 | + $previous_status = $this->get_extra_meta( |
|
1878 | + EE_Registration::PRE_TRASH_REG_STATUS_KEY, |
|
1879 | + true, |
|
1880 | + EEM_Registration::status_id_cancelled |
|
1881 | + ); |
|
1882 | + if ($previous_status) { |
|
1883 | + $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY); |
|
1884 | + $this->set_status($previous_status); |
|
1885 | + } |
|
1886 | + return parent::restore(); |
|
1887 | + } |
|
1888 | + |
|
1889 | + |
|
1890 | + /** |
|
1891 | + * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price |
|
1892 | + * |
|
1893 | + * @param boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic |
|
1894 | + * depending on whether the reg status changes to or from "Approved" |
|
1895 | + * @return boolean whether the Registration status was updated |
|
1896 | + * @throws EE_Error |
|
1897 | + * @throws RuntimeException |
|
1898 | + */ |
|
1899 | + public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true) |
|
1900 | + { |
|
1901 | + $paid = $this->paid(); |
|
1902 | + $price = $this->final_price(); |
|
1903 | + switch(true) { |
|
1904 | + // overpaid or paid |
|
1905 | + case EEH_Money::compare_floats($paid, $price, '>'): |
|
1906 | + case EEH_Money::compare_floats($paid, $price): |
|
1907 | + $new_status = EEM_Registration::status_id_approved; |
|
1908 | + break; |
|
1909 | + // underpaid |
|
1910 | + case EEH_Money::compare_floats($paid, $price, '<'): |
|
1911 | + $new_status = EEM_Registration::status_id_pending_payment; |
|
1912 | + break; |
|
1913 | + // uhhh Houston... |
|
1914 | + default: |
|
1915 | + throw new RuntimeException( |
|
1916 | + esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso') |
|
1917 | + ); |
|
1918 | + } |
|
1919 | + if ($new_status !== $this->status_ID()) { |
|
1920 | + if ($trigger_set_status_logic) { |
|
1921 | + return $this->set_status($new_status); |
|
1922 | + } |
|
1923 | + parent::set('STS_ID', $new_status); |
|
1924 | + return true; |
|
1925 | + } |
|
1926 | + return false; |
|
1927 | + } |
|
1928 | + |
|
1929 | + |
|
1930 | + /*************************** DEPRECATED ***************************/ |
|
1931 | + |
|
1932 | + |
|
1933 | + /** |
|
1934 | + * @deprecated |
|
1935 | + * @since 4.7.0 |
|
1936 | + * @access public |
|
1937 | + */ |
|
1938 | + public function price_paid() |
|
1939 | + { |
|
1940 | + EE_Error::doing_it_wrong('EE_Registration::price_paid()', |
|
1941 | + esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'), |
|
1942 | + '4.7.0'); |
|
1943 | + return $this->final_price(); |
|
1944 | + } |
|
1945 | + |
|
1946 | + |
|
1947 | + /** |
|
1948 | + * @deprecated |
|
1949 | + * @since 4.7.0 |
|
1950 | + * @access public |
|
1951 | + * @param float $REG_final_price |
|
1952 | + * @throws EE_Error |
|
1953 | + * @throws RuntimeException |
|
1954 | + */ |
|
1955 | + public function set_price_paid($REG_final_price = 0.00) |
|
1956 | + { |
|
1957 | + EE_Error::doing_it_wrong('EE_Registration::set_price_paid()', |
|
1958 | + esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'), |
|
1959 | + '4.7.0'); |
|
1960 | + $this->set_final_price($REG_final_price); |
|
1961 | + } |
|
1962 | + |
|
1963 | + |
|
1964 | + /** |
|
1965 | + * @deprecated |
|
1966 | + * @since 4.7.0 |
|
1967 | + * @return string |
|
1968 | + * @throws EE_Error |
|
1969 | + */ |
|
1970 | + public function pretty_price_paid() |
|
1971 | + { |
|
1972 | + EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()', |
|
1973 | + esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.', |
|
1974 | + 'event_espresso'), '4.7.0'); |
|
1975 | + return $this->pretty_final_price(); |
|
1976 | + } |
|
1977 | + |
|
1978 | + |
|
1979 | + /** |
|
1980 | + * Gets the primary datetime related to this registration via the related Event to this registration |
|
1981 | + * |
|
1982 | + * @deprecated 4.9.17 |
|
1983 | + * @return EE_Datetime |
|
1984 | + * @throws EE_Error |
|
1985 | + * @throws EntityNotFoundException |
|
1986 | + */ |
|
1987 | + public function get_related_primary_datetime() |
|
1988 | + { |
|
1989 | + EE_Error::doing_it_wrong( |
|
1990 | + __METHOD__, |
|
1991 | + esc_html__( |
|
1992 | + 'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()', |
|
1993 | + 'event_espresso' |
|
1994 | + ), |
|
1995 | + '4.9.17', |
|
1996 | + '5.0.0' |
|
1997 | + ); |
|
1998 | + return $this->event()->primary_datetime(); |
|
1999 | + } |
|
2000 | 2000 | |
2001 | 2001 | |
2002 | 2002 | } |
@@ -120,7 +120,7 @@ discard block |
||
120 | 120 | { |
121 | 121 | switch ($field_name) { |
122 | 122 | case 'REG_code': |
123 | - if (! empty($field_value) && $this->reg_code() === null) { |
|
123 | + if ( ! empty($field_value) && $this->reg_code() === null) { |
|
124 | 124 | $this->set_reg_code($field_value, $use_default); |
125 | 125 | } |
126 | 126 | break; |
@@ -181,7 +181,7 @@ discard block |
||
181 | 181 | // update status |
182 | 182 | parent::set('STS_ID', $new_STS_ID, $use_default); |
183 | 183 | $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context); |
184 | - if($this->statusChangeUpdatesTransaction($context)) { |
|
184 | + if ($this->statusChangeUpdatesTransaction($context)) { |
|
185 | 185 | $this->updateTransactionAfterStatusChange(); |
186 | 186 | } |
187 | 187 | do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context); |
@@ -409,7 +409,7 @@ discard block |
||
409 | 409 | public function event() |
410 | 410 | { |
411 | 411 | $event = $this->get_first_related('Event'); |
412 | - if (! $event instanceof \EE_Event) { |
|
412 | + if ( ! $event instanceof \EE_Event) { |
|
413 | 413 | throw new EntityNotFoundException('Event ID', $this->event_ID()); |
414 | 414 | } |
415 | 415 | return $event; |
@@ -1100,7 +1100,7 @@ discard block |
||
1100 | 1100 | false, |
1101 | 1101 | 'sentence' |
1102 | 1102 | ); |
1103 | - $icon = ''; |
|
1103 | + $icon = ''; |
|
1104 | 1104 | switch ($this->status_ID()) { |
1105 | 1105 | case EEM_Registration::status_id_approved: |
1106 | 1106 | $icon = $show_icons |
@@ -1138,7 +1138,7 @@ discard block |
||
1138 | 1138 | : ''; |
1139 | 1139 | break; |
1140 | 1140 | } |
1141 | - return $icon . $status[$this->status_ID()]; |
|
1141 | + return $icon.$status[$this->status_ID()]; |
|
1142 | 1142 | } |
1143 | 1143 | |
1144 | 1144 | |
@@ -1356,7 +1356,7 @@ discard block |
||
1356 | 1356 | return false; |
1357 | 1357 | } |
1358 | 1358 | //is there a datetime ticket that matches this dtt_ID? |
1359 | - if (! (EEM_Datetime_Ticket::instance()->exists(array( |
|
1359 | + if ( ! (EEM_Datetime_Ticket::instance()->exists(array( |
|
1360 | 1360 | array( |
1361 | 1361 | 'TKT_ID' => $this->get('TKT_ID'), |
1362 | 1362 | 'DTT_ID' => $DTT_ID, |
@@ -1385,7 +1385,7 @@ discard block |
||
1385 | 1385 | { |
1386 | 1386 | $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
1387 | 1387 | |
1388 | - if (! $DTT_ID) { |
|
1388 | + if ( ! $DTT_ID) { |
|
1389 | 1389 | return false; |
1390 | 1390 | } |
1391 | 1391 | |
@@ -1393,7 +1393,7 @@ discard block |
||
1393 | 1393 | |
1394 | 1394 | // if max uses is not set or equals infinity then return true cause its not a factor for whether user can |
1395 | 1395 | // check-in or not. |
1396 | - if (! $max_uses || $max_uses === EE_INF) { |
|
1396 | + if ( ! $max_uses || $max_uses === EE_INF) { |
|
1397 | 1397 | return true; |
1398 | 1398 | } |
1399 | 1399 | |
@@ -1449,7 +1449,7 @@ discard block |
||
1449 | 1449 | $datetime = $this->get_latest_related_datetime(); |
1450 | 1450 | $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0; |
1451 | 1451 | // verify the registration can checkin for the given DTT_ID |
1452 | - } elseif (! $this->can_checkin($DTT_ID, $verify)) { |
|
1452 | + } elseif ( ! $this->can_checkin($DTT_ID, $verify)) { |
|
1453 | 1453 | EE_Error::add_error( |
1454 | 1454 | sprintf( |
1455 | 1455 | esc_html__( |
@@ -1633,7 +1633,7 @@ discard block |
||
1633 | 1633 | public function transaction() |
1634 | 1634 | { |
1635 | 1635 | $transaction = $this->get_first_related('Transaction'); |
1636 | - if (! $transaction instanceof \EE_Transaction) { |
|
1636 | + if ( ! $transaction instanceof \EE_Transaction) { |
|
1637 | 1637 | throw new EntityNotFoundException('Transaction ID', $this->transaction_ID()); |
1638 | 1638 | } |
1639 | 1639 | return $transaction; |
@@ -1687,11 +1687,11 @@ discard block |
||
1687 | 1687 | ); |
1688 | 1688 | return; |
1689 | 1689 | } |
1690 | - if (! $this->reg_code()) { |
|
1690 | + if ( ! $this->reg_code()) { |
|
1691 | 1691 | parent::set('REG_code', $REG_code, $use_default); |
1692 | 1692 | } else { |
1693 | 1693 | EE_Error::doing_it_wrong( |
1694 | - __CLASS__ . '::' . __FUNCTION__, |
|
1694 | + __CLASS__.'::'.__FUNCTION__, |
|
1695 | 1695 | esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'), |
1696 | 1696 | '4.6.0' |
1697 | 1697 | ); |
@@ -1843,7 +1843,7 @@ discard block |
||
1843 | 1843 | break; |
1844 | 1844 | } |
1845 | 1845 | } |
1846 | - if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
1846 | + if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
1847 | 1847 | throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID()); |
1848 | 1848 | } |
1849 | 1849 | return $line_item; |
@@ -1900,7 +1900,7 @@ discard block |
||
1900 | 1900 | { |
1901 | 1901 | $paid = $this->paid(); |
1902 | 1902 | $price = $this->final_price(); |
1903 | - switch(true) { |
|
1903 | + switch (true) { |
|
1904 | 1904 | // overpaid or paid |
1905 | 1905 | case EEH_Money::compare_floats($paid, $price, '>'): |
1906 | 1906 | case EEH_Money::compare_floats($paid, $price): |
@@ -17,309 +17,309 @@ |
||
17 | 17 | class Benchmark |
18 | 18 | { |
19 | 19 | |
20 | - /** |
|
21 | - * array containing the start time for the timers |
|
22 | - */ |
|
23 | - private static $start_times; |
|
24 | - |
|
25 | - /** |
|
26 | - * array containing all the timer'd times, which can be outputted via show_times() |
|
27 | - */ |
|
28 | - private static $times = array(); |
|
29 | - |
|
30 | - /** |
|
31 | - * @var array |
|
32 | - */ |
|
33 | - protected static $memory_usage = array(); |
|
34 | - |
|
35 | - |
|
36 | - |
|
37 | - /** |
|
38 | - * whether to benchmark code or not |
|
39 | - */ |
|
40 | - public static function doNotRun() |
|
41 | - { |
|
42 | - return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX); |
|
43 | - } |
|
44 | - |
|
45 | - |
|
46 | - |
|
47 | - /** |
|
48 | - * resetTimes |
|
49 | - */ |
|
50 | - public static function resetTimes() |
|
51 | - { |
|
52 | - Benchmark::$times = array(); |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * Add Benchmark::startTimer() before a block of code you want to measure the performance of |
|
59 | - * |
|
60 | - * @param null $timer_name |
|
61 | - */ |
|
62 | - public static function startTimer($timer_name = null) |
|
63 | - { |
|
64 | - if (Benchmark::doNotRun()) { |
|
65 | - return; |
|
66 | - } |
|
67 | - $timer_name = $timer_name !== '' ? $timer_name : get_called_class(); |
|
68 | - Benchmark::$start_times[$timer_name] = microtime(true); |
|
69 | - } |
|
70 | - |
|
71 | - |
|
72 | - |
|
73 | - /** |
|
74 | - * Add Benchmark::stopTimer() after a block of code you want to measure the performance of |
|
75 | - * |
|
76 | - * @param string $timer_name |
|
77 | - */ |
|
78 | - public static function stopTimer($timer_name = '') |
|
79 | - { |
|
80 | - if (Benchmark::doNotRun()) { |
|
81 | - return; |
|
82 | - } |
|
83 | - $timer_name = $timer_name !== '' ? $timer_name : get_called_class(); |
|
84 | - if (isset(Benchmark::$start_times[$timer_name])) { |
|
85 | - $start_time = Benchmark::$start_times[$timer_name]; |
|
86 | - unset(Benchmark::$start_times[$timer_name]); |
|
87 | - } else { |
|
88 | - $start_time = array_pop(Benchmark::$start_times); |
|
89 | - } |
|
90 | - Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8); |
|
91 | - } |
|
92 | - |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * Measure the memory usage by PHP so far. |
|
97 | - * |
|
98 | - * @param string $label The label to show for this time eg "Start of calling Some_Class::some_function" |
|
99 | - * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called |
|
100 | - * @param bool $formatted |
|
101 | - * @return void |
|
102 | - */ |
|
103 | - public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true) |
|
104 | - { |
|
105 | - if (Benchmark::doNotRun()) { |
|
106 | - return; |
|
107 | - } |
|
108 | - $memory_used = Benchmark::convert(memory_get_usage(true)); |
|
109 | - Benchmark::$memory_usage[$label] = $memory_used; |
|
110 | - if ($output_now) { |
|
111 | - echo $formatted |
|
112 | - ? "<br>{$label} : {$memory_used}" |
|
113 | - : "\n {$label} : {$memory_used}"; |
|
114 | - } |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * will display the benchmarking results at shutdown |
|
121 | - * |
|
122 | - * @param bool $formatted |
|
123 | - * @return void |
|
124 | - */ |
|
125 | - public static function displayResultsAtShutdown($formatted = true) |
|
126 | - { |
|
127 | - add_action( |
|
128 | - 'shutdown', |
|
129 | - function () use ($formatted) { |
|
130 | - Benchmark::displayResults(true, $formatted); |
|
131 | - } |
|
132 | - ); |
|
133 | - } |
|
134 | - |
|
135 | - |
|
136 | - |
|
137 | - /** |
|
138 | - * will display the benchmarking results at shutdown |
|
139 | - * |
|
140 | - * @param string $filepath |
|
141 | - * @param bool $formatted |
|
142 | - * @param bool $append |
|
143 | - * @return void |
|
144 | - */ |
|
145 | - public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true) |
|
146 | - { |
|
147 | - add_action( |
|
148 | - 'shutdown', |
|
149 | - function () use ($filepath, $formatted, $append) { |
|
150 | - Benchmark::writeResultsToFile($filepath, $formatted, $append); |
|
151 | - } |
|
152 | - ); |
|
153 | - } |
|
154 | - |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * @param bool $formatted |
|
159 | - * @return string |
|
160 | - */ |
|
161 | - private static function generateResults($formatted = true) |
|
162 | - { |
|
163 | - if (Benchmark::doNotRun()) { |
|
164 | - return ''; |
|
165 | - } |
|
166 | - $output = ''; |
|
167 | - if (! empty(Benchmark::$times)) { |
|
168 | - $total = 0; |
|
169 | - $output .= $formatted |
|
170 | - ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />' |
|
171 | - : ''; |
|
172 | - foreach (Benchmark::$times as $timer_name => $total_time) { |
|
173 | - $output .= Benchmark::formatTime($timer_name, $total_time, $formatted); |
|
174 | - $output .= $formatted ? '<br />' : "\n"; |
|
175 | - $total += $total_time; |
|
176 | - } |
|
177 | - if($formatted) { |
|
178 | - $output .= '<br />'; |
|
179 | - $output .= '<h4>TOTAL TIME</h4>'; |
|
180 | - $output .= Benchmark::formatTime('', $total, $formatted); |
|
181 | - $output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />'; |
|
182 | - $output .= '<br />'; |
|
183 | - $output .= '<h5>Performance scale (from best to worse)</h5>'; |
|
184 | - $output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />'; |
|
185 | - $output .= '<span style="color:deepskyblue">Like...no way man!</span><br />'; |
|
186 | - $output .= '<span style="color:limegreen">Like...groovy!</span><br />'; |
|
187 | - $output .= '<span style="color:gold">Ruh Oh</span><br />'; |
|
188 | - $output .= '<span style="color:darkorange">Zoinks!</span><br />'; |
|
189 | - $output .= '<span style="color:red">Like...HEEELLLP</span><br />'; |
|
190 | - } |
|
191 | - } |
|
192 | - if (! empty(Benchmark::$memory_usage)) { |
|
193 | - $output .= $formatted |
|
194 | - ? '<h5>Memory</h5>' |
|
195 | - : "\nMemory"; |
|
196 | - foreach (Benchmark::$memory_usage as $label => $memory_usage) { |
|
197 | - $output .= $formatted |
|
198 | - ? '<br />' |
|
199 | - : "\n"; |
|
200 | - $output .= "{$memory_usage} : {$label}"; |
|
201 | - } |
|
202 | - } |
|
203 | - if (empty($output)) { |
|
204 | - return ''; |
|
205 | - } |
|
206 | - $output = $formatted |
|
207 | - ? '<div style="border:1px solid #dddddd; background-color:#ffffff;' |
|
208 | - . (is_admin() |
|
209 | - ? ' margin:2em 2em 2em 180px;' |
|
210 | - : ' margin:2em;') |
|
211 | - . ' padding:2em;">' |
|
212 | - . '<h4>BENCHMARKING</h4>' |
|
213 | - . $output |
|
214 | - . '</div>' |
|
215 | - : $output; |
|
216 | - return $output; |
|
217 | - } |
|
218 | - |
|
219 | - |
|
220 | - |
|
221 | - /** |
|
222 | - * @param bool $echo |
|
223 | - * @param bool $formatted |
|
224 | - * @return string |
|
225 | - */ |
|
226 | - public static function displayResults($echo = true, $formatted = true) |
|
227 | - { |
|
228 | - $results = Benchmark::generateResults($formatted); |
|
229 | - if ($echo) { |
|
230 | - echo $results; |
|
231 | - $results = ''; |
|
232 | - } |
|
233 | - return $results; |
|
234 | - } |
|
235 | - |
|
236 | - |
|
237 | - |
|
238 | - /** |
|
239 | - * @param string $filepath |
|
240 | - * @param bool $formatted |
|
241 | - * @param bool $append |
|
242 | - */ |
|
243 | - public static function writeResultsToFile($filepath = '', $formatted = true, $append = true) |
|
244 | - { |
|
245 | - $filepath = ! empty($filepath) && is_readable(dirname($filepath)) |
|
246 | - ? $filepath |
|
247 | - : ''; |
|
248 | - if( empty($filepath)) { |
|
249 | - $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html'; |
|
250 | - } |
|
251 | - file_put_contents( |
|
252 | - $filepath, |
|
253 | - "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted), |
|
254 | - $append ? FILE_APPEND | LOCK_EX : LOCK_EX |
|
255 | - ); |
|
256 | - } |
|
257 | - |
|
258 | - |
|
259 | - |
|
260 | - /** |
|
261 | - * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc) |
|
262 | - * |
|
263 | - * @param int $size |
|
264 | - * @return string |
|
265 | - */ |
|
266 | - public static function convert($size) |
|
267 | - { |
|
268 | - $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb'); |
|
269 | - return round( |
|
270 | - $size / pow(1024, $i = floor(log($size, 1024))), |
|
271 | - 2 |
|
272 | - ) . ' ' . $unit[absint($i)]; |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - |
|
277 | - /** |
|
278 | - * @param string $timer_name |
|
279 | - * @param float $total_time |
|
280 | - * @param bool $formatted |
|
281 | - * @return string |
|
282 | - */ |
|
283 | - public static function formatTime($timer_name, $total_time, $formatted = true) |
|
284 | - { |
|
285 | - $total_time *= 1000; |
|
286 | - switch ($total_time) { |
|
287 | - case $total_time > 12500 : |
|
288 | - $color = 'red'; |
|
289 | - $bold = 'bold'; |
|
290 | - break; |
|
291 | - case $total_time > 2500 : |
|
292 | - $color = 'darkorange'; |
|
293 | - $bold = 'bold'; |
|
294 | - break; |
|
295 | - case $total_time > 500 : |
|
296 | - $color = 'gold'; |
|
297 | - $bold = 'bold'; |
|
298 | - break; |
|
299 | - case $total_time > 100 : |
|
300 | - $color = 'limegreen'; |
|
301 | - $bold = 'normal'; |
|
302 | - break; |
|
303 | - case $total_time > 20 : |
|
304 | - $color = 'deepskyblue'; |
|
305 | - $bold = 'normal'; |
|
306 | - break; |
|
307 | - default : |
|
308 | - $color = 'mediumpurple'; |
|
309 | - $bold = 'normal'; |
|
310 | - break; |
|
311 | - } |
|
312 | - return $formatted |
|
313 | - ? '<span style="min-width: 10px; margin:0 1em; color:' |
|
314 | - . $color |
|
315 | - . '; font-weight:' |
|
316 | - . $bold |
|
317 | - . '; font-size:1.2em;">' |
|
318 | - . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT) |
|
319 | - . '</span> ' |
|
320 | - . $timer_name |
|
321 | - : str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT); |
|
322 | - } |
|
20 | + /** |
|
21 | + * array containing the start time for the timers |
|
22 | + */ |
|
23 | + private static $start_times; |
|
24 | + |
|
25 | + /** |
|
26 | + * array containing all the timer'd times, which can be outputted via show_times() |
|
27 | + */ |
|
28 | + private static $times = array(); |
|
29 | + |
|
30 | + /** |
|
31 | + * @var array |
|
32 | + */ |
|
33 | + protected static $memory_usage = array(); |
|
34 | + |
|
35 | + |
|
36 | + |
|
37 | + /** |
|
38 | + * whether to benchmark code or not |
|
39 | + */ |
|
40 | + public static function doNotRun() |
|
41 | + { |
|
42 | + return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX); |
|
43 | + } |
|
44 | + |
|
45 | + |
|
46 | + |
|
47 | + /** |
|
48 | + * resetTimes |
|
49 | + */ |
|
50 | + public static function resetTimes() |
|
51 | + { |
|
52 | + Benchmark::$times = array(); |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * Add Benchmark::startTimer() before a block of code you want to measure the performance of |
|
59 | + * |
|
60 | + * @param null $timer_name |
|
61 | + */ |
|
62 | + public static function startTimer($timer_name = null) |
|
63 | + { |
|
64 | + if (Benchmark::doNotRun()) { |
|
65 | + return; |
|
66 | + } |
|
67 | + $timer_name = $timer_name !== '' ? $timer_name : get_called_class(); |
|
68 | + Benchmark::$start_times[$timer_name] = microtime(true); |
|
69 | + } |
|
70 | + |
|
71 | + |
|
72 | + |
|
73 | + /** |
|
74 | + * Add Benchmark::stopTimer() after a block of code you want to measure the performance of |
|
75 | + * |
|
76 | + * @param string $timer_name |
|
77 | + */ |
|
78 | + public static function stopTimer($timer_name = '') |
|
79 | + { |
|
80 | + if (Benchmark::doNotRun()) { |
|
81 | + return; |
|
82 | + } |
|
83 | + $timer_name = $timer_name !== '' ? $timer_name : get_called_class(); |
|
84 | + if (isset(Benchmark::$start_times[$timer_name])) { |
|
85 | + $start_time = Benchmark::$start_times[$timer_name]; |
|
86 | + unset(Benchmark::$start_times[$timer_name]); |
|
87 | + } else { |
|
88 | + $start_time = array_pop(Benchmark::$start_times); |
|
89 | + } |
|
90 | + Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8); |
|
91 | + } |
|
92 | + |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * Measure the memory usage by PHP so far. |
|
97 | + * |
|
98 | + * @param string $label The label to show for this time eg "Start of calling Some_Class::some_function" |
|
99 | + * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called |
|
100 | + * @param bool $formatted |
|
101 | + * @return void |
|
102 | + */ |
|
103 | + public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true) |
|
104 | + { |
|
105 | + if (Benchmark::doNotRun()) { |
|
106 | + return; |
|
107 | + } |
|
108 | + $memory_used = Benchmark::convert(memory_get_usage(true)); |
|
109 | + Benchmark::$memory_usage[$label] = $memory_used; |
|
110 | + if ($output_now) { |
|
111 | + echo $formatted |
|
112 | + ? "<br>{$label} : {$memory_used}" |
|
113 | + : "\n {$label} : {$memory_used}"; |
|
114 | + } |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * will display the benchmarking results at shutdown |
|
121 | + * |
|
122 | + * @param bool $formatted |
|
123 | + * @return void |
|
124 | + */ |
|
125 | + public static function displayResultsAtShutdown($formatted = true) |
|
126 | + { |
|
127 | + add_action( |
|
128 | + 'shutdown', |
|
129 | + function () use ($formatted) { |
|
130 | + Benchmark::displayResults(true, $formatted); |
|
131 | + } |
|
132 | + ); |
|
133 | + } |
|
134 | + |
|
135 | + |
|
136 | + |
|
137 | + /** |
|
138 | + * will display the benchmarking results at shutdown |
|
139 | + * |
|
140 | + * @param string $filepath |
|
141 | + * @param bool $formatted |
|
142 | + * @param bool $append |
|
143 | + * @return void |
|
144 | + */ |
|
145 | + public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true) |
|
146 | + { |
|
147 | + add_action( |
|
148 | + 'shutdown', |
|
149 | + function () use ($filepath, $formatted, $append) { |
|
150 | + Benchmark::writeResultsToFile($filepath, $formatted, $append); |
|
151 | + } |
|
152 | + ); |
|
153 | + } |
|
154 | + |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * @param bool $formatted |
|
159 | + * @return string |
|
160 | + */ |
|
161 | + private static function generateResults($formatted = true) |
|
162 | + { |
|
163 | + if (Benchmark::doNotRun()) { |
|
164 | + return ''; |
|
165 | + } |
|
166 | + $output = ''; |
|
167 | + if (! empty(Benchmark::$times)) { |
|
168 | + $total = 0; |
|
169 | + $output .= $formatted |
|
170 | + ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />' |
|
171 | + : ''; |
|
172 | + foreach (Benchmark::$times as $timer_name => $total_time) { |
|
173 | + $output .= Benchmark::formatTime($timer_name, $total_time, $formatted); |
|
174 | + $output .= $formatted ? '<br />' : "\n"; |
|
175 | + $total += $total_time; |
|
176 | + } |
|
177 | + if($formatted) { |
|
178 | + $output .= '<br />'; |
|
179 | + $output .= '<h4>TOTAL TIME</h4>'; |
|
180 | + $output .= Benchmark::formatTime('', $total, $formatted); |
|
181 | + $output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />'; |
|
182 | + $output .= '<br />'; |
|
183 | + $output .= '<h5>Performance scale (from best to worse)</h5>'; |
|
184 | + $output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />'; |
|
185 | + $output .= '<span style="color:deepskyblue">Like...no way man!</span><br />'; |
|
186 | + $output .= '<span style="color:limegreen">Like...groovy!</span><br />'; |
|
187 | + $output .= '<span style="color:gold">Ruh Oh</span><br />'; |
|
188 | + $output .= '<span style="color:darkorange">Zoinks!</span><br />'; |
|
189 | + $output .= '<span style="color:red">Like...HEEELLLP</span><br />'; |
|
190 | + } |
|
191 | + } |
|
192 | + if (! empty(Benchmark::$memory_usage)) { |
|
193 | + $output .= $formatted |
|
194 | + ? '<h5>Memory</h5>' |
|
195 | + : "\nMemory"; |
|
196 | + foreach (Benchmark::$memory_usage as $label => $memory_usage) { |
|
197 | + $output .= $formatted |
|
198 | + ? '<br />' |
|
199 | + : "\n"; |
|
200 | + $output .= "{$memory_usage} : {$label}"; |
|
201 | + } |
|
202 | + } |
|
203 | + if (empty($output)) { |
|
204 | + return ''; |
|
205 | + } |
|
206 | + $output = $formatted |
|
207 | + ? '<div style="border:1px solid #dddddd; background-color:#ffffff;' |
|
208 | + . (is_admin() |
|
209 | + ? ' margin:2em 2em 2em 180px;' |
|
210 | + : ' margin:2em;') |
|
211 | + . ' padding:2em;">' |
|
212 | + . '<h4>BENCHMARKING</h4>' |
|
213 | + . $output |
|
214 | + . '</div>' |
|
215 | + : $output; |
|
216 | + return $output; |
|
217 | + } |
|
218 | + |
|
219 | + |
|
220 | + |
|
221 | + /** |
|
222 | + * @param bool $echo |
|
223 | + * @param bool $formatted |
|
224 | + * @return string |
|
225 | + */ |
|
226 | + public static function displayResults($echo = true, $formatted = true) |
|
227 | + { |
|
228 | + $results = Benchmark::generateResults($formatted); |
|
229 | + if ($echo) { |
|
230 | + echo $results; |
|
231 | + $results = ''; |
|
232 | + } |
|
233 | + return $results; |
|
234 | + } |
|
235 | + |
|
236 | + |
|
237 | + |
|
238 | + /** |
|
239 | + * @param string $filepath |
|
240 | + * @param bool $formatted |
|
241 | + * @param bool $append |
|
242 | + */ |
|
243 | + public static function writeResultsToFile($filepath = '', $formatted = true, $append = true) |
|
244 | + { |
|
245 | + $filepath = ! empty($filepath) && is_readable(dirname($filepath)) |
|
246 | + ? $filepath |
|
247 | + : ''; |
|
248 | + if( empty($filepath)) { |
|
249 | + $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html'; |
|
250 | + } |
|
251 | + file_put_contents( |
|
252 | + $filepath, |
|
253 | + "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted), |
|
254 | + $append ? FILE_APPEND | LOCK_EX : LOCK_EX |
|
255 | + ); |
|
256 | + } |
|
257 | + |
|
258 | + |
|
259 | + |
|
260 | + /** |
|
261 | + * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc) |
|
262 | + * |
|
263 | + * @param int $size |
|
264 | + * @return string |
|
265 | + */ |
|
266 | + public static function convert($size) |
|
267 | + { |
|
268 | + $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb'); |
|
269 | + return round( |
|
270 | + $size / pow(1024, $i = floor(log($size, 1024))), |
|
271 | + 2 |
|
272 | + ) . ' ' . $unit[absint($i)]; |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + |
|
277 | + /** |
|
278 | + * @param string $timer_name |
|
279 | + * @param float $total_time |
|
280 | + * @param bool $formatted |
|
281 | + * @return string |
|
282 | + */ |
|
283 | + public static function formatTime($timer_name, $total_time, $formatted = true) |
|
284 | + { |
|
285 | + $total_time *= 1000; |
|
286 | + switch ($total_time) { |
|
287 | + case $total_time > 12500 : |
|
288 | + $color = 'red'; |
|
289 | + $bold = 'bold'; |
|
290 | + break; |
|
291 | + case $total_time > 2500 : |
|
292 | + $color = 'darkorange'; |
|
293 | + $bold = 'bold'; |
|
294 | + break; |
|
295 | + case $total_time > 500 : |
|
296 | + $color = 'gold'; |
|
297 | + $bold = 'bold'; |
|
298 | + break; |
|
299 | + case $total_time > 100 : |
|
300 | + $color = 'limegreen'; |
|
301 | + $bold = 'normal'; |
|
302 | + break; |
|
303 | + case $total_time > 20 : |
|
304 | + $color = 'deepskyblue'; |
|
305 | + $bold = 'normal'; |
|
306 | + break; |
|
307 | + default : |
|
308 | + $color = 'mediumpurple'; |
|
309 | + $bold = 'normal'; |
|
310 | + break; |
|
311 | + } |
|
312 | + return $formatted |
|
313 | + ? '<span style="min-width: 10px; margin:0 1em; color:' |
|
314 | + . $color |
|
315 | + . '; font-weight:' |
|
316 | + . $bold |
|
317 | + . '; font-size:1.2em;">' |
|
318 | + . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT) |
|
319 | + . '</span> ' |
|
320 | + . $timer_name |
|
321 | + : str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT); |
|
322 | + } |
|
323 | 323 | |
324 | 324 | |
325 | 325 |
@@ -126,7 +126,7 @@ discard block |
||
126 | 126 | { |
127 | 127 | add_action( |
128 | 128 | 'shutdown', |
129 | - function () use ($formatted) { |
|
129 | + function() use ($formatted) { |
|
130 | 130 | Benchmark::displayResults(true, $formatted); |
131 | 131 | } |
132 | 132 | ); |
@@ -146,7 +146,7 @@ discard block |
||
146 | 146 | { |
147 | 147 | add_action( |
148 | 148 | 'shutdown', |
149 | - function () use ($filepath, $formatted, $append) { |
|
149 | + function() use ($filepath, $formatted, $append) { |
|
150 | 150 | Benchmark::writeResultsToFile($filepath, $formatted, $append); |
151 | 151 | } |
152 | 152 | ); |
@@ -164,17 +164,17 @@ discard block |
||
164 | 164 | return ''; |
165 | 165 | } |
166 | 166 | $output = ''; |
167 | - if (! empty(Benchmark::$times)) { |
|
167 | + if ( ! empty(Benchmark::$times)) { |
|
168 | 168 | $total = 0; |
169 | 169 | $output .= $formatted |
170 | 170 | ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />' |
171 | 171 | : ''; |
172 | 172 | foreach (Benchmark::$times as $timer_name => $total_time) { |
173 | 173 | $output .= Benchmark::formatTime($timer_name, $total_time, $formatted); |
174 | - $output .= $formatted ? '<br />' : "\n"; |
|
174 | + $output .= $formatted ? '<br />' : "\n"; |
|
175 | 175 | $total += $total_time; |
176 | 176 | } |
177 | - if($formatted) { |
|
177 | + if ($formatted) { |
|
178 | 178 | $output .= '<br />'; |
179 | 179 | $output .= '<h4>TOTAL TIME</h4>'; |
180 | 180 | $output .= Benchmark::formatTime('', $total, $formatted); |
@@ -189,7 +189,7 @@ discard block |
||
189 | 189 | $output .= '<span style="color:red">Like...HEEELLLP</span><br />'; |
190 | 190 | } |
191 | 191 | } |
192 | - if (! empty(Benchmark::$memory_usage)) { |
|
192 | + if ( ! empty(Benchmark::$memory_usage)) { |
|
193 | 193 | $output .= $formatted |
194 | 194 | ? '<h5>Memory</h5>' |
195 | 195 | : "\nMemory"; |
@@ -245,12 +245,12 @@ discard block |
||
245 | 245 | $filepath = ! empty($filepath) && is_readable(dirname($filepath)) |
246 | 246 | ? $filepath |
247 | 247 | : ''; |
248 | - if( empty($filepath)) { |
|
249 | - $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html'; |
|
248 | + if (empty($filepath)) { |
|
249 | + $filepath = EVENT_ESPRESSO_UPLOAD_DIR.'logs/benchmarking-'.date('Y-m-d').'.html'; |
|
250 | 250 | } |
251 | 251 | file_put_contents( |
252 | 252 | $filepath, |
253 | - "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted), |
|
253 | + "\n".date('Y-m-d H:i:s').Benchmark::generateResults($formatted), |
|
254 | 254 | $append ? FILE_APPEND | LOCK_EX : LOCK_EX |
255 | 255 | ); |
256 | 256 | } |
@@ -269,7 +269,7 @@ discard block |
||
269 | 269 | return round( |
270 | 270 | $size / pow(1024, $i = floor(log($size, 1024))), |
271 | 271 | 2 |
272 | - ) . ' ' . $unit[absint($i)]; |
|
272 | + ).' '.$unit[absint($i)]; |
|
273 | 273 | } |
274 | 274 | |
275 | 275 |
@@ -12,7 +12,7 @@ discard block |
||
12 | 12 | use RuntimeException; |
13 | 13 | |
14 | 14 | if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
15 | - exit('No direct script access allowed'); |
|
15 | + exit('No direct script access allowed'); |
|
16 | 16 | } |
17 | 17 | |
18 | 18 | |
@@ -30,145 +30,145 @@ discard block |
||
30 | 30 | { |
31 | 31 | |
32 | 32 | |
33 | - /** |
|
34 | - * @param EE_Registration $target_registration |
|
35 | - * @param EE_Registration $registration_to_copy |
|
36 | - * @return bool |
|
37 | - * @throws UnexpectedEntityException |
|
38 | - * @throws EntityNotFoundException |
|
39 | - * @throws RuntimeException |
|
40 | - * @throws EE_Error |
|
41 | - */ |
|
42 | - public function copyRegistrationDetails( |
|
43 | - EE_Registration $target_registration, |
|
44 | - EE_Registration $registration_to_copy |
|
45 | - ) { |
|
46 | - // copy attendee |
|
47 | - $target_registration->set_attendee_id($registration_to_copy->attendee_ID()); |
|
48 | - $target_registration->updateStatusBasedOnTotalPaid(false); |
|
49 | - $target_registration->save(); |
|
50 | - // get answers to previous reg questions |
|
51 | - $answers = $this->reindexAnswersByQuestionId($registration_to_copy->answers()); |
|
52 | - // get questions to new event reg form |
|
53 | - $new_event = $target_registration->event(); |
|
54 | - $question_groups = $new_event->question_groups( |
|
55 | - array( |
|
56 | - array( |
|
57 | - 'Event.EVT_ID' => $new_event->ID(), |
|
58 | - 'Event_Question_Group.EQG_primary' => $registration_to_copy->is_primary_registrant(), |
|
59 | - ), |
|
60 | - 'order_by' => array('QSG_order' => 'ASC'), |
|
61 | - ) |
|
62 | - ); |
|
63 | - foreach ($question_groups as $question_group) { |
|
64 | - if ($question_group instanceof \EE_Question_Group) { |
|
65 | - foreach ($question_group->questions() as $question) { |
|
66 | - if ($question instanceof EE_Question) { |
|
67 | - $this->generateNewAnswer( |
|
68 | - $question, |
|
69 | - $target_registration, |
|
70 | - $answers |
|
71 | - ); |
|
72 | - } |
|
73 | - } |
|
74 | - } |
|
75 | - } |
|
76 | - return true; |
|
77 | - } |
|
78 | - |
|
79 | - |
|
80 | - |
|
81 | - /** |
|
82 | - * @param EE_Answer[] $answers |
|
83 | - * @return array |
|
84 | - * @throws EE_Error |
|
85 | - */ |
|
86 | - protected function reindexAnswersByQuestionId(array $answers) |
|
87 | - { |
|
88 | - $reindexed_answers = array(); |
|
89 | - foreach ($answers as $answer) { |
|
90 | - if ($answer instanceof EE_Answer) { |
|
91 | - $reindexed_answers[ $answer->question_ID() ] = $answer->value(); |
|
92 | - } |
|
93 | - } |
|
94 | - return $reindexed_answers; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - |
|
99 | - /** |
|
100 | - * @param EE_Question $question |
|
101 | - * @param EE_Registration $registration |
|
102 | - * @param $previous_answers |
|
103 | - * @return EE_Answer |
|
104 | - * @throws UnexpectedEntityException |
|
105 | - * @throws EE_Error |
|
106 | - */ |
|
107 | - protected function generateNewAnswer( |
|
108 | - EE_Question $question, |
|
109 | - EE_Registration $registration, |
|
110 | - $previous_answers |
|
111 | - ) { |
|
112 | - $old_answer_value = isset($previous_answers[ $question->ID() ]) |
|
113 | - ? $previous_answers[ $question->ID() ] |
|
114 | - : ''; |
|
115 | - $new_answer = EE_Answer::new_instance( |
|
116 | - array( |
|
117 | - 'QST_ID' => $question->ID(), |
|
118 | - 'REG_ID' => $registration->ID(), |
|
119 | - 'ANS_value' => $old_answer_value, |
|
120 | - ) |
|
121 | - ); |
|
122 | - if ( ! $new_answer instanceof EE_Answer) { |
|
123 | - throw new UnexpectedEntityException($new_answer, 'EE_Answer'); |
|
124 | - } |
|
125 | - $new_answer->save(); |
|
126 | - return $new_answer; |
|
127 | - } |
|
128 | - |
|
129 | - |
|
130 | - |
|
131 | - /** |
|
132 | - * @param EE_Registration $target_registration |
|
133 | - * @param EE_Registration $registration_to_copy |
|
134 | - * @return bool |
|
135 | - * @throws RuntimeException |
|
136 | - * @throws UnexpectedEntityException |
|
137 | - * @throws EE_Error |
|
138 | - */ |
|
139 | - public function copyPaymentDetails( |
|
140 | - EE_Registration $target_registration, |
|
141 | - EE_Registration $registration_to_copy |
|
142 | - ) { |
|
143 | - $previous_payments = $registration_to_copy->registration_payments(); |
|
144 | - foreach ($previous_payments as $previous_payment) { |
|
145 | - if ( |
|
146 | - $previous_payment instanceof \EE_Registration_Payment |
|
147 | - && $previous_payment->payment() instanceof \EE_Payment |
|
148 | - && $previous_payment->payment()->is_approved() |
|
149 | - ) { |
|
150 | - $new_registration_payment = \EE_Registration_Payment::new_instance( |
|
151 | - array( |
|
152 | - 'REG_ID' => $target_registration->ID(), |
|
153 | - 'PAY_ID' => $previous_payment->ID(), |
|
154 | - 'RPY_amount' => $previous_payment->amount(), |
|
155 | - ) |
|
156 | - ); |
|
157 | - if ( ! $new_registration_payment instanceof \EE_Registration_Payment) { |
|
158 | - throw new UnexpectedEntityException($new_registration_payment, 'EE_Registration_Payment'); |
|
159 | - } |
|
160 | - $new_registration_payment->save(); |
|
161 | - $target_registration->set_paid($previous_payment->amount()); |
|
162 | - $target_registration->save(); |
|
163 | - // if new reg payment is good, then set old reg payment amount to zero |
|
164 | - $previous_payment->set_amount(0); |
|
165 | - $previous_payment->save(); |
|
166 | - $registration_to_copy->set_paid(0); |
|
167 | - $registration_to_copy->save(); |
|
168 | - } |
|
169 | - } |
|
170 | - return true; |
|
171 | - } |
|
33 | + /** |
|
34 | + * @param EE_Registration $target_registration |
|
35 | + * @param EE_Registration $registration_to_copy |
|
36 | + * @return bool |
|
37 | + * @throws UnexpectedEntityException |
|
38 | + * @throws EntityNotFoundException |
|
39 | + * @throws RuntimeException |
|
40 | + * @throws EE_Error |
|
41 | + */ |
|
42 | + public function copyRegistrationDetails( |
|
43 | + EE_Registration $target_registration, |
|
44 | + EE_Registration $registration_to_copy |
|
45 | + ) { |
|
46 | + // copy attendee |
|
47 | + $target_registration->set_attendee_id($registration_to_copy->attendee_ID()); |
|
48 | + $target_registration->updateStatusBasedOnTotalPaid(false); |
|
49 | + $target_registration->save(); |
|
50 | + // get answers to previous reg questions |
|
51 | + $answers = $this->reindexAnswersByQuestionId($registration_to_copy->answers()); |
|
52 | + // get questions to new event reg form |
|
53 | + $new_event = $target_registration->event(); |
|
54 | + $question_groups = $new_event->question_groups( |
|
55 | + array( |
|
56 | + array( |
|
57 | + 'Event.EVT_ID' => $new_event->ID(), |
|
58 | + 'Event_Question_Group.EQG_primary' => $registration_to_copy->is_primary_registrant(), |
|
59 | + ), |
|
60 | + 'order_by' => array('QSG_order' => 'ASC'), |
|
61 | + ) |
|
62 | + ); |
|
63 | + foreach ($question_groups as $question_group) { |
|
64 | + if ($question_group instanceof \EE_Question_Group) { |
|
65 | + foreach ($question_group->questions() as $question) { |
|
66 | + if ($question instanceof EE_Question) { |
|
67 | + $this->generateNewAnswer( |
|
68 | + $question, |
|
69 | + $target_registration, |
|
70 | + $answers |
|
71 | + ); |
|
72 | + } |
|
73 | + } |
|
74 | + } |
|
75 | + } |
|
76 | + return true; |
|
77 | + } |
|
78 | + |
|
79 | + |
|
80 | + |
|
81 | + /** |
|
82 | + * @param EE_Answer[] $answers |
|
83 | + * @return array |
|
84 | + * @throws EE_Error |
|
85 | + */ |
|
86 | + protected function reindexAnswersByQuestionId(array $answers) |
|
87 | + { |
|
88 | + $reindexed_answers = array(); |
|
89 | + foreach ($answers as $answer) { |
|
90 | + if ($answer instanceof EE_Answer) { |
|
91 | + $reindexed_answers[ $answer->question_ID() ] = $answer->value(); |
|
92 | + } |
|
93 | + } |
|
94 | + return $reindexed_answers; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + |
|
99 | + /** |
|
100 | + * @param EE_Question $question |
|
101 | + * @param EE_Registration $registration |
|
102 | + * @param $previous_answers |
|
103 | + * @return EE_Answer |
|
104 | + * @throws UnexpectedEntityException |
|
105 | + * @throws EE_Error |
|
106 | + */ |
|
107 | + protected function generateNewAnswer( |
|
108 | + EE_Question $question, |
|
109 | + EE_Registration $registration, |
|
110 | + $previous_answers |
|
111 | + ) { |
|
112 | + $old_answer_value = isset($previous_answers[ $question->ID() ]) |
|
113 | + ? $previous_answers[ $question->ID() ] |
|
114 | + : ''; |
|
115 | + $new_answer = EE_Answer::new_instance( |
|
116 | + array( |
|
117 | + 'QST_ID' => $question->ID(), |
|
118 | + 'REG_ID' => $registration->ID(), |
|
119 | + 'ANS_value' => $old_answer_value, |
|
120 | + ) |
|
121 | + ); |
|
122 | + if ( ! $new_answer instanceof EE_Answer) { |
|
123 | + throw new UnexpectedEntityException($new_answer, 'EE_Answer'); |
|
124 | + } |
|
125 | + $new_answer->save(); |
|
126 | + return $new_answer; |
|
127 | + } |
|
128 | + |
|
129 | + |
|
130 | + |
|
131 | + /** |
|
132 | + * @param EE_Registration $target_registration |
|
133 | + * @param EE_Registration $registration_to_copy |
|
134 | + * @return bool |
|
135 | + * @throws RuntimeException |
|
136 | + * @throws UnexpectedEntityException |
|
137 | + * @throws EE_Error |
|
138 | + */ |
|
139 | + public function copyPaymentDetails( |
|
140 | + EE_Registration $target_registration, |
|
141 | + EE_Registration $registration_to_copy |
|
142 | + ) { |
|
143 | + $previous_payments = $registration_to_copy->registration_payments(); |
|
144 | + foreach ($previous_payments as $previous_payment) { |
|
145 | + if ( |
|
146 | + $previous_payment instanceof \EE_Registration_Payment |
|
147 | + && $previous_payment->payment() instanceof \EE_Payment |
|
148 | + && $previous_payment->payment()->is_approved() |
|
149 | + ) { |
|
150 | + $new_registration_payment = \EE_Registration_Payment::new_instance( |
|
151 | + array( |
|
152 | + 'REG_ID' => $target_registration->ID(), |
|
153 | + 'PAY_ID' => $previous_payment->ID(), |
|
154 | + 'RPY_amount' => $previous_payment->amount(), |
|
155 | + ) |
|
156 | + ); |
|
157 | + if ( ! $new_registration_payment instanceof \EE_Registration_Payment) { |
|
158 | + throw new UnexpectedEntityException($new_registration_payment, 'EE_Registration_Payment'); |
|
159 | + } |
|
160 | + $new_registration_payment->save(); |
|
161 | + $target_registration->set_paid($previous_payment->amount()); |
|
162 | + $target_registration->save(); |
|
163 | + // if new reg payment is good, then set old reg payment amount to zero |
|
164 | + $previous_payment->set_amount(0); |
|
165 | + $previous_payment->save(); |
|
166 | + $registration_to_copy->set_paid(0); |
|
167 | + $registration_to_copy->save(); |
|
168 | + } |
|
169 | + } |
|
170 | + return true; |
|
171 | + } |
|
172 | 172 | |
173 | 173 | |
174 | 174 | } |
@@ -88,7 +88,7 @@ discard block |
||
88 | 88 | $reindexed_answers = array(); |
89 | 89 | foreach ($answers as $answer) { |
90 | 90 | if ($answer instanceof EE_Answer) { |
91 | - $reindexed_answers[ $answer->question_ID() ] = $answer->value(); |
|
91 | + $reindexed_answers[$answer->question_ID()] = $answer->value(); |
|
92 | 92 | } |
93 | 93 | } |
94 | 94 | return $reindexed_answers; |
@@ -109,8 +109,8 @@ discard block |
||
109 | 109 | EE_Registration $registration, |
110 | 110 | $previous_answers |
111 | 111 | ) { |
112 | - $old_answer_value = isset($previous_answers[ $question->ID() ]) |
|
113 | - ? $previous_answers[ $question->ID() ] |
|
112 | + $old_answer_value = isset($previous_answers[$question->ID()]) |
|
113 | + ? $previous_answers[$question->ID()] |
|
114 | 114 | : ''; |
115 | 115 | $new_answer = EE_Answer::new_instance( |
116 | 116 | array( |
@@ -459,7 +459,7 @@ discard block |
||
459 | 459 | * there's a single shared message template group among all the events. Otherwise it returns null. |
460 | 460 | * |
461 | 461 | * @param array $event_ids |
462 | - * @return EE_Message_Template_Group|null |
|
462 | + * @return null|EE_Base_Class |
|
463 | 463 | * @throws EE_Error |
464 | 464 | * @throws InvalidArgumentException |
465 | 465 | * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
@@ -495,7 +495,7 @@ discard block |
||
495 | 495 | /** |
496 | 496 | * Retrieves the global message template group for the current messenger and message type. |
497 | 497 | * |
498 | - * @return EE_Message_Template_Group|null |
|
498 | + * @return null|EE_Base_Class |
|
499 | 499 | * @throws EE_Error |
500 | 500 | * @throws InvalidArgumentException |
501 | 501 | * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
@@ -641,7 +641,7 @@ discard block |
||
641 | 641 | * @param EE_Messages_Addressee $recipient |
642 | 642 | * @param array $templates formatted array of templates used for parsing data. |
643 | 643 | * @param EE_Message_Template_Group $message_template_group |
644 | - * @return bool|EE_Message |
|
644 | + * @return EE_Message |
|
645 | 645 | * @throws EE_Error |
646 | 646 | */ |
647 | 647 | protected function _setup_message_object( |
@@ -13,970 +13,970 @@ |
||
13 | 13 | { |
14 | 14 | |
15 | 15 | |
16 | - /** |
|
17 | - * @type EE_Messages_Data_Handler_Collection |
|
18 | - */ |
|
19 | - protected $_data_handler_collection; |
|
20 | - |
|
21 | - /** |
|
22 | - * @type EE_Message_Template_Group_Collection |
|
23 | - */ |
|
24 | - protected $_template_collection; |
|
25 | - |
|
26 | - /** |
|
27 | - * This will hold the data handler for the current EE_Message being generated. |
|
28 | - * |
|
29 | - * @type EE_Messages_incoming_data |
|
30 | - */ |
|
31 | - protected $_current_data_handler; |
|
32 | - |
|
33 | - /** |
|
34 | - * This holds the EE_Messages_Queue that contains the messages to generate. |
|
35 | - * |
|
36 | - * @type EE_Messages_Queue |
|
37 | - */ |
|
38 | - protected $_generation_queue; |
|
39 | - |
|
40 | - /** |
|
41 | - * This holds the EE_Messages_Queue that will store the generated EE_Message objects. |
|
42 | - * |
|
43 | - * @type EE_Messages_Queue |
|
44 | - */ |
|
45 | - protected $_ready_queue; |
|
46 | - |
|
47 | - /** |
|
48 | - * This is a container for any error messages that get created through the generation |
|
49 | - * process. |
|
50 | - * |
|
51 | - * @type array |
|
52 | - */ |
|
53 | - protected $_error_msg = array(); |
|
54 | - |
|
55 | - /** |
|
56 | - * Flag used to set when the current EE_Message in the generation queue has been verified. |
|
57 | - * |
|
58 | - * @type bool |
|
59 | - */ |
|
60 | - protected $_verified = false; |
|
61 | - |
|
62 | - /** |
|
63 | - * This will hold the current messenger object corresponding with the current EE_Message in the generation queue. |
|
64 | - * |
|
65 | - * @type EE_messenger |
|
66 | - */ |
|
67 | - protected $_current_messenger; |
|
68 | - |
|
69 | - /** |
|
70 | - * This will hold the current message type object corresponding with the current EE_Message in the generation queue. |
|
71 | - * |
|
72 | - * @type EE_message_type |
|
73 | - */ |
|
74 | - protected $_current_message_type; |
|
75 | - |
|
76 | - /** |
|
77 | - * @type EEH_Parse_Shortcodes |
|
78 | - */ |
|
79 | - protected $_shortcode_parser; |
|
80 | - |
|
81 | - |
|
82 | - /** |
|
83 | - * @param EE_Messages_Queue $generation_queue |
|
84 | - * @param \EE_Messages_Queue $ready_queue |
|
85 | - * @param \EE_Messages_Data_Handler_Collection $data_handler_collection |
|
86 | - * @param \EE_Message_Template_Group_Collection $template_collection |
|
87 | - * @param \EEH_Parse_Shortcodes $shortcode_parser |
|
88 | - */ |
|
89 | - public function __construct( |
|
90 | - EE_Messages_Queue $generation_queue, |
|
91 | - EE_Messages_Queue $ready_queue, |
|
92 | - EE_Messages_Data_Handler_Collection $data_handler_collection, |
|
93 | - EE_Message_Template_Group_Collection $template_collection, |
|
94 | - EEH_Parse_Shortcodes $shortcode_parser |
|
95 | - ) { |
|
96 | - $this->_generation_queue = $generation_queue; |
|
97 | - $this->_ready_queue = $ready_queue; |
|
98 | - $this->_data_handler_collection = $data_handler_collection; |
|
99 | - $this->_template_collection = $template_collection; |
|
100 | - $this->_shortcode_parser = $shortcode_parser; |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @return EE_Messages_Queue |
|
106 | - */ |
|
107 | - public function generation_queue() |
|
108 | - { |
|
109 | - return $this->_generation_queue; |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * This iterates through the provided queue and generates the EE_Message objects. |
|
115 | - * When iterating through the queue, the queued item that served as the base for generating other EE_Message |
|
116 | - * objects gets removed and the new EE_Message objects get added to a NEW queue. The NEW queue is then returned |
|
117 | - * for the caller to decide what to do with it. |
|
118 | - * |
|
119 | - * @param bool $save Whether to save the EE_Message objects in the new queue or just return. |
|
120 | - * @return EE_Messages_Queue The new queue for holding generated EE_Message objects. |
|
121 | - * @throws EE_Error |
|
122 | - * @throws ReflectionException |
|
123 | - */ |
|
124 | - public function generate($save = true) |
|
125 | - { |
|
126 | - //iterate through the messages in the queue, generate, and add to new queue. |
|
127 | - $this->_generation_queue->get_message_repository()->rewind(); |
|
128 | - while ($this->_generation_queue->get_message_repository()->valid()) { |
|
129 | - //reset "current" properties |
|
130 | - $this->_reset_current_properties(); |
|
131 | - |
|
132 | - /** @type EE_Message $msg */ |
|
133 | - $msg = $this->_generation_queue->get_message_repository()->current(); |
|
134 | - |
|
135 | - /** |
|
136 | - * need to get the next object and capture it for setting manually after deletes. The reason is that when |
|
137 | - * an object is removed from the repo then valid for the next object will fail. |
|
138 | - */ |
|
139 | - $this->_generation_queue->get_message_repository()->next(); |
|
140 | - $next_msg = $this->_generation_queue->get_message_repository()->current(); |
|
141 | - //restore pointer to current item |
|
142 | - $this->_generation_queue->get_message_repository()->set_current($msg); |
|
143 | - |
|
144 | - //skip and delete if the current $msg is NOT incomplete (queued for generation) |
|
145 | - if ($msg->STS_ID() !== EEM_Message::status_incomplete) { |
|
146 | - //we keep this item in the db just remove from the repo. |
|
147 | - $this->_generation_queue->get_message_repository()->remove($msg); |
|
148 | - //next item |
|
149 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
150 | - continue; |
|
151 | - } |
|
152 | - |
|
153 | - if ($this->_verify()) { |
|
154 | - //let's get generating! |
|
155 | - $this->_generate(); |
|
156 | - } |
|
157 | - |
|
158 | - //don't persist debug_only messages if the messages system is not in debug mode. |
|
159 | - if ($msg->STS_ID() === EEM_Message::status_debug_only |
|
160 | - && ! EEM_Message::debug() |
|
161 | - ) { |
|
162 | - do_action( |
|
163 | - 'AHEE__EE_Messages_Generator__generate__before_debug_delete', |
|
164 | - $msg, |
|
165 | - $this->_error_msg, |
|
166 | - $this->_current_messenger, |
|
167 | - $this->_current_message_type, |
|
168 | - $this->_current_data_handler |
|
169 | - ); |
|
170 | - $this->_generation_queue->get_message_repository()->delete(); |
|
171 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
172 | - continue; |
|
173 | - } |
|
174 | - |
|
175 | - //if there are error messages then let's set the status and the error message. |
|
176 | - if ($this->_error_msg) { |
|
177 | - //if the status is already debug only, then let's leave it at that. |
|
178 | - if ($msg->STS_ID() !== EEM_Message::status_debug_only) { |
|
179 | - $msg->set_STS_ID(EEM_Message::status_failed); |
|
180 | - } |
|
181 | - do_action( |
|
182 | - 'AHEE__EE_Messages_Generator__generate__processing_failed_message', |
|
183 | - $msg, |
|
184 | - $this->_error_msg, |
|
185 | - $this->_current_messenger, |
|
186 | - $this->_current_message_type, |
|
187 | - $this->_current_data_handler |
|
188 | - ); |
|
189 | - $msg->set_error_message( |
|
190 | - esc_html__('Message failed to generate for the following reasons: ', 'event_espresso') |
|
191 | - . "\n" |
|
192 | - . implode("\n", $this->_error_msg) |
|
193 | - ); |
|
194 | - $msg->set_modified(time()); |
|
195 | - } else { |
|
196 | - do_action( |
|
197 | - 'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete', |
|
198 | - $msg, |
|
199 | - $this->_error_msg, |
|
200 | - $this->_current_messenger, |
|
201 | - $this->_current_message_type, |
|
202 | - $this->_current_data_handler |
|
203 | - ); |
|
204 | - //remove from db |
|
205 | - $this->_generation_queue->get_message_repository()->delete(); |
|
206 | - } |
|
207 | - //next item |
|
208 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
209 | - } |
|
210 | - |
|
211 | - //generation queue is ALWAYS saved to record any errors in the generation process. |
|
212 | - $this->_generation_queue->save(); |
|
213 | - |
|
214 | - /** |
|
215 | - * save _ready_queue if flag set. |
|
216 | - * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method. This |
|
217 | - * means if a field was added that is not a valid database column. The EE_Message was already saved to the db |
|
218 | - * so a EE_Extra_Meta entry could be created and attached to the EE_Message. In those cases the save flag is |
|
219 | - * irrelevant. |
|
220 | - */ |
|
221 | - if ($save) { |
|
222 | - $this->_ready_queue->save(); |
|
223 | - } |
|
224 | - |
|
225 | - //final reset of properties |
|
226 | - $this->_reset_current_properties(); |
|
227 | - |
|
228 | - return $this->_ready_queue; |
|
229 | - } |
|
230 | - |
|
231 | - |
|
232 | - /** |
|
233 | - * This resets all the properties used for holding "current" values corresponding to the current EE_Message object |
|
234 | - * in the generation queue. |
|
235 | - */ |
|
236 | - protected function _reset_current_properties() |
|
237 | - { |
|
238 | - $this->_verified = false; |
|
239 | - //make sure any _data value in the current message type is reset |
|
240 | - if ($this->_current_message_type instanceof EE_message_type) { |
|
241 | - $this->_current_message_type->reset_data(); |
|
242 | - } |
|
243 | - $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null; |
|
244 | - } |
|
245 | - |
|
246 | - |
|
247 | - /** |
|
248 | - * This proceeds with the actual generation of a message. By the time this is called, there should already be a |
|
249 | - * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the |
|
250 | - * _generating_queue. |
|
251 | - * |
|
252 | - * @return bool Whether the message was successfully generated or not. |
|
253 | - * @throws EE_Error |
|
254 | - * @throws InvalidArgumentException |
|
255 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
256 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
257 | - */ |
|
258 | - protected function _generate() |
|
259 | - { |
|
260 | - //double check verification has run and that everything is ready to work with (saves us having to validate |
|
261 | - // everything again). |
|
262 | - if (! $this->_verified) { |
|
263 | - return false; //get out because we don't have a valid setup to work with. |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - try { |
|
268 | - $addressees = $this->_current_message_type->get_addressees( |
|
269 | - $this->_current_data_handler, |
|
270 | - $this->_generation_queue->get_message_repository()->current()->context() |
|
271 | - ); |
|
272 | - } catch (EE_Error $e) { |
|
273 | - $this->_error_msg[] = $e->getMessage(); |
|
274 | - return false; |
|
275 | - } |
|
276 | - |
|
277 | - |
|
278 | - //if no addressees then get out because there is nothing to generation (possible bad data). |
|
279 | - if (! $this->_valid_addressees($addressees)) { |
|
280 | - do_action( |
|
281 | - 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
|
282 | - $this->_generation_queue->get_message_repository()->current(), |
|
283 | - $addressees, |
|
284 | - $this->_current_messenger, |
|
285 | - $this->_current_message_type, |
|
286 | - $this->_current_data_handler |
|
287 | - ); |
|
288 | - $this->_generation_queue->get_message_repository()->current()->set_STS_ID( |
|
289 | - EEM_Message::status_debug_only |
|
290 | - ); |
|
291 | - $this->_error_msg[] = esc_html__( |
|
292 | - 'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects. There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.', |
|
293 | - 'event_espresso' |
|
294 | - ); |
|
295 | - return false; |
|
296 | - } |
|
297 | - |
|
298 | - $message_template_group = $this->_get_message_template_group(); |
|
299 | - |
|
300 | - //in the unlikely event there is no EE_Message_Template_Group available, get out! |
|
301 | - if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
302 | - $this->_error_msg[] = esc_html__( |
|
303 | - 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
|
304 | - 'event_espresso' |
|
305 | - ); |
|
306 | - return false; |
|
307 | - } |
|
308 | - |
|
309 | - //get formatted templates for using to parse and setup EE_Message objects. |
|
310 | - $templates = $this->_get_templates($message_template_group); |
|
311 | - |
|
312 | - |
|
313 | - //setup new EE_Message objects (and add to _ready_queue) |
|
314 | - return $this->_assemble_messages($addressees, $templates, $message_template_group); |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * Retrieves the message template group being used for generating messages. |
|
320 | - * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times. |
|
321 | - * |
|
322 | - * @return EE_Message_Template_Group|null |
|
323 | - * @throws EE_Error |
|
324 | - * @throws InvalidArgumentException |
|
325 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
326 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
327 | - */ |
|
328 | - protected function _get_message_template_group() |
|
329 | - { |
|
330 | - //first see if there is a specific message template group requested (current message in the queue has a specific |
|
331 | - //GRP_ID |
|
332 | - $message_template_group = $this->_specific_message_template_group_from_queue(); |
|
333 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
334 | - return $message_template_group; |
|
335 | - } |
|
336 | - |
|
337 | - //get event_ids from the datahandler so we can check to see if there's already a message template group for them |
|
338 | - //in the collection. |
|
339 | - $event_ids = $this->_get_event_ids_from_current_data_handler(); |
|
340 | - $message_template_group = $this->_template_collection->get_by_key( |
|
341 | - $this->_template_collection->getKey( |
|
342 | - $this->_current_messenger->name, |
|
343 | - $this->_current_message_type->name, |
|
344 | - $event_ids |
|
345 | - ) |
|
346 | - ); |
|
347 | - |
|
348 | - //if we have a message template group then no need to hit the database, just return it. |
|
349 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
350 | - return $message_template_group; |
|
351 | - } |
|
352 | - |
|
353 | - //okay made it here, so let's get the global group first for this messenger and message type to ensure |
|
354 | - //there is no override set. |
|
355 | - $global_message_template_group = |
|
356 | - $this->_get_global_message_template_group_for_current_messenger_and_message_type(); |
|
357 | - |
|
358 | - if ($global_message_template_group instanceof EE_Message_Template_Group |
|
359 | - && $global_message_template_group->get('MTP_is_override') |
|
360 | - ) { |
|
361 | - return $global_message_template_group; |
|
362 | - } |
|
363 | - |
|
364 | - //if we're still here, that means there was no message template group for the events in the collection and |
|
365 | - //the global message template group for the messenger and message type is not set for override. So next step is |
|
366 | - //to see if there is a common shared custom message template group for this set of events. |
|
367 | - $message_template_group = $this->_get_shared_message_template_for_events($event_ids); |
|
368 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
369 | - return $message_template_group; |
|
370 | - } |
|
371 | - |
|
372 | - //STILL here? Okay that means the fallback is to just use the global message template group for this event set. |
|
373 | - //So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this request) |
|
374 | - //and return it. |
|
375 | - if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
376 | - $this->_template_collection->add( |
|
377 | - $global_message_template_group, |
|
378 | - $event_ids |
|
379 | - ); |
|
380 | - return $global_message_template_group; |
|
381 | - } |
|
382 | - |
|
383 | - //if we land here that means there's NO active message template group for this set. |
|
384 | - //TODO this will be a good target for some optimization down the road. Whenever there is no active message |
|
385 | - //template group for a given event set then cache that result so we don't repeat the logic. However, for now, |
|
386 | - //this should likely bit hit rarely enough that it's not a significant issue. |
|
387 | - return null; |
|
388 | - } |
|
389 | - |
|
390 | - |
|
391 | - /** |
|
392 | - * This checks the current message in the queue and determines if there is a specific Message Template Group |
|
393 | - * requested for that message. |
|
394 | - * |
|
395 | - * @return EE_Message_Template_Group|null |
|
396 | - * @throws EE_Error |
|
397 | - * @throws InvalidArgumentException |
|
398 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
399 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
400 | - */ |
|
401 | - protected function _specific_message_template_group_from_queue() |
|
402 | - { |
|
403 | - //is there a GRP_ID already on the EE_Message object? If there is, then a specific template has been requested |
|
404 | - //so let's use that. |
|
405 | - $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID(); |
|
406 | - |
|
407 | - if ($GRP_ID) { |
|
408 | - //attempt to retrieve from repo first |
|
409 | - $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
|
410 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
411 | - return $message_template_group; //got it! |
|
412 | - } |
|
413 | - |
|
414 | - //nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
|
415 | - //is not valid, so we'll continue on in the code assuming there's NO GRP_ID. |
|
416 | - $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID); |
|
417 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
418 | - $this->_template_collection->add($message_template_group); |
|
419 | - return $message_template_group; |
|
420 | - } |
|
421 | - } |
|
422 | - return null; |
|
423 | - } |
|
424 | - |
|
425 | - |
|
426 | - /** |
|
427 | - * Returns whether the event ids passed in all share the same message template group for the current message type |
|
428 | - * and messenger. |
|
429 | - * |
|
430 | - * @param array $event_ids |
|
431 | - * @return bool true means they DO share the same message template group, false means they don't. |
|
432 | - * @throws EE_Error |
|
433 | - * @throws InvalidArgumentException |
|
434 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
435 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
436 | - */ |
|
437 | - protected function _queue_shares_same_message_template_group_for_events(array $event_ids) |
|
438 | - { |
|
439 | - foreach ($this->_current_data_handler->events as $event) { |
|
440 | - $event_ids[$event['ID']] = $event['ID']; |
|
441 | - } |
|
442 | - $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count( |
|
443 | - array( |
|
444 | - array( |
|
445 | - 'Event.EVT_ID' => array('IN', $event_ids), |
|
446 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
447 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
448 | - ), |
|
449 | - ), |
|
450 | - 'GRP_ID', |
|
451 | - true |
|
452 | - ); |
|
453 | - return $count_of_message_template_groups === 1; |
|
454 | - } |
|
455 | - |
|
456 | - |
|
457 | - /** |
|
458 | - * This will get the shared message template group for events that are in the current data handler but ONLY if |
|
459 | - * there's a single shared message template group among all the events. Otherwise it returns null. |
|
460 | - * |
|
461 | - * @param array $event_ids |
|
462 | - * @return EE_Message_Template_Group|null |
|
463 | - * @throws EE_Error |
|
464 | - * @throws InvalidArgumentException |
|
465 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
466 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
467 | - */ |
|
468 | - protected function _get_shared_message_template_for_events(array $event_ids) |
|
469 | - { |
|
470 | - $message_template_group = null; |
|
471 | - if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) { |
|
472 | - $message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
473 | - array( |
|
474 | - array( |
|
475 | - 'Event.EVT_ID' => array('IN', $event_ids), |
|
476 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
477 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
478 | - 'MTP_is_active' => true, |
|
479 | - ), |
|
480 | - 'group_by' => 'GRP_ID', |
|
481 | - ) |
|
482 | - ); |
|
483 | - //store this in the collection if its valid |
|
484 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
485 | - $this->_template_collection->add( |
|
486 | - $message_template_group, |
|
487 | - $event_ids |
|
488 | - ); |
|
489 | - } |
|
490 | - } |
|
491 | - return $message_template_group; |
|
492 | - } |
|
493 | - |
|
494 | - |
|
495 | - /** |
|
496 | - * Retrieves the global message template group for the current messenger and message type. |
|
497 | - * |
|
498 | - * @return EE_Message_Template_Group|null |
|
499 | - * @throws EE_Error |
|
500 | - * @throws InvalidArgumentException |
|
501 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
502 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
503 | - */ |
|
504 | - protected function _get_global_message_template_group_for_current_messenger_and_message_type() |
|
505 | - { |
|
506 | - //first check the collection (we use an array with 0 in it to represent global groups). |
|
507 | - $global_message_template_group = $this->_template_collection->get_by_key( |
|
508 | - $this->_template_collection->getKey( |
|
509 | - $this->_current_messenger->name, |
|
510 | - $this->_current_message_type->name, |
|
511 | - array(0) |
|
512 | - ) |
|
513 | - ); |
|
514 | - |
|
515 | - //if we don't have a group lets hit the db. |
|
516 | - if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
517 | - $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
518 | - array( |
|
519 | - array( |
|
520 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
521 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
522 | - 'MTP_is_active' => true, |
|
523 | - 'MTP_is_global' => true, |
|
524 | - ), |
|
525 | - ) |
|
526 | - ); |
|
527 | - //if we have a group, add it to the collection. |
|
528 | - if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
529 | - $this->_template_collection->add( |
|
530 | - $global_message_template_group, |
|
531 | - array(0) |
|
532 | - ); |
|
533 | - } |
|
534 | - } |
|
535 | - return $global_message_template_group; |
|
536 | - } |
|
537 | - |
|
538 | - |
|
539 | - /** |
|
540 | - * Returns an array of event ids for all the events within the current data handler. |
|
541 | - * |
|
542 | - * @return array |
|
543 | - */ |
|
544 | - protected function _get_event_ids_from_current_data_handler() |
|
545 | - { |
|
546 | - $event_ids = array(); |
|
547 | - foreach ($this->_current_data_handler->events as $event) { |
|
548 | - $event_ids[$event['ID']] = $event['ID']; |
|
549 | - } |
|
550 | - return $event_ids; |
|
551 | - } |
|
552 | - |
|
553 | - |
|
554 | - /** |
|
555 | - * Retrieves formatted array of template information for each context specific to the given |
|
556 | - * EE_Message_Template_Group |
|
557 | - * |
|
558 | - * @param EE_Message_Template_Group $message_template_group |
|
559 | - * @return array The returned array is in this structure: |
|
560 | - * array( |
|
561 | - * 'field_name' => array( |
|
562 | - * 'context' => 'content' |
|
563 | - * ) |
|
564 | - * ) |
|
565 | - * @throws EE_Error |
|
566 | - */ |
|
567 | - protected function _get_templates(EE_Message_Template_Group $message_template_group) |
|
568 | - { |
|
569 | - $templates = array(); |
|
570 | - $context_templates = $message_template_group->context_templates(); |
|
571 | - foreach ($context_templates as $context => $template_fields) { |
|
572 | - foreach ($template_fields as $template_field => $template_obj) { |
|
573 | - if (! $template_obj instanceof EE_Message_Template) { |
|
574 | - continue; |
|
575 | - } |
|
576 | - $templates[$template_field][$context] = $template_obj->get('MTP_content'); |
|
577 | - } |
|
578 | - } |
|
579 | - return $templates; |
|
580 | - } |
|
581 | - |
|
582 | - |
|
583 | - /** |
|
584 | - * Assembles new fully generated EE_Message objects and adds to _ready_queue |
|
585 | - * |
|
586 | - * @param array $addressees Array of EE_Messages_Addressee objects indexed by message type |
|
587 | - * context. |
|
588 | - * @param array $templates formatted array of templates used for parsing data. |
|
589 | - * @param EE_Message_Template_Group $message_template_group |
|
590 | - * @return bool true if message generation went a-ok. false if some sort of exception occurred. Note: The |
|
591 | - * method will attempt to generate ALL EE_Message objects and add to |
|
592 | - * the _ready_queue. Successfully generated messages get added to the |
|
593 | - * queue with EEM_Message::status_idle, unsuccessfully generated |
|
594 | - * messages will get added to the queue as EEM_Message::status_failed. |
|
595 | - * Very rarely should "false" be returned from this method. |
|
596 | - * @throws EE_Error |
|
597 | - */ |
|
598 | - protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group) |
|
599 | - { |
|
600 | - |
|
601 | - //if templates are empty then get out because we can't generate anything. |
|
602 | - if (! $templates) { |
|
603 | - $this->_error_msg[] = esc_html__( |
|
604 | - 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
|
605 | - 'event_espresso' |
|
606 | - ); |
|
607 | - return false; |
|
608 | - } |
|
609 | - |
|
610 | - //We use this as the counter for generated messages because don't forget we may be executing this inside of a |
|
611 | - //generation_queue. So _ready_queue may have generated EE_Message objects already. |
|
612 | - $generated_count = 0; |
|
613 | - foreach ($addressees as $context => $recipients) { |
|
614 | - foreach ($recipients as $recipient) { |
|
615 | - $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group); |
|
616 | - if ($message instanceof EE_Message) { |
|
617 | - $this->_ready_queue->add( |
|
618 | - $message, |
|
619 | - array(), |
|
620 | - $this->_generation_queue->get_message_repository()->is_preview(), |
|
621 | - $this->_generation_queue->get_message_repository()->is_test_send() |
|
622 | - ); |
|
623 | - $generated_count++; |
|
624 | - } |
|
625 | - |
|
626 | - //if the current MSG being generated is for a test send then we'll only use ONE message in the |
|
627 | - // generation. |
|
628 | - if ($this->_generation_queue->get_message_repository()->is_test_send()) { |
|
629 | - break 2; |
|
630 | - } |
|
631 | - } |
|
632 | - } |
|
633 | - |
|
634 | - //if there are no generated messages then something else fatal went wrong. |
|
635 | - return $generated_count > 0; |
|
636 | - } |
|
637 | - |
|
638 | - |
|
639 | - /** |
|
640 | - * @param string $context The context for the generated message. |
|
641 | - * @param EE_Messages_Addressee $recipient |
|
642 | - * @param array $templates formatted array of templates used for parsing data. |
|
643 | - * @param EE_Message_Template_Group $message_template_group |
|
644 | - * @return bool|EE_Message |
|
645 | - * @throws EE_Error |
|
646 | - */ |
|
647 | - protected function _setup_message_object( |
|
648 | - $context, |
|
649 | - EE_Messages_Addressee $recipient, |
|
650 | - $templates, |
|
651 | - EE_Message_Template_Group $message_template_group |
|
652 | - ) { |
|
653 | - //stuff we already know |
|
654 | - $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0; |
|
655 | - $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction |
|
656 | - ? $this->_current_data_handler->txn->ID() |
|
657 | - : $transaction_id; |
|
658 | - $message_fields = array( |
|
659 | - 'GRP_ID' => $message_template_group->ID(), |
|
660 | - 'TXN_ID' => $transaction_id, |
|
661 | - 'MSG_messenger' => $this->_current_messenger->name, |
|
662 | - 'MSG_message_type' => $this->_current_message_type->name, |
|
663 | - 'MSG_context' => $context, |
|
664 | - ); |
|
665 | - |
|
666 | - //recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab |
|
667 | - // the info from the att_obj found in the EE_Messages_Addressee object. |
|
668 | - if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) { |
|
669 | - $message_fields['MSG_recipient_ID'] = $recipient->att_obj instanceof EE_Attendee |
|
670 | - ? $recipient->att_obj->ID() |
|
671 | - : 0; |
|
672 | - $message_fields['MSG_recipient_type'] = 'Attendee'; |
|
673 | - } else { |
|
674 | - $message_fields['MSG_recipient_ID'] = $recipient->recipient_id; |
|
675 | - $message_fields['MSG_recipient_type'] = $recipient->recipient_type; |
|
676 | - } |
|
677 | - $message = EE_Message_Factory::create($message_fields); |
|
678 | - |
|
679 | - //grab valid shortcodes for shortcode parser |
|
680 | - $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes(); |
|
681 | - $m_shortcodes = $this->_current_messenger->get_valid_shortcodes(); |
|
682 | - |
|
683 | - //if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing |
|
684 | - if (( |
|
685 | - ( |
|
686 | - empty($templates['to'][$context]) |
|
687 | - && ! $this->_current_messenger->allow_empty_to_field() |
|
688 | - ) |
|
689 | - || ! $message_template_group->is_context_active($context) |
|
690 | - ) |
|
691 | - && ! $this->_generation_queue->get_message_repository()->is_preview() |
|
692 | - ) { |
|
693 | - //we silently exit here and do NOT record a fail because the message is "turned off" by having no "to" |
|
694 | - //field. |
|
695 | - return false; |
|
696 | - } |
|
697 | - $error_msg = array(); |
|
698 | - foreach ($templates as $field => $field_context) { |
|
699 | - $error_msg = array(); |
|
700 | - //let's setup the valid shortcodes for the incoming context. |
|
701 | - $valid_shortcodes = $mt_shortcodes[$context]; |
|
702 | - //merge in valid shortcodes for the field. |
|
703 | - $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes; |
|
704 | - if (isset($templates[$field][$context])) { |
|
705 | - //prefix field. |
|
706 | - $column_name = 'MSG_' . $field; |
|
707 | - try { |
|
708 | - $content = $this->_shortcode_parser->parse_message_template( |
|
709 | - $templates[$field][$context], |
|
710 | - $recipient, |
|
711 | - $shortcodes, |
|
712 | - $this->_current_message_type, |
|
713 | - $this->_current_messenger, |
|
714 | - $message |
|
715 | - ); |
|
716 | - $message->set_field_or_extra_meta($column_name, $content); |
|
717 | - } catch (EE_Error $e) { |
|
718 | - $error_msg[] = sprintf( |
|
719 | - esc_html__( |
|
720 | - 'There was a problem generating the content for the field %s: %s', |
|
721 | - 'event_espresso' |
|
722 | - ), |
|
723 | - $field, |
|
724 | - $e->getMessage() |
|
725 | - ); |
|
726 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
727 | - } |
|
728 | - } |
|
729 | - } |
|
730 | - |
|
731 | - if ($message->STS_ID() === EEM_Message::status_failed) { |
|
732 | - $error_msg = esc_html__('There were problems generating this message:', 'event_espresso') |
|
733 | - . "\n" |
|
734 | - . implode("\n", $error_msg); |
|
735 | - $message->set_error_message($error_msg); |
|
736 | - } else { |
|
737 | - $message->set_STS_ID(EEM_Message::status_idle); |
|
738 | - } |
|
739 | - return $message; |
|
740 | - } |
|
741 | - |
|
742 | - |
|
743 | - /** |
|
744 | - * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate |
|
745 | - * error message if either is missing. |
|
746 | - * |
|
747 | - * @return bool true means there were no errors, false means there were errors. |
|
748 | - * @throws EE_Error |
|
749 | - * @throws ReflectionException |
|
750 | - */ |
|
751 | - protected function _verify() |
|
752 | - { |
|
753 | - //reset error message to an empty array. |
|
754 | - $this->_error_msg = array(); |
|
755 | - $valid = true; |
|
756 | - $valid = $valid ? $this->_validate_messenger_and_message_type() : $valid; |
|
757 | - $valid = $valid ? $this->_validate_and_setup_data() : $valid; |
|
758 | - |
|
759 | - //set the verified flag so we know everything has been validated. |
|
760 | - $this->_verified = $valid; |
|
761 | - |
|
762 | - return $valid; |
|
763 | - } |
|
764 | - |
|
765 | - |
|
766 | - /** |
|
767 | - * This accepts an array and validates that it is an array indexed by context with each value being an array of |
|
768 | - * EE_Messages_Addressee objects. |
|
769 | - * |
|
770 | - * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[] |
|
771 | - * @return bool |
|
772 | - */ |
|
773 | - protected function _valid_addressees($addressees) |
|
774 | - { |
|
775 | - if (! $addressees || ! is_array($addressees)) { |
|
776 | - return false; |
|
777 | - } |
|
778 | - |
|
779 | - foreach ($addressees as $addressee_array) { |
|
780 | - foreach ($addressee_array as $addressee) { |
|
781 | - if (! $addressee instanceof EE_Messages_Addressee) { |
|
782 | - return false; |
|
783 | - } |
|
784 | - } |
|
785 | - } |
|
786 | - return true; |
|
787 | - } |
|
788 | - |
|
789 | - |
|
790 | - /** |
|
791 | - * This validates the messenger, message type, and presences of generation data for the current EE_Message in the |
|
792 | - * queue. This process sets error messages if something is wrong. |
|
793 | - * |
|
794 | - * @return bool true is if there are no errors. false is if there is. |
|
795 | - */ |
|
796 | - protected function _validate_messenger_and_message_type() |
|
797 | - { |
|
798 | - |
|
799 | - //first are there any existing error messages? If so then return. |
|
800 | - if ($this->_error_msg) { |
|
801 | - return false; |
|
802 | - } |
|
803 | - /** @type EE_Message $message */ |
|
804 | - $message = $this->_generation_queue->get_message_repository()->current(); |
|
805 | - try { |
|
806 | - $this->_current_messenger = $message->valid_messenger(true) |
|
807 | - ? $message->messenger_object() |
|
808 | - : null; |
|
809 | - } catch (Exception $e) { |
|
810 | - $this->_error_msg[] = $e->getMessage(); |
|
811 | - } |
|
812 | - try { |
|
813 | - $this->_current_message_type = $message->valid_message_type(true) |
|
814 | - ? $message->message_type_object() |
|
815 | - : null; |
|
816 | - } catch (Exception $e) { |
|
817 | - $this->_error_msg[] = $e->getMessage(); |
|
818 | - } |
|
819 | - |
|
820 | - /** |
|
821 | - * Check if there is any generation data, but only if this is not for a preview. |
|
822 | - */ |
|
823 | - if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
824 | - && ( |
|
825 | - ! $this->_generation_queue->get_message_repository()->is_preview() |
|
826 | - && $this->_generation_queue->get_message_repository()->get_data_handler() |
|
827 | - !== 'EE_Messages_Preview_incoming_data' |
|
828 | - ) |
|
829 | - ) { |
|
830 | - $this->_error_msg[] = esc_html__( |
|
831 | - 'There is no generation data for this message. Unable to generate.', |
|
832 | - 'event_espresso' |
|
833 | - ); |
|
834 | - } |
|
835 | - |
|
836 | - return empty($this->_error_msg); |
|
837 | - } |
|
838 | - |
|
839 | - |
|
840 | - /** |
|
841 | - * This method retrieves the expected data handler for the message type and validates the generation data for that |
|
842 | - * data handler. |
|
843 | - * |
|
844 | - * @return bool true means there are no errors. false means there were errors (and handler did not get setup). |
|
845 | - * @throws EE_Error |
|
846 | - * @throws ReflectionException |
|
847 | - */ |
|
848 | - protected function _validate_and_setup_data() |
|
849 | - { |
|
850 | - |
|
851 | - //First, are there any existing error messages? If so, return because if there were errors elsewhere this can't |
|
852 | - //be used anyways. |
|
853 | - if ($this->_error_msg) { |
|
854 | - return false; |
|
855 | - } |
|
856 | - |
|
857 | - $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data(); |
|
858 | - |
|
859 | - /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
|
860 | - $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
|
861 | - ? $this->_generation_queue->get_message_repository()->get_data_handler() |
|
862 | - : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
863 | - |
|
864 | - //If this EE_Message is for a preview, then let's switch out to the preview data handler. |
|
865 | - if ($this->_generation_queue->get_message_repository()->is_preview()) { |
|
866 | - $data_handler_class_name = 'EE_Messages_Preview_incoming_data'; |
|
867 | - } |
|
868 | - |
|
869 | - //First get the class name for the data handler (and also verifies it exists. |
|
870 | - if (! class_exists($data_handler_class_name)) { |
|
871 | - $this->_error_msg[] = sprintf( |
|
872 | - esc_html__( |
|
873 | - 'The included data handler class name does not match any valid, accessible, "%1$s" classes. Looking for %2$s.', |
|
874 | - 'event_espresso' |
|
875 | - ), |
|
876 | - 'EE_Messages_incoming_data', |
|
877 | - $data_handler_class_name |
|
878 | - ); |
|
879 | - return false; |
|
880 | - } |
|
881 | - |
|
882 | - //convert generation_data for data_handler_instantiation. |
|
883 | - $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data); |
|
884 | - |
|
885 | - //note, this may set error messages as well. |
|
886 | - $this->_set_data_handler($generation_data, $data_handler_class_name); |
|
887 | - |
|
888 | - return empty($this->_error_msg); |
|
889 | - } |
|
890 | - |
|
891 | - |
|
892 | - /** |
|
893 | - * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and |
|
894 | - * adds it to the _data repository. |
|
895 | - * |
|
896 | - * @param mixed $generating_data This is data expected by the instantiated data handler. |
|
897 | - * @param string $data_handler_class_name This is the reference string indicating what data handler is being |
|
898 | - * instantiated. |
|
899 | - * @return void . |
|
900 | - * @throws EE_Error |
|
901 | - * @throws ReflectionException |
|
902 | - */ |
|
903 | - protected function _set_data_handler($generating_data, $data_handler_class_name) |
|
904 | - { |
|
905 | - //valid classname for the data handler. Now let's setup the key for the data handler repository to see if there |
|
906 | - //is already a ready data handler in the repository. |
|
907 | - $this->_current_data_handler = $this->_data_handler_collection->get_by_key( |
|
908 | - $this->_data_handler_collection->get_key( |
|
909 | - $data_handler_class_name, |
|
910 | - $generating_data |
|
911 | - ) |
|
912 | - ); |
|
913 | - if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
914 | - //no saved data_handler in the repo so let's set one up and add it to the repo. |
|
915 | - try { |
|
916 | - $this->_current_data_handler = new $data_handler_class_name($generating_data); |
|
917 | - $this->_data_handler_collection->add($this->_current_data_handler, $generating_data); |
|
918 | - } catch (EE_Error $e) { |
|
919 | - $this->_error_msg[] = $e->get_error(); |
|
920 | - } |
|
921 | - } |
|
922 | - } |
|
923 | - |
|
924 | - |
|
925 | - /** |
|
926 | - * The queued EE_Message for generation does not save the data used for generation as objects |
|
927 | - * because serialization of those objects could be problematic if the data is saved to the db. |
|
928 | - * So this method calls the static method on the associated data_handler for the given message_type |
|
929 | - * and that preps the data for later instantiation when generating. |
|
930 | - * |
|
931 | - * @param EE_Message_To_Generate $message_to_generate |
|
932 | - * @param bool $preview Indicate whether this is being used for a preview or not. |
|
933 | - * @return mixed Prepped data for persisting to the queue. false is returned if unable to prep data. |
|
934 | - */ |
|
935 | - protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview) |
|
936 | - { |
|
937 | - /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
|
938 | - $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
|
939 | - if (! $message_to_generate->valid()) { |
|
940 | - return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
|
941 | - } |
|
942 | - return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
|
943 | - } |
|
944 | - |
|
945 | - |
|
946 | - /** |
|
947 | - * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue. |
|
948 | - * |
|
949 | - * @param EE_Message_To_Generate $message_to_generate |
|
950 | - * @param bool $test_send Whether this is just a test send or not. Typically used for previews. |
|
951 | - * @throws InvalidArgumentException |
|
952 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
953 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
954 | - */ |
|
955 | - public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false) |
|
956 | - { |
|
957 | - //prep data |
|
958 | - $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview()); |
|
959 | - |
|
960 | - $message = $message_to_generate->get_EE_Message(); |
|
961 | - |
|
962 | - //is there a GRP_ID in the request? |
|
963 | - if ($GRP_ID = EE_Registry::instance()->REQ->get('GRP_ID')) { |
|
964 | - $message->set_GRP_ID($GRP_ID); |
|
965 | - } |
|
966 | - |
|
967 | - if ($data === false) { |
|
968 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
969 | - $message->set_error_message( |
|
970 | - esc_html__( |
|
971 | - 'Unable to prepare data for persistence to the database.', |
|
972 | - 'event_espresso' |
|
973 | - ) |
|
974 | - ); |
|
975 | - } else { |
|
976 | - //make sure that the data handler is cached on the message as well |
|
977 | - $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name(); |
|
978 | - } |
|
979 | - |
|
980 | - $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send); |
|
981 | - } |
|
16 | + /** |
|
17 | + * @type EE_Messages_Data_Handler_Collection |
|
18 | + */ |
|
19 | + protected $_data_handler_collection; |
|
20 | + |
|
21 | + /** |
|
22 | + * @type EE_Message_Template_Group_Collection |
|
23 | + */ |
|
24 | + protected $_template_collection; |
|
25 | + |
|
26 | + /** |
|
27 | + * This will hold the data handler for the current EE_Message being generated. |
|
28 | + * |
|
29 | + * @type EE_Messages_incoming_data |
|
30 | + */ |
|
31 | + protected $_current_data_handler; |
|
32 | + |
|
33 | + /** |
|
34 | + * This holds the EE_Messages_Queue that contains the messages to generate. |
|
35 | + * |
|
36 | + * @type EE_Messages_Queue |
|
37 | + */ |
|
38 | + protected $_generation_queue; |
|
39 | + |
|
40 | + /** |
|
41 | + * This holds the EE_Messages_Queue that will store the generated EE_Message objects. |
|
42 | + * |
|
43 | + * @type EE_Messages_Queue |
|
44 | + */ |
|
45 | + protected $_ready_queue; |
|
46 | + |
|
47 | + /** |
|
48 | + * This is a container for any error messages that get created through the generation |
|
49 | + * process. |
|
50 | + * |
|
51 | + * @type array |
|
52 | + */ |
|
53 | + protected $_error_msg = array(); |
|
54 | + |
|
55 | + /** |
|
56 | + * Flag used to set when the current EE_Message in the generation queue has been verified. |
|
57 | + * |
|
58 | + * @type bool |
|
59 | + */ |
|
60 | + protected $_verified = false; |
|
61 | + |
|
62 | + /** |
|
63 | + * This will hold the current messenger object corresponding with the current EE_Message in the generation queue. |
|
64 | + * |
|
65 | + * @type EE_messenger |
|
66 | + */ |
|
67 | + protected $_current_messenger; |
|
68 | + |
|
69 | + /** |
|
70 | + * This will hold the current message type object corresponding with the current EE_Message in the generation queue. |
|
71 | + * |
|
72 | + * @type EE_message_type |
|
73 | + */ |
|
74 | + protected $_current_message_type; |
|
75 | + |
|
76 | + /** |
|
77 | + * @type EEH_Parse_Shortcodes |
|
78 | + */ |
|
79 | + protected $_shortcode_parser; |
|
80 | + |
|
81 | + |
|
82 | + /** |
|
83 | + * @param EE_Messages_Queue $generation_queue |
|
84 | + * @param \EE_Messages_Queue $ready_queue |
|
85 | + * @param \EE_Messages_Data_Handler_Collection $data_handler_collection |
|
86 | + * @param \EE_Message_Template_Group_Collection $template_collection |
|
87 | + * @param \EEH_Parse_Shortcodes $shortcode_parser |
|
88 | + */ |
|
89 | + public function __construct( |
|
90 | + EE_Messages_Queue $generation_queue, |
|
91 | + EE_Messages_Queue $ready_queue, |
|
92 | + EE_Messages_Data_Handler_Collection $data_handler_collection, |
|
93 | + EE_Message_Template_Group_Collection $template_collection, |
|
94 | + EEH_Parse_Shortcodes $shortcode_parser |
|
95 | + ) { |
|
96 | + $this->_generation_queue = $generation_queue; |
|
97 | + $this->_ready_queue = $ready_queue; |
|
98 | + $this->_data_handler_collection = $data_handler_collection; |
|
99 | + $this->_template_collection = $template_collection; |
|
100 | + $this->_shortcode_parser = $shortcode_parser; |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @return EE_Messages_Queue |
|
106 | + */ |
|
107 | + public function generation_queue() |
|
108 | + { |
|
109 | + return $this->_generation_queue; |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * This iterates through the provided queue and generates the EE_Message objects. |
|
115 | + * When iterating through the queue, the queued item that served as the base for generating other EE_Message |
|
116 | + * objects gets removed and the new EE_Message objects get added to a NEW queue. The NEW queue is then returned |
|
117 | + * for the caller to decide what to do with it. |
|
118 | + * |
|
119 | + * @param bool $save Whether to save the EE_Message objects in the new queue or just return. |
|
120 | + * @return EE_Messages_Queue The new queue for holding generated EE_Message objects. |
|
121 | + * @throws EE_Error |
|
122 | + * @throws ReflectionException |
|
123 | + */ |
|
124 | + public function generate($save = true) |
|
125 | + { |
|
126 | + //iterate through the messages in the queue, generate, and add to new queue. |
|
127 | + $this->_generation_queue->get_message_repository()->rewind(); |
|
128 | + while ($this->_generation_queue->get_message_repository()->valid()) { |
|
129 | + //reset "current" properties |
|
130 | + $this->_reset_current_properties(); |
|
131 | + |
|
132 | + /** @type EE_Message $msg */ |
|
133 | + $msg = $this->_generation_queue->get_message_repository()->current(); |
|
134 | + |
|
135 | + /** |
|
136 | + * need to get the next object and capture it for setting manually after deletes. The reason is that when |
|
137 | + * an object is removed from the repo then valid for the next object will fail. |
|
138 | + */ |
|
139 | + $this->_generation_queue->get_message_repository()->next(); |
|
140 | + $next_msg = $this->_generation_queue->get_message_repository()->current(); |
|
141 | + //restore pointer to current item |
|
142 | + $this->_generation_queue->get_message_repository()->set_current($msg); |
|
143 | + |
|
144 | + //skip and delete if the current $msg is NOT incomplete (queued for generation) |
|
145 | + if ($msg->STS_ID() !== EEM_Message::status_incomplete) { |
|
146 | + //we keep this item in the db just remove from the repo. |
|
147 | + $this->_generation_queue->get_message_repository()->remove($msg); |
|
148 | + //next item |
|
149 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
150 | + continue; |
|
151 | + } |
|
152 | + |
|
153 | + if ($this->_verify()) { |
|
154 | + //let's get generating! |
|
155 | + $this->_generate(); |
|
156 | + } |
|
157 | + |
|
158 | + //don't persist debug_only messages if the messages system is not in debug mode. |
|
159 | + if ($msg->STS_ID() === EEM_Message::status_debug_only |
|
160 | + && ! EEM_Message::debug() |
|
161 | + ) { |
|
162 | + do_action( |
|
163 | + 'AHEE__EE_Messages_Generator__generate__before_debug_delete', |
|
164 | + $msg, |
|
165 | + $this->_error_msg, |
|
166 | + $this->_current_messenger, |
|
167 | + $this->_current_message_type, |
|
168 | + $this->_current_data_handler |
|
169 | + ); |
|
170 | + $this->_generation_queue->get_message_repository()->delete(); |
|
171 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
172 | + continue; |
|
173 | + } |
|
174 | + |
|
175 | + //if there are error messages then let's set the status and the error message. |
|
176 | + if ($this->_error_msg) { |
|
177 | + //if the status is already debug only, then let's leave it at that. |
|
178 | + if ($msg->STS_ID() !== EEM_Message::status_debug_only) { |
|
179 | + $msg->set_STS_ID(EEM_Message::status_failed); |
|
180 | + } |
|
181 | + do_action( |
|
182 | + 'AHEE__EE_Messages_Generator__generate__processing_failed_message', |
|
183 | + $msg, |
|
184 | + $this->_error_msg, |
|
185 | + $this->_current_messenger, |
|
186 | + $this->_current_message_type, |
|
187 | + $this->_current_data_handler |
|
188 | + ); |
|
189 | + $msg->set_error_message( |
|
190 | + esc_html__('Message failed to generate for the following reasons: ', 'event_espresso') |
|
191 | + . "\n" |
|
192 | + . implode("\n", $this->_error_msg) |
|
193 | + ); |
|
194 | + $msg->set_modified(time()); |
|
195 | + } else { |
|
196 | + do_action( |
|
197 | + 'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete', |
|
198 | + $msg, |
|
199 | + $this->_error_msg, |
|
200 | + $this->_current_messenger, |
|
201 | + $this->_current_message_type, |
|
202 | + $this->_current_data_handler |
|
203 | + ); |
|
204 | + //remove from db |
|
205 | + $this->_generation_queue->get_message_repository()->delete(); |
|
206 | + } |
|
207 | + //next item |
|
208 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
209 | + } |
|
210 | + |
|
211 | + //generation queue is ALWAYS saved to record any errors in the generation process. |
|
212 | + $this->_generation_queue->save(); |
|
213 | + |
|
214 | + /** |
|
215 | + * save _ready_queue if flag set. |
|
216 | + * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method. This |
|
217 | + * means if a field was added that is not a valid database column. The EE_Message was already saved to the db |
|
218 | + * so a EE_Extra_Meta entry could be created and attached to the EE_Message. In those cases the save flag is |
|
219 | + * irrelevant. |
|
220 | + */ |
|
221 | + if ($save) { |
|
222 | + $this->_ready_queue->save(); |
|
223 | + } |
|
224 | + |
|
225 | + //final reset of properties |
|
226 | + $this->_reset_current_properties(); |
|
227 | + |
|
228 | + return $this->_ready_queue; |
|
229 | + } |
|
230 | + |
|
231 | + |
|
232 | + /** |
|
233 | + * This resets all the properties used for holding "current" values corresponding to the current EE_Message object |
|
234 | + * in the generation queue. |
|
235 | + */ |
|
236 | + protected function _reset_current_properties() |
|
237 | + { |
|
238 | + $this->_verified = false; |
|
239 | + //make sure any _data value in the current message type is reset |
|
240 | + if ($this->_current_message_type instanceof EE_message_type) { |
|
241 | + $this->_current_message_type->reset_data(); |
|
242 | + } |
|
243 | + $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null; |
|
244 | + } |
|
245 | + |
|
246 | + |
|
247 | + /** |
|
248 | + * This proceeds with the actual generation of a message. By the time this is called, there should already be a |
|
249 | + * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the |
|
250 | + * _generating_queue. |
|
251 | + * |
|
252 | + * @return bool Whether the message was successfully generated or not. |
|
253 | + * @throws EE_Error |
|
254 | + * @throws InvalidArgumentException |
|
255 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
256 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
257 | + */ |
|
258 | + protected function _generate() |
|
259 | + { |
|
260 | + //double check verification has run and that everything is ready to work with (saves us having to validate |
|
261 | + // everything again). |
|
262 | + if (! $this->_verified) { |
|
263 | + return false; //get out because we don't have a valid setup to work with. |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + try { |
|
268 | + $addressees = $this->_current_message_type->get_addressees( |
|
269 | + $this->_current_data_handler, |
|
270 | + $this->_generation_queue->get_message_repository()->current()->context() |
|
271 | + ); |
|
272 | + } catch (EE_Error $e) { |
|
273 | + $this->_error_msg[] = $e->getMessage(); |
|
274 | + return false; |
|
275 | + } |
|
276 | + |
|
277 | + |
|
278 | + //if no addressees then get out because there is nothing to generation (possible bad data). |
|
279 | + if (! $this->_valid_addressees($addressees)) { |
|
280 | + do_action( |
|
281 | + 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
|
282 | + $this->_generation_queue->get_message_repository()->current(), |
|
283 | + $addressees, |
|
284 | + $this->_current_messenger, |
|
285 | + $this->_current_message_type, |
|
286 | + $this->_current_data_handler |
|
287 | + ); |
|
288 | + $this->_generation_queue->get_message_repository()->current()->set_STS_ID( |
|
289 | + EEM_Message::status_debug_only |
|
290 | + ); |
|
291 | + $this->_error_msg[] = esc_html__( |
|
292 | + 'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects. There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.', |
|
293 | + 'event_espresso' |
|
294 | + ); |
|
295 | + return false; |
|
296 | + } |
|
297 | + |
|
298 | + $message_template_group = $this->_get_message_template_group(); |
|
299 | + |
|
300 | + //in the unlikely event there is no EE_Message_Template_Group available, get out! |
|
301 | + if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
302 | + $this->_error_msg[] = esc_html__( |
|
303 | + 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
|
304 | + 'event_espresso' |
|
305 | + ); |
|
306 | + return false; |
|
307 | + } |
|
308 | + |
|
309 | + //get formatted templates for using to parse and setup EE_Message objects. |
|
310 | + $templates = $this->_get_templates($message_template_group); |
|
311 | + |
|
312 | + |
|
313 | + //setup new EE_Message objects (and add to _ready_queue) |
|
314 | + return $this->_assemble_messages($addressees, $templates, $message_template_group); |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * Retrieves the message template group being used for generating messages. |
|
320 | + * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times. |
|
321 | + * |
|
322 | + * @return EE_Message_Template_Group|null |
|
323 | + * @throws EE_Error |
|
324 | + * @throws InvalidArgumentException |
|
325 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
326 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
327 | + */ |
|
328 | + protected function _get_message_template_group() |
|
329 | + { |
|
330 | + //first see if there is a specific message template group requested (current message in the queue has a specific |
|
331 | + //GRP_ID |
|
332 | + $message_template_group = $this->_specific_message_template_group_from_queue(); |
|
333 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
334 | + return $message_template_group; |
|
335 | + } |
|
336 | + |
|
337 | + //get event_ids from the datahandler so we can check to see if there's already a message template group for them |
|
338 | + //in the collection. |
|
339 | + $event_ids = $this->_get_event_ids_from_current_data_handler(); |
|
340 | + $message_template_group = $this->_template_collection->get_by_key( |
|
341 | + $this->_template_collection->getKey( |
|
342 | + $this->_current_messenger->name, |
|
343 | + $this->_current_message_type->name, |
|
344 | + $event_ids |
|
345 | + ) |
|
346 | + ); |
|
347 | + |
|
348 | + //if we have a message template group then no need to hit the database, just return it. |
|
349 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
350 | + return $message_template_group; |
|
351 | + } |
|
352 | + |
|
353 | + //okay made it here, so let's get the global group first for this messenger and message type to ensure |
|
354 | + //there is no override set. |
|
355 | + $global_message_template_group = |
|
356 | + $this->_get_global_message_template_group_for_current_messenger_and_message_type(); |
|
357 | + |
|
358 | + if ($global_message_template_group instanceof EE_Message_Template_Group |
|
359 | + && $global_message_template_group->get('MTP_is_override') |
|
360 | + ) { |
|
361 | + return $global_message_template_group; |
|
362 | + } |
|
363 | + |
|
364 | + //if we're still here, that means there was no message template group for the events in the collection and |
|
365 | + //the global message template group for the messenger and message type is not set for override. So next step is |
|
366 | + //to see if there is a common shared custom message template group for this set of events. |
|
367 | + $message_template_group = $this->_get_shared_message_template_for_events($event_ids); |
|
368 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
369 | + return $message_template_group; |
|
370 | + } |
|
371 | + |
|
372 | + //STILL here? Okay that means the fallback is to just use the global message template group for this event set. |
|
373 | + //So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this request) |
|
374 | + //and return it. |
|
375 | + if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
376 | + $this->_template_collection->add( |
|
377 | + $global_message_template_group, |
|
378 | + $event_ids |
|
379 | + ); |
|
380 | + return $global_message_template_group; |
|
381 | + } |
|
382 | + |
|
383 | + //if we land here that means there's NO active message template group for this set. |
|
384 | + //TODO this will be a good target for some optimization down the road. Whenever there is no active message |
|
385 | + //template group for a given event set then cache that result so we don't repeat the logic. However, for now, |
|
386 | + //this should likely bit hit rarely enough that it's not a significant issue. |
|
387 | + return null; |
|
388 | + } |
|
389 | + |
|
390 | + |
|
391 | + /** |
|
392 | + * This checks the current message in the queue and determines if there is a specific Message Template Group |
|
393 | + * requested for that message. |
|
394 | + * |
|
395 | + * @return EE_Message_Template_Group|null |
|
396 | + * @throws EE_Error |
|
397 | + * @throws InvalidArgumentException |
|
398 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
399 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
400 | + */ |
|
401 | + protected function _specific_message_template_group_from_queue() |
|
402 | + { |
|
403 | + //is there a GRP_ID already on the EE_Message object? If there is, then a specific template has been requested |
|
404 | + //so let's use that. |
|
405 | + $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID(); |
|
406 | + |
|
407 | + if ($GRP_ID) { |
|
408 | + //attempt to retrieve from repo first |
|
409 | + $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
|
410 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
411 | + return $message_template_group; //got it! |
|
412 | + } |
|
413 | + |
|
414 | + //nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
|
415 | + //is not valid, so we'll continue on in the code assuming there's NO GRP_ID. |
|
416 | + $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID); |
|
417 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
418 | + $this->_template_collection->add($message_template_group); |
|
419 | + return $message_template_group; |
|
420 | + } |
|
421 | + } |
|
422 | + return null; |
|
423 | + } |
|
424 | + |
|
425 | + |
|
426 | + /** |
|
427 | + * Returns whether the event ids passed in all share the same message template group for the current message type |
|
428 | + * and messenger. |
|
429 | + * |
|
430 | + * @param array $event_ids |
|
431 | + * @return bool true means they DO share the same message template group, false means they don't. |
|
432 | + * @throws EE_Error |
|
433 | + * @throws InvalidArgumentException |
|
434 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
435 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
436 | + */ |
|
437 | + protected function _queue_shares_same_message_template_group_for_events(array $event_ids) |
|
438 | + { |
|
439 | + foreach ($this->_current_data_handler->events as $event) { |
|
440 | + $event_ids[$event['ID']] = $event['ID']; |
|
441 | + } |
|
442 | + $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count( |
|
443 | + array( |
|
444 | + array( |
|
445 | + 'Event.EVT_ID' => array('IN', $event_ids), |
|
446 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
447 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
448 | + ), |
|
449 | + ), |
|
450 | + 'GRP_ID', |
|
451 | + true |
|
452 | + ); |
|
453 | + return $count_of_message_template_groups === 1; |
|
454 | + } |
|
455 | + |
|
456 | + |
|
457 | + /** |
|
458 | + * This will get the shared message template group for events that are in the current data handler but ONLY if |
|
459 | + * there's a single shared message template group among all the events. Otherwise it returns null. |
|
460 | + * |
|
461 | + * @param array $event_ids |
|
462 | + * @return EE_Message_Template_Group|null |
|
463 | + * @throws EE_Error |
|
464 | + * @throws InvalidArgumentException |
|
465 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
466 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
467 | + */ |
|
468 | + protected function _get_shared_message_template_for_events(array $event_ids) |
|
469 | + { |
|
470 | + $message_template_group = null; |
|
471 | + if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) { |
|
472 | + $message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
473 | + array( |
|
474 | + array( |
|
475 | + 'Event.EVT_ID' => array('IN', $event_ids), |
|
476 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
477 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
478 | + 'MTP_is_active' => true, |
|
479 | + ), |
|
480 | + 'group_by' => 'GRP_ID', |
|
481 | + ) |
|
482 | + ); |
|
483 | + //store this in the collection if its valid |
|
484 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
485 | + $this->_template_collection->add( |
|
486 | + $message_template_group, |
|
487 | + $event_ids |
|
488 | + ); |
|
489 | + } |
|
490 | + } |
|
491 | + return $message_template_group; |
|
492 | + } |
|
493 | + |
|
494 | + |
|
495 | + /** |
|
496 | + * Retrieves the global message template group for the current messenger and message type. |
|
497 | + * |
|
498 | + * @return EE_Message_Template_Group|null |
|
499 | + * @throws EE_Error |
|
500 | + * @throws InvalidArgumentException |
|
501 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
502 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
503 | + */ |
|
504 | + protected function _get_global_message_template_group_for_current_messenger_and_message_type() |
|
505 | + { |
|
506 | + //first check the collection (we use an array with 0 in it to represent global groups). |
|
507 | + $global_message_template_group = $this->_template_collection->get_by_key( |
|
508 | + $this->_template_collection->getKey( |
|
509 | + $this->_current_messenger->name, |
|
510 | + $this->_current_message_type->name, |
|
511 | + array(0) |
|
512 | + ) |
|
513 | + ); |
|
514 | + |
|
515 | + //if we don't have a group lets hit the db. |
|
516 | + if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
517 | + $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
518 | + array( |
|
519 | + array( |
|
520 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
521 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
522 | + 'MTP_is_active' => true, |
|
523 | + 'MTP_is_global' => true, |
|
524 | + ), |
|
525 | + ) |
|
526 | + ); |
|
527 | + //if we have a group, add it to the collection. |
|
528 | + if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
529 | + $this->_template_collection->add( |
|
530 | + $global_message_template_group, |
|
531 | + array(0) |
|
532 | + ); |
|
533 | + } |
|
534 | + } |
|
535 | + return $global_message_template_group; |
|
536 | + } |
|
537 | + |
|
538 | + |
|
539 | + /** |
|
540 | + * Returns an array of event ids for all the events within the current data handler. |
|
541 | + * |
|
542 | + * @return array |
|
543 | + */ |
|
544 | + protected function _get_event_ids_from_current_data_handler() |
|
545 | + { |
|
546 | + $event_ids = array(); |
|
547 | + foreach ($this->_current_data_handler->events as $event) { |
|
548 | + $event_ids[$event['ID']] = $event['ID']; |
|
549 | + } |
|
550 | + return $event_ids; |
|
551 | + } |
|
552 | + |
|
553 | + |
|
554 | + /** |
|
555 | + * Retrieves formatted array of template information for each context specific to the given |
|
556 | + * EE_Message_Template_Group |
|
557 | + * |
|
558 | + * @param EE_Message_Template_Group $message_template_group |
|
559 | + * @return array The returned array is in this structure: |
|
560 | + * array( |
|
561 | + * 'field_name' => array( |
|
562 | + * 'context' => 'content' |
|
563 | + * ) |
|
564 | + * ) |
|
565 | + * @throws EE_Error |
|
566 | + */ |
|
567 | + protected function _get_templates(EE_Message_Template_Group $message_template_group) |
|
568 | + { |
|
569 | + $templates = array(); |
|
570 | + $context_templates = $message_template_group->context_templates(); |
|
571 | + foreach ($context_templates as $context => $template_fields) { |
|
572 | + foreach ($template_fields as $template_field => $template_obj) { |
|
573 | + if (! $template_obj instanceof EE_Message_Template) { |
|
574 | + continue; |
|
575 | + } |
|
576 | + $templates[$template_field][$context] = $template_obj->get('MTP_content'); |
|
577 | + } |
|
578 | + } |
|
579 | + return $templates; |
|
580 | + } |
|
581 | + |
|
582 | + |
|
583 | + /** |
|
584 | + * Assembles new fully generated EE_Message objects and adds to _ready_queue |
|
585 | + * |
|
586 | + * @param array $addressees Array of EE_Messages_Addressee objects indexed by message type |
|
587 | + * context. |
|
588 | + * @param array $templates formatted array of templates used for parsing data. |
|
589 | + * @param EE_Message_Template_Group $message_template_group |
|
590 | + * @return bool true if message generation went a-ok. false if some sort of exception occurred. Note: The |
|
591 | + * method will attempt to generate ALL EE_Message objects and add to |
|
592 | + * the _ready_queue. Successfully generated messages get added to the |
|
593 | + * queue with EEM_Message::status_idle, unsuccessfully generated |
|
594 | + * messages will get added to the queue as EEM_Message::status_failed. |
|
595 | + * Very rarely should "false" be returned from this method. |
|
596 | + * @throws EE_Error |
|
597 | + */ |
|
598 | + protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group) |
|
599 | + { |
|
600 | + |
|
601 | + //if templates are empty then get out because we can't generate anything. |
|
602 | + if (! $templates) { |
|
603 | + $this->_error_msg[] = esc_html__( |
|
604 | + 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
|
605 | + 'event_espresso' |
|
606 | + ); |
|
607 | + return false; |
|
608 | + } |
|
609 | + |
|
610 | + //We use this as the counter for generated messages because don't forget we may be executing this inside of a |
|
611 | + //generation_queue. So _ready_queue may have generated EE_Message objects already. |
|
612 | + $generated_count = 0; |
|
613 | + foreach ($addressees as $context => $recipients) { |
|
614 | + foreach ($recipients as $recipient) { |
|
615 | + $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group); |
|
616 | + if ($message instanceof EE_Message) { |
|
617 | + $this->_ready_queue->add( |
|
618 | + $message, |
|
619 | + array(), |
|
620 | + $this->_generation_queue->get_message_repository()->is_preview(), |
|
621 | + $this->_generation_queue->get_message_repository()->is_test_send() |
|
622 | + ); |
|
623 | + $generated_count++; |
|
624 | + } |
|
625 | + |
|
626 | + //if the current MSG being generated is for a test send then we'll only use ONE message in the |
|
627 | + // generation. |
|
628 | + if ($this->_generation_queue->get_message_repository()->is_test_send()) { |
|
629 | + break 2; |
|
630 | + } |
|
631 | + } |
|
632 | + } |
|
633 | + |
|
634 | + //if there are no generated messages then something else fatal went wrong. |
|
635 | + return $generated_count > 0; |
|
636 | + } |
|
637 | + |
|
638 | + |
|
639 | + /** |
|
640 | + * @param string $context The context for the generated message. |
|
641 | + * @param EE_Messages_Addressee $recipient |
|
642 | + * @param array $templates formatted array of templates used for parsing data. |
|
643 | + * @param EE_Message_Template_Group $message_template_group |
|
644 | + * @return bool|EE_Message |
|
645 | + * @throws EE_Error |
|
646 | + */ |
|
647 | + protected function _setup_message_object( |
|
648 | + $context, |
|
649 | + EE_Messages_Addressee $recipient, |
|
650 | + $templates, |
|
651 | + EE_Message_Template_Group $message_template_group |
|
652 | + ) { |
|
653 | + //stuff we already know |
|
654 | + $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0; |
|
655 | + $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction |
|
656 | + ? $this->_current_data_handler->txn->ID() |
|
657 | + : $transaction_id; |
|
658 | + $message_fields = array( |
|
659 | + 'GRP_ID' => $message_template_group->ID(), |
|
660 | + 'TXN_ID' => $transaction_id, |
|
661 | + 'MSG_messenger' => $this->_current_messenger->name, |
|
662 | + 'MSG_message_type' => $this->_current_message_type->name, |
|
663 | + 'MSG_context' => $context, |
|
664 | + ); |
|
665 | + |
|
666 | + //recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab |
|
667 | + // the info from the att_obj found in the EE_Messages_Addressee object. |
|
668 | + if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) { |
|
669 | + $message_fields['MSG_recipient_ID'] = $recipient->att_obj instanceof EE_Attendee |
|
670 | + ? $recipient->att_obj->ID() |
|
671 | + : 0; |
|
672 | + $message_fields['MSG_recipient_type'] = 'Attendee'; |
|
673 | + } else { |
|
674 | + $message_fields['MSG_recipient_ID'] = $recipient->recipient_id; |
|
675 | + $message_fields['MSG_recipient_type'] = $recipient->recipient_type; |
|
676 | + } |
|
677 | + $message = EE_Message_Factory::create($message_fields); |
|
678 | + |
|
679 | + //grab valid shortcodes for shortcode parser |
|
680 | + $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes(); |
|
681 | + $m_shortcodes = $this->_current_messenger->get_valid_shortcodes(); |
|
682 | + |
|
683 | + //if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing |
|
684 | + if (( |
|
685 | + ( |
|
686 | + empty($templates['to'][$context]) |
|
687 | + && ! $this->_current_messenger->allow_empty_to_field() |
|
688 | + ) |
|
689 | + || ! $message_template_group->is_context_active($context) |
|
690 | + ) |
|
691 | + && ! $this->_generation_queue->get_message_repository()->is_preview() |
|
692 | + ) { |
|
693 | + //we silently exit here and do NOT record a fail because the message is "turned off" by having no "to" |
|
694 | + //field. |
|
695 | + return false; |
|
696 | + } |
|
697 | + $error_msg = array(); |
|
698 | + foreach ($templates as $field => $field_context) { |
|
699 | + $error_msg = array(); |
|
700 | + //let's setup the valid shortcodes for the incoming context. |
|
701 | + $valid_shortcodes = $mt_shortcodes[$context]; |
|
702 | + //merge in valid shortcodes for the field. |
|
703 | + $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes; |
|
704 | + if (isset($templates[$field][$context])) { |
|
705 | + //prefix field. |
|
706 | + $column_name = 'MSG_' . $field; |
|
707 | + try { |
|
708 | + $content = $this->_shortcode_parser->parse_message_template( |
|
709 | + $templates[$field][$context], |
|
710 | + $recipient, |
|
711 | + $shortcodes, |
|
712 | + $this->_current_message_type, |
|
713 | + $this->_current_messenger, |
|
714 | + $message |
|
715 | + ); |
|
716 | + $message->set_field_or_extra_meta($column_name, $content); |
|
717 | + } catch (EE_Error $e) { |
|
718 | + $error_msg[] = sprintf( |
|
719 | + esc_html__( |
|
720 | + 'There was a problem generating the content for the field %s: %s', |
|
721 | + 'event_espresso' |
|
722 | + ), |
|
723 | + $field, |
|
724 | + $e->getMessage() |
|
725 | + ); |
|
726 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
727 | + } |
|
728 | + } |
|
729 | + } |
|
730 | + |
|
731 | + if ($message->STS_ID() === EEM_Message::status_failed) { |
|
732 | + $error_msg = esc_html__('There were problems generating this message:', 'event_espresso') |
|
733 | + . "\n" |
|
734 | + . implode("\n", $error_msg); |
|
735 | + $message->set_error_message($error_msg); |
|
736 | + } else { |
|
737 | + $message->set_STS_ID(EEM_Message::status_idle); |
|
738 | + } |
|
739 | + return $message; |
|
740 | + } |
|
741 | + |
|
742 | + |
|
743 | + /** |
|
744 | + * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate |
|
745 | + * error message if either is missing. |
|
746 | + * |
|
747 | + * @return bool true means there were no errors, false means there were errors. |
|
748 | + * @throws EE_Error |
|
749 | + * @throws ReflectionException |
|
750 | + */ |
|
751 | + protected function _verify() |
|
752 | + { |
|
753 | + //reset error message to an empty array. |
|
754 | + $this->_error_msg = array(); |
|
755 | + $valid = true; |
|
756 | + $valid = $valid ? $this->_validate_messenger_and_message_type() : $valid; |
|
757 | + $valid = $valid ? $this->_validate_and_setup_data() : $valid; |
|
758 | + |
|
759 | + //set the verified flag so we know everything has been validated. |
|
760 | + $this->_verified = $valid; |
|
761 | + |
|
762 | + return $valid; |
|
763 | + } |
|
764 | + |
|
765 | + |
|
766 | + /** |
|
767 | + * This accepts an array and validates that it is an array indexed by context with each value being an array of |
|
768 | + * EE_Messages_Addressee objects. |
|
769 | + * |
|
770 | + * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[] |
|
771 | + * @return bool |
|
772 | + */ |
|
773 | + protected function _valid_addressees($addressees) |
|
774 | + { |
|
775 | + if (! $addressees || ! is_array($addressees)) { |
|
776 | + return false; |
|
777 | + } |
|
778 | + |
|
779 | + foreach ($addressees as $addressee_array) { |
|
780 | + foreach ($addressee_array as $addressee) { |
|
781 | + if (! $addressee instanceof EE_Messages_Addressee) { |
|
782 | + return false; |
|
783 | + } |
|
784 | + } |
|
785 | + } |
|
786 | + return true; |
|
787 | + } |
|
788 | + |
|
789 | + |
|
790 | + /** |
|
791 | + * This validates the messenger, message type, and presences of generation data for the current EE_Message in the |
|
792 | + * queue. This process sets error messages if something is wrong. |
|
793 | + * |
|
794 | + * @return bool true is if there are no errors. false is if there is. |
|
795 | + */ |
|
796 | + protected function _validate_messenger_and_message_type() |
|
797 | + { |
|
798 | + |
|
799 | + //first are there any existing error messages? If so then return. |
|
800 | + if ($this->_error_msg) { |
|
801 | + return false; |
|
802 | + } |
|
803 | + /** @type EE_Message $message */ |
|
804 | + $message = $this->_generation_queue->get_message_repository()->current(); |
|
805 | + try { |
|
806 | + $this->_current_messenger = $message->valid_messenger(true) |
|
807 | + ? $message->messenger_object() |
|
808 | + : null; |
|
809 | + } catch (Exception $e) { |
|
810 | + $this->_error_msg[] = $e->getMessage(); |
|
811 | + } |
|
812 | + try { |
|
813 | + $this->_current_message_type = $message->valid_message_type(true) |
|
814 | + ? $message->message_type_object() |
|
815 | + : null; |
|
816 | + } catch (Exception $e) { |
|
817 | + $this->_error_msg[] = $e->getMessage(); |
|
818 | + } |
|
819 | + |
|
820 | + /** |
|
821 | + * Check if there is any generation data, but only if this is not for a preview. |
|
822 | + */ |
|
823 | + if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
824 | + && ( |
|
825 | + ! $this->_generation_queue->get_message_repository()->is_preview() |
|
826 | + && $this->_generation_queue->get_message_repository()->get_data_handler() |
|
827 | + !== 'EE_Messages_Preview_incoming_data' |
|
828 | + ) |
|
829 | + ) { |
|
830 | + $this->_error_msg[] = esc_html__( |
|
831 | + 'There is no generation data for this message. Unable to generate.', |
|
832 | + 'event_espresso' |
|
833 | + ); |
|
834 | + } |
|
835 | + |
|
836 | + return empty($this->_error_msg); |
|
837 | + } |
|
838 | + |
|
839 | + |
|
840 | + /** |
|
841 | + * This method retrieves the expected data handler for the message type and validates the generation data for that |
|
842 | + * data handler. |
|
843 | + * |
|
844 | + * @return bool true means there are no errors. false means there were errors (and handler did not get setup). |
|
845 | + * @throws EE_Error |
|
846 | + * @throws ReflectionException |
|
847 | + */ |
|
848 | + protected function _validate_and_setup_data() |
|
849 | + { |
|
850 | + |
|
851 | + //First, are there any existing error messages? If so, return because if there were errors elsewhere this can't |
|
852 | + //be used anyways. |
|
853 | + if ($this->_error_msg) { |
|
854 | + return false; |
|
855 | + } |
|
856 | + |
|
857 | + $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data(); |
|
858 | + |
|
859 | + /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
|
860 | + $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
|
861 | + ? $this->_generation_queue->get_message_repository()->get_data_handler() |
|
862 | + : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
863 | + |
|
864 | + //If this EE_Message is for a preview, then let's switch out to the preview data handler. |
|
865 | + if ($this->_generation_queue->get_message_repository()->is_preview()) { |
|
866 | + $data_handler_class_name = 'EE_Messages_Preview_incoming_data'; |
|
867 | + } |
|
868 | + |
|
869 | + //First get the class name for the data handler (and also verifies it exists. |
|
870 | + if (! class_exists($data_handler_class_name)) { |
|
871 | + $this->_error_msg[] = sprintf( |
|
872 | + esc_html__( |
|
873 | + 'The included data handler class name does not match any valid, accessible, "%1$s" classes. Looking for %2$s.', |
|
874 | + 'event_espresso' |
|
875 | + ), |
|
876 | + 'EE_Messages_incoming_data', |
|
877 | + $data_handler_class_name |
|
878 | + ); |
|
879 | + return false; |
|
880 | + } |
|
881 | + |
|
882 | + //convert generation_data for data_handler_instantiation. |
|
883 | + $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data); |
|
884 | + |
|
885 | + //note, this may set error messages as well. |
|
886 | + $this->_set_data_handler($generation_data, $data_handler_class_name); |
|
887 | + |
|
888 | + return empty($this->_error_msg); |
|
889 | + } |
|
890 | + |
|
891 | + |
|
892 | + /** |
|
893 | + * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and |
|
894 | + * adds it to the _data repository. |
|
895 | + * |
|
896 | + * @param mixed $generating_data This is data expected by the instantiated data handler. |
|
897 | + * @param string $data_handler_class_name This is the reference string indicating what data handler is being |
|
898 | + * instantiated. |
|
899 | + * @return void . |
|
900 | + * @throws EE_Error |
|
901 | + * @throws ReflectionException |
|
902 | + */ |
|
903 | + protected function _set_data_handler($generating_data, $data_handler_class_name) |
|
904 | + { |
|
905 | + //valid classname for the data handler. Now let's setup the key for the data handler repository to see if there |
|
906 | + //is already a ready data handler in the repository. |
|
907 | + $this->_current_data_handler = $this->_data_handler_collection->get_by_key( |
|
908 | + $this->_data_handler_collection->get_key( |
|
909 | + $data_handler_class_name, |
|
910 | + $generating_data |
|
911 | + ) |
|
912 | + ); |
|
913 | + if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
914 | + //no saved data_handler in the repo so let's set one up and add it to the repo. |
|
915 | + try { |
|
916 | + $this->_current_data_handler = new $data_handler_class_name($generating_data); |
|
917 | + $this->_data_handler_collection->add($this->_current_data_handler, $generating_data); |
|
918 | + } catch (EE_Error $e) { |
|
919 | + $this->_error_msg[] = $e->get_error(); |
|
920 | + } |
|
921 | + } |
|
922 | + } |
|
923 | + |
|
924 | + |
|
925 | + /** |
|
926 | + * The queued EE_Message for generation does not save the data used for generation as objects |
|
927 | + * because serialization of those objects could be problematic if the data is saved to the db. |
|
928 | + * So this method calls the static method on the associated data_handler for the given message_type |
|
929 | + * and that preps the data for later instantiation when generating. |
|
930 | + * |
|
931 | + * @param EE_Message_To_Generate $message_to_generate |
|
932 | + * @param bool $preview Indicate whether this is being used for a preview or not. |
|
933 | + * @return mixed Prepped data for persisting to the queue. false is returned if unable to prep data. |
|
934 | + */ |
|
935 | + protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview) |
|
936 | + { |
|
937 | + /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
|
938 | + $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
|
939 | + if (! $message_to_generate->valid()) { |
|
940 | + return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
|
941 | + } |
|
942 | + return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
|
943 | + } |
|
944 | + |
|
945 | + |
|
946 | + /** |
|
947 | + * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue. |
|
948 | + * |
|
949 | + * @param EE_Message_To_Generate $message_to_generate |
|
950 | + * @param bool $test_send Whether this is just a test send or not. Typically used for previews. |
|
951 | + * @throws InvalidArgumentException |
|
952 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
953 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
954 | + */ |
|
955 | + public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false) |
|
956 | + { |
|
957 | + //prep data |
|
958 | + $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview()); |
|
959 | + |
|
960 | + $message = $message_to_generate->get_EE_Message(); |
|
961 | + |
|
962 | + //is there a GRP_ID in the request? |
|
963 | + if ($GRP_ID = EE_Registry::instance()->REQ->get('GRP_ID')) { |
|
964 | + $message->set_GRP_ID($GRP_ID); |
|
965 | + } |
|
966 | + |
|
967 | + if ($data === false) { |
|
968 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
969 | + $message->set_error_message( |
|
970 | + esc_html__( |
|
971 | + 'Unable to prepare data for persistence to the database.', |
|
972 | + 'event_espresso' |
|
973 | + ) |
|
974 | + ); |
|
975 | + } else { |
|
976 | + //make sure that the data handler is cached on the message as well |
|
977 | + $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name(); |
|
978 | + } |
|
979 | + |
|
980 | + $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send); |
|
981 | + } |
|
982 | 982 | } |
@@ -259,7 +259,7 @@ discard block |
||
259 | 259 | { |
260 | 260 | //double check verification has run and that everything is ready to work with (saves us having to validate |
261 | 261 | // everything again). |
262 | - if (! $this->_verified) { |
|
262 | + if ( ! $this->_verified) { |
|
263 | 263 | return false; //get out because we don't have a valid setup to work with. |
264 | 264 | } |
265 | 265 | |
@@ -276,7 +276,7 @@ discard block |
||
276 | 276 | |
277 | 277 | |
278 | 278 | //if no addressees then get out because there is nothing to generation (possible bad data). |
279 | - if (! $this->_valid_addressees($addressees)) { |
|
279 | + if ( ! $this->_valid_addressees($addressees)) { |
|
280 | 280 | do_action( |
281 | 281 | 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
282 | 282 | $this->_generation_queue->get_message_repository()->current(), |
@@ -298,7 +298,7 @@ discard block |
||
298 | 298 | $message_template_group = $this->_get_message_template_group(); |
299 | 299 | |
300 | 300 | //in the unlikely event there is no EE_Message_Template_Group available, get out! |
301 | - if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
301 | + if ( ! $message_template_group instanceof EE_Message_Template_Group) { |
|
302 | 302 | $this->_error_msg[] = esc_html__( |
303 | 303 | 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
304 | 304 | 'event_espresso' |
@@ -408,7 +408,7 @@ discard block |
||
408 | 408 | //attempt to retrieve from repo first |
409 | 409 | $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
410 | 410 | if ($message_template_group instanceof EE_Message_Template_Group) { |
411 | - return $message_template_group; //got it! |
|
411 | + return $message_template_group; //got it! |
|
412 | 412 | } |
413 | 413 | |
414 | 414 | //nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
@@ -513,7 +513,7 @@ discard block |
||
513 | 513 | ); |
514 | 514 | |
515 | 515 | //if we don't have a group lets hit the db. |
516 | - if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
516 | + if ( ! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
517 | 517 | $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
518 | 518 | array( |
519 | 519 | array( |
@@ -570,7 +570,7 @@ discard block |
||
570 | 570 | $context_templates = $message_template_group->context_templates(); |
571 | 571 | foreach ($context_templates as $context => $template_fields) { |
572 | 572 | foreach ($template_fields as $template_field => $template_obj) { |
573 | - if (! $template_obj instanceof EE_Message_Template) { |
|
573 | + if ( ! $template_obj instanceof EE_Message_Template) { |
|
574 | 574 | continue; |
575 | 575 | } |
576 | 576 | $templates[$template_field][$context] = $template_obj->get('MTP_content'); |
@@ -599,7 +599,7 @@ discard block |
||
599 | 599 | { |
600 | 600 | |
601 | 601 | //if templates are empty then get out because we can't generate anything. |
602 | - if (! $templates) { |
|
602 | + if ( ! $templates) { |
|
603 | 603 | $this->_error_msg[] = esc_html__( |
604 | 604 | 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
605 | 605 | 'event_espresso' |
@@ -703,7 +703,7 @@ discard block |
||
703 | 703 | $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes; |
704 | 704 | if (isset($templates[$field][$context])) { |
705 | 705 | //prefix field. |
706 | - $column_name = 'MSG_' . $field; |
|
706 | + $column_name = 'MSG_'.$field; |
|
707 | 707 | try { |
708 | 708 | $content = $this->_shortcode_parser->parse_message_template( |
709 | 709 | $templates[$field][$context], |
@@ -772,13 +772,13 @@ discard block |
||
772 | 772 | */ |
773 | 773 | protected function _valid_addressees($addressees) |
774 | 774 | { |
775 | - if (! $addressees || ! is_array($addressees)) { |
|
775 | + if ( ! $addressees || ! is_array($addressees)) { |
|
776 | 776 | return false; |
777 | 777 | } |
778 | 778 | |
779 | 779 | foreach ($addressees as $addressee_array) { |
780 | 780 | foreach ($addressee_array as $addressee) { |
781 | - if (! $addressee instanceof EE_Messages_Addressee) { |
|
781 | + if ( ! $addressee instanceof EE_Messages_Addressee) { |
|
782 | 782 | return false; |
783 | 783 | } |
784 | 784 | } |
@@ -820,7 +820,7 @@ discard block |
||
820 | 820 | /** |
821 | 821 | * Check if there is any generation data, but only if this is not for a preview. |
822 | 822 | */ |
823 | - if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
823 | + if ( ! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
824 | 824 | && ( |
825 | 825 | ! $this->_generation_queue->get_message_repository()->is_preview() |
826 | 826 | && $this->_generation_queue->get_message_repository()->get_data_handler() |
@@ -859,7 +859,7 @@ discard block |
||
859 | 859 | /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
860 | 860 | $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
861 | 861 | ? $this->_generation_queue->get_message_repository()->get_data_handler() |
862 | - : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
862 | + : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data'; |
|
863 | 863 | |
864 | 864 | //If this EE_Message is for a preview, then let's switch out to the preview data handler. |
865 | 865 | if ($this->_generation_queue->get_message_repository()->is_preview()) { |
@@ -867,7 +867,7 @@ discard block |
||
867 | 867 | } |
868 | 868 | |
869 | 869 | //First get the class name for the data handler (and also verifies it exists. |
870 | - if (! class_exists($data_handler_class_name)) { |
|
870 | + if ( ! class_exists($data_handler_class_name)) { |
|
871 | 871 | $this->_error_msg[] = sprintf( |
872 | 872 | esc_html__( |
873 | 873 | 'The included data handler class name does not match any valid, accessible, "%1$s" classes. Looking for %2$s.', |
@@ -910,7 +910,7 @@ discard block |
||
910 | 910 | $generating_data |
911 | 911 | ) |
912 | 912 | ); |
913 | - if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
913 | + if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
914 | 914 | //no saved data_handler in the repo so let's set one up and add it to the repo. |
915 | 915 | try { |
916 | 916 | $this->_current_data_handler = new $data_handler_class_name($generating_data); |
@@ -936,7 +936,7 @@ discard block |
||
936 | 936 | { |
937 | 937 | /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
938 | 938 | $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
939 | - if (! $message_to_generate->valid()) { |
|
939 | + if ( ! $message_to_generate->valid()) { |
|
940 | 940 | return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
941 | 941 | } |
942 | 942 | return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
@@ -10,22 +10,22 @@ discard block |
||
10 | 10 | * @var int $message_template_group_id The ID for the message template group this context belongs to. |
11 | 11 | */ |
12 | 12 | $active_message = sprintf( |
13 | - esc_html__( |
|
14 | - 'The template for %1$s is currently %2$sactive%3$s.', |
|
15 | - 'event_espresso' |
|
16 | - ), |
|
17 | - $context_label, |
|
18 | - '<strong>', |
|
19 | - '</strong>' |
|
13 | + esc_html__( |
|
14 | + 'The template for %1$s is currently %2$sactive%3$s.', |
|
15 | + 'event_espresso' |
|
16 | + ), |
|
17 | + $context_label, |
|
18 | + '<strong>', |
|
19 | + '</strong>' |
|
20 | 20 | ); |
21 | 21 | $inactive_message = sprintf( |
22 | - esc_html__( |
|
23 | - 'The template for %1$s is currently %2$sinactive%3$s.', |
|
24 | - 'event_espresso' |
|
25 | - ), |
|
26 | - $context_label, |
|
27 | - '<strong>', |
|
28 | - '</strong>' |
|
22 | + esc_html__( |
|
23 | + 'The template for %1$s is currently %2$sinactive%3$s.', |
|
24 | + 'event_espresso' |
|
25 | + ), |
|
26 | + $context_label, |
|
27 | + '<strong>', |
|
28 | + '</strong>' |
|
29 | 29 | ); |
30 | 30 | ?> |
31 | 31 | <div class="context-active-control-container"> |
@@ -34,8 +34,8 @@ discard block |
||
34 | 34 | <span id="on-off-nonce-<?php echo $context; ?>" class="hidden"><?php echo $nonce; ?></span> |
35 | 35 | <span class="ee-on-off-toggle-label"> |
36 | 36 | <?php |
37 | - echo $is_active ? $active_message : $inactive_message; |
|
38 | - ?> |
|
37 | + echo $is_active ? $active_message : $inactive_message; |
|
38 | + ?> |
|
39 | 39 | </span> |
40 | 40 | <div class="hidden js-data"> |
41 | 41 | <span class="ee-active-message"><?php echo $active_message; ?></span> |
@@ -43,8 +43,8 @@ discard block |
||
43 | 43 | </div> |
44 | 44 | <div class="switch"> |
45 | 45 | <?php |
46 | - $checked = $is_active ? ' checked="checked"' : ''; |
|
47 | - ?> |
|
46 | + $checked = $is_active ? ' checked="checked"' : ''; |
|
47 | + ?> |
|
48 | 48 | <input data-grpid="<?php echo $message_template_group_id; ?>" id="ee-on-off-toggle-<?php echo $context; ?>" type="checkbox" class="ee-on-off-toggle ee-toggle-round-flat"<?php echo $checked; ?> value="<?php echo $on_off_action; ?>"> |
49 | 49 | <label for="ee-on-off-toggle-<?php echo $context; ?>"></label> |
50 | 50 | </div> |