Completed
Branch FET/11011/recurring-events-man... (00e770)
by
unknown
40:15 queued 25:22
created
core/db_models/EEM_Datetime.model.php 2 patches
Indentation   +652 added lines, -652 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -14,657 +14,657 @@  discard block
 block discarded – undo
14 14
 class EEM_Datetime extends EEM_Soft_Delete_Base
15 15
 {
16 16
 
17
-    /**
18
-     * @var EEM_Datetime $_instance
19
-     */
20
-    protected static $_instance;
21
-
22
-
23
-    /**
24
-     * private constructor to prevent direct creation
25
-     *
26
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
27
-     *                         (and any incoming timezone data that gets saved).
28
-     *                         Note this just sends the timezone info to the date time model field objects.
29
-     *                         Default is NULL
30
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
31
-     * @throws EE_Error
32
-     * @throws InvalidArgumentException
33
-     * @throws InvalidArgumentException
34
-     */
35
-    protected function __construct($timezone)
36
-    {
37
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
38
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
39
-        $this->_tables                 = array(
40
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
41
-        );
42
-        $this->_fields                 = array(
43
-            'Datetime' => array(
44
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
45
-                    'DTT_ID',
46
-                    esc_html__('Datetime ID', 'event_espresso')
47
-                ),
48
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
49
-                    'EVT_ID',
50
-                    esc_html__('Event ID', 'event_espresso'),
51
-                    false,
52
-                    0,
53
-                    'Event'
54
-                ),
55
-                'DTT_name'        => new EE_Plain_Text_Field(
56
-                    'DTT_name',
57
-                    esc_html__('Datetime Name', 'event_espresso'),
58
-                    false,
59
-                    ''
60
-                ),
61
-                'DTT_description' => new EE_Post_Content_Field(
62
-                    'DTT_description',
63
-                    esc_html__('Description for Datetime', 'event_espresso'),
64
-                    false,
65
-                    ''
66
-                ),
67
-                'DTT_EVT_start'   => new EE_Datetime_Field(
68
-                    'DTT_EVT_start',
69
-                    esc_html__('Start time/date of Event', 'event_espresso'),
70
-                    false,
71
-                    EE_Datetime_Field::now,
72
-                    $timezone
73
-                ),
74
-                'DTT_EVT_end'     => new EE_Datetime_Field(
75
-                    'DTT_EVT_end',
76
-                    esc_html__('End time/date of Event', 'event_espresso'),
77
-                    false,
78
-                    EE_Datetime_Field::now,
79
-                    $timezone
80
-                ),
81
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
82
-                    'DTT_reg_limit',
83
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
84
-                    true,
85
-                    EE_INF
86
-                ),
87
-                'DTT_sold'        => new EE_Integer_Field(
88
-                    'DTT_sold',
89
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
90
-                    true,
91
-                    0
92
-                ),
93
-                'DTT_reserved'    => new EE_Integer_Field(
94
-                    'DTT_reserved',
95
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
96
-                    false,
97
-                    0
98
-                ),
99
-                'DTT_is_primary'  => new EE_Boolean_Field(
100
-                    'DTT_is_primary',
101
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
102
-                    false,
103
-                    false
104
-                ),
105
-                'DTT_order'       => new EE_Integer_Field(
106
-                    'DTT_order',
107
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
108
-                    false,
109
-                    0
110
-                ),
111
-                'DTT_parent'      => new EE_Integer_Field(
112
-                    'DTT_parent',
113
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID'),
114
-                    true,
115
-                    0
116
-                ),
117
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
118
-                    'DTT_deleted',
119
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
120
-                    false,
121
-                    false
122
-                ),
123
-            ),
124
-        );
125
-        $this->_model_relations        = array(
126
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
127
-            'Event'   => new EE_Belongs_To_Relation(),
128
-            'Checkin' => new EE_Has_Many_Relation(),
129
-        );
130
-        $this->_model_chain_to_wp_user = 'Event';
131
-        //this model is generally available for reading
132
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
133
-            'Event'
134
-        );
135
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
136
-            'Event'
137
-        );
138
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
139
-            'Event'
140
-        );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
142
-            'Event',
143
-            EEM_Base::caps_edit
144
-        );
145
-        parent::__construct($timezone);
146
-    }
147
-
148
-
149
-    /**
150
-     * create new blank datetime
151
-     *
152
-     * @access public
153
-     * @return EE_Datetime[] array on success, FALSE on fail
154
-     * @throws EE_Error
155
-     */
156
-    public function create_new_blank_datetime()
157
-    {
158
-        //makes sure timezone is always set.
159
-        $timezone_string = $this->get_timezone();
160
-        $blank_datetime  = EE_Datetime::new_instance(
161
-            array(
162
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
163
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
164
-                'DTT_order'     => 1,
165
-                'DTT_reg_limit' => EE_INF,
166
-            ),
167
-            $timezone_string
168
-        );
169
-        $blank_datetime->set_start_time(
170
-            $this->convert_datetime_for_query(
171
-                'DTT_EVT_start',
172
-                '8am',
173
-                'ga',
174
-                $timezone_string
175
-            )
176
-        );
177
-        $blank_datetime->set_end_time(
178
-            $this->convert_datetime_for_query(
179
-                'DTT_EVT_end',
180
-                '5pm',
181
-                'ga',
182
-                $timezone_string
183
-            )
184
-        );
185
-        return array($blank_datetime);
186
-    }
187
-
188
-
189
-    /**
190
-     * get event start date from db
191
-     *
192
-     * @access public
193
-     * @param  int $EVT_ID
194
-     * @return EE_Datetime[] array on success, FALSE on fail
195
-     * @throws EE_Error
196
-     */
197
-    public function get_all_event_dates($EVT_ID = 0)
198
-    {
199
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
200
-            return $this->create_new_blank_datetime();
201
-        }
202
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
203
-        if (empty($results)) {
204
-            return $this->create_new_blank_datetime();
205
-        }
206
-        return $results;
207
-    }
208
-
209
-
210
-    /**
211
-     * get all datetimes attached to an event ordered by the DTT_order field
212
-     *
213
-     * @public
214
-     * @param  int    $EVT_ID     event id
215
-     * @param boolean $include_expired
216
-     * @param boolean $include_deleted
217
-     * @param  int    $limit      If included then limit the count of results by
218
-     *                            the given number
219
-     * @return EE_Datetime[]
220
-     * @throws EE_Error
221
-     */
222
-    public function get_datetimes_for_event_ordered_by_DTT_order(
223
-        $EVT_ID,
224
-        $include_expired = true,
225
-        $include_deleted = true,
226
-        $limit = null
227
-    ) {
228
-        //sanitize EVT_ID
229
-        $EVT_ID         = absint($EVT_ID);
230
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
231
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
232
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
233
-        $query_params = ! empty($limit)
234
-            ? array(
235
-                $where_params,
236
-                'limit'                    => $limit,
237
-                'order_by'                 => array('DTT_order' => 'ASC'),
238
-                'default_where_conditions' => 'none',
239
-            )
240
-            : array(
241
-                $where_params,
242
-                'order_by'                 => array('DTT_order' => 'ASC'),
243
-                'default_where_conditions' => 'none',
244
-            );
245
-        if (! $include_expired) {
246
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
247
-        }
248
-        if ($include_deleted) {
249
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
250
-        }
251
-        /** @var EE_Datetime[] $result */
252
-        $result = $this->get_all($query_params);
253
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
254
-        return $result;
255
-    }
256
-
257
-
258
-    /**
259
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
260
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
261
-     * and then the earlier datetimes are the most important.
262
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
263
-     *
264
-     * @param int $EVT_ID
265
-     * @param int $limit
266
-     * @return EE_Datetime[]|EE_Base_Class[]
267
-     * @throws EE_Error
268
-     */
269
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
270
-    {
271
-        return $this->get_all(
272
-            array(
273
-                array('Event.EVT_ID' => $EVT_ID),
274
-                'limit'                    => $limit,
275
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
276
-                'default_where_conditions' => 'none',
277
-            )
278
-        );
279
-    }
280
-
281
-
282
-    /**
283
-     * @param int     $EVT_ID
284
-     * @param boolean $include_expired
285
-     * @param boolean $include_deleted
286
-     * @return EE_Datetime
287
-     * @throws EE_Error
288
-     */
289
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
290
-    {
291
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
292
-            $EVT_ID,
293
-            $include_expired,
294
-            $include_deleted,
295
-            1
296
-        );
297
-        if ($results) {
298
-            return array_shift($results);
299
-        }
300
-        return null;
301
-    }
302
-
303
-
304
-    /**
305
-     * Gets the 'primary' datetime for an event.
306
-     *
307
-     * @param int  $EVT_ID
308
-     * @param bool $try_to_exclude_expired
309
-     * @param bool $try_to_exclude_deleted
310
-     * @return \EE_Datetime
311
-     * @throws EE_Error
312
-     */
313
-    public function get_primary_datetime_for_event(
314
-        $EVT_ID,
315
-        $try_to_exclude_expired = true,
316
-        $try_to_exclude_deleted = true
317
-    ) {
318
-        if ($try_to_exclude_expired) {
319
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
320
-            if ($non_expired) {
321
-                return $non_expired;
322
-            }
323
-        }
324
-        if ($try_to_exclude_deleted) {
325
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
326
-            if ($expired_even) {
327
-                return $expired_even;
328
-            }
329
-        }
330
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
331
-    }
332
-
333
-
334
-    /**
335
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
336
-     * only by start date
337
-     *
338
-     * @param int     $EVT_ID
339
-     * @param boolean $include_expired
340
-     * @param boolean $include_deleted
341
-     * @param int     $limit
342
-     * @return EE_Datetime[]
343
-     * @throws EE_Error
344
-     */
345
-    public function get_datetimes_for_event_ordered_by_start_time(
346
-        $EVT_ID,
347
-        $include_expired = true,
348
-        $include_deleted = true,
349
-        $limit = null
350
-    ) {
351
-        //sanitize EVT_ID
352
-        $EVT_ID         = absint($EVT_ID);
353
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
354
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
355
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
356
-        if (! $include_expired) {
357
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
358
-        }
359
-        if ($include_deleted) {
360
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
361
-        }
362
-        if ($limit) {
363
-            $query_params['limit'] = $limit;
364
-        }
365
-        /** @var EE_Datetime[] $result */
366
-        $result = $this->get_all($query_params);
367
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
368
-        return $result;
369
-    }
370
-
371
-
372
-    /**
373
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
374
-     * only by start date
375
-     *
376
-     * @param int     $TKT_ID
377
-     * @param boolean $include_expired
378
-     * @param boolean $include_deleted
379
-     * @param int     $limit
380
-     * @return EE_Datetime[]
381
-     * @throws EE_Error
382
-     */
383
-    public function get_datetimes_for_ticket_ordered_by_start_time(
384
-        $TKT_ID,
385
-        $include_expired = true,
386
-        $include_deleted = true,
387
-        $limit = null
388
-    ) {
389
-        //sanitize TKT_ID
390
-        $TKT_ID         = absint($TKT_ID);
391
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
392
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
393
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
394
-        if (! $include_expired) {
395
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
396
-        }
397
-        if ($include_deleted) {
398
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
399
-        }
400
-        if ($limit) {
401
-            $query_params['limit'] = $limit;
402
-        }
403
-        /** @var EE_Datetime[] $result */
404
-        $result = $this->get_all($query_params);
405
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
406
-        return $result;
407
-    }
408
-
409
-
410
-    /**
411
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
412
-     * datetimes.
413
-     *
414
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
415
-     * @param  boolean  $include_expired whether to include expired datetimes or not
416
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
417
-     * @param  int|null $limit           if null, no limit, if int then limit results by
418
-     *                                   that number
419
-     * @return EE_Datetime[]
420
-     * @throws EE_Error
421
-     */
422
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
423
-        $TKT_ID,
424
-        $include_expired = true,
425
-        $include_deleted = true,
426
-        $limit = null
427
-    ) {
428
-        //sanitize id.
429
-        $TKT_ID         = absint($TKT_ID);
430
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
431
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
432
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
433
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
434
-        if (! $include_expired) {
435
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
436
-        }
437
-        if ($include_deleted) {
438
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
439
-        }
440
-        if ($limit) {
441
-            $query_params['limit'] = $limit;
442
-        }
443
-        /** @var EE_Datetime[] $result */
444
-        $result = $this->get_all($query_params);
445
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
446
-        return $result;
447
-    }
448
-
449
-
450
-    /**
451
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
452
-     * reason it doesn't exist, we consider the earliest event the most important)
453
-     *
454
-     * @param int $EVT_ID
455
-     * @return EE_Datetime
456
-     * @throws EE_Error
457
-     */
458
-    public function get_most_important_datetime_for_event($EVT_ID)
459
-    {
460
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
461
-        if ($results) {
462
-            return array_shift($results);
463
-        }
464
-        return null;
465
-    }
466
-
467
-
468
-    /**
469
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
470
-     * grouped by month and year.
471
-     *
472
-     * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
473
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
474
-     *                                   Can be:
475
-     *                                   - '' = no filter
476
-     *                                   - upcoming = Published events with at least one upcoming datetime.
477
-     *                                   - expired = Events with all datetimes expired.
478
-     *                                   - active = Events that are published and have at least one datetime that
479
-     *                                   starts before now and ends after now.
480
-     *                                   - inactive = Events that are either not published.
481
-     * @return EE_Base_Class[]
482
-     * @throws EE_Error
483
-     * @throws InvalidArgumentException
484
-     * @throws InvalidArgumentException
485
-     */
486
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
487
-    {
488
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
489
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
490
-        switch ($evt_active_status) {
491
-            case 'upcoming' :
492
-                $where_params['Event.status'] = 'publish';
493
-                //if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
494
-                if (isset($where_params['DTT_EVT_start'])) {
495
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
496
-                }
497
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
498
-                break;
499
-            case 'expired' :
500
-                if (isset($where_params['Event.status'])) {
501
-                    unset($where_params['Event.status']);
502
-                }
503
-                //get events to exclude
504
-                $exclude_query[0] = array_merge($where_params,
505
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
506
-                //first get all events that have datetimes where its not expired.
507
-                $event_ids = $this->_get_all_wpdb_results(
508
-                    $exclude_query,
509
-                    OBJECT_K,
510
-                    'Datetime.EVT_ID'
511
-                );
512
-                $event_ids = array_keys($event_ids);
513
-                if (isset($where_params['DTT_EVT_end'])) {
514
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
-                }
516
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
-                break;
519
-            case 'active' :
520
-                $where_params['Event.status'] = 'publish';
521
-                if (isset($where_params['DTT_EVT_start'])) {
522
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
-                }
524
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
-                }
527
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
-                break;
530
-            case 'inactive' :
531
-                if (isset($where_params['Event.status'])) {
532
-                    unset($where_params['Event.status']);
533
-                }
534
-                if (isset($where_params['OR'])) {
535
-                    $where_params['AND']['OR'] = $where_params['OR'];
536
-                }
537
-                if (isset($where_params['DTT_EVT_end'])) {
538
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
-                    unset($where_params['DTT_EVT_end']);
540
-                }
541
-                if (isset($where_params['DTT_EVT_start'])) {
542
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
-                    unset($where_params['DTT_EVT_start']);
544
-                }
545
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
546
-                break;
547
-        }
548
-        $query_params[0]          = $where_params;
549
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
550
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(),
552
-            'DTT_EVT_start');
553
-        $columns_to_select        = array(
554
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
555
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
556
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
557
-        );
558
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
559
-    }
560
-
561
-
562
-    /**
563
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
564
-     * for the tickets for each datetime)
565
-     *
566
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
567
-     * @throws EE_Error
568
-     */
569
-    public function update_sold($datetimes)
570
-    {
571
-        EE_Error::doing_it_wrong(
572
-            __FUNCTION__,
573
-            esc_html__(
574
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
575
-                'event_espresso'
576
-            ),
577
-            '4.9.32.rc.005'
578
-        );
579
-        foreach ($datetimes as $datetime) {
580
-            $datetime->update_sold();
581
-        }
582
-    }
583
-
584
-
585
-    /**
586
-     *    Gets the total number of tickets available at a particular datetime
587
-     *    (does NOT take into account the datetime's spaces available)
588
-     *
589
-     * @param int   $DTT_ID
590
-     * @param array $query_params
591
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
592
-     *             tickets attached to datetime then FALSE is returned.
593
-     */
594
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
595
-    {
596
-        $datetime = $this->get_one_by_ID($DTT_ID);
597
-        if ($datetime instanceof EE_Datetime) {
598
-            return $datetime->tickets_remaining($query_params);
599
-        }
600
-        return 0;
601
-    }
602
-
603
-
604
-    /**
605
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
606
-     *
607
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
608
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
609
-     *                                 for all valid stati.
610
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
611
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
612
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
613
-     * @throws EE_Error
614
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
615
-     *                                 EE_Datetime::expired
616
-     */
617
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
618
-    {
619
-        //only accept where conditions for this query.
620
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
621
-        $status_query_args = array(
622
-            EE_Datetime::active   => array_merge(
623
-                $_where,
624
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
625
-            ),
626
-            EE_Datetime::upcoming => array_merge(
627
-                $_where,
628
-                array('DTT_EVT_start' => array('>', time()))
629
-            ),
630
-            EE_Datetime::expired  => array_merge(
631
-                $_where,
632
-                array('DTT_EVT_end' => array('<', time()))
633
-            ),
634
-        );
635
-        if (! empty($stati_to_include)) {
636
-            foreach (array_keys($status_query_args) as $status) {
637
-                if (! in_array($status, $stati_to_include, true)) {
638
-                    unset($status_query_args[ $status ]);
639
-                }
640
-            }
641
-        }
642
-        //loop through and query counts for each stati.
643
-        $status_query_results = array();
644
-        foreach ($status_query_args as $status => $status_where_conditions) {
645
-            $status_query_results[ $status ] = EEM_Datetime::count(
646
-                array($status_where_conditions),
647
-                'DTT_ID',
648
-                true
649
-            );
650
-        }
651
-        return $status_query_results;
652
-    }
653
-
654
-
655
-    /**
656
-     * Returns the specific count for a given Datetime status matching any given query_params.
657
-     *
658
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
659
-     * @param array  $query_params
660
-     * @return int
661
-     * @throws EE_Error
662
-     */
663
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
664
-    {
665
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
666
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
667
-    }
17
+	/**
18
+	 * @var EEM_Datetime $_instance
19
+	 */
20
+	protected static $_instance;
21
+
22
+
23
+	/**
24
+	 * private constructor to prevent direct creation
25
+	 *
26
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
27
+	 *                         (and any incoming timezone data that gets saved).
28
+	 *                         Note this just sends the timezone info to the date time model field objects.
29
+	 *                         Default is NULL
30
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
31
+	 * @throws EE_Error
32
+	 * @throws InvalidArgumentException
33
+	 * @throws InvalidArgumentException
34
+	 */
35
+	protected function __construct($timezone)
36
+	{
37
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
38
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
39
+		$this->_tables                 = array(
40
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
41
+		);
42
+		$this->_fields                 = array(
43
+			'Datetime' => array(
44
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
45
+					'DTT_ID',
46
+					esc_html__('Datetime ID', 'event_espresso')
47
+				),
48
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
49
+					'EVT_ID',
50
+					esc_html__('Event ID', 'event_espresso'),
51
+					false,
52
+					0,
53
+					'Event'
54
+				),
55
+				'DTT_name'        => new EE_Plain_Text_Field(
56
+					'DTT_name',
57
+					esc_html__('Datetime Name', 'event_espresso'),
58
+					false,
59
+					''
60
+				),
61
+				'DTT_description' => new EE_Post_Content_Field(
62
+					'DTT_description',
63
+					esc_html__('Description for Datetime', 'event_espresso'),
64
+					false,
65
+					''
66
+				),
67
+				'DTT_EVT_start'   => new EE_Datetime_Field(
68
+					'DTT_EVT_start',
69
+					esc_html__('Start time/date of Event', 'event_espresso'),
70
+					false,
71
+					EE_Datetime_Field::now,
72
+					$timezone
73
+				),
74
+				'DTT_EVT_end'     => new EE_Datetime_Field(
75
+					'DTT_EVT_end',
76
+					esc_html__('End time/date of Event', 'event_espresso'),
77
+					false,
78
+					EE_Datetime_Field::now,
79
+					$timezone
80
+				),
81
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
82
+					'DTT_reg_limit',
83
+					esc_html__('Registration Limit for this time', 'event_espresso'),
84
+					true,
85
+					EE_INF
86
+				),
87
+				'DTT_sold'        => new EE_Integer_Field(
88
+					'DTT_sold',
89
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
90
+					true,
91
+					0
92
+				),
93
+				'DTT_reserved'    => new EE_Integer_Field(
94
+					'DTT_reserved',
95
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
96
+					false,
97
+					0
98
+				),
99
+				'DTT_is_primary'  => new EE_Boolean_Field(
100
+					'DTT_is_primary',
101
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
102
+					false,
103
+					false
104
+				),
105
+				'DTT_order'       => new EE_Integer_Field(
106
+					'DTT_order',
107
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
108
+					false,
109
+					0
110
+				),
111
+				'DTT_parent'      => new EE_Integer_Field(
112
+					'DTT_parent',
113
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID'),
114
+					true,
115
+					0
116
+				),
117
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
118
+					'DTT_deleted',
119
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
120
+					false,
121
+					false
122
+				),
123
+			),
124
+		);
125
+		$this->_model_relations        = array(
126
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
127
+			'Event'   => new EE_Belongs_To_Relation(),
128
+			'Checkin' => new EE_Has_Many_Relation(),
129
+		);
130
+		$this->_model_chain_to_wp_user = 'Event';
131
+		//this model is generally available for reading
132
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
133
+			'Event'
134
+		);
135
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
136
+			'Event'
137
+		);
138
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
139
+			'Event'
140
+		);
141
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
142
+			'Event',
143
+			EEM_Base::caps_edit
144
+		);
145
+		parent::__construct($timezone);
146
+	}
147
+
148
+
149
+	/**
150
+	 * create new blank datetime
151
+	 *
152
+	 * @access public
153
+	 * @return EE_Datetime[] array on success, FALSE on fail
154
+	 * @throws EE_Error
155
+	 */
156
+	public function create_new_blank_datetime()
157
+	{
158
+		//makes sure timezone is always set.
159
+		$timezone_string = $this->get_timezone();
160
+		$blank_datetime  = EE_Datetime::new_instance(
161
+			array(
162
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
163
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
164
+				'DTT_order'     => 1,
165
+				'DTT_reg_limit' => EE_INF,
166
+			),
167
+			$timezone_string
168
+		);
169
+		$blank_datetime->set_start_time(
170
+			$this->convert_datetime_for_query(
171
+				'DTT_EVT_start',
172
+				'8am',
173
+				'ga',
174
+				$timezone_string
175
+			)
176
+		);
177
+		$blank_datetime->set_end_time(
178
+			$this->convert_datetime_for_query(
179
+				'DTT_EVT_end',
180
+				'5pm',
181
+				'ga',
182
+				$timezone_string
183
+			)
184
+		);
185
+		return array($blank_datetime);
186
+	}
187
+
188
+
189
+	/**
190
+	 * get event start date from db
191
+	 *
192
+	 * @access public
193
+	 * @param  int $EVT_ID
194
+	 * @return EE_Datetime[] array on success, FALSE on fail
195
+	 * @throws EE_Error
196
+	 */
197
+	public function get_all_event_dates($EVT_ID = 0)
198
+	{
199
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
200
+			return $this->create_new_blank_datetime();
201
+		}
202
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
203
+		if (empty($results)) {
204
+			return $this->create_new_blank_datetime();
205
+		}
206
+		return $results;
207
+	}
208
+
209
+
210
+	/**
211
+	 * get all datetimes attached to an event ordered by the DTT_order field
212
+	 *
213
+	 * @public
214
+	 * @param  int    $EVT_ID     event id
215
+	 * @param boolean $include_expired
216
+	 * @param boolean $include_deleted
217
+	 * @param  int    $limit      If included then limit the count of results by
218
+	 *                            the given number
219
+	 * @return EE_Datetime[]
220
+	 * @throws EE_Error
221
+	 */
222
+	public function get_datetimes_for_event_ordered_by_DTT_order(
223
+		$EVT_ID,
224
+		$include_expired = true,
225
+		$include_deleted = true,
226
+		$limit = null
227
+	) {
228
+		//sanitize EVT_ID
229
+		$EVT_ID         = absint($EVT_ID);
230
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
231
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
232
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
233
+		$query_params = ! empty($limit)
234
+			? array(
235
+				$where_params,
236
+				'limit'                    => $limit,
237
+				'order_by'                 => array('DTT_order' => 'ASC'),
238
+				'default_where_conditions' => 'none',
239
+			)
240
+			: array(
241
+				$where_params,
242
+				'order_by'                 => array('DTT_order' => 'ASC'),
243
+				'default_where_conditions' => 'none',
244
+			);
245
+		if (! $include_expired) {
246
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
247
+		}
248
+		if ($include_deleted) {
249
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
250
+		}
251
+		/** @var EE_Datetime[] $result */
252
+		$result = $this->get_all($query_params);
253
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
254
+		return $result;
255
+	}
256
+
257
+
258
+	/**
259
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
260
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
261
+	 * and then the earlier datetimes are the most important.
262
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
263
+	 *
264
+	 * @param int $EVT_ID
265
+	 * @param int $limit
266
+	 * @return EE_Datetime[]|EE_Base_Class[]
267
+	 * @throws EE_Error
268
+	 */
269
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
270
+	{
271
+		return $this->get_all(
272
+			array(
273
+				array('Event.EVT_ID' => $EVT_ID),
274
+				'limit'                    => $limit,
275
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
276
+				'default_where_conditions' => 'none',
277
+			)
278
+		);
279
+	}
280
+
281
+
282
+	/**
283
+	 * @param int     $EVT_ID
284
+	 * @param boolean $include_expired
285
+	 * @param boolean $include_deleted
286
+	 * @return EE_Datetime
287
+	 * @throws EE_Error
288
+	 */
289
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
290
+	{
291
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
292
+			$EVT_ID,
293
+			$include_expired,
294
+			$include_deleted,
295
+			1
296
+		);
297
+		if ($results) {
298
+			return array_shift($results);
299
+		}
300
+		return null;
301
+	}
302
+
303
+
304
+	/**
305
+	 * Gets the 'primary' datetime for an event.
306
+	 *
307
+	 * @param int  $EVT_ID
308
+	 * @param bool $try_to_exclude_expired
309
+	 * @param bool $try_to_exclude_deleted
310
+	 * @return \EE_Datetime
311
+	 * @throws EE_Error
312
+	 */
313
+	public function get_primary_datetime_for_event(
314
+		$EVT_ID,
315
+		$try_to_exclude_expired = true,
316
+		$try_to_exclude_deleted = true
317
+	) {
318
+		if ($try_to_exclude_expired) {
319
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
320
+			if ($non_expired) {
321
+				return $non_expired;
322
+			}
323
+		}
324
+		if ($try_to_exclude_deleted) {
325
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
326
+			if ($expired_even) {
327
+				return $expired_even;
328
+			}
329
+		}
330
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
331
+	}
332
+
333
+
334
+	/**
335
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
336
+	 * only by start date
337
+	 *
338
+	 * @param int     $EVT_ID
339
+	 * @param boolean $include_expired
340
+	 * @param boolean $include_deleted
341
+	 * @param int     $limit
342
+	 * @return EE_Datetime[]
343
+	 * @throws EE_Error
344
+	 */
345
+	public function get_datetimes_for_event_ordered_by_start_time(
346
+		$EVT_ID,
347
+		$include_expired = true,
348
+		$include_deleted = true,
349
+		$limit = null
350
+	) {
351
+		//sanitize EVT_ID
352
+		$EVT_ID         = absint($EVT_ID);
353
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
354
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
355
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
356
+		if (! $include_expired) {
357
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
358
+		}
359
+		if ($include_deleted) {
360
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
361
+		}
362
+		if ($limit) {
363
+			$query_params['limit'] = $limit;
364
+		}
365
+		/** @var EE_Datetime[] $result */
366
+		$result = $this->get_all($query_params);
367
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
368
+		return $result;
369
+	}
370
+
371
+
372
+	/**
373
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
374
+	 * only by start date
375
+	 *
376
+	 * @param int     $TKT_ID
377
+	 * @param boolean $include_expired
378
+	 * @param boolean $include_deleted
379
+	 * @param int     $limit
380
+	 * @return EE_Datetime[]
381
+	 * @throws EE_Error
382
+	 */
383
+	public function get_datetimes_for_ticket_ordered_by_start_time(
384
+		$TKT_ID,
385
+		$include_expired = true,
386
+		$include_deleted = true,
387
+		$limit = null
388
+	) {
389
+		//sanitize TKT_ID
390
+		$TKT_ID         = absint($TKT_ID);
391
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
392
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
393
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
394
+		if (! $include_expired) {
395
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
396
+		}
397
+		if ($include_deleted) {
398
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
399
+		}
400
+		if ($limit) {
401
+			$query_params['limit'] = $limit;
402
+		}
403
+		/** @var EE_Datetime[] $result */
404
+		$result = $this->get_all($query_params);
405
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
406
+		return $result;
407
+	}
408
+
409
+
410
+	/**
411
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
412
+	 * datetimes.
413
+	 *
414
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
415
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
416
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
417
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
418
+	 *                                   that number
419
+	 * @return EE_Datetime[]
420
+	 * @throws EE_Error
421
+	 */
422
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
423
+		$TKT_ID,
424
+		$include_expired = true,
425
+		$include_deleted = true,
426
+		$limit = null
427
+	) {
428
+		//sanitize id.
429
+		$TKT_ID         = absint($TKT_ID);
430
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
431
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
432
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
433
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
434
+		if (! $include_expired) {
435
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
436
+		}
437
+		if ($include_deleted) {
438
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
439
+		}
440
+		if ($limit) {
441
+			$query_params['limit'] = $limit;
442
+		}
443
+		/** @var EE_Datetime[] $result */
444
+		$result = $this->get_all($query_params);
445
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
446
+		return $result;
447
+	}
448
+
449
+
450
+	/**
451
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
452
+	 * reason it doesn't exist, we consider the earliest event the most important)
453
+	 *
454
+	 * @param int $EVT_ID
455
+	 * @return EE_Datetime
456
+	 * @throws EE_Error
457
+	 */
458
+	public function get_most_important_datetime_for_event($EVT_ID)
459
+	{
460
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
461
+		if ($results) {
462
+			return array_shift($results);
463
+		}
464
+		return null;
465
+	}
466
+
467
+
468
+	/**
469
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
470
+	 * grouped by month and year.
471
+	 *
472
+	 * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
473
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
474
+	 *                                   Can be:
475
+	 *                                   - '' = no filter
476
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
477
+	 *                                   - expired = Events with all datetimes expired.
478
+	 *                                   - active = Events that are published and have at least one datetime that
479
+	 *                                   starts before now and ends after now.
480
+	 *                                   - inactive = Events that are either not published.
481
+	 * @return EE_Base_Class[]
482
+	 * @throws EE_Error
483
+	 * @throws InvalidArgumentException
484
+	 * @throws InvalidArgumentException
485
+	 */
486
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
487
+	{
488
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
489
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
490
+		switch ($evt_active_status) {
491
+			case 'upcoming' :
492
+				$where_params['Event.status'] = 'publish';
493
+				//if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
494
+				if (isset($where_params['DTT_EVT_start'])) {
495
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
496
+				}
497
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
498
+				break;
499
+			case 'expired' :
500
+				if (isset($where_params['Event.status'])) {
501
+					unset($where_params['Event.status']);
502
+				}
503
+				//get events to exclude
504
+				$exclude_query[0] = array_merge($where_params,
505
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
506
+				//first get all events that have datetimes where its not expired.
507
+				$event_ids = $this->_get_all_wpdb_results(
508
+					$exclude_query,
509
+					OBJECT_K,
510
+					'Datetime.EVT_ID'
511
+				);
512
+				$event_ids = array_keys($event_ids);
513
+				if (isset($where_params['DTT_EVT_end'])) {
514
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
+				}
516
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
+				break;
519
+			case 'active' :
520
+				$where_params['Event.status'] = 'publish';
521
+				if (isset($where_params['DTT_EVT_start'])) {
522
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
+				}
524
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
+				}
527
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
+				break;
530
+			case 'inactive' :
531
+				if (isset($where_params['Event.status'])) {
532
+					unset($where_params['Event.status']);
533
+				}
534
+				if (isset($where_params['OR'])) {
535
+					$where_params['AND']['OR'] = $where_params['OR'];
536
+				}
537
+				if (isset($where_params['DTT_EVT_end'])) {
538
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
+					unset($where_params['DTT_EVT_end']);
540
+				}
541
+				if (isset($where_params['DTT_EVT_start'])) {
542
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
+					unset($where_params['DTT_EVT_start']);
544
+				}
545
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
546
+				break;
547
+		}
548
+		$query_params[0]          = $where_params;
549
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
550
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(),
552
+			'DTT_EVT_start');
553
+		$columns_to_select        = array(
554
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
555
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
556
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
557
+		);
558
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
559
+	}
560
+
561
+
562
+	/**
563
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
564
+	 * for the tickets for each datetime)
565
+	 *
566
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
567
+	 * @throws EE_Error
568
+	 */
569
+	public function update_sold($datetimes)
570
+	{
571
+		EE_Error::doing_it_wrong(
572
+			__FUNCTION__,
573
+			esc_html__(
574
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
575
+				'event_espresso'
576
+			),
577
+			'4.9.32.rc.005'
578
+		);
579
+		foreach ($datetimes as $datetime) {
580
+			$datetime->update_sold();
581
+		}
582
+	}
583
+
584
+
585
+	/**
586
+	 *    Gets the total number of tickets available at a particular datetime
587
+	 *    (does NOT take into account the datetime's spaces available)
588
+	 *
589
+	 * @param int   $DTT_ID
590
+	 * @param array $query_params
591
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
592
+	 *             tickets attached to datetime then FALSE is returned.
593
+	 */
594
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
595
+	{
596
+		$datetime = $this->get_one_by_ID($DTT_ID);
597
+		if ($datetime instanceof EE_Datetime) {
598
+			return $datetime->tickets_remaining($query_params);
599
+		}
600
+		return 0;
601
+	}
602
+
603
+
604
+	/**
605
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
606
+	 *
607
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
608
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
609
+	 *                                 for all valid stati.
610
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
611
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
612
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
613
+	 * @throws EE_Error
614
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
615
+	 *                                 EE_Datetime::expired
616
+	 */
617
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
618
+	{
619
+		//only accept where conditions for this query.
620
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
621
+		$status_query_args = array(
622
+			EE_Datetime::active   => array_merge(
623
+				$_where,
624
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
625
+			),
626
+			EE_Datetime::upcoming => array_merge(
627
+				$_where,
628
+				array('DTT_EVT_start' => array('>', time()))
629
+			),
630
+			EE_Datetime::expired  => array_merge(
631
+				$_where,
632
+				array('DTT_EVT_end' => array('<', time()))
633
+			),
634
+		);
635
+		if (! empty($stati_to_include)) {
636
+			foreach (array_keys($status_query_args) as $status) {
637
+				if (! in_array($status, $stati_to_include, true)) {
638
+					unset($status_query_args[ $status ]);
639
+				}
640
+			}
641
+		}
642
+		//loop through and query counts for each stati.
643
+		$status_query_results = array();
644
+		foreach ($status_query_args as $status => $status_where_conditions) {
645
+			$status_query_results[ $status ] = EEM_Datetime::count(
646
+				array($status_where_conditions),
647
+				'DTT_ID',
648
+				true
649
+			);
650
+		}
651
+		return $status_query_results;
652
+	}
653
+
654
+
655
+	/**
656
+	 * Returns the specific count for a given Datetime status matching any given query_params.
657
+	 *
658
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
659
+	 * @param array  $query_params
660
+	 * @return int
661
+	 * @throws EE_Error
662
+	 */
663
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
664
+	{
665
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
666
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
667
+	}
668 668
 }
