Completed
Branch FET-10416-autoload-b4-bootstra... (fc73d2)
by
unknown
105:49 queued 94:33
created
core/helpers/EEH_DTT_Helper.helper.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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)
Please login to merge, or discard this patch.
Indentation   +1177 added lines, -1177 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
Please login to merge, or discard this patch.
Spacing   +51 added lines, -52 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
         }
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 2 patches
Indentation   +854 added lines, -854 removed lines patch added patch discarded remove patch
@@ -15,395 +15,395 @@  discard block
 block discarded – undo
15 15
 final class EE_Admin implements InterminableInterface
16 16
 {
17 17
 
18
-    /**
19
-     * @access private
20
-     * @var EE_Admin $_instance
21
-     */
22
-    private static $_instance;
23
-
24
-
25
-    /**
26
-     *@ singleton method used to instantiate class object
27
-     *@ access public
28
-     *@ return class instance
29
-     *
30
-     * @throws \EE_Error
31
-     */
32
-    public static function instance()
33
-    {
34
-        // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Admin) {
36
-            self::$_instance = new self();
37
-        }
38
-        return self::$_instance;
39
-    }
40
-
41
-
42
-    /**
43
-     * @return EE_Admin
44
-     * @throws EE_Error
45
-     */
46
-    public static function reset()
47
-    {
48
-        self::$_instance = null;
49
-        return self::instance();
50
-    }
51
-
52
-
53
-    /**
54
-     * class constructor
55
-     *
56
-     * @throws \EE_Error
57
-     */
58
-    protected function __construct()
59
-    {
60
-        // define global EE_Admin constants
61
-        $this->_define_all_constants();
62
-        // set autoloaders for our admin page classes based on included path information
63
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
64
-        // admin hooks
65
-        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
66
-        // load EE_Request_Handler early
67
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
68
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
69
-        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
70
-        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
71
-        add_action('admin_init', array($this, 'admin_init'), 100);
72
-        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
73
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
74
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
75
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
76
-        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
77
-
78
-        //reset Environment config (we only do this on admin page loads);
79
-        EE_Registry::instance()->CFG->environment->recheck_values();
80
-
81
-        do_action('AHEE__EE_Admin__loaded');
82
-    }
83
-
84
-
85
-    /**
86
-     * _define_all_constants
87
-     * define constants that are set globally for all admin pages
88
-     *
89
-     * @access private
90
-     * @return void
91
-     */
92
-    private function _define_all_constants()
93
-    {
94
-        if (! defined('EE_ADMIN_URL')) {
95
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
99
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100
-        }
101
-    }
102
-
103
-
104
-    /**
105
-     *    filter_plugin_actions - adds links to the Plugins page listing
106
-     *
107
-     * @access    public
108
-     * @param    array  $links
109
-     * @param    string $plugin
110
-     * @return    array
111
-     */
112
-    public function filter_plugin_actions($links, $plugin)
113
-    {
114
-        // set $main_file in stone
115
-        static $main_file;
116
-        // if $main_file is not set yet
117
-        if (! $main_file) {
118
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119
-        }
120
-        if ($plugin === $main_file) {
121
-            // compare current plugin to this one
122
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
123
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
124
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
125
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
126
-                                    . '</a>';
127
-                array_unshift($links, $maintenance_link);
128
-            } else {
129
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
130
-                                     . esc_html__('Settings', 'event_espresso')
131
-                                     . '</a>';
132
-                $events_link       = '<a href="admin.php?page=espresso_events">'
133
-                                     . esc_html__('Events', 'event_espresso')
134
-                                     . '</a>';
135
-                // add before other links
136
-                array_unshift($links, $org_settings_link, $events_link);
137
-            }
138
-        }
139
-        return $links;
140
-    }
141
-
142
-
143
-    /**
144
-     *    _get_request
145
-     *
146
-     * @access public
147
-     * @return void
148
-     * @throws EE_Error
149
-     * @throws ReflectionException
150
-     */
151
-    public function get_request()
152
-    {
153
-        EE_Registry::instance()->load_core('Request_Handler');
154
-        EE_Registry::instance()->load_core('CPT_Strategy');
155
-    }
156
-
157
-
158
-    /**
159
-     *    hide_admin_pages_except_maintenance_mode
160
-     *
161
-     * @access public
162
-     * @param array $admin_page_folder_names
163
-     * @return array
164
-     */
165
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166
-    {
167
-        return array(
168
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
171
-        );
172
-    }
173
-
174
-
175
-    /**
176
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
177
-     * EE_Front_Controller's init phases have run
178
-     *
179
-     * @access public
180
-     * @return void
181
-     * @throws EE_Error
182
-     * @throws ReflectionException
183
-     */
184
-    public function init()
185
-    {
186
-        //only enable most of the EE_Admin IF we're not in full maintenance mode
187
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
188
-            //ok so we want to enable the entire admin
189
-            add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
190
-            add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
191
-            add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
192
-            //at a glance dashboard widget
193
-            add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
194
-            //filter for get_edit_post_link used on comments for custom post types
195
-            add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196
-        }
197
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
198
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199
-            try {
200
-                //this loads the controller for the admin pages which will setup routing etc
201
-                EE_Registry::instance()->load_core('Admin_Page_Loader');
202
-            } catch (EE_Error $e) {
203
-                $e->get_error();
204
-            }
205
-        }
206
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
207
-        //make sure our CPTs and custom taxonomy metaboxes get shown for first time users
208
-        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
209
-        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
210
-        //exclude EE critical pages from all nav menus and wp_list_pages
211
-        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
212
-    }
213
-
214
-
215
-    /**
216
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
217
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
218
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
219
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
220
-     * normal property on the post_type object.  It's found ONLY in this particular context.
221
-     *
222
-     * @param  object $post_type WP post type object
223
-     * @return object            WP post type object
224
-     */
225
-    public function remove_pages_from_nav_menu($post_type)
226
-    {
227
-        //if this isn't the "pages" post type let's get out
228
-        if ($post_type->name !== 'page') {
229
-            return $post_type;
230
-        }
231
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
232
-
233
-        $post_type->_default_query = array(
234
-            'post__not_in' => $critical_pages,
235
-        );
236
-        return $post_type;
237
-    }
238
-
239
-
240
-    /**
241
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
242
-     * metaboxes get shown as well
243
-     *
244
-     * @access public
245
-     * @return void
246
-     */
247
-    public function enable_hidden_ee_nav_menu_metaboxes()
248
-    {
249
-        global $wp_meta_boxes, $pagenow;
250
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251
-            return;
252
-        }
253
-        $user = wp_get_current_user();
254
-        //has this been done yet?
255
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
256
-            return;
257
-        }
258
-
259
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
260
-        $initial_meta_boxes = apply_filters(
261
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
262
-            array(
263
-                'nav-menu-theme-locations',
264
-                'add-page',
265
-                'add-custom-links',
266
-                'add-category',
267
-                'add-espresso_events',
268
-                'add-espresso_venues',
269
-                'add-espresso_event_categories',
270
-                'add-espresso_venue_categories',
271
-                'add-post-type-post',
272
-                'add-post-type-page',
273
-            )
274
-        );
275
-
276
-        if (is_array($hidden_meta_boxes)) {
277
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
-                if (in_array($meta_box_id, $initial_meta_boxes)) {
279
-                    unset($hidden_meta_boxes[$key]);
280
-                }
281
-            }
282
-        }
283
-
284
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
-    }
287
-
288
-
289
-    /**
290
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
-     *
293
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
-     *         addons etc.
295
-     * @access public
296
-     * @return void
297
-     */
298
-    public function register_custom_nav_menu_boxes()
299
-    {
300
-        add_meta_box(
301
-            'add-extra-nav-menu-pages',
302
-            esc_html__('Event Espresso Pages', 'event_espresso'),
303
-            array($this, 'ee_cpt_archive_pages'),
304
-            'nav-menus',
305
-            'side',
306
-            'core'
307
-        );
308
-    }
309
-
310
-
311
-    /**
312
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
313
-     *
314
-     * @since   4.3.0
315
-     * @param string $link the original link generated by wp
316
-     * @param int    $id   post id
317
-     * @return string  the (maybe) modified link
318
-     */
319
-    public function modify_edit_post_link($link, $id)
320
-    {
321
-        if (! $post = get_post($id)) {
322
-            return $link;
323
-        }
324
-        if ($post->post_type === 'espresso_attendees') {
325
-            $query_args = array(
326
-                'action' => 'edit_attendee',
327
-                'post'   => $id,
328
-            );
329
-            return EEH_URL::add_query_args_and_nonce(
330
-                $query_args,
331
-                admin_url('admin.php?page=espresso_registrations')
332
-            );
333
-        }
334
-        return $link;
335
-    }
336
-
337
-
338
-    public function ee_cpt_archive_pages()
339
-    {
340
-        global $nav_menu_selected_id;
341
-
342
-        $db_fields   = false;
343
-        $walker      = new Walker_Nav_Menu_Checklist($db_fields);
344
-        $current_tab = 'event-archives';
345
-
346
-        /*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
18
+	/**
19
+	 * @access private
20
+	 * @var EE_Admin $_instance
21
+	 */
22
+	private static $_instance;
23
+
24
+
25
+	/**
26
+	 *@ singleton method used to instantiate class object
27
+	 *@ access public
28
+	 *@ return class instance
29
+	 *
30
+	 * @throws \EE_Error
31
+	 */
32
+	public static function instance()
33
+	{
34
+		// check if class object is instantiated
35
+		if (! self::$_instance instanceof EE_Admin) {
36
+			self::$_instance = new self();
37
+		}
38
+		return self::$_instance;
39
+	}
40
+
41
+
42
+	/**
43
+	 * @return EE_Admin
44
+	 * @throws EE_Error
45
+	 */
46
+	public static function reset()
47
+	{
48
+		self::$_instance = null;
49
+		return self::instance();
50
+	}
51
+
52
+
53
+	/**
54
+	 * class constructor
55
+	 *
56
+	 * @throws \EE_Error
57
+	 */
58
+	protected function __construct()
59
+	{
60
+		// define global EE_Admin constants
61
+		$this->_define_all_constants();
62
+		// set autoloaders for our admin page classes based on included path information
63
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
64
+		// admin hooks
65
+		add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
66
+		// load EE_Request_Handler early
67
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
68
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
69
+		add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
70
+		add_action('wp_loaded', array($this, 'wp_loaded'), 100);
71
+		add_action('admin_init', array($this, 'admin_init'), 100);
72
+		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
73
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
74
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
75
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
76
+		add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
77
+
78
+		//reset Environment config (we only do this on admin page loads);
79
+		EE_Registry::instance()->CFG->environment->recheck_values();
80
+
81
+		do_action('AHEE__EE_Admin__loaded');
82
+	}
83
+
84
+
85
+	/**
86
+	 * _define_all_constants
87
+	 * define constants that are set globally for all admin pages
88
+	 *
89
+	 * @access private
90
+	 * @return void
91
+	 */
92
+	private function _define_all_constants()
93
+	{
94
+		if (! defined('EE_ADMIN_URL')) {
95
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
99
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100
+		}
101
+	}
102
+
103
+
104
+	/**
105
+	 *    filter_plugin_actions - adds links to the Plugins page listing
106
+	 *
107
+	 * @access    public
108
+	 * @param    array  $links
109
+	 * @param    string $plugin
110
+	 * @return    array
111
+	 */
112
+	public function filter_plugin_actions($links, $plugin)
113
+	{
114
+		// set $main_file in stone
115
+		static $main_file;
116
+		// if $main_file is not set yet
117
+		if (! $main_file) {
118
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119
+		}
120
+		if ($plugin === $main_file) {
121
+			// compare current plugin to this one
122
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
123
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
124
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
125
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
126
+									. '</a>';
127
+				array_unshift($links, $maintenance_link);
128
+			} else {
129
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
130
+									 . esc_html__('Settings', 'event_espresso')
131
+									 . '</a>';
132
+				$events_link       = '<a href="admin.php?page=espresso_events">'
133
+									 . esc_html__('Events', 'event_espresso')
134
+									 . '</a>';
135
+				// add before other links
136
+				array_unshift($links, $org_settings_link, $events_link);
137
+			}
138
+		}
139
+		return $links;
140
+	}
141
+
142
+
143
+	/**
144
+	 *    _get_request
145
+	 *
146
+	 * @access public
147
+	 * @return void
148
+	 * @throws EE_Error
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function get_request()
152
+	{
153
+		EE_Registry::instance()->load_core('Request_Handler');
154
+		EE_Registry::instance()->load_core('CPT_Strategy');
155
+	}
156
+
157
+
158
+	/**
159
+	 *    hide_admin_pages_except_maintenance_mode
160
+	 *
161
+	 * @access public
162
+	 * @param array $admin_page_folder_names
163
+	 * @return array
164
+	 */
165
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166
+	{
167
+		return array(
168
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
+			'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
+			'support'     => EE_ADMIN_PAGES . 'support' . DS,
171
+		);
172
+	}
173
+
174
+
175
+	/**
176
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
177
+	 * EE_Front_Controller's init phases have run
178
+	 *
179
+	 * @access public
180
+	 * @return void
181
+	 * @throws EE_Error
182
+	 * @throws ReflectionException
183
+	 */
184
+	public function init()
185
+	{
186
+		//only enable most of the EE_Admin IF we're not in full maintenance mode
187
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
188
+			//ok so we want to enable the entire admin
189
+			add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
190
+			add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
191
+			add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
192
+			//at a glance dashboard widget
193
+			add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
194
+			//filter for get_edit_post_link used on comments for custom post types
195
+			add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196
+		}
197
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
198
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199
+			try {
200
+				//this loads the controller for the admin pages which will setup routing etc
201
+				EE_Registry::instance()->load_core('Admin_Page_Loader');
202
+			} catch (EE_Error $e) {
203
+				$e->get_error();
204
+			}
205
+		}
206
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
207
+		//make sure our CPTs and custom taxonomy metaboxes get shown for first time users
208
+		add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
209
+		add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
210
+		//exclude EE critical pages from all nav menus and wp_list_pages
211
+		add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
212
+	}
213
+
214
+
215
+	/**
216
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
217
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
218
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
219
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
220
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
221
+	 *
222
+	 * @param  object $post_type WP post type object
223
+	 * @return object            WP post type object
224
+	 */
225
+	public function remove_pages_from_nav_menu($post_type)
226
+	{
227
+		//if this isn't the "pages" post type let's get out
228
+		if ($post_type->name !== 'page') {
229
+			return $post_type;
230
+		}
231
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
232
+
233
+		$post_type->_default_query = array(
234
+			'post__not_in' => $critical_pages,
235
+		);
236
+		return $post_type;
237
+	}
238
+
239
+
240
+	/**
241
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
242
+	 * metaboxes get shown as well
243
+	 *
244
+	 * @access public
245
+	 * @return void
246
+	 */
247
+	public function enable_hidden_ee_nav_menu_metaboxes()
248
+	{
249
+		global $wp_meta_boxes, $pagenow;
250
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251
+			return;
252
+		}
253
+		$user = wp_get_current_user();
254
+		//has this been done yet?
255
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
256
+			return;
257
+		}
258
+
259
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
260
+		$initial_meta_boxes = apply_filters(
261
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
262
+			array(
263
+				'nav-menu-theme-locations',
264
+				'add-page',
265
+				'add-custom-links',
266
+				'add-category',
267
+				'add-espresso_events',
268
+				'add-espresso_venues',
269
+				'add-espresso_event_categories',
270
+				'add-espresso_venue_categories',
271
+				'add-post-type-post',
272
+				'add-post-type-page',
273
+			)
274
+		);
275
+
276
+		if (is_array($hidden_meta_boxes)) {
277
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
+				if (in_array($meta_box_id, $initial_meta_boxes)) {
279
+					unset($hidden_meta_boxes[$key]);
280
+				}
281
+			}
282
+		}
283
+
284
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
+	}
287
+
288
+
289
+	/**
290
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
+	 *
293
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
+	 *         addons etc.
295
+	 * @access public
296
+	 * @return void
297
+	 */
298
+	public function register_custom_nav_menu_boxes()
299
+	{
300
+		add_meta_box(
301
+			'add-extra-nav-menu-pages',
302
+			esc_html__('Event Espresso Pages', 'event_espresso'),
303
+			array($this, 'ee_cpt_archive_pages'),
304
+			'nav-menus',
305
+			'side',
306
+			'core'
307
+		);
308
+	}
309
+
310
+
311
+	/**
312
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
313
+	 *
314
+	 * @since   4.3.0
315
+	 * @param string $link the original link generated by wp
316
+	 * @param int    $id   post id
317
+	 * @return string  the (maybe) modified link
318
+	 */
319
+	public function modify_edit_post_link($link, $id)
320
+	{
321
+		if (! $post = get_post($id)) {
322
+			return $link;
323
+		}
324
+		if ($post->post_type === 'espresso_attendees') {
325
+			$query_args = array(
326
+				'action' => 'edit_attendee',
327
+				'post'   => $id,
328
+			);
329
+			return EEH_URL::add_query_args_and_nonce(
330
+				$query_args,
331
+				admin_url('admin.php?page=espresso_registrations')
332
+			);
333
+		}
334
+		return $link;
335
+	}
336
+
337
+
338
+	public function ee_cpt_archive_pages()
339
+	{
340
+		global $nav_menu_selected_id;
341
+
342
+		$db_fields   = false;
343
+		$walker      = new Walker_Nav_Menu_Checklist($db_fields);
344
+		$current_tab = 'event-archives';
345
+
346
+		/*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
347 347
             $current_tab = 'search';
348 348
         }/**/
349 349
 
350
-        $removed_args = array(
351
-            'action',
352
-            'customlink-tab',
353
-            'edit-menu-item',
354
-            'menu-item',
355
-            'page-tab',
356
-            '_wpnonce',
357
-        );
350
+		$removed_args = array(
351
+			'action',
352
+			'customlink-tab',
353
+			'edit-menu-item',
354
+			'menu-item',
355
+			'page-tab',
356
+			'_wpnonce',
357
+		);
358 358
 
359
-        ?>
359
+		?>
360 360
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
361 361
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
362 362
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
363 363
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
364 364
                        href="<?php if ($nav_menu_selected_id) {
365
-                            echo esc_url(
366
-                                add_query_arg(
367
-                                    'extra-nav-menu-pages-tab',
368
-                                    'event-archives',
369
-                                    remove_query_arg($removed_args)
370
-                                )
371
-                            );
372
-                       } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
365
+							echo esc_url(
366
+								add_query_arg(
367
+									'extra-nav-menu-pages-tab',
368
+									'event-archives',
369
+									remove_query_arg($removed_args)
370
+								)
371
+							);
372
+					   } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
373 373
                         <?php _e('Event Archive Pages', 'event_espresso'); ?>
