Completed
Branch FET-9856-direct-instantiation (142681)
by
unknown
108:29 queued 96:36
created
core/services/loaders/LoaderFactory.php 2 patches
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -79,37 +79,37 @@
 block discarded – undo
79 79
 class LoaderFactory
80 80
 {
81 81
 
82
-    /**
83
-     * @var LoaderInterface $loader ;
84
-     */
85
-    private static $loader;
82
+	/**
83
+	 * @var LoaderInterface $loader ;
84
+	 */
85
+	private static $loader;
86 86
 
87 87
 
88 88
 
89
-    /**
90
-     * @param mixed $generator      provided during  very first instantiation in
91
-     *                              EE_Load_Espresso_Core::handle_request()
92
-     *                              otherwise can be left null
93
-     * @return LoaderInterface
94
-     * @throws InvalidArgumentException
95
-     * @throws InvalidInterfaceException
96
-     * @throws InvalidDataTypeException
97
-     */
98
-    public static function getLoader($generator = null)
99
-    {
100
-        if (! LoaderFactory::$loader instanceof LoaderInterface) {
101
-            $generator = $generator !== null ? $generator : EE_Registry::instance();
102
-            $core_loader = new CoreLoader($generator);
103
-            LoaderFactory::$loader = new Loader(
104
-                $core_loader,
105
-                new CachingLoader(
106
-                    $core_loader,
107
-                    new LooseCollection('')
108
-                )
109
-            );
110
-        }
111
-        return LoaderFactory::$loader;
112
-    }
89
+	/**
90
+	 * @param mixed $generator      provided during  very first instantiation in
91
+	 *                              EE_Load_Espresso_Core::handle_request()
92
+	 *                              otherwise can be left null
93
+	 * @return LoaderInterface
94
+	 * @throws InvalidArgumentException
95
+	 * @throws InvalidInterfaceException
96
+	 * @throws InvalidDataTypeException
97
+	 */
98
+	public static function getLoader($generator = null)
99
+	{
100
+		if (! LoaderFactory::$loader instanceof LoaderInterface) {
101
+			$generator = $generator !== null ? $generator : EE_Registry::instance();
102
+			$core_loader = new CoreLoader($generator);
103
+			LoaderFactory::$loader = new Loader(
104
+				$core_loader,
105
+				new CachingLoader(
106
+					$core_loader,
107
+					new LooseCollection('')
108
+				)
109
+			);
110
+		}
111
+		return LoaderFactory::$loader;
112
+	}
113 113
 
114 114
 
115 115
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -97,7 +97,7 @@
 block discarded – undo
97 97
      */
98 98
     public static function getLoader($generator = null)
99 99
     {
100
-        if (! LoaderFactory::$loader instanceof LoaderInterface) {
100
+        if ( ! LoaderFactory::$loader instanceof LoaderInterface) {
101 101
             $generator = $generator !== null ? $generator : EE_Registry::instance();
102 102
             $core_loader = new CoreLoader($generator);
103 103
             LoaderFactory::$loader = new Loader(
Please login to merge, or discard this patch.
core/db_models/fields/EE_Datetime_Field.php 1 patch
Indentation   +755 added lines, -755 removed lines patch added patch discarded remove patch
@@ -15,760 +15,760 @@
 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
-        $time = is_int($time) || $time === null ? $time : strtotime($time);
712
-        $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
713
-        $transitions = $DateTimeZone->getTransitions($time);
714
-        return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
715
-    }
716
-
717
-
718
-
719
-    /**
720
-     * get_timezone_offset
721
-     *
722
-     * @param \DateTimeZone $DateTimeZone
723
-     * @param int           $time
724
-     * @return mixed
725
-     * @throws \DomainException
726
-     */
727
-    public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
728
-    {
729
-        $transitions = $this->get_timezone_transitions($DateTimeZone, $time);
730
-        if ( ! isset($transitions['offset'])) {
731
-            throw new DomainException();
732
-        }
733
-        return $transitions['offset'];
734
-    }
735
-
736
-
737
-    /**
738
-     * This will take an incoming timezone string and return the abbreviation for that timezone
739
-     *
740
-     * @param  string $timezone_string
741
-     * @return string           abbreviation
742
-     * @throws \EE_Error
743
-     */
744
-    public function get_timezone_abbrev($timezone_string)
745
-    {
746
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
747
-        $dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
748
-
749
-        return $dateTime->format('T');
750
-    }
751
-
752
-    /**
753
-     * Overrides the parent to allow for having a dynamic "now" value
754
-     *
755
-     * @return mixed
756
-     */
757
-    public function get_default_value()
758
-    {
759
-        if ($this->_default_value === EE_Datetime_Field::now) {
760
-            return time();
761
-        } else {
762
-            return parent::get_default_value();
763
-        }
764
-    }
765
-
766
-
767
-    public function getSchemaDescription()
768
-    {
769
-        return sprintf(
770
-            esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
771
-            $this->get_nicename()
772
-        );
773
-    }
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
+		$time = is_int($time) || $time === null ? $time : strtotime($time);
712
+		$time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
713
+		$transitions = $DateTimeZone->getTransitions($time);
714
+		return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
715
+	}
716
+
717
+
718
+
719
+	/**
720
+	 * get_timezone_offset
721
+	 *
722
+	 * @param \DateTimeZone $DateTimeZone
723
+	 * @param int           $time
724
+	 * @return mixed
725
+	 * @throws \DomainException
726
+	 */
727
+	public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
728
+	{
729
+		$transitions = $this->get_timezone_transitions($DateTimeZone, $time);
730
+		if ( ! isset($transitions['offset'])) {
731
+			throw new DomainException();
732
+		}
733
+		return $transitions['offset'];
734
+	}
735
+
736
+
737
+	/**
738
+	 * This will take an incoming timezone string and return the abbreviation for that timezone
739
+	 *
740
+	 * @param  string $timezone_string
741
+	 * @return string           abbreviation
742
+	 * @throws \EE_Error
743
+	 */
744
+	public function get_timezone_abbrev($timezone_string)
745
+	{
746
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
747
+		$dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
748
+
749
+		return $dateTime->format('T');
750
+	}
751
+
752
+	/**
753
+	 * Overrides the parent to allow for having a dynamic "now" value
754
+	 *
755
+	 * @return mixed
756
+	 */
757
+	public function get_default_value()
758
+	{
759
+		if ($this->_default_value === EE_Datetime_Field::now) {
760
+			return time();
761
+		} else {
762
+			return parent::get_default_value();
763
+		}
764
+	}
765
+
766
+
767
+	public function getSchemaDescription()
768
+	{
769
+		return sprintf(
770
+			esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
771
+			$this->get_nicename()
772
+		);
773
+	}
774 774
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2689 added lines, -2689 removed lines patch added patch discarded remove patch
@@ -15,2696 +15,2696 @@
 block discarded – undo
15 15
 class Events_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17 17
 
18
-    /**
19
-     * This will hold the event object for event_details screen.
20
-     *
21
-     * @access protected
22
-     * @var EE_Event $_event
23
-     */
24
-    protected $_event;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var stdClass $_category
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This will hold the event model instance
37
-     *
38
-     * @var EEM_Event $_event_model
39
-     */
40
-    protected $_event_model;
41
-
42
-
43
-
44
-    /**
45
-     * @var EE_Event
46
-     */
47
-    protected $_cpt_model_obj = false;
48
-
49
-
50
-    /**
51
-     * Initialize page props for this admin page group.
52
-     */
53
-    protected function _init_page_props()
54
-    {
55
-        $this->page_slug = EVENTS_PG_SLUG;
56
-        $this->page_label = EVENTS_LABEL;
57
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
58
-        $this->_admin_base_path = EVENTS_ADMIN;
59
-        $this->_cpt_model_names = array(
60
-            'create_new' => 'EEM_Event',
61
-            'edit'       => 'EEM_Event',
62
-        );
63
-        $this->_cpt_edit_routes = array(
64
-            'espresso_events' => 'edit',
65
-        );
66
-        add_action(
67
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
-            array($this, 'verify_event_edit'), 10, 2
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * Sets the ajax hooks used for this admin page group.
75
-     */
76
-    protected function _ajax_hooks()
77
-    {
78
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
-    }
80
-
81
-
82
-    /**
83
-     * Sets the page properties for this admin page group.
84
-     */
85
-    protected function _define_page_props()
86
-    {
87
-        $this->_admin_page_title = EVENTS_LABEL;
88
-        $this->_labels = array(
89
-            'buttons'      => array(
90
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
91
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
-            ),
97
-            'editor_title' => array(
98
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
-            ),
100
-            'publishbox'   => array(
101
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
103
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
-            ),
107
-        );
108
-    }
109
-
110
-
111
-    /**
112
-     * Sets the page routes property for this admin page group.
113
-     */
114
-    protected function _set_page_routes()
115
-    {
116
-        //load formatter helper
117
-        //load field generator helper
118
-        //is there a evt_id in the request?
119
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
-            ? $this->_req_data['EVT_ID']
121
-            : 0;
122
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
-        $this->_page_routes = array(
124
-            'default'                       => array(
125
-                'func'       => '_events_overview_list_table',
126
-                'capability' => 'ee_read_events',
127
-            ),
128
-            'create_new'                    => array(
129
-                'func'       => '_create_new_cpt_item',
130
-                'capability' => 'ee_edit_events',
131
-            ),
132
-            'edit'                          => array(
133
-                'func'       => '_edit_cpt_item',
134
-                'capability' => 'ee_edit_event',
135
-                'obj_id'     => $evt_id,
136
-            ),
137
-            'copy_event'                    => array(
138
-                'func'       => '_copy_events',
139
-                'capability' => 'ee_edit_event',
140
-                'obj_id'     => $evt_id,
141
-                'noheader'   => true,
142
-            ),
143
-            'trash_event'                   => array(
144
-                'func'       => '_trash_or_restore_event',
145
-                'args'       => array('event_status' => 'trash'),
146
-                'capability' => 'ee_delete_event',
147
-                'obj_id'     => $evt_id,
148
-                'noheader'   => true,
149
-            ),
150
-            'trash_events'                  => array(
151
-                'func'       => '_trash_or_restore_events',
152
-                'args'       => array('event_status' => 'trash'),
153
-                'capability' => 'ee_delete_events',
154
-                'noheader'   => true,
155
-            ),
156
-            'restore_event'                 => array(
157
-                'func'       => '_trash_or_restore_event',
158
-                'args'       => array('event_status' => 'draft'),
159
-                'capability' => 'ee_delete_event',
160
-                'obj_id'     => $evt_id,
161
-                'noheader'   => true,
162
-            ),
163
-            'restore_events'                => array(
164
-                'func'       => '_trash_or_restore_events',
165
-                'args'       => array('event_status' => 'draft'),
166
-                'capability' => 'ee_delete_events',
167
-                'noheader'   => true,
168
-            ),
169
-            'delete_event'                  => array(
170
-                'func'       => '_delete_event',
171
-                'capability' => 'ee_delete_event',
172
-                'obj_id'     => $evt_id,
173
-                'noheader'   => true,
174
-            ),
175
-            'delete_events'                 => array(
176
-                'func'       => '_delete_events',
177
-                'capability' => 'ee_delete_events',
178
-                'noheader'   => true,
179
-            ),
180
-            'view_report'                   => array(
181
-                'func'      => '_view_report',
182
-                'capablity' => 'ee_edit_events',
183
-            ),
184
-            'default_event_settings'        => array(
185
-                'func'       => '_default_event_settings',
186
-                'capability' => 'manage_options',
187
-            ),
188
-            'update_default_event_settings' => array(
189
-                'func'       => '_update_default_event_settings',
190
-                'capability' => 'manage_options',
191
-                'noheader'   => true,
192
-            ),
193
-            'template_settings'             => array(
194
-                'func'       => '_template_settings',
195
-                'capability' => 'manage_options',
196
-            ),
197
-            //event category tab related
198
-            'add_category'                  => array(
199
-                'func'       => '_category_details',
200
-                'capability' => 'ee_edit_event_category',
201
-                'args'       => array('add'),
202
-            ),
203
-            'edit_category'                 => array(
204
-                'func'       => '_category_details',
205
-                'capability' => 'ee_edit_event_category',
206
-                'args'       => array('edit'),
207
-            ),
208
-            'delete_categories'             => array(
209
-                'func'       => '_delete_categories',
210
-                'capability' => 'ee_delete_event_category',
211
-                'noheader'   => true,
212
-            ),
213
-            'delete_category'               => array(
214
-                'func'       => '_delete_categories',
215
-                'capability' => 'ee_delete_event_category',
216
-                'noheader'   => true,
217
-            ),
218
-            'insert_category'               => array(
219
-                'func'       => '_insert_or_update_category',
220
-                'args'       => array('new_category' => true),
221
-                'capability' => 'ee_edit_event_category',
222
-                'noheader'   => true,
223
-            ),
224
-            'update_category'               => array(
225
-                'func'       => '_insert_or_update_category',
226
-                'args'       => array('new_category' => false),
227
-                'capability' => 'ee_edit_event_category',
228
-                'noheader'   => true,
229
-            ),
230
-            'category_list'                 => array(
231
-                'func'       => '_category_list_table',
232
-                'capability' => 'ee_manage_event_categories',
233
-            ),
234
-        );
235
-    }
236
-
237
-
238
-    /**
239
-     * Set the _page_config property for this admin page group.
240
-     */
241
-    protected function _set_page_config()
242
-    {
243
-        $this->_page_config = array(
244
-            'default'                => array(
245
-                'nav'           => array(
246
-                    'label' => esc_html__('Overview', 'event_espresso'),
247
-                    'order' => 10,
248
-                ),
249
-                'list_table'    => 'Events_Admin_List_Table',
250
-                'help_tabs'     => array(
251
-                    'events_overview_help_tab'                       => array(
252
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
253
-                        'filename' => 'events_overview',
254
-                    ),
255
-                    'events_overview_table_column_headings_help_tab' => array(
256
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
-                        'filename' => 'events_overview_table_column_headings',
258
-                    ),
259
-                    'events_overview_filters_help_tab'               => array(
260
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
-                        'filename' => 'events_overview_filters',
262
-                    ),
263
-                    'events_overview_view_help_tab'                  => array(
264
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
-                        'filename' => 'events_overview_views',
266
-                    ),
267
-                    'events_overview_other_help_tab'                 => array(
268
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
-                        'filename' => 'events_overview_other',
270
-                    ),
271
-                ),
272
-                'help_tour'     => array(
273
-                    'Event_Overview_Help_Tour',
274
-                    //'New_Features_Test_Help_Tour' for testing multiple help tour
275
-                ),
276
-                'qtips'         => array(
277
-                    'EE_Event_List_Table_Tips',
278
-                ),
279
-                'require_nonce' => false,
280
-            ),
281
-            'create_new'             => array(
282
-                'nav'           => array(
283
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
284
-                    'order'      => 5,
285
-                    'persistent' => false,
286
-                ),
287
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
-                'help_tabs'     => array(
289
-                    'event_editor_help_tab'                            => array(
290
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
291
-                        'filename' => 'event_editor',
292
-                    ),
293
-                    'event_editor_title_richtexteditor_help_tab'       => array(
294
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
-                        'filename' => 'event_editor_title_richtexteditor',
296
-                    ),
297
-                    'event_editor_venue_details_help_tab'              => array(
298
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
-                        'filename' => 'event_editor_venue_details',
300
-                    ),
301
-                    'event_editor_event_datetimes_help_tab'            => array(
302
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
-                        'filename' => 'event_editor_event_datetimes',
304
-                    ),
305
-                    'event_editor_event_tickets_help_tab'              => array(
306
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
-                        'filename' => 'event_editor_event_tickets',
308
-                    ),
309
-                    'event_editor_event_registration_options_help_tab' => array(
310
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
-                        'filename' => 'event_editor_event_registration_options',
312
-                    ),
313
-                    'event_editor_tags_categories_help_tab'            => array(
314
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
-                        'filename' => 'event_editor_tags_categories',
316
-                    ),
317
-                    'event_editor_questions_registrants_help_tab'      => array(
318
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
-                        'filename' => 'event_editor_questions_registrants',
320
-                    ),
321
-                    'event_editor_save_new_event_help_tab'             => array(
322
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
323
-                        'filename' => 'event_editor_save_new_event',
324
-                    ),
325
-                    'event_editor_other_help_tab'                      => array(
326
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
327
-                        'filename' => 'event_editor_other',
328
-                    ),
329
-                ),
330
-                'help_tour'     => array(
331
-                    'Event_Editor_Help_Tour',
332
-                ),
333
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
-                'require_nonce' => false,
335
-            ),
336
-            'edit'                   => array(
337
-                'nav'           => array(
338
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
339
-                    'order'      => 5,
340
-                    'persistent' => false,
341
-                    'url'        => isset($this->_req_data['post'])
342
-                        ? EE_Admin_Page::add_query_args_and_nonce(
343
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
-                            $this->_current_page_view_url
345
-                        )
346
-                        : $this->_admin_base_url,
347
-                ),
348
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
-                'help_tabs'     => array(
350
-                    'event_editor_help_tab'                            => array(
351
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
352
-                        'filename' => 'event_editor',
353
-                    ),
354
-                    'event_editor_title_richtexteditor_help_tab'       => array(
355
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
-                        'filename' => 'event_editor_title_richtexteditor',
357
-                    ),
358
-                    'event_editor_venue_details_help_tab'              => array(
359
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
-                        'filename' => 'event_editor_venue_details',
361
-                    ),
362
-                    'event_editor_event_datetimes_help_tab'            => array(
363
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
-                        'filename' => 'event_editor_event_datetimes',
365
-                    ),
366
-                    'event_editor_event_tickets_help_tab'              => array(
367
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
-                        'filename' => 'event_editor_event_tickets',
369
-                    ),
370
-                    'event_editor_event_registration_options_help_tab' => array(
371
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_registration_options',
373
-                    ),
374
-                    'event_editor_tags_categories_help_tab'            => array(
375
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
-                        'filename' => 'event_editor_tags_categories',
377
-                    ),
378
-                    'event_editor_questions_registrants_help_tab'      => array(
379
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
-                        'filename' => 'event_editor_questions_registrants',
381
-                    ),
382
-                    'event_editor_save_new_event_help_tab'             => array(
383
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
384
-                        'filename' => 'event_editor_save_new_event',
385
-                    ),
386
-                    'event_editor_other_help_tab'                      => array(
387
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
388
-                        'filename' => 'event_editor_other',
389
-                    ),
390
-                ),
391
-                /*'help_tour' => array(
18
+	/**
19
+	 * This will hold the event object for event_details screen.
20
+	 *
21
+	 * @access protected
22
+	 * @var EE_Event $_event
23
+	 */
24
+	protected $_event;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var stdClass $_category
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This will hold the event model instance
37
+	 *
38
+	 * @var EEM_Event $_event_model
39
+	 */
40
+	protected $_event_model;
41
+
42
+
43
+
44
+	/**
45
+	 * @var EE_Event
46
+	 */
47
+	protected $_cpt_model_obj = false;
48
+
49
+
50
+	/**
51
+	 * Initialize page props for this admin page group.
52
+	 */
53
+	protected function _init_page_props()
54
+	{
55
+		$this->page_slug = EVENTS_PG_SLUG;
56
+		$this->page_label = EVENTS_LABEL;
57
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
58
+		$this->_admin_base_path = EVENTS_ADMIN;
59
+		$this->_cpt_model_names = array(
60
+			'create_new' => 'EEM_Event',
61
+			'edit'       => 'EEM_Event',
62
+		);
63
+		$this->_cpt_edit_routes = array(
64
+			'espresso_events' => 'edit',
65
+		);
66
+		add_action(
67
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
+			array($this, 'verify_event_edit'), 10, 2
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * Sets the ajax hooks used for this admin page group.
75
+	 */
76
+	protected function _ajax_hooks()
77
+	{
78
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
+	}
80
+
81
+
82
+	/**
83
+	 * Sets the page properties for this admin page group.
84
+	 */
85
+	protected function _define_page_props()
86
+	{
87
+		$this->_admin_page_title = EVENTS_LABEL;
88
+		$this->_labels = array(
89
+			'buttons'      => array(
90
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
91
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
+			),
97
+			'editor_title' => array(
98
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
+			),
100
+			'publishbox'   => array(
101
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
103
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
+			),
107
+		);
108
+	}
109
+
110
+
111
+	/**
112
+	 * Sets the page routes property for this admin page group.
113
+	 */
114
+	protected function _set_page_routes()
115
+	{
116
+		//load formatter helper
117
+		//load field generator helper
118
+		//is there a evt_id in the request?
119
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
+			? $this->_req_data['EVT_ID']
121
+			: 0;
122
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
+		$this->_page_routes = array(
124
+			'default'                       => array(
125
+				'func'       => '_events_overview_list_table',
126
+				'capability' => 'ee_read_events',
127
+			),
128
+			'create_new'                    => array(
129
+				'func'       => '_create_new_cpt_item',
130
+				'capability' => 'ee_edit_events',
131
+			),
132
+			'edit'                          => array(
133
+				'func'       => '_edit_cpt_item',
134
+				'capability' => 'ee_edit_event',
135
+				'obj_id'     => $evt_id,
136
+			),
137
+			'copy_event'                    => array(
138
+				'func'       => '_copy_events',
139
+				'capability' => 'ee_edit_event',
140
+				'obj_id'     => $evt_id,
141
+				'noheader'   => true,
142
+			),
143
+			'trash_event'                   => array(
144
+				'func'       => '_trash_or_restore_event',
145
+				'args'       => array('event_status' => 'trash'),
146
+				'capability' => 'ee_delete_event',
147
+				'obj_id'     => $evt_id,
148
+				'noheader'   => true,
149
+			),
150
+			'trash_events'                  => array(
151
+				'func'       => '_trash_or_restore_events',
152
+				'args'       => array('event_status' => 'trash'),
153
+				'capability' => 'ee_delete_events',
154
+				'noheader'   => true,
155
+			),
156
+			'restore_event'                 => array(
157
+				'func'       => '_trash_or_restore_event',
158
+				'args'       => array('event_status' => 'draft'),
159
+				'capability' => 'ee_delete_event',
160
+				'obj_id'     => $evt_id,
161
+				'noheader'   => true,
162
+			),
163
+			'restore_events'                => array(
164
+				'func'       => '_trash_or_restore_events',
165
+				'args'       => array('event_status' => 'draft'),
166
+				'capability' => 'ee_delete_events',
167
+				'noheader'   => true,
168
+			),
169
+			'delete_event'                  => array(
170
+				'func'       => '_delete_event',
171
+				'capability' => 'ee_delete_event',
172
+				'obj_id'     => $evt_id,
173
+				'noheader'   => true,
174
+			),
175
+			'delete_events'                 => array(
176
+				'func'       => '_delete_events',
177
+				'capability' => 'ee_delete_events',
178
+				'noheader'   => true,
179
+			),
180
+			'view_report'                   => array(
181
+				'func'      => '_view_report',
182
+				'capablity' => 'ee_edit_events',
183
+			),
184
+			'default_event_settings'        => array(
185
+				'func'       => '_default_event_settings',
186
+				'capability' => 'manage_options',
187
+			),
188
+			'update_default_event_settings' => array(
189
+				'func'       => '_update_default_event_settings',
190
+				'capability' => 'manage_options',
191
+				'noheader'   => true,
192
+			),
193
+			'template_settings'             => array(
194
+				'func'       => '_template_settings',
195
+				'capability' => 'manage_options',
196
+			),
197
+			//event category tab related
198
+			'add_category'                  => array(
199
+				'func'       => '_category_details',
200
+				'capability' => 'ee_edit_event_category',
201
+				'args'       => array('add'),
202
+			),
203
+			'edit_category'                 => array(
204
+				'func'       => '_category_details',
205
+				'capability' => 'ee_edit_event_category',
206
+				'args'       => array('edit'),
207
+			),
208
+			'delete_categories'             => array(
209
+				'func'       => '_delete_categories',
210
+				'capability' => 'ee_delete_event_category',
211
+				'noheader'   => true,
212
+			),
213
+			'delete_category'               => array(
214
+				'func'       => '_delete_categories',
215
+				'capability' => 'ee_delete_event_category',
216
+				'noheader'   => true,
217
+			),
218
+			'insert_category'               => array(
219
+				'func'       => '_insert_or_update_category',
220
+				'args'       => array('new_category' => true),
221
+				'capability' => 'ee_edit_event_category',
222
+				'noheader'   => true,
223
+			),
224
+			'update_category'               => array(
225
+				'func'       => '_insert_or_update_category',
226
+				'args'       => array('new_category' => false),
227
+				'capability' => 'ee_edit_event_category',
228
+				'noheader'   => true,
229
+			),
230
+			'category_list'                 => array(
231
+				'func'       => '_category_list_table',
232
+				'capability' => 'ee_manage_event_categories',
233
+			),
234
+		);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Set the _page_config property for this admin page group.
240
+	 */
241
+	protected function _set_page_config()
242
+	{
243
+		$this->_page_config = array(
244
+			'default'                => array(
245
+				'nav'           => array(
246
+					'label' => esc_html__('Overview', 'event_espresso'),
247
+					'order' => 10,
248
+				),
249
+				'list_table'    => 'Events_Admin_List_Table',
250
+				'help_tabs'     => array(
251
+					'events_overview_help_tab'                       => array(
252
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
253
+						'filename' => 'events_overview',
254
+					),
255
+					'events_overview_table_column_headings_help_tab' => array(
256
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
+						'filename' => 'events_overview_table_column_headings',
258
+					),
259
+					'events_overview_filters_help_tab'               => array(
260
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
+						'filename' => 'events_overview_filters',
262
+					),
263
+					'events_overview_view_help_tab'                  => array(
264
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
+						'filename' => 'events_overview_views',
266
+					),
267
+					'events_overview_other_help_tab'                 => array(
268
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
+						'filename' => 'events_overview_other',
270
+					),
271
+				),
272
+				'help_tour'     => array(
273
+					'Event_Overview_Help_Tour',
274
+					//'New_Features_Test_Help_Tour' for testing multiple help tour
275
+				),
276
+				'qtips'         => array(
277
+					'EE_Event_List_Table_Tips',
278
+				),
279
+				'require_nonce' => false,
280
+			),
281
+			'create_new'             => array(
282
+				'nav'           => array(
283
+					'label'      => esc_html__('Add Event', 'event_espresso'),
284
+					'order'      => 5,
285
+					'persistent' => false,
286
+				),
287
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
+				'help_tabs'     => array(
289
+					'event_editor_help_tab'                            => array(
290
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
291
+						'filename' => 'event_editor',
292
+					),
293
+					'event_editor_title_richtexteditor_help_tab'       => array(
294
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
+						'filename' => 'event_editor_title_richtexteditor',
296
+					),
297
+					'event_editor_venue_details_help_tab'              => array(
298
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
+						'filename' => 'event_editor_venue_details',
300
+					),
301
+					'event_editor_event_datetimes_help_tab'            => array(
302
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
+						'filename' => 'event_editor_event_datetimes',
304
+					),
305
+					'event_editor_event_tickets_help_tab'              => array(
306
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
+						'filename' => 'event_editor_event_tickets',
308
+					),
309
+					'event_editor_event_registration_options_help_tab' => array(
310
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
+						'filename' => 'event_editor_event_registration_options',
312
+					),
313
+					'event_editor_tags_categories_help_tab'            => array(
314
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
+						'filename' => 'event_editor_tags_categories',
316
+					),
317
+					'event_editor_questions_registrants_help_tab'      => array(
318
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
+						'filename' => 'event_editor_questions_registrants',
320
+					),
321
+					'event_editor_save_new_event_help_tab'             => array(
322
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
323
+						'filename' => 'event_editor_save_new_event',
324
+					),
325
+					'event_editor_other_help_tab'                      => array(
326
+						'title'    => esc_html__('Event Other', 'event_espresso'),
327
+						'filename' => 'event_editor_other',
328
+					),
329
+				),
330
+				'help_tour'     => array(
331
+					'Event_Editor_Help_Tour',
332
+				),
333
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
+				'require_nonce' => false,
335
+			),
336
+			'edit'                   => array(
337
+				'nav'           => array(
338
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
339
+					'order'      => 5,
340
+					'persistent' => false,
341
+					'url'        => isset($this->_req_data['post'])
342
+						? EE_Admin_Page::add_query_args_and_nonce(
343
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
+							$this->_current_page_view_url
345
+						)
346
+						: $this->_admin_base_url,
347
+				),
348
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
+				'help_tabs'     => array(
350
+					'event_editor_help_tab'                            => array(
351
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
352
+						'filename' => 'event_editor',
353
+					),
354
+					'event_editor_title_richtexteditor_help_tab'       => array(
355
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
+						'filename' => 'event_editor_title_richtexteditor',
357
+					),
358
+					'event_editor_venue_details_help_tab'              => array(
359
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
+						'filename' => 'event_editor_venue_details',
361
+					),
362
+					'event_editor_event_datetimes_help_tab'            => array(
363
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
+						'filename' => 'event_editor_event_datetimes',
365
+					),
366
+					'event_editor_event_tickets_help_tab'              => array(
367
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
+						'filename' => 'event_editor_event_tickets',
369
+					),
370
+					'event_editor_event_registration_options_help_tab' => array(
371
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
+						'filename' => 'event_editor_event_registration_options',
373
+					),
374
+					'event_editor_tags_categories_help_tab'            => array(
375
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
+						'filename' => 'event_editor_tags_categories',
377
+					),
378
+					'event_editor_questions_registrants_help_tab'      => array(
379
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
+						'filename' => 'event_editor_questions_registrants',
381
+					),
382
+					'event_editor_save_new_event_help_tab'             => array(
383
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
384
+						'filename' => 'event_editor_save_new_event',
385
+					),
386
+					'event_editor_other_help_tab'                      => array(
387
+						'title'    => esc_html__('Event Other', 'event_espresso'),
388
+						'filename' => 'event_editor_other',
389
+					),
390
+				),
391
+				/*'help_tour' => array(
392 392
 					'Event_Edit_Help_Tour'
393 393
 				),*/
394
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
-                'require_nonce' => false,
396
-            ),
397
-            'default_event_settings' => array(
398
-                'nav'           => array(
399
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
400
-                    'order' => 40,
401
-                ),
402
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
-                'labels'        => array(
404
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
-                ),
406
-                'help_tabs'     => array(
407
-                    'default_settings_help_tab'        => array(
408
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
-                        'filename' => 'events_default_settings',
410
-                    ),
411
-                    'default_settings_status_help_tab' => array(
412
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
-                        'filename' => 'events_default_settings_status',
414
-                    ),
415
-                    'default_maximum_tickets_help_tab' => array(
416
-                        'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
-                        'filename' => 'events_default_settings_max_tickets',
418
-                    )
419
-                ),
420
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
-                'require_nonce' => false,
422
-            ),
423
-            //template settings
424
-            'template_settings'      => array(
425
-                'nav'           => array(
426
-                    'label' => esc_html__('Templates', 'event_espresso'),
427
-                    'order' => 30,
428
-                ),
429
-                'metaboxes'     => $this->_default_espresso_metaboxes,
430
-                'help_tabs'     => array(
431
-                    'general_settings_templates_help_tab' => array(
432
-                        'title'    => esc_html__('Templates', 'event_espresso'),
433
-                        'filename' => 'general_settings_templates',
434
-                    ),
435
-                ),
436
-                'help_tour'     => array('Templates_Help_Tour'),
437
-                'require_nonce' => false,
438
-            ),
439
-            //event category stuff
440
-            'add_category'           => array(
441
-                'nav'           => array(
442
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
443
-                    'order'      => 15,
444
-                    'persistent' => false,
445
-                ),
446
-                'help_tabs'     => array(
447
-                    'add_category_help_tab' => array(
448
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
-                        'filename' => 'events_add_category',
450
-                    ),
451
-                ),
452
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
-                'metaboxes'     => array('_publish_post_box'),
454
-                'require_nonce' => false,
455
-            ),
456
-            'edit_category'          => array(
457
-                'nav'           => array(
458
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
459
-                    'order'      => 15,
460
-                    'persistent' => false,
461
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
-                        ? add_query_arg(
463
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
-                            $this->_current_page_view_url
465
-                        )
466
-                        : $this->_admin_base_url,
467
-                ),
468
-                'help_tabs'     => array(
469
-                    'edit_category_help_tab' => array(
470
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
-                        'filename' => 'events_edit_category',
472
-                    ),
473
-                ),
474
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
-                'metaboxes'     => array('_publish_post_box'),
476
-                'require_nonce' => false,
477
-            ),
478
-            'category_list'          => array(
479
-                'nav'           => array(
480
-                    'label' => esc_html__('Categories', 'event_espresso'),
481
-                    'order' => 20,
482
-                ),
483
-                'list_table'    => 'Event_Categories_Admin_List_Table',
484
-                'help_tabs'     => array(
485
-                    'events_categories_help_tab'                       => array(
486
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
487
-                        'filename' => 'events_categories',
488
-                    ),
489
-                    'events_categories_table_column_headings_help_tab' => array(
490
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
-                        'filename' => 'events_categories_table_column_headings',
492
-                    ),
493
-                    'events_categories_view_help_tab'                  => array(
494
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
-                        'filename' => 'events_categories_views',
496
-                    ),
497
-                    'events_categories_other_help_tab'                 => array(
498
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
-                        'filename' => 'events_categories_other',
500
-                    ),
501
-                ),
502
-                'help_tour'     => array(
503
-                    'Event_Categories_Help_Tour',
504
-                ),
505
-                'metaboxes'     => $this->_default_espresso_metaboxes,
506
-                'require_nonce' => false,
507
-            ),
508
-        );
509
-    }
510
-
511
-
512
-    /**
513
-     * Used to register any global screen options if necessary for every route in this admin page group.
514
-     */
515
-    protected function _add_screen_options()
516
-    {
517
-    }
518
-
519
-
520
-    /**
521
-     * Implementing the screen options for the 'default' route.
522
-     */
523
-    protected function _add_screen_options_default()
524
-    {
525
-        $this->_per_page_screen_option();
526
-    }
527
-
528
-
529
-    /**
530
-     * Implementing screen options for the category list route.
531
-     */
532
-    protected function _add_screen_options_category_list()
533
-    {
534
-        $page_title = $this->_admin_page_title;
535
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
-        $this->_per_page_screen_option();
537
-        $this->_admin_page_title = $page_title;
538
-    }
539
-
540
-
541
-    /**
542
-     * Used to register any global feature pointers for the admin page group.
543
-     */
544
-    protected function _add_feature_pointers()
545
-    {
546
-    }
547
-
548
-
549
-    /**
550
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
551
-     */
552
-    public function load_scripts_styles()
553
-    {
554
-        wp_register_style(
555
-            'events-admin-css',
556
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
557
-            array(),
558
-            EVENT_ESPRESSO_VERSION
559
-        );
560
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
-        wp_enqueue_style('events-admin-css');
562
-        wp_enqueue_style('ee-cat-admin');
563
-        //todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
-        //registers for all views
565
-        //scripts
566
-        wp_register_script(
567
-            'event_editor_js',
568
-            EVENTS_ASSETS_URL . 'event_editor.js',
569
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
-            EVENT_ESPRESSO_VERSION,
571
-            true
572
-        );
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * Enqueuing scripts and styles specific to this view
579
-     */
580
-    public function load_scripts_styles_create_new()
581
-    {
582
-        $this->load_scripts_styles_edit();
583
-    }
584
-
585
-
586
-
587
-    /**
588
-     * Enqueuing scripts and styles specific to this view
589
-     */
590
-    public function load_scripts_styles_edit()
591
-    {
592
-        //styles
593
-        wp_enqueue_style('espresso-ui-theme');
594
-        wp_register_style(
595
-            'event-editor-css',
596
-            EVENTS_ASSETS_URL . 'event-editor.css',
597
-            array('ee-admin-css'),
598
-            EVENT_ESPRESSO_VERSION
599
-        );
600
-        wp_enqueue_style('event-editor-css');
601
-        //scripts
602
-        wp_register_script(
603
-            'event-datetime-metabox',
604
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
-            array('event_editor_js', 'ee-datepicker'),
606
-            EVENT_ESPRESSO_VERSION
607
-        );
608
-        wp_enqueue_script('event-datetime-metabox');
609
-    }
610
-
611
-
612
-    /**
613
-     * Populating the _views property for the category list table view.
614
-     */
615
-    protected function _set_list_table_views_category_list()
616
-    {
617
-        $this->_views = array(
618
-            'all' => array(
619
-                'slug'        => 'all',
620
-                'label'       => esc_html__('All', 'event_espresso'),
621
-                'count'       => 0,
622
-                'bulk_action' => array(
623
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
-                ),
625
-            ),
626
-        );
627
-    }
628
-
629
-
630
-    /**
631
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
-     */
633
-    public function admin_init()
634
-    {
635
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
-            'event_espresso'
638
-        );
639
-    }
640
-
641
-
642
-    /**
643
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page group.
644
-     */
645
-    public function admin_notices()
646
-    {
647
-    }
648
-
649
-
650
-    /**
651
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
-     * this admin page group.
653
-     */
654
-    public function admin_footer_scripts()
655
-    {
656
-    }
657
-
658
-
659
-
660
-    /**
661
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
-     * warning (via EE_Error::add_error());
663
-     *
664
-     * @param  EE_Event $event Event object
665
-     * @param string    $req_type
666
-     * @return void
667
-     * @throws EE_Error
668
-     * @access public
669
-     */
670
-    public function verify_event_edit($event = null, $req_type = '')
671
-    {
672
-        // don't need to do this when processing
673
-        if(!empty($req_type)) {
674
-            return;
675
-        }
676
-        // no event?
677
-        if (empty($event)) {
678
-            // set event
679
-            $event = $this->_cpt_model_obj;
680
-        }
681
-        // STILL no event?
682
-        if (! $event instanceof EE_Event) {
683
-            return;
684
-        }
685
-        $orig_status = $event->status();
686
-        // first check if event is active.
687
-        if (
688
-            $orig_status === EEM_Event::cancelled
689
-            || $orig_status === EEM_Event::postponed
690
-            || $event->is_expired()
691
-            || $event->is_inactive()
692
-        ) {
693
-            return;
694
-        }
695
-        //made it here so it IS active... next check that any of the tickets are sold.
696
-        if ($event->is_sold_out(true)) {
697
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
-                EE_Error::add_attention(
699
-                    sprintf(
700
-                        esc_html__(
701
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
702
-                            'event_espresso'
703
-                        ),
704
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
-                    )
706
-                );
707
-            }
708
-            return;
709
-        } else if ($orig_status === EEM_Event::sold_out) {
710
-            EE_Error::add_attention(
711
-                sprintf(
712
-                    esc_html__(
713
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
714
-                        'event_espresso'
715
-                    ),
716
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
717
-                )
718
-            );
719
-        }
720
-        //now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
-        if ( ! $event->tickets_on_sale()) {
722
-            return;
723
-        }
724
-        //made it here so show warning
725
-        $this->_edit_event_warning();
726
-    }
727
-
728
-
729
-
730
-    /**
731
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
732
-     * When needed, hook this into a EE_Error::add_error() notice.
733
-     *
734
-     * @access protected
735
-     * @return void
736
-     */
737
-    protected function _edit_event_warning()
738
-    {
739
-        // we don't want to add warnings during these requests
740
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
-            return;
742
-        }
743
-        EE_Error::add_attention(
744
-            esc_html__(
745
-                'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
-                'event_espresso'
747
-            )
748
-        );
749
-    }
750
-
751
-
752
-
753
-    /**
754
-     * When a user is creating a new event, notify them if they haven't set their timezone.
755
-     * Otherwise, do the normal logic
756
-     *
757
-     * @return string
758
-     * @throws \EE_Error
759
-     */
760
-    protected function _create_new_cpt_item()
761
-    {
762
-        $has_timezone_string = get_option('timezone_string');
763
-        //only nag them about setting their timezone if it's their first event, and they haven't already done it
764
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
-            EE_Error::add_attention(
766
-                sprintf(
767
-                    __(
768
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
-                        'event_espresso'
770
-                    ),
771
-                    '<br>',
772
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
-                    . '</select>',
775
-                    '<button class="button button-secondary timezone-submit">',
776
-                    '</button><span class="spinner"></span>'
777
-                ),
778
-                __FILE__,
779
-                __FUNCTION__,
780
-                __LINE__
781
-            );
782
-        }
783
-        return parent::_create_new_cpt_item();
784
-    }
785
-
786
-
787
-    /**
788
-     * Sets the _views property for the default route in this admin page group.
789
-     */
790
-    protected function _set_list_table_views_default()
791
-    {
792
-        $this->_views = array(
793
-            'all'   => array(
794
-                'slug'        => 'all',
795
-                'label'       => esc_html__('View All Events', 'event_espresso'),
796
-                'count'       => 0,
797
-                'bulk_action' => array(
798
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
-                ),
800
-            ),
801
-            'draft' => array(
802
-                'slug'        => 'draft',
803
-                'label'       => esc_html__('Draft', 'event_espresso'),
804
-                'count'       => 0,
805
-                'bulk_action' => array(
806
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
-                ),
808
-            ),
809
-        );
810
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
-            $this->_views['trash'] = array(
812
-                'slug'        => 'trash',
813
-                'label'       => esc_html__('Trash', 'event_espresso'),
814
-                'count'       => 0,
815
-                'bulk_action' => array(
816
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
-                ),
819
-            );
820
-        }
821
-    }
822
-
823
-
824
-
825
-    /**
826
-     * Provides the legend item array for the default list table view.
827
-     * @return array
828
-     */
829
-    protected function _event_legend_items()
830
-    {
831
-        $items = array(
832
-            'view_details'   => array(
833
-                'class' => 'dashicons dashicons-search',
834
-                'desc'  => esc_html__('View Event', 'event_espresso'),
835
-            ),
836
-            'edit_event'     => array(
837
-                'class' => 'ee-icon ee-icon-calendar-edit',
838
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
-            ),
840
-            'view_attendees' => array(
841
-                'class' => 'dashicons dashicons-groups',
842
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
-            ),
844
-        );
845
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
-        $statuses = array(
847
-            'sold_out_status'  => array(
848
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
-            ),
851
-            'active_status'    => array(
852
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
-            ),
855
-            'upcoming_status'  => array(
856
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
-            ),
859
-            'postponed_status' => array(
860
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
-            ),
863
-            'cancelled_status' => array(
864
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
-            ),
867
-            'expired_status'   => array(
868
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
-            ),
871
-            'inactive_status'  => array(
872
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
-            ),
875
-        );
876
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
-        return array_merge($items, $statuses);
878
-    }
879
-
880
-
881
-
882
-    /**
883
-     * @return EEM_Event
884
-     */
885
-    private function _event_model()
886
-    {
887
-        if ( ! $this->_event_model instanceof EEM_Event) {
888
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
889
-        }
890
-        return $this->_event_model;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * Adds extra buttons to the WP CPT permalink field row.
897
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
-     *
899
-     * @param  string $return    the current html
900
-     * @param  int    $id        the post id for the page
901
-     * @param  string $new_title What the title is
902
-     * @param  string $new_slug  what the slug is
903
-     * @return string            The new html string for the permalink area
904
-     */
905
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
-    {
907
-        //make sure this is only when editing
908
-        if ( ! empty($id)) {
909
-            $post = get_post($id);
910
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
-                       . esc_html__('Shortcode', 'event_espresso')
912
-                       . '</a> ';
913
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
-                       . $post->ID
915
-                       . ']">';
916
-        }
917
-        return $return;
918
-    }
919
-
920
-
921
-
922
-    /**
923
-     * _events_overview_list_table
924
-     * This contains the logic for showing the events_overview list
925
-     *
926
-     * @access protected
927
-     * @return void
928
-     * @throws \EE_Error
929
-     */
930
-    protected function _events_overview_list_table()
931
-    {
932
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
-            ? (array)$this->_template_args['after_list_table']
935
-            : array();
936
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
-                                                                              . EEH_Template::get_button_or_link(
938
-                get_post_type_archive_link('espresso_events'),
939
-                esc_html__("View Event Archive Page", "event_espresso"),
940
-                'button'
941
-            );
942
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
-                'create_new',
945
-                'add',
946
-                array(),
947
-                'add-new-h2'
948
-            );
949
-        $this->display_admin_list_table_page_with_no_sidebar();
950
-    }
951
-
952
-
953
-
954
-    /**
955
-     * this allows for extra misc actions in the default WP publish box
956
-     *
957
-     * @return void
958
-     */
959
-    public function extra_misc_actions_publish_box()
960
-    {
961
-        $this->_generate_publish_box_extra_content();
962
-    }
963
-
964
-
965
-
966
-    /**
967
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
-     * Typically you would use this to save any additional data.
969
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
-     * ALSO very important.  When a post transitions from scheduled to published,
971
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
-     * So MAKE sure that you handle this accordingly.
973
-     *
974
-     * @access protected
975
-     * @abstract
976
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
-     * @param  object $post    The post object of the cpt that was saved.
978
-     * @return void
979
-     * @throws \EE_Error
980
-     */
981
-    protected function _insert_update_cpt_item($post_id, $post)
982
-    {
983
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
-            //get out we're not processing an event save.
985
-            return;
986
-        }
987
-        $event_values = array(
988
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
-            'EVT_additional_limit'            => min(
991
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
-            ),
994
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
-                ? $this->_req_data['EVT_default_registration_status']
996
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
997
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
-                ? $this->_req_data['timezone_string'] : null,
1001
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
-                ? $this->_req_data['externalURL'] : null,
1003
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
-                ? $this->_req_data['event_phone'] : null,
1005
-        );
1006
-        //update event
1007
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
-        //get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1009
-        $get_one_where = array(
1010
-            $this->_event_model()->primary_key_name() => $post_id,
1011
-            'OR' => array(
1012
-                'status' => $post->post_status,
1013
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
-                // but the returned object here has a status of "publish", so use the original post status as well
1015
-                'status*1' => $this->_req_data['original_post_status'],
1016
-            )
1017
-        );
1018
-        $event = $this->_event_model()->get_one(array($get_one_where));
1019
-        //the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
-        $event_update_callbacks = apply_filters(
1021
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
-            array(
1023
-                array($this, '_default_venue_update'),
1024
-                array($this, '_default_tickets_update')
1025
-            )
1026
-        );
1027
-        $att_success = true;
1028
-        foreach ($event_update_callbacks as $e_callback) {
1029
-            $_success = is_callable($e_callback)
1030
-                ? call_user_func($e_callback, $event, $this->_req_data)
1031
-                : false;
1032
-            //if ANY of these updates fail then we want the appropriate global error message
1033
-            $att_success = ! $att_success ? $att_success : $_success;
1034
-        }
1035
-        //any errors?
1036
-        if ($success && false === $att_success) {
1037
-            EE_Error::add_error(
1038
-                esc_html__(
1039
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1040
-                    'event_espresso'
1041
-                ),
1042
-                __FILE__,
1043
-                __FUNCTION__,
1044
-                __LINE__
1045
-            );
1046
-        } else if ($success === false) {
1047
-            EE_Error::add_error(
1048
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
-                __FILE__,
1050
-                __FUNCTION__,
1051
-                __LINE__
1052
-            );
1053
-        }
1054
-    }
1055
-
1056
-
1057
-
1058
-    /**
1059
-     * @see parent::restore_item()
1060
-     * @param int $post_id
1061
-     * @param int $revision_id
1062
-     */
1063
-    protected function _restore_cpt_item($post_id, $revision_id)
1064
-    {
1065
-        //copy existing event meta to new post
1066
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
-        if ($post_evt instanceof EE_Event) {
1068
-            //meta revision restore
1069
-            $post_evt->restore_revision($revision_id);
1070
-            //related objs restore
1071
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
-        }
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * Attach the venue to the Event
1079
-     *
1080
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1081
-     * @param  array     $data   The request data from the form
1082
-     * @return bool           Success or fail.
1083
-     */
1084
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
-    {
1086
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1088
-        $rows_affected = null;
1089
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
-        // very important.  If we don't have a venue name...
1091
-        // then we'll get out because not necessary to create empty venue
1092
-        if (empty($data['venue_title'])) {
1093
-            return false;
1094
-        }
1095
-        $venue_array = array(
1096
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
-                : null,
1102
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
-            'status'              => 'publish',
1115
-        );
1116
-        //if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
-        if ( ! empty($venue_id)) {
1118
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1119
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1120
-            //we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1121
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1122
-            return $rows_affected > 0 ? true : false;
1123
-        } else {
1124
-            //we insert the venue
1125
-            $venue_id = $venue_model->insert($venue_array);
1126
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1127
-            return ! empty($venue_id) ? true : false;
1128
-        }
1129
-        //when we have the ancestor come in it's already been handled by the revision save.
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
-     *
1137
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1138
-     * @param  array    $data   The request data from the form
1139
-     * @return array
1140
-     */
1141
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
-    {
1143
-        $success = true;
1144
-        $saved_dtt = null;
1145
-        $saved_tickets = array();
1146
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1147
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
-            //trim all values to ensure any excess whitespace is removed.
1149
-            $dtt = array_map('trim', $dtt);
1150
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
-                : $dtt['DTT_EVT_start'];
1152
-            $datetime_values = array(
1153
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
-                'DTT_order'     => $row,
1158
-            );
1159
-            //if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1160
-            if ( ! empty($dtt['DTT_ID'])) {
1161
-                $DTM = EE_Registry::instance()
1162
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1164
-                $DTM->set_date_format($incoming_date_formats[0]);
1165
-                $DTM->set_time_format($incoming_date_formats[1]);
1166
-                foreach ($datetime_values as $field => $value) {
1167
-                    $DTM->set($field, $value);
1168
-                }
1169
-                //make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1170
-                $saved_dtts[$DTM->ID()] = $DTM;
1171
-            } else {
1172
-                $DTM = EE_Registry::instance()->load_class(
1173
-                    'Datetime',
1174
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
-                    false,
1176
-                    false
1177
-                );
1178
-                foreach ($datetime_values as $field => $value) {
1179
-                    $DTM->set($field, $value);
1180
-                }
1181
-            }
1182
-            $DTM->save();
1183
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
-            //load DTT helper
1185
-            //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1186
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
-                $DTT->save();
1190
-            }
1191
-            //now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1192
-            $saved_dtt = $DTT;
1193
-            $success = ! $success ? $success : $DTT;
1194
-            //if ANY of these updates fail then we want the appropriate global error message.
1195
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1196
-        }
1197
-        //no dtts get deleted so we don't do any of that logic here.
1198
-        //update tickets next
1199
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1201
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1202
-            $update_prices = false;
1203
-            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
-                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
-            // trim inputs to ensure any excess whitespace is removed.
1206
-            $tkt = array_map('trim', $tkt);
1207
-            if (empty($tkt['TKT_start_date'])) {
1208
-                //let's use now in the set timezone.
1209
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
-            }
1212
-            if (empty($tkt['TKT_end_date'])) {
1213
-                //use the start date of the first datetime
1214
-                $dtt = $evtobj->first_datetime();
1215
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
-                    $incoming_date_formats[0],
1217
-                    $incoming_date_formats[1]
1218
-                );
1219
-            }
1220
-            $TKT_values = array(
1221
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1226
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1227
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
-                'TKT_row'         => $row,
1232
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
-                'TKT_price'       => $ticket_price,
1234
-            );
1235
-            //if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1236
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
-                $TKT_values['TKT_ID'] = 0;
1238
-                $TKT_values['TKT_is_default'] = 0;
1239
-                $TKT_values['TKT_price'] = $ticket_price;
1240
-                $update_prices = true;
1241
-            }
1242
-            //if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
-            //we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1244
-            //keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1245
-            if ( ! empty($tkt['TKT_ID'])) {
1246
-                $TKT = EE_Registry::instance()
1247
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1249
-                if ($TKT instanceof EE_Ticket) {
1250
-                    $ticket_sold = $TKT->count_related(
1251
-                        'Registration',
1252
-                        array(
1253
-                            array(
1254
-                                'STS_ID' => array(
1255
-                                    'NOT IN',
1256
-                                    array(EEM_Registration::status_id_incomplete),
1257
-                                ),
1258
-                            ),
1259
-                        )
1260
-                    ) > 0 ? true : false;
1261
-                    //let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1262
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
-                                      && ! $TKT->get(
1264
-                        'TKT_deleted'
1265
-                    ) ? true : false;
1266
-                    $TKT->set_date_format($incoming_date_formats[0]);
1267
-                    $TKT->set_time_format($incoming_date_formats[1]);
1268
-                    //set new values
1269
-                    foreach ($TKT_values as $field => $value) {
1270
-                        if ($field == 'TKT_qty') {
1271
-                            $TKT->set_qty($value);
1272
-                        } else {
1273
-                            $TKT->set($field, $value);
1274
-                        }
1275
-                    }
1276
-                    //if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
-                    if ($create_new_TKT) {
1278
-                        //archive the old ticket first
1279
-                        $TKT->set('TKT_deleted', 1);
1280
-                        $TKT->save();
1281
-                        //make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
-                        $saved_tickets[$TKT->ID()] = $TKT;
1283
-                        //create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1284
-                        $TKT = clone $TKT;
1285
-                        $TKT->set('TKT_ID', 0);
1286
-                        $TKT->set('TKT_deleted', 0);
1287
-                        $TKT->set('TKT_price', $ticket_price);
1288
-                        $TKT->set('TKT_sold', 0);
1289
-                        //now we need to make sure that $new prices are created as well and attached to new ticket.
1290
-                        $update_prices = true;
1291
-                    }
1292
-                    //make sure price is set if it hasn't been already
1293
-                    $TKT->set('TKT_price', $ticket_price);
1294
-                }
1295
-            } else {
1296
-                //no TKT_id so a new TKT
1297
-                $TKT_values['TKT_price'] = $ticket_price;
1298
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
-                if ($TKT instanceof EE_Ticket) {
1300
-                    //need to reset values to properly account for the date formats
1301
-                    $TKT->set_date_format($incoming_date_formats[0]);
1302
-                    $TKT->set_time_format($incoming_date_formats[1]);
1303
-                    $TKT->set_timezone($evtobj->get_timezone());
1304
-                    //set new values
1305
-                    foreach ($TKT_values as $field => $value) {
1306
-                        if ($field == 'TKT_qty') {
1307
-                            $TKT->set_qty($value);
1308
-                        } else {
1309
-                            $TKT->set($field, $value);
1310
-                        }
1311
-                    }
1312
-                    $update_prices = true;
1313
-                }
1314
-            }
1315
-            // cap ticket qty by datetime reg limits
1316
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
-            //update ticket.
1318
-            $TKT->save();
1319
-            //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1320
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
-                $TKT->save();
1324
-            }
1325
-            //initially let's add the ticket to the dtt
1326
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
-            $saved_tickets[$TKT->ID()] = $TKT;
1328
-            //add prices to ticket
1329
-            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
-        }
1331
-        //however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1332
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
-        foreach ($tickets_removed as $id) {
1335
-            $id = absint($id);
1336
-            //get the ticket for this id
1337
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
-            //need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1339
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1340
-            foreach ($dtts as $dtt) {
1341
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
-            }
1343
-            //need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1344
-            $tkt_to_remove->delete_related_permanently('Price');
1345
-            //finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
-            $tkt_to_remove->delete_permanently();
1347
-        }
1348
-        return array($saved_dtt, $saved_tickets);
1349
-    }
1350
-
1351
-
1352
-
1353
-    /**
1354
-     * This attaches a list of given prices to a ticket.
1355
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
-     * price info and prices are automatically "archived" via the ticket.
1358
-     *
1359
-     * @access  private
1360
-     * @param array     $prices     Array of prices from the form.
1361
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
-     * @return  void
1364
-     */
1365
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
-    {
1367
-        foreach ($prices as $row => $prc) {
1368
-            $PRC_values = array(
1369
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
-                'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
-                'PRC_order'      => $row,
1376
-            );
1377
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
-                $PRC_values['PRC_ID'] = 0;
1379
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
-            } else {
1381
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
-                //update this price with new values
1383
-                foreach ($PRC_values as $field => $newprc) {
1384
-                    $PRC->set($field, $newprc);
1385
-                }
1386
-                $PRC->save();
1387
-            }
1388
-            $ticket->_add_relation_to($PRC, 'Price');
1389
-        }
1390
-    }
1391
-
1392
-
1393
-
1394
-    /**
1395
-     * Add in our autosave ajax handlers
1396
-     *
1397
-     */
1398
-    protected function _ee_autosave_create_new()
1399
-    {
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * More autosave handlers.
1405
-     */
1406
-    protected function _ee_autosave_edit()
1407
-    {
1408
-        return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
-    }
1410
-
1411
-
1412
-
1413
-    /**
1414
-     *    _generate_publish_box_extra_content
1415
-     */
1416
-    private function _generate_publish_box_extra_content()
1417
-    {
1418
-        //load formatter helper
1419
-        //args for getting related registrations
1420
-        $approved_query_args = array(
1421
-            array(
1422
-                'REG_deleted' => 0,
1423
-                'STS_ID'      => EEM_Registration::status_id_approved,
1424
-            ),
1425
-        );
1426
-        $not_approved_query_args = array(
1427
-            array(
1428
-                'REG_deleted' => 0,
1429
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
-            ),
1431
-        );
1432
-        $pending_payment_query_args = array(
1433
-            array(
1434
-                'REG_deleted' => 0,
1435
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
-            ),
1437
-        );
1438
-        // publish box
1439
-        $publish_box_extra_args = array(
1440
-            'view_approved_reg_url'        => add_query_arg(
1441
-                array(
1442
-                    'action'      => 'default',
1443
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1444
-                    '_reg_status' => EEM_Registration::status_id_approved,
1445
-                ),
1446
-                REG_ADMIN_URL
1447
-            ),
1448
-            'view_not_approved_reg_url'    => add_query_arg(
1449
-                array(
1450
-                    'action'      => 'default',
1451
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1452
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1453
-                ),
1454
-                REG_ADMIN_URL
1455
-            ),
1456
-            'view_pending_payment_reg_url' => add_query_arg(
1457
-                array(
1458
-                    'action'      => 'default',
1459
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1460
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1461
-                ),
1462
-                REG_ADMIN_URL
1463
-            ),
1464
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
-                'Registration',
1466
-                $approved_query_args
1467
-            ),
1468
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
-                'Registration',
1470
-                $not_approved_query_args
1471
-            ),
1472
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
-                'Registration',
1474
-                $pending_payment_query_args
1475
-            ),
1476
-            'misc_pub_section_class'       => apply_filters(
1477
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
-                'misc-pub-section'
1479
-            ),
1480
-        );
1481
-        ob_start();
1482
-        do_action(
1483
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
-            $this->_cpt_model_obj
1485
-        );
1486
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
-        // load template
1488
-        EEH_Template::display_template(
1489
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
-            $publish_box_extra_args
1491
-        );
1492
-    }
1493
-
1494
-
1495
-
1496
-    /**
1497
-     * @return EE_Event
1498
-     */
1499
-    public function get_event_object()
1500
-    {
1501
-        return $this->_cpt_model_obj;
1502
-    }
1503
-
1504
-
1505
-
1506
-
1507
-    /** METABOXES * */
1508
-    /**
1509
-     * _register_event_editor_meta_boxes
1510
-     * add all metaboxes related to the event_editor
1511
-     *
1512
-     * @return void
1513
-     */
1514
-    protected function _register_event_editor_meta_boxes()
1515
-    {
1516
-        $this->verify_cpt_object();
1517
-        add_meta_box(
1518
-            'espresso_event_editor_tickets',
1519
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
-            array($this, 'ticket_metabox'),
1521
-            $this->page_slug,
1522
-            'normal',
1523
-            'high'
1524
-        );
1525
-        add_meta_box(
1526
-            'espresso_event_editor_event_options',
1527
-            esc_html__('Event Registration Options', 'event_espresso'),
1528
-            array($this, 'registration_options_meta_box'),
1529
-            $this->page_slug,
1530
-            'side',
1531
-            'default'
1532
-        );
1533
-        // NOTE: if you're looking for other metaboxes in here,
1534
-        // where a metabox has a related management page in the admin
1535
-        // you will find it setup in the related management page's "_Hooks" file.
1536
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
-    }
1538
-
1539
-
1540
-    /**
1541
-     * @throws DomainException
1542
-     * @throws EE_Error
1543
-     */
1544
-    public function ticket_metabox()
1545
-    {
1546
-        $existing_datetime_ids = $existing_ticket_ids = array();
1547
-        //defaults for template args
1548
-        $template_args = array(
1549
-            'existing_datetime_ids'    => '',
1550
-            'event_datetime_help_link' => '',
1551
-            'ticket_options_help_link' => '',
1552
-            'time'                     => null,
1553
-            'ticket_rows'              => '',
1554
-            'existing_ticket_ids'      => '',
1555
-            'total_ticket_rows'        => 1,
1556
-            'ticket_js_structure'      => '',
1557
-            'trash_icon'               => 'ee-lock-icon',
1558
-            'disabled'                 => '',
1559
-        );
1560
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
-        /**
1563
-         * 1. Start with retrieving Datetimes
1564
-         * 2. Fore each datetime get related tickets
1565
-         * 3. For each ticket get related prices
1566
-         */
1567
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
-        /** @type EE_Datetime $first_datetime */
1569
-        $first_datetime = reset($times);
1570
-        //do we get related tickets?
1571
-        if ($first_datetime instanceof EE_Datetime
1572
-            && $first_datetime->ID() !== 0
1573
-        ) {
1574
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
-            $template_args['time'] = $first_datetime;
1576
-            $related_tickets = $first_datetime->tickets(
1577
-                array(
1578
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
-                    'default_where_conditions' => 'none',
1580
-                )
1581
-            );
1582
-            if ( ! empty($related_tickets)) {
1583
-                $template_args['total_ticket_rows'] = count($related_tickets);
1584
-                $row = 0;
1585
-                foreach ($related_tickets as $ticket) {
1586
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
-                    $row++;
1589
-                }
1590
-            } else {
1591
-                $template_args['total_ticket_rows'] = 1;
1592
-                /** @type EE_Ticket $ticket */
1593
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
-            }
1596
-        } else {
1597
-            $template_args['time'] = $times[0];
1598
-            /** @type EE_Ticket $ticket */
1599
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
-            // NOTE: we're just sending the first default row
1602
-            // (decaf can't manage default tickets so this should be sufficient);
1603
-        }
1604
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
-            'event_editor_event_datetimes_help_tab'
1606
-        );
1607
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
-            true
1613
-        );
1614
-        $template = apply_filters(
1615
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
-        );
1618
-        EEH_Template::display_template($template, $template_args);
1619
-    }
1620
-
1621
-
1622
-
1623
-    /**
1624
-     * Setup an individual ticket form for the decaf event editor page
1625
-     *
1626
-     * @access private
1627
-     * @param  EE_Ticket $ticket   the ticket object
1628
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
-     * @param int        $row
1630
-     * @return string generated html for the ticket row.
1631
-     */
1632
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
-    {
1634
-        $template_args = array(
1635
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
-                : '',
1638
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1640
-            'TKT_name'            => $ticket->get('TKT_name'),
1641
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
-            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
-                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
-            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
-                : ' disabled=disabled',
1652
-        );
1653
-        $price = $ticket->ID() !== 0
1654
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1656
-        $price_args = array(
1657
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
-            'PRC_amount'            => $price->get('PRC_amount'),
1659
-            'PRT_ID'                => $price->get('PRT_ID'),
1660
-            'PRC_ID'                => $price->get('PRC_ID'),
1661
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1662
-        );
1663
-        //make sure we have default start and end dates if skeleton
1664
-        //handle rows that should NOT be empty
1665
-        if (empty($template_args['TKT_start_date'])) {
1666
-            //if empty then the start date will be now.
1667
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
-        }
1669
-        if (empty($template_args['TKT_end_date'])) {
1670
-            //get the earliest datetime (if present);
1671
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
-                ? $this->_cpt_model_obj->get_first_related(
1673
-                    'Datetime',
1674
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
-                )
1676
-                : null;
1677
-            if ( ! empty($earliest_dtt)) {
1678
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
-            } else {
1680
-                $template_args['TKT_end_date'] = date(
1681
-                    'Y-m-d h:i a',
1682
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
-                );
1684
-            }
1685
-        }
1686
-        $template_args = array_merge($template_args, $price_args);
1687
-        $template = apply_filters(
1688
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
-            $ticket
1691
-        );
1692
-        return EEH_Template::display_template($template, $template_args, true);
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @throws DomainException
1698
-     */
1699
-    public function registration_options_meta_box()
1700
-    {
1701
-        $yes_no_values = array(
1702
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
-        );
1705
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1706
-            array(
1707
-                EEM_Registration::status_id_cancelled,
1708
-                EEM_Registration::status_id_declined,
1709
-                EEM_Registration::status_id_incomplete,
1710
-            ),
1711
-            true
1712
-        );
1713
-        //$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
-        $template_args['_event'] = $this->_cpt_model_obj;
1715
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
-            'default_reg_status',
1719
-            $default_reg_status_values,
1720
-            $this->_cpt_model_obj->default_registration_status()
1721
-        );
1722
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1723
-            'display_desc',
1724
-            $yes_no_values,
1725
-            $this->_cpt_model_obj->display_description()
1726
-        );
1727
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
-            'display_ticket_selector',
1729
-            $yes_no_values,
1730
-            $this->_cpt_model_obj->display_ticket_selector(),
1731
-            '',
1732
-            '',
1733
-            false
1734
-        );
1735
-        $template_args['additional_registration_options'] = apply_filters(
1736
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
-            '',
1738
-            $template_args,
1739
-            $yes_no_values,
1740
-            $default_reg_status_values
1741
-        );
1742
-        EEH_Template::display_template(
1743
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
-            $template_args
1745
-        );
1746
-    }
1747
-
1748
-
1749
-
1750
-    /**
1751
-     * _get_events()
1752
-     * This method simply returns all the events (for the given _view and paging)
1753
-     *
1754
-     * @access public
1755
-     * @param int  $per_page     count of items per page (20 default);
1756
-     * @param int  $current_page what is the current page being viewed.
1757
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
-     *                           If FALSE then we return an array of event objects
1759
-     *                           that match the given _view and paging parameters.
1760
-     * @return array an array of event objects.
1761
-     */
1762
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
-    {
1764
-        $EEME = $this->_event_model();
1765
-        $offset = ($current_page - 1) * $per_page;
1766
-        $limit = $count ? null : $offset . ',' . $per_page;
1767
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
-        if (isset($this->_req_data['month_range'])) {
1770
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
-            //simulate the FIRST day of the month, that fixes issues for months like February
1772
-            //where PHP doesn't know what to assume for date.
1773
-            //@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
-        }
1777
-        $where = array();
1778
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
-        //determine what post_status our condition will have for the query.
1780
-        switch ($status) {
1781
-            case 'month' :
1782
-            case 'today' :
1783
-            case null :
1784
-            case 'all' :
1785
-                break;
1786
-            case 'draft' :
1787
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1788
-                break;
1789
-            default :
1790
-                $where['status'] = $status;
1791
-        }
1792
-        //categories?
1793
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
-            ? $this->_req_data['EVT_CAT'] : null;
1795
-        if ( ! empty ($category)) {
1796
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
-            $where['Term_Taxonomy.term_id'] = $category;
1798
-        }
1799
-        //date where conditions
1800
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
-            $DateTime = new DateTime(
1803
-                $year_r . '-' . $month_r . '-01 00:00:00',
1804
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
-            );
1806
-            $start = $DateTime->format(implode(' ', $start_formats));
1807
-            $end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
-                ->format('t'))->setTime(23, 59, 59)
1809
-                            ->format(implode(' ', $start_formats));
1810
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
-            $now = date('Y-m-01');
1818
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
-                            ->setTime(23, 59, 59)
1822
-                            ->format(implode(' ', $start_formats));
1823
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
-        }
1825
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
-            $where['EVT_wp_user'] = get_current_user_id();
1827
-        } else {
1828
-            if ( ! isset($where['status'])) {
1829
-                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
-                    $where['OR'] = array(
1831
-                        'status*restrict_private' => array('!=', 'private'),
1832
-                        'AND'                     => array(
1833
-                            'status*inclusive' => array('=', 'private'),
1834
-                            'EVT_wp_user'      => get_current_user_id(),
1835
-                        ),
1836
-                    );
1837
-                }
1838
-            }
1839
-        }
1840
-        if (isset($this->_req_data['EVT_wp_user'])) {
1841
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
-            ) {
1844
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
-            }
1846
-        }
1847
-        //search query handling
1848
-        if (isset($this->_req_data['s'])) {
1849
-            $search_string = '%' . $this->_req_data['s'] . '%';
1850
-            $where['OR'] = array(
1851
-                'EVT_name'       => array('LIKE', $search_string),
1852
-                'EVT_desc'       => array('LIKE', $search_string),
1853
-                'EVT_short_desc' => array('LIKE', $search_string),
1854
-            );
1855
-        }
1856
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
-        $query_params = apply_filters(
1858
-            'FHEE__Events_Admin_Page__get_events__query_params',
1859
-            array(
1860
-                $where,
1861
-                'limit'    => $limit,
1862
-                'order_by' => $orderby,
1863
-                'order'    => $order,
1864
-                'group_by' => 'EVT_ID',
1865
-            ),
1866
-            $this->_req_data
1867
-        );
1868
-        //let's first check if we have special requests coming in.
1869
-        if (isset($this->_req_data['active_status'])) {
1870
-            switch ($this->_req_data['active_status']) {
1871
-                case 'upcoming' :
1872
-                    return $EEME->get_upcoming_events($query_params, $count);
1873
-                    break;
1874
-                case 'expired' :
1875
-                    return $EEME->get_expired_events($query_params, $count);
1876
-                    break;
1877
-                case 'active' :
1878
-                    return $EEME->get_active_events($query_params, $count);
1879
-                    break;
1880
-                case 'inactive' :
1881
-                    return $EEME->get_inactive_events($query_params, $count);
1882
-                    break;
1883
-            }
1884
-        }
1885
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
-        return $events;
1887
-    }
1888
-
1889
-
1890
-
1891
-    /**
1892
-     * handling for WordPress CPT actions (trash, restore, delete)
1893
-     *
1894
-     * @param string $post_id
1895
-     */
1896
-    public function trash_cpt_item($post_id)
1897
-    {
1898
-        $this->_req_data['EVT_ID'] = $post_id;
1899
-        $this->_trash_or_restore_event('trash', false);
1900
-    }
1901
-
1902
-
1903
-
1904
-    /**
1905
-     * @param string $post_id
1906
-     */
1907
-    public function restore_cpt_item($post_id)
1908
-    {
1909
-        $this->_req_data['EVT_ID'] = $post_id;
1910
-        $this->_trash_or_restore_event('draft', false);
1911
-    }
1912
-
1913
-
1914
-
1915
-    /**
1916
-     * @param string $post_id
1917
-     */
1918
-    public function delete_cpt_item($post_id)
1919
-    {
1920
-        $this->_req_data['EVT_ID'] = $post_id;
1921
-        $this->_delete_event(false);
1922
-    }
1923
-
1924
-
1925
-
1926
-    /**
1927
-     * _trash_or_restore_event
1928
-     *
1929
-     * @access protected
1930
-     * @param  string $event_status
1931
-     * @param bool    $redirect_after
1932
-     */
1933
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
-    {
1935
-        //determine the event id and set to array.
1936
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
-        // loop thru events
1938
-        if ($EVT_ID) {
1939
-            // clean status
1940
-            $event_status = sanitize_key($event_status);
1941
-            // grab status
1942
-            if ( ! empty($event_status)) {
1943
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1944
-            } else {
1945
-                $success = false;
1946
-                $msg = esc_html__(
1947
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
-                    'event_espresso'
1949
-                );
1950
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
-            }
1952
-        } else {
1953
-            $success = false;
1954
-            $msg = esc_html__(
1955
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
-                'event_espresso'
1957
-            );
1958
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
-        }
1960
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
-        if ($redirect_after) {
1962
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
-        }
1964
-    }
1965
-
1966
-
1967
-
1968
-    /**
1969
-     * _trash_or_restore_events
1970
-     *
1971
-     * @access protected
1972
-     * @param  string $event_status
1973
-     * @return void
1974
-     */
1975
-    protected function _trash_or_restore_events($event_status = 'trash')
1976
-    {
1977
-        // clean status
1978
-        $event_status = sanitize_key($event_status);
1979
-        // grab status
1980
-        if ( ! empty($event_status)) {
1981
-            $success = true;
1982
-            //determine the event id and set to array.
1983
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
-            // loop thru events
1985
-            foreach ($EVT_IDs as $EVT_ID) {
1986
-                if ($EVT_ID = absint($EVT_ID)) {
1987
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1988
-                    $success = $results !== false ? $success : false;
1989
-                } else {
1990
-                    $msg = sprintf(
1991
-                        esc_html__(
1992
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
-                            'event_espresso'
1994
-                        ),
1995
-                        $EVT_ID
1996
-                    );
1997
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
-                    $success = false;
1999
-                }
2000
-            }
2001
-        } else {
2002
-            $success = false;
2003
-            $msg = esc_html__(
2004
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
-                'event_espresso'
2006
-            );
2007
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
-        }
2009
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2010
-        $success = $success ? 2 : false;
2011
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
-    }
2014
-
2015
-
2016
-
2017
-    /**
2018
-     * _trash_or_restore_events
2019
-     *
2020
-     * @access  private
2021
-     * @param  int    $EVT_ID
2022
-     * @param  string $event_status
2023
-     * @return bool
2024
-     */
2025
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
-    {
2027
-        // grab event id
2028
-        if ( ! $EVT_ID) {
2029
-            $msg = esc_html__(
2030
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2031
-                'event_espresso'
2032
-            );
2033
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
-            return false;
2035
-        }
2036
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
-        // clean status
2038
-        $event_status = sanitize_key($event_status);
2039
-        // grab status
2040
-        if (empty($event_status)) {
2041
-            $msg = esc_html__(
2042
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2043
-                'event_espresso'
2044
-            );
2045
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
-            return false;
2047
-        }
2048
-        // was event trashed or restored ?
2049
-        switch ($event_status) {
2050
-            case 'draft' :
2051
-                $action = 'restored from the trash';
2052
-                $hook = 'AHEE_event_restored_from_trash';
2053
-                break;
2054
-            case 'trash' :
2055
-                $action = 'moved to the trash';
2056
-                $hook = 'AHEE_event_moved_to_trash';
2057
-                break;
2058
-            default :
2059
-                $action = 'updated';
2060
-                $hook = false;
2061
-        }
2062
-        //use class to change status
2063
-        $this->_cpt_model_obj->set_status($event_status);
2064
-        $success = $this->_cpt_model_obj->save();
2065
-        if ($success === false) {
2066
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
-            return false;
2069
-        }
2070
-        if ($hook) {
2071
-            do_action($hook);
2072
-        }
2073
-        return true;
2074
-    }
2075
-
2076
-
2077
-
2078
-    /**
2079
-     * _delete_event
2080
-     *
2081
-     * @access protected
2082
-     * @param bool $redirect_after
2083
-     */
2084
-    protected function _delete_event($redirect_after = true)
2085
-    {
2086
-        //determine the event id and set to array.
2087
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
-        // loop thru events
2090
-        if ($EVT_ID) {
2091
-            $success = $this->_permanently_delete_event($EVT_ID);
2092
-            // get list of events with no prices
2093
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
-            // remove this event from the list of events with no prices
2095
-            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2097
-            }
2098
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
-        } else {
2100
-            $success = false;
2101
-            $msg = esc_html__(
2102
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
-                'event_espresso'
2104
-            );
2105
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
-        }
2107
-        if ($redirect_after) {
2108
-            $this->_redirect_after_action(
2109
-                $success,
2110
-                'Event',
2111
-                'deleted',
2112
-                array('action' => 'default', 'status' => 'trash')
2113
-            );
2114
-        }
2115
-    }
2116
-
2117
-
2118
-
2119
-    /**
2120
-     * _delete_events
2121
-     *
2122
-     * @access protected
2123
-     * @return void
2124
-     */
2125
-    protected function _delete_events()
2126
-    {
2127
-        $success = true;
2128
-        // get list of events with no prices
2129
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
-        //determine the event id and set to array.
2131
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
-        // loop thru events
2133
-        foreach ($EVT_IDs as $EVT_ID) {
2134
-            $EVT_ID = absint($EVT_ID);
2135
-            if ($EVT_ID) {
2136
-                $results = $this->_permanently_delete_event($EVT_ID);
2137
-                $success = $results !== false ? $success : false;
2138
-                // remove this event from the list of events with no prices
2139
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2140
-            } else {
2141
-                $success = false;
2142
-                $msg = esc_html__(
2143
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
-                    'event_espresso'
2145
-                );
2146
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
-            }
2148
-        }
2149
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2151
-        $success = $success ? 2 : false;
2152
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
-    }
2154
-
2155
-
2156
-
2157
-    /**
2158
-     * _permanently_delete_event
2159
-     *
2160
-     * @access  private
2161
-     * @param  int $EVT_ID
2162
-     * @return bool
2163
-     */
2164
-    private function _permanently_delete_event($EVT_ID = 0)
2165
-    {
2166
-        // grab event id
2167
-        if ( ! $EVT_ID) {
2168
-            $msg = esc_html__(
2169
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2170
-                'event_espresso'
2171
-            );
2172
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
-            return false;
2174
-        }
2175
-        if (
2176
-            ! $this->_cpt_model_obj instanceof EE_Event
2177
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2178
-        ) {
2179
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
-        }
2181
-        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
-            return false;
2183
-        }
2184
-        //need to delete related tickets and prices first.
2185
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
-        foreach ($datetimes as $datetime) {
2187
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
-            $tickets = $datetime->get_many_related('Ticket');
2189
-            foreach ($tickets as $ticket) {
2190
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2191
-                $ticket->delete_related_permanently('Price');
2192
-                $ticket->delete_permanently();
2193
-            }
2194
-            $datetime->delete();
2195
-        }
2196
-        //what about related venues or terms?
2197
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
-        foreach ($venues as $venue) {
2199
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
-        }
2201
-        //any attached question groups?
2202
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
-        if ( ! empty($question_groups)) {
2204
-            foreach ($question_groups as $question_group) {
2205
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
-            }
2207
-        }
2208
-        //Message Template Groups
2209
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
-        foreach ($term_taxonomies as $term_taxonomy) {
2213
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
-        }
2215
-        $success = $this->_cpt_model_obj->delete_permanently();
2216
-        // did it all go as planned ?
2217
-        if ($success) {
2218
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
-            EE_Error::add_success($msg);
2220
-        } else {
2221
-            $msg = sprintf(
2222
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
-                $EVT_ID
2224
-            );
2225
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
-            return false;
2227
-        }
2228
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
-        return true;
2230
-    }
2231
-
2232
-
2233
-
2234
-    /**
2235
-     * get total number of events
2236
-     *
2237
-     * @access public
2238
-     * @return int
2239
-     */
2240
-    public function total_events()
2241
-    {
2242
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
-        return $count;
2244
-    }
2245
-
2246
-
2247
-
2248
-    /**
2249
-     * get total number of draft events
2250
-     *
2251
-     * @access public
2252
-     * @return int
2253
-     */
2254
-    public function total_events_draft()
2255
-    {
2256
-        $where = array(
2257
-            'status' => array('IN', array('draft', 'auto-draft')),
2258
-        );
2259
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
-        return $count;
2261
-    }
2262
-
2263
-
2264
-
2265
-    /**
2266
-     * get total number of trashed events
2267
-     *
2268
-     * @access public
2269
-     * @return int
2270
-     */
2271
-    public function total_trashed_events()
2272
-    {
2273
-        $where = array(
2274
-            'status' => 'trash',
2275
-        );
2276
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
-        return $count;
2278
-    }
2279
-
2280
-
2281
-    /**
2282
-     *    _default_event_settings
2283
-     *    This generates the Default Settings Tab
2284
-     *
2285
-     * @return void
2286
-     * @throws EE_Error
2287
-     */
2288
-    protected function _default_event_settings()
2289
-    {
2290
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2291
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2292
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
-        $this->display_admin_page_with_sidebar();
2294
-    }
2295
-
2296
-
2297
-    /**
2298
-     * Return the form for event settings.
2299
-     * @return EE_Form_Section_Proper
2300
-     */
2301
-    protected function _default_event_settings_form()
2302
-    {
2303
-        $registration_config = EE_Registry::instance()->CFG->registration;
2304
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
-        //exclude
2306
-            array(
2307
-                EEM_Registration::status_id_cancelled,
2308
-                EEM_Registration::status_id_declined,
2309
-                EEM_Registration::status_id_incomplete,
2310
-                EEM_Registration::status_id_wait_list,
2311
-            ),
2312
-            true
2313
-        );
2314
-        return new EE_Form_Section_Proper(
2315
-            array(
2316
-                'name' => 'update_default_event_settings',
2317
-                'html_id' => 'update_default_event_settings',
2318
-                'html_class' => 'form-table',
2319
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
-                'subsections' => apply_filters(
2321
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
-                    array(
2323
-                        'default_reg_status' => new EE_Select_Input(
2324
-                            $registration_stati_for_selection,
2325
-                            array(
2326
-                                'default' => isset($registration_config->default_STS_ID)
2327
-                                             && array_key_exists(
2328
-                                                $registration_config->default_STS_ID,
2329
-                                                $registration_stati_for_selection
2330
-                                             )
2331
-                                            ? sanitize_text_field($registration_config->default_STS_ID)
2332
-                                            : EEM_Registration::status_id_pending_payment,
2333
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
-                                                    . EEH_Template::get_help_tab_link(
2335
-                                                        'default_settings_status_help_tab'
2336
-                                                    ),
2337
-                                'html_help_text' => esc_html__(
2338
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2339
-                                    'event_espresso'
2340
-                                )
2341
-                            )
2342
-                        ),
2343
-                        'default_max_tickets' => new EE_Integer_Input(
2344
-                            array(
2345
-                                'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
-                                    ? $registration_config->default_maximum_number_of_tickets
2347
-                                    : EEM_Event::get_default_additional_limit(),
2348
-                                'html_label_text' => esc_html__(
2349
-                                    'Default Maximum Tickets Allowed Per Order:',
2350
-                                    'event_espresso'
2351
-                                ) . EEH_Template::get_help_tab_link(
2352
-                                    'default_maximum_tickets_help_tab"'
2353
-                                    ),
2354
-                                'html_help_text' => esc_html__(
2355
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
-                                    'event_espresso'
2357
-                                )
2358
-                            )
2359
-                        )
2360
-                    )
2361
-                )
2362
-            )
2363
-        );
2364
-    }
2365
-
2366
-
2367
-    /**
2368
-     * _update_default_event_settings
2369
-     *
2370
-     * @access protected
2371
-     * @return void
2372
-     * @throws EE_Error
2373
-     */
2374
-    protected function _update_default_event_settings()
2375
-    {
2376
-        $registration_config = EE_Registry::instance()->CFG->registration;
2377
-        $form = $this->_default_event_settings_form();
2378
-        if ($form->was_submitted()) {
2379
-            $form->receive_form_submission();
2380
-            if ($form->is_valid()) {
2381
-                $valid_data = $form->valid_data();
2382
-                if (isset($valid_data['default_reg_status'])) {
2383
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
-                }
2385
-                if (isset($valid_data['default_max_tickets'])) {
2386
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
-                }
2388
-                //update because data was valid!
2389
-                EE_Registry::instance()->CFG->update_espresso_config();
2390
-                EE_Error::overwrite_success();
2391
-                EE_Error::add_success(
2392
-                    __('Default Event Settings were updated', 'event_espresso')
2393
-                );
2394
-            }
2395
-        }
2396
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
-    }
2398
-
2399
-
2400
-
2401
-    /*************        Templates        *************/
2402
-    protected function _template_settings()
2403
-    {
2404
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
-        $this->_template_args['preview_img'] = '<img src="'
2406
-                                               . EVENTS_ASSETS_URL
2407
-                                               . DS
2408
-                                               . 'images'
2409
-                                               . DS
2410
-                                               . 'caffeinated_template_features.jpg" alt="'
2411
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
-                                               . '" />';
2413
-        $this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
-                'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2415
-                'event_espresso'
2416
-            ) . '</strong>';
2417
-        $this->display_admin_caf_preview_page('template_settings_tab');
2418
-    }
2419
-
2420
-
2421
-    /** Event Category Stuff **/
2422
-    /**
2423
-     * set the _category property with the category object for the loaded page.
2424
-     *
2425
-     * @access private
2426
-     * @return void
2427
-     */
2428
-    private function _set_category_object()
2429
-    {
2430
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
-            return;
2432
-        } //already have the category object so get out.
2433
-        //set default category object
2434
-        $this->_set_empty_category_object();
2435
-        //only set if we've got an id
2436
-        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
-            return;
2438
-        }
2439
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
-        $term = get_term($category_id, 'espresso_event_categories');
2441
-        if ( ! empty($term)) {
2442
-            $this->_category->category_name = $term->name;
2443
-            $this->_category->category_identifier = $term->slug;
2444
-            $this->_category->category_desc = $term->description;
2445
-            $this->_category->id = $term->term_id;
2446
-            $this->_category->parent = $term->parent;
2447
-        }
2448
-    }
2449
-
2450
-
2451
-    /**
2452
-     * Clears out category properties.
2453
-     */
2454
-    private function _set_empty_category_object()
2455
-    {
2456
-        $this->_category = new stdClass();
2457
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
-        $this->_category->id = $this->_category->parent = 0;
2459
-    }
2460
-
2461
-
2462
-    /**
2463
-     * @throws EE_Error
2464
-     */
2465
-    protected function _category_list_table()
2466
-    {
2467
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
-                'add_category',
2471
-                'add_category',
2472
-                array(),
2473
-                'add-new-h2'
2474
-            );
2475
-        $this->display_admin_list_table_page_with_sidebar();
2476
-    }
2477
-
2478
-
2479
-
2480
-    /**
2481
-     * Output category details view.
2482
-     */
2483
-    protected function _category_details($view)
2484
-    {
2485
-        //load formatter helper
2486
-        //load field generator helper
2487
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
-        $this->_set_add_edit_form_tags($route);
2489
-        $this->_set_category_object();
2490
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
-        $delete_action = 'delete_category';
2492
-        //custom redirect
2493
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
-            array('action' => 'category_list'),
2495
-            $this->_admin_base_url
2496
-        );
2497
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
-        //take care of contents
2499
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
-        $this->display_admin_page_with_sidebar();
2501
-    }
2502
-
2503
-
2504
-
2505
-    /**
2506
-     * Output category details content.
2507
-     */
2508
-    protected function _category_details_content()
2509
-    {
2510
-        $editor_args['category_desc'] = array(
2511
-            'type'          => 'wp_editor',
2512
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
-            'class'         => 'my_editor_custom',
2514
-            'wpeditor_args' => array('media_buttons' => false),
2515
-        );
2516
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
-        $all_terms = get_terms(
2518
-            array('espresso_event_categories'),
2519
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
-        );
2521
-        //setup category select for term parents.
2522
-        $category_select_values[] = array(
2523
-            'text' => esc_html__('No Parent', 'event_espresso'),
2524
-            'id'   => 0,
2525
-        );
2526
-        foreach ($all_terms as $term) {
2527
-            $category_select_values[] = array(
2528
-                'text' => $term->name,
2529
-                'id'   => $term->term_id,
2530
-            );
2531
-        }
2532
-        $category_select = EEH_Form_Fields::select_input(
2533
-            'category_parent',
2534
-            $category_select_values,
2535
-            $this->_category->parent
2536
-        );
2537
-        $template_args = array(
2538
-            'category'                 => $this->_category,
2539
-            'category_select'          => $category_select,
2540
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
-            'disable'                  => '',
2543
-            'disabled_message'         => false,
2544
-        );
2545
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
-        return EEH_Template::display_template($template, $template_args, true);
2547
-    }
2548
-
2549
-
2550
-    /**
2551
-     * Handles deleting categories.
2552
-     */
2553
-    protected function _delete_categories()
2554
-    {
2555
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
-            : (array)$this->_req_data['category_id'];
2557
-        foreach ($cat_ids as $cat_id) {
2558
-            $this->_delete_category($cat_id);
2559
-        }
2560
-        //doesn't matter what page we're coming from... we're going to the same place after delete.
2561
-        $query_args = array(
2562
-            'action' => 'category_list',
2563
-        );
2564
-        $this->_redirect_after_action(0, '', '', $query_args);
2565
-    }
2566
-
2567
-
2568
-
2569
-    /**
2570
-     * Handles deleting specific category.
2571
-     * @param int $cat_id
2572
-     */
2573
-    protected function _delete_category($cat_id)
2574
-    {
2575
-        $cat_id = absint($cat_id);
2576
-        wp_delete_term($cat_id, 'espresso_event_categories');
2577
-    }
2578
-
2579
-
2580
-
2581
-    /**
2582
-     * Handles triggering the update or insertion of a new category.
2583
-     * @param bool $new_category  true means we're triggering the insert of a new category.
2584
-     */
2585
-    protected function _insert_or_update_category($new_category)
2586
-    {
2587
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
-        $success = 0; //we already have a success message so lets not send another.
2589
-        if ($cat_id) {
2590
-            $query_args = array(
2591
-                'action'     => 'edit_category',
2592
-                'EVT_CAT_ID' => $cat_id,
2593
-            );
2594
-        } else {
2595
-            $query_args = array('action' => 'add_category');
2596
-        }
2597
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2598
-    }
2599
-
2600
-
2601
-
2602
-    /**
2603
-     * Inserts or updates category
2604
-     * @param bool $update (true indicates we're updating a category).
2605
-     * @return bool|mixed|string
2606
-     */
2607
-    private function _insert_category($update = false)
2608
-    {
2609
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
-        if (empty($category_name)) {
2614
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
-            return false;
2617
-        }
2618
-        $term_args = array(
2619
-            'name'        => $category_name,
2620
-            'description' => $category_desc,
2621
-            'parent'      => $category_parent,
2622
-        );
2623
-        //was the category_identifier input disabled?
2624
-        if (isset($this->_req_data['category_identifier'])) {
2625
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2626
-        }
2627
-        $insert_ids = $update
2628
-            ? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
-            : wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
-        if ( ! is_array($insert_ids)) {
2631
-            $msg = esc_html__(
2632
-                'An error occurred and the category has not been saved to the database.',
2633
-                'event_espresso'
2634
-            );
2635
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
-        } else {
2637
-            $cat_id = $insert_ids['term_id'];
2638
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
-            EE_Error::add_success($msg);
2640
-        }
2641
-        return $cat_id;
2642
-    }
2643
-
2644
-
2645
-
2646
-    /**
2647
-     * Gets categories or count of categories matching the arguments in the request.
2648
-     * @param int  $per_page
2649
-     * @param int  $current_page
2650
-     * @param bool $count
2651
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
-     */
2653
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
-    {
2655
-        //testing term stuff
2656
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
-        $limit = ($current_page - 1) * $per_page;
2659
-        $where = array('taxonomy' => 'espresso_event_categories');
2660
-        if (isset($this->_req_data['s'])) {
2661
-            $sstr = '%' . $this->_req_data['s'] . '%';
2662
-            $where['OR'] = array(
2663
-                'Term.name'   => array('LIKE', $sstr),
2664
-                'description' => array('LIKE', $sstr),
2665
-            );
2666
-        }
2667
-        $query_params = array(
2668
-            $where,
2669
-            'order_by'   => array($orderby => $order),
2670
-            'limit'      => $limit . ',' . $per_page,
2671
-            'force_join' => array('Term'),
2672
-        );
2673
-        $categories = $count
2674
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
-        return $categories;
2677
-    }
2678
-
2679
-    /* end category stuff */
2680
-    /**************/
2681
-
2682
-
2683
-    /**
2684
-     * Callback for the `ee_save_timezone_setting` ajax action.
2685
-     * @throws EE_Error
2686
-     */
2687
-    public function save_timezonestring_setting()
2688
-    {
2689
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2690
-            ? $this->_req_data['timezone_selected']
2691
-            : '';
2692
-        if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
-        {
2694
-            EE_Error::add_error(
2695
-                esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
-                __FILE__, __FUNCTION__, __LINE__
2697
-            );
2698
-            $this->_template_args['error'] = true;
2699
-            $this->_return_json();
2700
-        }
2701
-
2702
-        update_option('timezone_string', $timezone_string);
2703
-        EE_Error::add_success(
2704
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2705
-        );
2706
-        $this->_template_args['success'] = true;
2707
-        $this->_return_json(true, array('action' => 'create_new'));
2708
-    }
394
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
+				'require_nonce' => false,
396
+			),
397
+			'default_event_settings' => array(
398
+				'nav'           => array(
399
+					'label' => esc_html__('Default Settings', 'event_espresso'),
400
+					'order' => 40,
401
+				),
402
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
+				'labels'        => array(
404
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
+				),
406
+				'help_tabs'     => array(
407
+					'default_settings_help_tab'        => array(
408
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
+						'filename' => 'events_default_settings',
410
+					),
411
+					'default_settings_status_help_tab' => array(
412
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
+						'filename' => 'events_default_settings_status',
414
+					),
415
+					'default_maximum_tickets_help_tab' => array(
416
+						'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
+						'filename' => 'events_default_settings_max_tickets',
418
+					)
419
+				),
420
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
+				'require_nonce' => false,
422
+			),
423
+			//template settings
424
+			'template_settings'      => array(
425
+				'nav'           => array(
426
+					'label' => esc_html__('Templates', 'event_espresso'),
427
+					'order' => 30,
428
+				),
429
+				'metaboxes'     => $this->_default_espresso_metaboxes,
430
+				'help_tabs'     => array(
431
+					'general_settings_templates_help_tab' => array(
432
+						'title'    => esc_html__('Templates', 'event_espresso'),
433
+						'filename' => 'general_settings_templates',
434
+					),
435
+				),
436
+				'help_tour'     => array('Templates_Help_Tour'),
437
+				'require_nonce' => false,
438
+			),
439
+			//event category stuff
440
+			'add_category'           => array(
441
+				'nav'           => array(
442
+					'label'      => esc_html__('Add Category', 'event_espresso'),
443
+					'order'      => 15,
444
+					'persistent' => false,
445
+				),
446
+				'help_tabs'     => array(
447
+					'add_category_help_tab' => array(
448
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
+						'filename' => 'events_add_category',
450
+					),
451
+				),
452
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
+				'metaboxes'     => array('_publish_post_box'),
454
+				'require_nonce' => false,
455
+			),
456
+			'edit_category'          => array(
457
+				'nav'           => array(
458
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
459
+					'order'      => 15,
460
+					'persistent' => false,
461
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
+						? add_query_arg(
463
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
+							$this->_current_page_view_url
465
+						)
466
+						: $this->_admin_base_url,
467
+				),
468
+				'help_tabs'     => array(
469
+					'edit_category_help_tab' => array(
470
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
+						'filename' => 'events_edit_category',
472
+					),
473
+				),
474
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
+				'metaboxes'     => array('_publish_post_box'),
476
+				'require_nonce' => false,
477
+			),
478
+			'category_list'          => array(
479
+				'nav'           => array(
480
+					'label' => esc_html__('Categories', 'event_espresso'),
481
+					'order' => 20,
482
+				),
483
+				'list_table'    => 'Event_Categories_Admin_List_Table',
484
+				'help_tabs'     => array(
485
+					'events_categories_help_tab'                       => array(
486
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
487
+						'filename' => 'events_categories',
488
+					),
489
+					'events_categories_table_column_headings_help_tab' => array(
490
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
+						'filename' => 'events_categories_table_column_headings',
492
+					),
493
+					'events_categories_view_help_tab'                  => array(
494
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
+						'filename' => 'events_categories_views',
496
+					),
497
+					'events_categories_other_help_tab'                 => array(
498
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
+						'filename' => 'events_categories_other',
500
+					),
501
+				),
502
+				'help_tour'     => array(
503
+					'Event_Categories_Help_Tour',
504
+				),
505
+				'metaboxes'     => $this->_default_espresso_metaboxes,
506
+				'require_nonce' => false,
507
+			),
508
+		);
509
+	}
510
+
511
+
512
+	/**
513
+	 * Used to register any global screen options if necessary for every route in this admin page group.
514
+	 */
515
+	protected function _add_screen_options()
516
+	{
517
+	}
518
+
519
+
520
+	/**
521
+	 * Implementing the screen options for the 'default' route.
522
+	 */
523
+	protected function _add_screen_options_default()
524
+	{
525
+		$this->_per_page_screen_option();
526
+	}
527
+
528
+
529
+	/**
530
+	 * Implementing screen options for the category list route.
531
+	 */
532
+	protected function _add_screen_options_category_list()
533
+	{
534
+		$page_title = $this->_admin_page_title;
535
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
+		$this->_per_page_screen_option();
537
+		$this->_admin_page_title = $page_title;
538
+	}
539
+
540
+
541
+	/**
542
+	 * Used to register any global feature pointers for the admin page group.
543
+	 */
544
+	protected function _add_feature_pointers()
545
+	{
546
+	}
547
+
548
+
549
+	/**
550
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
551
+	 */
552
+	public function load_scripts_styles()
553
+	{
554
+		wp_register_style(
555
+			'events-admin-css',
556
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
557
+			array(),
558
+			EVENT_ESPRESSO_VERSION
559
+		);
560
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
+		wp_enqueue_style('events-admin-css');
562
+		wp_enqueue_style('ee-cat-admin');
563
+		//todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
+		//registers for all views
565
+		//scripts
566
+		wp_register_script(
567
+			'event_editor_js',
568
+			EVENTS_ASSETS_URL . 'event_editor.js',
569
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
+			EVENT_ESPRESSO_VERSION,
571
+			true
572
+		);
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * Enqueuing scripts and styles specific to this view
579
+	 */
580
+	public function load_scripts_styles_create_new()
581
+	{
582
+		$this->load_scripts_styles_edit();
583
+	}
584
+
585
+
586
+
587
+	/**
588
+	 * Enqueuing scripts and styles specific to this view
589
+	 */
590
+	public function load_scripts_styles_edit()
591
+	{
592
+		//styles
593
+		wp_enqueue_style('espresso-ui-theme');
594
+		wp_register_style(
595
+			'event-editor-css',
596
+			EVENTS_ASSETS_URL . 'event-editor.css',
597
+			array('ee-admin-css'),
598
+			EVENT_ESPRESSO_VERSION
599
+		);
600
+		wp_enqueue_style('event-editor-css');
601
+		//scripts
602
+		wp_register_script(
603
+			'event-datetime-metabox',
604
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
+			array('event_editor_js', 'ee-datepicker'),
606
+			EVENT_ESPRESSO_VERSION
607
+		);
608
+		wp_enqueue_script('event-datetime-metabox');
609
+	}
610
+
611
+
612
+	/**
613
+	 * Populating the _views property for the category list table view.
614
+	 */
615
+	protected function _set_list_table_views_category_list()
616
+	{
617
+		$this->_views = array(
618
+			'all' => array(
619
+				'slug'        => 'all',
620
+				'label'       => esc_html__('All', 'event_espresso'),
621
+				'count'       => 0,
622
+				'bulk_action' => array(
623
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
+				),
625
+			),
626
+		);
627
+	}
628
+
629
+
630
+	/**
631
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
+	 */
633
+	public function admin_init()
634
+	{
635
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
+			'event_espresso'
638
+		);
639
+	}
640
+
641
+
642
+	/**
643
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page group.
644
+	 */
645
+	public function admin_notices()
646
+	{
647
+	}
648
+
649
+
650
+	/**
651
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
+	 * this admin page group.
653
+	 */
654
+	public function admin_footer_scripts()
655
+	{
656
+	}
657
+
658
+
659
+
660
+	/**
661
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
+	 * warning (via EE_Error::add_error());
663
+	 *
664
+	 * @param  EE_Event $event Event object
665
+	 * @param string    $req_type
666
+	 * @return void
667
+	 * @throws EE_Error
668
+	 * @access public
669
+	 */
670
+	public function verify_event_edit($event = null, $req_type = '')
671
+	{
672
+		// don't need to do this when processing
673
+		if(!empty($req_type)) {
674
+			return;
675
+		}
676
+		// no event?
677
+		if (empty($event)) {
678
+			// set event
679
+			$event = $this->_cpt_model_obj;
680
+		}
681
+		// STILL no event?
682
+		if (! $event instanceof EE_Event) {
683
+			return;
684
+		}
685
+		$orig_status = $event->status();
686
+		// first check if event is active.
687
+		if (
688
+			$orig_status === EEM_Event::cancelled
689
+			|| $orig_status === EEM_Event::postponed
690
+			|| $event->is_expired()
691
+			|| $event->is_inactive()
692
+		) {
693
+			return;
694
+		}
695
+		//made it here so it IS active... next check that any of the tickets are sold.
696
+		if ($event->is_sold_out(true)) {
697
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
+				EE_Error::add_attention(
699
+					sprintf(
700
+						esc_html__(
701
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
702
+							'event_espresso'
703
+						),
704
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
+					)
706
+				);
707
+			}
708
+			return;
709
+		} else if ($orig_status === EEM_Event::sold_out) {
710
+			EE_Error::add_attention(
711
+				sprintf(
712
+					esc_html__(
713
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
714
+						'event_espresso'
715
+					),
716
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
717
+				)
718
+			);
719
+		}
720
+		//now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
+		if ( ! $event->tickets_on_sale()) {
722
+			return;
723
+		}
724
+		//made it here so show warning
725
+		$this->_edit_event_warning();
726
+	}
727
+
728
+
729
+
730
+	/**
731
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
732
+	 * When needed, hook this into a EE_Error::add_error() notice.
733
+	 *
734
+	 * @access protected
735
+	 * @return void
736
+	 */
737
+	protected function _edit_event_warning()
738
+	{
739
+		// we don't want to add warnings during these requests
740
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
+			return;
742
+		}
743
+		EE_Error::add_attention(
744
+			esc_html__(
745
+				'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
+				'event_espresso'
747
+			)
748
+		);
749
+	}
750
+
751
+
752
+
753
+	/**
754
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
755
+	 * Otherwise, do the normal logic
756
+	 *
757
+	 * @return string
758
+	 * @throws \EE_Error
759
+	 */
760
+	protected function _create_new_cpt_item()
761
+	{
762
+		$has_timezone_string = get_option('timezone_string');
763
+		//only nag them about setting their timezone if it's their first event, and they haven't already done it
764
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
+			EE_Error::add_attention(
766
+				sprintf(
767
+					__(
768
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
+						'event_espresso'
770
+					),
771
+					'<br>',
772
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
+					. '</select>',
775
+					'<button class="button button-secondary timezone-submit">',
776
+					'</button><span class="spinner"></span>'
777
+				),
778
+				__FILE__,
779
+				__FUNCTION__,
780
+				__LINE__
781
+			);
782
+		}
783
+		return parent::_create_new_cpt_item();
784
+	}
785
+
786
+
787
+	/**
788
+	 * Sets the _views property for the default route in this admin page group.
789
+	 */
790
+	protected function _set_list_table_views_default()
791
+	{
792
+		$this->_views = array(
793
+			'all'   => array(
794
+				'slug'        => 'all',
795
+				'label'       => esc_html__('View All Events', 'event_espresso'),
796
+				'count'       => 0,
797
+				'bulk_action' => array(
798
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
+				),
800
+			),
801
+			'draft' => array(
802
+				'slug'        => 'draft',
803
+				'label'       => esc_html__('Draft', 'event_espresso'),
804
+				'count'       => 0,
805
+				'bulk_action' => array(
806
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
+				),
808
+			),
809
+		);
810
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
+			$this->_views['trash'] = array(
812
+				'slug'        => 'trash',
813
+				'label'       => esc_html__('Trash', 'event_espresso'),
814
+				'count'       => 0,
815
+				'bulk_action' => array(
816
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
+				),
819
+			);
820
+		}
821
+	}
822
+
823
+
824
+
825
+	/**
826
+	 * Provides the legend item array for the default list table view.
827
+	 * @return array
828
+	 */
829
+	protected function _event_legend_items()
830
+	{
831
+		$items = array(
832
+			'view_details'   => array(
833
+				'class' => 'dashicons dashicons-search',
834
+				'desc'  => esc_html__('View Event', 'event_espresso'),
835
+			),
836
+			'edit_event'     => array(
837
+				'class' => 'ee-icon ee-icon-calendar-edit',
838
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
+			),
840
+			'view_attendees' => array(
841
+				'class' => 'dashicons dashicons-groups',
842
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
+			),
844
+		);
845
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
+		$statuses = array(
847
+			'sold_out_status'  => array(
848
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
+			),
851
+			'active_status'    => array(
852
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
+			),
855
+			'upcoming_status'  => array(
856
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
+			),
859
+			'postponed_status' => array(
860
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
+			),
863
+			'cancelled_status' => array(
864
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
+			),
867
+			'expired_status'   => array(
868
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
+			),
871
+			'inactive_status'  => array(
872
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
+			),
875
+		);
876
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
+		return array_merge($items, $statuses);
878
+	}
879
+
880
+
881
+
882
+	/**
883
+	 * @return EEM_Event
884
+	 */
885
+	private function _event_model()
886
+	{
887
+		if ( ! $this->_event_model instanceof EEM_Event) {
888
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
889
+		}
890
+		return $this->_event_model;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * Adds extra buttons to the WP CPT permalink field row.
897
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
+	 *
899
+	 * @param  string $return    the current html
900
+	 * @param  int    $id        the post id for the page
901
+	 * @param  string $new_title What the title is
902
+	 * @param  string $new_slug  what the slug is
903
+	 * @return string            The new html string for the permalink area
904
+	 */
905
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
+	{
907
+		//make sure this is only when editing
908
+		if ( ! empty($id)) {
909
+			$post = get_post($id);
910
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
+					   . esc_html__('Shortcode', 'event_espresso')
912
+					   . '</a> ';
913
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
+					   . $post->ID
915
+					   . ']">';
916
+		}
917
+		return $return;
918
+	}
919
+
920
+
921
+
922
+	/**
923
+	 * _events_overview_list_table
924
+	 * This contains the logic for showing the events_overview list
925
+	 *
926
+	 * @access protected
927
+	 * @return void
928
+	 * @throws \EE_Error
929
+	 */
930
+	protected function _events_overview_list_table()
931
+	{
932
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
+			? (array)$this->_template_args['after_list_table']
935
+			: array();
936
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
+																			  . EEH_Template::get_button_or_link(
938
+				get_post_type_archive_link('espresso_events'),
939
+				esc_html__("View Event Archive Page", "event_espresso"),
940
+				'button'
941
+			);
942
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
+				'create_new',
945
+				'add',
946
+				array(),
947
+				'add-new-h2'
948
+			);
949
+		$this->display_admin_list_table_page_with_no_sidebar();
950
+	}
951
+
952
+
953
+
954
+	/**
955
+	 * this allows for extra misc actions in the default WP publish box
956
+	 *
957
+	 * @return void
958
+	 */
959
+	public function extra_misc_actions_publish_box()
960
+	{
961
+		$this->_generate_publish_box_extra_content();
962
+	}
963
+
964
+
965
+
966
+	/**
967
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
+	 * Typically you would use this to save any additional data.
969
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
+	 * ALSO very important.  When a post transitions from scheduled to published,
971
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
+	 * So MAKE sure that you handle this accordingly.
973
+	 *
974
+	 * @access protected
975
+	 * @abstract
976
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
+	 * @param  object $post    The post object of the cpt that was saved.
978
+	 * @return void
979
+	 * @throws \EE_Error
980
+	 */
981
+	protected function _insert_update_cpt_item($post_id, $post)
982
+	{
983
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
+			//get out we're not processing an event save.
985
+			return;
986
+		}
987
+		$event_values = array(
988
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
+			'EVT_additional_limit'            => min(
991
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
+			),
994
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
+				? $this->_req_data['EVT_default_registration_status']
996
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
997
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
+				? $this->_req_data['timezone_string'] : null,
1001
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
+				? $this->_req_data['externalURL'] : null,
1003
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
+				? $this->_req_data['event_phone'] : null,
1005
+		);
1006
+		//update event
1007
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
+		//get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1009
+		$get_one_where = array(
1010
+			$this->_event_model()->primary_key_name() => $post_id,
1011
+			'OR' => array(
1012
+				'status' => $post->post_status,
1013
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
+				// but the returned object here has a status of "publish", so use the original post status as well
1015
+				'status*1' => $this->_req_data['original_post_status'],
1016
+			)
1017
+		);
1018
+		$event = $this->_event_model()->get_one(array($get_one_where));
1019
+		//the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
+		$event_update_callbacks = apply_filters(
1021
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
+			array(
1023
+				array($this, '_default_venue_update'),
1024
+				array($this, '_default_tickets_update')
1025
+			)
1026
+		);
1027
+		$att_success = true;
1028
+		foreach ($event_update_callbacks as $e_callback) {
1029
+			$_success = is_callable($e_callback)
1030
+				? call_user_func($e_callback, $event, $this->_req_data)
1031
+				: false;
1032
+			//if ANY of these updates fail then we want the appropriate global error message
1033
+			$att_success = ! $att_success ? $att_success : $_success;
1034
+		}
1035
+		//any errors?
1036
+		if ($success && false === $att_success) {
1037
+			EE_Error::add_error(
1038
+				esc_html__(
1039
+					'Event Details saved successfully but something went wrong with saving attachments.',
1040
+					'event_espresso'
1041
+				),
1042
+				__FILE__,
1043
+				__FUNCTION__,
1044
+				__LINE__
1045
+			);
1046
+		} else if ($success === false) {
1047
+			EE_Error::add_error(
1048
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
+				__FILE__,
1050
+				__FUNCTION__,
1051
+				__LINE__
1052
+			);
1053
+		}
1054
+	}
1055
+
1056
+
1057
+
1058
+	/**
1059
+	 * @see parent::restore_item()
1060
+	 * @param int $post_id
1061
+	 * @param int $revision_id
1062
+	 */
1063
+	protected function _restore_cpt_item($post_id, $revision_id)
1064
+	{
1065
+		//copy existing event meta to new post
1066
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
+		if ($post_evt instanceof EE_Event) {
1068
+			//meta revision restore
1069
+			$post_evt->restore_revision($revision_id);
1070
+			//related objs restore
1071
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
+		}
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * Attach the venue to the Event
1079
+	 *
1080
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1081
+	 * @param  array     $data   The request data from the form
1082
+	 * @return bool           Success or fail.
1083
+	 */
1084
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
+	{
1086
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1088
+		$rows_affected = null;
1089
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
+		// very important.  If we don't have a venue name...
1091
+		// then we'll get out because not necessary to create empty venue
1092
+		if (empty($data['venue_title'])) {
1093
+			return false;
1094
+		}
1095
+		$venue_array = array(
1096
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
+				: null,
1102
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
+			'status'              => 'publish',
1115
+		);
1116
+		//if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
+		if ( ! empty($venue_id)) {
1118
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1119
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1120
+			//we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1121
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1122
+			return $rows_affected > 0 ? true : false;
1123
+		} else {
1124
+			//we insert the venue
1125
+			$venue_id = $venue_model->insert($venue_array);
1126
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1127
+			return ! empty($venue_id) ? true : false;
1128
+		}
1129
+		//when we have the ancestor come in it's already been handled by the revision save.
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
+	 *
1137
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1138
+	 * @param  array    $data   The request data from the form
1139
+	 * @return array
1140
+	 */
1141
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
+	{
1143
+		$success = true;
1144
+		$saved_dtt = null;
1145
+		$saved_tickets = array();
1146
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1147
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
+			//trim all values to ensure any excess whitespace is removed.
1149
+			$dtt = array_map('trim', $dtt);
1150
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
+				: $dtt['DTT_EVT_start'];
1152
+			$datetime_values = array(
1153
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
+				'DTT_order'     => $row,
1158
+			);
1159
+			//if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1160
+			if ( ! empty($dtt['DTT_ID'])) {
1161
+				$DTM = EE_Registry::instance()
1162
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
+								  ->get_one_by_ID($dtt['DTT_ID']);
1164
+				$DTM->set_date_format($incoming_date_formats[0]);
1165
+				$DTM->set_time_format($incoming_date_formats[1]);
1166
+				foreach ($datetime_values as $field => $value) {
1167
+					$DTM->set($field, $value);
1168
+				}
1169
+				//make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1170
+				$saved_dtts[$DTM->ID()] = $DTM;
1171
+			} else {
1172
+				$DTM = EE_Registry::instance()->load_class(
1173
+					'Datetime',
1174
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
+					false,
1176
+					false
1177
+				);
1178
+				foreach ($datetime_values as $field => $value) {
1179
+					$DTM->set($field, $value);
1180
+				}
1181
+			}
1182
+			$DTM->save();
1183
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
+			//load DTT helper
1185
+			//before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1186
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
+				$DTT->save();
1190
+			}
1191
+			//now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1192
+			$saved_dtt = $DTT;
1193
+			$success = ! $success ? $success : $DTT;
1194
+			//if ANY of these updates fail then we want the appropriate global error message.
1195
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1196
+		}
1197
+		//no dtts get deleted so we don't do any of that logic here.
1198
+		//update tickets next
1199
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1201
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1202
+			$update_prices = false;
1203
+			$ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
+				? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
+			// trim inputs to ensure any excess whitespace is removed.
1206
+			$tkt = array_map('trim', $tkt);
1207
+			if (empty($tkt['TKT_start_date'])) {
1208
+				//let's use now in the set timezone.
1209
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
+			}
1212
+			if (empty($tkt['TKT_end_date'])) {
1213
+				//use the start date of the first datetime
1214
+				$dtt = $evtobj->first_datetime();
1215
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
+					$incoming_date_formats[0],
1217
+					$incoming_date_formats[1]
1218
+				);
1219
+			}
1220
+			$TKT_values = array(
1221
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1226
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1227
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
+				'TKT_row'         => $row,
1232
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
+				'TKT_price'       => $ticket_price,
1234
+			);
1235
+			//if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1236
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
+				$TKT_values['TKT_ID'] = 0;
1238
+				$TKT_values['TKT_is_default'] = 0;
1239
+				$TKT_values['TKT_price'] = $ticket_price;
1240
+				$update_prices = true;
1241
+			}
1242
+			//if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
+			//we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1244
+			//keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1245
+			if ( ! empty($tkt['TKT_ID'])) {
1246
+				$TKT = EE_Registry::instance()
1247
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
+								  ->get_one_by_ID($tkt['TKT_ID']);
1249
+				if ($TKT instanceof EE_Ticket) {
1250
+					$ticket_sold = $TKT->count_related(
1251
+						'Registration',
1252
+						array(
1253
+							array(
1254
+								'STS_ID' => array(
1255
+									'NOT IN',
1256
+									array(EEM_Registration::status_id_incomplete),
1257
+								),
1258
+							),
1259
+						)
1260
+					) > 0 ? true : false;
1261
+					//let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1262
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
+									  && ! $TKT->get(
1264
+						'TKT_deleted'
1265
+					) ? true : false;
1266
+					$TKT->set_date_format($incoming_date_formats[0]);
1267
+					$TKT->set_time_format($incoming_date_formats[1]);
1268
+					//set new values
1269
+					foreach ($TKT_values as $field => $value) {
1270
+						if ($field == 'TKT_qty') {
1271
+							$TKT->set_qty($value);
1272
+						} else {
1273
+							$TKT->set($field, $value);
1274
+						}
1275
+					}
1276
+					//if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
+					if ($create_new_TKT) {
1278
+						//archive the old ticket first
1279
+						$TKT->set('TKT_deleted', 1);
1280
+						$TKT->save();
1281
+						//make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
+						$saved_tickets[$TKT->ID()] = $TKT;
1283
+						//create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1284
+						$TKT = clone $TKT;
1285
+						$TKT->set('TKT_ID', 0);
1286
+						$TKT->set('TKT_deleted', 0);
1287
+						$TKT->set('TKT_price', $ticket_price);
1288
+						$TKT->set('TKT_sold', 0);
1289
+						//now we need to make sure that $new prices are created as well and attached to new ticket.
1290
+						$update_prices = true;
1291
+					}
1292
+					//make sure price is set if it hasn't been already
1293
+					$TKT->set('TKT_price', $ticket_price);
1294
+				}
1295
+			} else {
1296
+				//no TKT_id so a new TKT
1297
+				$TKT_values['TKT_price'] = $ticket_price;
1298
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
+				if ($TKT instanceof EE_Ticket) {
1300
+					//need to reset values to properly account for the date formats
1301
+					$TKT->set_date_format($incoming_date_formats[0]);
1302
+					$TKT->set_time_format($incoming_date_formats[1]);
1303
+					$TKT->set_timezone($evtobj->get_timezone());
1304
+					//set new values
1305
+					foreach ($TKT_values as $field => $value) {
1306
+						if ($field == 'TKT_qty') {
1307
+							$TKT->set_qty($value);
1308
+						} else {
1309
+							$TKT->set($field, $value);
1310
+						}
1311
+					}
1312
+					$update_prices = true;
1313
+				}
1314
+			}
1315
+			// cap ticket qty by datetime reg limits
1316
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
+			//update ticket.
1318
+			$TKT->save();
1319
+			//before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1320
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
+				$TKT->save();
1324
+			}
1325
+			//initially let's add the ticket to the dtt
1326
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
+			$saved_tickets[$TKT->ID()] = $TKT;
1328
+			//add prices to ticket
1329
+			$this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
+		}
1331
+		//however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1332
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
+		foreach ($tickets_removed as $id) {
1335
+			$id = absint($id);
1336
+			//get the ticket for this id
1337
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
+			//need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1339
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1340
+			foreach ($dtts as $dtt) {
1341
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
+			}
1343
+			//need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1344
+			$tkt_to_remove->delete_related_permanently('Price');
1345
+			//finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
+			$tkt_to_remove->delete_permanently();
1347
+		}
1348
+		return array($saved_dtt, $saved_tickets);
1349
+	}
1350
+
1351
+
1352
+
1353
+	/**
1354
+	 * This attaches a list of given prices to a ticket.
1355
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
+	 * price info and prices are automatically "archived" via the ticket.
1358
+	 *
1359
+	 * @access  private
1360
+	 * @param array     $prices     Array of prices from the form.
1361
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
+	 * @return  void
1364
+	 */
1365
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
+	{
1367
+		foreach ($prices as $row => $prc) {
1368
+			$PRC_values = array(
1369
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
+				'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
+				'PRC_order'      => $row,
1376
+			);
1377
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
+				$PRC_values['PRC_ID'] = 0;
1379
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
+			} else {
1381
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
+				//update this price with new values
1383
+				foreach ($PRC_values as $field => $newprc) {
1384
+					$PRC->set($field, $newprc);
1385
+				}
1386
+				$PRC->save();
1387
+			}
1388
+			$ticket->_add_relation_to($PRC, 'Price');
1389
+		}
1390
+	}
1391
+
1392
+
1393
+
1394
+	/**
1395
+	 * Add in our autosave ajax handlers
1396
+	 *
1397
+	 */
1398
+	protected function _ee_autosave_create_new()
1399
+	{
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * More autosave handlers.
1405
+	 */
1406
+	protected function _ee_autosave_edit()
1407
+	{
1408
+		return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
+	}
1410
+
1411
+
1412
+
1413
+	/**
1414
+	 *    _generate_publish_box_extra_content
1415
+	 */
1416
+	private function _generate_publish_box_extra_content()
1417
+	{
1418
+		//load formatter helper
1419
+		//args for getting related registrations
1420
+		$approved_query_args = array(
1421
+			array(
1422
+				'REG_deleted' => 0,
1423
+				'STS_ID'      => EEM_Registration::status_id_approved,
1424
+			),
1425
+		);
1426
+		$not_approved_query_args = array(
1427
+			array(
1428
+				'REG_deleted' => 0,
1429
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
+			),
1431
+		);
1432
+		$pending_payment_query_args = array(
1433
+			array(
1434
+				'REG_deleted' => 0,
1435
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
+			),
1437
+		);
1438
+		// publish box
1439
+		$publish_box_extra_args = array(
1440
+			'view_approved_reg_url'        => add_query_arg(
1441
+				array(
1442
+					'action'      => 'default',
1443
+					'event_id'    => $this->_cpt_model_obj->ID(),
1444
+					'_reg_status' => EEM_Registration::status_id_approved,
1445
+				),
1446
+				REG_ADMIN_URL
1447
+			),
1448
+			'view_not_approved_reg_url'    => add_query_arg(
1449
+				array(
1450
+					'action'      => 'default',
1451
+					'event_id'    => $this->_cpt_model_obj->ID(),
1452
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1453
+				),
1454
+				REG_ADMIN_URL
1455
+			),
1456
+			'view_pending_payment_reg_url' => add_query_arg(
1457
+				array(
1458
+					'action'      => 'default',
1459
+					'event_id'    => $this->_cpt_model_obj->ID(),
1460
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1461
+				),
1462
+				REG_ADMIN_URL
1463
+			),
1464
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
+				'Registration',
1466
+				$approved_query_args
1467
+			),
1468
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
+				'Registration',
1470
+				$not_approved_query_args
1471
+			),
1472
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
+				'Registration',
1474
+				$pending_payment_query_args
1475
+			),
1476
+			'misc_pub_section_class'       => apply_filters(
1477
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
+				'misc-pub-section'
1479
+			),
1480
+		);
1481
+		ob_start();
1482
+		do_action(
1483
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
+			$this->_cpt_model_obj
1485
+		);
1486
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
+		// load template
1488
+		EEH_Template::display_template(
1489
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
+			$publish_box_extra_args
1491
+		);
1492
+	}
1493
+
1494
+
1495
+
1496
+	/**
1497
+	 * @return EE_Event
1498
+	 */
1499
+	public function get_event_object()
1500
+	{
1501
+		return $this->_cpt_model_obj;
1502
+	}
1503
+
1504
+
1505
+
1506
+
1507
+	/** METABOXES * */
1508
+	/**
1509
+	 * _register_event_editor_meta_boxes
1510
+	 * add all metaboxes related to the event_editor
1511
+	 *
1512
+	 * @return void
1513
+	 */
1514
+	protected function _register_event_editor_meta_boxes()
1515
+	{
1516
+		$this->verify_cpt_object();
1517
+		add_meta_box(
1518
+			'espresso_event_editor_tickets',
1519
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
+			array($this, 'ticket_metabox'),
1521
+			$this->page_slug,
1522
+			'normal',
1523
+			'high'
1524
+		);
1525
+		add_meta_box(
1526
+			'espresso_event_editor_event_options',
1527
+			esc_html__('Event Registration Options', 'event_espresso'),
1528
+			array($this, 'registration_options_meta_box'),
1529
+			$this->page_slug,
1530
+			'side',
1531
+			'default'
1532
+		);
1533
+		// NOTE: if you're looking for other metaboxes in here,
1534
+		// where a metabox has a related management page in the admin
1535
+		// you will find it setup in the related management page's "_Hooks" file.
1536
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
+	}
1538
+
1539
+
1540
+	/**
1541
+	 * @throws DomainException
1542
+	 * @throws EE_Error
1543
+	 */
1544
+	public function ticket_metabox()
1545
+	{
1546
+		$existing_datetime_ids = $existing_ticket_ids = array();
1547
+		//defaults for template args
1548
+		$template_args = array(
1549
+			'existing_datetime_ids'    => '',
1550
+			'event_datetime_help_link' => '',
1551
+			'ticket_options_help_link' => '',
1552
+			'time'                     => null,
1553
+			'ticket_rows'              => '',
1554
+			'existing_ticket_ids'      => '',
1555
+			'total_ticket_rows'        => 1,
1556
+			'ticket_js_structure'      => '',
1557
+			'trash_icon'               => 'ee-lock-icon',
1558
+			'disabled'                 => '',
1559
+		);
1560
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
+		/**
1563
+		 * 1. Start with retrieving Datetimes
1564
+		 * 2. Fore each datetime get related tickets
1565
+		 * 3. For each ticket get related prices
1566
+		 */
1567
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
+		/** @type EE_Datetime $first_datetime */
1569
+		$first_datetime = reset($times);
1570
+		//do we get related tickets?
1571
+		if ($first_datetime instanceof EE_Datetime
1572
+			&& $first_datetime->ID() !== 0
1573
+		) {
1574
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
+			$template_args['time'] = $first_datetime;
1576
+			$related_tickets = $first_datetime->tickets(
1577
+				array(
1578
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
+					'default_where_conditions' => 'none',
1580
+				)
1581
+			);
1582
+			if ( ! empty($related_tickets)) {
1583
+				$template_args['total_ticket_rows'] = count($related_tickets);
1584
+				$row = 0;
1585
+				foreach ($related_tickets as $ticket) {
1586
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
+					$row++;
1589
+				}
1590
+			} else {
1591
+				$template_args['total_ticket_rows'] = 1;
1592
+				/** @type EE_Ticket $ticket */
1593
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
+			}
1596
+		} else {
1597
+			$template_args['time'] = $times[0];
1598
+			/** @type EE_Ticket $ticket */
1599
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
+			// NOTE: we're just sending the first default row
1602
+			// (decaf can't manage default tickets so this should be sufficient);
1603
+		}
1604
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
+			'event_editor_event_datetimes_help_tab'
1606
+		);
1607
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
+			true
1613
+		);
1614
+		$template = apply_filters(
1615
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
+		);
1618
+		EEH_Template::display_template($template, $template_args);
1619
+	}
1620
+
1621
+
1622
+
1623
+	/**
1624
+	 * Setup an individual ticket form for the decaf event editor page
1625
+	 *
1626
+	 * @access private
1627
+	 * @param  EE_Ticket $ticket   the ticket object
1628
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
+	 * @param int        $row
1630
+	 * @return string generated html for the ticket row.
1631
+	 */
1632
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
+	{
1634
+		$template_args = array(
1635
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
+				: '',
1638
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1640
+			'TKT_name'            => $ticket->get('TKT_name'),
1641
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
+			'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
+									 && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
+			'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
+				: ' disabled=disabled',
1652
+		);
1653
+		$price = $ticket->ID() !== 0
1654
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1656
+		$price_args = array(
1657
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
+			'PRC_amount'            => $price->get('PRC_amount'),
1659
+			'PRT_ID'                => $price->get('PRT_ID'),
1660
+			'PRC_ID'                => $price->get('PRC_ID'),
1661
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1662
+		);
1663
+		//make sure we have default start and end dates if skeleton
1664
+		//handle rows that should NOT be empty
1665
+		if (empty($template_args['TKT_start_date'])) {
1666
+			//if empty then the start date will be now.
1667
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
+		}
1669
+		if (empty($template_args['TKT_end_date'])) {
1670
+			//get the earliest datetime (if present);
1671
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
+				? $this->_cpt_model_obj->get_first_related(
1673
+					'Datetime',
1674
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
+				)
1676
+				: null;
1677
+			if ( ! empty($earliest_dtt)) {
1678
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
+			} else {
1680
+				$template_args['TKT_end_date'] = date(
1681
+					'Y-m-d h:i a',
1682
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
+				);
1684
+			}
1685
+		}
1686
+		$template_args = array_merge($template_args, $price_args);
1687
+		$template = apply_filters(
1688
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
+			$ticket
1691
+		);
1692
+		return EEH_Template::display_template($template, $template_args, true);
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @throws DomainException
1698
+	 */
1699
+	public function registration_options_meta_box()
1700
+	{
1701
+		$yes_no_values = array(
1702
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
+		);
1705
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1706
+			array(
1707
+				EEM_Registration::status_id_cancelled,
1708
+				EEM_Registration::status_id_declined,
1709
+				EEM_Registration::status_id_incomplete,
1710
+			),
1711
+			true
1712
+		);
1713
+		//$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
+		$template_args['_event'] = $this->_cpt_model_obj;
1715
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
+			'default_reg_status',
1719
+			$default_reg_status_values,
1720
+			$this->_cpt_model_obj->default_registration_status()
1721
+		);
1722
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1723
+			'display_desc',
1724
+			$yes_no_values,
1725
+			$this->_cpt_model_obj->display_description()
1726
+		);
1727
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
+			'display_ticket_selector',
1729
+			$yes_no_values,
1730
+			$this->_cpt_model_obj->display_ticket_selector(),
1731
+			'',
1732
+			'',
1733
+			false
1734
+		);
1735
+		$template_args['additional_registration_options'] = apply_filters(
1736
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
+			'',
1738
+			$template_args,
1739
+			$yes_no_values,
1740
+			$default_reg_status_values
1741
+		);
1742
+		EEH_Template::display_template(
1743
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
+			$template_args
1745
+		);
1746
+	}
1747
+
1748
+
1749
+
1750
+	/**
1751
+	 * _get_events()
1752
+	 * This method simply returns all the events (for the given _view and paging)
1753
+	 *
1754
+	 * @access public
1755
+	 * @param int  $per_page     count of items per page (20 default);
1756
+	 * @param int  $current_page what is the current page being viewed.
1757
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
+	 *                           If FALSE then we return an array of event objects
1759
+	 *                           that match the given _view and paging parameters.
1760
+	 * @return array an array of event objects.
1761
+	 */
1762
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
+	{
1764
+		$EEME = $this->_event_model();
1765
+		$offset = ($current_page - 1) * $per_page;
1766
+		$limit = $count ? null : $offset . ',' . $per_page;
1767
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
+		if (isset($this->_req_data['month_range'])) {
1770
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
+			//simulate the FIRST day of the month, that fixes issues for months like February
1772
+			//where PHP doesn't know what to assume for date.
1773
+			//@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
+		}
1777
+		$where = array();
1778
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
+		//determine what post_status our condition will have for the query.
1780
+		switch ($status) {
1781
+			case 'month' :
1782
+			case 'today' :
1783
+			case null :
1784
+			case 'all' :
1785
+				break;
1786
+			case 'draft' :
1787
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1788
+				break;
1789
+			default :
1790
+				$where['status'] = $status;
1791
+		}
1792
+		//categories?
1793
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
+			? $this->_req_data['EVT_CAT'] : null;
1795
+		if ( ! empty ($category)) {
1796
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
+			$where['Term_Taxonomy.term_id'] = $category;
1798
+		}
1799
+		//date where conditions
1800
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
+			$DateTime = new DateTime(
1803
+				$year_r . '-' . $month_r . '-01 00:00:00',
1804
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
+			);
1806
+			$start = $DateTime->format(implode(' ', $start_formats));
1807
+			$end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
+				->format('t'))->setTime(23, 59, 59)
1809
+							->format(implode(' ', $start_formats));
1810
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
+			$now = date('Y-m-01');
1818
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
+							->setTime(23, 59, 59)
1822
+							->format(implode(' ', $start_formats));
1823
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
+		}
1825
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
+			$where['EVT_wp_user'] = get_current_user_id();
1827
+		} else {
1828
+			if ( ! isset($where['status'])) {
1829
+				if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
+					$where['OR'] = array(
1831
+						'status*restrict_private' => array('!=', 'private'),
1832
+						'AND'                     => array(
1833
+							'status*inclusive' => array('=', 'private'),
1834
+							'EVT_wp_user'      => get_current_user_id(),
1835
+						),
1836
+					);
1837
+				}
1838
+			}
1839
+		}
1840
+		if (isset($this->_req_data['EVT_wp_user'])) {
1841
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
+			) {
1844
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
+			}
1846
+		}
1847
+		//search query handling
1848
+		if (isset($this->_req_data['s'])) {
1849
+			$search_string = '%' . $this->_req_data['s'] . '%';
1850
+			$where['OR'] = array(
1851
+				'EVT_name'       => array('LIKE', $search_string),
1852
+				'EVT_desc'       => array('LIKE', $search_string),
1853
+				'EVT_short_desc' => array('LIKE', $search_string),
1854
+			);
1855
+		}
1856
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
+		$query_params = apply_filters(
1858
+			'FHEE__Events_Admin_Page__get_events__query_params',
1859
+			array(
1860
+				$where,
1861
+				'limit'    => $limit,
1862
+				'order_by' => $orderby,
1863
+				'order'    => $order,
1864
+				'group_by' => 'EVT_ID',
1865
+			),
1866
+			$this->_req_data
1867
+		);
1868
+		//let's first check if we have special requests coming in.
1869
+		if (isset($this->_req_data['active_status'])) {
1870
+			switch ($this->_req_data['active_status']) {
1871
+				case 'upcoming' :
1872
+					return $EEME->get_upcoming_events($query_params, $count);
1873
+					break;
1874
+				case 'expired' :
1875
+					return $EEME->get_expired_events($query_params, $count);
1876
+					break;
1877
+				case 'active' :
1878
+					return $EEME->get_active_events($query_params, $count);
1879
+					break;
1880
+				case 'inactive' :
1881
+					return $EEME->get_inactive_events($query_params, $count);
1882
+					break;
1883
+			}
1884
+		}
1885
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
+		return $events;
1887
+	}
1888
+
1889
+
1890
+
1891
+	/**
1892
+	 * handling for WordPress CPT actions (trash, restore, delete)
1893
+	 *
1894
+	 * @param string $post_id
1895
+	 */
1896
+	public function trash_cpt_item($post_id)
1897
+	{
1898
+		$this->_req_data['EVT_ID'] = $post_id;
1899
+		$this->_trash_or_restore_event('trash', false);
1900
+	}
1901
+
1902
+
1903
+
1904
+	/**
1905
+	 * @param string $post_id
1906
+	 */
1907
+	public function restore_cpt_item($post_id)
1908
+	{
1909
+		$this->_req_data['EVT_ID'] = $post_id;
1910
+		$this->_trash_or_restore_event('draft', false);
1911
+	}
1912
+
1913
+
1914
+
1915
+	/**
1916
+	 * @param string $post_id
1917
+	 */
1918
+	public function delete_cpt_item($post_id)
1919
+	{
1920
+		$this->_req_data['EVT_ID'] = $post_id;
1921
+		$this->_delete_event(false);
1922
+	}
1923
+
1924
+
1925
+
1926
+	/**
1927
+	 * _trash_or_restore_event
1928
+	 *
1929
+	 * @access protected
1930
+	 * @param  string $event_status
1931
+	 * @param bool    $redirect_after
1932
+	 */
1933
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
+	{
1935
+		//determine the event id and set to array.
1936
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
+		// loop thru events
1938
+		if ($EVT_ID) {
1939
+			// clean status
1940
+			$event_status = sanitize_key($event_status);
1941
+			// grab status
1942
+			if ( ! empty($event_status)) {
1943
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1944
+			} else {
1945
+				$success = false;
1946
+				$msg = esc_html__(
1947
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
+					'event_espresso'
1949
+				);
1950
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
+			}
1952
+		} else {
1953
+			$success = false;
1954
+			$msg = esc_html__(
1955
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
+				'event_espresso'
1957
+			);
1958
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
+		}
1960
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
+		if ($redirect_after) {
1962
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
+		}
1964
+	}
1965
+
1966
+
1967
+
1968
+	/**
1969
+	 * _trash_or_restore_events
1970
+	 *
1971
+	 * @access protected
1972
+	 * @param  string $event_status
1973
+	 * @return void
1974
+	 */
1975
+	protected function _trash_or_restore_events($event_status = 'trash')
1976
+	{
1977
+		// clean status
1978
+		$event_status = sanitize_key($event_status);
1979
+		// grab status
1980
+		if ( ! empty($event_status)) {
1981
+			$success = true;
1982
+			//determine the event id and set to array.
1983
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
+			// loop thru events
1985
+			foreach ($EVT_IDs as $EVT_ID) {
1986
+				if ($EVT_ID = absint($EVT_ID)) {
1987
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1988
+					$success = $results !== false ? $success : false;
1989
+				} else {
1990
+					$msg = sprintf(
1991
+						esc_html__(
1992
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
+							'event_espresso'
1994
+						),
1995
+						$EVT_ID
1996
+					);
1997
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
+					$success = false;
1999
+				}
2000
+			}
2001
+		} else {
2002
+			$success = false;
2003
+			$msg = esc_html__(
2004
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
+				'event_espresso'
2006
+			);
2007
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
+		}
2009
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2010
+		$success = $success ? 2 : false;
2011
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
+	}
2014
+
2015
+
2016
+
2017
+	/**
2018
+	 * _trash_or_restore_events
2019
+	 *
2020
+	 * @access  private
2021
+	 * @param  int    $EVT_ID
2022
+	 * @param  string $event_status
2023
+	 * @return bool
2024
+	 */
2025
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
+	{
2027
+		// grab event id
2028
+		if ( ! $EVT_ID) {
2029
+			$msg = esc_html__(
2030
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2031
+				'event_espresso'
2032
+			);
2033
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
+			return false;
2035
+		}
2036
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
+		// clean status
2038
+		$event_status = sanitize_key($event_status);
2039
+		// grab status
2040
+		if (empty($event_status)) {
2041
+			$msg = esc_html__(
2042
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2043
+				'event_espresso'
2044
+			);
2045
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
+			return false;
2047
+		}
2048
+		// was event trashed or restored ?
2049
+		switch ($event_status) {
2050
+			case 'draft' :
2051
+				$action = 'restored from the trash';
2052
+				$hook = 'AHEE_event_restored_from_trash';
2053
+				break;
2054
+			case 'trash' :
2055
+				$action = 'moved to the trash';
2056
+				$hook = 'AHEE_event_moved_to_trash';
2057
+				break;
2058
+			default :
2059
+				$action = 'updated';
2060
+				$hook = false;
2061
+		}
2062
+		//use class to change status
2063
+		$this->_cpt_model_obj->set_status($event_status);
2064
+		$success = $this->_cpt_model_obj->save();
2065
+		if ($success === false) {
2066
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
+			return false;
2069
+		}
2070
+		if ($hook) {
2071
+			do_action($hook);
2072
+		}
2073
+		return true;
2074
+	}
2075
+
2076
+
2077
+
2078
+	/**
2079
+	 * _delete_event
2080
+	 *
2081
+	 * @access protected
2082
+	 * @param bool $redirect_after
2083
+	 */
2084
+	protected function _delete_event($redirect_after = true)
2085
+	{
2086
+		//determine the event id and set to array.
2087
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
+		// loop thru events
2090
+		if ($EVT_ID) {
2091
+			$success = $this->_permanently_delete_event($EVT_ID);
2092
+			// get list of events with no prices
2093
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
+			// remove this event from the list of events with no prices
2095
+			if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2097
+			}
2098
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
+		} else {
2100
+			$success = false;
2101
+			$msg = esc_html__(
2102
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
+				'event_espresso'
2104
+			);
2105
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
+		}
2107
+		if ($redirect_after) {
2108
+			$this->_redirect_after_action(
2109
+				$success,
2110
+				'Event',
2111
+				'deleted',
2112
+				array('action' => 'default', 'status' => 'trash')
2113
+			);
2114
+		}
2115
+	}
2116
+
2117
+
2118
+
2119
+	/**
2120
+	 * _delete_events
2121
+	 *
2122
+	 * @access protected
2123
+	 * @return void
2124
+	 */
2125
+	protected function _delete_events()
2126
+	{
2127
+		$success = true;
2128
+		// get list of events with no prices
2129
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
+		//determine the event id and set to array.
2131
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
+		// loop thru events
2133
+		foreach ($EVT_IDs as $EVT_ID) {
2134
+			$EVT_ID = absint($EVT_ID);
2135
+			if ($EVT_ID) {
2136
+				$results = $this->_permanently_delete_event($EVT_ID);
2137
+				$success = $results !== false ? $success : false;
2138
+				// remove this event from the list of events with no prices
2139
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2140
+			} else {
2141
+				$success = false;
2142
+				$msg = esc_html__(
2143
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
+					'event_espresso'
2145
+				);
2146
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
+			}
2148
+		}
2149
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2151
+		$success = $success ? 2 : false;
2152
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
+	}
2154
+
2155
+
2156
+
2157
+	/**
2158
+	 * _permanently_delete_event
2159
+	 *
2160
+	 * @access  private
2161
+	 * @param  int $EVT_ID
2162
+	 * @return bool
2163
+	 */
2164
+	private function _permanently_delete_event($EVT_ID = 0)
2165
+	{
2166
+		// grab event id
2167
+		if ( ! $EVT_ID) {
2168
+			$msg = esc_html__(
2169
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2170
+				'event_espresso'
2171
+			);
2172
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
+			return false;
2174
+		}
2175
+		if (
2176
+			! $this->_cpt_model_obj instanceof EE_Event
2177
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2178
+		) {
2179
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
+		}
2181
+		if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
+			return false;
2183
+		}
2184
+		//need to delete related tickets and prices first.
2185
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
+		foreach ($datetimes as $datetime) {
2187
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
+			$tickets = $datetime->get_many_related('Ticket');
2189
+			foreach ($tickets as $ticket) {
2190
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2191
+				$ticket->delete_related_permanently('Price');
2192
+				$ticket->delete_permanently();
2193
+			}
2194
+			$datetime->delete();
2195
+		}
2196
+		//what about related venues or terms?
2197
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
+		foreach ($venues as $venue) {
2199
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
+		}
2201
+		//any attached question groups?
2202
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
+		if ( ! empty($question_groups)) {
2204
+			foreach ($question_groups as $question_group) {
2205
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
+			}
2207
+		}
2208
+		//Message Template Groups
2209
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
+		foreach ($term_taxonomies as $term_taxonomy) {
2213
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
+		}
2215
+		$success = $this->_cpt_model_obj->delete_permanently();
2216
+		// did it all go as planned ?
2217
+		if ($success) {
2218
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
+			EE_Error::add_success($msg);
2220
+		} else {
2221
+			$msg = sprintf(
2222
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
+				$EVT_ID
2224
+			);
2225
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
+			return false;
2227
+		}
2228
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
+		return true;
2230
+	}
2231
+
2232
+
2233
+
2234
+	/**
2235
+	 * get total number of events
2236
+	 *
2237
+	 * @access public
2238
+	 * @return int
2239
+	 */
2240
+	public function total_events()
2241
+	{
2242
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
+		return $count;
2244
+	}
2245
+
2246
+
2247
+
2248
+	/**
2249
+	 * get total number of draft events
2250
+	 *
2251
+	 * @access public
2252
+	 * @return int
2253
+	 */
2254
+	public function total_events_draft()
2255
+	{
2256
+		$where = array(
2257
+			'status' => array('IN', array('draft', 'auto-draft')),
2258
+		);
2259
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
+		return $count;
2261
+	}
2262
+
2263
+
2264
+
2265
+	/**
2266
+	 * get total number of trashed events
2267
+	 *
2268
+	 * @access public
2269
+	 * @return int
2270
+	 */
2271
+	public function total_trashed_events()
2272
+	{
2273
+		$where = array(
2274
+			'status' => 'trash',
2275
+		);
2276
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
+		return $count;
2278
+	}
2279
+
2280
+
2281
+	/**
2282
+	 *    _default_event_settings
2283
+	 *    This generates the Default Settings Tab
2284
+	 *
2285
+	 * @return void
2286
+	 * @throws EE_Error
2287
+	 */
2288
+	protected function _default_event_settings()
2289
+	{
2290
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2291
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2292
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
+		$this->display_admin_page_with_sidebar();
2294
+	}
2295
+
2296
+
2297
+	/**
2298
+	 * Return the form for event settings.
2299
+	 * @return EE_Form_Section_Proper
2300
+	 */
2301
+	protected function _default_event_settings_form()
2302
+	{
2303
+		$registration_config = EE_Registry::instance()->CFG->registration;
2304
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
+		//exclude
2306
+			array(
2307
+				EEM_Registration::status_id_cancelled,
2308
+				EEM_Registration::status_id_declined,
2309
+				EEM_Registration::status_id_incomplete,
2310
+				EEM_Registration::status_id_wait_list,
2311
+			),
2312
+			true
2313
+		);
2314
+		return new EE_Form_Section_Proper(
2315
+			array(
2316
+				'name' => 'update_default_event_settings',
2317
+				'html_id' => 'update_default_event_settings',
2318
+				'html_class' => 'form-table',
2319
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
+				'subsections' => apply_filters(
2321
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
+					array(
2323
+						'default_reg_status' => new EE_Select_Input(
2324
+							$registration_stati_for_selection,
2325
+							array(
2326
+								'default' => isset($registration_config->default_STS_ID)
2327
+											 && array_key_exists(
2328
+												$registration_config->default_STS_ID,
2329
+												$registration_stati_for_selection
2330
+											 )
2331
+											? sanitize_text_field($registration_config->default_STS_ID)
2332
+											: EEM_Registration::status_id_pending_payment,
2333
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
+													. EEH_Template::get_help_tab_link(
2335
+														'default_settings_status_help_tab'
2336
+													),
2337
+								'html_help_text' => esc_html__(
2338
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2339
+									'event_espresso'
2340
+								)
2341
+							)
2342
+						),
2343
+						'default_max_tickets' => new EE_Integer_Input(
2344
+							array(
2345
+								'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
+									? $registration_config->default_maximum_number_of_tickets
2347
+									: EEM_Event::get_default_additional_limit(),
2348
+								'html_label_text' => esc_html__(
2349
+									'Default Maximum Tickets Allowed Per Order:',
2350
+									'event_espresso'
2351
+								) . EEH_Template::get_help_tab_link(
2352
+									'default_maximum_tickets_help_tab"'
2353
+									),
2354
+								'html_help_text' => esc_html__(
2355
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
+									'event_espresso'
2357
+								)
2358
+							)
2359
+						)
2360
+					)
2361
+				)
2362
+			)
2363
+		);
2364
+	}
2365
+
2366
+
2367
+	/**
2368
+	 * _update_default_event_settings
2369
+	 *
2370
+	 * @access protected
2371
+	 * @return void
2372
+	 * @throws EE_Error
2373
+	 */
2374
+	protected function _update_default_event_settings()
2375
+	{
2376
+		$registration_config = EE_Registry::instance()->CFG->registration;
2377
+		$form = $this->_default_event_settings_form();
2378
+		if ($form->was_submitted()) {
2379
+			$form->receive_form_submission();
2380
+			if ($form->is_valid()) {
2381
+				$valid_data = $form->valid_data();
2382
+				if (isset($valid_data['default_reg_status'])) {
2383
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
+				}
2385
+				if (isset($valid_data['default_max_tickets'])) {
2386
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
+				}
2388
+				//update because data was valid!
2389
+				EE_Registry::instance()->CFG->update_espresso_config();
2390
+				EE_Error::overwrite_success();
2391
+				EE_Error::add_success(
2392
+					__('Default Event Settings were updated', 'event_espresso')
2393
+				);
2394
+			}
2395
+		}
2396
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
+	}
2398
+
2399
+
2400
+
2401
+	/*************        Templates        *************/
2402
+	protected function _template_settings()
2403
+	{
2404
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
+		$this->_template_args['preview_img'] = '<img src="'
2406
+											   . EVENTS_ASSETS_URL
2407
+											   . DS
2408
+											   . 'images'
2409
+											   . DS
2410
+											   . 'caffeinated_template_features.jpg" alt="'
2411
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
+											   . '" />';
2413
+		$this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
+				'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2415
+				'event_espresso'
2416
+			) . '</strong>';
2417
+		$this->display_admin_caf_preview_page('template_settings_tab');
2418
+	}
2419
+
2420
+
2421
+	/** Event Category Stuff **/
2422
+	/**
2423
+	 * set the _category property with the category object for the loaded page.
2424
+	 *
2425
+	 * @access private
2426
+	 * @return void
2427
+	 */
2428
+	private function _set_category_object()
2429
+	{
2430
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
+			return;
2432
+		} //already have the category object so get out.
2433
+		//set default category object
2434
+		$this->_set_empty_category_object();
2435
+		//only set if we've got an id
2436
+		if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
+			return;
2438
+		}
2439
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
+		$term = get_term($category_id, 'espresso_event_categories');
2441
+		if ( ! empty($term)) {
2442
+			$this->_category->category_name = $term->name;
2443
+			$this->_category->category_identifier = $term->slug;
2444
+			$this->_category->category_desc = $term->description;
2445
+			$this->_category->id = $term->term_id;
2446
+			$this->_category->parent = $term->parent;
2447
+		}
2448
+	}
2449
+
2450
+
2451
+	/**
2452
+	 * Clears out category properties.
2453
+	 */
2454
+	private function _set_empty_category_object()
2455
+	{
2456
+		$this->_category = new stdClass();
2457
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
+		$this->_category->id = $this->_category->parent = 0;
2459
+	}
2460
+
2461
+
2462
+	/**
2463
+	 * @throws EE_Error
2464
+	 */
2465
+	protected function _category_list_table()
2466
+	{
2467
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
+				'add_category',
2471
+				'add_category',
2472
+				array(),
2473
+				'add-new-h2'
2474
+			);
2475
+		$this->display_admin_list_table_page_with_sidebar();
2476
+	}
2477
+
2478
+
2479
+
2480
+	/**
2481
+	 * Output category details view.
2482
+	 */
2483
+	protected function _category_details($view)
2484
+	{
2485
+		//load formatter helper
2486
+		//load field generator helper
2487
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
+		$this->_set_add_edit_form_tags($route);
2489
+		$this->_set_category_object();
2490
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
+		$delete_action = 'delete_category';
2492
+		//custom redirect
2493
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
+			array('action' => 'category_list'),
2495
+			$this->_admin_base_url
2496
+		);
2497
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
+		//take care of contents
2499
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
+		$this->display_admin_page_with_sidebar();
2501
+	}
2502
+
2503
+
2504
+
2505
+	/**
2506
+	 * Output category details content.
2507
+	 */
2508
+	protected function _category_details_content()
2509
+	{
2510
+		$editor_args['category_desc'] = array(
2511
+			'type'          => 'wp_editor',
2512
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
+			'class'         => 'my_editor_custom',
2514
+			'wpeditor_args' => array('media_buttons' => false),
2515
+		);
2516
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
+		$all_terms = get_terms(
2518
+			array('espresso_event_categories'),
2519
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
+		);
2521
+		//setup category select for term parents.
2522
+		$category_select_values[] = array(
2523
+			'text' => esc_html__('No Parent', 'event_espresso'),
2524
+			'id'   => 0,
2525
+		);
2526
+		foreach ($all_terms as $term) {
2527
+			$category_select_values[] = array(
2528
+				'text' => $term->name,
2529
+				'id'   => $term->term_id,
2530
+			);
2531
+		}
2532
+		$category_select = EEH_Form_Fields::select_input(
2533
+			'category_parent',
2534
+			$category_select_values,
2535
+			$this->_category->parent
2536
+		);
2537
+		$template_args = array(
2538
+			'category'                 => $this->_category,
2539
+			'category_select'          => $category_select,
2540
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
+			'disable'                  => '',
2543
+			'disabled_message'         => false,
2544
+		);
2545
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
+		return EEH_Template::display_template($template, $template_args, true);
2547
+	}
2548
+
2549
+
2550
+	/**
2551
+	 * Handles deleting categories.
2552
+	 */
2553
+	protected function _delete_categories()
2554
+	{
2555
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
+			: (array)$this->_req_data['category_id'];
2557
+		foreach ($cat_ids as $cat_id) {
2558
+			$this->_delete_category($cat_id);
2559
+		}
2560
+		//doesn't matter what page we're coming from... we're going to the same place after delete.
2561
+		$query_args = array(
2562
+			'action' => 'category_list',
2563
+		);
2564
+		$this->_redirect_after_action(0, '', '', $query_args);
2565
+	}
2566
+
2567
+
2568
+
2569
+	/**
2570
+	 * Handles deleting specific category.
2571
+	 * @param int $cat_id
2572
+	 */
2573
+	protected function _delete_category($cat_id)
2574
+	{
2575
+		$cat_id = absint($cat_id);
2576
+		wp_delete_term($cat_id, 'espresso_event_categories');
2577
+	}
2578
+
2579
+
2580
+
2581
+	/**
2582
+	 * Handles triggering the update or insertion of a new category.
2583
+	 * @param bool $new_category  true means we're triggering the insert of a new category.
2584
+	 */
2585
+	protected function _insert_or_update_category($new_category)
2586
+	{
2587
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
+		$success = 0; //we already have a success message so lets not send another.
2589
+		if ($cat_id) {
2590
+			$query_args = array(
2591
+				'action'     => 'edit_category',
2592
+				'EVT_CAT_ID' => $cat_id,
2593
+			);
2594
+		} else {
2595
+			$query_args = array('action' => 'add_category');
2596
+		}
2597
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2598
+	}
2599
+
2600
+
2601
+
2602
+	/**
2603
+	 * Inserts or updates category
2604
+	 * @param bool $update (true indicates we're updating a category).
2605
+	 * @return bool|mixed|string
2606
+	 */
2607
+	private function _insert_category($update = false)
2608
+	{
2609
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
+		if (empty($category_name)) {
2614
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
+			return false;
2617
+		}
2618
+		$term_args = array(
2619
+			'name'        => $category_name,
2620
+			'description' => $category_desc,
2621
+			'parent'      => $category_parent,
2622
+		);
2623
+		//was the category_identifier input disabled?
2624
+		if (isset($this->_req_data['category_identifier'])) {
2625
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2626
+		}
2627
+		$insert_ids = $update
2628
+			? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
+			: wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
+		if ( ! is_array($insert_ids)) {
2631
+			$msg = esc_html__(
2632
+				'An error occurred and the category has not been saved to the database.',
2633
+				'event_espresso'
2634
+			);
2635
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
+		} else {
2637
+			$cat_id = $insert_ids['term_id'];
2638
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
+			EE_Error::add_success($msg);
2640
+		}
2641
+		return $cat_id;
2642
+	}
2643
+
2644
+
2645
+
2646
+	/**
2647
+	 * Gets categories or count of categories matching the arguments in the request.
2648
+	 * @param int  $per_page
2649
+	 * @param int  $current_page
2650
+	 * @param bool $count
2651
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
+	 */
2653
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
+	{
2655
+		//testing term stuff
2656
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
+		$limit = ($current_page - 1) * $per_page;
2659
+		$where = array('taxonomy' => 'espresso_event_categories');
2660
+		if (isset($this->_req_data['s'])) {
2661
+			$sstr = '%' . $this->_req_data['s'] . '%';
2662
+			$where['OR'] = array(
2663
+				'Term.name'   => array('LIKE', $sstr),
2664
+				'description' => array('LIKE', $sstr),
2665
+			);
2666
+		}
2667
+		$query_params = array(
2668
+			$where,
2669
+			'order_by'   => array($orderby => $order),
2670
+			'limit'      => $limit . ',' . $per_page,
2671
+			'force_join' => array('Term'),
2672
+		);
2673
+		$categories = $count
2674
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
+		return $categories;
2677
+	}
2678
+
2679
+	/* end category stuff */
2680
+	/**************/
2681
+
2682
+
2683
+	/**
2684
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2685
+	 * @throws EE_Error
2686
+	 */
2687
+	public function save_timezonestring_setting()
2688
+	{
2689
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2690
+			? $this->_req_data['timezone_selected']
2691
+			: '';
2692
+		if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
+		{
2694
+			EE_Error::add_error(
2695
+				esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
+				__FILE__, __FUNCTION__, __LINE__
2697
+			);
2698
+			$this->_template_args['error'] = true;
2699
+			$this->_return_json();
2700
+		}
2701
+
2702
+		update_option('timezone_string', $timezone_string);
2703
+		EE_Error::add_success(
2704
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2705
+		);
2706
+		$this->_template_args['success'] = true;
2707
+		$this->_return_json(true, array('action' => 'create_new'));
2708
+	}
2709 2709
 }
2710 2710
 //end class Events_Admin_Page
Please login to merge, or discard this patch.
core/db_models/EEM_Attendee.model.php 1 patch
Indentation   +399 added lines, -399 removed lines patch added patch discarded remove patch
@@ -17,413 +17,413 @@
 block discarded – undo
17 17
 class EEM_Attendee extends EEM_CPT_Base
18 18
 {
19 19
 
20
-    // private instance of the Attendee object
21
-    protected static $_instance = null;
20
+	// private instance of the Attendee object
21
+	protected static $_instance = null;
22 22
 
23
-    /**
24
-     * QST_system for questions are strings not integers now,
25
-     * so these constants are deprecated.
26
-     * Please instead use the EEM_Attendee::system_question_* constants
27
-     *
28
-     * @deprecated
29
-     */
30
-    const fname_question_id = 1;
23
+	/**
24
+	 * QST_system for questions are strings not integers now,
25
+	 * so these constants are deprecated.
26
+	 * Please instead use the EEM_Attendee::system_question_* constants
27
+	 *
28
+	 * @deprecated
29
+	 */
30
+	const fname_question_id = 1;
31 31
 
32
-    /**
33
-     * @deprecated
34
-     */
35
-    const lname_question_id = 2;
32
+	/**
33
+	 * @deprecated
34
+	 */
35
+	const lname_question_id = 2;
36 36
 
37 37
 
38
-    /**
39
-     * @deprecated
40
-     */
41
-    const email_question_id = 3;
38
+	/**
39
+	 * @deprecated
40
+	 */
41
+	const email_question_id = 3;
42 42
 
43 43
 
44
-    /**
45
-     * @deprecated
46
-     */
47
-    const address_question_id = 4;
44
+	/**
45
+	 * @deprecated
46
+	 */
47
+	const address_question_id = 4;
48 48
 
49 49
 
50
-    /**
51
-     * @deprecated
52
-     */
53
-    const address2_question_id = 5;
54
-
55
-
56
-    /**
57
-     * @deprecated
58
-     */
59
-    const city_question_id = 6;
60
-
61
-
62
-    /**
63
-     * @deprecated
64
-     */
65
-    const state_question_id = 7;
66
-
67
-
68
-    /**
69
-     * @deprecated
70
-     */
71
-    const country_question_id = 8;
72
-
73
-
74
-    /**
75
-     * @deprecated
76
-     */
77
-    const zip_question_id = 9;
78
-
79
-
80
-    /**
81
-     * @deprecated
82
-     */
83
-    const phone_question_id = 10;
84
-
85
-    /**
86
-     * When looking for questions that correspond to attendee fields,
87
-     * look for the question with this QST_system value.
88
-     * These replace the old constants like EEM_Attendee::*_question_id
89
-     */
90
-    const system_question_fname = 'fname';
91
-
92
-    const system_question_lname = 'lname';
93
-
94
-    const system_question_email = 'email';
95
-
96
-    const system_question_address = 'address';
97
-
98
-    const system_question_address2 = 'address2';
99
-
100
-    const system_question_city = 'city';
101
-
102
-    const system_question_state = 'state';
103
-
104
-    const system_question_country = 'country';
105
-
106
-    const system_question_zip = 'zip';
107
-
108
-    const system_question_phone = 'phone';
109
-
110
-    /**
111
-     * Keys are all the EEM_Attendee::system_question_* constants, which are
112
-     * also all the values of QST_system in the questions table, and values
113
-     * are their corresponding Attendee field names
114
-     *
115
-     * @var array
116
-     */
117
-    protected $_system_question_to_attendee_field_name = array(
118
-        EEM_Attendee::system_question_fname    => 'ATT_fname',
119
-        EEM_Attendee::system_question_lname    => 'ATT_lname',
120
-        EEM_Attendee::system_question_email    => 'ATT_email',
121
-        EEM_Attendee::system_question_address  => 'ATT_address',
122
-        EEM_Attendee::system_question_address2 => 'ATT_address2',
123
-        EEM_Attendee::system_question_city     => 'ATT_city',
124
-        EEM_Attendee::system_question_state    => 'STA_ID',
125
-        EEM_Attendee::system_question_country  => 'CNT_ISO',
126
-        EEM_Attendee::system_question_zip      => 'ATT_zip',
127
-        EEM_Attendee::system_question_phone    => 'ATT_phone',
128
-    );
129
-
130
-
131
-
132
-    /**
133
-     * EEM_Attendee constructor.
134
-     *
135
-     * @param null              $timezone
136
-     * @param ModelFieldFactory $model_field_factory
137
-     * @throws EE_Error
138
-     * @throws InvalidArgumentException
139
-     */
140
-    protected function __construct($timezone = null, ModelFieldFactory $model_field_factory)
141
-    {
142
-        $this->singular_item = esc_html__('Attendee', 'event_espresso');
143
-        $this->plural_item = esc_html__('Attendees', 'event_espresso');
144
-        $this->_tables = array(
145
-            'Attendee_CPT'  => new EE_Primary_Table('posts', 'ID'),
146
-            'Attendee_Meta' => new EE_Secondary_Table(
147
-                'esp_attendee_meta',
148
-                'ATTM_ID',
149
-                'ATT_ID'
150
-            ),
151
-        );
152
-        $this->_fields = array(
153
-            'Attendee_CPT'  => array(
154
-                'ATT_ID'        => $model_field_factory->createPrimaryKeyIntField(
155
-                    'ID',
156
-                    esc_html__('Attendee ID', 'event_espresso')
157
-                ),
158
-                'ATT_full_name' => $model_field_factory->createPlainTextField(
159
-                    'post_title',
160
-                    esc_html__('Attendee Full Name', 'event_espresso'),
161
-                    false,
162
-                    esc_html__('Unknown', 'event_espresso')
163
-                ),
164
-                'ATT_bio'       => $model_field_factory->createPostContentField(
165
-                    'post_content',
166
-                    esc_html__('Attendee Biography', 'event_espresso'),
167
-                    false,
168
-                    esc_html__('No Biography Provided', 'event_espresso')
169
-                ),
170
-                'ATT_slug'      => $model_field_factory->createSlugField(
171
-                    'post_name',
172
-                    esc_html__('Attendee URL Slug', 'event_espresso')
173
-                ),
174
-                'ATT_created'   => $model_field_factory->createDatetimeField(
175
-                    'post_date',
176
-                    esc_html__('Time Attendee Created', 'event_espresso')
177
-                ),
178
-                'ATT_short_bio' => $model_field_factory->createSimpleHtmlField(
179
-                    'post_excerpt',
180
-                    esc_html__('Attendee Short Biography', 'event_espresso'),
181
-                    true,
182
-                    esc_html__('No Biography Provided', 'event_espresso')
183
-                ),
184
-                'ATT_modified'  => $model_field_factory->createDatetimeField(
185
-                    'post_modified',
186
-                    esc_html__('Time Attendee Last Modified', 'event_espresso')
187
-                ),
188
-                'ATT_author'    => $model_field_factory->createWpUserField(
189
-                    'post_author',
190
-                    esc_html__('Creator ID of the first Event attended', 'event_espresso'),
191
-                    false
192
-                ),
193
-                'ATT_parent'    => $model_field_factory->createDbOnlyIntField(
194
-                    'post_parent',
195
-                    esc_html__('Parent Attendee (unused)', 'event_espresso'),
196
-                    false,
197
-                    0
198
-                ),
199
-                'post_type'     => $model_field_factory->createWpPostTypeField('espresso_attendees'),
200
-                'status'        => $model_field_factory->createWpPostStatusField(
201
-                    'post_status',
202
-                    esc_html__('Attendee Status', 'event_espresso'),
203
-                    false,
204
-                    'publish'
205
-                ),
206
-            ),
207
-            'Attendee_Meta' => array(
208
-                'ATTM_ID'      => $model_field_factory->createDbOnlyIntField(
209
-                    'ATTM_ID',
210
-                    esc_html__('Attendee Meta Row ID', 'event_espresso'),
211
-                    false
212
-                ),
213
-                'ATT_ID_fk'    => $model_field_factory->createDbOnlyIntField(
214
-                    'ATT_ID',
215
-                    esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'),
216
-                    false
217
-                ),
218
-                'ATT_fname'    => $model_field_factory->createPlainTextField(
219
-                    'ATT_fname',
220
-                    esc_html__('First Name', 'event_espresso')
221
-                ),
222
-                'ATT_lname'    => $model_field_factory->createPlainTextField(
223
-                    'ATT_lname',
224
-                    esc_html__('Last Name', 'event_espresso')
225
-                ),
226
-                'ATT_address'  => $model_field_factory->createPlainTextField(
227
-                    'ATT_address',
228
-                    esc_html__('Address Part 1', 'event_espresso')
229
-                ),
230
-                'ATT_address2' => $model_field_factory->createPlainTextField(
231
-                    'ATT_address2',
232
-                    esc_html__('Address Part 2', 'event_espresso')
233
-                ),
234
-                'ATT_city'     => $model_field_factory->createPlainTextField(
235
-                    'ATT_city',
236
-                    esc_html__('City', 'event_espresso')
237
-                ),
238
-                'STA_ID'       => $model_field_factory->createForeignKeyIntField(
239
-                    'STA_ID',
240
-                    esc_html__('State', 'event_espresso'),
241
-                    true,
242
-                    0,
243
-                    'State'
244
-                ),
245
-                'CNT_ISO'      => $model_field_factory->createForeignKeyStringField(
246
-                    'CNT_ISO',
247
-                    esc_html__('Country', 'event_espresso'),
248
-                    true,
249
-                    '',
250
-                    'Country'
251
-                ),
252
-                'ATT_zip'      => $model_field_factory->createPlainTextField(
253
-                    'ATT_zip',
254
-                    esc_html__('ZIP/Postal Code', 'event_espresso')
255
-                ),
256
-                'ATT_email'    => $model_field_factory->createEmailField(
257
-                    'ATT_email',
258
-                    esc_html__('Email Address', 'event_espresso')
259
-                ),
260
-                'ATT_phone'    => $model_field_factory->createPlainTextField(
261
-                    'ATT_phone',
262
-                    esc_html__('Phone', 'event_espresso')
263
-                ),
264
-            ),
265
-        );
266
-        $this->_model_relations = array(
267
-            'Registration'      => new EE_Has_Many_Relation(),
268
-            'State'             => new EE_Belongs_To_Relation(),
269
-            'Country'           => new EE_Belongs_To_Relation(),
270
-            'Event'             => new EE_HABTM_Relation('Registration', false),
271
-            'WP_User'           => new EE_Belongs_To_Relation(),
272
-            'Message'           => new EE_Has_Many_Any_Relation(false),
273
-            //allow deletion of attendees even if they have messages in the queue for them.
274
-            'Term_Relationship' => new EE_Has_Many_Relation(),
275
-            'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
276
-        );
277
-        $this->_caps_slug = 'contacts';
278
-        parent::__construct($timezone);
279
-    }
280
-
281
-
282
-
283
-    /**
284
-     * Gets the name of the field on the attendee model corresponding to the system question string
285
-     * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name
286
-     *
287
-     * @param string $system_question_string
288
-     * @return string|null if not found
289
-     */
290
-    public function get_attendee_field_for_system_question($system_question_string)
291
-    {
292
-        return isset($this->_system_question_to_attendee_field_name[$system_question_string])
293
-            ? $this->_system_question_to_attendee_field_name[$system_question_string]
294
-            : null;
295
-    }
296
-
297
-
298
-
299
-    /**
300
-     * Gets mapping from esp_question.QST_system values to their corresponding attendee field names
301
-     *
302
-     * @return array
303
-     */
304
-    public function system_question_to_attendee_field_mapping()
305
-    {
306
-        return $this->_system_question_to_attendee_field_name;
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * Gets all the attendees for a transaction (by using the esp_registration as a join table)
313
-     *
314
-     * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID
315
-     * @return EE_Attendee[]|EE_Base_Class[]
316
-     * @throws EE_Error
317
-     */
318
-    public function get_attendees_for_transaction($transaction_id_or_obj)
319
-    {
320
-        return $this->get_all(
321
-            array(
322
-                array(
323
-                    'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction
324
-                        ? $transaction_id_or_obj->ID()
325
-                        : $transaction_id_or_obj,
326
-                ),
327
-            )
328
-        );
329
-    }
330
-
331
-
332
-
333
-    /**
334
-     * retrieve  a single attendee from db via their ID
335
-     *
336
-     * @param $ATT_ID
337
-     * @return mixed array on success, FALSE on fail
338
-     * @deprecated
339
-     */
340
-    public function get_attendee_by_ID($ATT_ID = false)
341
-    {
342
-        // retrieve a particular EE_Attendee
343
-        return $this->get_one_by_ID($ATT_ID);
344
-    }
345
-
346
-
347
-
348
-    /**
349
-     * retrieve  a single attendee from db via their ID
350
-     *
351
-     * @param array $where_cols_n_values
352
-     * @return mixed array on success, FALSE on fail
353
-     * @throws EE_Error
354
-     */
355
-    public function get_attendee($where_cols_n_values = array())
356
-    {
357
-        if (empty($where_cols_n_values)) {
358
-            return false;
359
-        }
360
-        $attendee = $this->get_all(array($where_cols_n_values));
361
-        if (! empty($attendee)) {
362
-            return array_shift($attendee);
363
-        }
364
-        return false;
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * Search for an existing Attendee record in the DB
371
-     *
372
-     * @param array $where_cols_n_values
373
-     * @return bool|mixed
374
-     * @throws EE_Error
375
-     */
376
-    public function find_existing_attendee($where_cols_n_values = null)
377
-    {
378
-        // search by combo of first and last names plus the email address
379
-        $attendee_data_keys = array(
380
-            'ATT_fname' => $this->_ATT_fname,
381
-            'ATT_lname' => $this->_ATT_lname,
382
-            'ATT_email' => $this->_ATT_email,
383
-        );
384
-        // no search params means attendee object already exists.
385
-        $where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values)
386
-            ? $where_cols_n_values
387
-            : $attendee_data_keys;
388
-        $valid_data = true;
389
-        // check for required values
390
-        $valid_data = isset($where_cols_n_values['ATT_fname']) && ! empty($where_cols_n_values['ATT_fname'])
391
-            ? $valid_data
392
-            : false;
393
-        $valid_data = isset($where_cols_n_values['ATT_lname']) && ! empty($where_cols_n_values['ATT_lname'])
394
-            ? $valid_data
395
-            : false;
396
-        $valid_data = isset($where_cols_n_values['ATT_email']) && ! empty($where_cols_n_values['ATT_email'])
397
-            ? $valid_data
398
-            : false;
399
-        if ($valid_data) {
400
-            $attendee = $this->get_attendee($where_cols_n_values);
401
-            if ($attendee instanceof EE_Attendee) {
402
-                return $attendee;
403
-            }
404
-        }
405
-        return false;
406
-    }
407
-
408
-
409
-
410
-    /**
411
-     * Takes an incoming array of EE_Registration ids
412
-     * and sends back a list of corresponding non duplicate EE_Attendee objects.
413
-     *
414
-     * @since  4.3.0
415
-     * @param  array $ids array of EE_Registration ids
416
-     * @return EE_Attendee[]|EE_Base_Class[]
417
-     * @throws EE_Error
418
-     */
419
-    public function get_array_of_contacts_from_reg_ids($ids)
420
-    {
421
-        $ids = (array)$ids;
422
-        $_where = array(
423
-            'Registration.REG_ID' => array('in', $ids),
424
-        );
425
-        return $this->get_all(array($_where));
426
-    }
50
+	/**
51
+	 * @deprecated
52
+	 */
53
+	const address2_question_id = 5;
54
+
55
+
56
+	/**
57
+	 * @deprecated
58
+	 */
59
+	const city_question_id = 6;
60
+
61
+
62
+	/**
63
+	 * @deprecated
64
+	 */
65
+	const state_question_id = 7;
66
+
67
+
68
+	/**
69
+	 * @deprecated
70
+	 */
71
+	const country_question_id = 8;
72
+
73
+
74
+	/**
75
+	 * @deprecated
76
+	 */
77
+	const zip_question_id = 9;
78
+
79
+
80
+	/**
81
+	 * @deprecated
82
+	 */
83
+	const phone_question_id = 10;
84
+
85
+	/**
86
+	 * When looking for questions that correspond to attendee fields,
87
+	 * look for the question with this QST_system value.
88
+	 * These replace the old constants like EEM_Attendee::*_question_id
89
+	 */
90
+	const system_question_fname = 'fname';
91
+
92
+	const system_question_lname = 'lname';
93
+
94
+	const system_question_email = 'email';
95
+
96
+	const system_question_address = 'address';
97
+
98
+	const system_question_address2 = 'address2';
99
+
100
+	const system_question_city = 'city';
101
+
102
+	const system_question_state = 'state';
103
+
104
+	const system_question_country = 'country';
105
+
106
+	const system_question_zip = 'zip';
107
+
108
+	const system_question_phone = 'phone';
109
+
110
+	/**
111
+	 * Keys are all the EEM_Attendee::system_question_* constants, which are
112
+	 * also all the values of QST_system in the questions table, and values
113
+	 * are their corresponding Attendee field names
114
+	 *
115
+	 * @var array
116
+	 */
117
+	protected $_system_question_to_attendee_field_name = array(
118
+		EEM_Attendee::system_question_fname    => 'ATT_fname',
119
+		EEM_Attendee::system_question_lname    => 'ATT_lname',
120
+		EEM_Attendee::system_question_email    => 'ATT_email',
121
+		EEM_Attendee::system_question_address  => 'ATT_address',
122
+		EEM_Attendee::system_question_address2 => 'ATT_address2',
123
+		EEM_Attendee::system_question_city     => 'ATT_city',
124
+		EEM_Attendee::system_question_state    => 'STA_ID',
125
+		EEM_Attendee::system_question_country  => 'CNT_ISO',
126
+		EEM_Attendee::system_question_zip      => 'ATT_zip',
127
+		EEM_Attendee::system_question_phone    => 'ATT_phone',
128
+	);
129
+
130
+
131
+
132
+	/**
133
+	 * EEM_Attendee constructor.
134
+	 *
135
+	 * @param null              $timezone
136
+	 * @param ModelFieldFactory $model_field_factory
137
+	 * @throws EE_Error
138
+	 * @throws InvalidArgumentException
139
+	 */
140
+	protected function __construct($timezone = null, ModelFieldFactory $model_field_factory)
141
+	{
142
+		$this->singular_item = esc_html__('Attendee', 'event_espresso');
143
+		$this->plural_item = esc_html__('Attendees', 'event_espresso');
144
+		$this->_tables = array(
145
+			'Attendee_CPT'  => new EE_Primary_Table('posts', 'ID'),
146
+			'Attendee_Meta' => new EE_Secondary_Table(
147
+				'esp_attendee_meta',
148
+				'ATTM_ID',
149
+				'ATT_ID'
150
+			),
151
+		);
152
+		$this->_fields = array(
153
+			'Attendee_CPT'  => array(
154
+				'ATT_ID'        => $model_field_factory->createPrimaryKeyIntField(
155
+					'ID',
156
+					esc_html__('Attendee ID', 'event_espresso')
157
+				),
158
+				'ATT_full_name' => $model_field_factory->createPlainTextField(
159
+					'post_title',
160
+					esc_html__('Attendee Full Name', 'event_espresso'),
161
+					false,
162
+					esc_html__('Unknown', 'event_espresso')
163
+				),
164
+				'ATT_bio'       => $model_field_factory->createPostContentField(
165
+					'post_content',
166
+					esc_html__('Attendee Biography', 'event_espresso'),
167
+					false,
168
+					esc_html__('No Biography Provided', 'event_espresso')
169
+				),
170
+				'ATT_slug'      => $model_field_factory->createSlugField(
171
+					'post_name',
172
+					esc_html__('Attendee URL Slug', 'event_espresso')
173
+				),
174
+				'ATT_created'   => $model_field_factory->createDatetimeField(
175
+					'post_date',
176
+					esc_html__('Time Attendee Created', 'event_espresso')
177
+				),
178
+				'ATT_short_bio' => $model_field_factory->createSimpleHtmlField(
179
+					'post_excerpt',
180
+					esc_html__('Attendee Short Biography', 'event_espresso'),
181
+					true,
182
+					esc_html__('No Biography Provided', 'event_espresso')
183
+				),
184
+				'ATT_modified'  => $model_field_factory->createDatetimeField(
185
+					'post_modified',
186
+					esc_html__('Time Attendee Last Modified', 'event_espresso')
187
+				),
188
+				'ATT_author'    => $model_field_factory->createWpUserField(
189
+					'post_author',
190
+					esc_html__('Creator ID of the first Event attended', 'event_espresso'),
191
+					false
192
+				),
193
+				'ATT_parent'    => $model_field_factory->createDbOnlyIntField(
194
+					'post_parent',
195
+					esc_html__('Parent Attendee (unused)', 'event_espresso'),
196
+					false,
197
+					0
198
+				),
199
+				'post_type'     => $model_field_factory->createWpPostTypeField('espresso_attendees'),
200
+				'status'        => $model_field_factory->createWpPostStatusField(
201
+					'post_status',
202
+					esc_html__('Attendee Status', 'event_espresso'),
203
+					false,
204
+					'publish'
205
+				),
206
+			),
207
+			'Attendee_Meta' => array(
208
+				'ATTM_ID'      => $model_field_factory->createDbOnlyIntField(
209
+					'ATTM_ID',
210
+					esc_html__('Attendee Meta Row ID', 'event_espresso'),
211
+					false
212
+				),
213
+				'ATT_ID_fk'    => $model_field_factory->createDbOnlyIntField(
214
+					'ATT_ID',
215
+					esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'),
216
+					false
217
+				),
218
+				'ATT_fname'    => $model_field_factory->createPlainTextField(
219
+					'ATT_fname',
220
+					esc_html__('First Name', 'event_espresso')
221
+				),
222
+				'ATT_lname'    => $model_field_factory->createPlainTextField(
223
+					'ATT_lname',
224
+					esc_html__('Last Name', 'event_espresso')
225
+				),
226
+				'ATT_address'  => $model_field_factory->createPlainTextField(
227
+					'ATT_address',
228
+					esc_html__('Address Part 1', 'event_espresso')
229
+				),
230
+				'ATT_address2' => $model_field_factory->createPlainTextField(
231
+					'ATT_address2',
232
+					esc_html__('Address Part 2', 'event_espresso')
233
+				),
234
+				'ATT_city'     => $model_field_factory->createPlainTextField(
235
+					'ATT_city',
236
+					esc_html__('City', 'event_espresso')
237
+				),
238
+				'STA_ID'       => $model_field_factory->createForeignKeyIntField(
239
+					'STA_ID',
240
+					esc_html__('State', 'event_espresso'),
241
+					true,
242
+					0,
243
+					'State'
244
+				),
245
+				'CNT_ISO'      => $model_field_factory->createForeignKeyStringField(
246
+					'CNT_ISO',
247
+					esc_html__('Country', 'event_espresso'),
248
+					true,
249
+					'',
250
+					'Country'
251
+				),
252
+				'ATT_zip'      => $model_field_factory->createPlainTextField(
253
+					'ATT_zip',
254
+					esc_html__('ZIP/Postal Code', 'event_espresso')
255
+				),
256
+				'ATT_email'    => $model_field_factory->createEmailField(
257
+					'ATT_email',
258
+					esc_html__('Email Address', 'event_espresso')
259
+				),
260
+				'ATT_phone'    => $model_field_factory->createPlainTextField(
261
+					'ATT_phone',
262
+					esc_html__('Phone', 'event_espresso')
263
+				),
264
+			),
265
+		);
266
+		$this->_model_relations = array(
267
+			'Registration'      => new EE_Has_Many_Relation(),
268
+			'State'             => new EE_Belongs_To_Relation(),
269
+			'Country'           => new EE_Belongs_To_Relation(),
270
+			'Event'             => new EE_HABTM_Relation('Registration', false),
271
+			'WP_User'           => new EE_Belongs_To_Relation(),
272
+			'Message'           => new EE_Has_Many_Any_Relation(false),
273
+			//allow deletion of attendees even if they have messages in the queue for them.
274
+			'Term_Relationship' => new EE_Has_Many_Relation(),
275
+			'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
276
+		);
277
+		$this->_caps_slug = 'contacts';
278
+		parent::__construct($timezone);
279
+	}
280
+
281
+
282
+
283
+	/**
284
+	 * Gets the name of the field on the attendee model corresponding to the system question string
285
+	 * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name
286
+	 *
287
+	 * @param string $system_question_string
288
+	 * @return string|null if not found
289
+	 */
290
+	public function get_attendee_field_for_system_question($system_question_string)
291
+	{
292
+		return isset($this->_system_question_to_attendee_field_name[$system_question_string])
293
+			? $this->_system_question_to_attendee_field_name[$system_question_string]
294
+			: null;
295
+	}
296
+
297
+
298
+
299
+	/**
300
+	 * Gets mapping from esp_question.QST_system values to their corresponding attendee field names
301
+	 *
302
+	 * @return array
303
+	 */
304
+	public function system_question_to_attendee_field_mapping()
305
+	{
306
+		return $this->_system_question_to_attendee_field_name;
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * Gets all the attendees for a transaction (by using the esp_registration as a join table)
313
+	 *
314
+	 * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID
315
+	 * @return EE_Attendee[]|EE_Base_Class[]
316
+	 * @throws EE_Error
317
+	 */
318
+	public function get_attendees_for_transaction($transaction_id_or_obj)
319
+	{
320
+		return $this->get_all(
321
+			array(
322
+				array(
323
+					'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction
324
+						? $transaction_id_or_obj->ID()
325
+						: $transaction_id_or_obj,
326
+				),
327
+			)
328
+		);
329
+	}
330
+
331
+
332
+
333
+	/**
334
+	 * retrieve  a single attendee from db via their ID
335
+	 *
336
+	 * @param $ATT_ID
337
+	 * @return mixed array on success, FALSE on fail
338
+	 * @deprecated
339
+	 */
340
+	public function get_attendee_by_ID($ATT_ID = false)
341
+	{
342
+		// retrieve a particular EE_Attendee
343
+		return $this->get_one_by_ID($ATT_ID);
344
+	}
345
+
346
+
347
+
348
+	/**
349
+	 * retrieve  a single attendee from db via their ID
350
+	 *
351
+	 * @param array $where_cols_n_values
352
+	 * @return mixed array on success, FALSE on fail
353
+	 * @throws EE_Error
354
+	 */
355
+	public function get_attendee($where_cols_n_values = array())
356
+	{
357
+		if (empty($where_cols_n_values)) {
358
+			return false;
359
+		}
360
+		$attendee = $this->get_all(array($where_cols_n_values));
361
+		if (! empty($attendee)) {
362
+			return array_shift($attendee);
363
+		}
364
+		return false;
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * Search for an existing Attendee record in the DB
371
+	 *
372
+	 * @param array $where_cols_n_values
373
+	 * @return bool|mixed
374
+	 * @throws EE_Error
375
+	 */
376
+	public function find_existing_attendee($where_cols_n_values = null)
377
+	{
378
+		// search by combo of first and last names plus the email address
379
+		$attendee_data_keys = array(
380
+			'ATT_fname' => $this->_ATT_fname,
381
+			'ATT_lname' => $this->_ATT_lname,
382
+			'ATT_email' => $this->_ATT_email,
383
+		);
384
+		// no search params means attendee object already exists.
385
+		$where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values)
386
+			? $where_cols_n_values
387
+			: $attendee_data_keys;
388
+		$valid_data = true;
389
+		// check for required values
390
+		$valid_data = isset($where_cols_n_values['ATT_fname']) && ! empty($where_cols_n_values['ATT_fname'])
391
+			? $valid_data
392
+			: false;
393
+		$valid_data = isset($where_cols_n_values['ATT_lname']) && ! empty($where_cols_n_values['ATT_lname'])
394
+			? $valid_data
395
+			: false;
396
+		$valid_data = isset($where_cols_n_values['ATT_email']) && ! empty($where_cols_n_values['ATT_email'])
397
+			? $valid_data
398
+			: false;
399
+		if ($valid_data) {
400
+			$attendee = $this->get_attendee($where_cols_n_values);
401
+			if ($attendee instanceof EE_Attendee) {
402
+				return $attendee;
403
+			}
404
+		}
405
+		return false;
406
+	}
407
+
408
+
409
+
410
+	/**
411
+	 * Takes an incoming array of EE_Registration ids
412
+	 * and sends back a list of corresponding non duplicate EE_Attendee objects.
413
+	 *
414
+	 * @since  4.3.0
415
+	 * @param  array $ids array of EE_Registration ids
416
+	 * @return EE_Attendee[]|EE_Base_Class[]
417
+	 * @throws EE_Error
418
+	 */
419
+	public function get_array_of_contacts_from_reg_ids($ids)
420
+	{
421
+		$ids = (array)$ids;
422
+		$_where = array(
423
+			'Registration.REG_ID' => array('in', $ids),
424
+		);
425
+		return $this->get_all(array($_where));
426
+	}
427 427
 
428 428
 
429 429
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 3 patches
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@
 block discarded – undo
1
-<?php use EventEspresso\core\services\orm\ModelFieldFactory;
1
+<?php 
2 2
 
3 3
 if (! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
Please login to merge, or discard this patch.
Indentation   +767 added lines, -767 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\services\orm\ModelFieldFactory;
2 2
 
3 3
 if (! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 require_once(EE_MODELS . 'EEM_CPT_Base.model.php');
7 7
 
@@ -18,772 +18,772 @@  discard block
 block discarded – undo
18 18
 class EEM_Event extends EEM_CPT_Base
19 19
 {
20 20
 
21
-    /**
22
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
23
-     * event
24
-     */
25
-    const sold_out = 'sold_out';
26
-
27
-    /**
28
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
29
-     * date)
30
-     */
31
-    const postponed = 'postponed';
32
-
33
-    /**
34
-     * constant used by status(), indicating that the event will no longer occur
35
-     */
36
-    const cancelled = 'cancelled';
37
-
38
-
39
-    /**
40
-     * @var string
41
-     */
42
-    protected static $_default_reg_status;
43
-
44
-
45
-    /**
46
-     * This is the default for the additional limit field.
47
-     * @var int
48
-     */
49
-    protected static $_default_additional_limit = 10;
50
-
51
-
52
-    /**
53
-     * private instance of the Event object
54
-     *
55
-     * @var EEM_Event
56
-     */
57
-    protected static $_instance;
58
-
59
-
60
-
61
-
62
-    /**
63
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
64
-     *
65
-     * @param string $timezone
66
-     * @throws \EE_Error
67
-     */
68
-    protected function __construct($timezone = null)
69
-    {
70
-        EE_Registry::instance()->load_model('Registration');
71
-        $this->singular_item = esc_html__('Event', 'event_espresso');
72
-        $this->plural_item = esc_html__('Events', 'event_espresso');
73
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
74
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
75
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
76
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
77
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
78
-        //	add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
79
-        $this->_custom_stati = apply_filters(
80
-            'AFEE__EEM_Event__construct___custom_stati',
81
-            array(
82
-                EEM_Event::cancelled => array(
83
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
84
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
85
-                ),
86
-                EEM_Event::postponed => array(
87
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
88
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
89
-                ),
90
-                EEM_Event::sold_out  => array(
91
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
92
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
93
-                ),
94
-            )
95
-        );
96
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
97
-            : self::$_default_reg_status;
98
-        $this->_tables = array(
99
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
100
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
101
-        );
102
-        $this->_fields = array(
103
-            'Event_CPT'  => array(
104
-                'EVT_ID'         => new EE_Primary_Key_Int_Field('ID',
105
-                    esc_html__('Post ID for Event', 'event_espresso')),
106
-                'EVT_name'       => new EE_Plain_Text_Field('post_title', esc_html__('Event Name', 'event_espresso'),
107
-                    false,
108
-                    ''),
109
-                'EVT_desc'       => new EE_Post_Content_Field('post_content',
110
-                    esc_html__('Event Description', 'event_espresso'),
111
-                    false, ''),
112
-                'EVT_slug'       => new EE_Slug_Field('post_name', esc_html__('Event Slug', 'event_espresso'), false,
113
-                    ''),
114
-                'EVT_created'    => new EE_Datetime_Field('post_date',
115
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
116
-                    false, EE_Datetime_Field::now),
117
-                'EVT_short_desc' => new EE_Simple_HTML_Field('post_excerpt',
118
-                    esc_html__('Event Short Description', 'event_espresso'), false, ''),
119
-                'EVT_modified'   => new EE_Datetime_Field('post_modified',
120
-                    esc_html__('Date/Time Event Modified', 'event_espresso'), false, EE_Datetime_Field::now),
121
-                'EVT_wp_user'    => new EE_WP_User_Field('post_author',
122
-                    esc_html__('Event Creator ID', 'event_espresso'),
123
-                    false),
124
-                'parent'         => new EE_Integer_Field('post_parent', esc_html__('Event Parent ID', 'event_espresso'),
125
-                    false,
126
-                    0),
127
-                'EVT_order'      => new EE_Integer_Field('menu_order', esc_html__('Event Menu Order', 'event_espresso'),
128
-                    false,
129
-                    1),
130
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
131
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
132
-                'status'         => new EE_WP_Post_Status_Field('post_status',
133
-                    esc_html__('Event Status', 'event_espresso'),
134
-                    false, 'draft', $this->_custom_stati),
135
-            ),
136
-            'Event_Meta' => array(
137
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field('EVTM_ID',
138
-                    esc_html__('Event Meta Row ID', 'event_espresso'), false),
139
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field('EVT_ID',
140
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'), false),
141
-                'EVT_display_desc'                => new EE_Boolean_Field('EVT_display_desc',
142
-                    esc_html__('Display Description Flag', 'event_espresso'), false, 1),
143
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field('EVT_display_ticket_selector',
144
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'), false, 1),
145
-                'EVT_visible_on'                  => new EE_Datetime_Field('EVT_visible_on',
146
-                    esc_html__('Event Visible Date', 'event_espresso'), true, EE_Datetime_Field::now),
147
-                'EVT_additional_limit'            => new EE_Integer_Field(
148
-                    'EVT_additional_limit',
149
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
150
-                    true,
151
-                    self::$_default_additional_limit
152
-                ),
153
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
154
-                    'EVT_default_registration_status',
155
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'), false,
156
-                    EEM_Event::$_default_reg_status, EEM_Registration::reg_status_array()
157
-                ),
158
-                'EVT_member_only'                 => new EE_Boolean_Field('EVT_member_only',
159
-                    esc_html__('Member-Only Event Flag', 'event_espresso'), false, false),
160
-                'EVT_phone'                       => new EE_Plain_Text_Field('EVT_phone',
161
-                    esc_html__('Event Phone Number', 'event_espresso'), false),
162
-                'EVT_allow_overflow'              => new EE_Boolean_Field('EVT_allow_overflow',
163
-                    esc_html__('Allow Overflow on Event', 'event_espresso'), false, false),
164
-                'EVT_timezone_string'             => new EE_Plain_Text_Field('EVT_timezone_string',
165
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'), false),
166
-                'EVT_external_URL'                => new EE_Plain_Text_Field('EVT_external_URL',
167
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'), true),
168
-                'EVT_donations'                   => new EE_Boolean_Field('EVT_donations',
169
-                    esc_html__('Accept Donations?', 'event_espresso'), false, false),
170
-            ),
171
-        );
172
-        $this->_model_relations = array(
173
-            'Registration'           => new EE_Has_Many_Relation(),
174
-            'Datetime'               => new EE_Has_Many_Relation(),
175
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
176
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
177
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
178
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
179
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
180
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
181
-            'WP_User'                => new EE_Belongs_To_Relation(),
182
-        );
183
-        //this model is generally available for reading
184
-        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
185
-        parent::__construct($timezone);
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     * @param string $default_reg_status
192
-     */
193
-    public static function set_default_reg_status($default_reg_status)
194
-    {
195
-        self::$_default_reg_status = $default_reg_status;
196
-        // if EEM_Event has already been instantiated,
197
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
198
-        if (self::$_instance instanceof EEM_Event) {
199
-            $default_reg_status = new EE_Enum_Text_Field(
200
-                'EVT_default_registration_status',
201
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
202
-                false,
203
-                $default_reg_status,
204
-                EEM_Registration::reg_status_array()
205
-            );
206
-            $default_reg_status->_construct_finalize(
207
-                'Event_Meta',
208
-                'EVT_default_registration_status',
209
-                'EEM_Event'
210
-            );
211
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
212
-        }
213
-    }
214
-
215
-
216
-    /**
217
-     * Used to override the default for the additional limit field.
218
-     * @param $additional_limit
219
-     */
220
-    public static function set_default_additional_limit($additional_limit)
221
-    {
222
-        self::$_default_additional_limit = (int) $additional_limit;
223
-        if (self::$_instance instanceof EEM_Event) {
224
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
225
-                'EVT_additional_limit',
226
-                __('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
227
-                true,
228
-                self::$_default_additional_limit
229
-            );
230
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
231
-                'Event_Meta',
232
-                'EVT_additional_limit',
233
-                'EEM_Event'
234
-            );
235
-        }
236
-    }
237
-
238
-
239
-    /**
240
-     * Return what is currently set as the default additional limit for the event.
241
-     * @return int
242
-     */
243
-    public static function get_default_additional_limit()
244
-    {
245
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
246
-    }
247
-
248
-
249
-    /**
250
-     * get_question_groups
251
-     *
252
-     * @return array
253
-     * @throws \EE_Error
254
-     */
255
-    public function get_all_question_groups()
256
-    {
257
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
258
-            array(
259
-                array('QSG_deleted' => false),
260
-                'order_by' => array('QSG_order' => 'ASC'),
261
-            )
262
-        );
263
-    }
264
-
265
-
266
-
267
-    /**
268
-     * get_question_groups
269
-     *
270
-     * @param int $EVT_ID
271
-     * @return array|bool
272
-     * @throws \EE_Error
273
-     */
274
-    public function get_all_event_question_groups($EVT_ID = 0)
275
-    {
276
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
277
-            EE_Error::add_error(
278
-                esc_html__(
279
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
280
-                    'event_espresso'
281
-                ),
282
-                __FILE__, __FUNCTION__, __LINE__
283
-            );
284
-            return false;
285
-        }
286
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
287
-            array(
288
-                array('EVT_ID' => $EVT_ID),
289
-            )
290
-        );
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * get_question_groups
297
-     *
298
-     * @param int     $EVT_ID
299
-     * @param boolean $for_primary_attendee
300
-     * @return array|bool
301
-     * @throws \EE_Error
302
-     */
303
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
304
-    {
305
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
306
-            EE_Error::add_error(
307
-                esc_html__(
308
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
309
-                    'event_espresso'
310
-                ),
311
-                __FILE__, __FUNCTION__, __LINE__
312
-            );
313
-            return false;
314
-        }
315
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
316
-            array(
317
-                array(
318
-                    'EVT_ID'      => $EVT_ID,
319
-                    'EQG_primary' => $for_primary_attendee,
320
-                ),
321
-            )
322
-        );
323
-    }
324
-
325
-
326
-
327
-    /**
328
-     * get_question_groups
329
-     *
330
-     * @param int             $EVT_ID
331
-     * @param EE_Registration $registration
332
-     * @return array|bool
333
-     * @throws \EE_Error
334
-     */
335
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
336
-    {
337
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
338
-            EE_Error::add_error(
339
-                esc_html__(
340
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
341
-                    'event_espresso'
342
-                ),
343
-                __FILE__, __FUNCTION__, __LINE__
344
-            );
345
-            return false;
346
-        }
347
-        $where_params = array(
348
-            'Event_Question_Group.EVT_ID'      => $EVT_ID,
349
-            'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
350
-            'QSG_deleted'                      => false,
351
-        );
352
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
353
-            array(
354
-                $where_params,
355
-                'order_by' => array('QSG_order' => 'ASC'),
356
-            )
357
-        );
358
-    }
359
-
360
-
361
-
362
-    /**
363
-     * get_question_target_db_column
364
-     *
365
-     * @param string $QSG_IDs csv list of $QSG IDs
366
-     * @return array|bool
367
-     * @throws \EE_Error
368
-     */
369
-    public function get_questions_in_groups($QSG_IDs = '')
370
-    {
371
-        if (empty($QSG_IDs)) {
372
-            EE_Error::add_error(
373
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
374
-                __FILE__, __FUNCTION__, __LINE__
375
-            );
376
-            return false;
377
-        }
378
-        return EE_Registry::instance()->load_model('Question')->get_all(
379
-            array(
380
-                array(
381
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
382
-                    'QST_deleted'           => false,
383
-                    'QST_admin_only'        => is_admin(),
384
-                ),
385
-                'order_by' => 'QST_order',
386
-            )
387
-        );
388
-    }
389
-
390
-
391
-
392
-    /**
393
-     * get_options_for_question
394
-     *
395
-     * @param string $QST_IDs csv list of $QST IDs
396
-     * @return array|bool
397
-     * @throws \EE_Error
398
-     */
399
-    public function get_options_for_question($QST_IDs)
400
-    {
401
-        if (empty($QST_IDs)) {
402
-            EE_Error::add_error(
403
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
404
-                __FILE__, __FUNCTION__, __LINE__
405
-            );
406
-            return false;
407
-        }
408
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
409
-            array(
410
-                array(
411
-                    'Question.QST_ID' => array('IN', $QST_IDs),
412
-                    'QSO_deleted'     => false,
413
-                ),
414
-                'order_by' => 'QSO_ID',
415
-            )
416
-        );
417
-    }
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-    /**
426
-     * Gets all events that are published
427
-     * and have event start time earlier than now and an event end time later than now
428
-     *
429
-     * @param  array $query_params An array of query params to further filter on
430
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
431
-     * @param bool   $count        whether to return the count or not (default FALSE)
432
-     * @return EE_Event[]|int
433
-     * @throws \EE_Error
434
-     */
435
-    public function get_active_events($query_params, $count = false)
436
-    {
437
-        if (array_key_exists(0, $query_params)) {
438
-            $where_params = $query_params[0];
439
-            unset($query_params[0]);
440
-        } else {
441
-            $where_params = array();
442
-        }
443
-        // if we have count make sure we don't include group by
444
-        if ($count && isset($query_params['group_by'])) {
445
-            unset($query_params['group_by']);
446
-        }
447
-        // let's add specific query_params for active_events
448
-        // keep in mind this will override any sent status in the query AND any date queries.
449
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
450
-        //if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
451
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
452
-            $where_params['Datetime.DTT_EVT_start******'] = array(
453
-                '<',
454
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
455
-            );
456
-        } else {
457
-            $where_params['Datetime.DTT_EVT_start'] = array(
458
-                '<',
459
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
460
-            );
461
-        }
462
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
463
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
464
-                '>',
465
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
466
-            );
467
-        } else {
468
-            $where_params['Datetime.DTT_EVT_end'] = array(
469
-                '>',
470
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
471
-            );
472
-        }
473
-        $query_params[0] = $where_params;
474
-        // don't use $query_params with count()
475
-        // because we don't want to include additional query clauses like "GROUP BY"
476
-        return $count
477
-            ? $this->count(array($where_params), 'EVT_ID', true)
478
-            : $this->get_all($query_params);
479
-    }
480
-
481
-
482
-
483
-    /**
484
-     * get all events that are published and have an event start time later than now
485
-     *
486
-     * @param  array $query_params An array of query params to further filter on
487
-     *                             (Note that status and DTT_EVT_start will be overridden)
488
-     * @param bool   $count        whether to return the count or not (default FALSE)
489
-     * @return EE_Event[]|int
490
-     * @throws \EE_Error
491
-     */
492
-    public function get_upcoming_events($query_params, $count = false)
493
-    {
494
-        if (array_key_exists(0, $query_params)) {
495
-            $where_params = $query_params[0];
496
-            unset($query_params[0]);
497
-        } else {
498
-            $where_params = array();
499
-        }
500
-        // if we have count make sure we don't include group by
501
-        if ($count && isset($query_params['group_by'])) {
502
-            unset($query_params['group_by']);
503
-        }
504
-        // let's add specific query_params for active_events
505
-        // keep in mind this will override any sent status in the query AND any date queries.
506
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
507
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
508
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
509
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
510
-                '>',
511
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
512
-            );
513
-        } else {
514
-            $where_params['Datetime.DTT_EVT_start'] = array(
515
-                '>',
516
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
517
-            );
518
-        }
519
-        $query_params[0] = $where_params;
520
-        // don't use $query_params with count()
521
-        // because we don't want to include additional query clauses like "GROUP BY"
522
-        return $count
523
-            ? $this->count(array($where_params), 'EVT_ID', true)
524
-            : $this->get_all($query_params);
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     * Gets all events that are published
531
-     * and have an event end time later than now
532
-     *
533
-     * @param  array $query_params An array of query params to further filter on
534
-     *                             (note that status and DTT_EVT_end will be overridden)
535
-     * @param bool   $count        whether to return the count or not (default FALSE)
536
-     * @return EE_Event[]|int
537
-     * @throws \EE_Error
538
-     */
539
-    public function get_active_and_upcoming_events($query_params, $count = false)
540
-    {
541
-        if (array_key_exists(0, $query_params)) {
542
-            $where_params = $query_params[0];
543
-            unset($query_params[0]);
544
-        } else {
545
-            $where_params = array();
546
-        }
547
-        // if we have count make sure we don't include group by
548
-        if ($count && isset($query_params['group_by'])) {
549
-            unset($query_params['group_by']);
550
-        }
551
-        // let's add specific query_params for active_events
552
-        // keep in mind this will override any sent status in the query AND any date queries.
553
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
554
-        // add where params for DTT_EVT_end
555
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
556
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
557
-                '>',
558
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
559
-            );
560
-        } else {
561
-            $where_params['Datetime.DTT_EVT_end'] = array(
562
-                '>',
563
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
564
-            );
565
-        }
566
-        $query_params[0] = $where_params;
567
-        // don't use $query_params with count()
568
-        // because we don't want to include additional query clauses like "GROUP BY"
569
-        return $count
570
-            ? $this->count(array($where_params), 'EVT_ID', true)
571
-            : $this->get_all($query_params);
572
-    }
573
-
574
-
575
-
576
-    /**
577
-     * This only returns events that are expired.
578
-     * They may still be published but all their datetimes have expired.
579
-     *
580
-     * @param  array $query_params An array of query params to further filter on
581
-     *                             (note that status and DTT_EVT_end will be overridden)
582
-     * @param bool   $count        whether to return the count or not (default FALSE)
583
-     * @return EE_Event[]|int
584
-     * @throws \EE_Error
585
-     */
586
-    public function get_expired_events($query_params, $count = false)
587
-    {
588
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
589
-        // if we have count make sure we don't include group by
590
-        if ($count && isset($query_params['group_by'])) {
591
-            unset($query_params['group_by']);
592
-        }
593
-        // let's add specific query_params for active_events
594
-        // keep in mind this will override any sent status in the query AND any date queries.
595
-        if (isset($where_params['status'])) {
596
-            unset($where_params['status']);
597
-        }
598
-        $exclude_query = $query_params;
599
-        if (isset($exclude_query[0])) {
600
-            unset($exclude_query[0]);
601
-        }
602
-        $exclude_query[0] = array(
603
-            'Datetime.DTT_EVT_end' => array(
604
-                '>',
605
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
606
-            ),
607
-        );
608
-        // first get all events that have datetimes where its not expired.
609
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
610
-        $event_ids = array_keys($event_ids);
611
-        // if we have any additional query_params, let's add them to the 'AND' condition
612
-        $and_condition = array(
613
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
614
-            'EVT_ID'               => array('NOT IN', $event_ids),
615
-        );
616
-        if (isset($where_params['OR'])) {
617
-            $and_condition['OR'] = $where_params['OR'];
618
-            unset($where_params['OR']);
619
-        }
620
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
621
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
622
-            unset($where_params['Datetime.DTT_EVT_end']);
623
-        }
624
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
625
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
626
-            unset($where_params['Datetime.DTT_EVT_start']);
627
-        }
628
-        // merge remaining $where params with the and conditions.
629
-        $where_params['AND'] = array_merge($and_condition, $where_params);
630
-        $query_params[0] = $where_params;
631
-        // don't use $query_params with count()
632
-        // because we don't want to include additional query clauses like "GROUP BY"
633
-        return $count
634
-            ? $this->count(array($where_params), 'EVT_ID', true)
635
-            : $this->get_all($query_params);
636
-    }
637
-
638
-
639
-
640
-    /**
641
-     * This basically just returns the events that do not have the publish status.
642
-     *
643
-     * @param  array   $query_params An array of query params to further filter on
644
-     *                               (note that status will be overwritten)
645
-     * @param  boolean $count        whether to return the count or not (default FALSE)
646
-     * @return EE_Event[]|int
647
-     * @throws \EE_Error
648
-     */
649
-    public function get_inactive_events($query_params, $count = false)
650
-    {
651
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
652
-        // let's add in specific query_params for inactive events.
653
-        if (isset($where_params['status'])) {
654
-            unset($where_params['status']);
655
-        }
656
-        // if we have count make sure we don't include group by
657
-        if ($count && isset($query_params['group_by'])) {
658
-            unset($query_params['group_by']);
659
-        }
660
-        // if we have any additional query_params, let's add them to the 'AND' condition
661
-        $where_params['AND']['status'] = array('!=', 'publish');
662
-        if (isset($where_params['OR'])) {
663
-            $where_params['AND']['OR'] = $where_params['OR'];
664
-            unset($where_params['OR']);
665
-        }
666
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
667
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
668
-            unset($where_params['Datetime.DTT_EVT_end']);
669
-        }
670
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
671
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
672
-            unset($where_params['Datetime.DTT_EVT_start']);
673
-        }
674
-        $query_params[0] = $where_params;
675
-        // don't use $query_params with count()
676
-        // because we don't want to include additional query clauses like "GROUP BY"
677
-        return $count
678
-            ? $this->count(array($where_params), 'EVT_ID', true)
679
-            : $this->get_all($query_params);
680
-    }
681
-
682
-
683
-
684
-    /**
685
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
686
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
687
-     * attached to the event. See parent for param descriptions
688
-     *
689
-     * @param        $id_or_obj
690
-     * @param        $other_model_id_or_obj
691
-     * @param string $relationName
692
-     * @param array  $where_query
693
-     * @return EE_Base_Class
694
-     * @throws EE_Error
695
-     */
696
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
697
-    {
698
-        if ($relationName === 'Price') {
699
-            //let's get the PRC object for the given ID to make sure that we aren't dealing with a default
700
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
701
-            //if EVT_ID = 0, then this is a default
702
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
703
-                //let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
704
-                $prc_chk->set('PRC_ID', 0);
705
-            }
706
-            //run parent
707
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
708
-        }
709
-        //otherwise carry on as normal
710
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
711
-    }
712
-
713
-
714
-
715
-    /******************** DEPRECATED METHODS ********************/
716
-
717
-
718
-
719
-    /**
720
-     * _get_question_target_db_column
721
-     *
722
-     * @deprecated as of 4.8.32.rc.001. Instead consider using
723
-     *             EE_Registration_Custom_Questions_Form located in
724
-     *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
725
-     * @access     public
726
-     * @param    EE_Registration $registration (so existing answers for registration are included)
727
-     * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
728
-     *                                         registration).
729
-     * @throws EE_Error
730
-     * @return    array
731
-     */
732
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
733
-    {
734
-        if (empty($EVT_ID)) {
735
-            throw new EE_Error(__('An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
736
-                'event_espresso'));
737
-        }
738
-        $questions = array();
739
-        // get all question groups for event
740
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
741
-        if (! empty($qgs)) {
742
-            foreach ($qgs as $qg) {
743
-                $qsts = $qg->questions();
744
-                $questions[$qg->ID()] = $qg->model_field_array();
745
-                $questions[$qg->ID()]['QSG_questions'] = array();
746
-                foreach ($qsts as $qst) {
747
-                    if ($qst->is_system_question()) {
748
-                        continue;
749
-                    }
750
-                    $answer = EEM_Answer::instance()->get_one(array(
751
-                        array(
752
-                            'QST_ID' => $qst->ID(),
753
-                            'REG_ID' => $registration->ID(),
754
-                        ),
755
-                    ));
756
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
757
-                    $qst_name = $qstn_id = $qst->ID();
758
-                    $ans_id = $answer->ID();
759
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
760
-                    $input_name = '';
761
-                    $input_id = sanitize_key($qst->display_text());
762
-                    $input_class = '';
763
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
764
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
765
-                                                                                           . $input_name
766
-                                                                                           . $qst_name;
767
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
768
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
769
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
770
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
771
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
772
-                    //leave responses as-is, don't convert stuff into html entities please!
773
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
774
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
775
-                        $QSOs = $qst->options(true, $answer->value());
776
-                        if (is_array($QSOs)) {
777
-                            foreach ($QSOs as $QSO_ID => $QSO) {
778
-                                $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
779
-                            }
780
-                        }
781
-                    }
782
-                }
783
-            }
784
-        }
785
-        return $questions;
786
-    }
21
+	/**
22
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
23
+	 * event
24
+	 */
25
+	const sold_out = 'sold_out';
26
+
27
+	/**
28
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
29
+	 * date)
30
+	 */
31
+	const postponed = 'postponed';
32
+
33
+	/**
34
+	 * constant used by status(), indicating that the event will no longer occur
35
+	 */
36
+	const cancelled = 'cancelled';
37
+
38
+
39
+	/**
40
+	 * @var string
41
+	 */
42
+	protected static $_default_reg_status;
43
+
44
+
45
+	/**
46
+	 * This is the default for the additional limit field.
47
+	 * @var int
48
+	 */
49
+	protected static $_default_additional_limit = 10;
50
+
51
+
52
+	/**
53
+	 * private instance of the Event object
54
+	 *
55
+	 * @var EEM_Event
56
+	 */
57
+	protected static $_instance;
58
+
59
+
60
+
61
+
62
+	/**
63
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
64
+	 *
65
+	 * @param string $timezone
66
+	 * @throws \EE_Error
67
+	 */
68
+	protected function __construct($timezone = null)
69
+	{
70
+		EE_Registry::instance()->load_model('Registration');
71
+		$this->singular_item = esc_html__('Event', 'event_espresso');
72
+		$this->plural_item = esc_html__('Events', 'event_espresso');
73
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
74
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
75
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
76
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
77
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
78
+		//	add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
79
+		$this->_custom_stati = apply_filters(
80
+			'AFEE__EEM_Event__construct___custom_stati',
81
+			array(
82
+				EEM_Event::cancelled => array(
83
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
84
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
85
+				),
86
+				EEM_Event::postponed => array(
87
+					'label'  => esc_html__('Postponed', 'event_espresso'),
88
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
89
+				),
90
+				EEM_Event::sold_out  => array(
91
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
92
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
93
+				),
94
+			)
95
+		);
96
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
97
+			: self::$_default_reg_status;
98
+		$this->_tables = array(
99
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
100
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
101
+		);
102
+		$this->_fields = array(
103
+			'Event_CPT'  => array(
104
+				'EVT_ID'         => new EE_Primary_Key_Int_Field('ID',
105
+					esc_html__('Post ID for Event', 'event_espresso')),
106
+				'EVT_name'       => new EE_Plain_Text_Field('post_title', esc_html__('Event Name', 'event_espresso'),
107
+					false,
108
+					''),
109
+				'EVT_desc'       => new EE_Post_Content_Field('post_content',
110
+					esc_html__('Event Description', 'event_espresso'),
111
+					false, ''),
112
+				'EVT_slug'       => new EE_Slug_Field('post_name', esc_html__('Event Slug', 'event_espresso'), false,
113
+					''),
114
+				'EVT_created'    => new EE_Datetime_Field('post_date',
115
+					esc_html__('Date/Time Event Created', 'event_espresso'),
116
+					false, EE_Datetime_Field::now),
117
+				'EVT_short_desc' => new EE_Simple_HTML_Field('post_excerpt',
118
+					esc_html__('Event Short Description', 'event_espresso'), false, ''),
119
+				'EVT_modified'   => new EE_Datetime_Field('post_modified',
120
+					esc_html__('Date/Time Event Modified', 'event_espresso'), false, EE_Datetime_Field::now),
121
+				'EVT_wp_user'    => new EE_WP_User_Field('post_author',
122
+					esc_html__('Event Creator ID', 'event_espresso'),
123
+					false),
124
+				'parent'         => new EE_Integer_Field('post_parent', esc_html__('Event Parent ID', 'event_espresso'),
125
+					false,
126
+					0),
127
+				'EVT_order'      => new EE_Integer_Field('menu_order', esc_html__('Event Menu Order', 'event_espresso'),
128
+					false,
129
+					1),
130
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
131
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
132
+				'status'         => new EE_WP_Post_Status_Field('post_status',
133
+					esc_html__('Event Status', 'event_espresso'),
134
+					false, 'draft', $this->_custom_stati),
135
+			),
136
+			'Event_Meta' => array(
137
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field('EVTM_ID',
138
+					esc_html__('Event Meta Row ID', 'event_espresso'), false),
139
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field('EVT_ID',
140
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'), false),
141
+				'EVT_display_desc'                => new EE_Boolean_Field('EVT_display_desc',
142
+					esc_html__('Display Description Flag', 'event_espresso'), false, 1),
143
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field('EVT_display_ticket_selector',
144
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'), false, 1),
145
+				'EVT_visible_on'                  => new EE_Datetime_Field('EVT_visible_on',
146
+					esc_html__('Event Visible Date', 'event_espresso'), true, EE_Datetime_Field::now),
147
+				'EVT_additional_limit'            => new EE_Integer_Field(
148
+					'EVT_additional_limit',
149
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
150
+					true,
151
+					self::$_default_additional_limit
152
+				),
153
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
154
+					'EVT_default_registration_status',
155
+					esc_html__('Default Registration Status on this Event', 'event_espresso'), false,
156
+					EEM_Event::$_default_reg_status, EEM_Registration::reg_status_array()
157
+				),
158
+				'EVT_member_only'                 => new EE_Boolean_Field('EVT_member_only',
159
+					esc_html__('Member-Only Event Flag', 'event_espresso'), false, false),
160
+				'EVT_phone'                       => new EE_Plain_Text_Field('EVT_phone',
161
+					esc_html__('Event Phone Number', 'event_espresso'), false),
162
+				'EVT_allow_overflow'              => new EE_Boolean_Field('EVT_allow_overflow',
163
+					esc_html__('Allow Overflow on Event', 'event_espresso'), false, false),
164
+				'EVT_timezone_string'             => new EE_Plain_Text_Field('EVT_timezone_string',
165
+					esc_html__('Timezone (name) for Event times', 'event_espresso'), false),
166
+				'EVT_external_URL'                => new EE_Plain_Text_Field('EVT_external_URL',
167
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'), true),
168
+				'EVT_donations'                   => new EE_Boolean_Field('EVT_donations',
169
+					esc_html__('Accept Donations?', 'event_espresso'), false, false),
170
+			),
171
+		);
172
+		$this->_model_relations = array(
173
+			'Registration'           => new EE_Has_Many_Relation(),
174
+			'Datetime'               => new EE_Has_Many_Relation(),
175
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
176
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
177
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
178
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
179
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
180
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
181
+			'WP_User'                => new EE_Belongs_To_Relation(),
182
+		);
183
+		//this model is generally available for reading
184
+		$this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
185
+		parent::__construct($timezone);
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 * @param string $default_reg_status
192
+	 */
193
+	public static function set_default_reg_status($default_reg_status)
194
+	{
195
+		self::$_default_reg_status = $default_reg_status;
196
+		// if EEM_Event has already been instantiated,
197
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
198
+		if (self::$_instance instanceof EEM_Event) {
199
+			$default_reg_status = new EE_Enum_Text_Field(
200
+				'EVT_default_registration_status',
201
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
202
+				false,
203
+				$default_reg_status,
204
+				EEM_Registration::reg_status_array()
205
+			);
206
+			$default_reg_status->_construct_finalize(
207
+				'Event_Meta',
208
+				'EVT_default_registration_status',
209
+				'EEM_Event'
210
+			);
211
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
212
+		}
213
+	}
214
+
215
+
216
+	/**
217
+	 * Used to override the default for the additional limit field.
218
+	 * @param $additional_limit
219
+	 */
220
+	public static function set_default_additional_limit($additional_limit)
221
+	{
222
+		self::$_default_additional_limit = (int) $additional_limit;
223
+		if (self::$_instance instanceof EEM_Event) {
224
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
225
+				'EVT_additional_limit',
226
+				__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
227
+				true,
228
+				self::$_default_additional_limit
229
+			);
230
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
231
+				'Event_Meta',
232
+				'EVT_additional_limit',
233
+				'EEM_Event'
234
+			);
235
+		}
236
+	}
237
+
238
+
239
+	/**
240
+	 * Return what is currently set as the default additional limit for the event.
241
+	 * @return int
242
+	 */
243
+	public static function get_default_additional_limit()
244
+	{
245
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
246
+	}
247
+
248
+
249
+	/**
250
+	 * get_question_groups
251
+	 *
252
+	 * @return array
253
+	 * @throws \EE_Error
254
+	 */
255
+	public function get_all_question_groups()
256
+	{
257
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
258
+			array(
259
+				array('QSG_deleted' => false),
260
+				'order_by' => array('QSG_order' => 'ASC'),
261
+			)
262
+		);
263
+	}
264
+
265
+
266
+
267
+	/**
268
+	 * get_question_groups
269
+	 *
270
+	 * @param int $EVT_ID
271
+	 * @return array|bool
272
+	 * @throws \EE_Error
273
+	 */
274
+	public function get_all_event_question_groups($EVT_ID = 0)
275
+	{
276
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
277
+			EE_Error::add_error(
278
+				esc_html__(
279
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
280
+					'event_espresso'
281
+				),
282
+				__FILE__, __FUNCTION__, __LINE__
283
+			);
284
+			return false;
285
+		}
286
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
287
+			array(
288
+				array('EVT_ID' => $EVT_ID),
289
+			)
290
+		);
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * get_question_groups
297
+	 *
298
+	 * @param int     $EVT_ID
299
+	 * @param boolean $for_primary_attendee
300
+	 * @return array|bool
301
+	 * @throws \EE_Error
302
+	 */
303
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
304
+	{
305
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
306
+			EE_Error::add_error(
307
+				esc_html__(
308
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
309
+					'event_espresso'
310
+				),
311
+				__FILE__, __FUNCTION__, __LINE__
312
+			);
313
+			return false;
314
+		}
315
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
316
+			array(
317
+				array(
318
+					'EVT_ID'      => $EVT_ID,
319
+					'EQG_primary' => $for_primary_attendee,
320
+				),
321
+			)
322
+		);
323
+	}
324
+
325
+
326
+
327
+	/**
328
+	 * get_question_groups
329
+	 *
330
+	 * @param int             $EVT_ID
331
+	 * @param EE_Registration $registration
332
+	 * @return array|bool
333
+	 * @throws \EE_Error
334
+	 */
335
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
336
+	{
337
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
338
+			EE_Error::add_error(
339
+				esc_html__(
340
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
341
+					'event_espresso'
342
+				),
343
+				__FILE__, __FUNCTION__, __LINE__
344
+			);
345
+			return false;
346
+		}
347
+		$where_params = array(
348
+			'Event_Question_Group.EVT_ID'      => $EVT_ID,
349
+			'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
350
+			'QSG_deleted'                      => false,
351
+		);
352
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
353
+			array(
354
+				$where_params,
355
+				'order_by' => array('QSG_order' => 'ASC'),
356
+			)
357
+		);
358
+	}
359
+
360
+
361
+
362
+	/**
363
+	 * get_question_target_db_column
364
+	 *
365
+	 * @param string $QSG_IDs csv list of $QSG IDs
366
+	 * @return array|bool
367
+	 * @throws \EE_Error
368
+	 */
369
+	public function get_questions_in_groups($QSG_IDs = '')
370
+	{
371
+		if (empty($QSG_IDs)) {
372
+			EE_Error::add_error(
373
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
374
+				__FILE__, __FUNCTION__, __LINE__
375
+			);
376
+			return false;
377
+		}
378
+		return EE_Registry::instance()->load_model('Question')->get_all(
379
+			array(
380
+				array(
381
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
382
+					'QST_deleted'           => false,
383
+					'QST_admin_only'        => is_admin(),
384
+				),
385
+				'order_by' => 'QST_order',
386
+			)
387
+		);
388
+	}
389
+
390
+
391
+
392
+	/**
393
+	 * get_options_for_question
394
+	 *
395
+	 * @param string $QST_IDs csv list of $QST IDs
396
+	 * @return array|bool
397
+	 * @throws \EE_Error
398
+	 */
399
+	public function get_options_for_question($QST_IDs)
400
+	{
401
+		if (empty($QST_IDs)) {
402
+			EE_Error::add_error(
403
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
404
+				__FILE__, __FUNCTION__, __LINE__
405
+			);
406
+			return false;
407
+		}
408
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
409
+			array(
410
+				array(
411
+					'Question.QST_ID' => array('IN', $QST_IDs),
412
+					'QSO_deleted'     => false,
413
+				),
414
+				'order_by' => 'QSO_ID',
415
+			)
416
+		);
417
+	}
418
+
419
+
420
+
421
+
422
+
423
+
424
+
425
+	/**
426
+	 * Gets all events that are published
427
+	 * and have event start time earlier than now and an event end time later than now
428
+	 *
429
+	 * @param  array $query_params An array of query params to further filter on
430
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
431
+	 * @param bool   $count        whether to return the count or not (default FALSE)
432
+	 * @return EE_Event[]|int
433
+	 * @throws \EE_Error
434
+	 */
435
+	public function get_active_events($query_params, $count = false)
436
+	{
437
+		if (array_key_exists(0, $query_params)) {
438
+			$where_params = $query_params[0];
439
+			unset($query_params[0]);
440
+		} else {
441
+			$where_params = array();
442
+		}
443
+		// if we have count make sure we don't include group by
444
+		if ($count && isset($query_params['group_by'])) {
445
+			unset($query_params['group_by']);
446
+		}
447
+		// let's add specific query_params for active_events
448
+		// keep in mind this will override any sent status in the query AND any date queries.
449
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
450
+		//if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
451
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
452
+			$where_params['Datetime.DTT_EVT_start******'] = array(
453
+				'<',
454
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
455
+			);
456
+		} else {
457
+			$where_params['Datetime.DTT_EVT_start'] = array(
458
+				'<',
459
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
460
+			);
461
+		}
462
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
463
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
464
+				'>',
465
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
466
+			);
467
+		} else {
468
+			$where_params['Datetime.DTT_EVT_end'] = array(
469
+				'>',
470
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
471
+			);
472
+		}
473
+		$query_params[0] = $where_params;
474
+		// don't use $query_params with count()
475
+		// because we don't want to include additional query clauses like "GROUP BY"
476
+		return $count
477
+			? $this->count(array($where_params), 'EVT_ID', true)
478
+			: $this->get_all($query_params);
479
+	}
480
+
481
+
482
+
483
+	/**
484
+	 * get all events that are published and have an event start time later than now
485
+	 *
486
+	 * @param  array $query_params An array of query params to further filter on
487
+	 *                             (Note that status and DTT_EVT_start will be overridden)
488
+	 * @param bool   $count        whether to return the count or not (default FALSE)
489
+	 * @return EE_Event[]|int
490
+	 * @throws \EE_Error
491
+	 */
492
+	public function get_upcoming_events($query_params, $count = false)
493
+	{
494
+		if (array_key_exists(0, $query_params)) {
495
+			$where_params = $query_params[0];
496
+			unset($query_params[0]);
497
+		} else {
498
+			$where_params = array();
499
+		}
500
+		// if we have count make sure we don't include group by
501
+		if ($count && isset($query_params['group_by'])) {
502
+			unset($query_params['group_by']);
503
+		}
504
+		// let's add specific query_params for active_events
505
+		// keep in mind this will override any sent status in the query AND any date queries.
506
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
507
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
508
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
509
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
510
+				'>',
511
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
512
+			);
513
+		} else {
514
+			$where_params['Datetime.DTT_EVT_start'] = array(
515
+				'>',
516
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
517
+			);
518
+		}
519
+		$query_params[0] = $where_params;
520
+		// don't use $query_params with count()
521
+		// because we don't want to include additional query clauses like "GROUP BY"
522
+		return $count
523
+			? $this->count(array($where_params), 'EVT_ID', true)
524
+			: $this->get_all($query_params);
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 * Gets all events that are published
531
+	 * and have an event end time later than now
532
+	 *
533
+	 * @param  array $query_params An array of query params to further filter on
534
+	 *                             (note that status and DTT_EVT_end will be overridden)
535
+	 * @param bool   $count        whether to return the count or not (default FALSE)
536
+	 * @return EE_Event[]|int
537
+	 * @throws \EE_Error
538
+	 */
539
+	public function get_active_and_upcoming_events($query_params, $count = false)
540
+	{
541
+		if (array_key_exists(0, $query_params)) {
542
+			$where_params = $query_params[0];
543
+			unset($query_params[0]);
544
+		} else {
545
+			$where_params = array();
546
+		}
547
+		// if we have count make sure we don't include group by
548
+		if ($count && isset($query_params['group_by'])) {
549
+			unset($query_params['group_by']);
550
+		}
551
+		// let's add specific query_params for active_events
552
+		// keep in mind this will override any sent status in the query AND any date queries.
553
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
554
+		// add where params for DTT_EVT_end
555
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
556
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
557
+				'>',
558
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
559
+			);
560
+		} else {
561
+			$where_params['Datetime.DTT_EVT_end'] = array(
562
+				'>',
563
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
564
+			);
565
+		}
566
+		$query_params[0] = $where_params;
567
+		// don't use $query_params with count()
568
+		// because we don't want to include additional query clauses like "GROUP BY"
569
+		return $count
570
+			? $this->count(array($where_params), 'EVT_ID', true)
571
+			: $this->get_all($query_params);
572
+	}
573
+
574
+
575
+
576
+	/**
577
+	 * This only returns events that are expired.
578
+	 * They may still be published but all their datetimes have expired.
579
+	 *
580
+	 * @param  array $query_params An array of query params to further filter on
581
+	 *                             (note that status and DTT_EVT_end will be overridden)
582
+	 * @param bool   $count        whether to return the count or not (default FALSE)
583
+	 * @return EE_Event[]|int
584
+	 * @throws \EE_Error
585
+	 */
586
+	public function get_expired_events($query_params, $count = false)
587
+	{
588
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
589
+		// if we have count make sure we don't include group by
590
+		if ($count && isset($query_params['group_by'])) {
591
+			unset($query_params['group_by']);
592
+		}
593
+		// let's add specific query_params for active_events
594
+		// keep in mind this will override any sent status in the query AND any date queries.
595
+		if (isset($where_params['status'])) {
596
+			unset($where_params['status']);
597
+		}
598
+		$exclude_query = $query_params;
599
+		if (isset($exclude_query[0])) {
600
+			unset($exclude_query[0]);
601
+		}
602
+		$exclude_query[0] = array(
603
+			'Datetime.DTT_EVT_end' => array(
604
+				'>',
605
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
606
+			),
607
+		);
608
+		// first get all events that have datetimes where its not expired.
609
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
610
+		$event_ids = array_keys($event_ids);
611
+		// if we have any additional query_params, let's add them to the 'AND' condition
612
+		$and_condition = array(
613
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
614
+			'EVT_ID'               => array('NOT IN', $event_ids),
615
+		);
616
+		if (isset($where_params['OR'])) {
617
+			$and_condition['OR'] = $where_params['OR'];
618
+			unset($where_params['OR']);
619
+		}
620
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
621
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
622
+			unset($where_params['Datetime.DTT_EVT_end']);
623
+		}
624
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
625
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
626
+			unset($where_params['Datetime.DTT_EVT_start']);
627
+		}
628
+		// merge remaining $where params with the and conditions.
629
+		$where_params['AND'] = array_merge($and_condition, $where_params);
630
+		$query_params[0] = $where_params;
631
+		// don't use $query_params with count()
632
+		// because we don't want to include additional query clauses like "GROUP BY"
633
+		return $count
634
+			? $this->count(array($where_params), 'EVT_ID', true)
635
+			: $this->get_all($query_params);
636
+	}
637
+
638
+
639
+
640
+	/**
641
+	 * This basically just returns the events that do not have the publish status.
642
+	 *
643
+	 * @param  array   $query_params An array of query params to further filter on
644
+	 *                               (note that status will be overwritten)
645
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
646
+	 * @return EE_Event[]|int
647
+	 * @throws \EE_Error
648
+	 */
649
+	public function get_inactive_events($query_params, $count = false)
650
+	{
651
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
652
+		// let's add in specific query_params for inactive events.
653
+		if (isset($where_params['status'])) {
654
+			unset($where_params['status']);
655
+		}
656
+		// if we have count make sure we don't include group by
657
+		if ($count && isset($query_params['group_by'])) {
658
+			unset($query_params['group_by']);
659
+		}
660
+		// if we have any additional query_params, let's add them to the 'AND' condition
661
+		$where_params['AND']['status'] = array('!=', 'publish');
662
+		if (isset($where_params['OR'])) {
663
+			$where_params['AND']['OR'] = $where_params['OR'];
664
+			unset($where_params['OR']);
665
+		}
666
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
667
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
668
+			unset($where_params['Datetime.DTT_EVT_end']);
669
+		}
670
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
671
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
672
+			unset($where_params['Datetime.DTT_EVT_start']);
673
+		}
674
+		$query_params[0] = $where_params;
675
+		// don't use $query_params with count()
676
+		// because we don't want to include additional query clauses like "GROUP BY"
677
+		return $count
678
+			? $this->count(array($where_params), 'EVT_ID', true)
679
+			: $this->get_all($query_params);
680
+	}
681
+
682
+
683
+
684
+	/**
685
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
686
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
687
+	 * attached to the event. See parent for param descriptions
688
+	 *
689
+	 * @param        $id_or_obj
690
+	 * @param        $other_model_id_or_obj
691
+	 * @param string $relationName
692
+	 * @param array  $where_query
693
+	 * @return EE_Base_Class
694
+	 * @throws EE_Error
695
+	 */
696
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
697
+	{
698
+		if ($relationName === 'Price') {
699
+			//let's get the PRC object for the given ID to make sure that we aren't dealing with a default
700
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
701
+			//if EVT_ID = 0, then this is a default
702
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
703
+				//let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
704
+				$prc_chk->set('PRC_ID', 0);
705
+			}
706
+			//run parent
707
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
708
+		}
709
+		//otherwise carry on as normal
710
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
711
+	}
712
+
713
+
714
+
715
+	/******************** DEPRECATED METHODS ********************/
716
+
717
+
718
+
719
+	/**
720
+	 * _get_question_target_db_column
721
+	 *
722
+	 * @deprecated as of 4.8.32.rc.001. Instead consider using
723
+	 *             EE_Registration_Custom_Questions_Form located in
724
+	 *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
725
+	 * @access     public
726
+	 * @param    EE_Registration $registration (so existing answers for registration are included)
727
+	 * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
728
+	 *                                         registration).
729
+	 * @throws EE_Error
730
+	 * @return    array
731
+	 */
732
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
733
+	{
734
+		if (empty($EVT_ID)) {
735
+			throw new EE_Error(__('An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
736
+				'event_espresso'));
737
+		}
738
+		$questions = array();
739
+		// get all question groups for event
740
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
741
+		if (! empty($qgs)) {
742
+			foreach ($qgs as $qg) {
743
+				$qsts = $qg->questions();
744
+				$questions[$qg->ID()] = $qg->model_field_array();
745
+				$questions[$qg->ID()]['QSG_questions'] = array();
746
+				foreach ($qsts as $qst) {
747
+					if ($qst->is_system_question()) {
748
+						continue;
749
+					}
750
+					$answer = EEM_Answer::instance()->get_one(array(
751
+						array(
752
+							'QST_ID' => $qst->ID(),
753
+							'REG_ID' => $registration->ID(),
754
+						),
755
+					));
756
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
757
+					$qst_name = $qstn_id = $qst->ID();
758
+					$ans_id = $answer->ID();
759
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
760
+					$input_name = '';
761
+					$input_id = sanitize_key($qst->display_text());
762
+					$input_class = '';
763
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
764
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
765
+																						   . $input_name
766
+																						   . $qst_name;
767
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
768
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
769
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
770
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
771
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
772
+					//leave responses as-is, don't convert stuff into html entities please!
773
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
774
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
775
+						$QSOs = $qst->options(true, $answer->value());
776
+						if (is_array($QSOs)) {
777
+							foreach ($QSOs as $QSO_ID => $QSO) {
778
+								$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
779
+							}
780
+						}
781
+					}
782
+				}
783
+			}
784
+		}
785
+		return $questions;
786
+	}
787 787
 
788 788
 
789 789
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -1,9 +1,9 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\services\orm\ModelFieldFactory;
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
-require_once(EE_MODELS . 'EEM_CPT_Base.model.php');
6
+require_once(EE_MODELS.'EEM_CPT_Base.model.php');
7 7
 
8 8
 
9 9
 
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
      */
274 274
     public function get_all_event_question_groups($EVT_ID = 0)
275 275
     {
276
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
276
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
277 277
             EE_Error::add_error(
278 278
                 esc_html__(
279 279
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
      */
303 303
     public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
304 304
     {
305
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
305
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
306 306
             EE_Error::add_error(
307 307
                 esc_html__(
308 308
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
      */
335 335
     public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
336 336
     {
337
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
337
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
338 338
             EE_Error::add_error(
339 339
                 esc_html__(
340 340
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -738,7 +738,7 @@  discard block
 block discarded – undo
738 738
         $questions = array();
739 739
         // get all question groups for event
740 740
         $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
741
-        if (! empty($qgs)) {
741
+        if ( ! empty($qgs)) {
742 742
             foreach ($qgs as $qg) {
743 743
                 $qsts = $qg->questions();
744 744
                 $questions[$qg->ID()] = $qg->model_field_array();
@@ -756,7 +756,7 @@  discard block
 block discarded – undo
756 756
                     $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
757 757
                     $qst_name = $qstn_id = $qst->ID();
758 758
                     $ans_id = $answer->ID();
759
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
759
+                    $qst_name = ! empty($ans_id) ? '['.$qst_name.']['.$ans_id.']' : '['.$qst_name.']';
760 760
                     $input_name = '';
761 761
                     $input_id = sanitize_key($qst->display_text());
762 762
                     $input_class = '';
@@ -764,7 +764,7 @@  discard block
 block discarded – undo
764 764
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
765 765
                                                                                            . $input_name
766 766
                                                                                            . $qst_name;
767
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
767
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id.'-'.$qstn_id;
768 768
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
769 769
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
770 770
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
Please login to merge, or discard this patch.
core/services/orm/ModelFieldFactory.php 3 patches
Doc Comments   +4 added lines, -5 removed lines patch added patch discarded remove patch
@@ -132,7 +132,6 @@  discard block
 block discarded – undo
132 132
     /**
133 133
      * @param string $table_column
134 134
      * @param string $nice_name
135
-     * @param string $timezone_string
136 135
      * @param bool   $nullable
137 136
      * @param string $default_value
138 137
      * @throws EE_Error
@@ -179,7 +178,7 @@  discard block
 block discarded – undo
179 178
      * @param string $table_column
180 179
      * @param string $nice_name
181 180
      * @param bool   $nullable
182
-     * @param null   $default_value
181
+     * @param integer   $default_value
183 182
      * @return EE_DB_Only_Int_Field
184 183
      */
185 184
     public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
@@ -295,7 +294,7 @@  discard block
 block discarded – undo
295 294
      * @param string $table_column
296 295
      * @param string $nice_name
297 296
      * @param bool   $nullable
298
-     * @param null   $default_value
297
+     * @param integer   $default_value
299 298
      * @param string $model_name
300 299
      * @return EE_Foreign_Key_Int_Field
301 300
      */
@@ -313,7 +312,7 @@  discard block
 block discarded – undo
313 312
      * @param string $table_column
314 313
      * @param string $nice_name
315 314
      * @param bool   $nullable
316
-     * @param null   $default_value
315
+     * @param string   $default_value
317 316
      * @param string $model_name
318 317
      * @return EE_Foreign_Key_String_Field
319 318
      */
@@ -564,7 +563,7 @@  discard block
 block discarded – undo
564 563
      * @param string $table_column
565 564
      * @param string $nice_name
566 565
      * @param bool   $nullable
567
-     * @param mixed  $default_value
566
+     * @param string  $default_value
568 567
      * @param array  $values        If additional stati are to be used other than the default WP statuses,
569 568
      *                              then they can be registered via this property.
570 569
      *                              The format of the array should be as follows:
Please login to merge, or discard this patch.
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -33,9 +33,6 @@
 block discarded – undo
33 33
 use EE_WP_Post_Status_Field;
34 34
 use EE_WP_Post_Type_Field;
35 35
 use EE_WP_User_Field;
36
-use EventEspresso\core\exceptions\InvalidDataTypeException;
37
-use EventEspresso\core\exceptions\InvalidInterfaceException;
38
-use EventEspresso\core\services\loaders\LoaderFactory;
39 36
 use EventEspresso\core\services\loaders\LoaderInterface;
40 37
 use InvalidArgumentException;
41 38
 
Please login to merge, or discard this patch.
Indentation   +570 added lines, -570 removed lines patch added patch discarded remove patch
@@ -53,576 +53,576 @@
 block discarded – undo
53 53
 class ModelFieldFactory
54 54
 {
55 55
 
56
-    /**
57
-     * @var LoaderInterface $loader
58
-     */
59
-    private $loader;
60
-
61
-
62
-
63
-    /**
64
-     * ModelFieldFactory constructor.
65
-     *
66
-     * @param LoaderInterface $loader
67
-     */
68
-    public function __construct(LoaderInterface $loader)
69
-    {
70
-        $this->loader = $loader;
71
-    }
72
-
73
-
74
-
75
-    /**
76
-     * @param string $table_column
77
-     * @param string $nice_name
78
-     * @param bool   $nullable
79
-     * @param null   $default_value
80
-     * @return EE_All_Caps_Text_Field
81
-     */
82
-    public function createAllCapsTextField($table_column, $nice_name, $nullable, $default_value = null)
83
-    {
84
-        return $this->loader->getNew(
85
-            'EE_All_Caps_Text_Field',
86
-            array($table_column, $nice_name, $nullable, $default_value)
87
-        );
88
-    }
89
-
90
-
91
-
92
-    /**
93
-     * @param string $table_column
94
-     * @param string $nice_name
95
-     * @param bool   $nullable
96
-     * @param null   $default_value
97
-     * @param string $model_name
98
-     * @return EE_Any_Foreign_Model_Name_Field
99
-     */
100
-    public function createAnyForeignModelNameField(
101
-        $table_column,
102
-        $nice_name,
103
-        $nullable,
104
-        $default_value = null,
105
-        $model_name
106
-    ) {
107
-        return $this->loader->getNew(
108
-            'EE_Any_Foreign_Model_Name_Field',
109
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
110
-        );
111
-    }
112
-
113
-
114
-
115
-    /**
116
-     * @param string $table_column
117
-     * @param string $nice_name
118
-     * @param bool   $nullable
119
-     * @param null   $default_value
120
-     * @return EE_Boolean_Field
121
-     */
122
-    public function createBooleanField($table_column, $nice_name, $nullable, $default_value = null)
123
-    {
124
-        return $this->loader->getNew(
125
-            'EE_Boolean_Field',
126
-            array($table_column, $nice_name, $nullable, $default_value)
127
-        );
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * @param string $table_column
134
-     * @param string $nice_name
135
-     * @param string $timezone_string
136
-     * @param bool   $nullable
137
-     * @param string $default_value
138
-     * @throws EE_Error
139
-     * @throws InvalidArgumentException
140
-     * @return EE_Datetime_Field
141
-     */
142
-    public function createDatetimeField(
143
-        $table_column,
144
-        $nice_name,
145
-        $nullable = false,
146
-        $default_value = EE_Datetime_Field::now
147
-    ) {
148
-        return $this->loader->getNew(
149
-            'EE_Datetime_Field',
150
-            array(
151
-                $table_column,
152
-                $nice_name,
153
-                $nullable,
154
-                $default_value
155
-            )
156
-        );
157
-    }
158
-
159
-
160
-
161
-    /**
162
-     * @param string $table_column
163
-     * @param string $nice_name
164
-     * @param bool   $nullable
165
-     * @param null   $default_value
166
-     * @return EE_DB_Only_Float_Field
167
-     */
168
-    public function createDbOnlyFloatField($table_column, $nice_name, $nullable, $default_value = null)
169
-    {
170
-        return $this->loader->getNew(
171
-            'EE_DB_Only_Float_Field',
172
-            array($table_column, $nice_name, $nullable, $default_value)
173
-        );
174
-    }
175
-
176
-
177
-
178
-    /**
179
-     * @param string $table_column
180
-     * @param string $nice_name
181
-     * @param bool   $nullable
182
-     * @param null   $default_value
183
-     * @return EE_DB_Only_Int_Field
184
-     */
185
-    public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
186
-    {
187
-        return $this->loader->getNew(
188
-            'EE_DB_Only_Int_Field',
189
-            array($table_column, $nice_name, $nullable, $default_value)
190
-        );
191
-    }
192
-
193
-
194
-
195
-    /**
196
-     * @param string $table_column
197
-     * @param string $nice_name
198
-     * @param bool   $nullable
199
-     * @param null   $default_value
200
-     * @return EE_DB_Only_Text_Field
201
-     */
202
-    public function createDbOnlyTextField($table_column, $nice_name, $nullable, $default_value = null)
203
-    {
204
-        return $this->loader->getNew(
205
-            'EE_DB_Only_Text_Field',
206
-            array($table_column, $nice_name, $nullable, $default_value)
207
-        );
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     * @param string $table_column
214
-     * @param string $nice_name
215
-     * @param bool   $nullable
216
-     * @param string $default_value
217
-     * @return EE_Email_Field
218
-     */
219
-    public function createEmailField($table_column, $nice_name, $nullable = true, $default_value = '')
220
-    {
221
-        return $this->loader->getNew(
222
-            'EE_Email_Field',
223
-            array($table_column, $nice_name, $nullable, $default_value)
224
-        );
225
-    }
226
-
227
-
228
-
229
-    /**
230
-     * @param string $table_column
231
-     * @param string $nice_name
232
-     * @param bool   $nullable
233
-     * @param null   $default_value
234
-     * @param array  $allowed_enum_values keys are values to be used in the DB,
235
-     *                                    values are how they should be displayed
236
-     * @return EE_Enum_Integer_Field
237
-     */
238
-    public function createEnumIntegerField(
239
-        $table_column,
240
-        $nice_name,
241
-        $nullable,
242
-        $default_value = null,
243
-        array $allowed_enum_values
244
-    ) {
245
-        return $this->loader->getNew(
246
-            'EE_Enum_Integer_Field',
247
-            array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
248
-        );
249
-    }
250
-
251
-
252
-
253
-    /**
254
-     * @param string $table_column
255
-     * @param string $nice_name
256
-     * @param bool   $nullable
257
-     * @param null   $default_value
258
-     * @param array  $allowed_enum_values keys are values to be used in the DB,
259
-     *                                    values are how they should be displayed
260
-     * @return EE_Enum_Text_Field
261
-     */
262
-    public function createEnumTextField(
263
-        $table_column,
264
-        $nice_name,
265
-        $nullable,
266
-        $default_value,
267
-        array $allowed_enum_values
268
-    ) {
269
-        return $this->loader->getNew(
270
-            'EE_Enum_Text_Field',
271
-            array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
272
-        );
273
-    }
274
-
275
-
276
-
277
-    /**
278
-     * @param string $table_column
279
-     * @param string $nice_name
280
-     * @param bool   $nullable
281
-     * @param null   $default_value
282
-     * @return EE_Float_Field
283
-     */
284
-    public function createFloatField($table_column, $nice_name, $nullable, $default_value = null)
285
-    {
286
-        return $this->loader->getNew(
287
-            'EE_Float_Field',
288
-            array($table_column, $nice_name, $nullable, $default_value)
289
-        );
290
-    }
291
-
292
-
293
-
294
-    /**
295
-     * @param string $table_column
296
-     * @param string $nice_name
297
-     * @param bool   $nullable
298
-     * @param null   $default_value
299
-     * @param string $model_name
300
-     * @return EE_Foreign_Key_Int_Field
301
-     */
302
-    public function createForeignKeyIntField($table_column, $nice_name, $nullable, $default_value, $model_name)
303
-    {
304
-        return $this->loader->getNew(
305
-            'EE_Foreign_Key_Int_Field',
306
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
307
-        );
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * @param string $table_column
314
-     * @param string $nice_name
315
-     * @param bool   $nullable
316
-     * @param null   $default_value
317
-     * @param string $model_name
318
-     * @return EE_Foreign_Key_String_Field
319
-     */
320
-    public function createForeignKeyStringField(
321
-        $table_column,
322
-        $nice_name,
323
-        $nullable,
324
-        $default_value,
325
-        $model_name
326
-    ) {
327
-        return $this->loader->getNew(
328
-            'EE_Foreign_Key_String_Field',
329
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
330
-        );
331
-    }
332
-
333
-
334
-
335
-    /**
336
-     * @param string $table_column
337
-     * @param string $nice_name
338
-     * @param bool   $nullable
339
-     * @param null   $default_value
340
-     * @return EE_Full_HTML_Field
341
-     */
342
-    public function createFullHtmlField($table_column, $nice_name, $nullable, $default_value = null)
343
-    {
344
-        return $this->loader->getNew(
345
-            'EE_Full_HTML_Field',
346
-            array($table_column, $nice_name, $nullable, $default_value)
347
-        );
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * @param string $table_column
354
-     * @param string $nice_name
355
-     * @param bool   $nullable
356
-     * @param null   $default_value
357
-     * @return EE_Infinite_Integer_Field
358
-     */
359
-    public function createInfiniteIntegerField($table_column, $nice_name, $nullable, $default_value = null)
360
-    {
361
-        return $this->loader->getNew(
362
-            'EE_Infinite_Integer_Field',
363
-            array($table_column, $nice_name, $nullable, $default_value)
364
-        );
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * @param string $table_column
371
-     * @param string $nice_name
372
-     * @param bool   $nullable
373
-     * @param null   $default_value
374
-     * @return EE_Integer_Field
375
-     */
376
-    public function createIntegerField($table_column, $nice_name, $nullable, $default_value = null)
377
-    {
378
-        return $this->loader->getNew(
379
-            'EE_Integer_Field',
380
-            array($table_column, $nice_name, $nullable, $default_value)
381
-        );
382
-    }
383
-
384
-
385
-
386
-    /**
387
-     * @param string $table_column
388
-     * @param string $nice_name
389
-     * @param bool   $nullable
390
-     * @param null   $default_value
391
-     * @return EE_Maybe_Serialized_Simple_HTML_Field
392
-     */
393
-    public function createMaybeSerializedSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
394
-    {
395
-        return $this->loader->getNew(
396
-            'EE_Maybe_Serialized_Simple_HTML_Field',
397
-            array($table_column, $nice_name, $nullable, $default_value)
398
-        );
399
-    }
400
-
401
-
402
-
403
-    /**
404
-     * @param string $table_column
405
-     * @param string $nice_name
406
-     * @param bool   $nullable
407
-     * @param null   $default_value
408
-     * @return EE_Maybe_Serialized_Text_Field
409
-     */
410
-    public function createMaybeSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
411
-    {
412
-        return $this->loader->getNew(
413
-            'EE_Maybe_Serialized_Text_Field',
414
-            array($table_column, $nice_name, $nullable, $default_value)
415
-        );
416
-    }
417
-
418
-
419
-
420
-    /**
421
-     * @param string $table_column
422
-     * @param string $nice_name
423
-     * @param bool   $nullable
424
-     * @param null   $default_value
425
-     * @return EE_Money_Field
426
-     */
427
-    public function createMoneyField($table_column, $nice_name, $nullable, $default_value = null)
428
-    {
429
-        return $this->loader->getNew(
430
-            'EE_Money_Field',
431
-            array($table_column, $nice_name, $nullable, $default_value)
432
-        );
433
-    }
434
-
435
-
436
-
437
-    /**
438
-     * @param string $table_column
439
-     * @param string $nice_name
440
-     * @param bool   $nullable
441
-     * @param string $default_value
442
-     * @return EE_Plain_Text_Field
443
-     */
444
-    public function createPlainTextField($table_column, $nice_name, $nullable = true, $default_value = '')
445
-    {
446
-        return $this->loader->getNew(
447
-            'EE_Plain_Text_Field',
448
-            array($table_column, $nice_name, $nullable, $default_value)
449
-        );
450
-    }
451
-
452
-
453
-
454
-    /**
455
-     * @param string $table_column
456
-     * @param string $nice_name
457
-     * @param bool   $nullable
458
-     * @param null   $default_value
459
-     * @return EE_Post_Content_Field
460
-     */
461
-    public function createPostContentField($table_column, $nice_name, $nullable, $default_value = null)
462
-    {
463
-        return $this->loader->getNew(
464
-            'EE_Post_Content_Field',
465
-            array($table_column, $nice_name, $nullable, $default_value)
466
-        );
467
-    }
468
-
469
-
470
-
471
-    /**
472
-     * @param string $table_column
473
-     * @param string $nice_name
474
-     * @return EE_Primary_Key_Int_Field
475
-     */
476
-    public function createPrimaryKeyIntField($table_column, $nice_name)
477
-    {
478
-        return $this->loader->getNew('EE_Primary_Key_Int_Field', array($table_column, $nice_name));
479
-    }
480
-
481
-
482
-
483
-    /**
484
-     * @param string $table_column
485
-     * @param string $nice_name
486
-     * @return EE_Primary_Key_String_Field
487
-     */
488
-    public function createPrimaryKeyStringField($table_column, $nice_name)
489
-    {
490
-        return $this->loader->getNew('EE_Primary_Key_String_Field', array($table_column, $nice_name));
491
-    }
492
-
493
-
494
-
495
-    /**
496
-     * @param string $table_column
497
-     * @param string $nice_name
498
-     * @param bool   $nullable
499
-     * @param null   $default_value
500
-     * @return EE_Serialized_Text_Field
501
-     */
502
-    public function createSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
503
-    {
504
-        return $this->loader->getNew(
505
-            'EE_Serialized_Text_Field',
506
-            array($table_column, $nice_name, $nullable, $default_value)
507
-        );
508
-    }
509
-
510
-
511
-
512
-    /**
513
-     * @param string $table_column
514
-     * @param string $nice_name
515
-     * @param bool   $nullable
516
-     * @param null   $default_value
517
-     * @return EE_Simple_HTML_Field
518
-     */
519
-    public function createSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
520
-    {
521
-        return $this->loader->getNew(
522
-            'EE_Simple_HTML_Field',
523
-            array($table_column, $nice_name, $nullable, $default_value)
524
-        );
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     * @param string $table_column
531
-     * @param string $nice_name
532
-     * @param bool   $nullable
533
-     * @param null   $default_value
534
-     * @return EE_Slug_Field
535
-     */
536
-    public function createSlugField($table_column, $nice_name, $nullable = false, $default_value = null)
537
-    {
538
-        return $this->loader->getNew(
539
-            'EE_Slug_Field',
540
-            array($table_column, $nice_name, $nullable, $default_value)
541
-        );
542
-    }
543
-
544
-
545
-
546
-    /**
547
-     * @param string $table_column
548
-     * @param string $nice_name
549
-     * @param bool   $nullable
550
-     * @param null   $default_value
551
-     * @return EE_Trashed_Flag_Field
552
-     */
553
-    public function createTrashedFlagField($table_column, $nice_name, $nullable, $default_value = null)
554
-    {
555
-        return $this->loader->getNew(
556
-            'EE_Trashed_Flag_Field',
557
-            array($table_column, $nice_name, $nullable, $default_value)
558
-        );
559
-    }
560
-
561
-
562
-
563
-    /**
564
-     * @param string $table_column
565
-     * @param string $nice_name
566
-     * @param bool   $nullable
567
-     * @param mixed  $default_value
568
-     * @param array  $values        If additional stati are to be used other than the default WP statuses,
569
-     *                              then they can be registered via this property.
570
-     *                              The format of the array should be as follows:
571
-     *  array(
572
-     *      'status_reference' => array(
573
-     *          'label' => __('Status Reference Label', 'event_espresso'),
574
-     *          'public' => true,                 // whether this status should be shown on the frontend of the site
575
-     *          'exclude_from_search' => false,   // whether this status should be excluded from wp searches
576
-     *          'show_in_admin_all_list' => true, // whether this status is included in queries
577
-     *                                               for the admin "all" view in list table views.
578
-     *          'show_in_admin_status_list' => true, // show in the list of statuses with post counts at the top
579
-     *                                                  of the admin list tables (i.e. Status Reference(2) )
580
-     *          'label_count' => _n_noop(
581
-     *              'Status Reference <span class="count">(%s)</span>',
582
-     *              'Status References <span class="count">(%s)</span>'
583
-     *          ),                                   // the text to display on the admin screen
584
-     *                                                  ( or you won't see your status count ).
585
-     *      )
586
-     *  )
587
-     * @link http://codex.wordpress.org/Function_Reference/register_post_status for more info
588
-     * @return EE_WP_Post_Status_Field
589
-     */
590
-    public function createWpPostStatusField(
591
-        $table_column,
592
-        $nice_name,
593
-        $nullable,
594
-        $default_value = null,
595
-        array $values = array()
596
-    ) {
597
-        return $this->loader->getNew(
598
-            'EE_WP_Post_Status_Field',
599
-            array($table_column, $nice_name, $nullable, $default_value, $values)
600
-        );
601
-    }
602
-
603
-
604
-
605
-    /**
606
-     * @param string $post_type
607
-     * @return EE_WP_Post_Type_Field
608
-     */
609
-    public function createWpPostTypeField($post_type)
610
-    {
611
-        return $this->loader->getNew('EE_WP_Post_Type_Field', array($post_type));
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     * @param string $table_column
618
-     * @param string $nice_name
619
-     * @param bool   $nullable
620
-     * @return EE_WP_User_Field
621
-     */
622
-    public function createWpUserField($table_column, $nice_name, $nullable)
623
-    {
624
-        return $this->loader->getNew('EE_WP_User_Field', array($table_column, $nice_name, $nullable));
625
-    }
56
+	/**
57
+	 * @var LoaderInterface $loader
58
+	 */
59
+	private $loader;
60
+
61
+
62
+
63
+	/**
64
+	 * ModelFieldFactory constructor.
65
+	 *
66
+	 * @param LoaderInterface $loader
67
+	 */
68
+	public function __construct(LoaderInterface $loader)
69
+	{
70
+		$this->loader = $loader;
71
+	}
72
+
73
+
74
+
75
+	/**
76
+	 * @param string $table_column
77
+	 * @param string $nice_name
78
+	 * @param bool   $nullable
79
+	 * @param null   $default_value
80
+	 * @return EE_All_Caps_Text_Field
81
+	 */
82
+	public function createAllCapsTextField($table_column, $nice_name, $nullable, $default_value = null)
83
+	{
84
+		return $this->loader->getNew(
85
+			'EE_All_Caps_Text_Field',
86
+			array($table_column, $nice_name, $nullable, $default_value)
87
+		);
88
+	}
89
+
90
+
91
+
92
+	/**
93
+	 * @param string $table_column
94
+	 * @param string $nice_name
95
+	 * @param bool   $nullable
96
+	 * @param null   $default_value
97
+	 * @param string $model_name
98
+	 * @return EE_Any_Foreign_Model_Name_Field
99
+	 */
100
+	public function createAnyForeignModelNameField(
101
+		$table_column,
102
+		$nice_name,
103
+		$nullable,
104
+		$default_value = null,
105
+		$model_name
106
+	) {
107
+		return $this->loader->getNew(
108
+			'EE_Any_Foreign_Model_Name_Field',
109
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
110
+		);
111
+	}
112
+
113
+
114
+
115
+	/**
116
+	 * @param string $table_column
117
+	 * @param string $nice_name
118
+	 * @param bool   $nullable
119
+	 * @param null   $default_value
120
+	 * @return EE_Boolean_Field
121
+	 */
122
+	public function createBooleanField($table_column, $nice_name, $nullable, $default_value = null)
123
+	{
124
+		return $this->loader->getNew(
125
+			'EE_Boolean_Field',
126
+			array($table_column, $nice_name, $nullable, $default_value)
127
+		);
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * @param string $table_column
134
+	 * @param string $nice_name
135
+	 * @param string $timezone_string
136
+	 * @param bool   $nullable
137
+	 * @param string $default_value
138
+	 * @throws EE_Error
139
+	 * @throws InvalidArgumentException
140
+	 * @return EE_Datetime_Field
141
+	 */
142
+	public function createDatetimeField(
143
+		$table_column,
144
+		$nice_name,
145
+		$nullable = false,
146
+		$default_value = EE_Datetime_Field::now
147
+	) {
148
+		return $this->loader->getNew(
149
+			'EE_Datetime_Field',
150
+			array(
151
+				$table_column,
152
+				$nice_name,
153
+				$nullable,
154
+				$default_value
155
+			)
156
+		);
157
+	}
158
+
159
+
160
+
161
+	/**
162
+	 * @param string $table_column
163
+	 * @param string $nice_name
164
+	 * @param bool   $nullable
165
+	 * @param null   $default_value
166
+	 * @return EE_DB_Only_Float_Field
167
+	 */
168
+	public function createDbOnlyFloatField($table_column, $nice_name, $nullable, $default_value = null)
169
+	{
170
+		return $this->loader->getNew(
171
+			'EE_DB_Only_Float_Field',
172
+			array($table_column, $nice_name, $nullable, $default_value)
173
+		);
174
+	}
175
+
176
+
177
+
178
+	/**
179
+	 * @param string $table_column
180
+	 * @param string $nice_name
181
+	 * @param bool   $nullable
182
+	 * @param null   $default_value
183
+	 * @return EE_DB_Only_Int_Field
184
+	 */
185
+	public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
186
+	{
187
+		return $this->loader->getNew(
188
+			'EE_DB_Only_Int_Field',
189
+			array($table_column, $nice_name, $nullable, $default_value)
190
+		);
191
+	}
192
+
193
+
194
+
195
+	/**
196
+	 * @param string $table_column
197
+	 * @param string $nice_name
198
+	 * @param bool   $nullable
199
+	 * @param null   $default_value
200
+	 * @return EE_DB_Only_Text_Field
201
+	 */
202
+	public function createDbOnlyTextField($table_column, $nice_name, $nullable, $default_value = null)
203
+	{
204
+		return $this->loader->getNew(
205
+			'EE_DB_Only_Text_Field',
206
+			array($table_column, $nice_name, $nullable, $default_value)
207
+		);
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 * @param string $table_column
214
+	 * @param string $nice_name
215
+	 * @param bool   $nullable
216
+	 * @param string $default_value
217
+	 * @return EE_Email_Field
218
+	 */
219
+	public function createEmailField($table_column, $nice_name, $nullable = true, $default_value = '')
220
+	{
221
+		return $this->loader->getNew(
222
+			'EE_Email_Field',
223
+			array($table_column, $nice_name, $nullable, $default_value)
224
+		);
225
+	}
226
+
227
+
228
+
229
+	/**
230
+	 * @param string $table_column
231
+	 * @param string $nice_name
232
+	 * @param bool   $nullable
233
+	 * @param null   $default_value
234
+	 * @param array  $allowed_enum_values keys are values to be used in the DB,
235
+	 *                                    values are how they should be displayed
236
+	 * @return EE_Enum_Integer_Field
237
+	 */
238
+	public function createEnumIntegerField(
239
+		$table_column,
240
+		$nice_name,
241
+		$nullable,
242
+		$default_value = null,
243
+		array $allowed_enum_values
244
+	) {
245
+		return $this->loader->getNew(
246
+			'EE_Enum_Integer_Field',
247
+			array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
248
+		);
249
+	}
250
+
251
+
252
+
253
+	/**
254
+	 * @param string $table_column
255
+	 * @param string $nice_name
256
+	 * @param bool   $nullable
257
+	 * @param null   $default_value
258
+	 * @param array  $allowed_enum_values keys are values to be used in the DB,
259
+	 *                                    values are how they should be displayed
260
+	 * @return EE_Enum_Text_Field
261
+	 */
262
+	public function createEnumTextField(
263
+		$table_column,
264
+		$nice_name,
265
+		$nullable,
266
+		$default_value,
267
+		array $allowed_enum_values
268
+	) {
269
+		return $this->loader->getNew(
270
+			'EE_Enum_Text_Field',
271
+			array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
272
+		);
273
+	}
274
+
275
+
276
+
277
+	/**
278
+	 * @param string $table_column
279
+	 * @param string $nice_name
280
+	 * @param bool   $nullable
281
+	 * @param null   $default_value
282
+	 * @return EE_Float_Field
283
+	 */
284
+	public function createFloatField($table_column, $nice_name, $nullable, $default_value = null)
285
+	{
286
+		return $this->loader->getNew(
287
+			'EE_Float_Field',
288
+			array($table_column, $nice_name, $nullable, $default_value)
289
+		);
290
+	}
291
+
292
+
293
+
294
+	/**
295
+	 * @param string $table_column
296
+	 * @param string $nice_name
297
+	 * @param bool   $nullable
298
+	 * @param null   $default_value
299
+	 * @param string $model_name
300
+	 * @return EE_Foreign_Key_Int_Field
301
+	 */
302
+	public function createForeignKeyIntField($table_column, $nice_name, $nullable, $default_value, $model_name)
303
+	{
304
+		return $this->loader->getNew(
305
+			'EE_Foreign_Key_Int_Field',
306
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
307
+		);
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * @param string $table_column
314
+	 * @param string $nice_name
315
+	 * @param bool   $nullable
316
+	 * @param null   $default_value
317
+	 * @param string $model_name
318
+	 * @return EE_Foreign_Key_String_Field
319
+	 */
320
+	public function createForeignKeyStringField(
321
+		$table_column,
322
+		$nice_name,
323
+		$nullable,
324
+		$default_value,
325
+		$model_name
326
+	) {
327
+		return $this->loader->getNew(
328
+			'EE_Foreign_Key_String_Field',
329
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
330
+		);
331
+	}
332
+
333
+
334
+
335
+	/**
336
+	 * @param string $table_column
337
+	 * @param string $nice_name
338
+	 * @param bool   $nullable
339
+	 * @param null   $default_value
340
+	 * @return EE_Full_HTML_Field
341
+	 */
342
+	public function createFullHtmlField($table_column, $nice_name, $nullable, $default_value = null)
343
+	{
344
+		return $this->loader->getNew(
345
+			'EE_Full_HTML_Field',
346
+			array($table_column, $nice_name, $nullable, $default_value)
347
+		);
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * @param string $table_column
354
+	 * @param string $nice_name
355
+	 * @param bool   $nullable
356
+	 * @param null   $default_value
357
+	 * @return EE_Infinite_Integer_Field
358
+	 */
359
+	public function createInfiniteIntegerField($table_column, $nice_name, $nullable, $default_value = null)
360
+	{
361
+		return $this->loader->getNew(
362
+			'EE_Infinite_Integer_Field',
363
+			array($table_column, $nice_name, $nullable, $default_value)
364
+		);
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * @param string $table_column
371
+	 * @param string $nice_name
372
+	 * @param bool   $nullable
373
+	 * @param null   $default_value
374
+	 * @return EE_Integer_Field
375
+	 */
376
+	public function createIntegerField($table_column, $nice_name, $nullable, $default_value = null)
377
+	{
378
+		return $this->loader->getNew(
379
+			'EE_Integer_Field',
380
+			array($table_column, $nice_name, $nullable, $default_value)
381
+		);
382
+	}
383
+
384
+
385
+
386
+	/**
387
+	 * @param string $table_column
388
+	 * @param string $nice_name
389
+	 * @param bool   $nullable
390
+	 * @param null   $default_value
391
+	 * @return EE_Maybe_Serialized_Simple_HTML_Field
392
+	 */
393
+	public function createMaybeSerializedSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
394
+	{
395
+		return $this->loader->getNew(
396
+			'EE_Maybe_Serialized_Simple_HTML_Field',
397
+			array($table_column, $nice_name, $nullable, $default_value)
398
+		);
399
+	}
400
+
401
+
402
+
403
+	/**
404
+	 * @param string $table_column
405
+	 * @param string $nice_name
406
+	 * @param bool   $nullable
407
+	 * @param null   $default_value
408
+	 * @return EE_Maybe_Serialized_Text_Field
409
+	 */
410
+	public function createMaybeSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
411
+	{
412
+		return $this->loader->getNew(
413
+			'EE_Maybe_Serialized_Text_Field',
414
+			array($table_column, $nice_name, $nullable, $default_value)
415
+		);
416
+	}
417
+
418
+
419
+
420
+	/**
421
+	 * @param string $table_column
422
+	 * @param string $nice_name
423
+	 * @param bool   $nullable
424
+	 * @param null   $default_value
425
+	 * @return EE_Money_Field
426
+	 */
427
+	public function createMoneyField($table_column, $nice_name, $nullable, $default_value = null)
428
+	{
429
+		return $this->loader->getNew(
430
+			'EE_Money_Field',
431
+			array($table_column, $nice_name, $nullable, $default_value)
432
+		);
433
+	}
434
+
435
+
436
+
437
+	/**
438
+	 * @param string $table_column
439
+	 * @param string $nice_name
440
+	 * @param bool   $nullable
441
+	 * @param string $default_value
442
+	 * @return EE_Plain_Text_Field
443
+	 */
444
+	public function createPlainTextField($table_column, $nice_name, $nullable = true, $default_value = '')
445
+	{
446
+		return $this->loader->getNew(
447
+			'EE_Plain_Text_Field',
448
+			array($table_column, $nice_name, $nullable, $default_value)
449
+		);
450
+	}
451
+
452
+
453
+
454
+	/**
455
+	 * @param string $table_column
456
+	 * @param string $nice_name
457
+	 * @param bool   $nullable
458
+	 * @param null   $default_value
459
+	 * @return EE_Post_Content_Field
460
+	 */
461
+	public function createPostContentField($table_column, $nice_name, $nullable, $default_value = null)
462
+	{
463
+		return $this->loader->getNew(
464
+			'EE_Post_Content_Field',
465
+			array($table_column, $nice_name, $nullable, $default_value)
466
+		);
467
+	}
468
+
469
+
470
+
471
+	/**
472
+	 * @param string $table_column
473
+	 * @param string $nice_name
474
+	 * @return EE_Primary_Key_Int_Field
475
+	 */
476
+	public function createPrimaryKeyIntField($table_column, $nice_name)
477
+	{
478
+		return $this->loader->getNew('EE_Primary_Key_Int_Field', array($table_column, $nice_name));
479
+	}
480
+
481
+
482
+
483
+	/**
484
+	 * @param string $table_column
485
+	 * @param string $nice_name
486
+	 * @return EE_Primary_Key_String_Field
487
+	 */
488
+	public function createPrimaryKeyStringField($table_column, $nice_name)
489
+	{
490
+		return $this->loader->getNew('EE_Primary_Key_String_Field', array($table_column, $nice_name));
491
+	}
492
+
493
+
494
+
495
+	/**
496
+	 * @param string $table_column
497
+	 * @param string $nice_name
498
+	 * @param bool   $nullable
499
+	 * @param null   $default_value
500
+	 * @return EE_Serialized_Text_Field
501
+	 */
502
+	public function createSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
503
+	{
504
+		return $this->loader->getNew(
505
+			'EE_Serialized_Text_Field',
506
+			array($table_column, $nice_name, $nullable, $default_value)
507
+		);
508
+	}
509
+
510
+
511
+
512
+	/**
513
+	 * @param string $table_column
514
+	 * @param string $nice_name
515
+	 * @param bool   $nullable
516
+	 * @param null   $default_value
517
+	 * @return EE_Simple_HTML_Field
518
+	 */
519
+	public function createSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
520
+	{
521
+		return $this->loader->getNew(
522
+			'EE_Simple_HTML_Field',
523
+			array($table_column, $nice_name, $nullable, $default_value)
524
+		);
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 * @param string $table_column
531
+	 * @param string $nice_name
532
+	 * @param bool   $nullable
533
+	 * @param null   $default_value
534
+	 * @return EE_Slug_Field
535
+	 */
536
+	public function createSlugField($table_column, $nice_name, $nullable = false, $default_value = null)
537
+	{
538
+		return $this->loader->getNew(
539
+			'EE_Slug_Field',
540
+			array($table_column, $nice_name, $nullable, $default_value)
541
+		);
542
+	}
543
+
544
+
545
+
546
+	/**
547
+	 * @param string $table_column
548
+	 * @param string $nice_name
549
+	 * @param bool   $nullable
550
+	 * @param null   $default_value
551
+	 * @return EE_Trashed_Flag_Field
552
+	 */
553
+	public function createTrashedFlagField($table_column, $nice_name, $nullable, $default_value = null)
554
+	{
555
+		return $this->loader->getNew(
556
+			'EE_Trashed_Flag_Field',
557
+			array($table_column, $nice_name, $nullable, $default_value)
558
+		);
559
+	}
560
+
561
+
562
+
563
+	/**
564
+	 * @param string $table_column
565
+	 * @param string $nice_name
566
+	 * @param bool   $nullable
567
+	 * @param mixed  $default_value
568
+	 * @param array  $values        If additional stati are to be used other than the default WP statuses,
569
+	 *                              then they can be registered via this property.
570
+	 *                              The format of the array should be as follows:
571
+	 *  array(
572
+	 *      'status_reference' => array(
573
+	 *          'label' => __('Status Reference Label', 'event_espresso'),
574
+	 *          'public' => true,                 // whether this status should be shown on the frontend of the site
575
+	 *          'exclude_from_search' => false,   // whether this status should be excluded from wp searches
576
+	 *          'show_in_admin_all_list' => true, // whether this status is included in queries
577
+	 *                                               for the admin "all" view in list table views.
578
+	 *          'show_in_admin_status_list' => true, // show in the list of statuses with post counts at the top
579
+	 *                                                  of the admin list tables (i.e. Status Reference(2) )
580
+	 *          'label_count' => _n_noop(
581
+	 *              'Status Reference <span class="count">(%s)</span>',
582
+	 *              'Status References <span class="count">(%s)</span>'
583
+	 *          ),                                   // the text to display on the admin screen
584
+	 *                                                  ( or you won't see your status count ).
585
+	 *      )
586
+	 *  )
587
+	 * @link http://codex.wordpress.org/Function_Reference/register_post_status for more info
588
+	 * @return EE_WP_Post_Status_Field
589
+	 */
590
+	public function createWpPostStatusField(
591
+		$table_column,
592
+		$nice_name,
593
+		$nullable,
594
+		$default_value = null,
595
+		array $values = array()
596
+	) {
597
+		return $this->loader->getNew(
598
+			'EE_WP_Post_Status_Field',
599
+			array($table_column, $nice_name, $nullable, $default_value, $values)
600
+		);
601
+	}
602
+
603
+
604
+
605
+	/**
606
+	 * @param string $post_type
607
+	 * @return EE_WP_Post_Type_Field
608
+	 */
609
+	public function createWpPostTypeField($post_type)
610
+	{
611
+		return $this->loader->getNew('EE_WP_Post_Type_Field', array($post_type));
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 * @param string $table_column
618
+	 * @param string $nice_name
619
+	 * @param bool   $nullable
620
+	 * @return EE_WP_User_Field
621
+	 */
622
+	public function createWpUserField($table_column, $nice_name, $nullable)
623
+	{
624
+		return $this->loader->getNew('EE_WP_User_Field', array($table_column, $nice_name, $nullable));
625
+	}
626 626
 
627 627
 
628 628
 
Please login to merge, or discard this patch.
core/services/Benchmark.php 2 patches
Indentation   +297 added lines, -297 removed lines patch added patch discarded remove patch
@@ -17,303 +17,303 @@
 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_peak_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>' . implode('<br />', Benchmark::$memory_usage)
195
-                : implode("\n", Benchmark::$memory_usage);
196
-        }
197
-        if (empty($output)) {
198
-            return '';
199
-        }
200
-        $output = $formatted
201
-            ? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
202
-              . (is_admin()
203
-                ? ' margin:2em 2em 2em 180px;'
204
-                : ' margin:2em;')
205
-              . ' padding:2em;">'
206
-              . '<h4>BENCHMARKING</h4>'
207
-              . $output
208
-              . '</div>'
209
-            : $output;
210
-        return $output;
211
-    }
212
-
213
-
214
-
215
-    /**
216
-     * @param bool $echo
217
-     * @param bool $formatted
218
-     * @return string
219
-     */
220
-    public static function displayResults($echo = true, $formatted = true)
221
-    {
222
-        $results = Benchmark::generateResults($formatted);
223
-        if ($echo) {
224
-            echo $results;
225
-            $results = '';
226
-        }
227
-        return $results;
228
-    }
229
-
230
-
231
-
232
-    /**
233
-     * @param string $filepath
234
-     * @param bool   $formatted
235
-     * @param bool   $append
236
-     */
237
-    public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
238
-    {
239
-        $filepath = ! empty($filepath) && is_readable(dirname($filepath))
240
-            ? $filepath
241
-            : '';
242
-        if( empty($filepath)) {
243
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
244
-        }
245
-        file_put_contents(
246
-            $filepath,
247
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
248
-            $append ? FILE_APPEND | LOCK_EX : LOCK_EX
249
-        );
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
256
-     *
257
-     * @param int $size
258
-     * @return string
259
-     */
260
-    public static function convert($size)
261
-    {
262
-        $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
263
-        return round(
264
-            $size / pow(1024, $i = floor(log($size, 1024))),
265
-            2
266
-        ) . ' ' . $unit[absint($i)];
267
-    }
268
-
269
-
270
-
271
-    /**
272
-     * @param string $timer_name
273
-     * @param float  $total_time
274
-     * @param bool   $formatted
275
-     * @return string
276
-     */
277
-    public static function formatTime($timer_name, $total_time, $formatted = true)
278
-    {
279
-        $total_time *= 1000;
280
-        switch ($total_time) {
281
-            case $total_time > 12500 :
282
-                $color = 'red';
283
-                $bold = 'bold';
284
-                break;
285
-            case $total_time > 2500 :
286
-                $color = 'darkorange';
287
-                $bold = 'bold';
288
-                break;
289
-            case $total_time > 500 :
290
-                $color = 'gold';
291
-                $bold = 'bold';
292
-                break;
293
-            case $total_time > 100 :
294
-                $color = 'limegreen';
295
-                $bold = 'normal';
296
-                break;
297
-            case $total_time > 20 :
298
-                $color = 'deepskyblue';
299
-                $bold = 'normal';
300
-                break;
301
-            default :
302
-                $color = 'mediumpurple';
303
-                $bold = 'normal';
304
-                break;
305
-        }
306
-        return $formatted
307
-            ? '<span style="min-width: 10px; margin:0 1em; color:'
308
-               . $color
309
-               . '; font-weight:'
310
-               . $bold
311
-               . '; font-size:1.2em;">'
312
-               . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
313
-               . '</span> '
314
-               . $timer_name
315
-            :  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
316
-    }
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_peak_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>' . implode('<br />', Benchmark::$memory_usage)
195
+				: implode("\n", Benchmark::$memory_usage);
196
+		}
197
+		if (empty($output)) {
198
+			return '';
199
+		}
200
+		$output = $formatted
201
+			? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
202
+			  . (is_admin()
203
+				? ' margin:2em 2em 2em 180px;'
204
+				: ' margin:2em;')
205
+			  . ' padding:2em;">'
206
+			  . '<h4>BENCHMARKING</h4>'
207
+			  . $output
208
+			  . '</div>'
209
+			: $output;
210
+		return $output;
211
+	}
212
+
213
+
214
+
215
+	/**
216
+	 * @param bool $echo
217
+	 * @param bool $formatted
218
+	 * @return string
219
+	 */
220
+	public static function displayResults($echo = true, $formatted = true)
221
+	{
222
+		$results = Benchmark::generateResults($formatted);
223
+		if ($echo) {
224
+			echo $results;
225
+			$results = '';
226
+		}
227
+		return $results;
228
+	}
229
+
230
+
231
+
232
+	/**
233
+	 * @param string $filepath
234
+	 * @param bool   $formatted
235
+	 * @param bool   $append
236
+	 */
237
+	public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
238
+	{
239
+		$filepath = ! empty($filepath) && is_readable(dirname($filepath))
240
+			? $filepath
241
+			: '';
242
+		if( empty($filepath)) {
243
+			$filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
244
+		}
245
+		file_put_contents(
246
+			$filepath,
247
+			"\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
248
+			$append ? FILE_APPEND | LOCK_EX : LOCK_EX
249
+		);
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
256
+	 *
257
+	 * @param int $size
258
+	 * @return string
259
+	 */
260
+	public static function convert($size)
261
+	{
262
+		$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
263
+		return round(
264
+			$size / pow(1024, $i = floor(log($size, 1024))),
265
+			2
266
+		) . ' ' . $unit[absint($i)];
267
+	}
268
+
269
+
270
+
271
+	/**
272
+	 * @param string $timer_name
273
+	 * @param float  $total_time
274
+	 * @param bool   $formatted
275
+	 * @return string
276
+	 */
277
+	public static function formatTime($timer_name, $total_time, $formatted = true)
278
+	{
279
+		$total_time *= 1000;
280
+		switch ($total_time) {
281
+			case $total_time > 12500 :
282
+				$color = 'red';
283
+				$bold = 'bold';
284
+				break;
285
+			case $total_time > 2500 :
286
+				$color = 'darkorange';
287
+				$bold = 'bold';
288
+				break;
289
+			case $total_time > 500 :
290
+				$color = 'gold';
291
+				$bold = 'bold';
292
+				break;
293
+			case $total_time > 100 :
294
+				$color = 'limegreen';
295
+				$bold = 'normal';
296
+				break;
297
+			case $total_time > 20 :
298
+				$color = 'deepskyblue';
299
+				$bold = 'normal';
300
+				break;
301
+			default :
302
+				$color = 'mediumpurple';
303
+				$bold = 'normal';
304
+				break;
305
+		}
306
+		return $formatted
307
+			? '<span style="min-width: 10px; margin:0 1em; color:'
308
+			   . $color
309
+			   . '; font-weight:'
310
+			   . $bold
311
+			   . '; font-size:1.2em;">'
312
+			   . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
313
+			   . '</span> '
314
+			   . $timer_name
315
+			:  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
316
+	}
317 317
 
318 318
 
319 319
 
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 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,9 +189,9 @@  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
-                ? '<h5>Memory</h5>' . implode('<br />', Benchmark::$memory_usage)
194
+                ? '<h5>Memory</h5>'.implode('<br />', Benchmark::$memory_usage)
195 195
                 : implode("\n", Benchmark::$memory_usage);
196 196
         }
197 197
         if (empty($output)) {
@@ -239,12 +239,12 @@  discard block
 block discarded – undo
239 239
         $filepath = ! empty($filepath) && is_readable(dirname($filepath))
240 240
             ? $filepath
241 241
             : '';
242
-        if( empty($filepath)) {
243
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
242
+        if (empty($filepath)) {
243
+            $filepath = EVENT_ESPRESSO_UPLOAD_DIR.'logs/benchmarking-'.date('Y-m-d').'.html';
244 244
         }
245 245
         file_put_contents(
246 246
             $filepath,
247
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
247
+            "\n".date('Y-m-d H:i:s').Benchmark::generateResults($formatted),
248 248
             $append ? FILE_APPEND | LOCK_EX : LOCK_EX
249 249
         );
250 250
     }
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
         return round(
264 264
             $size / pow(1024, $i = floor(log($size, 1024))),
265 265
             2
266
-        ) . ' ' . $unit[absint($i)];
266
+        ).' '.$unit[absint($i)];
267 267
     }
268 268
 
269 269
 
Please login to merge, or discard this patch.
admin_pages/maintenance/Maintenance_Admin_Page.core.php 2 patches
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -261,13 +261,13 @@  discard block
 block discarded – undo
261 261
                 && $most_recent_migration->is_broken()
262 262
             )
263 263
         ) {
264
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
264
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_was_borked_page.template.php';
265 265
             $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266 266
             $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267 267
                                                                                         'success' => '0',
268 268
             ), EE_MAINTENANCE_ADMIN_URL);
269 269
         } elseif ($addons_should_be_upgraded_first) {
270
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
270
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_upgrade_addons_before_migrating.template.php';
271 271
         } else {
272 272
             if ($most_recent_migration
273 273
                 && $most_recent_migration instanceof EE_Data_Migration_Script_Base
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
                 $this->_template_args['current_db_state'] = null;
298 298
                 $this->_template_args['next_db_state'] = null;
299 299
             }
300
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
300
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_page.template.php';
301 301
             $this->_template_args = array_merge(
302 302
                 $this->_template_args,
303 303
                 array(
@@ -336,13 +336,13 @@  discard block
 block discarded – undo
336 336
                 'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337 337
             ));
338 338
         }
339
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
339
+        $this->_template_args['most_recent_migration'] = $most_recent_migration; //the actual most recently ran migration
340 340
         //now render the migration options part, and put it in a variable
341 341
         $migration_options_template_file = apply_filters(
342 342
             'FHEE__ee_migration_page__migration_options_template',
343
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
343
+            EE_MAINTENANCE_TEMPLATE_PATH.'migration_options_from_ee4.template.php'
344 344
         );
345
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
345
+        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args, true);
346 346
         $this->_template_args['migration_options_html'] = $migration_options_html;
347 347
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348 348
             $this->_template_args, true);
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
      */
402 402
     public function _data_reset_and_delete()
403 403
     {
404
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
404
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_data_reset_and_delete.template.php';
405 405
         $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406 406
             'reset_reservations',
407 407
             'reset_reservations',
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
 
439 439
     protected function _reset_reservations()
440 440
     {
441
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
441
+        if (\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442 442
             EE_Error::add_success(
443 443
                 __(
444 444
                     'Ticket and datetime reserved counts have been successfully reset.',
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
      */
487 487
     public function _system_status()
488 488
     {
489
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
489
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_system_stati_page.template.php';
490 490
         $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491 491
         $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492 492
             array(
@@ -505,11 +505,11 @@  discard block
 block discarded – undo
505 505
     public function _download_system_status()
506 506
     {
507 507
         $status_info = EEM_System_Status::instance()->get_system_stati();
508
-        header( 'Content-Disposition: attachment' );
509
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
508
+        header('Content-Disposition: attachment');
509
+        header("Content-Disposition: attachment; filename=system_status_".sanitize_key(site_url()).".html");
510 510
         echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
-        echo "<h1>System Information for " . site_url() . "</h1>";
512
-        echo EEH_Template::layout_array_as_table( $status_info );
511
+        echo "<h1>System Information for ".site_url()."</h1>";
512
+        echo EEH_Template::layout_array_as_table($status_info);
513 513
         die;
514 514
     }
515 515
 
@@ -523,7 +523,7 @@  discard block
 block discarded – undo
523 523
         try {
524 524
             $success = wp_mail(EE_SUPPORT_EMAIL,
525 525
                 'Migration Crash Report',
526
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
526
+                $body."/r/n<br>".print_r(EEM_System_Status::instance()->get_system_stati(), true),
527 527
                 array(
528 528
                     "from:$from_name<$from>",
529 529
                     //					'content-type:text/html charset=UTF-8'
@@ -558,7 +558,7 @@  discard block
 block discarded – undo
558 558
             EE_MAINTENANCE_ADMIN_URL);
559 559
         $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560 560
             EE_MAINTENANCE_ADMIN_URL);
561
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
561
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_confirm_migration_crash_report_sent.template.php';
562 562
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563 563
             $this->_template_args, true);
564 564
         $this->display_admin_page_with_sidebar();
@@ -659,9 +659,9 @@  discard block
 block discarded – undo
659 659
         wp_enqueue_script('ee_admin_js');
660 660
 //		wp_enqueue_media();
661 661
 //		wp_enqueue_script('media-upload');
662
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
662
+        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL.'/ee-maintenance.js', array('jquery'),
663 663
             EVENT_ESPRESSO_VERSION, true);
664
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
664
+        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.css', array(),
665 665
             EVENT_ESPRESSO_VERSION);
666 666
         wp_enqueue_style('espresso_maintenance');
667 667
     }
@@ -698,8 +698,8 @@  discard block
 block discarded – undo
698 698
 
699 699
     protected function _get_datetime_offset_fix_form()
700 700
     {
701
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
701
+        if ( ! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
+            $this->datetime_fix_offset_form = new EE_Form_Section_Proper(
703 703
                 array(
704 704
                     'name' => 'datetime_offset_fix_option',
705 705
                     'layout_strategy' => new EE_Admin_Two_Column_Layout(),
Please login to merge, or discard this patch.
Indentation   +736 added lines, -736 removed lines patch added patch discarded remove patch
@@ -28,755 +28,755 @@
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * @var EE_Datetime_Offset_Fix_Form
33
-     */
34
-    protected $datetime_fix_offset_form;
35
-
36
-
37
-
38
-    protected function _init_page_props()
39
-    {
40
-        $this->page_slug = EE_MAINTENANCE_PG_SLUG;
41
-        $this->page_label = EE_MAINTENANCE_LABEL;
42
-        $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
43
-        $this->_admin_base_path = EE_MAINTENANCE_ADMIN;
44
-    }
45
-
46
-
47
-
48
-    protected function _ajax_hooks()
49
-    {
50
-        add_action('wp_ajax_migration_step', array($this, 'migration_step'));
51
-        add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
52
-    }
53
-
54
-
55
-
56
-    protected function _define_page_props()
57
-    {
58
-        $this->_admin_page_title = EE_MAINTENANCE_LABEL;
59
-        $this->_labels = array(
60
-            'buttons' => array(
61
-                'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
62
-                'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
63
-            ),
64
-        );
65
-    }
66
-
67
-
68
-
69
-    protected function _set_page_routes()
70
-    {
71
-        $this->_page_routes = array(
72
-            'default'                             => array(
73
-                'func'       => '_maintenance',
74
-                'capability' => 'manage_options',
75
-            ),
76
-            'change_maintenance_level'            => array(
77
-                'func'       => '_change_maintenance_level',
78
-                'capability' => 'manage_options',
79
-                'noheader'   => true,
80
-            ),
81
-            'system_status'                       => array(
82
-                'func'       => '_system_status',
83
-                'capability' => 'manage_options',
84
-            ),
85
-            'download_system_status' => array(
86
-                'func'       => '_download_system_status',
87
-                'capability' => 'manage_options',
88
-                'noheader'   => true,
89
-            ),
90
-            'send_migration_crash_report'         => array(
91
-                'func'       => '_send_migration_crash_report',
92
-                'capability' => 'manage_options',
93
-                'noheader'   => true,
94
-            ),
95
-            'confirm_migration_crash_report_sent' => array(
96
-                'func'       => '_confirm_migration_crash_report_sent',
97
-                'capability' => 'manage_options',
98
-            ),
99
-            'data_reset'                          => array(
100
-                'func'       => '_data_reset_and_delete',
101
-                'capability' => 'manage_options',
102
-            ),
103
-            'reset_db'                            => array(
104
-                'func'       => '_reset_db',
105
-                'capability' => 'manage_options',
106
-                'noheader'   => true,
107
-                'args'       => array('nuke_old_ee4_data' => true),
108
-            ),
109
-            'start_with_fresh_ee4_db'             => array(
110
-                'func'       => '_reset_db',
111
-                'capability' => 'manage_options',
112
-                'noheader'   => true,
113
-                'args'       => array('nuke_old_ee4_data' => false),
114
-            ),
115
-            'delete_db'                           => array(
116
-                'func'       => '_delete_db',
117
-                'capability' => 'manage_options',
118
-                'noheader'   => true,
119
-            ),
120
-            'rerun_migration_from_ee3'            => array(
121
-                'func'       => '_rerun_migration_from_ee3',
122
-                'capability' => 'manage_options',
123
-                'noheader'   => true,
124
-            ),
125
-            'reset_reservations'                  => array(
126
-                'func'       => '_reset_reservations',
127
-                'capability' => 'manage_options',
128
-                'noheader'   => true,
129
-            ),
130
-            'reset_capabilities'                  => array(
131
-                'func'       => '_reset_capabilities',
132
-                'capability' => 'manage_options',
133
-                'noheader'   => true,
134
-            ),
135
-            'reattempt_migration'                 => array(
136
-                'func'       => '_reattempt_migration',
137
-                'capability' => 'manage_options',
138
-                'noheader'   => true,
139
-            ),
140
-            'datetime_tools' => array(
141
-                'func' => '_datetime_tools',
142
-                'capability' => 'manage_options'
143
-            ),
144
-            'run_datetime_offset_fix' => array(
145
-                'func' => '_apply_datetime_offset',
146
-                'noheader' => true,
147
-                'headers_sent_route' => 'datetime_tools',
148
-                'capability' => 'manage_options'
149
-            )
150
-        );
151
-    }
152
-
153
-
154
-
155
-    protected function _set_page_config()
156
-    {
157
-        $this->_page_config = array(
158
-            'default'       => array(
159
-                'nav'           => array(
160
-                    'label' => esc_html__('Maintenance', 'event_espresso'),
161
-                    'order' => 10,
162
-                ),
163
-                'require_nonce' => false,
164
-            ),
165
-            'data_reset'    => array(
166
-                'nav'           => array(
167
-                    'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
168
-                    'order' => 20,
169
-                ),
170
-                'require_nonce' => false,
171
-            ),
172
-            'datetime_tools' => array(
173
-                'nav' => array(
174
-                    'label' => esc_html__('Datetime Utilities', 'event_espresso'),
175
-                    'order' => 25
176
-                ),
177
-                'require_nonce' => false,
178
-            ),
179
-            'system_status' => array(
180
-                'nav'           => array(
181
-                    'label' => esc_html__("System Information", "event_espresso"),
182
-                    'order' => 30,
183
-                ),
184
-                'require_nonce' => false,
185
-            ),
186
-        );
187
-    }
188
-
189
-
190
-
191
-    /**
192
-     * default maintenance page. If we're in maintenance mode level 2, then we need to show
193
-     * the migration scripts and all that UI.
194
-     */
195
-    public function _maintenance()
196
-    {
197
-        //it all depends if we're in maintenance model level 1 (frontend-only) or
198
-        //level 2 (everything except maintenance page)
199
-        try {
200
-            //get the current maintenance level and check if
201
-            //we are removed
202
-            $mm = EE_Maintenance_Mode::instance()->level();
203
-            $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
204
-            if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
205
-                //we just took the site out of maintenance mode, so notify the user.
206
-                //unfortunately this message appears to be echoed on the NEXT page load...
207
-                //oh well, we should really be checking for this on addon deactivation anyways
208
-                EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
209
-                    'event_espresso'));
210
-                $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
211
-            }
212
-            //in case an exception is thrown while trying to handle migrations
213
-            switch (EE_Maintenance_Mode::instance()->level()) {
214
-                case EE_Maintenance_Mode::level_0_not_in_maintenance:
215
-                case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
216
-                    $show_maintenance_switch = true;
217
-                    $show_backup_db_text = false;
218
-                    $show_migration_progress = false;
219
-                    $script_names = array();
220
-                    $addons_should_be_upgraded_first = false;
221
-                    break;
222
-                case EE_Maintenance_Mode::level_2_complete_maintenance:
223
-                    $show_maintenance_switch = false;
224
-                    $show_migration_progress = true;
225
-                    if (isset($this->_req_data['continue_migration'])) {
226
-                        $show_backup_db_text = false;
227
-                    } else {
228
-                        $show_backup_db_text = true;
229
-                    }
230
-                    $scripts_needing_to_run = EE_Data_Migration_Manager::instance()
231
-                                                                       ->check_for_applicable_data_migration_scripts();
232
-                    $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
233
-                    $script_names = array();
234
-                    $current_script = null;
235
-                    foreach ($scripts_needing_to_run as $script) {
236
-                        if ($script instanceof EE_Data_Migration_Script_Base) {
237
-                            if ( ! $current_script) {
238
-                                $current_script = $script;
239
-                                $current_script->migration_page_hooks();
240
-                            }
241
-                            $script_names[] = $script->pretty_name();
242
-                        }
243
-                    }
244
-                    break;
245
-            }
246
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
247
-            $exception_thrown = false;
248
-        } catch (EE_Error $e) {
249
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
250
-            //now, just so we can display the page correctly, make a error migration script stage object
251
-            //and also put the error on it. It only persists for the duration of this request
252
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
253
-            $most_recent_migration->add_error($e->getMessage());
254
-            $exception_thrown = true;
255
-        }
256
-        $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
257
-        $current_db_state = str_replace('.decaf', '', $current_db_state);
258
-        if ($exception_thrown
259
-            || ($most_recent_migration
260
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
261
-                && $most_recent_migration->is_broken()
262
-            )
263
-        ) {
264
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
265
-            $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266
-            $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267
-                                                                                        'success' => '0',
268
-            ), EE_MAINTENANCE_ADMIN_URL);
269
-        } elseif ($addons_should_be_upgraded_first) {
270
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
271
-        } else {
272
-            if ($most_recent_migration
273
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
274
-                && $most_recent_migration->can_continue()
275
-            ) {
276
-                $show_backup_db_text = false;
277
-                $show_continue_current_migration_script = true;
278
-                $show_most_recent_migration = true;
279
-            } elseif (isset($this->_req_data['continue_migration'])) {
280
-                $show_most_recent_migration = true;
281
-                $show_continue_current_migration_script = false;
282
-            } else {
283
-                $show_most_recent_migration = false;
284
-                $show_continue_current_migration_script = false;
285
-            }
286
-            if (isset($current_script)) {
287
-                $migrates_to = $current_script->migrates_to_version();
288
-                $plugin_slug = $migrates_to['slug'];
289
-                $new_version = $migrates_to['version'];
290
-                $this->_template_args = array_merge($this->_template_args, array(
291
-                    'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
292
-                        isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
293
-                    'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
294
-                        $new_version, $plugin_slug) : null,
295
-                ));
296
-            } else {
297
-                $this->_template_args['current_db_state'] = null;
298
-                $this->_template_args['next_db_state'] = null;
299
-            }
300
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
301
-            $this->_template_args = array_merge(
302
-                $this->_template_args,
303
-                array(
304
-                    'show_most_recent_migration'             => $show_most_recent_migration,
305
-                    //flag for showing the most recent migration's status and/or errors
306
-                    'show_migration_progress'                => $show_migration_progress,
307
-                    //flag for showing the option to run migrations and see their progress
308
-                    'show_backup_db_text'                    => $show_backup_db_text,
309
-                    //flag for showing text telling the user to backup their DB
310
-                    'show_maintenance_switch'                => $show_maintenance_switch,
311
-                    //flag for showing the option to change maintenance mode between levels 0 and 1
312
-                    'script_names'                           => $script_names,
313
-                    //array of names of scripts that have run
314
-                    'show_continue_current_migration_script' => $show_continue_current_migration_script,
315
-                    //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
316
-                    'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
317
-                        EE_MAINTENANCE_ADMIN_URL),
318
-                    'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
319
-                        EE_MAINTENANCE_ADMIN_URL),
320
-                    'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
321
-                        EE_MAINTENANCE_ADMIN_URL),
322
-                    'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
323
-                        espresso_version()),
324
-                )
325
-            );
326
-            //make sure we have the form fields helper available. It usually is, but sometimes it isn't
327
-            //localize script stuff
328
-            wp_localize_script('ee-maintenance', 'ee_maintenance', array(
329
-                'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
330
-                'next'                             => esc_html__("Next", "event_espresso"),
331
-                'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
332
-                'click_next_when_ready'            => esc_html__("The current Database Update has ended. Click 'next' when ready to proceed",
333
-                    "event_espresso"),
334
-                'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
335
-                'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
336
-                'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337
-            ));
338
-        }
339
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
340
-        //now render the migration options part, and put it in a variable
341
-        $migration_options_template_file = apply_filters(
342
-            'FHEE__ee_migration_page__migration_options_template',
343
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
344
-        );
345
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
346
-        $this->_template_args['migration_options_html'] = $migration_options_html;
347
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348
-            $this->_template_args, true);
349
-        $this->display_admin_page_with_sidebar();
350
-    }
351
-
352
-
353
-
354
-    /**
355
-     * returns JSON and executes another step of the currently-executing data migration (called via ajax)
356
-     */
357
-    public function migration_step()
358
-    {
359
-        $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
360
-        $this->_return_json();
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * Can be used by js when it notices a response with HTML in it in order
367
-     * to log the malformed response
368
-     */
369
-    public function add_error_to_migrations_ran()
370
-    {
371
-        EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
372
-        $this->_template_args['data'] = array('ok' => true);
373
-        $this->_return_json();
374
-    }
375
-
376
-
377
-
378
-    /**
379
-     * changes the maintenance level, provided there are still no migration scripts that should run
380
-     */
381
-    public function _change_maintenance_level()
382
-    {
383
-        $new_level = absint($this->_req_data['maintenance_mode_level']);
384
-        if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
385
-            EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
386
-            $success = true;
387
-        } else {
388
-            EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
389
-            $success = false;
390
-        }
391
-        $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
392
-    }
393
-
394
-
395
-
396
-    /**
397
-     * a tab with options for resetting and/or deleting EE data
398
-     *
399
-     * @throws \EE_Error
400
-     * @throws \DomainException
401
-     */
402
-    public function _data_reset_and_delete()
403
-    {
404
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
405
-        $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406
-            'reset_reservations',
407
-            'reset_reservations',
408
-            array(),
409
-            'button button-primary',
410
-            '',
411
-            false
412
-        );
413
-        $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
414
-            'reset_capabilities',
415
-            'reset_capabilities',
416
-            array(),
417
-            'button button-primary',
418
-            '',
419
-            false
420
-        );
421
-        $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
422
-            array('action' => 'delete_db'),
423
-            EE_MAINTENANCE_ADMIN_URL
424
-        );
425
-        $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
426
-            array('action' => 'reset_db'),
427
-            EE_MAINTENANCE_ADMIN_URL
428
-        );
429
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
430
-            $this->_template_path,
431
-            $this->_template_args,
432
-            true
433
-        );
434
-        $this->display_admin_page_with_sidebar();
435
-    }
436
-
437
-
438
-
439
-    protected function _reset_reservations()
440
-    {
441
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442
-            EE_Error::add_success(
443
-                __(
444
-                    'Ticket and datetime reserved counts have been successfully reset.',
445
-                    'event_espresso'
446
-                )
447
-            );
448
-        } else {
449
-            EE_Error::add_success(
450
-                __(
451
-                    'Ticket and datetime reserved counts were correct and did not need resetting.',
452
-                    'event_espresso'
453
-                )
454
-            );
455
-        }
456
-        $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
457
-    }
458
-
459
-
460
-
461
-    protected function _reset_capabilities()
462
-    {
463
-        EE_Registry::instance()->CAP->init_caps(true);
464
-        EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
465
-            'event_espresso'));
466
-        $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
467
-    }
468
-
469
-
470
-
471
-    /**
472
-     * resets the DMSs so we can attempt to continue migrating after a fatal error
473
-     * (only a good idea when someone has somehow tried ot fix whatever caused
474
-     * the fatal error in teh first place)
475
-     */
476
-    protected function _reattempt_migration()
477
-    {
478
-        EE_Data_Migration_Manager::instance()->reattempt();
479
-        $this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * shows the big ol' System Information page
486
-     */
487
-    public function _system_status()
488
-    {
489
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
490
-        $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491
-        $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492
-            array(
493
-                'action' => 'download_system_status',
494
-            ),
495
-            EE_MAINTENANCE_ADMIN_URL
496
-        );
497
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
498
-            $this->_template_args, true);
499
-        $this->display_admin_page_with_sidebar();
500
-    }
501
-
502
-    /**
503
-     * Downloads an HTML file of the system status that can be easily stored or emailed
504
-     */
505
-    public function _download_system_status()
506
-    {
507
-        $status_info = EEM_System_Status::instance()->get_system_stati();
508
-        header( 'Content-Disposition: attachment' );
509
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
510
-        echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
-        echo "<h1>System Information for " . site_url() . "</h1>";
512
-        echo EEH_Template::layout_array_as_table( $status_info );
513
-        die;
514
-    }
515
-
516
-
517
-
518
-    public function _send_migration_crash_report()
519
-    {
520
-        $from = $this->_req_data['from'];
521
-        $from_name = $this->_req_data['from_name'];
522
-        $body = $this->_req_data['body'];
523
-        try {
524
-            $success = wp_mail(EE_SUPPORT_EMAIL,
525
-                'Migration Crash Report',
526
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
527
-                array(
528
-                    "from:$from_name<$from>",
529
-                    //					'content-type:text/html charset=UTF-8'
530
-                ));
531
-        } catch (Exception $e) {
532
-            $success = false;
533
-        }
534
-        $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
535
-            esc_html__("sent", "event_espresso"),
536
-            array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
537
-    }
538
-
539
-
540
-
541
-    public function _confirm_migration_crash_report_sent()
542
-    {
543
-        try {
544
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
545
-        } catch (EE_Error $e) {
546
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
547
-            //now, just so we can display the page correctly, make a error migration script stage object
548
-            //and also put the error on it. It only persists for the duration of this request
549
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
550
-            $most_recent_migration->add_error($e->getMessage());
551
-        }
552
-        $success = $this->_req_data['success'] == '1' ? true : false;
553
-        $this->_template_args['success'] = $success;
554
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;
555
-        $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
556
-            EE_MAINTENANCE_ADMIN_URL);
557
-        $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
558
-            EE_MAINTENANCE_ADMIN_URL);
559
-        $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560
-            EE_MAINTENANCE_ADMIN_URL);
561
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
562
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563
-            $this->_template_args, true);
564
-        $this->display_admin_page_with_sidebar();
565
-    }
566
-
567
-
568
-
569
-    /**
570
-     * Resets the entire EE4 database.
571
-     * Currently basically only sets up ee4 database for a fresh install- doesn't
572
-     * actually clean out the old wp options, or cpts (although does erase old ee table data)
573
-     *
574
-     * @param boolean $nuke_old_ee4_data controls whether or not we
575
-     *                                   destroy the old ee4 data, or just try initializing ee4 default data
576
-     */
577
-    public function _reset_db($nuke_old_ee4_data = true)
578
-    {
579
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
580
-        if ($nuke_old_ee4_data) {
581
-            EEH_Activation::delete_all_espresso_cpt_data();
582
-            EEH_Activation::delete_all_espresso_tables_and_data(false);
583
-            EEH_Activation::remove_cron_tasks();
584
-        }
585
-        //make sure when we reset the registry's config that it
586
-        //switches to using the new singleton
587
-        EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
588
-        EE_System::instance()->initialize_db_if_no_migrations_required(true);
589
-        EE_System::instance()->redirect_to_about_ee();
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     * Deletes ALL EE tables, Records, and Options from the database.
596
-     */
597
-    public function _delete_db()
598
-    {
599
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
600
-        EEH_Activation::delete_all_espresso_cpt_data();
601
-        EEH_Activation::delete_all_espresso_tables_and_data();
602
-        EEH_Activation::remove_cron_tasks();
603
-        EEH_Activation::deactivate_event_espresso();
604
-        wp_safe_redirect(admin_url('plugins.php'));
605
-        exit;
606
-    }
607
-
608
-
609
-
610
-    /**
611
-     * sets up EE4 to rerun the migrations from ee3 to ee4
612
-     */
613
-    public function _rerun_migration_from_ee3()
614
-    {
615
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
616
-        EEH_Activation::delete_all_espresso_cpt_data();
617
-        EEH_Activation::delete_all_espresso_tables_and_data(false);
618
-        //set the db state to something that will require migrations
619
-        update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
620
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
621
-        $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
622
-    }
623
-
624
-
625
-
626
-    //none of the below group are currently used for Gateway Settings
627
-    protected function _add_screen_options()
628
-    {
629
-    }
630
-
631
-
632
-
633
-    protected function _add_feature_pointers()
634
-    {
635
-    }
636
-
31
+	/**
32
+	 * @var EE_Datetime_Offset_Fix_Form
33
+	 */
34
+	protected $datetime_fix_offset_form;
35
+
36
+
37
+
38
+	protected function _init_page_props()
39
+	{
40
+		$this->page_slug = EE_MAINTENANCE_PG_SLUG;
41
+		$this->page_label = EE_MAINTENANCE_LABEL;
42
+		$this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
43
+		$this->_admin_base_path = EE_MAINTENANCE_ADMIN;
44
+	}
45
+
46
+
47
+
48
+	protected function _ajax_hooks()
49
+	{
50
+		add_action('wp_ajax_migration_step', array($this, 'migration_step'));
51
+		add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
52
+	}
53
+
54
+
55
+
56
+	protected function _define_page_props()
57
+	{
58
+		$this->_admin_page_title = EE_MAINTENANCE_LABEL;
59
+		$this->_labels = array(
60
+			'buttons' => array(
61
+				'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
62
+				'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
63
+			),
64
+		);
65
+	}
66
+
67
+
68
+
69
+	protected function _set_page_routes()
70
+	{
71
+		$this->_page_routes = array(
72
+			'default'                             => array(
73
+				'func'       => '_maintenance',
74
+				'capability' => 'manage_options',
75
+			),
76
+			'change_maintenance_level'            => array(
77
+				'func'       => '_change_maintenance_level',
78
+				'capability' => 'manage_options',
79
+				'noheader'   => true,
80
+			),
81
+			'system_status'                       => array(
82
+				'func'       => '_system_status',
83
+				'capability' => 'manage_options',
84
+			),
85
+			'download_system_status' => array(
86
+				'func'       => '_download_system_status',
87
+				'capability' => 'manage_options',
88
+				'noheader'   => true,
89
+			),
90
+			'send_migration_crash_report'         => array(
91
+				'func'       => '_send_migration_crash_report',
92
+				'capability' => 'manage_options',
93
+				'noheader'   => true,
94
+			),
95
+			'confirm_migration_crash_report_sent' => array(
96
+				'func'       => '_confirm_migration_crash_report_sent',
97
+				'capability' => 'manage_options',
98
+			),
99
+			'data_reset'                          => array(
100
+				'func'       => '_data_reset_and_delete',
101
+				'capability' => 'manage_options',
102
+			),
103
+			'reset_db'                            => array(
104
+				'func'       => '_reset_db',
105
+				'capability' => 'manage_options',
106
+				'noheader'   => true,
107
+				'args'       => array('nuke_old_ee4_data' => true),
108
+			),
109
+			'start_with_fresh_ee4_db'             => array(
110
+				'func'       => '_reset_db',
111
+				'capability' => 'manage_options',
112
+				'noheader'   => true,
113
+				'args'       => array('nuke_old_ee4_data' => false),
114
+			),
115
+			'delete_db'                           => array(
116
+				'func'       => '_delete_db',
117
+				'capability' => 'manage_options',
118
+				'noheader'   => true,
119
+			),
120
+			'rerun_migration_from_ee3'            => array(
121
+				'func'       => '_rerun_migration_from_ee3',
122
+				'capability' => 'manage_options',
123
+				'noheader'   => true,
124
+			),
125
+			'reset_reservations'                  => array(
126
+				'func'       => '_reset_reservations',
127
+				'capability' => 'manage_options',
128
+				'noheader'   => true,
129
+			),
130
+			'reset_capabilities'                  => array(
131
+				'func'       => '_reset_capabilities',
132
+				'capability' => 'manage_options',
133
+				'noheader'   => true,
134
+			),
135
+			'reattempt_migration'                 => array(
136
+				'func'       => '_reattempt_migration',
137
+				'capability' => 'manage_options',
138
+				'noheader'   => true,
139
+			),
140
+			'datetime_tools' => array(
141
+				'func' => '_datetime_tools',
142
+				'capability' => 'manage_options'
143
+			),
144
+			'run_datetime_offset_fix' => array(
145
+				'func' => '_apply_datetime_offset',
146
+				'noheader' => true,
147
+				'headers_sent_route' => 'datetime_tools',
148
+				'capability' => 'manage_options'
149
+			)
150
+		);
151
+	}
152
+
153
+
154
+
155
+	protected function _set_page_config()
156
+	{
157
+		$this->_page_config = array(
158
+			'default'       => array(
159
+				'nav'           => array(
160
+					'label' => esc_html__('Maintenance', 'event_espresso'),
161
+					'order' => 10,
162
+				),
163
+				'require_nonce' => false,
164
+			),
165
+			'data_reset'    => array(
166
+				'nav'           => array(
167
+					'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
168
+					'order' => 20,
169
+				),
170
+				'require_nonce' => false,
171
+			),
172
+			'datetime_tools' => array(
173
+				'nav' => array(
174
+					'label' => esc_html__('Datetime Utilities', 'event_espresso'),
175
+					'order' => 25
176
+				),
177
+				'require_nonce' => false,
178
+			),
179
+			'system_status' => array(
180
+				'nav'           => array(
181
+					'label' => esc_html__("System Information", "event_espresso"),
182
+					'order' => 30,
183
+				),
184
+				'require_nonce' => false,
185
+			),
186
+		);
187
+	}
188
+
189
+
190
+
191
+	/**
192
+	 * default maintenance page. If we're in maintenance mode level 2, then we need to show
193
+	 * the migration scripts and all that UI.
194
+	 */
195
+	public function _maintenance()
196
+	{
197
+		//it all depends if we're in maintenance model level 1 (frontend-only) or
198
+		//level 2 (everything except maintenance page)
199
+		try {
200
+			//get the current maintenance level and check if
201
+			//we are removed
202
+			$mm = EE_Maintenance_Mode::instance()->level();
203
+			$placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
204
+			if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
205
+				//we just took the site out of maintenance mode, so notify the user.
206
+				//unfortunately this message appears to be echoed on the NEXT page load...
207
+				//oh well, we should really be checking for this on addon deactivation anyways
208
+				EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
209
+					'event_espresso'));
210
+				$this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
211
+			}
212
+			//in case an exception is thrown while trying to handle migrations
213
+			switch (EE_Maintenance_Mode::instance()->level()) {
214
+				case EE_Maintenance_Mode::level_0_not_in_maintenance:
215
+				case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
216
+					$show_maintenance_switch = true;
217
+					$show_backup_db_text = false;
218
+					$show_migration_progress = false;
219
+					$script_names = array();
220
+					$addons_should_be_upgraded_first = false;
221
+					break;
222
+				case EE_Maintenance_Mode::level_2_complete_maintenance:
223
+					$show_maintenance_switch = false;
224
+					$show_migration_progress = true;
225
+					if (isset($this->_req_data['continue_migration'])) {
226
+						$show_backup_db_text = false;
227
+					} else {
228
+						$show_backup_db_text = true;
229
+					}
230
+					$scripts_needing_to_run = EE_Data_Migration_Manager::instance()
231
+																	   ->check_for_applicable_data_migration_scripts();
232
+					$addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
233
+					$script_names = array();
234
+					$current_script = null;
235
+					foreach ($scripts_needing_to_run as $script) {
236
+						if ($script instanceof EE_Data_Migration_Script_Base) {
237
+							if ( ! $current_script) {
238
+								$current_script = $script;
239
+								$current_script->migration_page_hooks();
240
+							}
241
+							$script_names[] = $script->pretty_name();
242
+						}
243
+					}
244
+					break;
245
+			}
246
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
247
+			$exception_thrown = false;
248
+		} catch (EE_Error $e) {
249
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
250
+			//now, just so we can display the page correctly, make a error migration script stage object
251
+			//and also put the error on it. It only persists for the duration of this request
252
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
253
+			$most_recent_migration->add_error($e->getMessage());
254
+			$exception_thrown = true;
255
+		}
256
+		$current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
257
+		$current_db_state = str_replace('.decaf', '', $current_db_state);
258
+		if ($exception_thrown
259
+			|| ($most_recent_migration
260
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
261
+				&& $most_recent_migration->is_broken()
262
+			)
263
+		) {
264
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
265
+			$this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266
+			$this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267
+																						'success' => '0',
268
+			), EE_MAINTENANCE_ADMIN_URL);
269
+		} elseif ($addons_should_be_upgraded_first) {
270
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
271
+		} else {
272
+			if ($most_recent_migration
273
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
274
+				&& $most_recent_migration->can_continue()
275
+			) {
276
+				$show_backup_db_text = false;
277
+				$show_continue_current_migration_script = true;
278
+				$show_most_recent_migration = true;
279
+			} elseif (isset($this->_req_data['continue_migration'])) {
280
+				$show_most_recent_migration = true;
281
+				$show_continue_current_migration_script = false;
282
+			} else {
283
+				$show_most_recent_migration = false;
284
+				$show_continue_current_migration_script = false;
285
+			}
286
+			if (isset($current_script)) {
287
+				$migrates_to = $current_script->migrates_to_version();
288
+				$plugin_slug = $migrates_to['slug'];
289
+				$new_version = $migrates_to['version'];
290
+				$this->_template_args = array_merge($this->_template_args, array(
291
+					'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
292
+						isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
293
+					'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
294
+						$new_version, $plugin_slug) : null,
295
+				));
296
+			} else {
297
+				$this->_template_args['current_db_state'] = null;
298
+				$this->_template_args['next_db_state'] = null;
299
+			}
300
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
301
+			$this->_template_args = array_merge(
302
+				$this->_template_args,
303
+				array(
304
+					'show_most_recent_migration'             => $show_most_recent_migration,
305
+					//flag for showing the most recent migration's status and/or errors
306
+					'show_migration_progress'                => $show_migration_progress,
307
+					//flag for showing the option to run migrations and see their progress
308
+					'show_backup_db_text'                    => $show_backup_db_text,
309
+					//flag for showing text telling the user to backup their DB
310
+					'show_maintenance_switch'                => $show_maintenance_switch,
311
+					//flag for showing the option to change maintenance mode between levels 0 and 1
312
+					'script_names'                           => $script_names,
313
+					//array of names of scripts that have run
314
+					'show_continue_current_migration_script' => $show_continue_current_migration_script,
315
+					//flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
316
+					'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
317
+						EE_MAINTENANCE_ADMIN_URL),
318
+					'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
319
+						EE_MAINTENANCE_ADMIN_URL),
320
+					'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
321
+						EE_MAINTENANCE_ADMIN_URL),
322
+					'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
323
+						espresso_version()),
324
+				)
325
+			);
326
+			//make sure we have the form fields helper available. It usually is, but sometimes it isn't
327
+			//localize script stuff
328
+			wp_localize_script('ee-maintenance', 'ee_maintenance', array(
329
+				'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
330
+				'next'                             => esc_html__("Next", "event_espresso"),
331
+				'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
332
+				'click_next_when_ready'            => esc_html__("The current Database Update has ended. Click 'next' when ready to proceed",
333
+					"event_espresso"),
334
+				'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
335
+				'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
336
+				'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337
+			));
338
+		}
339
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
340
+		//now render the migration options part, and put it in a variable
341
+		$migration_options_template_file = apply_filters(
342
+			'FHEE__ee_migration_page__migration_options_template',
343
+			EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
344
+		);
345
+		$migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
346
+		$this->_template_args['migration_options_html'] = $migration_options_html;
347
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348
+			$this->_template_args, true);
349
+		$this->display_admin_page_with_sidebar();
350
+	}
351
+
352
+
353
+
354
+	/**
355
+	 * returns JSON and executes another step of the currently-executing data migration (called via ajax)
356
+	 */
357
+	public function migration_step()
358
+	{
359
+		$this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
360
+		$this->_return_json();
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * Can be used by js when it notices a response with HTML in it in order
367
+	 * to log the malformed response
368
+	 */
369
+	public function add_error_to_migrations_ran()
370
+	{
371
+		EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
372
+		$this->_template_args['data'] = array('ok' => true);
373
+		$this->_return_json();
374
+	}
375
+
376
+
377
+
378
+	/**
379
+	 * changes the maintenance level, provided there are still no migration scripts that should run
380
+	 */
381
+	public function _change_maintenance_level()
382
+	{
383
+		$new_level = absint($this->_req_data['maintenance_mode_level']);
384
+		if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
385
+			EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
386
+			$success = true;
387
+		} else {
388
+			EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
389
+			$success = false;
390
+		}
391
+		$this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
392
+	}
393
+
394
+
395
+
396
+	/**
397
+	 * a tab with options for resetting and/or deleting EE data
398
+	 *
399
+	 * @throws \EE_Error
400
+	 * @throws \DomainException
401
+	 */
402
+	public function _data_reset_and_delete()
403
+	{
404
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
405
+		$this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406
+			'reset_reservations',
407
+			'reset_reservations',
408
+			array(),
409
+			'button button-primary',
410
+			'',
411
+			false
412
+		);
413
+		$this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
414
+			'reset_capabilities',
415
+			'reset_capabilities',
416
+			array(),
417
+			'button button-primary',
418
+			'',
419
+			false
420
+		);
421
+		$this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
422
+			array('action' => 'delete_db'),
423
+			EE_MAINTENANCE_ADMIN_URL
424
+		);
425
+		$this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
426
+			array('action' => 'reset_db'),
427
+			EE_MAINTENANCE_ADMIN_URL
428
+		);
429
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
430
+			$this->_template_path,
431
+			$this->_template_args,
432
+			true
433
+		);
434
+		$this->display_admin_page_with_sidebar();
435
+	}
436
+
437
+
438
+
439
+	protected function _reset_reservations()
440
+	{
441
+		if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442
+			EE_Error::add_success(
443
+				__(
444
+					'Ticket and datetime reserved counts have been successfully reset.',
445
+					'event_espresso'
446
+				)
447
+			);
448
+		} else {
449
+			EE_Error::add_success(
450
+				__(
451
+					'Ticket and datetime reserved counts were correct and did not need resetting.',
452
+					'event_espresso'
453
+				)
454
+			);
455
+		}
456
+		$this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
457
+	}
458
+
459
+
460
+
461
+	protected function _reset_capabilities()
462
+	{
463
+		EE_Registry::instance()->CAP->init_caps(true);
464
+		EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
465
+			'event_espresso'));
466
+		$this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
467
+	}
468
+
469
+
470
+
471
+	/**
472
+	 * resets the DMSs so we can attempt to continue migrating after a fatal error
473
+	 * (only a good idea when someone has somehow tried ot fix whatever caused
474
+	 * the fatal error in teh first place)
475
+	 */
476
+	protected function _reattempt_migration()
477
+	{
478
+		EE_Data_Migration_Manager::instance()->reattempt();
479
+		$this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * shows the big ol' System Information page
486
+	 */
487
+	public function _system_status()
488
+	{
489
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
490
+		$this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491
+		$this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492
+			array(
493
+				'action' => 'download_system_status',
494
+			),
495
+			EE_MAINTENANCE_ADMIN_URL
496
+		);
497
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
498
+			$this->_template_args, true);
499
+		$this->display_admin_page_with_sidebar();
500
+	}
501
+
502
+	/**
503
+	 * Downloads an HTML file of the system status that can be easily stored or emailed
504
+	 */
505
+	public function _download_system_status()
506
+	{
507
+		$status_info = EEM_System_Status::instance()->get_system_stati();
508
+		header( 'Content-Disposition: attachment' );
509
+		header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
510
+		echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
+		echo "<h1>System Information for " . site_url() . "</h1>";
512
+		echo EEH_Template::layout_array_as_table( $status_info );
513
+		die;
514
+	}
515
+
516
+
517
+
518
+	public function _send_migration_crash_report()
519
+	{
520
+		$from = $this->_req_data['from'];
521
+		$from_name = $this->_req_data['from_name'];
522
+		$body = $this->_req_data['body'];
523
+		try {
524
+			$success = wp_mail(EE_SUPPORT_EMAIL,
525
+				'Migration Crash Report',
526
+				$body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
527
+				array(
528
+					"from:$from_name<$from>",
529
+					//					'content-type:text/html charset=UTF-8'
530
+				));
531
+		} catch (Exception $e) {
532
+			$success = false;
533
+		}
534
+		$this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
535
+			esc_html__("sent", "event_espresso"),
536
+			array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
537
+	}
538
+
539
+
540
+
541
+	public function _confirm_migration_crash_report_sent()
542
+	{
543
+		try {
544
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
545
+		} catch (EE_Error $e) {
546
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
547
+			//now, just so we can display the page correctly, make a error migration script stage object
548
+			//and also put the error on it. It only persists for the duration of this request
549
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
550
+			$most_recent_migration->add_error($e->getMessage());
551
+		}
552
+		$success = $this->_req_data['success'] == '1' ? true : false;
553
+		$this->_template_args['success'] = $success;
554
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;
555
+		$this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
556
+			EE_MAINTENANCE_ADMIN_URL);
557
+		$this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
558
+			EE_MAINTENANCE_ADMIN_URL);
559
+		$this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560
+			EE_MAINTENANCE_ADMIN_URL);
561
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
562
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563
+			$this->_template_args, true);
564
+		$this->display_admin_page_with_sidebar();
565
+	}
566
+
567
+
568
+
569
+	/**
570
+	 * Resets the entire EE4 database.
571
+	 * Currently basically only sets up ee4 database for a fresh install- doesn't
572
+	 * actually clean out the old wp options, or cpts (although does erase old ee table data)
573
+	 *
574
+	 * @param boolean $nuke_old_ee4_data controls whether or not we
575
+	 *                                   destroy the old ee4 data, or just try initializing ee4 default data
576
+	 */
577
+	public function _reset_db($nuke_old_ee4_data = true)
578
+	{
579
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
580
+		if ($nuke_old_ee4_data) {
581
+			EEH_Activation::delete_all_espresso_cpt_data();
582
+			EEH_Activation::delete_all_espresso_tables_and_data(false);
583
+			EEH_Activation::remove_cron_tasks();
584
+		}
585
+		//make sure when we reset the registry's config that it
586
+		//switches to using the new singleton
587
+		EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
588
+		EE_System::instance()->initialize_db_if_no_migrations_required(true);
589
+		EE_System::instance()->redirect_to_about_ee();
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 * Deletes ALL EE tables, Records, and Options from the database.
596
+	 */
597
+	public function _delete_db()
598
+	{
599
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
600
+		EEH_Activation::delete_all_espresso_cpt_data();
601
+		EEH_Activation::delete_all_espresso_tables_and_data();
602
+		EEH_Activation::remove_cron_tasks();
603
+		EEH_Activation::deactivate_event_espresso();
604
+		wp_safe_redirect(admin_url('plugins.php'));
605
+		exit;
606
+	}
607
+
608
+
609
+
610
+	/**
611
+	 * sets up EE4 to rerun the migrations from ee3 to ee4
612
+	 */
613
+	public function _rerun_migration_from_ee3()
614
+	{
615
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
616
+		EEH_Activation::delete_all_espresso_cpt_data();
617
+		EEH_Activation::delete_all_espresso_tables_and_data(false);
618
+		//set the db state to something that will require migrations
619
+		update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
620
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
621
+		$this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
622
+	}
623
+
624
+
625
+
626
+	//none of the below group are currently used for Gateway Settings
627
+	protected function _add_screen_options()
628
+	{
629
+	}
630
+
631
+
632
+
633
+	protected function _add_feature_pointers()
634
+	{
635
+	}
636
+
637 637
 
638 638
 
639
-    public function admin_init()
640
-    {
641
-    }
642
-
643
-
644
-
645
-    public function admin_notices()
646
-    {
647
-    }
648
-
639
+	public function admin_init()
640
+	{
641
+	}
642
+
643
+
644
+
645
+	public function admin_notices()
646
+	{
647
+	}
648
+
649 649
 
650 650
 
651
-    public function admin_footer_scripts()
652
-    {
653
-    }
651
+	public function admin_footer_scripts()
652
+	{
653
+	}
654 654
 
655 655
 
656 656
 
657
-    public function load_scripts_styles()
658
-    {
659
-        wp_enqueue_script('ee_admin_js');
657
+	public function load_scripts_styles()
658
+	{
659
+		wp_enqueue_script('ee_admin_js');
660 660
 //		wp_enqueue_media();
661 661
 //		wp_enqueue_script('media-upload');
662
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
663
-            EVENT_ESPRESSO_VERSION, true);
664
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
665
-            EVENT_ESPRESSO_VERSION);
666
-        wp_enqueue_style('espresso_maintenance');
667
-    }
662
+		wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
663
+			EVENT_ESPRESSO_VERSION, true);
664
+		wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
665
+			EVENT_ESPRESSO_VERSION);
666
+		wp_enqueue_style('espresso_maintenance');
667
+	}
668 668
 
669 669
 
670 670
 
671
-    public function load_scripts_styles_default()
672
-    {
673
-        //styles
671
+	public function load_scripts_styles_default()
672
+	{
673
+		//styles
674 674
 //		wp_enqueue_style('ee-text-links');
675 675
 //		//scripts
676 676
 //		wp_enqueue_script('ee-text-links');
677
-    }
678
-
679
-
680
-    protected function _datetime_tools()
681
-    {
682
-        $form_action = EE_Admin_Page::add_query_args_and_nonce(
683
-            array(
684
-                'action' => 'run_datetime_offset_fix',
685
-                'return_action' => $this->_req_action
686
-            ),
687
-            EE_MAINTENANCE_ADMIN_URL
688
-        );
689
-        $form = $this->_get_datetime_offset_fix_form();
690
-        $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
691
-        $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
692
-                                                      . $form->get_html_and_js()
693
-                                                      . $form->form_close();
694
-        $this->display_admin_page_with_no_sidebar();
695
-    }
696
-
697
-
698
-
699
-    protected function _get_datetime_offset_fix_form()
700
-    {
701
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
703
-                array(
704
-                    'name' => 'datetime_offset_fix_option',
705
-                    'layout_strategy' => new EE_Admin_Two_Column_Layout(),
706
-                    'subsections' => array(
707
-                        'title' => new EE_Form_Section_HTML(
708
-                            EEH_HTML::h2(
709
-                                esc_html__('Datetime Offset Tool', 'event_espresso')
710
-                            )
711
-                        ),
712
-                        'explanation' => new EE_Form_Section_HTML(
713
-                            EEH_HTML::p(
714
-                                esc_html__(
715
-                                    'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
716
-                                    'event_espresso'
717
-                                )
718
-                            )
719
-                            . EEH_HTML::p(
720
-                                esc_html__(
721
-                                    'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
722
-                                    'event_espresso'
723
-                                )
724
-                            )
725
-                        ),
726
-                        'offset_input' => new EE_Float_Input(
727
-                            array(
728
-                                'html_name' => 'offset_for_datetimes',
729
-                                'html_label_text' => esc_html__(
730
-                                    'Offset to apply (in hours):',
731
-                                    'event_espresso'
732
-                                ),
733
-                                'min_value' => '-12',
734
-                                'max_value' => '14',
735
-                                'step_value' => '.25',
736
-                                'default' => DatetimeOffsetFix::getOffset()
737
-                            )
738
-                        ),
739
-                        'submit' => new EE_Submit_Input(
740
-                            array(
741
-                                'html_label_text' => '',
742
-                                'default' => esc_html__('Apply Offset', 'event_espresso')
743
-                            )
744
-                        )
745
-                    )
746
-                )
747
-            );
748
-        }
749
-        return $this->datetime_fix_offset_form;
750
-    }
751
-
752
-
753
-    /**
754
-     * Callback for the run_datetime_offset_fix route.
755
-     * @throws EE_Error
756
-     */
757
-    protected function _apply_datetime_offset()
758
-    {
759
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
760
-            $form = $this->_get_datetime_offset_fix_form();
761
-            $form->receive_form_submission($this->_req_data);
762
-            if ($form->is_valid()) {
763
-                //save offset so batch processor can get it.
764
-                DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
765
-                //redirect to batch tool
766
-                wp_redirect(
767
-                    EE_Admin_Page::add_query_args_and_nonce(
768
-                        array(
769
-                            'page' => 'espresso_batch',
770
-                            'batch' => 'job',
771
-                            'label' => esc_html__('Applying Offset', 'event_espresso'),
772
-                            'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
773
-                            'return_url' => urlencode(home_url(add_query_arg(null, null))),
774
-                        ),
775
-                        admin_url()
776
-                    )
777
-                );
778
-                exit;
779
-            }
780
-        }
781
-    }
677
+	}
678
+
679
+
680
+	protected function _datetime_tools()
681
+	{
682
+		$form_action = EE_Admin_Page::add_query_args_and_nonce(
683
+			array(
684
+				'action' => 'run_datetime_offset_fix',
685
+				'return_action' => $this->_req_action
686
+			),
687
+			EE_MAINTENANCE_ADMIN_URL
688
+		);
689
+		$form = $this->_get_datetime_offset_fix_form();
690
+		$this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
691
+		$this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
692
+													  . $form->get_html_and_js()
693
+													  . $form->form_close();
694
+		$this->display_admin_page_with_no_sidebar();
695
+	}
696
+
697
+
698
+
699
+	protected function _get_datetime_offset_fix_form()
700
+	{
701
+		if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
+			$this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
703
+				array(
704
+					'name' => 'datetime_offset_fix_option',
705
+					'layout_strategy' => new EE_Admin_Two_Column_Layout(),
706
+					'subsections' => array(
707
+						'title' => new EE_Form_Section_HTML(
708
+							EEH_HTML::h2(
709
+								esc_html__('Datetime Offset Tool', 'event_espresso')
710
+							)
711
+						),
712
+						'explanation' => new EE_Form_Section_HTML(
713
+							EEH_HTML::p(
714
+								esc_html__(
715
+									'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
716
+									'event_espresso'
717
+								)
718
+							)
719
+							. EEH_HTML::p(
720
+								esc_html__(
721
+									'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
722
+									'event_espresso'
723
+								)
724
+							)
725
+						),
726
+						'offset_input' => new EE_Float_Input(
727
+							array(
728
+								'html_name' => 'offset_for_datetimes',
729
+								'html_label_text' => esc_html__(
730
+									'Offset to apply (in hours):',
731
+									'event_espresso'
732
+								),
733
+								'min_value' => '-12',
734
+								'max_value' => '14',
735
+								'step_value' => '.25',
736
+								'default' => DatetimeOffsetFix::getOffset()
737
+							)
738
+						),
739
+						'submit' => new EE_Submit_Input(
740
+							array(
741
+								'html_label_text' => '',
742
+								'default' => esc_html__('Apply Offset', 'event_espresso')
743
+							)
744
+						)
745
+					)
746
+				)
747
+			);
748
+		}
749
+		return $this->datetime_fix_offset_form;
750
+	}
751
+
752
+
753
+	/**
754
+	 * Callback for the run_datetime_offset_fix route.
755
+	 * @throws EE_Error
756
+	 */
757
+	protected function _apply_datetime_offset()
758
+	{
759
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
760
+			$form = $this->_get_datetime_offset_fix_form();
761
+			$form->receive_form_submission($this->_req_data);
762
+			if ($form->is_valid()) {
763
+				//save offset so batch processor can get it.
764
+				DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
765
+				//redirect to batch tool
766
+				wp_redirect(
767
+					EE_Admin_Page::add_query_args_and_nonce(
768
+						array(
769
+							'page' => 'espresso_batch',
770
+							'batch' => 'job',
771
+							'label' => esc_html__('Applying Offset', 'event_espresso'),
772
+							'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
773
+							'return_url' => urlencode(home_url(add_query_arg(null, null))),
774
+						),
775
+						admin_url()
776
+					)
777
+				);
778
+				exit;
779
+			}
780
+		}
781
+	}
782 782
 } //end Maintenance_Admin_Page class
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 2 patches
Spacing   +28 added lines, -28 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
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
     public function get_persistent_admin_notices()
658 658
     {
659 659
         // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
-        $args       = array(
660
+        $args = array(
661 661
             'page'   => EE_Registry::instance()->REQ->is_set('page')
662 662
                 ? EE_Registry::instance()->REQ->get('page')
663 663
                 : '',
@@ -704,21 +704,21 @@  discard block
 block discarded – undo
704 704
                 ),
705 705
             )
706 706
         );
707
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
707
+        $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
708 708
             array('page' => 'espresso_registrations'),
709 709
             admin_url('admin.php')
710 710
         );
711
-        $items['registrations']['text']  = sprintf(
711
+        $items['registrations']['text'] = sprintf(
712 712
             _n('%s Registration', '%s Registrations', $registrations),
713 713
             number_format_i18n($registrations)
714 714
         );
715 715
         $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716 716
 
717
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
717
+        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718 718
 
719 719
         foreach ($items as $type => $item_properties) {
720 720
             $elements[] = sprintf(
721
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
721
+                '<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>',
722 722
                 $item_properties['url'],
723 723
                 $item_properties['title'],
724 724
                 $item_properties['text']
@@ -744,10 +744,10 @@  discard block
 block discarded – undo
744 744
         // check for date_format or time_format
745 745
         switch ($option) {
746 746
             case 'date_format':
747
-                $date_time_format = $value . ' ' . get_option('time_format');
747
+                $date_time_format = $value.' '.get_option('time_format');
748 748
                 break;
749 749
             case 'time_format':
750
-                $date_time_format = get_option('date_format') . ' ' . $value;
750
+                $date_time_format = get_option('date_format').' '.$value;
751 751
                 break;
752 752
             default:
753 753
                 $date_time_format = false;
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
 
771 771
 
772 772
                 foreach ($error_msg as $error) {
773
-                    $msg .= '<li>' . $error . '</li>';
773
+                    $msg .= '<li>'.$error.'</li>';
774 774
                 }
775 775
 
776 776
                 $msg .= '</ul></p><p>'
Please login to merge, or discard this patch.
Indentation   +848 added lines, -848 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,485 +416,485 @@  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
-        //add non-dismissable notice for datetime changes.  Only valid if EE version is greater than 4.9.46.p and the
628
-        // site does not have a timezone_string set.
629
-        if (EE_Register_Addon::_meets_min_core_version_requirement(
630
-                '4.9.46.p'
631
-            )
632
-            && ! get_option('timezone_string')
633
-        ) {
634
-            EE_Error::add_attention(
635
-                sprintf(
636
-                    esc_html__(
637
-                        '%1$sImportant%2$s: Please note some upcoming changes to dates and times in Event Espresso that may affect your website.  Read more about it %3$shere%4$s.',
638
-                        'event_espresso'
639
-                    ),
640
-                    '<strong>',
641
-                    '</strong>',
642
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
643
-                    '</a>'
644
-                )
645
-            );
646
-        }
647
-        echo EE_Error::get_notices();
648
-    }
649
-
650
-
651
-    /**
652
-     *    get_persistent_admin_notices
653
-     *
654
-     * @access    public
655
-     * @return        void
656
-     */
657
-    public function get_persistent_admin_notices()
658
-    {
659
-        // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
-        $args       = array(
661
-            'page'   => EE_Registry::instance()->REQ->is_set('page')
662
-                ? EE_Registry::instance()->REQ->get('page')
663
-                : '',
664
-            'action' => EE_Registry::instance()->REQ->is_set('action')
665
-                ? EE_Registry::instance()->REQ->get('action')
666
-                : '',
667
-        );
668
-        $return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
669
-        echo EE_Error::get_persistent_admin_notices($return_url);
670
-    }
671
-
672
-
673
-    /**
674
-     *    dismiss_persistent_admin_notice
675
-     *
676
-     * @access    public
677
-     * @return        void
678
-     */
679
-    public function dismiss_ee_nag_notice_callback()
680
-    {
681
-        EE_Error::dismiss_persistent_admin_notice();
682
-    }
683
-
684
-
685
-    /**
686
-     * @param array $elements
687
-     * @return array
688
-     * @throws \EE_Error
689
-     */
690
-    public function dashboard_glance_items($elements)
691
-    {
692
-        $elements                        = is_array($elements) ? $elements : array($elements);
693
-        $events                          = EEM_Event::instance()->count();
694
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
695
-            array('page' => 'espresso_events'),
696
-            admin_url('admin.php')
697
-        );
698
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
699
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
700
-        $registrations                   = EEM_Registration::instance()->count(
701
-            array(
702
-                array(
703
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
704
-                ),
705
-            )
706
-        );
707
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
708
-            array('page' => 'espresso_registrations'),
709
-            admin_url('admin.php')
710
-        );
711
-        $items['registrations']['text']  = sprintf(
712
-            _n('%s Registration', '%s Registrations', $registrations),
713
-            number_format_i18n($registrations)
714
-        );
715
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716
-
717
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718
-
719
-        foreach ($items as $type => $item_properties) {
720
-            $elements[] = sprintf(
721
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
722
-                $item_properties['url'],
723
-                $item_properties['title'],
724
-                $item_properties['text']
725
-            );
726
-        }
727
-        return $elements;
728
-    }
729
-
730
-
731
-    /**
732
-     *    check_for_invalid_datetime_formats
733
-     *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
734
-     *    their selected format can be parsed by PHP
735
-     *
736
-     * @access    public
737
-     * @param    $value
738
-     * @param    $option
739
-     * @throws EE_Error
740
-     * @return    string
741
-     */
742
-    public function check_for_invalid_datetime_formats($value, $option)
743
-    {
744
-        // check for date_format or time_format
745
-        switch ($option) {
746
-            case 'date_format':
747
-                $date_time_format = $value . ' ' . get_option('time_format');
748
-                break;
749
-            case 'time_format':
750
-                $date_time_format = get_option('date_format') . ' ' . $value;
751
-                break;
752
-            default:
753
-                $date_time_format = false;
754
-        }
755
-        // do we have a date_time format to check ?
756
-        if ($date_time_format) {
757
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
758
-
759
-            if (is_array($error_msg)) {
760
-                $msg = '<p>'
761
-                       . sprintf(
762
-                           esc_html__(
763
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
764
-                               'event_espresso'
765
-                           ),
766
-                           date($date_time_format),
767
-                           $date_time_format
768
-                       )
769
-                       . '</p><p><ul>';
770
-
771
-
772
-                foreach ($error_msg as $error) {
773
-                    $msg .= '<li>' . $error . '</li>';
774
-                }
775
-
776
-                $msg .= '</ul></p><p>'
777
-                        . sprintf(
778
-                            esc_html__(
779
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
780
-                                'event_espresso'
781
-                            ),
782
-                            '<span style="color:#D54E21;">',
783
-                            '</span>'
784
-                        )
785
-                        . '</p>';
786
-
787
-                // trigger WP settings error
788
-                add_settings_error(
789
-                    'date_format',
790
-                    'date_format',
791
-                    $msg
792
-                );
793
-
794
-                // set format to something valid
795
-                switch ($option) {
796
-                    case 'date_format':
797
-                        $value = 'F j, Y';
798
-                        break;
799
-                    case 'time_format':
800
-                        $value = 'g:i a';
801
-                        break;
802
-                }
803
-            }
804
-        }
805
-        return $value;
806
-    }
807
-
808
-
809
-    /**
810
-     *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
811
-     *
812
-     * @access    public
813
-     * @param $content
814
-     * @return    string
815
-     */
816
-    public function its_eSpresso($content)
817
-    {
818
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
819
-    }
820
-
821
-
822
-    /**
823
-     *    espresso_admin_footer
824
-     *
825
-     * @access    public
826
-     * @return    string
827
-     */
828
-    public function espresso_admin_footer()
829
-    {
830
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
831
-    }
832
-
833
-
834
-    /**
835
-     * static method for registering ee admin page.
836
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
837
-     *
838
-     * @since      4.3.0
839
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
840
-     * @see        EE_Register_Admin_Page::register()
841
-     * @param       $page_basename
842
-     * @param       $page_path
843
-     * @param array $config
844
-     * @return void
845
-     * @throws EE_Error
846
-     */
847
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
848
-    {
849
-        EE_Error::doing_it_wrong(
850
-            __METHOD__,
851
-            sprintf(
852
-                esc_html__(
853
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
854
-                    'event_espresso'
855
-                ),
856
-                $page_basename
857
-            ),
858
-            '4.3'
859
-        );
860
-        if (class_exists('EE_Register_Admin_Page')) {
861
-            $config['page_path'] = $page_path;
862
-        }
863
-        EE_Register_Admin_Page::register($page_basename, $config);
864
-    }
865
-
866
-
867
-    /**
868
-     * @deprecated 4.8.41
869
-     * @access     public
870
-     * @param  int      $post_ID
871
-     * @param  \WP_Post $post
872
-     * @return void
873
-     */
874
-    public static function parse_post_content_on_save($post_ID, $post)
875
-    {
876
-        EE_Error::doing_it_wrong(
877
-            __METHOD__,
878
-            esc_html__('Usage is deprecated', 'event_espresso'),
879
-            '4.8.41'
880
-        );
881
-    }
882
-
883
-
884
-    /**
885
-     * @deprecated 4.8.41
886
-     * @access     public
887
-     * @param  $option
888
-     * @param  $old_value
889
-     * @param  $value
890
-     * @return void
891
-     */
892
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
893
-    {
894
-        EE_Error::doing_it_wrong(
895
-            __METHOD__,
896
-            esc_html__('Usage is deprecated', 'event_espresso'),
897
-            '4.8.41'
898
-        );
899
-    }
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
+		//add non-dismissable notice for datetime changes.  Only valid if EE version is greater than 4.9.46.p and the
628
+		// site does not have a timezone_string set.
629
+		if (EE_Register_Addon::_meets_min_core_version_requirement(
630
+				'4.9.46.p'
631
+			)
632
+			&& ! get_option('timezone_string')
633
+		) {
634
+			EE_Error::add_attention(
635
+				sprintf(
636
+					esc_html__(
637
+						'%1$sImportant%2$s: Please note some upcoming changes to dates and times in Event Espresso that may affect your website.  Read more about it %3$shere%4$s.',
638
+						'event_espresso'
639
+					),
640
+					'<strong>',
641
+					'</strong>',
642
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
643
+					'</a>'
644
+				)
645
+			);
646
+		}
647
+		echo EE_Error::get_notices();
648
+	}
649
+
650
+
651
+	/**
652
+	 *    get_persistent_admin_notices
653
+	 *
654
+	 * @access    public
655
+	 * @return        void
656
+	 */
657
+	public function get_persistent_admin_notices()
658
+	{
659
+		// http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
+		$args       = array(
661
+			'page'   => EE_Registry::instance()->REQ->is_set('page')
662
+				? EE_Registry::instance()->REQ->get('page')
663
+				: '',
664
+			'action' => EE_Registry::instance()->REQ->is_set('action')
665
+				? EE_Registry::instance()->REQ->get('action')
666
+				: '',
667
+		);
668
+		$return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
669
+		echo EE_Error::get_persistent_admin_notices($return_url);
670
+	}
671
+
672
+
673
+	/**
674
+	 *    dismiss_persistent_admin_notice
675
+	 *
676
+	 * @access    public
677
+	 * @return        void
678
+	 */
679
+	public function dismiss_ee_nag_notice_callback()
680
+	{
681
+		EE_Error::dismiss_persistent_admin_notice();
682
+	}
683
+
684
+
685
+	/**
686
+	 * @param array $elements
687
+	 * @return array
688
+	 * @throws \EE_Error
689
+	 */
690
+	public function dashboard_glance_items($elements)
691
+	{
692
+		$elements                        = is_array($elements) ? $elements : array($elements);
693
+		$events                          = EEM_Event::instance()->count();
694
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
695
+			array('page' => 'espresso_events'),
696
+			admin_url('admin.php')
697
+		);
698
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
699
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
700
+		$registrations                   = EEM_Registration::instance()->count(
701
+			array(
702
+				array(
703
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
704
+				),
705
+			)
706
+		);
707
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
708
+			array('page' => 'espresso_registrations'),
709
+			admin_url('admin.php')
710
+		);
711
+		$items['registrations']['text']  = sprintf(
712
+			_n('%s Registration', '%s Registrations', $registrations),
713
+			number_format_i18n($registrations)
714
+		);
715
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716
+
717
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718
+
719
+		foreach ($items as $type => $item_properties) {
720
+			$elements[] = sprintf(
721
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
722
+				$item_properties['url'],
723
+				$item_properties['title'],
724
+				$item_properties['text']
725
+			);
726
+		}
727
+		return $elements;
728
+	}
729
+
730
+
731
+	/**
732
+	 *    check_for_invalid_datetime_formats
733
+	 *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
734
+	 *    their selected format can be parsed by PHP
735
+	 *
736
+	 * @access    public
737
+	 * @param    $value
738
+	 * @param    $option
739
+	 * @throws EE_Error
740
+	 * @return    string
741
+	 */
742
+	public function check_for_invalid_datetime_formats($value, $option)
743
+	{
744
+		// check for date_format or time_format
745
+		switch ($option) {
746
+			case 'date_format':
747
+				$date_time_format = $value . ' ' . get_option('time_format');
748
+				break;
749
+			case 'time_format':
750
+				$date_time_format = get_option('date_format') . ' ' . $value;
751
+				break;
752
+			default:
753
+				$date_time_format = false;
754
+		}
755
+		// do we have a date_time format to check ?
756
+		if ($date_time_format) {
757
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
758
+
759
+			if (is_array($error_msg)) {
760
+				$msg = '<p>'
761
+					   . sprintf(
762
+						   esc_html__(
763
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
764
+							   'event_espresso'
765
+						   ),
766
+						   date($date_time_format),
767
+						   $date_time_format
768
+					   )
769
+					   . '</p><p><ul>';
770
+
771
+
772
+				foreach ($error_msg as $error) {
773
+					$msg .= '<li>' . $error . '</li>';
774
+				}
775
+
776
+				$msg .= '</ul></p><p>'
777
+						. sprintf(
778
+							esc_html__(
779
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
780
+								'event_espresso'
781
+							),
782
+							'<span style="color:#D54E21;">',
783
+							'</span>'
784
+						)
785
+						. '</p>';
786
+
787
+				// trigger WP settings error
788
+				add_settings_error(
789
+					'date_format',
790
+					'date_format',
791
+					$msg
792
+				);
793
+
794
+				// set format to something valid
795
+				switch ($option) {
796
+					case 'date_format':
797
+						$value = 'F j, Y';
798
+						break;
799
+					case 'time_format':
800
+						$value = 'g:i a';
801
+						break;
802
+				}
803
+			}
804
+		}
805
+		return $value;
806
+	}
807
+
808
+
809
+	/**
810
+	 *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
811
+	 *
812
+	 * @access    public
813
+	 * @param $content
814
+	 * @return    string
815
+	 */
816
+	public function its_eSpresso($content)
817
+	{
818
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
819
+	}
820
+
821
+
822
+	/**
823
+	 *    espresso_admin_footer
824
+	 *
825
+	 * @access    public
826
+	 * @return    string
827
+	 */
828
+	public function espresso_admin_footer()
829
+	{
830
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
831
+	}
832
+
833
+
834
+	/**
835
+	 * static method for registering ee admin page.
836
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
837
+	 *
838
+	 * @since      4.3.0
839
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
840
+	 * @see        EE_Register_Admin_Page::register()
841
+	 * @param       $page_basename
842
+	 * @param       $page_path
843
+	 * @param array $config
844
+	 * @return void
845
+	 * @throws EE_Error
846
+	 */
847
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
848
+	{
849
+		EE_Error::doing_it_wrong(
850
+			__METHOD__,
851
+			sprintf(
852
+				esc_html__(
853
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
854
+					'event_espresso'
855
+				),
856
+				$page_basename
857
+			),
858
+			'4.3'
859
+		);
860
+		if (class_exists('EE_Register_Admin_Page')) {
861
+			$config['page_path'] = $page_path;
862
+		}
863
+		EE_Register_Admin_Page::register($page_basename, $config);
864
+	}
865
+
866
+
867
+	/**
868
+	 * @deprecated 4.8.41
869
+	 * @access     public
870
+	 * @param  int      $post_ID
871
+	 * @param  \WP_Post $post
872
+	 * @return void
873
+	 */
874
+	public static function parse_post_content_on_save($post_ID, $post)
875
+	{
876
+		EE_Error::doing_it_wrong(
877
+			__METHOD__,
878
+			esc_html__('Usage is deprecated', 'event_espresso'),
879
+			'4.8.41'
880
+		);
881
+	}
882
+
883
+
884
+	/**
885
+	 * @deprecated 4.8.41
886
+	 * @access     public
887
+	 * @param  $option
888
+	 * @param  $old_value
889
+	 * @param  $value
890
+	 * @return void
891
+	 */
892
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
893
+	{
894
+		EE_Error::doing_it_wrong(
895
+			__METHOD__,
896
+			esc_html__('Usage is deprecated', 'event_espresso'),
897
+			'4.8.41'
898
+		);
899
+	}
900 900
 }
Please login to merge, or discard this patch.