669 669
 // End of file EEM_Datetime.model.php
670 670
 // Location: /includes/models/EEM_Datetime.model.php
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -122,23 +122,23 @@  discard block
 block discarded – undo
122 122
                 ),
123 123
             ),
124 124
         );
125
-        $this->_model_relations        = array(
125
+        $this->_model_relations = array(
126 126
             'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
127 127
             'Event'   => new EE_Belongs_To_Relation(),
128 128
             'Checkin' => new EE_Has_Many_Relation(),
129 129
         );
130 130
         $this->_model_chain_to_wp_user = 'Event';
131 131
         //this model is generally available for reading
132
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
132
+        $this->_cap_restriction_generators[EEM_Base::caps_read]       = new EE_Restriction_Generator_Event_Related_Public(
133 133
             'Event'
134 134
         );
135
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
135
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected(
136 136
             'Event'
137 137
         );
138
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
138
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]       = new EE_Restriction_Generator_Event_Related_Protected(
139 139
             'Event'
140 140
         );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
141
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]     = new EE_Restriction_Generator_Event_Related_Protected(
142 142
             'Event',
143 143
             EEM_Base::caps_edit
144 144
         );
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
      */
197 197
     public function get_all_event_dates($EVT_ID = 0)
198 198
     {
199
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
199
+        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
200 200
             return $this->create_new_blank_datetime();
201 201
         }
202 202
         $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
                 'order_by'                 => array('DTT_order' => 'ASC'),
243 243
                 'default_where_conditions' => 'none',
244 244
             );