374 374
                     </a>
375 375
                 </li>
376 376
 
377 377
                 <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
378
-                echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
379
-                ?>">
378
+				echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
379
+				?>">
380 380
                     <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
381 381
                         <?php
382
-                        $pages          = $this->_get_extra_nav_menu_pages_items();
383
-                        $args['walker'] = $walker;
384
-                        echo walk_nav_menu_tree(
385
-                            array_map(
386
-                                array($this, '_setup_extra_nav_menu_pages_items'),
387
-                                $pages
388
-                            ),
389
-                            0,
390
-                            (object) $args
391
-                        );
392
-                        ?>
382
+						$pages          = $this->_get_extra_nav_menu_pages_items();
383
+						$args['walker'] = $walker;
384
+						echo walk_nav_menu_tree(
385
+							array_map(
386
+								array($this, '_setup_extra_nav_menu_pages_items'),
387
+								$pages
388
+							),
389
+							0,
390
+							(object) $args
391
+						);
392
+						?>
393 393
                     </ul>
394 394
                 </div><!-- /.tabs-panel -->
395 395
 
396 396
                 <p class="button-controls">
397 397
                 <span class="list-controls">
398 398
                     <a href="<?php
399
-                    echo esc_url(add_query_arg(
400
-                        array(
401
-                            'extra-nav-menu-pages-tab' => 'event-archives',
402
-                            'selectall'                => 1,
403
-                        ),
404
-                        remove_query_arg($removed_args)
405
-                    ));
406
-                    ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
399
+					echo esc_url(add_query_arg(
400
+						array(
401
+							'extra-nav-menu-pages-tab' => 'event-archives',
402
+							'selectall'                => 1,
403
+						),
404
+						remove_query_arg($removed_args)
405
+					));
406
+					?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
407 407
                 </span>
408 408
                 <span class="add-to-menu">
409 409
                     <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
@@ -416,491 +416,491 @@  discard block
 block discarded – undo
416 416
 
417 417
         </div><!-- /.posttypediv -->
418 418
         <?php
419
-    }
420
-
421
-
422
-    /**
423
-     * Returns an array of event archive nav items.
424
-     *
425
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
426
-     *        method we use for getting the extra nav menu items
427
-     * @return array
428
-     */
429
-    private function _get_extra_nav_menu_pages_items()
430
-    {
431
-        $menuitems[] = array(
432
-            'title'       => esc_html__('Event List', 'event_espresso'),
433
-            'url'         => get_post_type_archive_link('espresso_events'),
434
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
435
-        );
436
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
437
-    }
438
-
439
-
440
-    /**
441
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
442
-     * the properties and converts it to the menu item object.
443
-     *
444
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
445
-     * @param $menu_item_values
446
-     * @return stdClass
447
-     */
448
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
449
-    {
450
-        $menu_item = new stdClass();
451
-        $keys      = array(
452
-            'ID'               => 0,
453
-            'db_id'            => 0,
454
-            'menu_item_parent' => 0,
455
-            'object_id'        => -1,
456
-            'post_parent'      => 0,
457
-            'type'             => 'custom',
458
-            'object'           => '',
459
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
460
-            'title'            => '',
461
-            'url'              => '',
462
-            'target'           => '',
463
-            'attr_title'       => '',
464
-            'description'      => '',
465
-            'classes'          => array(),
466
-            'xfn'              => '',
467
-        );
468
-
469
-        foreach ($keys as $key => $value) {
470
-            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
471
-        }
472
-        return $menu_item;
473
-    }
474
-
475
-
476
-    /**
477
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
478
-     * EE_Admin_Page route is called.
479
-     *
480
-     * @return void
481
-     */
482
-    public function route_admin_request()
483
-    {
484
-    }
485
-
486
-
487
-    /**
488
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
489
-     *
490
-     * @return void
491
-     */
492
-    public function wp_loaded()
493
-    {
494
-    }
495
-
496
-
497
-    /**
498
-     * admin_init
499
-     *
500
-     * @access public
501
-     * @return void
502
-     * @throws EE_Error
503
-     * @throws ReflectionException
504
-     */
505
-    public function admin_init()
506
-    {
507
-
508
-        /**
509
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
510
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
511
-         * - check if doing post processing.
512
-         * - check if doing post processing of one of EE CPTs
513
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
514
-         */
515
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
516
-            EE_Registry::instance()->load_core('Register_CPTs');
517
-            EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
518
-        }
519
-
520
-
521
-        /**
522
-         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
523
-         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
524
-         * Pages" tab in the EE General Settings Admin page.
525
-         * This is for user-proofing.
526
-         */
527
-        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
528
-    }
529
-
530
-
531
-    /**
532
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
533
-     *
534
-     * @param string $output Current output.
535
-     * @return string
536
-     */
537
-    public function modify_dropdown_pages($output)
538
-    {
539
-        //get critical pages
540
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
541
-
542
-        //split current output by line break for easier parsing.
543
-        $split_output = explode("\n", $output);
544
-
545
-        //loop through to remove any critical pages from the array.
546
-        foreach ($critical_pages as $page_id) {
547
-            $needle = 'value="' . $page_id . '"';
548
-            foreach ($split_output as $key => $haystack) {
549
-                if (strpos($haystack, $needle) !== false) {
550
-                    unset($split_output[$key]);
551
-                }
552
-            }
553
-        }
554
-
555
-        //replace output with the new contents
556
-        return implode("\n", $split_output);
557
-    }
558
-
559
-
560
-    /**
561
-     * enqueue all admin scripts that need loaded for admin pages
562
-     *
563
-     * @access public
564
-     * @return void
565
-     */
566
-    public function enqueue_admin_scripts()
567
-    {
568
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
569
-        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
570
-        // calls.
571
-        wp_enqueue_script(
572
-            'ee-inject-wp',
573
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
574
-            array('jquery'),
575
-            EVENT_ESPRESSO_VERSION,
576
-            true
577
-        );
578
-        // register cookie script for future dependencies
579
-        wp_register_script(
580
-            'jquery-cookie',
581
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
582
-            array('jquery'),
583
-            '2.1',
584
-            true
585
-        );
586
-        //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
587
-        // via: add_filter('FHEE_load_joyride', '__return_true' );
588
-        if (apply_filters('FHEE_load_joyride', false)) {
589
-            //joyride style
590
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
591
-            wp_register_style(
592
-                'ee-joyride-css',
593
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
594
-                array('joyride-css'),
595
-                EVENT_ESPRESSO_VERSION
596
-            );
597
-            wp_register_script(
598
-                'joyride-modernizr',
599
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
600
-                array(),
601
-                '2.1',
602
-                true
603
-            );
604
-            //joyride JS
605
-            wp_register_script(
606
-                'jquery-joyride',
607
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
608
-                array('jquery-cookie', 'joyride-modernizr'),
609
-                '2.1',
610
-                true
611
-            );
612
-            // wanna go for a joyride?
613
-            wp_enqueue_style('ee-joyride-css');
614
-            wp_enqueue_script('jquery-joyride');
615
-        }
616
-    }
617
-
618
-
619
-    /**
620
-     *    display_admin_notices
621
-     *
622
-     * @access    public
623
-     * @return    string
624
-     */
625
-    public function display_admin_notices()
626
-    {
627
-        echo EE_Error::get_notices();
628
-    }
629
-
630
-
631
-    /**
632
-     *    get_persistent_admin_notices
633
-     *
634
-     * @access    public
635
-     * @return        void
636
-     */
637
-    public function get_persistent_admin_notices()
638
-    {
639
-        // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
640
-        $args       = array(
641
-            'page'   => EE_Registry::instance()->REQ->is_set('page')
642
-                ? EE_Registry::instance()->REQ->get('page')
643
-                : '',
644
-            'action' => EE_Registry::instance()->REQ->is_set('action')
645
-                ? EE_Registry::instance()->REQ->get('action')
646
-                : '',
647
-        );
648
-        $return_url = EE_Admin_Page::add_query_args_and_nonce($args, admin_url('admin.php'));
649
-        //add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
650
-        //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
651
-        //with this.  But after enough time (indeterminate at this point) we can just remove this notice.
652
-        //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
653
-        if (! get_option('timezone_string')) {
654
-            EE_Error::add_persistent_admin_notice(
655
-                'datetime_fix_notice',
656
-                sprintf(
657
-                    esc_html__(
658
-                        '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
659
-                        'event_espresso'
660
-                    ),
661
-                    '<strong>',
662
-                    '</strong>',
663
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
664
-                    '</a>',
665
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
666
-                        array(
667
-                            'page' => 'espresso_maintenance_settings',
668
-                            'action' => 'datetime_tools'
669
-                        ),
670
-                        admin_url('admin.php')
671
-                    ) . '">'
672
-                )
673
-            );
674
-        }
675
-        echo EE_Error::get_persistent_admin_notices($return_url);
676
-    }
677
-
678
-
679
-    /**
680
-     *    dismiss_persistent_admin_notice
681
-     *
682
-     * @access    public
683
-     * @return        void
684
-     */
685
-    public function dismiss_ee_nag_notice_callback()
686
-    {
687
-        EE_Error::dismiss_persistent_admin_notice();
688
-    }
689
-
690
-
691
-    /**
692
-     * @param array $elements
693
-     * @return array
694
-     * @throws \EE_Error
695
-     */
696
-    public function dashboard_glance_items($elements)
697
-    {
698
-        $elements                        = is_array($elements) ? $elements : array($elements);
699
-        $events                          = EEM_Event::instance()->count();
700
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
701
-            array('page' => 'espresso_events'),
702
-            admin_url('admin.php')
703
-        );
704
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
705
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
706
-        $registrations                   = EEM_Registration::instance()->count(
707
-            array(
708
-                array(
709
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
710
-                ),
711
-            )
712
-        );
713
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
714
-            array('page' => 'espresso_registrations'),
715
-            admin_url('admin.php')
716
-        );
717
-        $items['registrations']['text']  = sprintf(
718
-            _n('%s Registration', '%s Registrations', $registrations),
719
-            number_format_i18n($registrations)
720
-        );
721
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
722
-
723
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
724
-
725
-        foreach ($items as $type => $item_properties) {
726
-            $elements[] = sprintf(
727
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
728
-                $item_properties['url'],
729
-                $item_properties['title'],
730
-                $item_properties['text']
731
-            );
732
-        }
733
-        return $elements;
734
-    }
735
-
736
-
737
-    /**
738
-     *    check_for_invalid_datetime_formats
739
-     *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
740
-     *    their selected format can be parsed by PHP
741
-     *
742
-     * @access    public
743
-     * @param    $value
744
-     * @param    $option
745
-     * @throws EE_Error
746
-     * @return    string
747
-     */
748
-    public function check_for_invalid_datetime_formats($value, $option)
749
-    {
750
-        // check for date_format or time_format
751
-        switch ($option) {
752
-            case 'date_format':
753
-                $date_time_format = $value . ' ' . get_option('time_format');
754
-                break;
755
-            case 'time_format':
756
-                $date_time_format = get_option('date_format') . ' ' . $value;
757
-                break;
758
-            default:
759
-                $date_time_format = false;
760
-        }
761
-        // do we have a date_time format to check ?
762
-        if ($date_time_format) {
763
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
764
-
765
-            if (is_array($error_msg)) {
766
-                $msg = '<p>'
767
-                       . sprintf(
768
-                           esc_html__(
769
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
770
-                               'event_espresso'
771
-                           ),
772
-                           date($date_time_format),
773
-                           $date_time_format
774
-                       )
775
-                       . '</p><p><ul>';
776
-
777
-
778
-                foreach ($error_msg as $error) {
779
-                    $msg .= '<li>' . $error . '</li>';
780
-                }
781
-
782
-                $msg .= '</ul></p><p>'
783
-                        . sprintf(
784
-                            esc_html__(
785
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
786
-                                'event_espresso'
787
-                            ),
788
-                            '<span style="color:#D54E21;">',
789
-                            '</span>'
790
-                        )
791
-                        . '</p>';
792
-
793
-                // trigger WP settings error
794
-                add_settings_error(
795
-                    'date_format',
796
-                    'date_format',
797
-                    $msg
798
-                );
799
-
800
-                // set format to something valid
801
-                switch ($option) {
802
-                    case 'date_format':
803
-                        $value = 'F j, Y';
804
-                        break;
805
-                    case 'time_format':
806
-                        $value = 'g:i a';
807
-                        break;
808
-                }
809
-            }
810
-        }
811
-        return $value;
812
-    }
813
-
814
-
815
-    /**
816
-     *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
817
-     *
818
-     * @access    public
819
-     * @param $content
820
-     * @return    string
821
-     */
822
-    public function its_eSpresso($content)
823
-    {
824
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
825
-    }
826
-
827
-
828
-    /**
829
-     *    espresso_admin_footer
830
-     *
831
-     * @access    public
832
-     * @return    string
833
-     */
834
-    public function espresso_admin_footer()
835
-    {
836
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
837
-    }
838
-
839
-
840
-    /**
841
-     * static method for registering ee admin page.
842
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
843
-     *
844
-     * @since      4.3.0
845
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
846
-     * @see        EE_Register_Admin_Page::register()
847
-     * @param       $page_basename
848
-     * @param       $page_path
849
-     * @param array $config
850
-     * @return void
851
-     * @throws EE_Error
852
-     */
853
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
854
-    {
855
-        EE_Error::doing_it_wrong(
856
-            __METHOD__,
857
-            sprintf(
858
-                esc_html__(
859
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
860
-                    'event_espresso'
861
-                ),
862
-                $page_basename
863
-            ),
864
-            '4.3'
865
-        );
866
-        if (class_exists('EE_Register_Admin_Page')) {
867
-            $config['page_path'] = $page_path;
868
-        }
869
-        EE_Register_Admin_Page::register($page_basename, $config);
870
-    }
871
-
872
-
873
-    /**
874
-     * @deprecated 4.8.41
875
-     * @access     public
876
-     * @param  int      $post_ID
877
-     * @param  \WP_Post $post
878
-     * @return void
879
-     */
880
-    public static function parse_post_content_on_save($post_ID, $post)
881
-    {
882
-        EE_Error::doing_it_wrong(
883
-            __METHOD__,
884
-            esc_html__('Usage is deprecated', 'event_espresso'),
885
-            '4.8.41'
886
-        );
887
-    }
888
-
889
-
890
-    /**
891
-     * @deprecated 4.8.41
892
-     * @access     public
893
-     * @param  $option
894
-     * @param  $old_value
895
-     * @param  $value
896
-     * @return void
897
-     */
898
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
899
-    {
900
-        EE_Error::doing_it_wrong(
901
-            __METHOD__,
902
-            esc_html__('Usage is deprecated', 'event_espresso'),
903
-            '4.8.41'
904
-        );
905
-    }
419
+	}
420
+
421
+
422
+	/**
423
+	 * Returns an array of event archive nav items.
424
+	 *
425
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
426
+	 *        method we use for getting the extra nav menu items
427
+	 * @return array
428
+	 */
429
+	private function _get_extra_nav_menu_pages_items()
430
+	{
431
+		$menuitems[] = array(
432
+			'title'       => esc_html__('Event List', 'event_espresso'),
433
+			'url'         => get_post_type_archive_link('espresso_events'),
434
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
435
+		);
436
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
437
+	}
438
+
439
+
440
+	/**
441
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
442
+	 * the properties and converts it to the menu item object.
443
+	 *
444
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
445
+	 * @param $menu_item_values
446
+	 * @return stdClass
447
+	 */
448
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
449
+	{
450
+		$menu_item = new stdClass();
451
+		$keys      = array(
452
+			'ID'               => 0,
453
+			'db_id'            => 0,
454
+			'menu_item_parent' => 0,
455
+			'object_id'        => -1,
456
+			'post_parent'      => 0,
457
+			'type'             => 'custom',
458
+			'object'           => '',
459
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
460
+			'title'            => '',
461
+			'url'              => '',
462
+			'target'           => '',
463
+			'attr_title'       => '',
464
+			'description'      => '',
465
+			'classes'          => array(),
466
+			'xfn'              => '',
467
+		);
468
+
469
+		foreach ($keys as $key => $value) {
470
+			$menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
471
+		}
472
+		return $menu_item;
473
+	}
474
+
475
+
476
+	/**
477
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
478
+	 * EE_Admin_Page route is called.
479
+	 *
480
+	 * @return void
481
+	 */
482
+	public function route_admin_request()
483
+	{
484
+	}
485
+
486
+
487
+	/**
488
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
489
+	 *
490
+	 * @return void
491
+	 */
492
+	public function wp_loaded()
493
+	{
494
+	}
495
+
496
+
497
+	/**
498
+	 * admin_init
499
+	 *
500
+	 * @access public
501
+	 * @return void
502
+	 * @throws EE_Error
503
+	 * @throws ReflectionException
504
+	 */
505
+	public function admin_init()
506
+	{
507
+
508
+		/**
509
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
510
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
511
+		 * - check if doing post processing.
512
+		 * - check if doing post processing of one of EE CPTs
513
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
514
+		 */
515
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
516
+			EE_Registry::instance()->load_core('Register_CPTs');
517
+			EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
518
+		}
519
+
520
+
521
+		/**
522
+		 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
523
+		 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
524
+		 * Pages" tab in the EE General Settings Admin page.
525
+		 * This is for user-proofing.
526
+		 */
527
+		add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
528
+	}
529
+
530
+
531
+	/**
532
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
533
+	 *
534
+	 * @param string $output Current output.
535
+	 * @return string
536
+	 */
537
+	public function modify_dropdown_pages($output)
538
+	{
539
+		//get critical pages
540
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
541
+
542
+		//split current output by line break for easier parsing.
543
+		$split_output = explode("\n", $output);
544
+
545
+		//loop through to remove any critical pages from the array.
546
+		foreach ($critical_pages as $page_id) {
547
+			$needle = 'value="' . $page_id . '"';
548
+			foreach ($split_output as $key => $haystack) {
549
+				if (strpos($haystack, $needle) !== false) {
550
+					unset($split_output[$key]);
551
+				}
552
+			}
553
+		}
554
+
555
+		//replace output with the new contents
556
+		return implode("\n", $split_output);
557
+	}
558
+
559
+
560
+	/**
561
+	 * enqueue all admin scripts that need loaded for admin pages
562
+	 *
563
+	 * @access public
564
+	 * @return void
565
+	 */
566
+	public function enqueue_admin_scripts()
567
+	{
568
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
569
+		// Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
570
+		// calls.
571
+		wp_enqueue_script(
572
+			'ee-inject-wp',
573
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
574
+			array('jquery'),
575
+			EVENT_ESPRESSO_VERSION,
576
+			true
577
+		);
578
+		// register cookie script for future dependencies
579
+		wp_register_script(
580
+			'jquery-cookie',
581
+			EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
582
+			array('jquery'),
583
+			'2.1',
584
+			true
585
+		);
586
+		//joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
587
+		// via: add_filter('FHEE_load_joyride', '__return_true' );
588
+		if (apply_filters('FHEE_load_joyride', false)) {
589
+			//joyride style
590
+			wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
591
+			wp_register_style(
592
+				'ee-joyride-css',
593
+				EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
594
+				array('joyride-css'),
595
+				EVENT_ESPRESSO_VERSION
596
+			);
597
+			wp_register_script(
598
+				'joyride-modernizr',
599
+				EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
600
+				array(),
601
+				'2.1',
602
+				true
603
+			);
604
+			//joyride JS
605
+			wp_register_script(
606
+				'jquery-joyride',
607
+				EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
608
+				array('jquery-cookie', 'joyride-modernizr'),
609
+				'2.1',
610
+				true
611
+			);
612
+			// wanna go for a joyride?
613
+			wp_enqueue_style('ee-joyride-css');
614
+			wp_enqueue_script('jquery-joyride');
615
+		}
616
+	}
617
+
618
+
619
+	/**
620
+	 *    display_admin_notices
621
+	 *
622
+	 * @access    public
623
+	 * @return    string
624
+	 */
625
+	public function display_admin_notices()
626
+	{
627
+		echo EE_Error::get_notices();
628
+	}
629
+
630
+
631
+	/**
632
+	 *    get_persistent_admin_notices
633
+	 *
634
+	 * @access    public
635
+	 * @return        void
636
+	 */
637
+	public function get_persistent_admin_notices()
638
+	{
639
+		// http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
640
+		$args       = array(
641
+			'page'   => EE_Registry::instance()->REQ->is_set('page')
642
+				? EE_Registry::instance()->REQ->get('page')
643
+				: '',
644
+			'action' => EE_Registry::instance()->REQ->is_set('action')
645
+				? EE_Registry::instance()->REQ->get('action')
646
+				: '',
647
+		);
648
+		$return_url = EE_Admin_Page::add_query_args_and_nonce($args, admin_url('admin.php'));
649
+		//add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
650
+		//@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
651
+		//with this.  But after enough time (indeterminate at this point) we can just remove this notice.
652
+		//this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
653
+		if (! get_option('timezone_string')) {
654
+			EE_Error::add_persistent_admin_notice(
655
+				'datetime_fix_notice',
656
+				sprintf(
657
+					esc_html__(
658
+						'%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
659
+						'event_espresso'
660
+					),
661
+					'<strong>',
662
+					'</strong>',
663
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
664
+					'</a>',
665
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
666
+						array(
667
+							'page' => 'espresso_maintenance_settings',
668
+							'action' => 'datetime_tools'
669
+						),
670
+						admin_url('admin.php')
671
+					) . '">'
672
+				)
673
+			);
674
+		}
675
+		echo EE_Error::get_persistent_admin_notices($return_url);
676
+	}
677
+
678
+
679
+	/**
680
+	 *    dismiss_persistent_admin_notice
681
+	 *
682
+	 * @access    public
683
+	 * @return        void
684
+	 */
685
+	public function dismiss_ee_nag_notice_callback()
686
+	{
687
+		EE_Error::dismiss_persistent_admin_notice();
688
+	}
689
+
690
+
691
+	/**
692
+	 * @param array $elements
693
+	 * @return array
694
+	 * @throws \EE_Error
695
+	 */
696
+	public function dashboard_glance_items($elements)
697
+	{
698
+		$elements                        = is_array($elements) ? $elements : array($elements);
699
+		$events                          = EEM_Event::instance()->count();
700
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
701
+			array('page' => 'espresso_events'),
702
+			admin_url('admin.php')
703
+		);
704
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
705
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
706
+		$registrations                   = EEM_Registration::instance()->count(
707
+			array(
708
+				array(
709
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
710
+				),
711
+			)
712
+		);
713
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
714
+			array('page' => 'espresso_registrations'),
715
+			admin_url('admin.php')
716
+		);
717
+		$items['registrations']['text']  = sprintf(
718
+			_n('%s Registration', '%s Registrations', $registrations),
719
+			number_format_i18n($registrations)
720
+		);
721
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
722
+
723
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
724
+
725
+		foreach ($items as $type => $item_properties) {
726
+			$elements[] = sprintf(
727
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
728
+				$item_properties['url'],
729
+				$item_properties['title'],
730
+				$item_properties['text']
731
+			);
732
+		}
733
+		return $elements;
734
+	}
735
+
736
+
737
+	/**
738
+	 *    check_for_invalid_datetime_formats
739
+	 *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
740
+	 *    their selected format can be parsed by PHP
741
+	 *
742
+	 * @access    public
743
+	 * @param    $value
744
+	 * @param    $option
745
+	 * @throws EE_Error
746
+	 * @return    string
747
+	 */
748
+	public function check_for_invalid_datetime_formats($value, $option)
749
+	{
750
+		// check for date_format or time_format
751
+		switch ($option) {
752
+			case 'date_format':
753
+				$date_time_format = $value . ' ' . get_option('time_format');
754
+				break;
755
+			case 'time_format':
756
+				$date_time_format = get_option('date_format') . ' ' . $value;
757
+				break;
758
+			default:
759
+				$date_time_format = false;
760
+		}
761
+		// do we have a date_time format to check ?
762
+		if ($date_time_format) {
763
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
764
+
765
+			if (is_array($error_msg)) {
766
+				$msg = '<p>'
767
+					   . sprintf(
768
+						   esc_html__(
769
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
770
+							   'event_espresso'
771
+						   ),
772
+						   date($date_time_format),
773
+						   $date_time_format
774
+					   )
775
+					   . '</p><p><ul>';
776
+
777
+
778
+				foreach ($error_msg as $error) {
779
+					$msg .= '<li>' . $error . '</li>';
780
+				}
781
+
782
+				$msg .= '</ul></p><p>'
783
+						. sprintf(
784
+							esc_html__(
785
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
786
+								'event_espresso'
787
+							),
788
+							'<span style="color:#D54E21;">',
789
+							'</span>'
790
+						)
791
+						. '</p>';
792
+
793
+				// trigger WP settings error
794
+				add_settings_error(
795
+					'date_format',
796
+					'date_format',
797
+					$msg
798
+				);
799
+
800
+				// set format to something valid
801
+				switch ($option) {
802
+					case 'date_format':
803
+						$value = 'F j, Y';
804
+						break;
805
+					case 'time_format':
806
+						$value = 'g:i a';
807
+						break;
808
+				}
809
+			}
810
+		}
811
+		return $value;
812
+	}
813
+
814
+
815
+	/**
816
+	 *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
817
+	 *
818
+	 * @access    public
819
+	 * @param $content
820
+	 * @return    string
821
+	 */
822
+	public function its_eSpresso($content)
823
+	{
824
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
825
+	}
826
+
827
+
828
+	/**
829
+	 *    espresso_admin_footer
830
+	 *
831
+	 * @access    public
832
+	 * @return    string
833
+	 */
834
+	public function espresso_admin_footer()
835
+	{
836
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
837
+	}
838
+
839
+
840
+	/**
841
+	 * static method for registering ee admin page.
842
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
843
+	 *
844
+	 * @since      4.3.0
845
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
846
+	 * @see        EE_Register_Admin_Page::register()
847
+	 * @param       $page_basename
848
+	 * @param       $page_path
849
+	 * @param array $config
850
+	 * @return void
851
+	 * @throws EE_Error
852
+	 */
853
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
854
+	{
855
+		EE_Error::doing_it_wrong(
856
+			__METHOD__,
857
+			sprintf(
858
+				esc_html__(
859
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
860
+					'event_espresso'
861
+				),
862
+				$page_basename
863
+			),
864
+			'4.3'
865
+		);
866
+		if (class_exists('EE_Register_Admin_Page')) {
867
+			$config['page_path'] = $page_path;
868
+		}
869
+		EE_Register_Admin_Page::register($page_basename, $config);
870
+	}
871
+
872
+
873
+	/**
874
+	 * @deprecated 4.8.41
875
+	 * @access     public
876
+	 * @param  int      $post_ID
877
+	 * @param  \WP_Post $post
878
+	 * @return void
879
+	 */
880
+	public static function parse_post_content_on_save($post_ID, $post)
881
+	{
882
+		EE_Error::doing_it_wrong(
883
+			__METHOD__,
884
+			esc_html__('Usage is deprecated', 'event_espresso'),
885
+			'4.8.41'
886
+		);
887
+	}
888
+
889
+
890
+	/**
891
+	 * @deprecated 4.8.41
892
+	 * @access     public
893
+	 * @param  $option
894
+	 * @param  $old_value
895
+	 * @param  $value
896
+	 * @return void
897
+	 */
898
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
899
+	{
900
+		EE_Error::doing_it_wrong(
901
+			__METHOD__,
902
+			esc_html__('Usage is deprecated', 'event_espresso'),
903
+			'4.8.41'
904
+		);
905
+	}
906 906
 }