245
-        if (! $include_expired) {
245
+        if ( ! $include_expired) {
246 246
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
247 247
         }
248 248
         if ($include_deleted) {
@@ -353,7 +353,7 @@  discard block
 block discarded – undo
353 353
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
354 354
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
355 355
         $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
356
-        if (! $include_expired) {
356
+        if ( ! $include_expired) {
357 357
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
358 358
         }
359 359
         if ($include_deleted) {
@@ -391,7 +391,7 @@  discard block
 block discarded – undo
391 391
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
392 392
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
393 393
         $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
394
-        if (! $include_expired) {
394
+        if ( ! $include_expired) {
395 395
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
396 396
         }
397 397
         if ($include_deleted) {
@@ -431,7 +431,7 @@  discard block
 block discarded – undo
431 431
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
432 432
         $where_params = array('Ticket.TKT_ID' => $TKT_ID);
433 433
         $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
434
-        if (! $include_expired) {
434
+        if ( ! $include_expired) {
435 435
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
436 436
         }
437 437
         if ($include_deleted) {
@@ -551,9 +551,9 @@  discard block
 block discarded – undo
551 551
         $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(),
552 552
             'DTT_EVT_start');
553 553
         $columns_to_select        = array(
554
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
555
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
556
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
554
+            'dtt_year'      => array('YEAR('.$query_interval.')', '%s'),
555
+            'dtt_month'     => array('MONTHNAME('.$query_interval.')', '%s'),
556
+            'dtt_month_num' => array('MONTH('.$query_interval.')', '%s'),
557 557
         );
558 558
         return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
559 559
     }
@@ -632,17 +632,17 @@  discard block
 block discarded – undo
632 632
                 array('DTT_EVT_end' => array('<', time()))
633 633
             ),
634 634
         );
635
-        if (! empty($stati_to_include)) {
635
+        if ( ! empty($stati_to_include)) {
636 636
             foreach (array_keys($status_query_args) as $status) {
637
-                if (! in_array($status, $stati_to_include, true)) {
638
-                    unset($status_query_args[ $status ]);
637
+                if ( ! in_array($status, $stati_to_include, true)) {
638
+                    unset($status_query_args[$status]);
639 639
                 }
640 640
             }
641 641
         }
642 642
         //loop through and query counts for each stati.
643 643
         $status_query_results = array();
644 644
         foreach ($status_query_args as $status => $status_where_conditions) {
645
-            $status_query_results[ $status ] = EEM_Datetime::count(
645
+            $status_query_results[$status] = EEM_Datetime::count(
646 646
                 array($status_where_conditions),
647 647
                 'DTT_ID',
648 648
                 true
@@ -663,7 +663,7 @@  discard block
 block discarded – undo
663 663
     public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
664 664
     {
665 665
         $count = $this->get_datetime_counts_by_status(array($status), $query_params);
666
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
666
+        return ! empty($count[$status]) ? $count[$status] : 0;
667 667
     }
668 668
 }
669 669
 // End of file EEM_Datetime.model.php
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since       4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 
64 64
 } else {
65
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
-        /**
68
-         * espresso_minimum_php_version_error
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
65
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
+		/**
68
+		 * espresso_minimum_php_version_error
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.58.rc.016');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.58.rc.016');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1587 added lines, -1587 removed lines patch added patch discarded remove patch
@@ -23,1593 +23,1593 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var array $_class_abbreviations
38
-     */
39
-    protected $_class_abbreviations = array();
40
-
41
-    /**
42
-     * @var CommandBusInterface $BUS
43
-     */
44
-    public $BUS;
45
-
46
-    /**
47
-     * @var EE_Cart $CART
48
-     */
49
-    public $CART;
50
-
51
-    /**
52
-     * @var EE_Config $CFG
53
-     */
54
-    public $CFG;
55
-
56
-    /**
57
-     * @var EE_Network_Config $NET_CFG
58
-     */
59
-    public $NET_CFG;
60
-
61
-    /**
62
-     * StdClass object for storing library classes in
63
-     *
64
-     * @var StdClass $LIB
65
-     */
66
-    public $LIB;
67
-
68
-    /**
69
-     * @var EE_Request_Handler $REQ
70
-     */
71
-    public $REQ;
72
-
73
-    /**
74
-     * @var EE_Session $SSN
75
-     */
76
-    public $SSN;
77
-
78
-    /**
79
-     * @since 4.5.0
80
-     * @var EE_Capabilities $CAP
81
-     */
82
-    public $CAP;
83
-
84
-    /**
85
-     * @since 4.9.0
86
-     * @var EE_Message_Resource_Manager $MRM
87
-     */
88
-    public $MRM;
89
-
90
-
91
-    /**
92
-     * @var Registry $AssetsRegistry
93
-     */
94
-    public $AssetsRegistry;
95
-
96
-    /**
97
-     * StdClass object for holding addons which have registered themselves to work with EE core
98
-     *
99
-     * @var EE_Addon[] $addons
100
-     */
101
-    public $addons;
102
-
103
-    /**
104
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
-     *
106
-     * @var EEM_Base[] $models
107
-     */
108
-    public $models = array();
109
-
110
-    /**
111
-     * @var EED_Module[] $modules
112
-     */
113
-    public $modules;
114
-
115
-    /**
116
-     * @var EES_Shortcode[] $shortcodes
117
-     */
118
-    public $shortcodes;
119
-
120
-    /**
121
-     * @var WP_Widget[] $widgets
122
-     */
123
-    public $widgets;
124
-
125
-    /**
126
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
-     * classnames (eg "EEM_Event")
130
-     *
131
-     * @var array $non_abstract_db_models
132
-     */
133
-    public $non_abstract_db_models = array();
134
-
135
-
136
-    /**
137
-     * internationalization for JS strings
138
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
-     *    in js file:  var translatedString = eei18n.string_key;
140
-     *
141
-     * @var array $i18n_js_strings
142
-     */
143
-    public static $i18n_js_strings = array();
144
-
145
-
146
-    /**
147
-     * $main_file - path to espresso.php
148
-     *
149
-     * @var array $main_file
150
-     */
151
-    public $main_file;
152
-
153
-    /**
154
-     * array of ReflectionClass objects where the key is the class name
155
-     *
156
-     * @var ReflectionClass[] $_reflectors
157
-     */
158
-    public $_reflectors;
159
-
160
-    /**
161
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
-     *
163
-     * @var boolean $_cache_on
164
-     */
165
-    protected $_cache_on = true;
166
-
167
-
168
-
169
-    /**
170
-     * @singleton method used to instantiate class object
171
-     * @param  EE_Dependency_Map $dependency_map
172
-     * @return EE_Registry instance
173
-     * @throws InvalidArgumentException
174
-     * @throws InvalidInterfaceException
175
-     * @throws InvalidDataTypeException
176
-     */
177
-    public static function instance(EE_Dependency_Map $dependency_map = null)
178
-    {
179
-        // check if class object is instantiated
180
-        if (! self::$_instance instanceof EE_Registry) {
181
-            self::$_instance = new self($dependency_map);
182
-        }
183
-        return self::$_instance;
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * protected constructor to prevent direct creation
190
-     *
191
-     * @Constructor
192
-     * @param  EE_Dependency_Map $dependency_map
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     * @throws InvalidArgumentException
196
-     */
197
-    protected function __construct(EE_Dependency_Map $dependency_map)
198
-    {
199
-        $this->_dependency_map = $dependency_map;
200
-        // $registry_container = new RegistryContainer();
201
-        $this->LIB = new RegistryContainer();
202
-        $this->addons = new RegistryContainer();
203
-        $this->modules = new RegistryContainer();
204
-        $this->shortcodes = new RegistryContainer();
205
-        $this->widgets = new RegistryContainer();
206
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
-    }
208
-
209
-
210
-
211
-    /**
212
-     * initialize
213
-     *
214
-     * @throws EE_Error
215
-     * @throws ReflectionException
216
-     */
217
-    public function initialize()
218
-    {
219
-        $this->_class_abbreviations = apply_filters(
220
-            'FHEE__EE_Registry____construct___class_abbreviations',
221
-            array(
222
-                'EE_Config'                                       => 'CFG',
223
-                'EE_Session'                                      => 'SSN',
224
-                'EE_Capabilities'                                 => 'CAP',
225
-                'EE_Cart'                                         => 'CART',
226
-                'EE_Network_Config'                               => 'NET_CFG',
227
-                'EE_Request_Handler'                              => 'REQ',
228
-                'EE_Message_Resource_Manager'                     => 'MRM',
229
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
-            )
232
-        );
233
-        $this->load_core('Base', array(), true);
234
-        // add our request and response objects to the cache
235
-        $request_loader = $this->_dependency_map->class_loader(
236
-            'EventEspresso\core\services\request\Request'
237
-        );
238
-        $this->_set_cached_class(
239
-            $request_loader(),
240
-            'EventEspresso\core\services\request\Request'
241
-        );
242
-        $response_loader = $this->_dependency_map->class_loader(
243
-            'EventEspresso\core\services\request\Response'
244
-        );
245
-        $this->_set_cached_class(
246
-            $response_loader(),
247
-            'EventEspresso\core\services\request\Response'
248
-        );
249
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * @return void
256
-     */
257
-    public function init()
258
-    {
259
-        // Get current page protocol
260
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
-        // Output admin-ajax.php URL with same protocol as current page
262
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * localize_i18n_js_strings
270
-     *
271
-     * @return string
272
-     */
273
-    public static function localize_i18n_js_strings()
274
-    {
275
-        $i18n_js_strings = (array)self::$i18n_js_strings;
276
-        foreach ($i18n_js_strings as $key => $value) {
277
-            if (is_scalar($value)) {
278
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
-            }
280
-        }
281
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param mixed string | EED_Module $module
288
-     * @throws EE_Error
289
-     * @throws ReflectionException
290
-     */
291
-    public function add_module($module)
292
-    {
293
-        if ($module instanceof EED_Module) {
294
-            $module_class = get_class($module);
295
-            $this->modules->{$module_class} = $module;
296
-        } else {
297
-            if ( ! class_exists('EE_Module_Request_Router', false)) {
298
-                $this->load_core('Module_Request_Router');
299
-            }
300
-            EE_Module_Request_Router::module_factory($module);
301
-        }
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @param string $module_name
308
-     * @return mixed EED_Module | NULL
309
-     */
310
-    public function get_module($module_name = '')
311
-    {
312
-        return isset($this->modules->{$module_name})
313
-            ? $this->modules->{$module_name}
314
-            : null;
315
-    }
316
-
317
-
318
-
319
-    /**
320
-     * loads core classes - must be singletons
321
-     *
322
-     * @param string $class_name - simple class name ie: session
323
-     * @param mixed  $arguments
324
-     * @param bool   $load_only
325
-     * @return mixed
326
-     * @throws EE_Error
327
-     * @throws ReflectionException
328
-     */
329
-    public function load_core($class_name, $arguments = array(), $load_only = false)
330
-    {
331
-        $core_paths = apply_filters(
332
-            'FHEE__EE_Registry__load_core__core_paths',
333
-            array(
334
-                EE_CORE,
335
-                EE_ADMIN,
336
-                EE_CPTS,
337
-                EE_CORE . 'data_migration_scripts' . DS,
338
-                EE_CORE . 'capabilities' . DS,
339
-                EE_CORE . 'request_stack' . DS,
340
-                EE_CORE . 'middleware' . DS,
341
-            )
342
-        );
343
-        // retrieve instantiated class
344
-        return $this->_load(
345
-            $core_paths,
346
-            'EE_',
347
-            $class_name,
348
-            'core',
349
-            $arguments,
350
-            false,
351
-            true,
352
-            $load_only
353
-        );
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * loads service classes
360
-     *
361
-     * @param string $class_name - simple class name ie: session
362
-     * @param mixed  $arguments
363
-     * @param bool   $load_only
364
-     * @return mixed
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    public function load_service($class_name, $arguments = array(), $load_only = false)
369
-    {
370
-        $service_paths = apply_filters(
371
-            'FHEE__EE_Registry__load_service__service_paths',
372
-            array(
373
-                EE_CORE . 'services' . DS,
374
-            )
375
-        );
376
-        // retrieve instantiated class
377
-        return $this->_load(
378
-            $service_paths,
379
-            'EE_',
380
-            $class_name,
381
-            'class',
382
-            $arguments,
383
-            false,
384
-            true,
385
-            $load_only
386
-        );
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * loads data_migration_scripts
393
-     *
394
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
-     * @param mixed  $arguments
396
-     * @return EE_Data_Migration_Script_Base|mixed
397
-     * @throws EE_Error
398
-     * @throws ReflectionException
399
-     */
400
-    public function load_dms($class_name, $arguments = array())
401
-    {
402
-        // retrieve instantiated class
403
-        return $this->_load(
404
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
-            'EE_DMS_',
406
-            $class_name,
407
-            'dms',
408
-            $arguments,
409
-            false,
410
-            false
411
-        );
412
-    }
413
-
414
-
415
-
416
-    /**
417
-     * loads object creating classes - must be singletons
418
-     *
419
-     * @param string $class_name - simple class name ie: attendee
420
-     * @param mixed  $arguments  - an array of arguments to pass to the class
421
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
-     *                           instantiate
423
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
-     *                           (default)
427
-     * @return EE_Base_Class | bool
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     */
431
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
-    {
433
-        $paths = apply_filters(
434
-            'FHEE__EE_Registry__load_class__paths', array(
435
-            EE_CORE,
436
-            EE_CLASSES,
437
-            EE_BUSINESS,
438
-        )
439
-        );
440
-        // retrieve instantiated class
441
-        return $this->_load(
442
-            $paths,
443
-            'EE_',
444
-            $class_name,
445
-            'class',
446
-            $arguments,
447
-            $from_db,
448
-            $cache,
449
-            $load_only
450
-        );
451
-    }
452
-
453
-
454
-
455
-    /**
456
-     * loads helper classes - must be singletons
457
-     *
458
-     * @param string $class_name - simple class name ie: price
459
-     * @param mixed  $arguments
460
-     * @param bool   $load_only
461
-     * @return EEH_Base | bool
462
-     * @throws EE_Error
463
-     * @throws ReflectionException
464
-     */
465
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
466
-    {
467
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
-        // retrieve instantiated class
470
-        return $this->_load(
471
-            $helper_paths,
472
-            'EEH_',
473
-            $class_name,
474
-            'helper',
475
-            $arguments,
476
-            false,
477
-            true,
478
-            $load_only
479
-        );
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * loads core classes - must be singletons
486
-     *
487
-     * @param string $class_name - simple class name ie: session
488
-     * @param mixed  $arguments
489
-     * @param bool   $load_only
490
-     * @param bool   $cache      whether to cache the object or not.
491
-     * @return mixed
492
-     * @throws EE_Error
493
-     * @throws ReflectionException
494
-     */
495
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
-    {
497
-        $paths = array(
498
-            EE_LIBRARIES,
499
-            EE_LIBRARIES . 'messages' . DS,
500
-            EE_LIBRARIES . 'shortcodes' . DS,
501
-            EE_LIBRARIES . 'qtips' . DS,
502
-            EE_LIBRARIES . 'payment_methods' . DS,
503
-        );
504
-        // retrieve instantiated class
505
-        return $this->_load(
506
-            $paths,
507
-            'EE_',
508
-            $class_name,
509
-            'lib',
510
-            $arguments,
511
-            false,
512
-            $cache,
513
-            $load_only
514
-        );
515
-    }
516
-
517
-
518
-
519
-    /**
520
-     * loads model classes - must be singletons
521
-     *
522
-     * @param string $class_name - simple class name ie: price
523
-     * @param mixed  $arguments
524
-     * @param bool   $load_only
525
-     * @return EEM_Base | bool
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     */
529
-    public function load_model($class_name, $arguments = array(), $load_only = false)
530
-    {
531
-        $paths = apply_filters(
532
-            'FHEE__EE_Registry__load_model__paths', array(
533
-            EE_MODELS,
534
-            EE_CORE,
535
-        )
536
-        );
537
-        // retrieve instantiated class
538
-        return $this->_load(
539
-            $paths,
540
-            'EEM_',
541
-            $class_name,
542
-            'model',
543
-            $arguments,
544
-            false,
545
-            true,
546
-            $load_only
547
-        );
548
-    }
549
-
550
-
551
-
552
-    /**
553
-     * loads model classes - must be singletons
554
-     *
555
-     * @param string $class_name - simple class name ie: price
556
-     * @param mixed  $arguments
557
-     * @param bool   $load_only
558
-     * @return mixed | bool
559
-     * @throws EE_Error
560
-     * @throws ReflectionException
561
-     */
562
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
-    {
564
-        $paths = array(
565
-            EE_MODELS . 'fields' . DS,
566
-            EE_MODELS . 'helpers' . DS,
567
-            EE_MODELS . 'relations' . DS,
568
-            EE_MODELS . 'strategies' . DS,
569
-        );
570
-        // retrieve instantiated class
571
-        return $this->_load(
572
-            $paths,
573
-            'EE_',
574
-            $class_name,
575
-            '',
576
-            $arguments,
577
-            false,
578
-            true,
579
-            $load_only
580
-        );
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * Determines if $model_name is the name of an actual EE model.
587
-     *
588
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
-     * @return boolean
590
-     */
591
-    public function is_model_name($model_name)
592
-    {
593
-        return isset($this->models[$model_name]);
594
-    }
595
-
596
-
597
-
598
-    /**
599
-     * generic class loader
600
-     *
601
-     * @param string $path_to_file - directory path to file location, not including filename
602
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
603
-     * @param string $type         - file type - core? class? helper? model?
604
-     * @param mixed  $arguments
605
-     * @param bool   $load_only
606
-     * @return mixed
607
-     * @throws EE_Error
608
-     * @throws ReflectionException
609
-     */
610
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
-    {
612
-        // retrieve instantiated class
613
-        return $this->_load(
614
-            $path_to_file,
615
-            '',
616
-            $file_name,
617
-            $type,
618
-            $arguments,
619
-            false,
620
-            true,
621
-            $load_only
622
-        );
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @param string $path_to_file - directory path to file location, not including filename
629
-     * @param string $class_name   - full class name  ie:  My_Class
630
-     * @param string $type         - file type - core? class? helper? model?
631
-     * @param mixed  $arguments
632
-     * @param bool   $load_only
633
-     * @return bool|EE_Addon|object
634
-     * @throws EE_Error
635
-     * @throws ReflectionException
636
-     */
637
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
-    {
639
-        // retrieve instantiated class
640
-        return $this->_load(
641
-            $path_to_file,
642
-            'addon',
643
-            $class_name,
644
-            $type,
645
-            $arguments,
646
-            false,
647
-            true,
648
-            $load_only
649
-        );
650
-    }
651
-
652
-
653
-
654
-    /**
655
-     * instantiates, caches, and automatically resolves dependencies
656
-     * for classes that use a Fully Qualified Class Name.
657
-     * if the class is not capable of being loaded using PSR-4 autoloading,
658
-     * then you need to use one of the existing load_*() methods
659
-     * which can resolve the classname and filepath from the passed arguments
660
-     *
661
-     * @param bool|string $class_name   Fully Qualified Class Name
662
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
-     * @param bool        $cache        whether to cache the instantiated object for reuse
664
-     * @param bool        $from_db      some classes are instantiated from the db
665
-     *                                  and thus call a different method to instantiate
666
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
669
-     *                                  object = class loaded and instantiated successfully.
670
-     *                                  bool = fail or success when $load_only is true
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     */
674
-    public function create(
675
-        $class_name = false,
676
-        $arguments = array(),
677
-        $cache = false,
678
-        $from_db = false,
679
-        $load_only = false,
680
-        $addon = false
681
-    ) {
682
-        $class_name = ltrim($class_name, '\\');
683
-        $class_name = $this->_dependency_map->get_alias($class_name);
684
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
-        // if a non-FQCN was passed, then verifyClassExists() might return an object
686
-        // or it could return null if the class just could not be found anywhere
687
-        if ($class_exists instanceof $class_name || $class_exists === null){
688
-            // either way, return the results
689
-            return $class_exists;
690
-        }
691
-        $class_name = $class_exists;
692
-        // if we're only loading the class and it already exists, then let's just return true immediately
693
-        if ($load_only) {
694
-            return true;
695
-        }
696
-        $addon = $addon
697
-            ? 'addon'
698
-            : '';
699
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
-        if ($this->_cache_on && $cache && ! $load_only) {
703
-            // return object if it's already cached
704
-            $cached_class = $this->_get_cached_class($class_name, $addon);
705
-            if ($cached_class !== null) {
706
-                return $cached_class;
707
-            }
708
-        }
709
-        // obtain the loader method from the dependency map
710
-        $loader = $this->_dependency_map->class_loader($class_name);
711
-        // instantiate the requested object
712
-        if ($loader instanceof Closure) {
713
-            $class_obj = $loader($arguments);
714
-        } else if ($loader && method_exists($this, $loader)) {
715
-            $class_obj = $this->{$loader}($class_name, $arguments);
716
-        } else {
717
-            $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
-        }
719
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
-            // save it for later... kinda like gum  { : $
721
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
-        }
723
-        $this->_cache_on = true;
724
-        return $class_obj;
725
-    }
726
-
727
-
728
-
729
-    /**
730
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
-     *
732
-     * @param string $class_name
733
-     * @param array  $arguments
734
-     * @param int    $attempt
735
-     * @return mixed
736
-     */
737
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
-        if (is_object($class_name) || class_exists($class_name)) {
739
-            return $class_name;
740
-        }
741
-        switch ($attempt) {
742
-            case 1:
743
-                // if it's a FQCN then maybe the class is registered with a preceding \
744
-                $class_name = strpos($class_name, '\\') !== false
745
-                    ? '\\' . ltrim($class_name, '\\')
746
-                    : $class_name;
747
-                break;
748
-            case 2:
749
-                //
750
-                $loader = $this->_dependency_map->class_loader($class_name);
751
-                if ($loader && method_exists($this, $loader)) {
752
-                    return $this->{$loader}($class_name, $arguments);
753
-                }
754
-                break;
755
-            case 3:
756
-            default;
757
-                return null;
758
-        }
759
-        $attempt++;
760
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
-    }
762
-
763
-
764
-
765
-    /**
766
-     * instantiates, caches, and injects dependencies for classes
767
-     *
768
-     * @param array       $file_paths   an array of paths to folders to look in
769
-     * @param string      $class_prefix EE  or EEM or... ???
770
-     * @param bool|string $class_name   $class name
771
-     * @param string      $type         file type - core? class? helper? model?
772
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
-     * @param bool        $from_db      some classes are instantiated from the db
774
-     *                                  and thus call a different method to instantiate
775
-     * @param bool        $cache        whether to cache the instantiated object for reuse
776
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
-     * @return bool|null|object null = failure to load or instantiate class object.
778
-     *                                  object = class loaded and instantiated successfully.
779
-     *                                  bool = fail or success when $load_only is true
780
-     * @throws EE_Error
781
-     * @throws ReflectionException
782
-     */
783
-    protected function _load(
784
-        $file_paths = array(),
785
-        $class_prefix = 'EE_',
786
-        $class_name = false,
787
-        $type = 'class',
788
-        $arguments = array(),
789
-        $from_db = false,
790
-        $cache = true,
791
-        $load_only = false
792
-    ) {
793
-        $class_name = ltrim($class_name, '\\');
794
-        // strip php file extension
795
-        $class_name = str_replace('.php', '', trim($class_name));
796
-        // does the class have a prefix ?
797
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
-            // make sure $class_prefix is uppercase
799
-            $class_prefix = strtoupper(trim($class_prefix));
800
-            // add class prefix ONCE!!!
801
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
-        }
803
-        $class_name = $this->_dependency_map->get_alias($class_name);
804
-        $class_exists = class_exists($class_name, false);
805
-        // if we're only loading the class and it already exists, then let's just return true immediately
806
-        if ($load_only && $class_exists) {
807
-            return true;
808
-        }
809
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
-        if ($this->_cache_on && $cache && ! $load_only) {
813
-            // return object if it's already cached
814
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
-            if ($cached_class !== null) {
816
-                return $cached_class;
817
-            }
818
-        }
819
-        // if the class doesn't already exist.. then we need to try and find the file and load it
820
-        if (! $class_exists) {
821
-            // get full path to file
822
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
823
-            // load the file
824
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
-            // if loading failed, or we are only loading a file but NOT instantiating an object
826
-            if (! $loaded || $load_only) {
827
-                // return boolean if only loading, or null if an object was expected
828
-                return $load_only
829
-                    ? $loaded
830
-                    : null;
831
-            }
832
-        }
833
-        // instantiate the requested object
834
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
-        if ($this->_cache_on && $cache) {
836
-            // save it for later... kinda like gum  { : $
837
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
-        }
839
-        $this->_cache_on = true;
840
-        return $class_obj;
841
-    }
842
-
843
-
844
-
845
-    /**
846
-     * @param string $class_name
847
-     * @param string $default have to specify something, but not anything that will conflict
848
-     * @return mixed|string
849
-     */
850
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
-    {
852
-        return isset($this->_class_abbreviations[$class_name])
853
-            ? $this->_class_abbreviations[$class_name]
854
-            : $default;
855
-    }
856
-
857
-    /**
858
-     * attempts to find a cached version of the requested class
859
-     * by looking in the following places:
860
-     *        $this->{$class_abbreviation}            ie:    $this->CART
861
-     *        $this->{$class_name}                        ie:    $this->Some_Class
862
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
-     *
865
-     * @param string $class_name
866
-     * @param string $class_prefix
867
-     * @return mixed
868
-     * @throws OutOfBoundsException
869
-     */
870
-    protected function _get_cached_class($class_name, $class_prefix = '')
871
-    {
872
-        if ($class_name === 'EE_Registry') {
873
-            return $this;
874
-        }
875
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
876
-        $class_name = str_replace('\\', '_', $class_name);
877
-        // check if class has already been loaded, and return it if it has been
878
-        if (isset($this->{$class_abbreviation})) {
879
-            return $this->{$class_abbreviation};
880
-        }
881
-        if (isset ($this->{$class_name})) {
882
-            return $this->{$class_name};
883
-        }
884
-        if (isset ($this->LIB->{$class_name})) {
885
-            return $this->LIB->{$class_name};
886
-        }
887
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
-            return $this->addons->{$class_name};
889
-        }
890
-        return null;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * removes a cached version of the requested class
897
-     *
898
-     * @param string  $class_name
899
-     * @param boolean $addon
900
-     * @return boolean
901
-     * @throws OutOfBoundsException
902
-     */
903
-    public function clear_cached_class($class_name, $addon = false)
904
-    {
905
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
906
-        $class_name = str_replace('\\', '_', $class_name);
907
-        // check if class has already been loaded, and return it if it has been
908
-        if (isset($this->{$class_abbreviation})) {
909
-            $this->{$class_abbreviation} = null;
910
-            return true;
911
-        }
912
-        if (isset($this->{$class_name})) {
913
-            $this->{$class_name} = null;
914
-            return true;
915
-        }
916
-        if (isset($this->LIB->{$class_name})) {
917
-            unset($this->LIB->{$class_name});
918
-            return true;
919
-        }
920
-        if ($addon && isset($this->addons->{$class_name})) {
921
-            unset($this->addons->{$class_name});
922
-            return true;
923
-        }
924
-        return false;
925
-    }
926
-
927
-
928
-
929
-    /**
930
-     * attempts to find a full valid filepath for the requested class.
931
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
-     * then returns that path if the target file has been found and is readable
933
-     *
934
-     * @param string $class_name
935
-     * @param string $type
936
-     * @param array  $file_paths
937
-     * @return string | bool
938
-     */
939
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
-    {
941
-        // make sure $file_paths is an array
942
-        $file_paths = is_array($file_paths)
943
-            ? $file_paths
944
-            : array($file_paths);
945
-        // cycle thru paths
946
-        foreach ($file_paths as $key => $file_path) {
947
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
-            $file_path = $file_path
949
-                ? str_replace(array('/', '\\'), DS, $file_path)
950
-                : EE_CLASSES;
951
-            // prep file type
952
-            $type = ! empty($type)
953
-                ? trim($type, '.') . '.'
954
-                : '';
955
-            // build full file path
956
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
-            //does the file exist and can be read ?
958
-            if (is_readable($file_paths[$key])) {
959
-                return $file_paths[$key];
960
-            }
961
-        }
962
-        return false;
963
-    }
964
-
965
-
966
-
967
-    /**
968
-     * basically just performs a require_once()
969
-     * but with some error handling
970
-     *
971
-     * @param  string $path
972
-     * @param  string $class_name
973
-     * @param  string $type
974
-     * @param  array  $file_paths
975
-     * @return bool
976
-     * @throws EE_Error
977
-     * @throws ReflectionException
978
-     */
979
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
-    {
981
-        $this->resolve_legacy_class_parent($class_name);
982
-        // don't give up! you gotta...
983
-        try {
984
-            //does the file exist and can it be read ?
985
-            if (! $path) {
986
-                // just in case the file has already been autoloaded,
987
-                // but discrepancies in the naming schema are preventing it from
988
-                // being loaded via one of the EE_Registry::load_*() methods,
989
-                // then let's try one last hail mary before throwing an exception
990
-                // and call class_exists() again, but with autoloading turned ON
991
-                if(class_exists($class_name)) {
992
-                    return true;
993
-                }
994
-                // so sorry, can't find the file
995
-                throw new EE_Error (
996
-                    sprintf(
997
-                        esc_html__(
998
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
-                            'event_espresso'
1000
-                        ),
1001
-                        trim($type, '.'),
1002
-                        $class_name,
1003
-                        '<br />' . implode(',<br />', $file_paths)
1004
-                    )
1005
-                );
1006
-            }
1007
-            // get the file
1008
-            require_once($path);
1009
-            // if the class isn't already declared somewhere
1010
-            if (class_exists($class_name, false) === false) {
1011
-                // so sorry, not a class
1012
-                throw new EE_Error(
1013
-                    sprintf(
1014
-                        esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
-                        $type,
1016
-                        $path,
1017
-                        $class_name
1018
-                    )
1019
-                );
1020
-            }
1021
-        } catch (EE_Error $e) {
1022
-            $e->get_error();
1023
-            return false;
1024
-        }
1025
-        return true;
1026
-    }
1027
-
1028
-
1029
-
1030
-    /**
1031
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
-     * before their class declaration in order to ensure that the parent class was loaded.
1033
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
-     *
1036
-     * @param string $class_name
1037
-     */
1038
-    protected function resolve_legacy_class_parent($class_name = '')
1039
-    {
1040
-        try {
1041
-            $legacy_parent_class_map = array(
1042
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
-            );
1044
-            if(isset($legacy_parent_class_map[$class_name])) {
1045
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
-            }
1047
-        } catch (Exception $exception) {
1048
-        }
1049
-    }
1050
-
1051
-
1052
-
1053
-    /**
1054
-     * _create_object
1055
-     * Attempts to instantiate the requested class via any of the
1056
-     * commonly used instantiation methods employed throughout EE.
1057
-     * The priority for instantiation is as follows:
1058
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
-     *        - model objects via their 'new_instance_from_db' method
1060
-     *        - model objects via their 'new_instance' method
1061
-     *        - "singleton" classes" via their 'instance' method
1062
-     *    - standard instantiable classes via their __constructor
1063
-     * Prior to instantiation, if the classname exists in the dependency_map,
1064
-     * then the constructor for the requested class will be examined to determine
1065
-     * if any dependencies exist, and if they can be injected.
1066
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1067
-     *
1068
-     * @param string $class_name
1069
-     * @param array  $arguments
1070
-     * @param string $type
1071
-     * @param bool   $from_db
1072
-     * @return null|object
1073
-     * @throws EE_Error
1074
-     * @throws ReflectionException
1075
-     */
1076
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
-    {
1078
-        // create reflection
1079
-        $reflector = $this->get_ReflectionClass($class_name);
1080
-        // make sure arguments are an array
1081
-        $arguments = is_array($arguments)
1082
-            ? $arguments
1083
-            : array($arguments);
1084
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
-            ? $arguments
1088
-            : array($arguments);
1089
-        // attempt to inject dependencies ?
1090
-        if ($this->_dependency_map->has($class_name)) {
1091
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
-        }
1093
-        // instantiate the class if possible
1094
-        if ($reflector->isAbstract()) {
1095
-            // nothing to instantiate, loading file was enough
1096
-            // does not throw an exception so $instantiation_mode is unused
1097
-            // $instantiation_mode = "1) no constructor abstract class";
1098
-            return true;
1099
-        }
1100
-        if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1102
-            // $instantiation_mode = "2) no constructor but instantiable";
1103
-            return $reflector->newInstance();
1104
-        }
1105
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
-            // $instantiation_mode = "3) new_instance_from_db()";
1107
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
-        }
1109
-        if (method_exists($class_name, 'new_instance')) {
1110
-            // $instantiation_mode = "4) new_instance()";
1111
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
-        }
1113
-        if (method_exists($class_name, 'instance')) {
1114
-            // $instantiation_mode = "5) instance()";
1115
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
-        }
1117
-        if ($reflector->isInstantiable()) {
1118
-            // $instantiation_mode = "6) constructor";
1119
-            return $reflector->newInstanceArgs($arguments);
1120
-        }
1121
-        // heh ? something's not right !
1122
-        throw new EE_Error(
1123
-            sprintf(
1124
-                __('The %s file %s could not be instantiated.', 'event_espresso'),
1125
-                $type,
1126
-                $class_name
1127
-            )
1128
-        );
1129
-    }
1130
-
1131
-
1132
-
1133
-    /**
1134
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
-     * @param array $array
1136
-     * @return bool
1137
-     */
1138
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
-    {
1140
-        return ! empty($array)
1141
-            ? array_keys($array) === range(0, count($array) - 1)
1142
-            : true;
1143
-    }
1144
-
1145
-
1146
-
1147
-    /**
1148
-     * getReflectionClass
1149
-     * checks if a ReflectionClass object has already been generated for a class
1150
-     * and returns that instead of creating a new one
1151
-     *
1152
-     * @param string $class_name
1153
-     * @return ReflectionClass
1154
-     * @throws ReflectionException
1155
-     */
1156
-    public function get_ReflectionClass($class_name)
1157
-    {
1158
-        if (
1159
-            ! isset($this->_reflectors[$class_name])
1160
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
-        ) {
1162
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
-        }
1164
-        return $this->_reflectors[$class_name];
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * _resolve_dependencies
1171
-     * examines the constructor for the requested class to determine
1172
-     * if any dependencies exist, and if they can be injected.
1173
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1174
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1175
-     * For example:
1176
-     *        if attempting to load a class "Foo" with the following constructor:
1177
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
-     *        but only IF they are NOT already present in the incoming arguments array,
1180
-     *        and the correct classes can be loaded
1181
-     *
1182
-     * @param ReflectionClass $reflector
1183
-     * @param string          $class_name
1184
-     * @param array           $arguments
1185
-     * @return array
1186
-     * @throws EE_Error
1187
-     * @throws ReflectionException
1188
-     */
1189
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
-    {
1191
-        // let's examine the constructor
1192
-        $constructor = $reflector->getConstructor();
1193
-        // whu? huh? nothing?
1194
-        if (! $constructor) {
1195
-            return $arguments;
1196
-        }
1197
-        // get constructor parameters
1198
-        $params = $constructor->getParameters();
1199
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
-        $argument_keys = array_keys($arguments);
1201
-        // now loop thru all of the constructors expected parameters
1202
-        foreach ($params as $index => $param) {
1203
-            // is this a dependency for a specific class ?
1204
-            $param_class = $param->getClass()
1205
-                ? $param->getClass()->name
1206
-                : null;
1207
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1210
-                : $param_class;
1211
-            if (
1212
-                // param is not even a class
1213
-                $param_class === null
1214
-                // and something already exists in the incoming arguments for this param
1215
-                && array_key_exists($index, $argument_keys)
1216
-                && array_key_exists($argument_keys[$index], $arguments)
1217
-            ) {
1218
-                // so let's skip this argument and move on to the next
1219
-                continue;
1220
-            }
1221
-            if (
1222
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
-                $param_class !== null
1224
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1226
-            ) {
1227
-                // skip this argument and move on to the next
1228
-                continue;
1229
-            }
1230
-            if (
1231
-                // parameter is type hinted as a class, and should be injected
1232
-                $param_class !== null
1233
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
-            ) {
1235
-                $arguments = $this->_resolve_dependency(
1236
-                    $class_name,
1237
-                    $param_class,
1238
-                    $arguments,
1239
-                    $index,
1240
-                    $argument_keys
1241
-                );
1242
-            } else {
1243
-                try {
1244
-                    $arguments[$index] = $param->isDefaultValueAvailable()
1245
-                        ? $param->getDefaultValue()
1246
-                        : null;
1247
-                } catch (ReflectionException $e) {
1248
-                    throw new ReflectionException(
1249
-                        sprintf(
1250
-                            esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
-                            $e->getMessage(),
1252
-                            $param->getName(),
1253
-                            $class_name
1254
-                        )
1255
-                    );
1256
-                }
1257
-            }
1258
-        }
1259
-        return $arguments;
1260
-    }
1261
-
1262
-
1263
-
1264
-    /**
1265
-     * @param string $class_name
1266
-     * @param string $param_class
1267
-     * @param array  $arguments
1268
-     * @param mixed  $index
1269
-     * @param array  $argument_keys
1270
-     * @return array
1271
-     * @throws EE_Error
1272
-     * @throws ReflectionException
1273
-     * @throws InvalidArgumentException
1274
-     * @throws InvalidInterfaceException
1275
-     * @throws InvalidDataTypeException
1276
-     */
1277
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
-    {
1279
-        $dependency = null;
1280
-        // should dependency be loaded from cache ?
1281
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
-            $class_name,
1283
-            $param_class
1284
-        );
1285
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
-        // we might have a dependency...
1287
-        // let's MAYBE try and find it in our cache if that's what's been requested
1288
-        $cached_class = $cache_on
1289
-            ? $this->_get_cached_class($param_class)
1290
-            : null;
1291
-        // and grab it if it exists
1292
-        if ($cached_class instanceof $param_class) {
1293
-            $dependency = $cached_class;
1294
-        } else if ($param_class !== $class_name) {
1295
-            // obtain the loader method from the dependency map
1296
-            $loader = $this->_dependency_map->class_loader($param_class);
1297
-            // is loader a custom closure ?
1298
-            if ($loader instanceof Closure) {
1299
-                $dependency = $loader($arguments);
1300
-            } else {
1301
-                // set the cache on property for the recursive loading call
1302
-                $this->_cache_on = $cache_on;
1303
-                // if not, then let's try and load it via the registry
1304
-                if ($loader && method_exists($this, $loader)) {
1305
-                    $dependency = $this->{$loader}($param_class);
1306
-                } else {
1307
-                    $dependency = LoaderFactory::getLoader()->load(
1308
-                        $param_class,
1309
-                        array(),
1310
-                        $cache_on
1311
-                    );
1312
-                }
1313
-            }
1314
-        }
1315
-        // did we successfully find the correct dependency ?
1316
-        if ($dependency instanceof $param_class) {
1317
-            // then let's inject it into the incoming array of arguments at the correct location
1318
-            $arguments[$index] = $dependency;
1319
-        }
1320
-        return $arguments;
1321
-    }
1322
-
1323
-
1324
-
1325
-    /**
1326
-     * _set_cached_class
1327
-     * attempts to cache the instantiated class locally
1328
-     * in one of the following places, in the following order:
1329
-     *        $this->{class_abbreviation}   ie:    $this->CART
1330
-     *        $this->{$class_name}          ie:    $this->Some_Class
1331
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
-     *
1334
-     * @param object $class_obj
1335
-     * @param string $class_name
1336
-     * @param string $class_prefix
1337
-     * @param bool   $from_db
1338
-     * @return void
1339
-     * @throws OutOfBoundsException
1340
-     */
1341
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
-    {
1343
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
-            return;
1345
-        }
1346
-        // return newly instantiated class
1347
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
-        if ($class_abbreviation) {
1349
-            $this->{$class_abbreviation} = $class_obj;
1350
-            return;
1351
-        }
1352
-        $class_name = str_replace('\\', '_', $class_name);
1353
-        if (property_exists($this, $class_name)) {
1354
-            $this->{$class_name} = $class_obj;
1355
-            return;
1356
-        }
1357
-        if ($class_prefix === 'addon') {
1358
-            $this->addons->{$class_name} = $class_obj;
1359
-            return;
1360
-        }
1361
-        if (! $from_db) {
1362
-            $this->LIB->{$class_name} = $class_obj;
1363
-        }
1364
-    }
1365
-
1366
-
1367
-
1368
-    /**
1369
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
-     *
1371
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1373
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
-     * @param array  $arguments
1375
-     * @return object
1376
-     */
1377
-    public static function factory($classname, $arguments = array())
1378
-    {
1379
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1380
-        if ($loader instanceof Closure) {
1381
-            return $loader($arguments);
1382
-        }
1383
-        if (method_exists(self::instance(), $loader)) {
1384
-            return self::instance()->{$loader}($classname, $arguments);
1385
-        }
1386
-        return null;
1387
-    }
1388
-
1389
-
1390
-
1391
-    /**
1392
-     * Gets the addon by its class name
1393
-     *
1394
-     * @param string $class_name
1395
-     * @return EE_Addon
1396
-     * @throws OutOfBoundsException
1397
-     */
1398
-    public function getAddon($class_name)
1399
-    {
1400
-        $class_name = str_replace('\\', '_', $class_name);
1401
-        return $this->addons->{$class_name};
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * removes the addon from the internal cache
1407
-     *
1408
-     * @param string $class_name
1409
-     * @return void
1410
-     */
1411
-    public function removeAddon($class_name)
1412
-    {
1413
-        $class_name = str_replace('\\', '_', $class_name);
1414
-        unset($this->addons->{$class_name});
1415
-    }
1416
-
1417
-
1418
-
1419
-    /**
1420
-     * Gets the addon by its name/slug (not classname. For that, just
1421
-     * use the get_addon() method above
1422
-     *
1423
-     * @param string $name
1424
-     * @return EE_Addon
1425
-     */
1426
-    public function get_addon_by_name($name)
1427
-    {
1428
-        foreach ($this->addons as $addon) {
1429
-            if ($addon->name() === $name) {
1430
-                return $addon;
1431
-            }
1432
-        }
1433
-        return null;
1434
-    }
1435
-
1436
-
1437
-
1438
-    /**
1439
-     * Gets an array of all the registered addons, where the keys are their names.
1440
-     * (ie, what each returns for their name() function)
1441
-     * They're already available on EE_Registry::instance()->addons as properties,
1442
-     * where each property's name is the addon's classname,
1443
-     * So if you just want to get the addon by classname,
1444
-     * OR use the get_addon() method above.
1445
-     * PLEASE  NOTE:
1446
-     * addons with Fully Qualified Class Names
1447
-     * have had the namespace separators converted to underscores,
1448
-     * so a classname like Fully\Qualified\ClassName
1449
-     * would have been converted to Fully_Qualified_ClassName
1450
-     *
1451
-     * @return EE_Addon[] where the KEYS are the addon's name()
1452
-     */
1453
-    public function get_addons_by_name()
1454
-    {
1455
-        $addons = array();
1456
-        foreach ($this->addons as $addon) {
1457
-            $addons[$addon->name()] = $addon;
1458
-        }
1459
-        return $addons;
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
-     * a stale copy of it around
1466
-     *
1467
-     * @param string $model_name
1468
-     * @return \EEM_Base
1469
-     * @throws \EE_Error
1470
-     */
1471
-    public function reset_model($model_name)
1472
-    {
1473
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1474
-            ? "EEM_{$model_name}"
1475
-            : $model_name;
1476
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
-            return null;
1478
-        }
1479
-        //get that model reset it and make sure we nuke the old reference to it
1480
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
-            && is_callable(
1482
-                array($model_class_name, 'reset')
1483
-            )) {
1484
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
-        } else {
1486
-            throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
-        }
1488
-        return $this->LIB->{$model_class_name};
1489
-    }
1490
-
1491
-
1492
-
1493
-    /**
1494
-     * Resets the registry.
1495
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
-     * - $_dependency_map
1498
-     * - $_class_abbreviations
1499
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
-     * - $REQ:  Still on the same request so no need to change.
1501
-     * - $CAP: There is no site specific state in the EE_Capability class.
1502
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
-     *             switch or on the restore.
1507
-     * - $modules
1508
-     * - $shortcodes
1509
-     * - $widgets
1510
-     *
1511
-     * @param boolean $hard             [deprecated]
1512
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
-     *                                  client
1517
-     *                                  code instead can just change the model context to a different blog id if
1518
-     *                                  necessary
1519
-     * @return EE_Registry
1520
-     * @throws EE_Error
1521
-     * @throws ReflectionException
1522
-     */
1523
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
-    {
1525
-        $instance = self::instance();
1526
-        $instance->_cache_on = true;
1527
-        // reset some "special" classes
1528
-        EEH_Activation::reset();
1529
-        $hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
-        $instance->CART = null;
1532
-        $instance->MRM = null;
1533
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
-        //messages reset
1535
-        EED_Messages::reset();
1536
-        //handle of objects cached on LIB
1537
-        foreach (array('LIB', 'modules') as $cache) {
1538
-            foreach ($instance->{$cache} as $class_name => $class) {
1539
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1540
-                    unset($instance->{$cache}->{$class_name});
1541
-                }
1542
-            }
1543
-        }
1544
-        return $instance;
1545
-    }
1546
-
1547
-
1548
-
1549
-    /**
1550
-     * if passed object implements ResettableInterface, then call it's reset() method
1551
-     * if passed object implements InterminableInterface, then return false,
1552
-     * to indicate that it should NOT be cleared from the Registry cache
1553
-     *
1554
-     * @param      $object
1555
-     * @param bool $reset_models
1556
-     * @return bool returns true if cached object should be unset
1557
-     */
1558
-    private static function _reset_and_unset_object($object, $reset_models)
1559
-    {
1560
-        if (! is_object($object)) {
1561
-            // don't unset anything that's not an object
1562
-            return false;
1563
-        }
1564
-        if ($object instanceof EED_Module) {
1565
-            $object::reset();
1566
-            // don't unset modules
1567
-            return false;
1568
-        }
1569
-        if ($object instanceof ResettableInterface) {
1570
-            if ($object instanceof EEM_Base) {
1571
-                if ($reset_models) {
1572
-                    $object->reset();
1573
-                    return true;
1574
-                }
1575
-                return false;
1576
-            }
1577
-            $object->reset();
1578
-            return true;
1579
-        }
1580
-        if (! $object instanceof InterminableInterface) {
1581
-            return true;
1582
-        }
1583
-        return false;
1584
-    }
1585
-
1586
-
1587
-
1588
-    /**
1589
-     * Gets all the custom post type models defined
1590
-     *
1591
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
-     */
1593
-    public function cpt_models()
1594
-    {
1595
-        $cpt_models = array();
1596
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
-                $cpt_models[$short_name] = $classname;
1599
-            }
1600
-        }
1601
-        return $cpt_models;
1602
-    }
1603
-
1604
-
1605
-
1606
-    /**
1607
-     * @return \EE_Config
1608
-     */
1609
-    public static function CFG()
1610
-    {
1611
-        return self::instance()->CFG;
1612
-    }
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var array $_class_abbreviations
38
+	 */
39
+	protected $_class_abbreviations = array();
40
+
41
+	/**
42
+	 * @var CommandBusInterface $BUS
43
+	 */
44
+	public $BUS;
45
+
46
+	/**
47
+	 * @var EE_Cart $CART
48
+	 */
49
+	public $CART;
50
+
51
+	/**
52
+	 * @var EE_Config $CFG
53
+	 */
54
+	public $CFG;
55
+
56
+	/**
57
+	 * @var EE_Network_Config $NET_CFG
58
+	 */
59
+	public $NET_CFG;
60
+
61
+	/**
62
+	 * StdClass object for storing library classes in
63
+	 *
64
+	 * @var StdClass $LIB
65
+	 */
66
+	public $LIB;
67
+
68
+	/**
69
+	 * @var EE_Request_Handler $REQ
70
+	 */
71
+	public $REQ;
72
+
73
+	/**
74
+	 * @var EE_Session $SSN
75
+	 */
76
+	public $SSN;
77
+
78
+	/**
79
+	 * @since 4.5.0
80
+	 * @var EE_Capabilities $CAP
81
+	 */
82
+	public $CAP;
83
+
84
+	/**
85
+	 * @since 4.9.0
86
+	 * @var EE_Message_Resource_Manager $MRM
87
+	 */
88
+	public $MRM;
89
+
90
+
91
+	/**
92
+	 * @var Registry $AssetsRegistry
93
+	 */
94
+	public $AssetsRegistry;
95
+
96
+	/**
97
+	 * StdClass object for holding addons which have registered themselves to work with EE core
98
+	 *
99
+	 * @var EE_Addon[] $addons
100
+	 */
101
+	public $addons;
102
+
103
+	/**
104
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
+	 *
106
+	 * @var EEM_Base[] $models
107
+	 */
108
+	public $models = array();
109
+
110
+	/**
111
+	 * @var EED_Module[] $modules
112
+	 */
113
+	public $modules;
114
+
115
+	/**
116
+	 * @var EES_Shortcode[] $shortcodes
117
+	 */
118
+	public $shortcodes;
119
+
120
+	/**
121
+	 * @var WP_Widget[] $widgets
122
+	 */
123
+	public $widgets;
124
+
125
+	/**
126
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
+	 * classnames (eg "EEM_Event")
130
+	 *
131
+	 * @var array $non_abstract_db_models
132
+	 */
133
+	public $non_abstract_db_models = array();
134
+
135
+
136
+	/**
137
+	 * internationalization for JS strings
138
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
+	 *    in js file:  var translatedString = eei18n.string_key;
140
+	 *
141
+	 * @var array $i18n_js_strings
142
+	 */
143
+	public static $i18n_js_strings = array();
144
+
145
+
146
+	/**
147
+	 * $main_file - path to espresso.php
148
+	 *
149
+	 * @var array $main_file
150
+	 */
151
+	public $main_file;
152
+
153
+	/**
154
+	 * array of ReflectionClass objects where the key is the class name
155
+	 *
156
+	 * @var ReflectionClass[] $_reflectors
157
+	 */
158
+	public $_reflectors;
159
+
160
+	/**
161
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
+	 *
163
+	 * @var boolean $_cache_on
164
+	 */
165
+	protected $_cache_on = true;
166
+
167
+
168
+
169
+	/**
170
+	 * @singleton method used to instantiate class object
171
+	 * @param  EE_Dependency_Map $dependency_map
172
+	 * @return EE_Registry instance
173
+	 * @throws InvalidArgumentException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws InvalidDataTypeException
176
+	 */
177
+	public static function instance(EE_Dependency_Map $dependency_map = null)
178
+	{
179
+		// check if class object is instantiated
180
+		if (! self::$_instance instanceof EE_Registry) {
181
+			self::$_instance = new self($dependency_map);
182
+		}
183
+		return self::$_instance;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * protected constructor to prevent direct creation
190
+	 *
191
+	 * @Constructor
192
+	 * @param  EE_Dependency_Map $dependency_map
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 * @throws InvalidArgumentException
196
+	 */
197
+	protected function __construct(EE_Dependency_Map $dependency_map)
198
+	{
199
+		$this->_dependency_map = $dependency_map;
200
+		// $registry_container = new RegistryContainer();
201
+		$this->LIB = new RegistryContainer();
202
+		$this->addons = new RegistryContainer();
203
+		$this->modules = new RegistryContainer();
204
+		$this->shortcodes = new RegistryContainer();
205
+		$this->widgets = new RegistryContainer();
206
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
+	}
208
+
209
+
210
+
211
+	/**
212
+	 * initialize
213
+	 *
214
+	 * @throws EE_Error
215
+	 * @throws ReflectionException
216
+	 */
217
+	public function initialize()
218
+	{
219
+		$this->_class_abbreviations = apply_filters(
220
+			'FHEE__EE_Registry____construct___class_abbreviations',
221
+			array(
222
+				'EE_Config'                                       => 'CFG',
223
+				'EE_Session'                                      => 'SSN',
224
+				'EE_Capabilities'                                 => 'CAP',
225
+				'EE_Cart'                                         => 'CART',
226
+				'EE_Network_Config'                               => 'NET_CFG',
227
+				'EE_Request_Handler'                              => 'REQ',
228
+				'EE_Message_Resource_Manager'                     => 'MRM',
229
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
+			)
232
+		);
233
+		$this->load_core('Base', array(), true);
234
+		// add our request and response objects to the cache
235
+		$request_loader = $this->_dependency_map->class_loader(
236
+			'EventEspresso\core\services\request\Request'
237
+		);
238
+		$this->_set_cached_class(
239
+			$request_loader(),
240
+			'EventEspresso\core\services\request\Request'
241
+		);
242
+		$response_loader = $this->_dependency_map->class_loader(
243
+			'EventEspresso\core\services\request\Response'
244
+		);
245
+		$this->_set_cached_class(
246
+			$response_loader(),
247
+			'EventEspresso\core\services\request\Response'
248
+		);
249
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * @return void
256
+	 */
257
+	public function init()
258
+	{
259
+		// Get current page protocol
260
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
+		// Output admin-ajax.php URL with same protocol as current page
262
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * localize_i18n_js_strings
270
+	 *
271
+	 * @return string
272
+	 */
273
+	public static function localize_i18n_js_strings()
274
+	{
275
+		$i18n_js_strings = (array)self::$i18n_js_strings;
276
+		foreach ($i18n_js_strings as $key => $value) {
277
+			if (is_scalar($value)) {
278
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
+			}
280
+		}
281
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param mixed string | EED_Module $module
288
+	 * @throws EE_Error
289
+	 * @throws ReflectionException
290
+	 */
291
+	public function add_module($module)
292
+	{
293
+		if ($module instanceof EED_Module) {
294
+			$module_class = get_class($module);
295
+			$this->modules->{$module_class} = $module;
296
+		} else {
297
+			if ( ! class_exists('EE_Module_Request_Router', false)) {
298
+				$this->load_core('Module_Request_Router');
299
+			}
300
+			EE_Module_Request_Router::module_factory($module);
301
+		}
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @param string $module_name
308
+	 * @return mixed EED_Module | NULL
309
+	 */
310
+	public function get_module($module_name = '')
311
+	{
312
+		return isset($this->modules->{$module_name})
313
+			? $this->modules->{$module_name}
314
+			: null;
315
+	}
316
+
317
+
318
+
319
+	/**
320
+	 * loads core classes - must be singletons
321
+	 *
322
+	 * @param string $class_name - simple class name ie: session
323
+	 * @param mixed  $arguments
324
+	 * @param bool   $load_only
325
+	 * @return mixed
326
+	 * @throws EE_Error
327
+	 * @throws ReflectionException
328
+	 */
329
+	public function load_core($class_name, $arguments = array(), $load_only = false)
330
+	{
331
+		$core_paths = apply_filters(
332
+			'FHEE__EE_Registry__load_core__core_paths',
333
+			array(
334
+				EE_CORE,
335
+				EE_ADMIN,
336
+				EE_CPTS,
337
+				EE_CORE . 'data_migration_scripts' . DS,
338
+				EE_CORE . 'capabilities' . DS,
339
+				EE_CORE . 'request_stack' . DS,
340
+				EE_CORE . 'middleware' . DS,
341
+			)
342
+		);
343
+		// retrieve instantiated class
344
+		return $this->_load(
345
+			$core_paths,
346
+			'EE_',
347
+			$class_name,
348
+			'core',
349
+			$arguments,
350
+			false,
351
+			true,
352
+			$load_only
353
+		);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * loads service classes
360
+	 *
361
+	 * @param string $class_name - simple class name ie: session
362
+	 * @param mixed  $arguments
363
+	 * @param bool   $load_only
364
+	 * @return mixed
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	public function load_service($class_name, $arguments = array(), $load_only = false)
369
+	{
370
+		$service_paths = apply_filters(
371
+			'FHEE__EE_Registry__load_service__service_paths',
372
+			array(
373
+				EE_CORE . 'services' . DS,
374
+			)
375
+		);
376
+		// retrieve instantiated class
377
+		return $this->_load(
378
+			$service_paths,
379
+			'EE_',
380
+			$class_name,
381
+			'class',
382
+			$arguments,
383
+			false,
384
+			true,
385
+			$load_only
386
+		);
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * loads data_migration_scripts
393
+	 *
394
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
+	 * @param mixed  $arguments
396
+	 * @return EE_Data_Migration_Script_Base|mixed
397
+	 * @throws EE_Error
398
+	 * @throws ReflectionException
399
+	 */
400
+	public function load_dms($class_name, $arguments = array())
401
+	{
402
+		// retrieve instantiated class
403
+		return $this->_load(
404
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
+			'EE_DMS_',
406
+			$class_name,
407
+			'dms',
408
+			$arguments,
409
+			false,
410
+			false
411
+		);
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 * loads object creating classes - must be singletons
418
+	 *
419
+	 * @param string $class_name - simple class name ie: attendee
420
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
421
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
+	 *                           instantiate
423
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
+	 *                           (default)
427
+	 * @return EE_Base_Class | bool
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
+	{
433
+		$paths = apply_filters(
434
+			'FHEE__EE_Registry__load_class__paths', array(
435
+			EE_CORE,
436
+			EE_CLASSES,
437
+			EE_BUSINESS,
438
+		)
439
+		);
440
+		// retrieve instantiated class
441
+		return $this->_load(
442
+			$paths,
443
+			'EE_',
444
+			$class_name,
445
+			'class',
446
+			$arguments,
447
+			$from_db,
448
+			$cache,
449
+			$load_only
450
+		);
451
+	}
452
+
453
+
454
+
455
+	/**
456
+	 * loads helper classes - must be singletons
457
+	 *
458
+	 * @param string $class_name - simple class name ie: price
459
+	 * @param mixed  $arguments
460
+	 * @param bool   $load_only
461
+	 * @return EEH_Base | bool
462
+	 * @throws EE_Error
463
+	 * @throws ReflectionException
464
+	 */
465
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
466
+	{
467
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
+		// retrieve instantiated class
470
+		return $this->_load(
471
+			$helper_paths,
472
+			'EEH_',
473
+			$class_name,
474
+			'helper',
475
+			$arguments,
476
+			false,
477
+			true,
478
+			$load_only
479
+		);
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * loads core classes - must be singletons
486
+	 *
487
+	 * @param string $class_name - simple class name ie: session
488
+	 * @param mixed  $arguments
489
+	 * @param bool   $load_only
490
+	 * @param bool   $cache      whether to cache the object or not.
491
+	 * @return mixed
492
+	 * @throws EE_Error
493
+	 * @throws ReflectionException
494
+	 */
495
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
+	{
497
+		$paths = array(
498
+			EE_LIBRARIES,
499
+			EE_LIBRARIES . 'messages' . DS,
500
+			EE_LIBRARIES . 'shortcodes' . DS,
501
+			EE_LIBRARIES . 'qtips' . DS,
502
+			EE_LIBRARIES . 'payment_methods' . DS,
503
+		);
504
+		// retrieve instantiated class
505
+		return $this->_load(
506
+			$paths,
507
+			'EE_',
508
+			$class_name,
509
+			'lib',
510
+			$arguments,
511
+			false,
512
+			$cache,
513
+			$load_only
514
+		);
515
+	}
516
+
517
+
518
+
519
+	/**
520
+	 * loads model classes - must be singletons
521
+	 *
522
+	 * @param string $class_name - simple class name ie: price
523
+	 * @param mixed  $arguments
524
+	 * @param bool   $load_only
525
+	 * @return EEM_Base | bool
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 */
529
+	public function load_model($class_name, $arguments = array(), $load_only = false)
530
+	{
531
+		$paths = apply_filters(
532
+			'FHEE__EE_Registry__load_model__paths', array(
533
+			EE_MODELS,
534
+			EE_CORE,
535
+		)
536
+		);
537
+		// retrieve instantiated class
538
+		return $this->_load(
539
+			$paths,
540
+			'EEM_',
541
+			$class_name,
542
+			'model',
543
+			$arguments,
544
+			false,
545
+			true,
546
+			$load_only
547
+		);
548
+	}
549
+
550
+
551
+
552
+	/**
553
+	 * loads model classes - must be singletons
554
+	 *
555
+	 * @param string $class_name - simple class name ie: price
556
+	 * @param mixed  $arguments
557
+	 * @param bool   $load_only
558
+	 * @return mixed | bool
559
+	 * @throws EE_Error
560
+	 * @throws ReflectionException
561
+	 */
562
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
+	{
564
+		$paths = array(
565
+			EE_MODELS . 'fields' . DS,
566
+			EE_MODELS . 'helpers' . DS,
567
+			EE_MODELS . 'relations' . DS,
568
+			EE_MODELS . 'strategies' . DS,
569
+		);
570
+		// retrieve instantiated class
571
+		return $this->_load(
572
+			$paths,
573
+			'EE_',
574
+			$class_name,
575
+			'',
576
+			$arguments,
577
+			false,
578
+			true,
579
+			$load_only
580
+		);
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * Determines if $model_name is the name of an actual EE model.
587
+	 *
588
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
+	 * @return boolean
590
+	 */
591
+	public function is_model_name($model_name)
592
+	{
593
+		return isset($this->models[$model_name]);
594
+	}
595
+
596
+
597
+
598
+	/**
599
+	 * generic class loader
600
+	 *
601
+	 * @param string $path_to_file - directory path to file location, not including filename
602
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
603
+	 * @param string $type         - file type - core? class? helper? model?
604
+	 * @param mixed  $arguments
605
+	 * @param bool   $load_only
606
+	 * @return mixed
607
+	 * @throws EE_Error
608
+	 * @throws ReflectionException
609
+	 */
610
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
+	{
612
+		// retrieve instantiated class
613
+		return $this->_load(
614
+			$path_to_file,
615
+			'',
616
+			$file_name,
617
+			$type,
618
+			$arguments,
619
+			false,
620
+			true,
621
+			$load_only
622
+		);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @param string $path_to_file - directory path to file location, not including filename
629
+	 * @param string $class_name   - full class name  ie:  My_Class
630
+	 * @param string $type         - file type - core? class? helper? model?
631
+	 * @param mixed  $arguments
632
+	 * @param bool   $load_only
633
+	 * @return bool|EE_Addon|object
634
+	 * @throws EE_Error
635
+	 * @throws ReflectionException
636
+	 */
637
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
+	{
639
+		// retrieve instantiated class
640
+		return $this->_load(
641
+			$path_to_file,
642
+			'addon',
643
+			$class_name,
644
+			$type,
645
+			$arguments,
646
+			false,
647
+			true,
648
+			$load_only
649
+		);
650
+	}
651
+
652
+
653
+
654
+	/**
655
+	 * instantiates, caches, and automatically resolves dependencies
656
+	 * for classes that use a Fully Qualified Class Name.
657
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
658
+	 * then you need to use one of the existing load_*() methods
659
+	 * which can resolve the classname and filepath from the passed arguments
660
+	 *
661
+	 * @param bool|string $class_name   Fully Qualified Class Name
662
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
664
+	 * @param bool        $from_db      some classes are instantiated from the db
665
+	 *                                  and thus call a different method to instantiate
666
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
669
+	 *                                  object = class loaded and instantiated successfully.
670
+	 *                                  bool = fail or success when $load_only is true
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 */
674
+	public function create(
675
+		$class_name = false,
676
+		$arguments = array(),
677
+		$cache = false,
678
+		$from_db = false,
679
+		$load_only = false,
680
+		$addon = false
681
+	) {
682
+		$class_name = ltrim($class_name, '\\');
683
+		$class_name = $this->_dependency_map->get_alias($class_name);
684
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
+		// if a non-FQCN was passed, then verifyClassExists() might return an object
686
+		// or it could return null if the class just could not be found anywhere
687
+		if ($class_exists instanceof $class_name || $class_exists === null){
688
+			// either way, return the results
689
+			return $class_exists;
690
+		}
691
+		$class_name = $class_exists;
692
+		// if we're only loading the class and it already exists, then let's just return true immediately
693
+		if ($load_only) {
694
+			return true;
695
+		}
696
+		$addon = $addon
697
+			? 'addon'
698
+			: '';
699
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
+		if ($this->_cache_on && $cache && ! $load_only) {
703
+			// return object if it's already cached
704
+			$cached_class = $this->_get_cached_class($class_name, $addon);
705
+			if ($cached_class !== null) {
706
+				return $cached_class;
707
+			}
708
+		}
709
+		// obtain the loader method from the dependency map
710
+		$loader = $this->_dependency_map->class_loader($class_name);
711
+		// instantiate the requested object
712
+		if ($loader instanceof Closure) {
713
+			$class_obj = $loader($arguments);
714
+		} else if ($loader && method_exists($this, $loader)) {
715
+			$class_obj = $this->{$loader}($class_name, $arguments);
716
+		} else {
717
+			$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
+		}
719
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
+			// save it for later... kinda like gum  { : $
721
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
+		}
723
+		$this->_cache_on = true;
724
+		return $class_obj;
725
+	}
726
+
727
+
728
+
729
+	/**
730
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
+	 *
732
+	 * @param string $class_name
733
+	 * @param array  $arguments
734
+	 * @param int    $attempt
735
+	 * @return mixed
736
+	 */
737
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
+		if (is_object($class_name) || class_exists($class_name)) {
739
+			return $class_name;
740
+		}
741
+		switch ($attempt) {
742
+			case 1:
743
+				// if it's a FQCN then maybe the class is registered with a preceding \
744
+				$class_name = strpos($class_name, '\\') !== false
745
+					? '\\' . ltrim($class_name, '\\')
746
+					: $class_name;
747
+				break;
748
+			case 2:
749
+				//
750
+				$loader = $this->_dependency_map->class_loader($class_name);
751
+				if ($loader && method_exists($this, $loader)) {
752
+					return $this->{$loader}($class_name, $arguments);
753
+				}
754
+				break;
755
+			case 3:
756
+			default;
757
+				return null;
758
+		}
759
+		$attempt++;
760
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
+	}
762
+
763
+
764
+
765
+	/**
766
+	 * instantiates, caches, and injects dependencies for classes
767
+	 *
768
+	 * @param array       $file_paths   an array of paths to folders to look in
769
+	 * @param string      $class_prefix EE  or EEM or... ???
770
+	 * @param bool|string $class_name   $class name
771
+	 * @param string      $type         file type - core? class? helper? model?
772
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
+	 * @param bool        $from_db      some classes are instantiated from the db
774
+	 *                                  and thus call a different method to instantiate
775
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
776
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
+	 * @return bool|null|object null = failure to load or instantiate class object.
778
+	 *                                  object = class loaded and instantiated successfully.
779
+	 *                                  bool = fail or success when $load_only is true
780
+	 * @throws EE_Error
781
+	 * @throws ReflectionException
782
+	 */
783
+	protected function _load(
784
+		$file_paths = array(),
785
+		$class_prefix = 'EE_',
786
+		$class_name = false,
787
+		$type = 'class',
788
+		$arguments = array(),
789
+		$from_db = false,
790
+		$cache = true,
791
+		$load_only = false
792
+	) {
793
+		$class_name = ltrim($class_name, '\\');
794
+		// strip php file extension
795
+		$class_name = str_replace('.php', '', trim($class_name));
796
+		// does the class have a prefix ?
797
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
+			// make sure $class_prefix is uppercase
799
+			$class_prefix = strtoupper(trim($class_prefix));
800
+			// add class prefix ONCE!!!
801
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
+		}
803
+		$class_name = $this->_dependency_map->get_alias($class_name);
804
+		$class_exists = class_exists($class_name, false);
805
+		// if we're only loading the class and it already exists, then let's just return true immediately
806
+		if ($load_only && $class_exists) {
807
+			return true;
808
+		}
809
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
+		if ($this->_cache_on && $cache && ! $load_only) {
813
+			// return object if it's already cached
814
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
+			if ($cached_class !== null) {
816
+				return $cached_class;
817
+			}
818
+		}
819
+		// if the class doesn't already exist.. then we need to try and find the file and load it
820
+		if (! $class_exists) {
821
+			// get full path to file
822
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
823
+			// load the file
824
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
+			// if loading failed, or we are only loading a file but NOT instantiating an object
826
+			if (! $loaded || $load_only) {
827
+				// return boolean if only loading, or null if an object was expected
828
+				return $load_only
829
+					? $loaded
830
+					: null;
831
+			}
832
+		}
833
+		// instantiate the requested object
834
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
+		if ($this->_cache_on && $cache) {
836
+			// save it for later... kinda like gum  { : $
837
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
+		}
839
+		$this->_cache_on = true;
840
+		return $class_obj;
841
+	}
842
+
843
+
844
+
845
+	/**
846
+	 * @param string $class_name
847
+	 * @param string $default have to specify something, but not anything that will conflict
848
+	 * @return mixed|string
849
+	 */
850
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
+	{
852
+		return isset($this->_class_abbreviations[$class_name])
853
+			? $this->_class_abbreviations[$class_name]
854
+			: $default;
855
+	}
856
+
857
+	/**
858
+	 * attempts to find a cached version of the requested class
859
+	 * by looking in the following places:
860
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
861
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
862
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
+	 *
865
+	 * @param string $class_name
866
+	 * @param string $class_prefix
867
+	 * @return mixed
868
+	 * @throws OutOfBoundsException
869
+	 */
870
+	protected function _get_cached_class($class_name, $class_prefix = '')
871
+	{
872
+		if ($class_name === 'EE_Registry') {
873
+			return $this;
874
+		}
875
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
876
+		$class_name = str_replace('\\', '_', $class_name);
877
+		// check if class has already been loaded, and return it if it has been
878
+		if (isset($this->{$class_abbreviation})) {
879
+			return $this->{$class_abbreviation};
880
+		}
881
+		if (isset ($this->{$class_name})) {
882
+			return $this->{$class_name};
883
+		}
884
+		if (isset ($this->LIB->{$class_name})) {
885
+			return $this->LIB->{$class_name};
886
+		}
887
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
+			return $this->addons->{$class_name};
889
+		}
890
+		return null;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * removes a cached version of the requested class
897
+	 *
898
+	 * @param string  $class_name
899
+	 * @param boolean $addon
900
+	 * @return boolean
901
+	 * @throws OutOfBoundsException
902
+	 */
903
+	public function clear_cached_class($class_name, $addon = false)
904
+	{
905
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
906
+		$class_name = str_replace('\\', '_', $class_name);
907
+		// check if class has already been loaded, and return it if it has been
908
+		if (isset($this->{$class_abbreviation})) {
909
+			$this->{$class_abbreviation} = null;
910
+			return true;
911
+		}
912
+		if (isset($this->{$class_name})) {
913
+			$this->{$class_name} = null;
914
+			return true;
915
+		}
916
+		if (isset($this->LIB->{$class_name})) {
917
+			unset($this->LIB->{$class_name});
918
+			return true;
919
+		}
920
+		if ($addon && isset($this->addons->{$class_name})) {
921
+			unset($this->addons->{$class_name});
922
+			return true;
923
+		}
924
+		return false;
925
+	}
926
+
927
+
928
+
929
+	/**
930
+	 * attempts to find a full valid filepath for the requested class.
931
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
+	 * then returns that path if the target file has been found and is readable
933
+	 *
934
+	 * @param string $class_name
935
+	 * @param string $type
936
+	 * @param array  $file_paths
937
+	 * @return string | bool
938
+	 */
939
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
+	{
941
+		// make sure $file_paths is an array
942
+		$file_paths = is_array($file_paths)
943
+			? $file_paths
944
+			: array($file_paths);
945
+		// cycle thru paths
946
+		foreach ($file_paths as $key => $file_path) {
947
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
+			$file_path = $file_path
949
+				? str_replace(array('/', '\\'), DS, $file_path)
950
+				: EE_CLASSES;
951
+			// prep file type
952
+			$type = ! empty($type)
953
+				? trim($type, '.') . '.'
954
+				: '';
955
+			// build full file path
956
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
+			//does the file exist and can be read ?
958
+			if (is_readable($file_paths[$key])) {
959
+				return $file_paths[$key];
960
+			}
961
+		}
962
+		return false;
963
+	}
964
+
965
+
966
+
967
+	/**
968
+	 * basically just performs a require_once()
969
+	 * but with some error handling
970
+	 *
971
+	 * @param  string $path
972
+	 * @param  string $class_name
973
+	 * @param  string $type
974
+	 * @param  array  $file_paths
975
+	 * @return bool
976
+	 * @throws EE_Error
977
+	 * @throws ReflectionException
978
+	 */
979
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
+	{
981
+		$this->resolve_legacy_class_parent($class_name);
982
+		// don't give up! you gotta...
983
+		try {
984
+			//does the file exist and can it be read ?
985
+			if (! $path) {
986
+				// just in case the file has already been autoloaded,
987
+				// but discrepancies in the naming schema are preventing it from
988
+				// being loaded via one of the EE_Registry::load_*() methods,
989
+				// then let's try one last hail mary before throwing an exception
990
+				// and call class_exists() again, but with autoloading turned ON
991
+				if(class_exists($class_name)) {
992
+					return true;
993
+				}
994
+				// so sorry, can't find the file
995
+				throw new EE_Error (
996
+					sprintf(
997
+						esc_html__(
998
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
+							'event_espresso'
1000
+						),
1001
+						trim($type, '.'),
1002
+						$class_name,
1003
+						'<br />' . implode(',<br />', $file_paths)
1004
+					)
1005
+				);
1006
+			}
1007
+			// get the file
1008
+			require_once($path);
1009
+			// if the class isn't already declared somewhere
1010
+			if (class_exists($class_name, false) === false) {
1011
+				// so sorry, not a class
1012
+				throw new EE_Error(
1013
+					sprintf(
1014
+						esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
+						$type,
1016
+						$path,
1017
+						$class_name
1018
+					)
1019
+				);
1020
+			}
1021
+		} catch (EE_Error $e) {
1022
+			$e->get_error();
1023
+			return false;
1024
+		}
1025
+		return true;
1026
+	}
1027
+
1028
+
1029
+
1030
+	/**
1031
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
+	 * before their class declaration in order to ensure that the parent class was loaded.
1033
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
+	 *
1036
+	 * @param string $class_name
1037
+	 */
1038
+	protected function resolve_legacy_class_parent($class_name = '')
1039
+	{
1040
+		try {
1041
+			$legacy_parent_class_map = array(
1042
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
+			);
1044
+			if(isset($legacy_parent_class_map[$class_name])) {
1045
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
+			}
1047
+		} catch (Exception $exception) {
1048
+		}
1049
+	}
1050
+
1051
+
1052
+
1053
+	/**
1054
+	 * _create_object
1055
+	 * Attempts to instantiate the requested class via any of the
1056
+	 * commonly used instantiation methods employed throughout EE.
1057
+	 * The priority for instantiation is as follows:
1058
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
+	 *        - model objects via their 'new_instance_from_db' method
1060
+	 *        - model objects via their 'new_instance' method
1061
+	 *        - "singleton" classes" via their 'instance' method
1062
+	 *    - standard instantiable classes via their __constructor
1063
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1064
+	 * then the constructor for the requested class will be examined to determine
1065
+	 * if any dependencies exist, and if they can be injected.
1066
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1067
+	 *
1068
+	 * @param string $class_name
1069
+	 * @param array  $arguments
1070
+	 * @param string $type
1071
+	 * @param bool   $from_db
1072
+	 * @return null|object
1073
+	 * @throws EE_Error
1074
+	 * @throws ReflectionException
1075
+	 */
1076
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
+	{
1078
+		// create reflection
1079
+		$reflector = $this->get_ReflectionClass($class_name);
1080
+		// make sure arguments are an array
1081
+		$arguments = is_array($arguments)
1082
+			? $arguments
1083
+			: array($arguments);
1084
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
+			? $arguments
1088
+			: array($arguments);
1089
+		// attempt to inject dependencies ?
1090
+		if ($this->_dependency_map->has($class_name)) {
1091
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
+		}
1093
+		// instantiate the class if possible
1094
+		if ($reflector->isAbstract()) {
1095
+			// nothing to instantiate, loading file was enough
1096
+			// does not throw an exception so $instantiation_mode is unused
1097
+			// $instantiation_mode = "1) no constructor abstract class";
1098
+			return true;
1099
+		}
1100
+		if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1102
+			// $instantiation_mode = "2) no constructor but instantiable";
1103
+			return $reflector->newInstance();
1104
+		}
1105
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
+			// $instantiation_mode = "3) new_instance_from_db()";
1107
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
+		}
1109
+		if (method_exists($class_name, 'new_instance')) {
1110
+			// $instantiation_mode = "4) new_instance()";
1111
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
+		}
1113
+		if (method_exists($class_name, 'instance')) {
1114
+			// $instantiation_mode = "5) instance()";
1115
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
+		}
1117
+		if ($reflector->isInstantiable()) {
1118
+			// $instantiation_mode = "6) constructor";
1119
+			return $reflector->newInstanceArgs($arguments);
1120
+		}
1121
+		// heh ? something's not right !
1122
+		throw new EE_Error(
1123
+			sprintf(
1124
+				__('The %s file %s could not be instantiated.', 'event_espresso'),
1125
+				$type,
1126
+				$class_name
1127
+			)
1128
+		);
1129
+	}
1130
+
1131
+
1132
+
1133
+	/**
1134
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
+	 * @param array $array
1136
+	 * @return bool
1137
+	 */
1138
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
+	{
1140
+		return ! empty($array)
1141
+			? array_keys($array) === range(0, count($array) - 1)
1142
+			: true;
1143
+	}
1144
+
1145
+
1146
+
1147
+	/**
1148
+	 * getReflectionClass
1149
+	 * checks if a ReflectionClass object has already been generated for a class
1150
+	 * and returns that instead of creating a new one
1151
+	 *
1152
+	 * @param string $class_name
1153
+	 * @return ReflectionClass
1154
+	 * @throws ReflectionException
1155
+	 */
1156
+	public function get_ReflectionClass($class_name)
1157
+	{
1158
+		if (
1159
+			! isset($this->_reflectors[$class_name])
1160
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
+		) {
1162
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
+		}
1164
+		return $this->_reflectors[$class_name];
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * _resolve_dependencies
1171
+	 * examines the constructor for the requested class to determine
1172
+	 * if any dependencies exist, and if they can be injected.
1173
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1174
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1175
+	 * For example:
1176
+	 *        if attempting to load a class "Foo" with the following constructor:
1177
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
+	 *        but only IF they are NOT already present in the incoming arguments array,
1180
+	 *        and the correct classes can be loaded
1181
+	 *
1182
+	 * @param ReflectionClass $reflector
1183
+	 * @param string          $class_name
1184
+	 * @param array           $arguments
1185
+	 * @return array
1186
+	 * @throws EE_Error
1187
+	 * @throws ReflectionException
1188
+	 */
1189
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
+	{
1191
+		// let's examine the constructor
1192
+		$constructor = $reflector->getConstructor();
1193
+		// whu? huh? nothing?
1194
+		if (! $constructor) {
1195
+			return $arguments;
1196
+		}
1197
+		// get constructor parameters
1198
+		$params = $constructor->getParameters();
1199
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
+		$argument_keys = array_keys($arguments);
1201
+		// now loop thru all of the constructors expected parameters
1202
+		foreach ($params as $index => $param) {
1203
+			// is this a dependency for a specific class ?
1204
+			$param_class = $param->getClass()
1205
+				? $param->getClass()->name
1206
+				: null;
1207
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1210
+				: $param_class;
1211
+			if (
1212
+				// param is not even a class
1213
+				$param_class === null
1214
+				// and something already exists in the incoming arguments for this param
1215
+				&& array_key_exists($index, $argument_keys)
1216
+				&& array_key_exists($argument_keys[$index], $arguments)
1217
+			) {
1218
+				// so let's skip this argument and move on to the next
1219
+				continue;
1220
+			}
1221
+			if (
1222
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
+				$param_class !== null
1224
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1226
+			) {
1227
+				// skip this argument and move on to the next
1228
+				continue;
1229
+			}
1230
+			if (
1231
+				// parameter is type hinted as a class, and should be injected
1232
+				$param_class !== null
1233
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
+			) {
1235
+				$arguments = $this->_resolve_dependency(
1236
+					$class_name,
1237
+					$param_class,
1238
+					$arguments,
1239
+					$index,
1240
+					$argument_keys
1241
+				);
1242
+			} else {
1243
+				try {
1244
+					$arguments[$index] = $param->isDefaultValueAvailable()
1245
+						? $param->getDefaultValue()
1246
+						: null;
1247
+				} catch (ReflectionException $e) {
1248
+					throw new ReflectionException(
1249
+						sprintf(
1250
+							esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
+							$e->getMessage(),
1252
+							$param->getName(),
1253
+							$class_name
1254
+						)
1255
+					);
1256
+				}
1257
+			}
1258
+		}
1259
+		return $arguments;
1260
+	}
1261
+
1262
+
1263
+
1264
+	/**
1265
+	 * @param string $class_name
1266
+	 * @param string $param_class
1267
+	 * @param array  $arguments
1268
+	 * @param mixed  $index
1269
+	 * @param array  $argument_keys
1270
+	 * @return array
1271
+	 * @throws EE_Error
1272
+	 * @throws ReflectionException
1273
+	 * @throws InvalidArgumentException
1274
+	 * @throws InvalidInterfaceException
1275
+	 * @throws InvalidDataTypeException
1276
+	 */
1277
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
+	{
1279
+		$dependency = null;
1280
+		// should dependency be loaded from cache ?
1281
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
+			$class_name,
1283
+			$param_class
1284
+		);
1285
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
+		// we might have a dependency...
1287
+		// let's MAYBE try and find it in our cache if that's what's been requested
1288
+		$cached_class = $cache_on
1289
+			? $this->_get_cached_class($param_class)
1290
+			: null;
1291
+		// and grab it if it exists
1292
+		if ($cached_class instanceof $param_class) {
1293
+			$dependency = $cached_class;
1294
+		} else if ($param_class !== $class_name) {
1295
+			// obtain the loader method from the dependency map
1296
+			$loader = $this->_dependency_map->class_loader($param_class);
1297
+			// is loader a custom closure ?
1298
+			if ($loader instanceof Closure) {
1299
+				$dependency = $loader($arguments);
1300
+			} else {
1301
+				// set the cache on property for the recursive loading call
1302
+				$this->_cache_on = $cache_on;
1303
+				// if not, then let's try and load it via the registry
1304
+				if ($loader && method_exists($this, $loader)) {
1305
+					$dependency = $this->{$loader}($param_class);
1306
+				} else {
1307
+					$dependency = LoaderFactory::getLoader()->load(
1308
+						$param_class,
1309
+						array(),
1310
+						$cache_on
1311
+					);
1312
+				}
1313
+			}
1314
+		}
1315
+		// did we successfully find the correct dependency ?
1316
+		if ($dependency instanceof $param_class) {
1317
+			// then let's inject it into the incoming array of arguments at the correct location
1318
+			$arguments[$index] = $dependency;
1319
+		}
1320
+		return $arguments;
1321
+	}
1322
+
1323
+
1324
+
1325
+	/**
1326
+	 * _set_cached_class
1327
+	 * attempts to cache the instantiated class locally
1328
+	 * in one of the following places, in the following order:
1329
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1330
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1331
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
+	 *
1334
+	 * @param object $class_obj
1335
+	 * @param string $class_name
1336
+	 * @param string $class_prefix
1337
+	 * @param bool   $from_db
1338
+	 * @return void
1339
+	 * @throws OutOfBoundsException
1340
+	 */
1341
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
+	{
1343
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
+			return;
1345
+		}
1346
+		// return newly instantiated class
1347
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
+		if ($class_abbreviation) {
1349
+			$this->{$class_abbreviation} = $class_obj;
1350
+			return;
1351
+		}
1352
+		$class_name = str_replace('\\', '_', $class_name);
1353
+		if (property_exists($this, $class_name)) {
1354
+			$this->{$class_name} = $class_obj;
1355
+			return;
1356
+		}
1357
+		if ($class_prefix === 'addon') {
1358
+			$this->addons->{$class_name} = $class_obj;
1359
+			return;
1360
+		}
1361
+		if (! $from_db) {
1362
+			$this->LIB->{$class_name} = $class_obj;
1363
+		}
1364
+	}
1365
+
1366
+
1367
+
1368
+	/**
1369
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
+	 *
1371
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1373
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
+	 * @param array  $arguments
1375
+	 * @return object
1376
+	 */
1377
+	public static function factory($classname, $arguments = array())
1378
+	{
1379
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1380
+		if ($loader instanceof Closure) {
1381
+			return $loader($arguments);
1382
+		}
1383
+		if (method_exists(self::instance(), $loader)) {
1384
+			return self::instance()->{$loader}($classname, $arguments);
1385
+		}
1386
+		return null;
1387
+	}
1388
+
1389
+
1390
+
1391
+	/**
1392
+	 * Gets the addon by its class name
1393
+	 *
1394
+	 * @param string $class_name
1395
+	 * @return EE_Addon
1396
+	 * @throws OutOfBoundsException
1397
+	 */
1398
+	public function getAddon($class_name)
1399
+	{
1400
+		$class_name = str_replace('\\', '_', $class_name);
1401
+		return $this->addons->{$class_name};
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * removes the addon from the internal cache
1407
+	 *
1408
+	 * @param string $class_name
1409
+	 * @return void
1410
+	 */
1411
+	public function removeAddon($class_name)
1412
+	{
1413
+		$class_name = str_replace('\\', '_', $class_name);
1414
+		unset($this->addons->{$class_name});
1415
+	}
1416
+
1417
+
1418
+
1419
+	/**
1420
+	 * Gets the addon by its name/slug (not classname. For that, just
1421
+	 * use the get_addon() method above
1422
+	 *
1423
+	 * @param string $name
1424
+	 * @return EE_Addon
1425
+	 */
1426
+	public function get_addon_by_name($name)
1427
+	{
1428
+		foreach ($this->addons as $addon) {
1429
+			if ($addon->name() === $name) {
1430
+				return $addon;
1431
+			}
1432
+		}
1433
+		return null;
1434
+	}
1435
+
1436
+
1437
+
1438
+	/**
1439
+	 * Gets an array of all the registered addons, where the keys are their names.
1440
+	 * (ie, what each returns for their name() function)
1441
+	 * They're already available on EE_Registry::instance()->addons as properties,
1442
+	 * where each property's name is the addon's classname,
1443
+	 * So if you just want to get the addon by classname,
1444
+	 * OR use the get_addon() method above.
1445
+	 * PLEASE  NOTE:
1446
+	 * addons with Fully Qualified Class Names
1447
+	 * have had the namespace separators converted to underscores,
1448
+	 * so a classname like Fully\Qualified\ClassName
1449
+	 * would have been converted to Fully_Qualified_ClassName
1450
+	 *
1451
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1452
+	 */
1453
+	public function get_addons_by_name()
1454
+	{
1455
+		$addons = array();
1456
+		foreach ($this->addons as $addon) {
1457
+			$addons[$addon->name()] = $addon;
1458
+		}
1459
+		return $addons;
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
+	 * a stale copy of it around
1466
+	 *
1467
+	 * @param string $model_name
1468
+	 * @return \EEM_Base
1469
+	 * @throws \EE_Error
1470
+	 */
1471
+	public function reset_model($model_name)
1472
+	{
1473
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1474
+			? "EEM_{$model_name}"
1475
+			: $model_name;
1476
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
+			return null;
1478
+		}
1479
+		//get that model reset it and make sure we nuke the old reference to it
1480
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
+			&& is_callable(
1482
+				array($model_class_name, 'reset')
1483
+			)) {
1484
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
+		} else {
1486
+			throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
+		}
1488
+		return $this->LIB->{$model_class_name};
1489
+	}
1490
+
1491
+
1492
+
1493
+	/**
1494
+	 * Resets the registry.
1495
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
+	 * - $_dependency_map
1498
+	 * - $_class_abbreviations
1499
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
+	 * - $REQ:  Still on the same request so no need to change.
1501
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1502
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
+	 *             switch or on the restore.
1507
+	 * - $modules
1508
+	 * - $shortcodes
1509
+	 * - $widgets
1510
+	 *
1511
+	 * @param boolean $hard             [deprecated]
1512
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
+	 *                                  client
1517
+	 *                                  code instead can just change the model context to a different blog id if
1518
+	 *                                  necessary
1519
+	 * @return EE_Registry
1520
+	 * @throws EE_Error
1521
+	 * @throws ReflectionException
1522
+	 */
1523
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
+	{
1525
+		$instance = self::instance();
1526
+		$instance->_cache_on = true;
1527
+		// reset some "special" classes
1528
+		EEH_Activation::reset();
1529
+		$hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
+		$instance->CART = null;
1532
+		$instance->MRM = null;
1533
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
+		//messages reset
1535
+		EED_Messages::reset();
1536
+		//handle of objects cached on LIB
1537
+		foreach (array('LIB', 'modules') as $cache) {
1538
+			foreach ($instance->{$cache} as $class_name => $class) {
1539
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1540
+					unset($instance->{$cache}->{$class_name});
1541
+				}
1542
+			}
1543
+		}
1544
+		return $instance;
1545
+	}
1546
+
1547
+
1548
+
1549
+	/**
1550
+	 * if passed object implements ResettableInterface, then call it's reset() method
1551
+	 * if passed object implements InterminableInterface, then return false,
1552
+	 * to indicate that it should NOT be cleared from the Registry cache
1553
+	 *
1554
+	 * @param      $object
1555
+	 * @param bool $reset_models
1556
+	 * @return bool returns true if cached object should be unset
1557
+	 */
1558
+	private static function _reset_and_unset_object($object, $reset_models)
1559
+	{
1560
+		if (! is_object($object)) {
1561
+			// don't unset anything that's not an object
1562
+			return false;
1563
+		}
1564
+		if ($object instanceof EED_Module) {
1565
+			$object::reset();
1566
+			// don't unset modules
1567
+			return false;
1568
+		}
1569
+		if ($object instanceof ResettableInterface) {
1570
+			if ($object instanceof EEM_Base) {
1571
+				if ($reset_models) {
1572
+					$object->reset();
1573
+					return true;
1574
+				}
1575
+				return false;
1576
+			}
1577
+			$object->reset();
1578
+			return true;
1579
+		}
1580
+		if (! $object instanceof InterminableInterface) {
1581
+			return true;
1582
+		}
1583
+		return false;
1584
+	}
1585
+
1586
+
1587
+
1588
+	/**
1589
+	 * Gets all the custom post type models defined
1590
+	 *
1591
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
+	 */
1593
+	public function cpt_models()
1594
+	{
1595
+		$cpt_models = array();
1596
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
+				$cpt_models[$short_name] = $classname;
1599
+			}
1600
+		}
1601
+		return $cpt_models;
1602
+	}
1603
+
1604
+
1605
+
1606
+	/**
1607
+	 * @return \EE_Config
1608
+	 */
1609
+	public static function CFG()
1610
+	{
1611
+		return self::instance()->CFG;
1612
+	}
1613 1613
 
1614 1614
 
1615 1615
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_CPT.core.php 2 patches
Indentation   +1432 added lines, -1432 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\services\request\middleware\RecommendedVersions;
4 4
 
5 5
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6
-    exit('No direct script access allowed');
6
+	exit('No direct script access allowed');
7 7
 }
8 8
 
9 9
 /**
@@ -28,470 +28,470 @@  discard block
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * This gets set in _setup_cpt
33
-     * It will contain the object for the custom post type.
34
-     *
35
-     * @var EE_CPT_Base
36
-     */
37
-    protected $_cpt_object;
38
-
39
-
40
-
41
-    /**
42
-     * a boolean flag to set whether the current route is a cpt route or not.
43
-     *
44
-     * @var bool
45
-     */
46
-    protected $_cpt_route = false;
47
-
48
-
49
-
50
-    /**
51
-     * This property allows cpt classes to define multiple routes as cpt routes.
52
-     * //in this array we define what the custom post type for this route is.
53
-     * array(
54
-     * 'route_name' => 'custom_post_type_slug'
55
-     * )
56
-     *
57
-     * @var array
58
-     */
59
-    protected $_cpt_routes = array();
60
-
31
+	/**
32
+	 * This gets set in _setup_cpt
33
+	 * It will contain the object for the custom post type.
34
+	 *
35
+	 * @var EE_CPT_Base
36
+	 */
37
+	protected $_cpt_object;
38
+
39
+
40
+
41
+	/**
42
+	 * a boolean flag to set whether the current route is a cpt route or not.
43
+	 *
44
+	 * @var bool
45
+	 */
46
+	protected $_cpt_route = false;
47
+
48
+
49
+
50
+	/**
51
+	 * This property allows cpt classes to define multiple routes as cpt routes.
52
+	 * //in this array we define what the custom post type for this route is.
53
+	 * array(
54
+	 * 'route_name' => 'custom_post_type_slug'
55
+	 * )
56
+	 *
57
+	 * @var array
58
+	 */
59
+	protected $_cpt_routes = array();
60
+
61 61
 
62 62
 
63
-    /**
64
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
65
-     * in this format:
66
-     * array(
67
-     * 'post_type_slug' => 'edit_route'
68
-     * )
69
-     *
70
-     * @var array
71
-     */
72
-    protected $_cpt_edit_routes = array();
73
-
74
-
75
-
76
-    /**
77
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
78
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
79
-     * _cpt_model_names property should be in the following format: array(
80
-     * 'route_defined_by_action_param' => 'Model_Name')
81
-     *
82
-     * @var array $_cpt_model_names
83
-     */
84
-    protected $_cpt_model_names = array();
85
-
86
-
87
-    /**
88
-     * @var EE_CPT_Base
89
-     */
90
-    protected $_cpt_model_obj = false;
91
-
92
-
93
-
94
-    /**
95
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
96
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
97
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
98
-     * Registration of containers should be done before load_page_dependencies() is run.
99
-     *
100
-     * @var array()
101
-     */
102
-    protected $_autosave_containers = array();
103
-    protected $_autosave_fields = array();
104
-
105
-    /**
106
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
107
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
108
-     *
109
-     * @var array
110
-     */
111
-    protected $_pagenow_map;
112
-
113
-
114
-
115
-    /**
116
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
117
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
118
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
119
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
120
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
121
-     *
122
-     * @access protected
123
-     * @abstract
124
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
125
-     * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
126
-     * @return void
127
-     */
128
-    abstract protected function _insert_update_cpt_item($post_id, $post);
129
-
130
-
131
-
132
-    /**
133
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
134
-     *
135
-     * @abstract
136
-     * @access public
137
-     * @param  string $post_id The ID of the cpt that was trashed
138
-     * @return void
139
-     */
140
-    abstract public function trash_cpt_item($post_id);
141
-
142
-
143
-
144
-    /**
145
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
146
-     *
147
-     * @param  string $post_id theID of the cpt that was untrashed
148
-     * @return void
149
-     */
150
-    abstract public function restore_cpt_item($post_id);
151
-
152
-
153
-
154
-    /**
155
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
156
-     * from the db
157
-     *
158
-     * @param  string $post_id the ID of the cpt that was deleted
159
-     * @return void
160
-     */
161
-    abstract public function delete_cpt_item($post_id);
162
-
163
-
164
-
165
-    /**
166
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
-     *
168
-     * @access protected
169
-     * @return void
170
-     */
171
-    protected function _before_page_setup()
172
-    {
173
-        $page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
174
-        $this->_cpt_routes = array_merge(array(
175
-            'create_new' => $this->page_slug,
176
-            'edit'       => $this->page_slug,
177
-            'trash'      => $this->page_slug,
178
-        ), $this->_cpt_routes);
179
-        //let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
180
-        $this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[$this->_req_data['action']])
181
-            ? get_post_type_object($this->_cpt_routes[$this->_req_data['action']])
182
-            : get_post_type_object($page);
183
-        //tweak pagenow for page loading.
184
-        if ( ! $this->_pagenow_map) {
185
-            $this->_pagenow_map = array(
186
-                'create_new' => 'post-new.php',
187
-                'edit'       => 'post.php',
188
-                'trash'      => 'post.php',
189
-            );
190
-        }
191
-        add_action('current_screen', array($this, 'modify_pagenow'));
192
-        //TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
193
-        //get current page from autosave
194
-        $current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
195
-            ? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
196
-            : null;
197
-        $this->_current_page = isset($this->_req_data['current_page'])
198
-            ? $this->_req_data['current_page']
199
-            : $current_page;
200
-        //autosave... make sure its only for the correct page
201
-        //if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
202
-            //setup autosave ajax hook
203
-            //add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
204
-        //}
205
-    }
206
-
207
-
208
-
209
-    /**
210
-     * Simply ensure that we simulate the correct post route for cpt screens
211
-     *
212
-     * @param WP_Screen $current_screen
213
-     * @return void
214
-     */
215
-    public function modify_pagenow($current_screen)
216
-    {
217
-        global $pagenow, $hook_suffix;
218
-        //possibly reset pagenow.
219
-        if ( ! empty($this->_req_data['page'])
220
-             && $this->_req_data['page'] == $this->page_slug
221
-             && ! empty($this->_req_data['action'])
222
-             && isset($this->_pagenow_map[$this->_req_data['action']])
223
-        ) {
224
-            $pagenow = $this->_pagenow_map[$this->_req_data['action']];
225
-            $hook_suffix = $pagenow;
226
-        }
227
-    }
228
-
229
-
230
-
231
-    /**
232
-     * This method is used to register additional autosave containers to the _autosave_containers property.
233
-     *
234
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
235
-     *       automatically register the id for the post metabox as a container.
236
-     * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
237
-     *                    you would send along the id of a metabox container.
238
-     * @return void
239
-     */
240
-    protected function _register_autosave_containers($ids)
241
-    {
242
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
243
-    }
244
-
245
-
246
-
247
-    /**
248
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
249
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
250
-     */
251
-    protected function _set_autosave_containers()
252
-    {
253
-        global $wp_meta_boxes;
254
-        $containers = array();
255
-        if (empty($wp_meta_boxes)) {
256
-            return;
257
-        }
258
-        $current_metaboxes = isset($wp_meta_boxes[$this->page_slug]) ? $wp_meta_boxes[$this->page_slug] : array();
259
-        foreach ($current_metaboxes as $box_context) {
260
-            foreach ($box_context as $box_details) {
261
-                foreach ($box_details as $box) {
262
-                    if (
263
-                        is_array($box['callback'])
264
-                        && (
265
-                            $box['callback'][0] instanceof EE_Admin_Page
266
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
267
-                        )
268
-                    ) {
269
-                        $containers[] = $box['id'];
270
-                    }
271
-                }
272
-            }
273
-        }
274
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
275
-        //add hidden inputs container
276
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
277
-    }
278
-
279
-
280
-
281
-    protected function _load_autosave_scripts_styles()
282
-    {
283
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
63
+	/**
64
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
65
+	 * in this format:
66
+	 * array(
67
+	 * 'post_type_slug' => 'edit_route'
68
+	 * )
69
+	 *
70
+	 * @var array
71
+	 */
72
+	protected $_cpt_edit_routes = array();
73
+
74
+
75
+
76
+	/**
77
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
78
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
79
+	 * _cpt_model_names property should be in the following format: array(
80
+	 * 'route_defined_by_action_param' => 'Model_Name')
81
+	 *
82
+	 * @var array $_cpt_model_names
83
+	 */
84
+	protected $_cpt_model_names = array();
85
+
86
+
87
+	/**
88
+	 * @var EE_CPT_Base
89
+	 */
90
+	protected $_cpt_model_obj = false;
91
+
92
+
93
+
94
+	/**
95
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
96
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
97
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
98
+	 * Registration of containers should be done before load_page_dependencies() is run.
99
+	 *
100
+	 * @var array()
101
+	 */
102
+	protected $_autosave_containers = array();
103
+	protected $_autosave_fields = array();
104
+
105
+	/**
106
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
107
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
108
+	 *
109
+	 * @var array
110
+	 */
111
+	protected $_pagenow_map;
112
+
113
+
114
+
115
+	/**
116
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
117
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
118
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
119
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
120
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
121
+	 *
122
+	 * @access protected
123
+	 * @abstract
124
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
125
+	 * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
126
+	 * @return void
127
+	 */
128
+	abstract protected function _insert_update_cpt_item($post_id, $post);
129
+
130
+
131
+
132
+	/**
133
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
134
+	 *
135
+	 * @abstract
136
+	 * @access public
137
+	 * @param  string $post_id The ID of the cpt that was trashed
138
+	 * @return void
139
+	 */
140
+	abstract public function trash_cpt_item($post_id);
141
+
142
+
143
+
144
+	/**
145
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
146
+	 *
147
+	 * @param  string $post_id theID of the cpt that was untrashed
148
+	 * @return void
149
+	 */
150
+	abstract public function restore_cpt_item($post_id);
151
+
152
+
153
+
154
+	/**
155
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
156
+	 * from the db
157
+	 *
158
+	 * @param  string $post_id the ID of the cpt that was deleted
159
+	 * @return void
160
+	 */
161
+	abstract public function delete_cpt_item($post_id);
162
+
163
+
164
+
165
+	/**
166
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
+	 *
168
+	 * @access protected
169
+	 * @return void
170
+	 */
171
+	protected function _before_page_setup()
172
+	{
173
+		$page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
174
+		$this->_cpt_routes = array_merge(array(
175
+			'create_new' => $this->page_slug,
176
+			'edit'       => $this->page_slug,
177
+			'trash'      => $this->page_slug,
178
+		), $this->_cpt_routes);
179
+		//let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
180
+		$this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[$this->_req_data['action']])
181
+			? get_post_type_object($this->_cpt_routes[$this->_req_data['action']])
182
+			: get_post_type_object($page);
183
+		//tweak pagenow for page loading.
184
+		if ( ! $this->_pagenow_map) {
185
+			$this->_pagenow_map = array(
186
+				'create_new' => 'post-new.php',
187
+				'edit'       => 'post.php',
188
+				'trash'      => 'post.php',
189
+			);
190
+		}
191
+		add_action('current_screen', array($this, 'modify_pagenow'));
192
+		//TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
193
+		//get current page from autosave
194
+		$current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
195
+			? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
196
+			: null;
197
+		$this->_current_page = isset($this->_req_data['current_page'])
198
+			? $this->_req_data['current_page']
199
+			: $current_page;
200
+		//autosave... make sure its only for the correct page
201
+		//if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
202
+			//setup autosave ajax hook
203
+			//add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
204
+		//}
205
+	}
206
+
207
+
208
+
209
+	/**
210
+	 * Simply ensure that we simulate the correct post route for cpt screens
211
+	 *
212
+	 * @param WP_Screen $current_screen
213
+	 * @return void
214
+	 */
215
+	public function modify_pagenow($current_screen)
216
+	{
217
+		global $pagenow, $hook_suffix;
218
+		//possibly reset pagenow.
219
+		if ( ! empty($this->_req_data['page'])
220
+			 && $this->_req_data['page'] == $this->page_slug
221
+			 && ! empty($this->_req_data['action'])
222
+			 && isset($this->_pagenow_map[$this->_req_data['action']])
223
+		) {
224
+			$pagenow = $this->_pagenow_map[$this->_req_data['action']];
225
+			$hook_suffix = $pagenow;
226
+		}
227
+	}
228
+
229
+
230
+
231
+	/**
232
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
233
+	 *
234
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
235
+	 *       automatically register the id for the post metabox as a container.
236
+	 * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
237
+	 *                    you would send along the id of a metabox container.
238
+	 * @return void
239
+	 */
240
+	protected function _register_autosave_containers($ids)
241
+	{
242
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
243
+	}
244
+
245
+
246
+
247
+	/**
248
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
249
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
250
+	 */
251
+	protected function _set_autosave_containers()
252
+	{
253
+		global $wp_meta_boxes;
254
+		$containers = array();
255
+		if (empty($wp_meta_boxes)) {
256
+			return;
257
+		}
258
+		$current_metaboxes = isset($wp_meta_boxes[$this->page_slug]) ? $wp_meta_boxes[$this->page_slug] : array();
259
+		foreach ($current_metaboxes as $box_context) {
260
+			foreach ($box_context as $box_details) {
261
+				foreach ($box_details as $box) {
262
+					if (
263
+						is_array($box['callback'])
264
+						&& (
265
+							$box['callback'][0] instanceof EE_Admin_Page
266
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
267
+						)
268
+					) {
269
+						$containers[] = $box['id'];
270
+					}
271
+				}
272
+			}
273
+		}
274
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
275
+		//add hidden inputs container
276
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
277
+	}
278
+
279
+
280
+
281
+	protected function _load_autosave_scripts_styles()
282
+	{
283
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
284 284
         wp_enqueue_script('cpt-autosave');/**/ //todo re-enable when we start doing autosave again in 4.2
285 285
 
286
-        //filter _autosave_containers
287
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288
-            $this->_autosave_containers, $this);
289
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
-            $containers, $this);
291
-
292
-        wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
293
-            $containers); //todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
294
-
295
-        $unsaved_data_msg = array(
296
-            'eventmsg'     => sprintf(__("The changes you made to this %s will be lost if you navigate away from this page.",
297
-                'event_espresso'), $this->_cpt_object->labels->singular_name),
298
-            'inputChanged' => 0,
299
-        );
300
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
301
-    }
302
-
303
-
304
-
305
-    public function load_page_dependencies()
306
-    {
307
-        try {
308
-            $this->_load_page_dependencies();
309
-        } catch (EE_Error $e) {
310
-            $e->get_error();
311
-        }
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
-     *
319
-     * @access protected
320
-     * @return void
321
-     */
322
-    protected function _load_page_dependencies()
323
-    {
324
-        //we only add stuff if this is a cpt_route!
325
-        if ( ! $this->_cpt_route) {
326
-            parent::_load_page_dependencies();
327
-            return;
328
-        }
329
-        // now let's do some automatic filters into the wp_system
330
-        // and we'll check to make sure the CHILD class
331
-        // automatically has the required methods in place.
332
-        // the following filters are for setting all the redirects
333
-        // on DEFAULT WP custom post type actions
334
-        // let's add a hidden input to the post-edit form
335
-        // so we know when we have to trigger our custom redirects!
336
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
337
-        add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
338
-        // inject our Admin page nav tabs...
339
-        // let's make sure the nav tabs are set if they aren't already
340
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
341
-        add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
342
-        // modify the post_updated messages array
343
-        add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
344
-        // add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
345
-        // cpts use the same format for shortlinks as posts!
346
-        add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
347
-        // This basically allows us to change the title of the "publish" metabox area
348
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
349
-        if ( ! empty($this->_labels['publishbox'])) {
350
-            $box_label = is_array($this->_labels['publishbox'])
351
-                         && isset($this->_labels['publishbox'][$this->_req_action])
352
-                    ? $this->_labels['publishbox'][$this->_req_action]
353
-                    : $this->_labels['publishbox'];
354
-            add_meta_box(
355
-                'submitdiv',
356
-                $box_label,
357
-                'post_submit_meta_box',
358
-                $this->_cpt_routes[$this->_req_action],
359
-                'side',
360
-                'core'
361
-            );
362
-        }
363
-        //let's add page_templates metabox if this cpt added support for it.
364
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
365
-            add_meta_box(
366
-                'page_templates',
367
-                __('Page Template', 'event_espresso'),
368
-                array($this, 'page_template_meta_box'),
369
-                $this->_cpt_routes[$this->_req_action],
370
-                'side',
371
-                'default'
372
-            );
373
-        }
374
-        //this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
375
-        if (method_exists($this, 'extra_permalink_field_buttons')) {
376
-            add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
377
-        }
378
-        //add preview button
379
-        add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
380
-        //insert our own post_stati dropdown
381
-        add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
382
-        //This allows adding additional information to the publish post submitbox on the wp post edit form
383
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
384
-            add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
385
-        }
386
-        // This allows for adding additional stuff after the title field on the wp post edit form.
387
-        // This is also before the wp_editor for post description field.
388
-        if (method_exists($this, 'edit_form_after_title')) {
389
-            add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
390
-        }
391
-        /**
392
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
393
-         */
394
-        add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
395
-        parent::_load_page_dependencies();
396
-        // notice we are ALSO going to load the pagenow hook set for this route
397
-        // (see _before_page_setup for the reset of the pagenow global ).
398
-        // This is for any plugins that are doing things properly
399
-        // and hooking into the load page hook for core wp cpt routes.
400
-        global $pagenow;
401
-        do_action('load-' . $pagenow);
402
-        $this->modify_current_screen();
403
-        add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404
-        //we route REALLY early.
405
-        try {
406
-            $this->_route_admin_request();
407
-        } catch (EE_Error $e) {
408
-            $e->get_error();
409
-        }
410
-    }
411
-
412
-
413
-
414
-    /**
415
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
-     * route instead.
418
-     *
419
-     * @param string $good_protocol_url The escaped url.
420
-     * @param string $original_url      The original url.
421
-     * @param string $_context          The context sent to the esc_url method.
422
-     * @return string possibly a new url for our route.
423
-     */
424
-    public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
-    {
426
-        $routes_to_match = array(
427
-            0 => array(
428
-                'edit.php?post_type=espresso_attendees',
429
-                'admin.php?page=espresso_registrations&action=contact_list',
430
-            ),
431
-            1 => array(
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
434
-            ),
435
-        );
436
-        foreach ($routes_to_match as $route_matches) {
437
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
-            }
440
-        }
441
-        return $good_protocol_url;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     * Determine whether the current cpt supports page templates or not.
448
-     *
449
-     * @since %VER%
450
-     * @param string $cpt_name The cpt slug we're checking on.
451
-     * @return bool True supported, false not.
452
-     */
453
-    private function _supports_page_templates($cpt_name)
454
-    {
455
-
456
-        $cpt_args = EE_Register_CPTs::get_CPTs();
457
-        $cpt_args = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : array();
458
-        $cpt_has_support = ! empty($cpt_args['page_templates']);
459
-
460
-        //if the installed version of WP is > 4.7 we do some additional checks.
461
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
462
-            $post_templates = wp_get_theme()->get_post_templates();
463
-            //if there are $post_templates for this cpt, then we return false for this method because
464
-            //that means we aren't going to load our page template manager and leave that up to the native
465
-            //cpt template manager.
466
-            $cpt_has_support = ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
467
-        }
468
-
469
-        return $cpt_has_support;
470
-    }
471
-
472
-
473
-    /**
474
-     * Callback for the page_templates metabox selector.
475
-     *
476
-     * @since %VER%
477
-     * @return void
478
-     */
479
-    public function page_template_meta_box()
480
-    {
481
-        global $post;
482
-        $template = '';
483
-
484
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
485
-            $page_template_count = count(get_page_templates());
486
-        } else {
487
-            $page_template_count = count(get_page_templates($post));
488
-        };
489
-
490
-        if ($page_template_count) {
491
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
492
-            $template      = ! empty($page_template) ? $page_template : '';
493
-        }
494
-        ?>
286
+		//filter _autosave_containers
287
+		$containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288
+			$this->_autosave_containers, $this);
289
+		$containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
+			$containers, $this);
291
+
292
+		wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
293
+			$containers); //todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
294
+
295
+		$unsaved_data_msg = array(
296
+			'eventmsg'     => sprintf(__("The changes you made to this %s will be lost if you navigate away from this page.",
297
+				'event_espresso'), $this->_cpt_object->labels->singular_name),
298
+			'inputChanged' => 0,
299
+		);
300
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
301
+	}
302
+
303
+
304
+
305
+	public function load_page_dependencies()
306
+	{
307
+		try {
308
+			$this->_load_page_dependencies();
309
+		} catch (EE_Error $e) {
310
+			$e->get_error();
311
+		}
312
+	}
313
+
314
+
315
+
316
+	/**
317
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
+	 *
319
+	 * @access protected
320
+	 * @return void
321
+	 */
322
+	protected function _load_page_dependencies()
323
+	{
324
+		//we only add stuff if this is a cpt_route!
325
+		if ( ! $this->_cpt_route) {
326
+			parent::_load_page_dependencies();
327
+			return;
328
+		}
329
+		// now let's do some automatic filters into the wp_system
330
+		// and we'll check to make sure the CHILD class
331
+		// automatically has the required methods in place.
332
+		// the following filters are for setting all the redirects
333
+		// on DEFAULT WP custom post type actions
334
+		// let's add a hidden input to the post-edit form
335
+		// so we know when we have to trigger our custom redirects!
336
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
337
+		add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
338
+		// inject our Admin page nav tabs...
339
+		// let's make sure the nav tabs are set if they aren't already
340
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
341
+		add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
342
+		// modify the post_updated messages array
343
+		add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
344
+		// add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
345
+		// cpts use the same format for shortlinks as posts!
346
+		add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
347
+		// This basically allows us to change the title of the "publish" metabox area
348
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
349
+		if ( ! empty($this->_labels['publishbox'])) {
350
+			$box_label = is_array($this->_labels['publishbox'])
351
+						 && isset($this->_labels['publishbox'][$this->_req_action])
352
+					? $this->_labels['publishbox'][$this->_req_action]
353
+					: $this->_labels['publishbox'];
354
+			add_meta_box(
355
+				'submitdiv',
356
+				$box_label,
357
+				'post_submit_meta_box',
358
+				$this->_cpt_routes[$this->_req_action],
359
+				'side',
360
+				'core'
361
+			);
362
+		}
363
+		//let's add page_templates metabox if this cpt added support for it.
364
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
365
+			add_meta_box(
366
+				'page_templates',
367
+				__('Page Template', 'event_espresso'),
368
+				array($this, 'page_template_meta_box'),
369
+				$this->_cpt_routes[$this->_req_action],
370
+				'side',
371
+				'default'
372
+			);
373
+		}
374
+		//this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
375
+		if (method_exists($this, 'extra_permalink_field_buttons')) {
376
+			add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
377
+		}
378
+		//add preview button
379
+		add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
380
+		//insert our own post_stati dropdown
381
+		add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
382
+		//This allows adding additional information to the publish post submitbox on the wp post edit form
383
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
384
+			add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
385
+		}
386
+		// This allows for adding additional stuff after the title field on the wp post edit form.
387
+		// This is also before the wp_editor for post description field.
388
+		if (method_exists($this, 'edit_form_after_title')) {
389
+			add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
390
+		}
391
+		/**
392
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
393
+		 */
394
+		add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
395
+		parent::_load_page_dependencies();
396
+		// notice we are ALSO going to load the pagenow hook set for this route
397
+		// (see _before_page_setup for the reset of the pagenow global ).
398
+		// This is for any plugins that are doing things properly
399
+		// and hooking into the load page hook for core wp cpt routes.
400
+		global $pagenow;
401
+		do_action('load-' . $pagenow);
402
+		$this->modify_current_screen();
403
+		add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404
+		//we route REALLY early.
405
+		try {
406
+			$this->_route_admin_request();
407
+		} catch (EE_Error $e) {
408
+			$e->get_error();
409
+		}
410
+	}
411
+
412
+
413
+
414
+	/**
415
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
+	 * route instead.
418
+	 *
419
+	 * @param string $good_protocol_url The escaped url.
420
+	 * @param string $original_url      The original url.
421
+	 * @param string $_context          The context sent to the esc_url method.
422
+	 * @return string possibly a new url for our route.
423
+	 */
424
+	public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
+	{
426
+		$routes_to_match = array(
427
+			0 => array(
428
+				'edit.php?post_type=espresso_attendees',
429
+				'admin.php?page=espresso_registrations&action=contact_list',
430
+			),
431
+			1 => array(
432
+				'edit.php?post_type=' . $this->_cpt_object->name,
433
+				'admin.php?page=' . $this->_cpt_object->name,
434
+			),
435
+		);
436
+		foreach ($routes_to_match as $route_matches) {
437
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
+			}
440
+		}
441
+		return $good_protocol_url;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 * Determine whether the current cpt supports page templates or not.
448
+	 *
449
+	 * @since %VER%
450
+	 * @param string $cpt_name The cpt slug we're checking on.
451
+	 * @return bool True supported, false not.
452
+	 */
453
+	private function _supports_page_templates($cpt_name)
454
+	{
455
+
456
+		$cpt_args = EE_Register_CPTs::get_CPTs();
457
+		$cpt_args = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : array();
458
+		$cpt_has_support = ! empty($cpt_args['page_templates']);
459
+
460
+		//if the installed version of WP is > 4.7 we do some additional checks.
461
+		if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
462
+			$post_templates = wp_get_theme()->get_post_templates();
463
+			//if there are $post_templates for this cpt, then we return false for this method because
464
+			//that means we aren't going to load our page template manager and leave that up to the native
465
+			//cpt template manager.
466
+			$cpt_has_support = ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
467
+		}
468
+
469
+		return $cpt_has_support;
470
+	}
471
+
472
+
473
+	/**
474
+	 * Callback for the page_templates metabox selector.
475
+	 *
476
+	 * @since %VER%
477
+	 * @return void
478
+	 */
479
+	public function page_template_meta_box()
480
+	{
481
+		global $post;
482
+		$template = '';
483
+
484
+		if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
485
+			$page_template_count = count(get_page_templates());
486
+		} else {
487
+			$page_template_count = count(get_page_templates($post));
488
+		};
489
+
490
+		if ($page_template_count) {
491
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
492
+			$template      = ! empty($page_template) ? $page_template : '';
493
+		}
494
+		?>
495 495
         <p><strong><?php _e('Template') ?></strong></p>
496 496
         <label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select
497 497
             name="page_template" id="page_template">
@@ -499,450 +499,450 @@  discard block
 block discarded – undo
499 499
         <?php page_template_dropdown($template); ?>
500 500
     </select>
501 501
         <?php
502
-    }
503
-
504
-
505
-
506
-    /**
507
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
508
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
509
-     *
510
-     * @param  string $return    the current html
511
-     * @param  int    $id        the post id for the page
512
-     * @param  string $new_title What the title is
513
-     * @param  string $new_slug  what the slug is
514
-     * @return string            The new html string for the permalink area
515
-     */
516
-    public function preview_button_html($return, $id, $new_title, $new_slug)
517
-    {
518
-        $post = get_post($id);
519
-        if ('publish' !== get_post_status($post)) {
520
-            //include shims for the `get_preview_post_link` function
521
-            require_once( EE_CORE . 'wordpress-shims.php' );
522
-            $return .= '<span_id="view-post-btn"><a target="_blank" href="'
523
-                       . get_preview_post_link($id)
524
-                       . '" class="button button-small">'
525
-                       . __('Preview', 'event_espresso')
526
-                       . '</a></span>'
527
-                       . "\n";
528
-        }
529
-        return $return;
530
-    }
531
-
532
-
533
-
534
-    /**
535
-     * add our custom post stati dropdown on the wp post page for this cpt
536
-     *
537
-     * @return void
538
-     */
539
-    public function custom_post_stati_dropdown()
540
-    {
541
-
542
-        $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
543
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
544
-            ? $statuses[$this->_cpt_model_obj->status()]
545
-            : '';
546
-        $template_args    = array(
547
-            'cur_status'            => $this->_cpt_model_obj->status(),
548
-            'statuses'              => $statuses,
549
-            'cur_status_label'      => $cur_status_label,
550
-            'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
551
-        );
552
-        //we'll add a trash post status (WP doesn't add one for some reason)
553
-        if ($this->_cpt_model_obj->status() === 'trash') {
554
-            $template_args['cur_status_label'] = __('Trashed', 'event_espresso');
555
-            $statuses['trash']                 = __('Trashed', 'event_espresso');
556
-            $template_args['statuses']         = $statuses;
557
-        }
558
-
559
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
560
-        EEH_Template::display_template($template, $template_args);
561
-    }
562
-
563
-
564
-
565
-    public function setup_autosave_hooks()
566
-    {
567
-        $this->_set_autosave_containers();
568
-        $this->_load_autosave_scripts_styles();
569
-    }
570
-
571
-
572
-
573
-    /**
574
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
575
-     * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
576
-     * for the nonce in here, but then this method looks for two things:
577
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
578
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
579
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
580
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
581
-     * template args.
582
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
583
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
584
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
585
-     *    $this->_template_args['data']['items'] = array(
586
-     *        'event-datetime-ids' => '1,2,3';
587
-     *    );
588
-     *    Keep in mind the following things:
589
-     *    - "where" index is for the input with the id as that string.
590
-     *    - "what" index is what will be used for the value of that input.
591
-     *
592
-     * @return void
593
-     */
594
-    public function do_extra_autosave_stuff()
595
-    {
596
-        //next let's check for the autosave nonce (we'll use _verify_nonce )
597
-        $nonce = isset($this->_req_data['autosavenonce'])
598
-                ? $this->_req_data['autosavenonce']
599
-                : null;
600
-        $this->_verify_nonce($nonce, 'autosave');
601
-        //make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
602
-        if ( ! defined('DOING_AUTOSAVE')) {
603
-            define('DOING_AUTOSAVE', true);
604
-        }
605
-        //if we made it here then the nonce checked out.  Let's run our methods and actions
606
-        $autosave = "_ee_autosave_{$this->_current_view}";
607
-        if (method_exists($this, $autosave)) {
608
-            $this->$autosave();
609
-        } else {
610
-            $this->_template_args['success'] = true;
611
-        }
612
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
614
-        //now let's return json
615
-        $this->_return_json();
616
-    }
617
-
618
-
619
-
620
-    /**
621
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
622
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
623
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
624
-     *
625
-     * @access protected
626
-     * @throws EE_Error
627
-     * @return void
628
-     */
629
-    protected function _extend_page_config_for_cpt()
630
-    {
631
-        //before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
632
-        if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
633
-            return;
634
-        }
635
-        //set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
636
-        if ( ! empty($this->_cpt_object)) {
637
-            $this->_page_routes = array_merge(array(
638
-                'create_new' => '_create_new_cpt_item',
639
-                'edit'       => '_edit_cpt_item',
640
-            ), $this->_page_routes);
641
-            $this->_page_config = array_merge(array(
642
-                'create_new' => array(
643
-                    'nav'           => array(
644
-                        'label' => $this->_cpt_object->labels->add_new_item,
645
-                        'order' => 5,
646
-                    ),
647
-                    'require_nonce' => false,
648
-                ),
649
-                'edit'       => array(
650
-                    'nav'           => array(
651
-                        'label'      => $this->_cpt_object->labels->edit_item,
652
-                        'order'      => 5,
653
-                        'persistent' => false,
654
-                        'url'        => '',
655
-                    ),
656
-                    'require_nonce' => false,
657
-                ),
658
-            ),
659
-                $this->_page_config
660
-            );
661
-        }
662
-        //load the next section only if this is a matching cpt route as set in the cpt routes array.
663
-        if ( ! isset($this->_cpt_routes[$this->_req_action])) {
664
-            return;
665
-        }
666
-        $this->_cpt_route = isset($this->_cpt_routes[$this->_req_action]) ? true : false;
667
-        //add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
668
-        if (empty($this->_cpt_object)) {
669
-            $msg = sprintf(__('This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).'),
670
-                $this->page_slug, $this->_req_action, get_class($this));
671
-            throw new EE_Error($msg);
672
-        }
673
-        if ($this->_cpt_route) {
674
-            $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
675
-            $this->_set_model_object($id);
676
-        }
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
-     *
684
-     * @access protected
685
-     * @param int  $id The id to retrieve the model object for. If empty we set a default object.
686
-     * @param bool $ignore_route_check
687
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
-     * @throws EE_Error
689
-     */
690
-    protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
691
-    {
692
-        $model = null;
693
-        if (
694
-            empty($this->_cpt_model_names)
695
-            || (
696
-                ! $ignore_route_check
697
-                && ! isset($this->_cpt_routes[$this->_req_action])
698
-            ) || (
699
-                $this->_cpt_model_obj instanceof EE_CPT_Base
700
-                && $this->_cpt_model_obj->ID() === $id
701
-            )
702
-        ) {
703
-            //get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
704
-            return;
705
-        }
706
-        //if ignore_route_check is true, then get the model name via EE_Register_CPTs
707
-        if ($ignore_route_check) {
708
-            $model_names = EE_Register_CPTs::get_cpt_model_names();
709
-            $post_type   = get_post_type($id);
710
-            if (isset($model_names[$post_type])) {
711
-                $model = EE_Registry::instance()->load_model($model_names[$post_type]);
712
-            }
713
-        } else {
714
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
715
-        }
716
-        if ($model instanceof EEM_Base) {
717
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
718
-        }
719
-        do_action(
720
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
721
-            $this->_cpt_model_obj,
722
-            $req_type
723
-        );
724
-    }
725
-
726
-
727
-
728
-    /**
729
-     * admin_init_global
730
-     * This runs all the code that we want executed within the WP admin_init hook.
731
-     * This method executes for ALL EE Admin pages.
732
-     *
733
-     * @access public
734
-     * @return void
735
-     */
736
-    public function admin_init_global()
737
-    {
738
-        $post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
739
-        //its possible this is a new save so let's catch that instead
740
-        $post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
741
-        $post_type = $post ? $post->post_type : false;
742
-        $current_route = isset($this->_req_data['current_route'])
743
-            ? $this->_req_data['current_route']
744
-            : 'shouldneverwork';
745
-        $route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
746
-            ? $this->_cpt_routes[$current_route]
747
-            : '';
748
-        add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
749
-        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
750
-        if ($post_type === $route_to_check) {
751
-            add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
752
-        }
753
-        //now let's filter redirect if we're on a revision page and the revision is for an event CPT.
754
-        $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
755
-        if ( ! empty($revision)) {
756
-            $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
757
-            //doing a restore?
758
-            if ( ! empty($action) && $action === 'restore') {
759
-                //get post for revision
760
-                $rev_post = get_post($revision);
761
-                $rev_parent = get_post($rev_post->post_parent);
762
-                //only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
763
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
764
-                    add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
765
-                    //restores of revisions
766
-                    add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
767
-                }
768
-            }
769
-        }
770
-        //NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
771
-        if ($post_type && $post_type === $route_to_check) {
772
-            //$post_id, $post
773
-            add_action('save_post', array($this, 'insert_update'), 10, 3);
774
-            //$post_id
775
-            add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
776
-            add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
777
-            add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
778
-            add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
779
-        }
780
-    }
781
-
782
-
783
-
784
-    /**
785
-     * Callback for the WordPress trashed_post hook.
786
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
787
-     *
788
-     * @param int $post_id
789
-     * @throws \EE_Error
790
-     */
791
-    public function before_trash_cpt_item($post_id)
792
-    {
793
-        $this->_set_model_object($post_id, true, 'trash');
794
-        //if our cpt object isn't existent then get out immediately.
795
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
796
-            return;
797
-        }
798
-        $this->trash_cpt_item($post_id);
799
-    }
800
-
801
-
802
-
803
-    /**
804
-     * Callback for the WordPress untrashed_post hook.
805
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
806
-     *
807
-     * @param $post_id
808
-     * @throws \EE_Error
809
-     */
810
-    public function before_restore_cpt_item($post_id)
811
-    {
812
-        $this->_set_model_object($post_id, true, 'restore');
813
-        //if our cpt object isn't existent then get out immediately.
814
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
815
-            return;
816
-        }
817
-        $this->restore_cpt_item($post_id);
818
-    }
819
-
820
-
821
-
822
-    /**
823
-     * Callback for the WordPress after_delete_post hook.
824
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
825
-     *
826
-     * @param $post_id
827
-     * @throws \EE_Error
828
-     */
829
-    public function before_delete_cpt_item($post_id)
830
-    {
831
-        $this->_set_model_object($post_id, true, 'delete');
832
-        //if our cpt object isn't existent then get out immediately.
833
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
834
-            return;
835
-        }
836
-        $this->delete_cpt_item($post_id);
837
-    }
838
-
839
-
840
-
841
-    /**
842
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
843
-     * accordingly.
844
-     *
845
-     * @access public
846
-     * @throws EE_Error
847
-     * @return void
848
-     */
849
-    public function verify_cpt_object()
850
-    {
851
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
852
-        // verify event object
853
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
854
-            throw new EE_Error(sprintf(__('Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
855
-                    'event_espresso'), $label));
856
-        }
857
-        //if auto-draft then throw an error
858
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
859
-            EE_Error::overwrite_errors();
860
-            EE_Error::add_error(sprintf(__('This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.'),
861
-                    $label), __FILE__, __FUNCTION__, __LINE__);
862
-        }
863
-    }
864
-
865
-
866
-
867
-    /**
868
-     * admin_footer_scripts_global
869
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
870
-     * will apply on ALL EE_Admin pages.
871
-     *
872
-     * @access public
873
-     * @return void
874
-     */
875
-    public function admin_footer_scripts_global()
876
-    {
877
-        $this->_add_admin_page_ajax_loading_img();
878
-        $this->_add_admin_page_overlay();
879
-    }
880
-
881
-
882
-
883
-    /**
884
-     * add in any global scripts for cpt routes
885
-     *
886
-     * @return void
887
-     */
888
-    public function load_global_scripts_styles()
889
-    {
890
-        parent::load_global_scripts_styles();
891
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
892
-            //setup custom post status object for localize script but only if we've got a cpt object
893
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
894
-            if ( ! empty($statuses)) {
895
-                //get ALL statuses!
896
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
897
-                //setup object
898
-                $ee_cpt_statuses = array();
899
-                foreach ($statuses as $status => $label) {
900
-                    $ee_cpt_statuses[$status] = array(
901
-                        'label'      => $label,
902
-                        'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
903
-                    );
904
-                }
905
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
906
-            }
907
-        }
908
-    }
909
-
910
-
911
-
912
-    /**
913
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
914
-     * insert/updates
915
-     *
916
-     * @param  int     $post_id ID of post being updated
917
-     * @param  WP_Post $post    Post object from WP
918
-     * @param  bool    $update  Whether this is an update or a new save.
919
-     * @return void
920
-     * @throws \EE_Error
921
-     */
922
-    public function insert_update($post_id, $post, $update)
923
-    {
924
-        //make sure that if this is a revision OR trash action that we don't do any updates!
925
-        if (
926
-            isset($this->_req_data['action'])
927
-            && (
928
-                $this->_req_data['action'] === 'restore'
929
-                || $this->_req_data['action'] === 'trash'
930
-            )
931
-        ) {
932
-            return;
933
-        }
934
-        $this->_set_model_object($post_id, true, 'insert_update');
935
-        //if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
936
-        if ($update
937
-            && (
938
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
939
-                || $this->_cpt_model_obj->ID() !== $post_id
940
-            )
941
-        ) {
942
-            return;
943
-        }
944
-        //check for autosave and update our req_data property accordingly.
945
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
502
+	}
503
+
504
+
505
+
506
+	/**
507
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
508
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
509
+	 *
510
+	 * @param  string $return    the current html
511
+	 * @param  int    $id        the post id for the page
512
+	 * @param  string $new_title What the title is
513
+	 * @param  string $new_slug  what the slug is
514
+	 * @return string            The new html string for the permalink area
515
+	 */
516
+	public function preview_button_html($return, $id, $new_title, $new_slug)
517
+	{
518
+		$post = get_post($id);
519
+		if ('publish' !== get_post_status($post)) {
520
+			//include shims for the `get_preview_post_link` function
521
+			require_once( EE_CORE . 'wordpress-shims.php' );
522
+			$return .= '<span_id="view-post-btn"><a target="_blank" href="'
523
+					   . get_preview_post_link($id)
524
+					   . '" class="button button-small">'
525
+					   . __('Preview', 'event_espresso')
526
+					   . '</a></span>'
527
+					   . "\n";
528
+		}
529
+		return $return;
530
+	}
531
+
532
+
533
+
534
+	/**
535
+	 * add our custom post stati dropdown on the wp post page for this cpt
536
+	 *
537
+	 * @return void
538
+	 */
539
+	public function custom_post_stati_dropdown()
540
+	{
541
+
542
+		$statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
543
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
544
+			? $statuses[$this->_cpt_model_obj->status()]
545
+			: '';
546
+		$template_args    = array(
547
+			'cur_status'            => $this->_cpt_model_obj->status(),
548
+			'statuses'              => $statuses,
549
+			'cur_status_label'      => $cur_status_label,
550
+			'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
551
+		);
552
+		//we'll add a trash post status (WP doesn't add one for some reason)
553
+		if ($this->_cpt_model_obj->status() === 'trash') {
554
+			$template_args['cur_status_label'] = __('Trashed', 'event_espresso');
555
+			$statuses['trash']                 = __('Trashed', 'event_espresso');
556
+			$template_args['statuses']         = $statuses;
557
+		}
558
+
559
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
560
+		EEH_Template::display_template($template, $template_args);
561
+	}
562
+
563
+
564
+
565
+	public function setup_autosave_hooks()
566
+	{
567
+		$this->_set_autosave_containers();
568
+		$this->_load_autosave_scripts_styles();
569
+	}
570
+
571
+
572
+
573
+	/**
574
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
575
+	 * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
576
+	 * for the nonce in here, but then this method looks for two things:
577
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
578
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
579
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
580
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
581
+	 * template args.
582
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
583
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
584
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
585
+	 *    $this->_template_args['data']['items'] = array(
586
+	 *        'event-datetime-ids' => '1,2,3';
587
+	 *    );
588
+	 *    Keep in mind the following things:
589
+	 *    - "where" index is for the input with the id as that string.
590
+	 *    - "what" index is what will be used for the value of that input.
591
+	 *
592
+	 * @return void
593
+	 */
594
+	public function do_extra_autosave_stuff()
595
+	{
596
+		//next let's check for the autosave nonce (we'll use _verify_nonce )
597
+		$nonce = isset($this->_req_data['autosavenonce'])
598
+				? $this->_req_data['autosavenonce']
599
+				: null;
600
+		$this->_verify_nonce($nonce, 'autosave');
601
+		//make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
602
+		if ( ! defined('DOING_AUTOSAVE')) {
603
+			define('DOING_AUTOSAVE', true);
604
+		}
605
+		//if we made it here then the nonce checked out.  Let's run our methods and actions
606
+		$autosave = "_ee_autosave_{$this->_current_view}";
607
+		if (method_exists($this, $autosave)) {
608
+			$this->$autosave();
609
+		} else {
610
+			$this->_template_args['success'] = true;
611
+		}
612
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
614
+		//now let's return json
615
+		$this->_return_json();
616
+	}
617
+
618
+
619
+
620
+	/**
621
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
622
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
623
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
624
+	 *
625
+	 * @access protected
626
+	 * @throws EE_Error
627
+	 * @return void
628
+	 */
629
+	protected function _extend_page_config_for_cpt()
630
+	{
631
+		//before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
632
+		if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
633
+			return;
634
+		}
635
+		//set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
636
+		if ( ! empty($this->_cpt_object)) {
637
+			$this->_page_routes = array_merge(array(
638
+				'create_new' => '_create_new_cpt_item',
639
+				'edit'       => '_edit_cpt_item',
640
+			), $this->_page_routes);
641
+			$this->_page_config = array_merge(array(
642
+				'create_new' => array(
643
+					'nav'           => array(
644
+						'label' => $this->_cpt_object->labels->add_new_item,
645
+						'order' => 5,
646
+					),
647
+					'require_nonce' => false,
648
+				),
649
+				'edit'       => array(
650
+					'nav'           => array(
651
+						'label'      => $this->_cpt_object->labels->edit_item,
652
+						'order'      => 5,
653
+						'persistent' => false,
654
+						'url'        => '',
655
+					),
656
+					'require_nonce' => false,
657
+				),
658
+			),
659
+				$this->_page_config
660
+			);
661
+		}
662
+		//load the next section only if this is a matching cpt route as set in the cpt routes array.
663
+		if ( ! isset($this->_cpt_routes[$this->_req_action])) {
664
+			return;
665
+		}
666
+		$this->_cpt_route = isset($this->_cpt_routes[$this->_req_action]) ? true : false;
667
+		//add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
668
+		if (empty($this->_cpt_object)) {
669
+			$msg = sprintf(__('This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).'),
670
+				$this->page_slug, $this->_req_action, get_class($this));
671
+			throw new EE_Error($msg);
672
+		}
673
+		if ($this->_cpt_route) {
674
+			$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
675
+			$this->_set_model_object($id);
676
+		}
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
+	 *
684
+	 * @access protected
685
+	 * @param int  $id The id to retrieve the model object for. If empty we set a default object.
686
+	 * @param bool $ignore_route_check
687
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
+	 * @throws EE_Error
689
+	 */
690
+	protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
691
+	{
692
+		$model = null;
693
+		if (
694
+			empty($this->_cpt_model_names)
695
+			|| (
696
+				! $ignore_route_check
697
+				&& ! isset($this->_cpt_routes[$this->_req_action])
698
+			) || (
699
+				$this->_cpt_model_obj instanceof EE_CPT_Base
700
+				&& $this->_cpt_model_obj->ID() === $id
701
+			)
702
+		) {
703
+			//get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
704
+			return;
705
+		}
706
+		//if ignore_route_check is true, then get the model name via EE_Register_CPTs
707
+		if ($ignore_route_check) {
708
+			$model_names = EE_Register_CPTs::get_cpt_model_names();
709
+			$post_type   = get_post_type($id);
710
+			if (isset($model_names[$post_type])) {
711
+				$model = EE_Registry::instance()->load_model($model_names[$post_type]);
712
+			}
713
+		} else {
714
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
715
+		}
716
+		if ($model instanceof EEM_Base) {
717
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
718
+		}
719
+		do_action(
720
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
721
+			$this->_cpt_model_obj,
722
+			$req_type
723
+		);
724
+	}
725
+
726
+
727
+
728
+	/**
729
+	 * admin_init_global
730
+	 * This runs all the code that we want executed within the WP admin_init hook.
731
+	 * This method executes for ALL EE Admin pages.
732
+	 *
733
+	 * @access public
734
+	 * @return void
735
+	 */
736
+	public function admin_init_global()
737
+	{
738
+		$post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
739
+		//its possible this is a new save so let's catch that instead
740
+		$post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
741
+		$post_type = $post ? $post->post_type : false;
742
+		$current_route = isset($this->_req_data['current_route'])
743
+			? $this->_req_data['current_route']
744
+			: 'shouldneverwork';
745
+		$route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
746
+			? $this->_cpt_routes[$current_route]
747
+			: '';
748
+		add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
749
+		add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
750
+		if ($post_type === $route_to_check) {
751
+			add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
752
+		}
753
+		//now let's filter redirect if we're on a revision page and the revision is for an event CPT.
754
+		$revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
755
+		if ( ! empty($revision)) {
756
+			$action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
757
+			//doing a restore?
758
+			if ( ! empty($action) && $action === 'restore') {
759
+				//get post for revision
760
+				$rev_post = get_post($revision);
761
+				$rev_parent = get_post($rev_post->post_parent);
762
+				//only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
763
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
764
+					add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
765
+					//restores of revisions
766
+					add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
767
+				}
768
+			}
769
+		}
770
+		//NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
771
+		if ($post_type && $post_type === $route_to_check) {
772
+			//$post_id, $post
773
+			add_action('save_post', array($this, 'insert_update'), 10, 3);
774
+			//$post_id
775
+			add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
776
+			add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
777
+			add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
778
+			add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
779
+		}
780
+	}
781
+
782
+
783
+
784
+	/**
785
+	 * Callback for the WordPress trashed_post hook.
786
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
787
+	 *
788
+	 * @param int $post_id
789
+	 * @throws \EE_Error
790
+	 */
791
+	public function before_trash_cpt_item($post_id)
792
+	{
793
+		$this->_set_model_object($post_id, true, 'trash');
794
+		//if our cpt object isn't existent then get out immediately.
795
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
796
+			return;
797
+		}
798
+		$this->trash_cpt_item($post_id);
799
+	}
800
+
801
+
802
+
803
+	/**
804
+	 * Callback for the WordPress untrashed_post hook.
805
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
806
+	 *
807
+	 * @param $post_id
808
+	 * @throws \EE_Error
809
+	 */
810
+	public function before_restore_cpt_item($post_id)
811
+	{
812
+		$this->_set_model_object($post_id, true, 'restore');
813
+		//if our cpt object isn't existent then get out immediately.
814
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
815
+			return;
816
+		}
817
+		$this->restore_cpt_item($post_id);
818
+	}
819
+
820
+
821
+
822
+	/**
823
+	 * Callback for the WordPress after_delete_post hook.
824
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
825
+	 *
826
+	 * @param $post_id
827
+	 * @throws \EE_Error
828
+	 */
829
+	public function before_delete_cpt_item($post_id)
830
+	{
831
+		$this->_set_model_object($post_id, true, 'delete');
832
+		//if our cpt object isn't existent then get out immediately.
833
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
834
+			return;
835
+		}
836
+		$this->delete_cpt_item($post_id);
837
+	}
838
+
839
+
840
+
841
+	/**
842
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
843
+	 * accordingly.
844
+	 *
845
+	 * @access public
846
+	 * @throws EE_Error
847
+	 * @return void
848
+	 */
849
+	public function verify_cpt_object()
850
+	{
851
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
852
+		// verify event object
853
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
854
+			throw new EE_Error(sprintf(__('Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
855
+					'event_espresso'), $label));
856
+		}
857
+		//if auto-draft then throw an error
858
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
859
+			EE_Error::overwrite_errors();
860
+			EE_Error::add_error(sprintf(__('This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.'),
861
+					$label), __FILE__, __FUNCTION__, __LINE__);
862
+		}
863
+	}
864
+
865
+
866
+
867
+	/**
868
+	 * admin_footer_scripts_global
869
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
870
+	 * will apply on ALL EE_Admin pages.
871
+	 *
872
+	 * @access public
873
+	 * @return void
874
+	 */
875
+	public function admin_footer_scripts_global()
876
+	{
877
+		$this->_add_admin_page_ajax_loading_img();
878
+		$this->_add_admin_page_overlay();
879
+	}
880
+
881
+
882
+
883
+	/**
884
+	 * add in any global scripts for cpt routes
885
+	 *
886
+	 * @return void
887
+	 */
888
+	public function load_global_scripts_styles()
889
+	{
890
+		parent::load_global_scripts_styles();
891
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
892
+			//setup custom post status object for localize script but only if we've got a cpt object
893
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
894
+			if ( ! empty($statuses)) {
895
+				//get ALL statuses!
896
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
897
+				//setup object
898
+				$ee_cpt_statuses = array();
899
+				foreach ($statuses as $status => $label) {
900
+					$ee_cpt_statuses[$status] = array(
901
+						'label'      => $label,
902
+						'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
903
+					);
904
+				}
905
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
906
+			}
907
+		}
908
+	}
909
+
910
+
911
+
912
+	/**
913
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
914
+	 * insert/updates
915
+	 *
916
+	 * @param  int     $post_id ID of post being updated
917
+	 * @param  WP_Post $post    Post object from WP
918
+	 * @param  bool    $update  Whether this is an update or a new save.
919
+	 * @return void
920
+	 * @throws \EE_Error
921
+	 */
922
+	public function insert_update($post_id, $post, $update)
923
+	{
924
+		//make sure that if this is a revision OR trash action that we don't do any updates!
925
+		if (
926
+			isset($this->_req_data['action'])
927
+			&& (
928
+				$this->_req_data['action'] === 'restore'
929
+				|| $this->_req_data['action'] === 'trash'
930
+			)
931
+		) {
932
+			return;
933
+		}
934
+		$this->_set_model_object($post_id, true, 'insert_update');
935
+		//if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
936
+		if ($update
937
+			&& (
938
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
939
+				|| $this->_cpt_model_obj->ID() !== $post_id
940
+			)
941
+		) {
942
+			return;
943
+		}
944
+		//check for autosave and update our req_data property accordingly.
945
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
946 946
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
947 947
 
948 948
                 foreach ( (array) $values as $key => $value ) {
@@ -952,542 +952,542 @@  discard block
 block discarded – undo
952 952
 
953 953
         }/**/ //TODO reactivate after autosave is implemented in 4.2
954 954
 
955
-        //take care of updating any selected page_template IF this cpt supports it.
956
-        if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
957
-            //wp version aware.
958
-            if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
959
-                $page_templates = wp_get_theme()->get_page_templates();
960
-            } else {
961
-                $post->page_template = $this->_req_data['page_template'];
962
-                $page_templates      = wp_get_theme()->get_page_templates($post);
963
-            }
964
-            if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[$this->_req_data['page_template']])) {
965
-                EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
966
-            } else {
967
-                update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
968
-            }
969
-        }
970
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
971
-            return;
972
-        } //TODO we'll remove this after reimplementing autosave in 4.2
973
-        $this->_insert_update_cpt_item($post_id, $post);
974
-    }
975
-
976
-
977
-
978
-    /**
979
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
980
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
981
-     * so we don't have to check for our CPT.
982
-     *
983
-     * @param  int $post_id ID of the post
984
-     * @return void
985
-     */
986
-    public function dont_permanently_delete_ee_cpts($post_id)
987
-    {
988
-        //only do this if we're actually processing one of our CPTs
989
-        //if our cpt object isn't existent then get out immediately.
990
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
991
-            return;
992
-        }
993
-        delete_post_meta($post_id, '_wp_trash_meta_status');
994
-        delete_post_meta($post_id, '_wp_trash_meta_time');
995
-        //our cpts may have comments so let's take care of that too
996
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
997
-    }
998
-
999
-
1000
-
1001
-    /**
1002
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1003
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1004
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1005
-     *
1006
-     * @param  int $post_id     ID of cpt item
1007
-     * @param  int $revision_id ID of revision being restored
1008
-     * @return void
1009
-     */
1010
-    public function restore_revision($post_id, $revision_id)
1011
-    {
1012
-        $this->_restore_cpt_item($post_id, $revision_id);
1013
-        //global action
1014
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015
-        //class specific action so you can limit hooking into a specific page.
1016
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * @see restore_revision() for details
1023
-     * @param  int $post_id     ID of cpt item
1024
-     * @param  int $revision_id ID of revision for item
1025
-     * @return void
1026
-     */
1027
-    abstract protected function _restore_cpt_item($post_id, $revision_id);
1028
-
1029
-
1030
-
1031
-    /**
1032
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1033
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1034
-     * To fix we have to reset the current_screen using the page_slug
1035
-     * (which is identical - or should be - to our registered_post_type id.)
1036
-     * Also, since the core WP file loads the admin_header.php for WP
1037
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1038
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1039
-     *
1040
-     * @return void
1041
-     */
1042
-    public function modify_current_screen()
1043
-    {
1044
-        //ONLY do this if the current page_route IS a cpt route
1045
-        if ( ! $this->_cpt_route) {
1046
-            return;
1047
-        }
1048
-        //routing things REALLY early b/c this is a cpt admin page
1049
-        set_current_screen($this->_cpt_routes[$this->_req_action]);
1050
-        $this->_current_screen       = get_current_screen();
1051
-        $this->_current_screen->base = 'event-espresso';
1052
-        $this->_add_help_tabs(); //we make sure we add any help tabs back in!
1053
-        /*try {
955
+		//take care of updating any selected page_template IF this cpt supports it.
956
+		if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
957
+			//wp version aware.
958
+			if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
959
+				$page_templates = wp_get_theme()->get_page_templates();
960
+			} else {
961
+				$post->page_template = $this->_req_data['page_template'];
962
+				$page_templates      = wp_get_theme()->get_page_templates($post);
963
+			}
964
+			if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[$this->_req_data['page_template']])) {
965
+				EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
966
+			} else {
967
+				update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
968
+			}
969
+		}
970
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
971
+			return;
972
+		} //TODO we'll remove this after reimplementing autosave in 4.2
973
+		$this->_insert_update_cpt_item($post_id, $post);
974
+	}
975
+
976
+
977
+
978
+	/**
979
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
980
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
981
+	 * so we don't have to check for our CPT.
982
+	 *
983
+	 * @param  int $post_id ID of the post
984
+	 * @return void
985
+	 */
986
+	public function dont_permanently_delete_ee_cpts($post_id)
987
+	{
988
+		//only do this if we're actually processing one of our CPTs
989
+		//if our cpt object isn't existent then get out immediately.
990
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
991
+			return;
992
+		}
993
+		delete_post_meta($post_id, '_wp_trash_meta_status');
994
+		delete_post_meta($post_id, '_wp_trash_meta_time');
995
+		//our cpts may have comments so let's take care of that too
996
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
997
+	}
998
+
999
+
1000
+
1001
+	/**
1002
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1003
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1004
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1005
+	 *
1006
+	 * @param  int $post_id     ID of cpt item
1007
+	 * @param  int $revision_id ID of revision being restored
1008
+	 * @return void
1009
+	 */
1010
+	public function restore_revision($post_id, $revision_id)
1011
+	{
1012
+		$this->_restore_cpt_item($post_id, $revision_id);
1013
+		//global action
1014
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015
+		//class specific action so you can limit hooking into a specific page.
1016
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * @see restore_revision() for details
1023
+	 * @param  int $post_id     ID of cpt item
1024
+	 * @param  int $revision_id ID of revision for item
1025
+	 * @return void
1026
+	 */
1027
+	abstract protected function _restore_cpt_item($post_id, $revision_id);
1028
+
1029
+
1030
+
1031
+	/**
1032
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1033
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1034
+	 * To fix we have to reset the current_screen using the page_slug
1035
+	 * (which is identical - or should be - to our registered_post_type id.)
1036
+	 * Also, since the core WP file loads the admin_header.php for WP
1037
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1038
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1039
+	 *
1040
+	 * @return void
1041
+	 */
1042
+	public function modify_current_screen()
1043
+	{
1044
+		//ONLY do this if the current page_route IS a cpt route
1045
+		if ( ! $this->_cpt_route) {
1046
+			return;
1047
+		}
1048
+		//routing things REALLY early b/c this is a cpt admin page
1049
+		set_current_screen($this->_cpt_routes[$this->_req_action]);
1050
+		$this->_current_screen       = get_current_screen();
1051
+		$this->_current_screen->base = 'event-espresso';
1052
+		$this->_add_help_tabs(); //we make sure we add any help tabs back in!
1053
+		/*try {
1054 1054
             $this->_route_admin_request();
1055 1055
         } catch ( EE_Error $e ) {
1056 1056
             $e->get_error();
1057 1057
         }/**/
1058
-    }
1059
-
1060
-
1061
-
1062
-    /**
1063
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1064
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1065
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1066
-     * default to be.
1067
-     *
1068
-     * @param string $title The new title (or existing if there is no editor_title defined)
1069
-     * @return string
1070
-     */
1071
-    public function add_custom_editor_default_title($title)
1072
-    {
1073
-        return isset($this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]])
1074
-            ? $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1075
-            : $title;
1076
-    }
1077
-
1078
-
1079
-
1080
-    /**
1081
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1082
-     *
1083
-     * @param string $shortlink   The already generated shortlink
1084
-     * @param int    $id          Post ID for this item
1085
-     * @param string $context     The context for the link
1086
-     * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1087
-     * @return string
1088
-     */
1089
-    public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1090
-    {
1091
-        if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092
-            $post = get_post($id);
1093
-            if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
-                $shortlink = home_url('?p=' . $post->ID);
1095
-            }
1096
-        }
1097
-        return $shortlink;
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1104
-     * already run in modify_current_screen())
1105
-     *
1106
-     * @return void
1107
-     */
1108
-    public function route_admin_request()
1109
-    {
1110
-        if ($this->_cpt_route) {
1111
-            return;
1112
-        }
1113
-        try {
1114
-            $this->_route_admin_request();
1115
-        } catch (EE_Error $e) {
1116
-            $e->get_error();
1117
-        }
1118
-    }
1119
-
1120
-
1121
-
1122
-    /**
1123
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1124
-     *
1125
-     * @return void
1126
-     */
1127
-    public function cpt_post_form_hidden_input()
1128
-    {
1129
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1130
-        //we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131
-        echo '<div id="ee-cpt-hidden-inputs">';
1132
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1134
-        echo '</div>';
1135
-    }
1136
-
1137
-
1138
-
1139
-    /**
1140
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1141
-     *
1142
-     * @param  string $location Original location url
1143
-     * @param  int    $status   Status for http header
1144
-     * @return string           new (or original) url to redirect to.
1145
-     */
1146
-    public function revision_redirect($location, $status)
1147
-    {
1148
-        //get revision
1149
-        $rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1150
-        //can't do anything without revision so let's get out if not present
1151
-        if (empty($rev_id)) {
1152
-            return $location;
1153
-        }
1154
-        //get rev_post_data
1155
-        $rev = get_post($rev_id);
1156
-        $admin_url = $this->_admin_base_url;
1157
-        $query_args = array(
1158
-            'action'   => 'edit',
1159
-            'post'     => $rev->post_parent,
1160
-            'revision' => $rev_id,
1161
-            'message'  => 5,
1162
-        );
1163
-        $this->_process_notices($query_args, true);
1164
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1171
-     *
1172
-     * @param  string $link    the original generated link
1173
-     * @param  int    $id      post id
1174
-     * @param  string $context optional, defaults to display.  How to write the '&'
1175
-     * @return string          the link
1176
-     */
1177
-    public function modify_edit_post_link($link, $id, $context)
1178
-    {
1179
-        $post = get_post($id);
1180
-        if ( ! isset($this->_req_data['action'])
1181
-             || ! isset($this->_cpt_routes[$this->_req_data['action']])
1182
-             || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1183
-        ) {
1184
-            return $link;
1185
-        }
1186
-        $query_args = array(
1187
-            'action' => isset($this->_cpt_edit_routes[$post->post_type])
1188
-                ? $this->_cpt_edit_routes[$post->post_type]
1189
-                : 'edit',
1190
-            'post'   => $id,
1191
-        );
1192
-        return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1198
-     * our routes.
1199
-     *
1200
-     * @param  string $delete_link  original delete link
1201
-     * @param  int    $post_id      id of cpt object
1202
-     * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1203
-     * @return string new delete link
1204
-     * @throws EE_Error
1205
-     */
1206
-    public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1207
-    {
1208
-        $post = get_post($post_id);
1209
-
1210
-        if (empty($this->_req_data['action'])
1211
-            || ! isset($this->_cpt_routes[$this->_req_data['action']])
1212
-            || ! $post instanceof WP_Post
1213
-            || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1214
-        ) {
1215
-            return $delete_link;
1216
-        }
1217
-        $this->_set_model_object($post->ID, true);
1218
-
1219
-        //returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221
-
1222
-        return EE_Admin_Page::add_query_args_and_nonce(
1223
-            array(
1224
-                'page' => $this->_req_data['page'],
1225
-                'action' => $action,
1226
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1227
-                    => $post->ID
1228
-            ),
1229
-            admin_url()
1230
-        );
1231
-    }
1232
-
1233
-
1234
-
1235
-    /**
1236
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1237
-     * so that we can hijack the default redirect locations for wp custom post types
1238
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1239
-     *
1240
-     * @param  string $location This is the incoming currently set redirect location
1241
-     * @param  string $post_id  This is the 'ID' value of the wp_posts table
1242
-     * @return string           the new location to redirect to
1243
-     */
1244
-    public function cpt_post_location_redirect($location, $post_id)
1245
-    {
1246
-        //we DO have a match so let's setup the url
1247
-        //we have to get the post to determine our route
1248
-        $post       = get_post($post_id);
1249
-        $edit_route = $this->_cpt_edit_routes[$post->post_type];
1250
-        //shared query_args
1251
-        $query_args = array('action' => $edit_route, 'post' => $post_id);
1252
-        $admin_url  = $this->_admin_base_url;
1253
-        if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1254
-            $status = get_post_status($post_id);
1255
-            if (isset($this->_req_data['publish'])) {
1256
-                switch ($status) {
1257
-                    case 'pending':
1258
-                        $message = 8;
1259
-                        break;
1260
-                    case 'future':
1261
-                        $message = 9;
1262
-                        break;
1263
-                    default:
1264
-                        $message = 6;
1265
-                }
1266
-            } else {
1267
-                $message = 'draft' === $status ? 10 : 1;
1268
-            }
1269
-        } else if (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1270
-            $message = 2;
1271
-            //			$append = '#postcustom';
1272
-        } else if (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1273
-            $message = 3;
1274
-            //			$append = '#postcustom';
1275
-        } elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1276
-            $message = 7;
1277
-        } else {
1278
-            $message = 4;
1279
-        }
1280
-        //change the message if the post type is not viewable on the frontend
1281
-        $this->_cpt_object = get_post_type_object($post->post_type);
1282
-        $message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1283
-        $query_args = array_merge(array('message' => $message), $query_args);
1284
-        $this->_process_notices($query_args, true);
1285
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1286
-    }
1287
-
1288
-
1289
-
1290
-    /**
1291
-     * This method is called to inject nav tabs on core WP cpt pages
1292
-     *
1293
-     * @access public
1294
-     * @return void
1295
-     */
1296
-    public function inject_nav_tabs()
1297
-    {
1298
-        //can we hijack and insert the nav_tabs?
1299
-        $nav_tabs = $this->_get_main_nav_tabs();
1300
-        //first close off existing form tag
1301
-        $html = '>';
1302
-        $html .= $nav_tabs;
1303
-        //now let's handle the remaining tag ( missing ">" is CORRECT )
1304
-        $html .= '<span></span';
1305
-        echo $html;
1306
-    }
1307
-
1308
-
1309
-
1310
-    /**
1311
-     * This just sets up the post update messages when an update form is loaded
1312
-     *
1313
-     * @access public
1314
-     * @param  array $messages the original messages array
1315
-     * @return array           the new messages array
1316
-     */
1317
-    public function post_update_messages($messages)
1318
-    {
1319
-        global $post;
1320
-        $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1321
-        $id = empty($id) && is_object($post) ? $post->ID : null;
1322
-        //		$post_type = $post ? $post->post_type : false;
1323
-        /*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1058
+	}
1059
+
1060
+
1061
+
1062
+	/**
1063
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1064
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1065
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1066
+	 * default to be.
1067
+	 *
1068
+	 * @param string $title The new title (or existing if there is no editor_title defined)
1069
+	 * @return string
1070
+	 */
1071
+	public function add_custom_editor_default_title($title)
1072
+	{
1073
+		return isset($this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]])
1074
+			? $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1075
+			: $title;
1076
+	}
1077
+
1078
+
1079
+
1080
+	/**
1081
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1082
+	 *
1083
+	 * @param string $shortlink   The already generated shortlink
1084
+	 * @param int    $id          Post ID for this item
1085
+	 * @param string $context     The context for the link
1086
+	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1087
+	 * @return string
1088
+	 */
1089
+	public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1090
+	{
1091
+		if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092
+			$post = get_post($id);
1093
+			if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
+				$shortlink = home_url('?p=' . $post->ID);
1095
+			}
1096
+		}
1097
+		return $shortlink;
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1104
+	 * already run in modify_current_screen())
1105
+	 *
1106
+	 * @return void
1107
+	 */
1108
+	public function route_admin_request()
1109
+	{
1110
+		if ($this->_cpt_route) {
1111
+			return;
1112
+		}
1113
+		try {
1114
+			$this->_route_admin_request();
1115
+		} catch (EE_Error $e) {
1116
+			$e->get_error();
1117
+		}
1118
+	}
1119
+
1120
+
1121
+
1122
+	/**
1123
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1124
+	 *
1125
+	 * @return void
1126
+	 */
1127
+	public function cpt_post_form_hidden_input()
1128
+	{
1129
+		echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1130
+		//we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131
+		echo '<div id="ee-cpt-hidden-inputs">';
1132
+		echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
+		echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1134
+		echo '</div>';
1135
+	}
1136
+
1137
+
1138
+
1139
+	/**
1140
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1141
+	 *
1142
+	 * @param  string $location Original location url
1143
+	 * @param  int    $status   Status for http header
1144
+	 * @return string           new (or original) url to redirect to.
1145
+	 */
1146
+	public function revision_redirect($location, $status)
1147
+	{
1148
+		//get revision
1149
+		$rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1150
+		//can't do anything without revision so let's get out if not present
1151
+		if (empty($rev_id)) {
1152
+			return $location;
1153
+		}
1154
+		//get rev_post_data
1155
+		$rev = get_post($rev_id);
1156
+		$admin_url = $this->_admin_base_url;
1157
+		$query_args = array(
1158
+			'action'   => 'edit',
1159
+			'post'     => $rev->post_parent,
1160
+			'revision' => $rev_id,
1161
+			'message'  => 5,
1162
+		);
1163
+		$this->_process_notices($query_args, true);
1164
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1171
+	 *
1172
+	 * @param  string $link    the original generated link
1173
+	 * @param  int    $id      post id
1174
+	 * @param  string $context optional, defaults to display.  How to write the '&'
1175
+	 * @return string          the link
1176
+	 */
1177
+	public function modify_edit_post_link($link, $id, $context)
1178
+	{
1179
+		$post = get_post($id);
1180
+		if ( ! isset($this->_req_data['action'])
1181
+			 || ! isset($this->_cpt_routes[$this->_req_data['action']])
1182
+			 || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1183
+		) {
1184
+			return $link;
1185
+		}
1186
+		$query_args = array(
1187
+			'action' => isset($this->_cpt_edit_routes[$post->post_type])
1188
+				? $this->_cpt_edit_routes[$post->post_type]
1189
+				: 'edit',
1190
+			'post'   => $id,
1191
+		);
1192
+		return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1198
+	 * our routes.
1199
+	 *
1200
+	 * @param  string $delete_link  original delete link
1201
+	 * @param  int    $post_id      id of cpt object
1202
+	 * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1203
+	 * @return string new delete link
1204
+	 * @throws EE_Error
1205
+	 */
1206
+	public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1207
+	{
1208
+		$post = get_post($post_id);
1209
+
1210
+		if (empty($this->_req_data['action'])
1211
+			|| ! isset($this->_cpt_routes[$this->_req_data['action']])
1212
+			|| ! $post instanceof WP_Post
1213
+			|| $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1214
+		) {
1215
+			return $delete_link;
1216
+		}
1217
+		$this->_set_model_object($post->ID, true);
1218
+
1219
+		//returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221
+
1222
+		return EE_Admin_Page::add_query_args_and_nonce(
1223
+			array(
1224
+				'page' => $this->_req_data['page'],
1225
+				'action' => $action,
1226
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1227
+					=> $post->ID
1228
+			),
1229
+			admin_url()
1230
+		);
1231
+	}
1232
+
1233
+
1234
+
1235
+	/**
1236
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1237
+	 * so that we can hijack the default redirect locations for wp custom post types
1238
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1239
+	 *
1240
+	 * @param  string $location This is the incoming currently set redirect location
1241
+	 * @param  string $post_id  This is the 'ID' value of the wp_posts table
1242
+	 * @return string           the new location to redirect to
1243
+	 */
1244
+	public function cpt_post_location_redirect($location, $post_id)
1245
+	{
1246
+		//we DO have a match so let's setup the url
1247
+		//we have to get the post to determine our route
1248
+		$post       = get_post($post_id);
1249
+		$edit_route = $this->_cpt_edit_routes[$post->post_type];
1250
+		//shared query_args
1251
+		$query_args = array('action' => $edit_route, 'post' => $post_id);
1252
+		$admin_url  = $this->_admin_base_url;
1253
+		if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1254
+			$status = get_post_status($post_id);
1255
+			if (isset($this->_req_data['publish'])) {
1256
+				switch ($status) {
1257
+					case 'pending':
1258
+						$message = 8;
1259
+						break;
1260
+					case 'future':
1261
+						$message = 9;
1262
+						break;
1263
+					default:
1264
+						$message = 6;
1265
+				}
1266
+			} else {
1267
+				$message = 'draft' === $status ? 10 : 1;
1268
+			}
1269
+		} else if (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1270
+			$message = 2;
1271
+			//			$append = '#postcustom';
1272
+		} else if (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1273
+			$message = 3;
1274
+			//			$append = '#postcustom';
1275
+		} elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1276
+			$message = 7;
1277
+		} else {
1278
+			$message = 4;
1279
+		}
1280
+		//change the message if the post type is not viewable on the frontend
1281
+		$this->_cpt_object = get_post_type_object($post->post_type);
1282
+		$message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1283
+		$query_args = array_merge(array('message' => $message), $query_args);
1284
+		$this->_process_notices($query_args, true);
1285
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1286
+	}
1287
+
1288
+
1289
+
1290
+	/**
1291
+	 * This method is called to inject nav tabs on core WP cpt pages
1292
+	 *
1293
+	 * @access public
1294
+	 * @return void
1295
+	 */
1296
+	public function inject_nav_tabs()
1297
+	{
1298
+		//can we hijack and insert the nav_tabs?
1299
+		$nav_tabs = $this->_get_main_nav_tabs();
1300
+		//first close off existing form tag
1301
+		$html = '>';
1302
+		$html .= $nav_tabs;
1303
+		//now let's handle the remaining tag ( missing ">" is CORRECT )
1304
+		$html .= '<span></span';
1305
+		echo $html;
1306
+	}
1307
+
1308
+
1309
+
1310
+	/**
1311
+	 * This just sets up the post update messages when an update form is loaded
1312
+	 *
1313
+	 * @access public
1314
+	 * @param  array $messages the original messages array
1315
+	 * @return array           the new messages array
1316
+	 */
1317
+	public function post_update_messages($messages)
1318
+	{
1319
+		global $post;
1320
+		$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1321
+		$id = empty($id) && is_object($post) ? $post->ID : null;
1322
+		//		$post_type = $post ? $post->post_type : false;
1323
+		/*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1324 1324
 
1325 1325
         $route_to_check = $post_type && isset( $this->_cpt_routes[$current_route]) ? $this->_cpt_routes[$current_route] : '';/**/
1326
-        $messages[$post->post_type] = array(
1327
-            0 => '', //Unused. Messages start at index 1.
1328
-            1 => sprintf(
1329
-                __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330
-                $this->_cpt_object->labels->singular_name,
1331
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1332
-                '</a>'
1333
-            ),
1334
-            2 => __('Custom field updated'),
1335
-            3 => __('Custom field deleted.'),
1336
-            4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337
-            5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
-                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1339
-                : false,
1340
-            6 => sprintf(
1341
-                __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342
-                $this->_cpt_object->labels->singular_name,
1343
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1344
-                '</a>'
1345
-            ),
1346
-            7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347
-            8 => sprintf(
1348
-                __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349
-                $this->_cpt_object->labels->singular_name,
1350
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1351
-                '</a>'
1352
-            ),
1353
-            9 => sprintf(
1354
-                __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355
-                $this->_cpt_object->labels->singular_name,
1356
-                '<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1358
-                '</a>'
1359
-            ),
1360
-            10 => sprintf(
1361
-                __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362
-                $this->_cpt_object->labels->singular_name,
1363
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364
-                '</a>'
1365
-            ),
1366
-        );
1367
-        return $messages;
1368
-    }
1369
-
1370
-
1371
-
1372
-    /**
1373
-     * default method for the 'create_new' route for cpt admin pages.
1374
-     * For reference what to include in here, see wp-admin/post-new.php
1375
-     *
1376
-     * @access  protected
1377
-     * @return void
1378
-     */
1379
-    protected function _create_new_cpt_item()
1380
-    {
1381
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1382
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1383
-        $post_type        = $this->_cpt_routes[$this->_req_action];
1384
-        $post_type_object = $this->_cpt_object;
1385
-        $title            = $post_type_object->labels->add_new_item;
1386
-        $post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388
-        //modify the default editor title field with default title.
1389
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1390
-        $this->loadEditorTemplate(true);
1391
-    }
1392
-
1393
-
1394
-    /**
1395
-     * Enqueues auto-save and loads the editor template
1396
-     *
1397
-     * @param bool $creating
1398
-     */
1399
-    private function loadEditorTemplate($creating = true) {
1400
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1401
-        //these vars are used by the template
1402
-        $editing = true;
1403
-        $post_ID = $post->ID;
1404
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1405
-            //only enqueue autosave when creating event (necessary to get permalink/url generated)
1406
-            //otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1407
-            if ($creating) {
1408
-                wp_enqueue_script('autosave');
1409
-            } else {
1410
-                if (isset($this->_cpt_routes[$this->_req_data['action']])
1411
-                    && ! isset($this->_labels['hide_add_button_on_cpt_route'][$this->_req_data['action']])
1412
-                ) {
1413
-                    $create_new_action = apply_filters('FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1414
-                        'create_new', $this);
1415
-                    $post_new_file = EE_Admin_Page::add_query_args_and_nonce(array(
1416
-                        'action' => $create_new_action,
1417
-                        'page'   => $this->page_slug,
1418
-                    ), 'admin.php');
1419
-                }
1420
-            }
1421
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1422
-        }
1423
-    }
1424
-
1425
-
1426
-
1427
-    public function add_new_admin_page_global()
1428
-    {
1429
-        $admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1430
-        ?>
1326
+		$messages[$post->post_type] = array(
1327
+			0 => '', //Unused. Messages start at index 1.
1328
+			1 => sprintf(
1329
+				__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330
+				$this->_cpt_object->labels->singular_name,
1331
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1332
+				'</a>'
1333
+			),
1334
+			2 => __('Custom field updated'),
1335
+			3 => __('Custom field deleted.'),
1336
+			4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337
+			5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
+				$this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1339
+				: false,
1340
+			6 => sprintf(
1341
+				__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342
+				$this->_cpt_object->labels->singular_name,
1343
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1344
+				'</a>'
1345
+			),
1346
+			7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347
+			8 => sprintf(
1348
+				__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349
+				$this->_cpt_object->labels->singular_name,
1350
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1351
+				'</a>'
1352
+			),
1353
+			9 => sprintf(
1354
+				__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355
+				$this->_cpt_object->labels->singular_name,
1356
+				'<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1358
+				'</a>'
1359
+			),
1360
+			10 => sprintf(
1361
+				__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362
+				$this->_cpt_object->labels->singular_name,
1363
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364
+				'</a>'
1365
+			),
1366
+		);
1367
+		return $messages;
1368
+	}
1369
+
1370
+
1371
+
1372
+	/**
1373
+	 * default method for the 'create_new' route for cpt admin pages.
1374
+	 * For reference what to include in here, see wp-admin/post-new.php
1375
+	 *
1376
+	 * @access  protected
1377
+	 * @return void
1378
+	 */
1379
+	protected function _create_new_cpt_item()
1380
+	{
1381
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1382
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1383
+		$post_type        = $this->_cpt_routes[$this->_req_action];
1384
+		$post_type_object = $this->_cpt_object;
1385
+		$title            = $post_type_object->labels->add_new_item;
1386
+		$post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388
+		//modify the default editor title field with default title.
1389
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1390
+		$this->loadEditorTemplate(true);
1391
+	}
1392
+
1393
+
1394
+	/**
1395
+	 * Enqueues auto-save and loads the editor template
1396
+	 *
1397
+	 * @param bool $creating
1398
+	 */
1399
+	private function loadEditorTemplate($creating = true) {
1400
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1401
+		//these vars are used by the template
1402
+		$editing = true;
1403
+		$post_ID = $post->ID;
1404
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1405
+			//only enqueue autosave when creating event (necessary to get permalink/url generated)
1406
+			//otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1407
+			if ($creating) {
1408
+				wp_enqueue_script('autosave');
1409
+			} else {
1410
+				if (isset($this->_cpt_routes[$this->_req_data['action']])
1411
+					&& ! isset($this->_labels['hide_add_button_on_cpt_route'][$this->_req_data['action']])
1412
+				) {
1413
+					$create_new_action = apply_filters('FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1414
+						'create_new', $this);
1415
+					$post_new_file = EE_Admin_Page::add_query_args_and_nonce(array(
1416
+						'action' => $create_new_action,
1417
+						'page'   => $this->page_slug,
1418
+					), 'admin.php');
1419
+				}
1420
+			}
1421
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1422
+		}
1423
+	}
1424
+
1425
+
1426
+
1427
+	public function add_new_admin_page_global()
1428
+	{
1429
+		$admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1430
+		?>
1431 1431
         <script type="text/javascript">
1432 1432
             adminpage = '<?php echo $admin_page; ?>';
1433 1433
         </script>
1434 1434
         <?php
1435
-    }
1436
-
1437
-
1438
-
1439
-    /**
1440
-     * default method for the 'edit' route for cpt admin pages
1441
-     * For reference on what to put in here, refer to wp-admin/post.php
1442
-     *
1443
-     * @access protected
1444
-     * @return string   template for edit cpt form
1445
-     */
1446
-    protected function _edit_cpt_item()
1447
-    {
1448
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1449
-        $post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1450
-        $post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1451
-        if (empty ($post)) {
1452
-            wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?'));
1453
-        }
1454
-        if ( ! empty($_GET['get-post-lock'])) {
1455
-            wp_set_post_lock($post_id);
1456
-            wp_redirect(get_edit_post_link($post_id, 'url'));
1457
-            exit();
1458
-        }
1459
-
1460
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1461
-        $post_type        = $this->_cpt_routes[$this->_req_action];
1462
-        $post_type_object = $this->_cpt_object;
1463
-
1464
-        if ( ! wp_check_post_lock($post->ID)) {
1465
-            wp_set_post_lock($post->ID);
1466
-        }
1467
-        add_action('admin_footer', '_admin_notice_post_locked');
1468
-        if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1469
-            wp_enqueue_script('admin-comments');
1470
-            enqueue_comment_hotkeys_js();
1471
-        }
1472
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1473
-        //modify the default editor title field with default title.
1474
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1475
-        $this->loadEditorTemplate(false);
1476
-    }
1477
-
1478
-
1479
-
1480
-    /**
1481
-     * some getters
1482
-     */
1483
-    /**
1484
-     * This returns the protected _cpt_model_obj property
1485
-     *
1486
-     * @return EE_CPT_Base
1487
-     */
1488
-    public function get_cpt_model_obj()
1489
-    {
1490
-        return $this->_cpt_model_obj;
1491
-    }
1435
+	}
1436
+
1437
+
1438
+
1439
+	/**
1440
+	 * default method for the 'edit' route for cpt admin pages
1441
+	 * For reference on what to put in here, refer to wp-admin/post.php
1442
+	 *
1443
+	 * @access protected
1444
+	 * @return string   template for edit cpt form
1445
+	 */
1446
+	protected function _edit_cpt_item()
1447
+	{
1448
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1449
+		$post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1450
+		$post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1451
+		if (empty ($post)) {
1452
+			wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?'));
1453
+		}
1454
+		if ( ! empty($_GET['get-post-lock'])) {
1455
+			wp_set_post_lock($post_id);
1456
+			wp_redirect(get_edit_post_link($post_id, 'url'));
1457
+			exit();
1458
+		}
1459
+
1460
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1461
+		$post_type        = $this->_cpt_routes[$this->_req_action];
1462
+		$post_type_object = $this->_cpt_object;
1463
+
1464
+		if ( ! wp_check_post_lock($post->ID)) {
1465
+			wp_set_post_lock($post->ID);
1466
+		}
1467
+		add_action('admin_footer', '_admin_notice_post_locked');
1468
+		if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1469
+			wp_enqueue_script('admin-comments');
1470
+			enqueue_comment_hotkeys_js();
1471
+		}
1472
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1473
+		//modify the default editor title field with default title.
1474
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1475
+		$this->loadEditorTemplate(false);
1476
+	}
1477
+
1478
+
1479
+
1480
+	/**
1481
+	 * some getters
1482
+	 */
1483
+	/**
1484
+	 * This returns the protected _cpt_model_obj property
1485
+	 *
1486
+	 * @return EE_CPT_Base
1487
+	 */
1488
+	public function get_cpt_model_obj()
1489
+	{
1490
+		return $this->_cpt_model_obj;
1491
+	}
1492 1492
 