Please login to merge, or discard this patch.
Spacing   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     public static function instance()
33 33
     {
34 34
         // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Admin) {
35
+        if ( ! self::$_instance instanceof EE_Admin) {
36 36
             self::$_instance = new self();
37 37
         }
38 38
         return self::$_instance;
@@ -91,11 +91,11 @@  discard block
 block discarded – undo
91 91
      */
92 92
     private function _define_all_constants()
93 93
     {
94
-        if (! defined('EE_ADMIN_URL')) {
95
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
94
+        if ( ! defined('EE_ADMIN_URL')) {
95
+            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL.'core/admin/');
96
+            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL.'admin_pages/');
97
+            define('EE_ADMIN_TEMPLATE', EE_ADMIN.'templates'.DS);
98
+            define('WP_ADMIN_PATH', ABSPATH.'wp-admin/');
99 99
             define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100 100
         }
101 101
     }
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
         // set $main_file in stone
115 115
         static $main_file;
116 116
         // if $main_file is not set yet
117
-        if (! $main_file) {
117
+        if ( ! $main_file) {
118 118
             $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119 119
         }
120 120
         if ($plugin === $main_file) {
@@ -165,9 +165,9 @@  discard block
 block discarded – undo
165 165
     public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166 166
     {
167 167
         return array(
168
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
168
+            'maintenance' => EE_ADMIN_PAGES.'maintenance'.DS,
169
+            'about'       => EE_ADMIN_PAGES.'about'.DS,
170
+            'support'     => EE_ADMIN_PAGES.'support'.DS,
171 171
         );
172 172
     }
173 173
 
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
             add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196 196
         }
197 197
         // run the admin page factory but ONLY if we are doing an ee admin ajax request
198
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
198
+        if ( ! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199 199
             try {
200 200
                 //this loads the controller for the admin pages which will setup routing etc
201 201
                 EE_Registry::instance()->load_core('Admin_Page_Loader');
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
     public function enable_hidden_ee_nav_menu_metaboxes()
248 248
     {
249 249
         global $wp_meta_boxes, $pagenow;
250
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
250
+        if ( ! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251 251
             return;
252 252
         }
253 253
         $user = wp_get_current_user();
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
      */
319 319
     public function modify_edit_post_link($link, $id)
320 320
     {
321
-        if (! $post = get_post($id)) {
321
+        if ( ! $post = get_post($id)) {
322 322
             return $link;
323 323
         }
324 324
         if ($post->post_type === 'espresso_attendees') {
@@ -544,7 +544,7 @@  discard block
 block discarded – undo
544 544
 
545 545
         //loop through to remove any critical pages from the array.
546 546
         foreach ($critical_pages as $page_id) {
547
-            $needle = 'value="' . $page_id . '"';
547
+            $needle = 'value="'.$page_id.'"';
548 548
             foreach ($split_output as $key => $haystack) {
549 549
                 if (strpos($haystack, $needle) !== false) {
550 550
                     unset($split_output[$key]);
@@ -570,7 +570,7 @@  discard block
 block discarded – undo
570 570
         // calls.
571 571
         wp_enqueue_script(
572 572
             'ee-inject-wp',
573
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
573
+            EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js',
574 574
             array('jquery'),
575 575
             EVENT_ESPRESSO_VERSION,
576 576
             true
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
         // register cookie script for future dependencies
579 579
         wp_register_script(
580 580
             'jquery-cookie',
581
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
581
+            EE_THIRD_PARTY_URL.'joyride/jquery.cookie.js',
582 582
             array('jquery'),
583 583
             '2.1',
584 584
             true
@@ -587,16 +587,16 @@  discard block
 block discarded – undo
587 587
         // via: add_filter('FHEE_load_joyride', '__return_true' );
588 588
         if (apply_filters('FHEE_load_joyride', false)) {
589 589
             //joyride style
590
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
590
+            wp_register_style('joyride-css', EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css', array(), '2.1');
591 591
             wp_register_style(
592 592
                 'ee-joyride-css',
593
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
593
+                EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css',
594 594
                 array('joyride-css'),
595 595
                 EVENT_ESPRESSO_VERSION
596 596
             );
597 597
             wp_register_script(
598 598
                 'joyride-modernizr',
599
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
599
+                EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js',
600 600
                 array(),
601 601
                 '2.1',
602 602
                 true
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
             //joyride JS
605 605
             wp_register_script(
606 606
                 'jquery-joyride',
607
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
607
+                EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js',
608 608
                 array('jquery-cookie', 'joyride-modernizr'),
609 609
                 '2.1',
610 610
                 true
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
     public function get_persistent_admin_notices()
638 638
     {
639 639
         // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
640
-        $args       = array(
640
+        $args = array(
641 641
             'page'   => EE_Registry::instance()->REQ->is_set('page')
642 642
                 ? EE_Registry::instance()->REQ->get('page')
643 643
                 : '',
@@ -650,7 +650,7 @@  discard block
 block discarded – undo
650 650
         //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
651 651
         //with this.  But after enough time (indeterminate at this point) we can just remove this notice.
652 652
         //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
653
-        if (! get_option('timezone_string')) {
653
+        if ( ! get_option('timezone_string')) {
654 654
             EE_Error::add_persistent_admin_notice(
655 655
                 'datetime_fix_notice',
656 656
                 sprintf(
@@ -662,13 +662,13 @@  discard block
 block discarded – undo
662 662
                     '</strong>',
663 663
                     '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
664 664
                     '</a>',
665
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
665
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
666 666
                         array(
667 667
                             'page' => 'espresso_maintenance_settings',
668 668
                             'action' => 'datetime_tools'
669 669
                         ),
670 670
                         admin_url('admin.php')
671
-                    ) . '">'
671
+                    ).'">'
672 672
                 )
673 673
             );
674 674
         }
@@ -710,21 +710,21 @@  discard block
 block discarded – undo
710 710
                 ),
711 711
             )
712 712
         );
713
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
713
+        $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
714 714
             array('page' => 'espresso_registrations'),
715 715
             admin_url('admin.php')
716 716
         );
717
-        $items['registrations']['text']  = sprintf(
717
+        $items['registrations']['text'] = sprintf(
718 718
             _n('%s Registration', '%s Registrations', $registrations),
719 719
             number_format_i18n($registrations)
720 720
         );
721 721
         $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
722 722
 
723
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
723
+        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
724 724
 
725 725
         foreach ($items as $type => $item_properties) {
726 726
             $elements[] = sprintf(
727
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
727
+                '<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>',
728 728
                 $item_properties['url'],
729 729
                 $item_properties['title'],
730 730
                 $item_properties['text']
@@ -750,10 +750,10 @@  discard block
 block discarded – undo
750 750
         // check for date_format or time_format
751 751
         switch ($option) {
752 752
             case 'date_format':
753
-                $date_time_format = $value . ' ' . get_option('time_format');
753
+                $date_time_format = $value.' '.get_option('time_format');
754 754
                 break;
755 755
             case 'time_format':
756
-                $date_time_format = get_option('date_format') . ' ' . $value;
756
+                $date_time_format = get_option('date_format').' '.$value;
757 757
                 break;
758 758
             default:
759 759
                 $date_time_format = false;
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
 
777 777
 
778 778
                 foreach ($error_msg as $error) {
779
-                    $msg .= '<li>' . $error . '</li>';
779
+                    $msg .= '<li>'.$error.'</li>';
780 780
                 }
781 781
 
782 782
                 $msg .= '</ul></p><p>'
Please login to merge, or discard this patch.
libraries/messages/data_class/EE_Messages_Gateways_incoming_data.class.php 2 patches
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -135,11 +135,11 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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)));
Please login to merge, or discard this patch.
core/db_models/fields/EE_Datetime_Field.php 1 patch
Indentation   +748 added lines, -748 removed lines patch added patch discarded remove patch
@@ -15,753 +15,753 @@
 block discarded – undo
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
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 3 patches
Doc Comments   +4 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1164,7 +1164,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
     {
Please login to merge, or discard this patch.
Indentation   +1979 added lines, -1979 removed lines patch added patch discarded remove patch
@@ -18,1985 +18,1985 @@
 block discarded – undo
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
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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):
Please login to merge, or discard this patch.
core/services/Benchmark.php 2 patches
Indentation   +303 added lines, -303 removed lines patch added patch discarded remove patch
@@ -17,309 +17,309 @@
 block discarded – undo
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
 
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 
Please login to merge, or discard this patch.
core/domain/services/registration/CopyRegistrationService.php 2 patches
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -12,7 +12,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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(
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Generator.lib.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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(
Please login to merge, or discard this patch.
Indentation   +966 added lines, -966 removed lines patch added patch discarded remove patch
@@ -13,970 +13,970 @@
 block discarded – undo
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
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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());
Please login to merge, or discard this patch.
messages/templates/ee_msg_editor_active_context_element.template.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -10,22 +10,22 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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>
Please login to merge, or discard this patch.