1493 1493
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
      */
240 240
     protected function _register_autosave_containers($ids)
241 241
     {
242
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
242
+        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
243 243
     }
244 244
 
245 245
 
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
         //filter _autosave_containers
287 287
         $containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288 288
             $this->_autosave_containers, $this);
289
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
289
+        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__'.get_class($this).'___load_autosave_scripts_styles__containers',
290 290
             $containers, $this);
291 291
 
292 292
         wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
         // This is for any plugins that are doing things properly
399 399
         // and hooking into the load page hook for core wp cpt routes.
400 400
         global $pagenow;
401
-        do_action('load-' . $pagenow);
401
+        do_action('load-'.$pagenow);
402 402
         $this->modify_current_screen();
403 403
         add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404 404
         //we route REALLY early.
@@ -429,8 +429,8 @@  discard block
 block discarded – undo
429 429
                 'admin.php?page=espresso_registrations&action=contact_list',
430 430
             ),
431 431
             1 => array(
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
432
+                'edit.php?post_type='.$this->_cpt_object->name,
433
+                'admin.php?page='.$this->_cpt_object->name,
434 434
             ),
435 435
         );
436 436
         foreach ($routes_to_match as $route_matches) {
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
         $cpt_has_support = ! empty($cpt_args['page_templates']);
459 459
 
460 460
         //if the installed version of WP is > 4.7 we do some additional checks.
461
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
461
+        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
462 462
             $post_templates = wp_get_theme()->get_post_templates();
463 463
             //if there are $post_templates for this cpt, then we return false for this method because
464 464
             //that means we aren't going to load our page template manager and leave that up to the native
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
         global $post;
482 482
         $template = '';
483 483
 
484
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
484
+        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
485 485
             $page_template_count = count(get_page_templates());
486 486
         } else {
487 487
             $page_template_count = count(get_page_templates($post));
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
         $post = get_post($id);
519 519
         if ('publish' !== get_post_status($post)) {
520 520
             //include shims for the `get_preview_post_link` function
521
-            require_once( EE_CORE . 'wordpress-shims.php' );
521
+            require_once(EE_CORE.'wordpress-shims.php');
522 522
             $return .= '<span_id="view-post-btn"><a target="_blank" href="'
523 523
                        . get_preview_post_link($id)
524 524
                        . '" class="button button-small">'
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
             $template_args['statuses']         = $statuses;
557 557
         }
558 558
 
559
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
559
+        $template = EE_ADMIN_TEMPLATE.'status_dropdown.template.php';
560 560
         EEH_Template::display_template($template, $template_args);
561 561
     }
562 562
 
@@ -610,7 +610,7 @@  discard block
 block discarded – undo
610 610
             $this->_template_args['success'] = true;
611 611
         }
612 612
         do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
613
+        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_'.get_class($this), $this);
614 614
         //now let's return json
615 615
         $this->_return_json();
616 616
     }
@@ -1013,7 +1013,7 @@  discard block
 block discarded – undo
1013 1013
         //global action
1014 1014
         do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015 1015
         //class specific action so you can limit hooking into a specific page.
1016
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1016
+        do_action('AHEE_EE_Admin_Page_CPT_'.get_class($this).'__restore_revision', $post_id, $revision_id);
1017 1017
     }
1018 1018
 
1019 1019
 
@@ -1091,7 +1091,7 @@  discard block
 block discarded – undo
1091 1091
         if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092 1092
             $post = get_post($id);
1093 1093
             if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
-                $shortlink = home_url('?p=' . $post->ID);
1094
+                $shortlink = home_url('?p='.$post->ID);
1095 1095
             }
1096 1096
         }
1097 1097
         return $shortlink;
@@ -1126,11 +1126,11 @@  discard block
 block discarded – undo
1126 1126
      */
1127 1127
     public function cpt_post_form_hidden_input()
1128 1128
     {
1129
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1129
+        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="'.$this->_admin_base_url.'" />';
1130 1130
         //we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131 1131
         echo '<div id="ee-cpt-hidden-inputs">';
1132
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1132
+        echo '<input type="hidden" id="current_route" name="current_route" value="'.$this->_current_view.'" />';
1133
+        echo '<input type="hidden" id="current_page" name="current_page" value="'.$this->page_slug.'" />';
1134 1134
         echo '</div>';
1135 1135
     }
1136 1136
 
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
         $this->_set_model_object($post->ID, true);
1218 1218
 
1219 1219
         //returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1220
+        $action = 'trash_'.str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221 1221
 
1222 1222
         return EE_Admin_Page::add_query_args_and_nonce(
1223 1223
             array(
@@ -1328,39 +1328,39 @@  discard block
 block discarded – undo
1328 1328
             1 => sprintf(
1329 1329
                 __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330 1330
                 $this->_cpt_object->labels->singular_name,
1331
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1331
+                '<a href="'.esc_url(get_permalink($id)).'">',
1332 1332
                 '</a>'
1333 1333
             ),
1334 1334
             2 => __('Custom field updated'),
1335 1335
             3 => __('Custom field deleted.'),
1336 1336
             4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337 1337
             5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
-                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1338
+                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int) $_GET['revision'], false))
1339 1339
                 : false,
1340 1340
             6 => sprintf(
1341 1341
                 __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342 1342
                 $this->_cpt_object->labels->singular_name,
1343
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1343
+                '<a href="'.esc_url(get_permalink($id)).'">',
1344 1344
                 '</a>'
1345 1345
             ),
1346 1346
             7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347 1347
             8 => sprintf(
1348 1348
                 __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349 1349
                 $this->_cpt_object->labels->singular_name,
1350
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1350
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))).'">',
1351 1351
                 '</a>'
1352 1352
             ),
1353 1353
             9 => sprintf(
1354 1354
                 __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355 1355
                 $this->_cpt_object->labels->singular_name,
1356
-                '<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1356
+                '<strong>'.date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)).'</strong>',
1357
+                '<a target="_blank" href="'.esc_url(get_permalink($id)),
1358 1358
                 '</a>'
1359 1359
             ),
1360 1360
             10 => sprintf(
1361 1361
                 __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362 1362
                 $this->_cpt_object->labels->singular_name,
1363
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1363
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364 1364
                 '</a>'
1365 1365
             ),
1366 1366
         );
@@ -1383,7 +1383,7 @@  discard block
 block discarded – undo
1383 1383
         $post_type        = $this->_cpt_routes[$this->_req_action];
1384 1384
         $post_type_object = $this->_cpt_object;
1385 1385
         $title            = $post_type_object->labels->add_new_item;
1386
-        $post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1386
+        $post = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387 1387
         add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388 1388
         //modify the default editor title field with default title.
1389 1389
         add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
@@ -1418,7 +1418,7 @@  discard block
 block discarded – undo
1418 1418
                     ), 'admin.php');
1419 1419
                 }
1420 1420
             }
1421
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1421
+            include_once WP_ADMIN_PATH.'edit-form-advanced.php';
1422 1422
         }
1423 1423
     }
1424 1424
 
Please login to merge, or discard this patch.