Completed
Branch dependabot/npm_and_yarn/@wordp... (e9f48b)
by
unknown
60:52 queued 52:34
created
core/db_models/EEM_Datetime.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -529,7 +529,7 @@
 block discarded – undo
529 529
     /**
530 530
      * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
531 531
      *
532
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
532
+     * @param  string[] $stati_to_include If included you can restrict the statuses we return counts for by including the
533 533
      *                                 stati you want counts for as values in the array.  An empty array returns counts
534 534
      *                                 for all valid stati.
535 535
      * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
Please login to merge, or discard this patch.
Indentation   +743 added lines, -743 removed lines patch added patch discarded remove patch
@@ -13,747 +13,747 @@
 block discarded – undo
13 13
 class EEM_Datetime extends EEM_Soft_Delete_Base
14 14
 {
15 15
 
16
-    /**
17
-     * @var EEM_Datetime $_instance
18
-     */
19
-    protected static $_instance;
20
-
21
-
22
-    /**
23
-     * private constructor to prevent direct creation
24
-     *
25
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
-     *                         (and any incoming timezone data that gets saved).
27
-     *                         Note this just sends the timezone info to the date time model field objects.
28
-     *                         Default is NULL
29
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
-     * @throws EE_Error
31
-     * @throws InvalidArgumentException
32
-     * @throws InvalidArgumentException
33
-     */
34
-    protected function __construct($timezone)
35
-    {
36
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
-        $this->_tables                 = array(
39
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
-        );
41
-        $this->_fields                 = array(
42
-            'Datetime' => array(
43
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
-                    'DTT_ID',
45
-                    esc_html__('Datetime ID', 'event_espresso')
46
-                ),
47
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
-                    'EVT_ID',
49
-                    esc_html__('Event ID', 'event_espresso'),
50
-                    false,
51
-                    0,
52
-                    'Event'
53
-                ),
54
-                'DTT_name'        => new EE_Plain_Text_Field(
55
-                    'DTT_name',
56
-                    esc_html__('Datetime Name', 'event_espresso'),
57
-                    false,
58
-                    ''
59
-                ),
60
-                'DTT_description' => new EE_Post_Content_Field(
61
-                    'DTT_description',
62
-                    esc_html__('Description for Datetime', 'event_espresso'),
63
-                    false,
64
-                    ''
65
-                ),
66
-                'DTT_EVT_start'   => new EE_Datetime_Field(
67
-                    'DTT_EVT_start',
68
-                    esc_html__('Start time/date of Event', 'event_espresso'),
69
-                    false,
70
-                    EE_Datetime_Field::now,
71
-                    $timezone
72
-                ),
73
-                'DTT_EVT_end'     => new EE_Datetime_Field(
74
-                    'DTT_EVT_end',
75
-                    esc_html__('End time/date of Event', 'event_espresso'),
76
-                    false,
77
-                    EE_Datetime_Field::now,
78
-                    $timezone
79
-                ),
80
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
81
-                    'DTT_reg_limit',
82
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
83
-                    true,
84
-                    EE_INF
85
-                ),
86
-                'DTT_sold'        => new EE_Integer_Field(
87
-                    'DTT_sold',
88
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
89
-                    true,
90
-                    0
91
-                ),
92
-                'DTT_reserved'    => new EE_Integer_Field(
93
-                    'DTT_reserved',
94
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
95
-                    false,
96
-                    0
97
-                ),
98
-                'DTT_is_primary'  => new EE_Boolean_Field(
99
-                    'DTT_is_primary',
100
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
101
-                    false,
102
-                    false
103
-                ),
104
-                'DTT_order'       => new EE_Integer_Field(
105
-                    'DTT_order',
106
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
107
-                    false,
108
-                    0
109
-                ),
110
-                'DTT_parent'      => new EE_Integer_Field(
111
-                    'DTT_parent',
112
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
113
-                    true,
114
-                    0
115
-                ),
116
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
117
-                    'DTT_deleted',
118
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
119
-                    false,
120
-                    false
121
-                ),
122
-            ),
123
-        );
124
-        $this->_model_relations        = array(
125
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
126
-            'Event'   => new EE_Belongs_To_Relation(),
127
-            'Checkin' => new EE_Has_Many_Relation(),
128
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
129
-        );
130
-        $path_to_event_model = 'Event';
131
-        $this->model_chain_to_password = $path_to_event_model;
132
-        $this->_model_chain_to_wp_user = $path_to_event_model;
133
-        // this model is generally available for reading
134
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
135
-            $path_to_event_model
136
-        );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
138
-            $path_to_event_model
139
-        );
140
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
141
-            $path_to_event_model
142
-        );
143
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
144
-            $path_to_event_model,
145
-            EEM_Base::caps_edit
146
-        );
147
-        parent::__construct($timezone);
148
-    }
149
-
150
-
151
-    /**
152
-     * create new blank datetime
153
-     *
154
-     * @access public
155
-     * @return EE_Datetime[] array on success, FALSE on fail
156
-     * @throws EE_Error
157
-     * @throws InvalidArgumentException
158
-     * @throws InvalidDataTypeException
159
-     * @throws ReflectionException
160
-     * @throws InvalidInterfaceException
161
-     */
162
-    public function create_new_blank_datetime()
163
-    {
164
-        // makes sure timezone is always set.
165
-        $timezone_string = $this->get_timezone();
166
-        /**
167
-         * Filters the initial start date for the new datetime.
168
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
169
-         *
170
-         * @param int $start_date Unixtimestamp representing now + 30 days in seconds.
171
-         * @return int unixtimestamp
172
-         */
173
-        $start_date = apply_filters(
174
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
175
-            $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
176
-        );
177
-        /**
178
-         * Filters the initial end date for the new datetime.
179
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
180
-         *
181
-         * @param int $end_data Unixtimestamp representing now + 30 days in seconds.
182
-         * @return int unixtimestamp
183
-         */
184
-        $end_date = apply_filters(
185
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
186
-            $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
187
-        );
188
-        $blank_datetime = EE_Datetime::new_instance(
189
-            array(
190
-                'DTT_EVT_start' => $start_date,
191
-                'DTT_EVT_end'   => $end_date,
192
-                'DTT_order'     => 1,
193
-                'DTT_reg_limit' => EE_INF,
194
-            ),
195
-            $timezone_string
196
-        );
197
-        /**
198
-         * Filters the initial start time and format for the new EE_Datetime instance.
199
-         *
200
-         * @param array $start_time An array having size 2.  First element is the time, second element is the time
201
-         *                          format.
202
-         * @return array
203
-         */
204
-        $start_time = apply_filters(
205
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
206
-            ['8am', 'ga']
207
-        );
208
-        /**
209
-         * Filters the initial end time and format for the new EE_Datetime instance.
210
-         *
211
-         * @param array $end_time An array having size 2.  First element is the time, second element is the time
212
-         *                        format
213
-         * @return array
214
-         */
215
-        $end_time = apply_filters(
216
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
217
-            ['5pm', 'ga']
218
-        );
219
-        $this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
220
-        $blank_datetime->set_start_time(
221
-            $this->convert_datetime_for_query(
222
-                'DTT_EVT_start',
223
-                $start_time[0],
224
-                $start_time[1],
225
-                $timezone_string
226
-            )
227
-        );
228
-        $blank_datetime->set_end_time(
229
-            $this->convert_datetime_for_query(
230
-                'DTT_EVT_end',
231
-                $end_time[0],
232
-                $end_time[1],
233
-                $timezone_string
234
-            )
235
-        );
236
-        return array($blank_datetime);
237
-    }
238
-
239
-
240
-    /**
241
-     * Validates whether the start_time and end_time are in the expected format.
242
-     * @param array $start_time
243
-     * @param array $end_time
244
-     * @throws InvalidArgumentException
245
-     * @throws InvalidDataTypeException
246
-     */
247
-    private function validateStartAndEndTimeForBlankDate($start_time, $end_time)
248
-    {
249
-        if (! is_array($start_time)) {
250
-            throw new InvalidDataTypeException('start_time', $start_time, 'array');
251
-        }
252
-        if (! is_array($end_time)) {
253
-            throw new InvalidDataTypeException('end_time', $end_time, 'array');
254
-        }
255
-        if (count($start_time) !== 2) {
256
-            throw new InvalidArgumentException(
257
-                sprintf(
258
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
259
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
260
-                    '$start_time'
261
-                )
262
-            );
263
-        }
264
-        if (count($end_time) !== 2) {
265
-            throw new InvalidArgumentException(
266
-                sprintf(
267
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
268
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
269
-                    '$end_time'
270
-                )
271
-            );
272
-        }
273
-    }
274
-
275
-
276
-    /**
277
-     * get event start date from db
278
-     *
279
-     * @access public
280
-     * @param  int $EVT_ID
281
-     * @return EE_Datetime[] array on success, FALSE on fail
282
-     * @throws EE_Error
283
-     */
284
-    public function get_all_event_dates($EVT_ID = 0)
285
-    {
286
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
287
-            return $this->create_new_blank_datetime();
288
-        }
289
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
290
-        if (empty($results)) {
291
-            return $this->create_new_blank_datetime();
292
-        }
293
-        return $results;
294
-    }
295
-
296
-
297
-    /**
298
-     * get all datetimes attached to an event ordered by the DTT_order field
299
-     *
300
-     * @public
301
-     * @param  int    $EVT_ID     event id
302
-     * @param boolean $include_expired
303
-     * @param boolean $include_deleted
304
-     * @param  int    $limit      If included then limit the count of results by
305
-     *                            the given number
306
-     * @return EE_Datetime[]
307
-     * @throws EE_Error
308
-     */
309
-    public function get_datetimes_for_event_ordered_by_DTT_order(
310
-        $EVT_ID,
311
-        $include_expired = true,
312
-        $include_deleted = true,
313
-        $limit = null
314
-    ) {
315
-        // sanitize EVT_ID
316
-        $EVT_ID         = absint($EVT_ID);
317
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
318
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
319
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
320
-        $query_params = ! empty($limit)
321
-            ? array(
322
-                $where_params,
323
-                'limit'                    => $limit,
324
-                'order_by'                 => array('DTT_order' => 'ASC'),
325
-                'default_where_conditions' => 'none',
326
-            )
327
-            : array(
328
-                $where_params,
329
-                'order_by'                 => array('DTT_order' => 'ASC'),
330
-                'default_where_conditions' => 'none',
331
-            );
332
-        if (! $include_expired) {
333
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
334
-        }
335
-        if ($include_deleted) {
336
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
337
-        }
338
-        /** @var EE_Datetime[] $result */
339
-        $result = $this->get_all($query_params);
340
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
341
-        return $result;
342
-    }
343
-
344
-
345
-    /**
346
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
347
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
348
-     * and then the earlier datetimes are the most important.
349
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
350
-     *
351
-     * @param int $EVT_ID
352
-     * @param int $limit
353
-     * @return EE_Datetime[]|EE_Base_Class[]
354
-     * @throws EE_Error
355
-     */
356
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
357
-    {
358
-        return $this->get_all(
359
-            array(
360
-                array('Event.EVT_ID' => $EVT_ID),
361
-                'limit'                    => $limit,
362
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
363
-                'default_where_conditions' => 'none',
364
-            )
365
-        );
366
-    }
367
-
368
-
369
-    /**
370
-     * @param int     $EVT_ID
371
-     * @param boolean $include_expired
372
-     * @param boolean $include_deleted
373
-     * @return EE_Datetime
374
-     * @throws EE_Error
375
-     */
376
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
377
-    {
378
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
379
-            $EVT_ID,
380
-            $include_expired,
381
-            $include_deleted,
382
-            1
383
-        );
384
-        if ($results) {
385
-            return array_shift($results);
386
-        }
387
-        return null;
388
-    }
389
-
390
-
391
-    /**
392
-     * Gets the 'primary' datetime for an event.
393
-     *
394
-     * @param int  $EVT_ID
395
-     * @param bool $try_to_exclude_expired
396
-     * @param bool $try_to_exclude_deleted
397
-     * @return \EE_Datetime
398
-     * @throws EE_Error
399
-     */
400
-    public function get_primary_datetime_for_event(
401
-        $EVT_ID,
402
-        $try_to_exclude_expired = true,
403
-        $try_to_exclude_deleted = true
404
-    ) {
405
-        if ($try_to_exclude_expired) {
406
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
407
-            if ($non_expired) {
408
-                return $non_expired;
409
-            }
410
-        }
411
-        if ($try_to_exclude_deleted) {
412
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
413
-            if ($expired_even) {
414
-                return $expired_even;
415
-            }
416
-        }
417
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
418
-    }
419
-
420
-
421
-    /**
422
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
423
-     * only by start date
424
-     *
425
-     * @param int     $EVT_ID
426
-     * @param boolean $include_expired
427
-     * @param boolean $include_deleted
428
-     * @param int     $limit
429
-     * @return EE_Datetime[]
430
-     * @throws EE_Error
431
-     */
432
-    public function get_datetimes_for_event_ordered_by_start_time(
433
-        $EVT_ID,
434
-        $include_expired = true,
435
-        $include_deleted = true,
436
-        $limit = null
437
-    ) {
438
-        // sanitize EVT_ID
439
-        $EVT_ID         = absint($EVT_ID);
440
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
441
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
442
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
443
-        if (! $include_expired) {
444
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
445
-        }
446
-        if ($include_deleted) {
447
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
448
-        }
449
-        if ($limit) {
450
-            $query_params['limit'] = $limit;
451
-        }
452
-        /** @var EE_Datetime[] $result */
453
-        $result = $this->get_all($query_params);
454
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
455
-        return $result;
456
-    }
457
-
458
-
459
-    /**
460
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
461
-     * only by start date
462
-     *
463
-     * @param int     $TKT_ID
464
-     * @param boolean $include_expired
465
-     * @param boolean $include_deleted
466
-     * @param int     $limit
467
-     * @return EE_Datetime[]
468
-     * @throws EE_Error
469
-     */
470
-    public function get_datetimes_for_ticket_ordered_by_start_time(
471
-        $TKT_ID,
472
-        $include_expired = true,
473
-        $include_deleted = true,
474
-        $limit = null
475
-    ) {
476
-        // sanitize TKT_ID
477
-        $TKT_ID         = absint($TKT_ID);
478
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
479
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
480
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
481
-        if (! $include_expired) {
482
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
483
-        }
484
-        if ($include_deleted) {
485
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
486
-        }
487
-        if ($limit) {
488
-            $query_params['limit'] = $limit;
489
-        }
490
-        /** @var EE_Datetime[] $result */
491
-        $result = $this->get_all($query_params);
492
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
493
-        return $result;
494
-    }
495
-
496
-
497
-    /**
498
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
499
-     * datetimes.
500
-     *
501
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
502
-     * @param  boolean  $include_expired whether to include expired datetimes or not
503
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
504
-     * @param  int|null $limit           if null, no limit, if int then limit results by
505
-     *                                   that number
506
-     * @return EE_Datetime[]
507
-     * @throws EE_Error
508
-     */
509
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
510
-        $TKT_ID,
511
-        $include_expired = true,
512
-        $include_deleted = true,
513
-        $limit = null
514
-    ) {
515
-        // sanitize id.
516
-        $TKT_ID         = absint($TKT_ID);
517
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
518
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
519
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
520
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
521
-        if (! $include_expired) {
522
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
523
-        }
524
-        if ($include_deleted) {
525
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
526
-        }
527
-        if ($limit) {
528
-            $query_params['limit'] = $limit;
529
-        }
530
-        /** @var EE_Datetime[] $result */
531
-        $result = $this->get_all($query_params);
532
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
533
-        return $result;
534
-    }
535
-
536
-
537
-    /**
538
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
539
-     * reason it doesn't exist, we consider the earliest event the most important)
540
-     *
541
-     * @param int $EVT_ID
542
-     * @return EE_Datetime
543
-     * @throws EE_Error
544
-     */
545
-    public function get_most_important_datetime_for_event($EVT_ID)
546
-    {
547
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
548
-        if ($results) {
549
-            return array_shift($results);
550
-        }
551
-        return null;
552
-    }
553
-
554
-
555
-    /**
556
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
557
-     * grouped by month and year.
558
-     *
559
-     * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
560
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
561
-     *                                   Can be:
562
-     *                                   - '' = no filter
563
-     *                                   - upcoming = Published events with at least one upcoming datetime.
564
-     *                                   - expired = Events with all datetimes expired.
565
-     *                                   - active = Events that are published and have at least one datetime that
566
-     *                                   starts before now and ends after now.
567
-     *                                   - inactive = Events that are either not published.
568
-     * @return EE_Base_Class[]
569
-     * @throws EE_Error
570
-     * @throws InvalidArgumentException
571
-     * @throws InvalidArgumentException
572
-     */
573
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
574
-    {
575
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
576
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
577
-        switch ($evt_active_status) {
578
-            case 'upcoming':
579
-                $where_params['Event.status'] = 'publish';
580
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
581
-                if (isset($where_params['DTT_EVT_start'])) {
582
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
583
-                }
584
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
585
-                break;
586
-            case 'expired':
587
-                if (isset($where_params['Event.status'])) {
588
-                    unset($where_params['Event.status']);
589
-                }
590
-                // get events to exclude
591
-                $exclude_query[0] = array_merge(
592
-                    $where_params,
593
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
594
-                );
595
-                // first get all events that have datetimes where its not expired.
596
-                $event_ids = $this->_get_all_wpdb_results(
597
-                    $exclude_query,
598
-                    OBJECT_K,
599
-                    'Datetime.EVT_ID'
600
-                );
601
-                $event_ids = array_keys($event_ids);
602
-                if (isset($where_params['DTT_EVT_end'])) {
603
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
604
-                }
605
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
606
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
607
-                break;
608
-            case 'active':
609
-                $where_params['Event.status'] = 'publish';
610
-                if (isset($where_params['DTT_EVT_start'])) {
611
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
612
-                }
613
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
614
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
615
-                }
616
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
617
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
618
-                break;
619
-            case 'inactive':
620
-                if (isset($where_params['Event.status'])) {
621
-                    unset($where_params['Event.status']);
622
-                }
623
-                if (isset($where_params['OR'])) {
624
-                    $where_params['AND']['OR'] = $where_params['OR'];
625
-                }
626
-                if (isset($where_params['DTT_EVT_end'])) {
627
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
628
-                    unset($where_params['DTT_EVT_end']);
629
-                }
630
-                if (isset($where_params['DTT_EVT_start'])) {
631
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
632
-                    unset($where_params['DTT_EVT_start']);
633
-                }
634
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
635
-                break;
636
-        }
637
-        $query_params[0]          = $where_params;
638
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
639
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
640
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
641
-            $this->get_timezone(),
642
-            'DTT_EVT_start'
643
-        );
644
-        $columns_to_select        = array(
645
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
646
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
647
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
648
-        );
649
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
650
-    }
651
-
652
-
653
-    /**
654
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
655
-     * for the tickets for each datetime)
656
-     *
657
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
658
-     * @throws EE_Error
659
-     */
660
-    public function update_sold($datetimes)
661
-    {
662
-        EE_Error::doing_it_wrong(
663
-            __FUNCTION__,
664
-            esc_html__(
665
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
666
-                'event_espresso'
667
-            ),
668
-            '4.9.32.rc.005'
669
-        );
670
-        foreach ($datetimes as $datetime) {
671
-            $datetime->update_sold();
672
-        }
673
-    }
674
-
675
-
676
-    /**
677
-     *    Gets the total number of tickets available at a particular datetime
678
-     *    (does NOT take into account the datetime's spaces available)
679
-     *
680
-     * @param int   $DTT_ID
681
-     * @param array $query_params
682
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
683
-     *             tickets attached to datetime then FALSE is returned.
684
-     */
685
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
686
-    {
687
-        $datetime = $this->get_one_by_ID($DTT_ID);
688
-        if ($datetime instanceof EE_Datetime) {
689
-            return $datetime->tickets_remaining($query_params);
690
-        }
691
-        return 0;
692
-    }
693
-
694
-
695
-    /**
696
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
697
-     *
698
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
699
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
700
-     *                                 for all valid stati.
701
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
702
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
703
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
704
-     * @throws EE_Error
705
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
706
-     *                                 EE_Datetime::expired
707
-     */
708
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
709
-    {
710
-        // only accept where conditions for this query.
711
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
712
-        $status_query_args = array(
713
-            EE_Datetime::active   => array_merge(
714
-                $_where,
715
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
716
-            ),
717
-            EE_Datetime::upcoming => array_merge(
718
-                $_where,
719
-                array('DTT_EVT_start' => array('>', time()))
720
-            ),
721
-            EE_Datetime::expired  => array_merge(
722
-                $_where,
723
-                array('DTT_EVT_end' => array('<', time()))
724
-            ),
725
-        );
726
-        if (! empty($stati_to_include)) {
727
-            foreach (array_keys($status_query_args) as $status) {
728
-                if (! in_array($status, $stati_to_include, true)) {
729
-                    unset($status_query_args[ $status ]);
730
-                }
731
-            }
732
-        }
733
-        // loop through and query counts for each stati.
734
-        $status_query_results = array();
735
-        foreach ($status_query_args as $status => $status_where_conditions) {
736
-            $status_query_results[ $status ] = EEM_Datetime::count(
737
-                array($status_where_conditions),
738
-                'DTT_ID',
739
-                true
740
-            );
741
-        }
742
-        return $status_query_results;
743
-    }
744
-
745
-
746
-    /**
747
-     * Returns the specific count for a given Datetime status matching any given query_params.
748
-     *
749
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
750
-     * @param array  $query_params
751
-     * @return int
752
-     * @throws EE_Error
753
-     */
754
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
755
-    {
756
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
757
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
758
-    }
16
+	/**
17
+	 * @var EEM_Datetime $_instance
18
+	 */
19
+	protected static $_instance;
20
+
21
+
22
+	/**
23
+	 * private constructor to prevent direct creation
24
+	 *
25
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
+	 *                         (and any incoming timezone data that gets saved).
27
+	 *                         Note this just sends the timezone info to the date time model field objects.
28
+	 *                         Default is NULL
29
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
+	 * @throws EE_Error
31
+	 * @throws InvalidArgumentException
32
+	 * @throws InvalidArgumentException
33
+	 */
34
+	protected function __construct($timezone)
35
+	{
36
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
+		$this->_tables                 = array(
39
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
+		);
41
+		$this->_fields                 = array(
42
+			'Datetime' => array(
43
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
+					'DTT_ID',
45
+					esc_html__('Datetime ID', 'event_espresso')
46
+				),
47
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
+					'EVT_ID',
49
+					esc_html__('Event ID', 'event_espresso'),
50
+					false,
51
+					0,
52
+					'Event'
53
+				),
54
+				'DTT_name'        => new EE_Plain_Text_Field(
55
+					'DTT_name',
56
+					esc_html__('Datetime Name', 'event_espresso'),
57
+					false,
58
+					''
59
+				),
60
+				'DTT_description' => new EE_Post_Content_Field(
61
+					'DTT_description',
62
+					esc_html__('Description for Datetime', 'event_espresso'),
63
+					false,
64
+					''
65
+				),
66
+				'DTT_EVT_start'   => new EE_Datetime_Field(
67
+					'DTT_EVT_start',
68
+					esc_html__('Start time/date of Event', 'event_espresso'),
69
+					false,
70
+					EE_Datetime_Field::now,
71
+					$timezone
72
+				),
73
+				'DTT_EVT_end'     => new EE_Datetime_Field(
74
+					'DTT_EVT_end',
75
+					esc_html__('End time/date of Event', 'event_espresso'),
76
+					false,
77
+					EE_Datetime_Field::now,
78
+					$timezone
79
+				),
80
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
81
+					'DTT_reg_limit',
82
+					esc_html__('Registration Limit for this time', 'event_espresso'),
83
+					true,
84
+					EE_INF
85
+				),
86
+				'DTT_sold'        => new EE_Integer_Field(
87
+					'DTT_sold',
88
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
89
+					true,
90
+					0
91
+				),
92
+				'DTT_reserved'    => new EE_Integer_Field(
93
+					'DTT_reserved',
94
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
95
+					false,
96
+					0
97
+				),
98
+				'DTT_is_primary'  => new EE_Boolean_Field(
99
+					'DTT_is_primary',
100
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
101
+					false,
102
+					false
103
+				),
104
+				'DTT_order'       => new EE_Integer_Field(
105
+					'DTT_order',
106
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
107
+					false,
108
+					0
109
+				),
110
+				'DTT_parent'      => new EE_Integer_Field(
111
+					'DTT_parent',
112
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
113
+					true,
114
+					0
115
+				),
116
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
117
+					'DTT_deleted',
118
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
119
+					false,
120
+					false
121
+				),
122
+			),
123
+		);
124
+		$this->_model_relations        = array(
125
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
126
+			'Event'   => new EE_Belongs_To_Relation(),
127
+			'Checkin' => new EE_Has_Many_Relation(),
128
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
129
+		);
130
+		$path_to_event_model = 'Event';
131
+		$this->model_chain_to_password = $path_to_event_model;
132
+		$this->_model_chain_to_wp_user = $path_to_event_model;
133
+		// this model is generally available for reading
134
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
135
+			$path_to_event_model
136
+		);
137
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
138
+			$path_to_event_model
139
+		);
140
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
141
+			$path_to_event_model
142
+		);
143
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
144
+			$path_to_event_model,
145
+			EEM_Base::caps_edit
146
+		);
147
+		parent::__construct($timezone);
148
+	}
149
+
150
+
151
+	/**
152
+	 * create new blank datetime
153
+	 *
154
+	 * @access public
155
+	 * @return EE_Datetime[] array on success, FALSE on fail
156
+	 * @throws EE_Error
157
+	 * @throws InvalidArgumentException
158
+	 * @throws InvalidDataTypeException
159
+	 * @throws ReflectionException
160
+	 * @throws InvalidInterfaceException
161
+	 */
162
+	public function create_new_blank_datetime()
163
+	{
164
+		// makes sure timezone is always set.
165
+		$timezone_string = $this->get_timezone();
166
+		/**
167
+		 * Filters the initial start date for the new datetime.
168
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
169
+		 *
170
+		 * @param int $start_date Unixtimestamp representing now + 30 days in seconds.
171
+		 * @return int unixtimestamp
172
+		 */
173
+		$start_date = apply_filters(
174
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
175
+			$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
176
+		);
177
+		/**
178
+		 * Filters the initial end date for the new datetime.
179
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
180
+		 *
181
+		 * @param int $end_data Unixtimestamp representing now + 30 days in seconds.
182
+		 * @return int unixtimestamp
183
+		 */
184
+		$end_date = apply_filters(
185
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
186
+			$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
187
+		);
188
+		$blank_datetime = EE_Datetime::new_instance(
189
+			array(
190
+				'DTT_EVT_start' => $start_date,
191
+				'DTT_EVT_end'   => $end_date,
192
+				'DTT_order'     => 1,
193
+				'DTT_reg_limit' => EE_INF,
194
+			),
195
+			$timezone_string
196
+		);
197
+		/**
198
+		 * Filters the initial start time and format for the new EE_Datetime instance.
199
+		 *
200
+		 * @param array $start_time An array having size 2.  First element is the time, second element is the time
201
+		 *                          format.
202
+		 * @return array
203
+		 */
204
+		$start_time = apply_filters(
205
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
206
+			['8am', 'ga']
207
+		);
208
+		/**
209
+		 * Filters the initial end time and format for the new EE_Datetime instance.
210
+		 *
211
+		 * @param array $end_time An array having size 2.  First element is the time, second element is the time
212
+		 *                        format
213
+		 * @return array
214
+		 */
215
+		$end_time = apply_filters(
216
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
217
+			['5pm', 'ga']
218
+		);
219
+		$this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
220
+		$blank_datetime->set_start_time(
221
+			$this->convert_datetime_for_query(
222
+				'DTT_EVT_start',
223
+				$start_time[0],
224
+				$start_time[1],
225
+				$timezone_string
226
+			)
227
+		);
228
+		$blank_datetime->set_end_time(
229
+			$this->convert_datetime_for_query(
230
+				'DTT_EVT_end',
231
+				$end_time[0],
232
+				$end_time[1],
233
+				$timezone_string
234
+			)
235
+		);
236
+		return array($blank_datetime);
237
+	}
238
+
239
+
240
+	/**
241
+	 * Validates whether the start_time and end_time are in the expected format.
242
+	 * @param array $start_time
243
+	 * @param array $end_time
244
+	 * @throws InvalidArgumentException
245
+	 * @throws InvalidDataTypeException
246
+	 */
247
+	private function validateStartAndEndTimeForBlankDate($start_time, $end_time)
248
+	{
249
+		if (! is_array($start_time)) {
250
+			throw new InvalidDataTypeException('start_time', $start_time, 'array');
251
+		}
252
+		if (! is_array($end_time)) {
253
+			throw new InvalidDataTypeException('end_time', $end_time, 'array');
254
+		}
255
+		if (count($start_time) !== 2) {
256
+			throw new InvalidArgumentException(
257
+				sprintf(
258
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
259
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
260
+					'$start_time'
261
+				)
262
+			);
263
+		}
264
+		if (count($end_time) !== 2) {
265
+			throw new InvalidArgumentException(
266
+				sprintf(
267
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
268
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
269
+					'$end_time'
270
+				)
271
+			);
272
+		}
273
+	}
274
+
275
+
276
+	/**
277
+	 * get event start date from db
278
+	 *
279
+	 * @access public
280
+	 * @param  int $EVT_ID
281
+	 * @return EE_Datetime[] array on success, FALSE on fail
282
+	 * @throws EE_Error
283
+	 */
284
+	public function get_all_event_dates($EVT_ID = 0)
285
+	{
286
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
287
+			return $this->create_new_blank_datetime();
288
+		}
289
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
290
+		if (empty($results)) {
291
+			return $this->create_new_blank_datetime();
292
+		}
293
+		return $results;
294
+	}
295
+
296
+
297
+	/**
298
+	 * get all datetimes attached to an event ordered by the DTT_order field
299
+	 *
300
+	 * @public
301
+	 * @param  int    $EVT_ID     event id
302
+	 * @param boolean $include_expired
303
+	 * @param boolean $include_deleted
304
+	 * @param  int    $limit      If included then limit the count of results by
305
+	 *                            the given number
306
+	 * @return EE_Datetime[]
307
+	 * @throws EE_Error
308
+	 */
309
+	public function get_datetimes_for_event_ordered_by_DTT_order(
310
+		$EVT_ID,
311
+		$include_expired = true,
312
+		$include_deleted = true,
313
+		$limit = null
314
+	) {
315
+		// sanitize EVT_ID
316
+		$EVT_ID         = absint($EVT_ID);
317
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
318
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
319
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
320
+		$query_params = ! empty($limit)
321
+			? array(
322
+				$where_params,
323
+				'limit'                    => $limit,
324
+				'order_by'                 => array('DTT_order' => 'ASC'),
325
+				'default_where_conditions' => 'none',
326
+			)
327
+			: array(
328
+				$where_params,
329
+				'order_by'                 => array('DTT_order' => 'ASC'),
330
+				'default_where_conditions' => 'none',
331
+			);
332
+		if (! $include_expired) {
333
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
334
+		}
335
+		if ($include_deleted) {
336
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
337
+		}
338
+		/** @var EE_Datetime[] $result */
339
+		$result = $this->get_all($query_params);
340
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
341
+		return $result;
342
+	}
343
+
344
+
345
+	/**
346
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
347
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
348
+	 * and then the earlier datetimes are the most important.
349
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
350
+	 *
351
+	 * @param int $EVT_ID
352
+	 * @param int $limit
353
+	 * @return EE_Datetime[]|EE_Base_Class[]
354
+	 * @throws EE_Error
355
+	 */
356
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
357
+	{
358
+		return $this->get_all(
359
+			array(
360
+				array('Event.EVT_ID' => $EVT_ID),
361
+				'limit'                    => $limit,
362
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
363
+				'default_where_conditions' => 'none',
364
+			)
365
+		);
366
+	}
367
+
368
+
369
+	/**
370
+	 * @param int     $EVT_ID
371
+	 * @param boolean $include_expired
372
+	 * @param boolean $include_deleted
373
+	 * @return EE_Datetime
374
+	 * @throws EE_Error
375
+	 */
376
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
377
+	{
378
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
379
+			$EVT_ID,
380
+			$include_expired,
381
+			$include_deleted,
382
+			1
383
+		);
384
+		if ($results) {
385
+			return array_shift($results);
386
+		}
387
+		return null;
388
+	}
389
+
390
+
391
+	/**
392
+	 * Gets the 'primary' datetime for an event.
393
+	 *
394
+	 * @param int  $EVT_ID
395
+	 * @param bool $try_to_exclude_expired
396
+	 * @param bool $try_to_exclude_deleted
397
+	 * @return \EE_Datetime
398
+	 * @throws EE_Error
399
+	 */
400
+	public function get_primary_datetime_for_event(
401
+		$EVT_ID,
402
+		$try_to_exclude_expired = true,
403
+		$try_to_exclude_deleted = true
404
+	) {
405
+		if ($try_to_exclude_expired) {
406
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
407
+			if ($non_expired) {
408
+				return $non_expired;
409
+			}
410
+		}
411
+		if ($try_to_exclude_deleted) {
412
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
413
+			if ($expired_even) {
414
+				return $expired_even;
415
+			}
416
+		}
417
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
418
+	}
419
+
420
+
421
+	/**
422
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
423
+	 * only by start date
424
+	 *
425
+	 * @param int     $EVT_ID
426
+	 * @param boolean $include_expired
427
+	 * @param boolean $include_deleted
428
+	 * @param int     $limit
429
+	 * @return EE_Datetime[]
430
+	 * @throws EE_Error
431
+	 */
432
+	public function get_datetimes_for_event_ordered_by_start_time(
433
+		$EVT_ID,
434
+		$include_expired = true,
435
+		$include_deleted = true,
436
+		$limit = null
437
+	) {
438
+		// sanitize EVT_ID
439
+		$EVT_ID         = absint($EVT_ID);
440
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
441
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
442
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
443
+		if (! $include_expired) {
444
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
445
+		}
446
+		if ($include_deleted) {
447
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
448
+		}
449
+		if ($limit) {
450
+			$query_params['limit'] = $limit;
451
+		}
452
+		/** @var EE_Datetime[] $result */
453
+		$result = $this->get_all($query_params);
454
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
455
+		return $result;
456
+	}
457
+
458
+
459
+	/**
460
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
461
+	 * only by start date
462
+	 *
463
+	 * @param int     $TKT_ID
464
+	 * @param boolean $include_expired
465
+	 * @param boolean $include_deleted
466
+	 * @param int     $limit
467
+	 * @return EE_Datetime[]
468
+	 * @throws EE_Error
469
+	 */
470
+	public function get_datetimes_for_ticket_ordered_by_start_time(
471
+		$TKT_ID,
472
+		$include_expired = true,
473
+		$include_deleted = true,
474
+		$limit = null
475
+	) {
476
+		// sanitize TKT_ID
477
+		$TKT_ID         = absint($TKT_ID);
478
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
479
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
480
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
481
+		if (! $include_expired) {
482
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
483
+		}
484
+		if ($include_deleted) {
485
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
486
+		}
487
+		if ($limit) {
488
+			$query_params['limit'] = $limit;
489
+		}
490
+		/** @var EE_Datetime[] $result */
491
+		$result = $this->get_all($query_params);
492
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
493
+		return $result;
494
+	}
495
+
496
+
497
+	/**
498
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
499
+	 * datetimes.
500
+	 *
501
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
502
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
503
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
504
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
505
+	 *                                   that number
506
+	 * @return EE_Datetime[]
507
+	 * @throws EE_Error
508
+	 */
509
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
510
+		$TKT_ID,
511
+		$include_expired = true,
512
+		$include_deleted = true,
513
+		$limit = null
514
+	) {
515
+		// sanitize id.
516
+		$TKT_ID         = absint($TKT_ID);
517
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
518
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
519
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
520
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
521
+		if (! $include_expired) {
522
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
523
+		}
524
+		if ($include_deleted) {
525
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
526
+		}
527
+		if ($limit) {
528
+			$query_params['limit'] = $limit;
529
+		}
530
+		/** @var EE_Datetime[] $result */
531
+		$result = $this->get_all($query_params);
532
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
533
+		return $result;
534
+	}
535
+
536
+
537
+	/**
538
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
539
+	 * reason it doesn't exist, we consider the earliest event the most important)
540
+	 *
541
+	 * @param int $EVT_ID
542
+	 * @return EE_Datetime
543
+	 * @throws EE_Error
544
+	 */
545
+	public function get_most_important_datetime_for_event($EVT_ID)
546
+	{
547
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
548
+		if ($results) {
549
+			return array_shift($results);
550
+		}
551
+		return null;
552
+	}
553
+
554
+
555
+	/**
556
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
557
+	 * grouped by month and year.
558
+	 *
559
+	 * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
560
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
561
+	 *                                   Can be:
562
+	 *                                   - '' = no filter
563
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
564
+	 *                                   - expired = Events with all datetimes expired.
565
+	 *                                   - active = Events that are published and have at least one datetime that
566
+	 *                                   starts before now and ends after now.
567
+	 *                                   - inactive = Events that are either not published.
568
+	 * @return EE_Base_Class[]
569
+	 * @throws EE_Error
570
+	 * @throws InvalidArgumentException
571
+	 * @throws InvalidArgumentException
572
+	 */
573
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
574
+	{
575
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
576
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
577
+		switch ($evt_active_status) {
578
+			case 'upcoming':
579
+				$where_params['Event.status'] = 'publish';
580
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
581
+				if (isset($where_params['DTT_EVT_start'])) {
582
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
583
+				}
584
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
585
+				break;
586
+			case 'expired':
587
+				if (isset($where_params['Event.status'])) {
588
+					unset($where_params['Event.status']);
589
+				}
590
+				// get events to exclude
591
+				$exclude_query[0] = array_merge(
592
+					$where_params,
593
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
594
+				);
595
+				// first get all events that have datetimes where its not expired.
596
+				$event_ids = $this->_get_all_wpdb_results(
597
+					$exclude_query,
598
+					OBJECT_K,
599
+					'Datetime.EVT_ID'
600
+				);
601
+				$event_ids = array_keys($event_ids);
602
+				if (isset($where_params['DTT_EVT_end'])) {
603
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
604
+				}
605
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
606
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
607
+				break;
608
+			case 'active':
609
+				$where_params['Event.status'] = 'publish';
610
+				if (isset($where_params['DTT_EVT_start'])) {
611
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
612
+				}
613
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
614
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
615
+				}
616
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
617
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
618
+				break;
619
+			case 'inactive':
620
+				if (isset($where_params['Event.status'])) {
621
+					unset($where_params['Event.status']);
622
+				}
623
+				if (isset($where_params['OR'])) {
624
+					$where_params['AND']['OR'] = $where_params['OR'];
625
+				}
626
+				if (isset($where_params['DTT_EVT_end'])) {
627
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
628
+					unset($where_params['DTT_EVT_end']);
629
+				}
630
+				if (isset($where_params['DTT_EVT_start'])) {
631
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
632
+					unset($where_params['DTT_EVT_start']);
633
+				}
634
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
635
+				break;
636
+		}
637
+		$query_params[0]          = $where_params;
638
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
639
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
640
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
641
+			$this->get_timezone(),
642
+			'DTT_EVT_start'
643
+		);
644
+		$columns_to_select        = array(
645
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
646
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
647
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
648
+		);
649
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
650
+	}
651
+
652
+
653
+	/**
654
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
655
+	 * for the tickets for each datetime)
656
+	 *
657
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
658
+	 * @throws EE_Error
659
+	 */
660
+	public function update_sold($datetimes)
661
+	{
662
+		EE_Error::doing_it_wrong(
663
+			__FUNCTION__,
664
+			esc_html__(
665
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
666
+				'event_espresso'
667
+			),
668
+			'4.9.32.rc.005'
669
+		);
670
+		foreach ($datetimes as $datetime) {
671
+			$datetime->update_sold();
672
+		}
673
+	}
674
+
675
+
676
+	/**
677
+	 *    Gets the total number of tickets available at a particular datetime
678
+	 *    (does NOT take into account the datetime's spaces available)
679
+	 *
680
+	 * @param int   $DTT_ID
681
+	 * @param array $query_params
682
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
683
+	 *             tickets attached to datetime then FALSE is returned.
684
+	 */
685
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
686
+	{
687
+		$datetime = $this->get_one_by_ID($DTT_ID);
688
+		if ($datetime instanceof EE_Datetime) {
689
+			return $datetime->tickets_remaining($query_params);
690
+		}
691
+		return 0;
692
+	}
693
+
694
+
695
+	/**
696
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
697
+	 *
698
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
699
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
700
+	 *                                 for all valid stati.
701
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
702
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
703
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
704
+	 * @throws EE_Error
705
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
706
+	 *                                 EE_Datetime::expired
707
+	 */
708
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
709
+	{
710
+		// only accept where conditions for this query.
711
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
712
+		$status_query_args = array(
713
+			EE_Datetime::active   => array_merge(
714
+				$_where,
715
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
716
+			),
717
+			EE_Datetime::upcoming => array_merge(
718
+				$_where,
719
+				array('DTT_EVT_start' => array('>', time()))
720
+			),
721
+			EE_Datetime::expired  => array_merge(
722
+				$_where,
723
+				array('DTT_EVT_end' => array('<', time()))
724
+			),
725
+		);
726
+		if (! empty($stati_to_include)) {
727
+			foreach (array_keys($status_query_args) as $status) {
728
+				if (! in_array($status, $stati_to_include, true)) {
729
+					unset($status_query_args[ $status ]);
730
+				}
731
+			}
732
+		}
733
+		// loop through and query counts for each stati.
734
+		$status_query_results = array();
735
+		foreach ($status_query_args as $status => $status_where_conditions) {
736
+			$status_query_results[ $status ] = EEM_Datetime::count(
737
+				array($status_where_conditions),
738
+				'DTT_ID',
739
+				true
740
+			);
741
+		}
742
+		return $status_query_results;
743
+	}
744
+
745
+
746
+	/**
747
+	 * Returns the specific count for a given Datetime status matching any given query_params.
748
+	 *
749
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
750
+	 * @param array  $query_params
751
+	 * @return int
752
+	 * @throws EE_Error
753
+	 */
754
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
755
+	{
756
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
757
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
758
+	}
759 759
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
                 ),
122 122
             ),
123 123
         );
124
-        $this->_model_relations        = array(
124
+        $this->_model_relations = array(
125 125
             'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
126 126
             'Event'   => new EE_Belongs_To_Relation(),
127 127
             'Checkin' => new EE_Has_Many_Relation(),
@@ -131,16 +131,16 @@  discard block
 block discarded – undo
131 131
         $this->model_chain_to_password = $path_to_event_model;
132 132
         $this->_model_chain_to_wp_user = $path_to_event_model;
133 133
         // this model is generally available for reading
134
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
134
+        $this->_cap_restriction_generators[EEM_Base::caps_read]       = new EE_Restriction_Generator_Event_Related_Public(
135 135
             $path_to_event_model
136 136
         );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
137
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected(
138 138
             $path_to_event_model
139 139
         );
140
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
140
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]       = new EE_Restriction_Generator_Event_Related_Protected(
141 141
             $path_to_event_model
142 142
         );
143
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
143
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]     = new EE_Restriction_Generator_Event_Related_Protected(
144 144
             $path_to_event_model,
145 145
             EEM_Base::caps_edit
146 146
         );
@@ -246,10 +246,10 @@  discard block
 block discarded – undo
246 246
      */
247 247
     private function validateStartAndEndTimeForBlankDate($start_time, $end_time)
248 248
     {
249
-        if (! is_array($start_time)) {
249
+        if ( ! is_array($start_time)) {
250 250
             throw new InvalidDataTypeException('start_time', $start_time, 'array');
251 251
         }
252
-        if (! is_array($end_time)) {
252
+        if ( ! is_array($end_time)) {
253 253
             throw new InvalidDataTypeException('end_time', $end_time, 'array');
254 254
         }
255 255
         if (count($start_time) !== 2) {
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
      */
284 284
     public function get_all_event_dates($EVT_ID = 0)
285 285
     {
286
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
286
+        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
287 287
             return $this->create_new_blank_datetime();
288 288
         }
289 289
         $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
                 'order_by'                 => array('DTT_order' => 'ASC'),
330 330
                 'default_where_conditions' => 'none',
331 331
             );
332
-        if (! $include_expired) {
332
+        if ( ! $include_expired) {
333 333
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
334 334
         }
335 335
         if ($include_deleted) {
@@ -440,7 +440,7 @@  discard block
 block discarded – undo
440 440
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
441 441
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
442 442
         $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
443
-        if (! $include_expired) {
443
+        if ( ! $include_expired) {
444 444
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
445 445
         }
446 446
         if ($include_deleted) {
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
479 479
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
480 480
         $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
481
-        if (! $include_expired) {
481
+        if ( ! $include_expired) {
482 482
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
483 483
         }
484 484
         if ($include_deleted) {
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
519 519
         $where_params = array('Ticket.TKT_ID' => $TKT_ID);
520 520
         $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
521
-        if (! $include_expired) {
521
+        if ( ! $include_expired) {
522 522
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
523 523
         }
524 524
         if ($include_deleted) {
@@ -641,10 +641,10 @@  discard block
 block discarded – undo
641 641
             $this->get_timezone(),
642 642
             'DTT_EVT_start'
643 643
         );
644
-        $columns_to_select        = array(
645
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
646
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
647
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
644
+        $columns_to_select = array(
645
+            'dtt_year'      => array('YEAR('.$query_interval.')', '%s'),
646
+            'dtt_month'     => array('MONTHNAME('.$query_interval.')', '%s'),
647
+            'dtt_month_num' => array('MONTH('.$query_interval.')', '%s'),
648 648
         );
649 649
         return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
650 650
     }
@@ -723,17 +723,17 @@  discard block
 block discarded – undo
723 723
                 array('DTT_EVT_end' => array('<', time()))
724 724
             ),
725 725
         );
726
-        if (! empty($stati_to_include)) {
726
+        if ( ! empty($stati_to_include)) {
727 727
             foreach (array_keys($status_query_args) as $status) {
728
-                if (! in_array($status, $stati_to_include, true)) {
729
-                    unset($status_query_args[ $status ]);
728
+                if ( ! in_array($status, $stati_to_include, true)) {
729
+                    unset($status_query_args[$status]);
730 730
                 }
731 731
             }
732 732
         }
733 733
         // loop through and query counts for each stati.
734 734
         $status_query_results = array();
735 735
         foreach ($status_query_args as $status => $status_where_conditions) {
736
-            $status_query_results[ $status ] = EEM_Datetime::count(
736
+            $status_query_results[$status] = EEM_Datetime::count(
737 737
                 array($status_where_conditions),
738 738
                 'DTT_ID',
739 739
                 true
@@ -754,6 +754,6 @@  discard block
 block discarded – undo
754 754
     public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
755 755
     {
756 756
         $count = $this->get_datetime_counts_by_status(array($status), $query_params);
757
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
757
+        return ! empty($count[$status]) ? $count[$status] : 0;
758 758
     }
759 759
 }
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/content-espresso_events-datetimes.php 1 patch
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -1,15 +1,15 @@
 block discarded – undo
1 1
 <?php
2 2
 //echo '<br/><h6 style="color:#2EA2CC;">'. __FILE__ . ' &nbsp; <span style="font-weight:normal;color:#E76700"> Line #: ' . __LINE__ . '</span></h6>';
3 3
 
4
-if ( is_single() || ( is_archive() && espresso_display_datetimes_in_event_list() ) ) :
4
+if (is_single() || (is_archive() && espresso_display_datetimes_in_event_list())) :
5 5
 global $post;
6
-do_action( 'AHEE_event_details_before_event_date', $post );
6
+do_action('AHEE_event_details_before_event_date', $post);
7 7
 ?>
8 8
 	<div class="event-datetimes">
9
-		<?php espresso_list_of_event_dates( $post->ID );?>
9
+		<?php espresso_list_of_event_dates($post->ID); ?>
10 10
 	</div>
11 11
 	<!-- .event-datetimes -->
12 12
 <?php
13
-do_action( 'AHEE_event_details_after_event_date', $post );
13
+do_action('AHEE_event_details_after_event_date', $post);
14 14
 endif;
15 15
 ?>
16 16
\ No newline at end of file
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1247,7 +1247,7 @@
 block discarded – undo
1247 1247
     /**
1248 1248
      * Sets up the limit for the registrations query.
1249 1249
      *
1250
-     * @param $per_page
1250
+     * @param integer $per_page
1251 1251
      * @return array
1252 1252
      */
1253 1253
     protected function _get_limit($per_page)
Please login to merge, or discard this patch.
Indentation   +3826 added lines, -3826 removed lines patch added patch discarded remove patch
@@ -19,2398 +19,2398 @@  discard block
 block discarded – undo
19 19
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * @var EE_Registration
24
-     */
25
-    private $_registration;
26
-
27
-    /**
28
-     * @var EE_Event
29
-     */
30
-    private $_reg_event;
31
-
32
-    /**
33
-     * @var EE_Session
34
-     */
35
-    private $_session;
36
-
37
-    private static $_reg_status;
38
-
39
-    /**
40
-     * Form for displaying the custom questions for this registration.
41
-     * This gets used a few times throughout the request so its best to cache it
42
-     *
43
-     * @var EE_Registration_Custom_Questions_Form
44
-     */
45
-    protected $_reg_custom_questions_form = null;
46
-
47
-
48
-    /**
49
-     *        constructor
50
-     *
51
-     * @Constructor
52
-     * @access public
53
-     * @param bool $routing
54
-     * @return Registrations_Admin_Page
55
-     */
56
-    public function __construct($routing = true)
57
-    {
58
-        parent::__construct($routing);
59
-        add_action('wp_loaded', array($this, 'wp_loaded'));
60
-    }
61
-
62
-
63
-    public function wp_loaded()
64
-    {
65
-        // when adding a new registration...
66
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
-            EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
69
-                || absint($this->_req_data['processing_registration']) !== 1
70
-            ) {
71
-                // and it's NOT the attendee information reg step
72
-                // force cookie expiration by setting time to last week
73
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
-                // and update the global
75
-                $_COOKIE['ee_registration_added'] = 0;
76
-            }
77
-        }
78
-    }
79
-
80
-
81
-    protected function _init_page_props()
82
-    {
83
-        $this->page_slug = REG_PG_SLUG;
84
-        $this->_admin_base_url = REG_ADMIN_URL;
85
-        $this->_admin_base_path = REG_ADMIN;
86
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
87
-        $this->_cpt_routes = array(
88
-            'add_new_attendee' => 'espresso_attendees',
89
-            'edit_attendee'    => 'espresso_attendees',
90
-            'insert_attendee'  => 'espresso_attendees',
91
-            'update_attendee'  => 'espresso_attendees',
92
-        );
93
-        $this->_cpt_model_names = array(
94
-            'add_new_attendee' => 'EEM_Attendee',
95
-            'edit_attendee'    => 'EEM_Attendee',
96
-        );
97
-        $this->_cpt_edit_routes = array(
98
-            'espresso_attendees' => 'edit_attendee',
99
-        );
100
-        $this->_pagenow_map = array(
101
-            'add_new_attendee' => 'post-new.php',
102
-            'edit_attendee'    => 'post.php',
103
-            'trash'            => 'post.php',
104
-        );
105
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
-        // add filters so that the comment urls don't take users to a confusing 404 page
107
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
-    }
109
-
110
-
111
-    public function clear_comment_link($link, $comment, $args)
112
-    {
113
-        // gotta make sure this only happens on this route
114
-        $post_type = get_post_type($comment->comment_post_ID);
115
-        if ($post_type === 'espresso_attendees') {
116
-            return '#commentsdiv';
117
-        }
118
-        return $link;
119
-    }
120
-
121
-
122
-    protected function _ajax_hooks()
123
-    {
124
-        // todo: all hooks for registrations ajax goes in here
125
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
-    }
127
-
128
-
129
-    protected function _define_page_props()
130
-    {
131
-        $this->_admin_page_title = $this->page_label;
132
-        $this->_labels = array(
133
-            'buttons'                      => array(
134
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
-            ),
143
-            'publishbox'                   => array(
144
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
-            ),
147
-            'hide_add_button_on_cpt_route' => array(
148
-                'edit_attendee' => true,
149
-            ),
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     *        grab url requests and route them
156
-     *
157
-     * @access private
158
-     * @return void
159
-     */
160
-    public function _set_page_routes()
161
-    {
162
-        $this->_get_registration_status_array();
163
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
-            ? $this->_req_data['_REG_ID'] : 0;
165
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
167
-            : $reg_id;
168
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
-            ? $this->_req_data['ATT_ID'] : 0;
170
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
-            ? $this->_req_data['post']
172
-            : $att_id;
173
-        $this->_page_routes = array(
174
-            'default'                             => array(
175
-                'func'       => '_registrations_overview_list_table',
176
-                'capability' => 'ee_read_registrations',
177
-            ),
178
-            'view_registration'                   => array(
179
-                'func'       => '_registration_details',
180
-                'capability' => 'ee_read_registration',
181
-                'obj_id'     => $reg_id,
182
-            ),
183
-            'edit_registration'                   => array(
184
-                'func'               => '_update_attendee_registration_form',
185
-                'noheader'           => true,
186
-                'headers_sent_route' => 'view_registration',
187
-                'capability'         => 'ee_edit_registration',
188
-                'obj_id'             => $reg_id,
189
-                '_REG_ID'            => $reg_id,
190
-            ),
191
-            'trash_registrations'                 => array(
192
-                'func'       => '_trash_or_restore_registrations',
193
-                'args'       => array('trash' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_delete_registrations',
196
-            ),
197
-            'restore_registrations'               => array(
198
-                'func'       => '_trash_or_restore_registrations',
199
-                'args'       => array('trash' => false),
200
-                'noheader'   => true,
201
-                'capability' => 'ee_delete_registrations',
202
-            ),
203
-            'delete_registrations'                => array(
204
-                'func'       => '_delete_registrations',
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'new_registration'                    => array(
209
-                'func'       => 'new_registration',
210
-                'capability' => 'ee_edit_registrations',
211
-            ),
212
-            'process_reg_step'                    => array(
213
-                'func'       => 'process_reg_step',
214
-                'noheader'   => true,
215
-                'capability' => 'ee_edit_registrations',
216
-            ),
217
-            'redirect_to_txn'                     => array(
218
-                'func'       => 'redirect_to_txn',
219
-                'noheader'   => true,
220
-                'capability' => 'ee_edit_registrations',
221
-            ),
222
-            'change_reg_status'                   => array(
223
-                'func'       => '_change_reg_status',
224
-                'noheader'   => true,
225
-                'capability' => 'ee_edit_registration',
226
-                'obj_id'     => $reg_id,
227
-            ),
228
-            'approve_registration'                => array(
229
-                'func'       => 'approve_registration',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registration',
232
-                'obj_id'     => $reg_id,
233
-            ),
234
-            'approve_and_notify_registration'     => array(
235
-                'func'       => 'approve_registration',
236
-                'noheader'   => true,
237
-                'args'       => array(true),
238
-                'capability' => 'ee_edit_registration',
239
-                'obj_id'     => $reg_id,
240
-            ),
241
-            'approve_registrations'               => array(
242
-                'func'       => 'bulk_action_on_registrations',
243
-                'noheader'   => true,
244
-                'capability' => 'ee_edit_registrations',
245
-                'args'       => array('approve'),
246
-            ),
247
-            'approve_and_notify_registrations'    => array(
248
-                'func'       => 'bulk_action_on_registrations',
249
-                'noheader'   => true,
250
-                'capability' => 'ee_edit_registrations',
251
-                'args'       => array('approve', true),
252
-            ),
253
-            'decline_registration'                => array(
254
-                'func'       => 'decline_registration',
255
-                'noheader'   => true,
256
-                'capability' => 'ee_edit_registration',
257
-                'obj_id'     => $reg_id,
258
-            ),
259
-            'decline_and_notify_registration'     => array(
260
-                'func'       => 'decline_registration',
261
-                'noheader'   => true,
262
-                'args'       => array(true),
263
-                'capability' => 'ee_edit_registration',
264
-                'obj_id'     => $reg_id,
265
-            ),
266
-            'decline_registrations'               => array(
267
-                'func'       => 'bulk_action_on_registrations',
268
-                'noheader'   => true,
269
-                'capability' => 'ee_edit_registrations',
270
-                'args'       => array('decline'),
271
-            ),
272
-            'decline_and_notify_registrations'    => array(
273
-                'func'       => 'bulk_action_on_registrations',
274
-                'noheader'   => true,
275
-                'capability' => 'ee_edit_registrations',
276
-                'args'       => array('decline', true),
277
-            ),
278
-            'pending_registration'                => array(
279
-                'func'       => 'pending_registration',
280
-                'noheader'   => true,
281
-                'capability' => 'ee_edit_registration',
282
-                'obj_id'     => $reg_id,
283
-            ),
284
-            'pending_and_notify_registration'     => array(
285
-                'func'       => 'pending_registration',
286
-                'noheader'   => true,
287
-                'args'       => array(true),
288
-                'capability' => 'ee_edit_registration',
289
-                'obj_id'     => $reg_id,
290
-            ),
291
-            'pending_registrations'               => array(
292
-                'func'       => 'bulk_action_on_registrations',
293
-                'noheader'   => true,
294
-                'capability' => 'ee_edit_registrations',
295
-                'args'       => array('pending'),
296
-            ),
297
-            'pending_and_notify_registrations'    => array(
298
-                'func'       => 'bulk_action_on_registrations',
299
-                'noheader'   => true,
300
-                'capability' => 'ee_edit_registrations',
301
-                'args'       => array('pending', true),
302
-            ),
303
-            'no_approve_registration'             => array(
304
-                'func'       => 'not_approve_registration',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'no_approve_and_notify_registration'  => array(
310
-                'func'       => 'not_approve_registration',
311
-                'noheader'   => true,
312
-                'args'       => array(true),
313
-                'capability' => 'ee_edit_registration',
314
-                'obj_id'     => $reg_id,
315
-            ),
316
-            'no_approve_registrations'            => array(
317
-                'func'       => 'bulk_action_on_registrations',
318
-                'noheader'   => true,
319
-                'capability' => 'ee_edit_registrations',
320
-                'args'       => array('not_approve'),
321
-            ),
322
-            'no_approve_and_notify_registrations' => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('not_approve', true),
327
-            ),
328
-            'cancel_registration'                 => array(
329
-                'func'       => 'cancel_registration',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registration',
332
-                'obj_id'     => $reg_id,
333
-            ),
334
-            'cancel_and_notify_registration'      => array(
335
-                'func'       => 'cancel_registration',
336
-                'noheader'   => true,
337
-                'args'       => array(true),
338
-                'capability' => 'ee_edit_registration',
339
-                'obj_id'     => $reg_id,
340
-            ),
341
-            'cancel_registrations'                => array(
342
-                'func'       => 'bulk_action_on_registrations',
343
-                'noheader'   => true,
344
-                'capability' => 'ee_edit_registrations',
345
-                'args'       => array('cancel'),
346
-            ),
347
-            'cancel_and_notify_registrations'     => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('cancel', true),
352
-            ),
353
-            'wait_list_registration'              => array(
354
-                'func'       => 'wait_list_registration',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registration',
357
-                'obj_id'     => $reg_id,
358
-            ),
359
-            'wait_list_and_notify_registration'   => array(
360
-                'func'       => 'wait_list_registration',
361
-                'noheader'   => true,
362
-                'args'       => array(true),
363
-                'capability' => 'ee_edit_registration',
364
-                'obj_id'     => $reg_id,
365
-            ),
366
-            'contact_list'                        => array(
367
-                'func'       => '_attendee_contact_list_table',
368
-                'capability' => 'ee_read_contacts',
369
-            ),
370
-            'add_new_attendee'                    => array(
371
-                'func' => '_create_new_cpt_item',
372
-                'args' => array(
373
-                    'new_attendee' => true,
374
-                    'capability'   => 'ee_edit_contacts',
375
-                ),
376
-            ),
377
-            'edit_attendee'                       => array(
378
-                'func'       => '_edit_cpt_item',
379
-                'capability' => 'ee_edit_contacts',
380
-                'obj_id'     => $att_id,
381
-            ),
382
-            'duplicate_attendee'                  => array(
383
-                'func'       => '_duplicate_attendee',
384
-                'noheader'   => true,
385
-                'capability' => 'ee_edit_contacts',
386
-                'obj_id'     => $att_id,
387
-            ),
388
-            'insert_attendee'                     => array(
389
-                'func'       => '_insert_or_update_attendee',
390
-                'args'       => array(
391
-                    'new_attendee' => true,
392
-                ),
393
-                'noheader'   => true,
394
-                'capability' => 'ee_edit_contacts',
395
-            ),
396
-            'update_attendee'                     => array(
397
-                'func'       => '_insert_or_update_attendee',
398
-                'args'       => array(
399
-                    'new_attendee' => false,
400
-                ),
401
-                'noheader'   => true,
402
-                'capability' => 'ee_edit_contacts',
403
-                'obj_id'     => $att_id,
404
-            ),
405
-            'trash_attendees'                     => array(
406
-                'func'       => '_trash_or_restore_attendees',
407
-                'args'       => array(
408
-                    'trash' => 'true',
409
-                ),
410
-                'noheader'   => true,
411
-                'capability' => 'ee_delete_contacts',
412
-            ),
413
-            'trash_attendee'                      => array(
414
-                'func'       => '_trash_or_restore_attendees',
415
-                'args'       => array(
416
-                    'trash' => true,
417
-                ),
418
-                'noheader'   => true,
419
-                'capability' => 'ee_delete_contacts',
420
-                'obj_id'     => $att_id,
421
-            ),
422
-            'restore_attendees'                   => array(
423
-                'func'       => '_trash_or_restore_attendees',
424
-                'args'       => array(
425
-                    'trash' => false,
426
-                ),
427
-                'noheader'   => true,
428
-                'capability' => 'ee_delete_contacts',
429
-                'obj_id'     => $att_id,
430
-            ),
431
-            'resend_registration'                 => array(
432
-                'func'       => '_resend_registration',
433
-                'noheader'   => true,
434
-                'capability' => 'ee_send_message',
435
-            ),
436
-            'registrations_report'                => array(
437
-                'func'       => '_registrations_report',
438
-                'noheader'   => true,
439
-                'capability' => 'ee_read_registrations',
440
-            ),
441
-            'contact_list_export'                 => array(
442
-                'func'       => '_contact_list_export',
443
-                'noheader'   => true,
444
-                'capability' => 'export',
445
-            ),
446
-            'contact_list_report'                 => array(
447
-                'func'       => '_contact_list_report',
448
-                'noheader'   => true,
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-        );
452
-    }
453
-
454
-
455
-    protected function _set_page_config()
456
-    {
457
-        $this->_page_config = array(
458
-            'default'           => array(
459
-                'nav'           => array(
460
-                    'label' => esc_html__('Overview', 'event_espresso'),
461
-                    'order' => 5,
462
-                ),
463
-                'help_tabs'     => array(
464
-                    'registrations_overview_help_tab'                       => array(
465
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
-                        'filename' => 'registrations_overview',
467
-                    ),
468
-                    'registrations_overview_table_column_headings_help_tab' => array(
469
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
-                        'filename' => 'registrations_overview_table_column_headings',
471
-                    ),
472
-                    'registrations_overview_filters_help_tab'               => array(
473
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
-                        'filename' => 'registrations_overview_filters',
475
-                    ),
476
-                    'registrations_overview_views_help_tab'                 => array(
477
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
478
-                        'filename' => 'registrations_overview_views',
479
-                    ),
480
-                    'registrations_regoverview_other_help_tab'              => array(
481
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
-                        'filename' => 'registrations_overview_other',
483
-                    ),
484
-                ),
485
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
486
-                'qtips'         => array('Registration_List_Table_Tips'),
487
-                'list_table'    => 'EE_Registrations_List_Table',
488
-                'require_nonce' => false,
489
-            ),
490
-            'view_registration' => array(
491
-                'nav'           => array(
492
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
493
-                    'order'      => 15,
494
-                    'url'        => isset($this->_req_data['_REG_ID'])
495
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
-                        : $this->_admin_base_url,
497
-                    'persistent' => false,
498
-                ),
499
-                'help_tabs'     => array(
500
-                    'registrations_details_help_tab'                    => array(
501
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
502
-                        'filename' => 'registrations_details',
503
-                    ),
504
-                    'registrations_details_table_help_tab'              => array(
505
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
-                        'filename' => 'registrations_details_table',
507
-                    ),
508
-                    'registrations_details_form_answers_help_tab'       => array(
509
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
-                        'filename' => 'registrations_details_form_answers',
511
-                    ),
512
-                    'registrations_details_registrant_details_help_tab' => array(
513
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
514
-                        'filename' => 'registrations_details_registrant_details',
515
-                    ),
516
-                ),
517
-                'help_tour'     => array('Registration_Details_Help_Tour'),
518
-                'metaboxes'     => array_merge(
519
-                    $this->_default_espresso_metaboxes,
520
-                    array('_registration_details_metaboxes')
521
-                ),
522
-                'require_nonce' => false,
523
-            ),
524
-            'new_registration'  => array(
525
-                'nav'           => array(
526
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
-                    'url'        => '#',
528
-                    'order'      => 15,
529
-                    'persistent' => false,
530
-                ),
531
-                'metaboxes'     => $this->_default_espresso_metaboxes,
532
-                'labels'        => array(
533
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
-                ),
535
-                'require_nonce' => false,
536
-            ),
537
-            'add_new_attendee'  => array(
538
-                'nav'           => array(
539
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
540
-                    'order'      => 15,
541
-                    'persistent' => false,
542
-                ),
543
-                'metaboxes'     => array_merge(
544
-                    $this->_default_espresso_metaboxes,
545
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
546
-                ),
547
-                'require_nonce' => false,
548
-            ),
549
-            'edit_attendee'     => array(
550
-                'nav'           => array(
551
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
-                    'order'      => 15,
553
-                    'persistent' => false,
554
-                    'url'        => isset($this->_req_data['ATT_ID'])
555
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
-                        : $this->_admin_base_url,
557
-                ),
558
-                'metaboxes'     => array('attendee_editor_metaboxes'),
559
-                'require_nonce' => false,
560
-            ),
561
-            'contact_list'      => array(
562
-                'nav'           => array(
563
-                    'label' => esc_html__('Contact List', 'event_espresso'),
564
-                    'order' => 20,
565
-                ),
566
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
567
-                'help_tabs'     => array(
568
-                    'registrations_contact_list_help_tab'                       => array(
569
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
-                        'filename' => 'registrations_contact_list',
571
-                    ),
572
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
573
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
-                        'filename' => 'registrations_contact_list_table_column_headings',
575
-                    ),
576
-                    'registrations_contact_list_views_help_tab'                 => array(
577
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
-                        'filename' => 'registrations_contact_list_views',
579
-                    ),
580
-                    'registrations_contact_list_other_help_tab'                 => array(
581
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
-                        'filename' => 'registrations_contact_list_other',
583
-                    ),
584
-                ),
585
-                'help_tour'     => array('Contact_List_Help_Tour'),
586
-                'metaboxes'     => array(),
587
-                'require_nonce' => false,
588
-            ),
589
-            // override default cpt routes
590
-            'create_new'        => '',
591
-            'edit'              => '',
592
-        );
593
-    }
594
-
595
-
596
-    /**
597
-     * The below methods aren't used by this class currently
598
-     */
599
-    protected function _add_screen_options()
600
-    {
601
-    }
602
-
603
-
604
-    protected function _add_feature_pointers()
605
-    {
606
-    }
607
-
608
-
609
-    public function admin_init()
610
-    {
611
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
-            'click "Update Registration Questions" to save your changes',
613
-            'event_espresso'
614
-        );
615
-    }
616
-
617
-
618
-    public function admin_notices()
619
-    {
620
-    }
621
-
622
-
623
-    public function admin_footer_scripts()
624
-    {
625
-    }
626
-
627
-
628
-    /**
629
-     *        get list of registration statuses
630
-     *
631
-     * @access private
632
-     * @return void
633
-     * @throws EE_Error
634
-     */
635
-    private function _get_registration_status_array()
636
-    {
637
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
-    }
639
-
640
-
641
-    protected function _add_screen_options_default()
642
-    {
643
-        $this->_per_page_screen_option();
644
-    }
645
-
646
-
647
-    protected function _add_screen_options_contact_list()
648
-    {
649
-        $page_title = $this->_admin_page_title;
650
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
-        $this->_per_page_screen_option();
652
-        $this->_admin_page_title = $page_title;
653
-    }
654
-
655
-
656
-    public function load_scripts_styles()
657
-    {
658
-        // style
659
-        wp_register_style(
660
-            'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
-            array('ee-admin-css'),
663
-            EVENT_ESPRESSO_VERSION
664
-        );
665
-        wp_enqueue_style('espresso_reg');
666
-        // script
667
-        wp_register_script(
668
-            'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
-            EVENT_ESPRESSO_VERSION,
672
-            true
673
-        );
674
-        wp_enqueue_script('espresso_reg');
675
-    }
676
-
677
-
678
-    public function load_scripts_styles_edit_attendee()
679
-    {
680
-        // stuff to only show up on our attendee edit details page.
681
-        $attendee_details_translations = array(
682
-            'att_publish_text' => sprintf(
683
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
-                $this->_cpt_model_obj->get_datetime('ATT_created')
685
-            ),
686
-        );
687
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
-        wp_enqueue_script('jquery-validate');
689
-    }
690
-
691
-
692
-    public function load_scripts_styles_view_registration()
693
-    {
694
-        // styles
695
-        wp_enqueue_style('espresso-ui-theme');
696
-        // scripts
697
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
698
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
-    }
700
-
701
-
702
-    public function load_scripts_styles_contact_list()
703
-    {
704
-        wp_dequeue_style('espresso_reg');
705
-        wp_register_style(
706
-            'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
-            array('ee-admin-css'),
709
-            EVENT_ESPRESSO_VERSION
710
-        );
711
-        wp_enqueue_style('espresso_att');
712
-    }
713
-
714
-
715
-    public function load_scripts_styles_new_registration()
716
-    {
717
-        wp_register_script(
718
-            'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
720
-            array('underscore', 'jquery'),
721
-            EVENT_ESPRESSO_VERSION,
722
-            true
723
-        );
724
-        wp_enqueue_script('ee-spco-for-admin');
725
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
-        EE_Form_Section_Proper::wp_enqueue_scripts();
727
-        EED_Ticket_Selector::load_tckt_slctr_assets();
728
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
729
-    }
730
-
731
-
732
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
-    {
734
-        add_filter('FHEE_load_EE_messages', '__return_true');
735
-    }
736
-
737
-
738
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
-    {
740
-        add_filter('FHEE_load_EE_messages', '__return_true');
741
-    }
742
-
743
-
744
-    protected function _set_list_table_views_default()
745
-    {
746
-        // for notification related bulk actions we need to make sure only active messengers have an option.
747
-        EED_Messages::set_autoloaders();
748
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
749
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
-        $active_mts = $message_resource_manager->list_of_active_message_types();
751
-        // key= bulk_action_slug, value= message type.
752
-        $match_array = array(
753
-            'approve_registrations'    => 'registration',
754
-            'decline_registrations'    => 'declined_registration',
755
-            'pending_registrations'    => 'pending_approval',
756
-            'no_approve_registrations' => 'not_approved_registration',
757
-            'cancel_registrations'     => 'cancelled_registration',
758
-        );
759
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
760
-            'ee_send_message',
761
-            'batch_send_messages'
762
-        );
763
-        /** setup reg status bulk actions **/
764
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
-                'Approve and Notify Registrations',
768
-                'event_espresso'
769
-            );
770
-        }
771
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
-                'Decline and Notify Registrations',
775
-                'event_espresso'
776
-            );
777
-        }
778
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
779
-            'Set Registrations to Pending Payment',
780
-            'event_espresso'
781
-        );
782
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
-                'Set Registrations to Pending Payment and Notify',
785
-                'event_espresso'
786
-            );
787
-        }
788
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
-            'Set Registrations to Not Approved',
790
-            'event_espresso'
791
-        );
792
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
-                'Set Registrations to Not Approved and Notify',
795
-                'event_espresso'
796
-            );
797
-        }
798
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
-                'Cancel Registrations and Notify',
802
-                'event_espresso'
803
-            );
804
-        }
805
-        $def_reg_status_actions = apply_filters(
806
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
-            $def_reg_status_actions,
808
-            $active_mts,
809
-            $can_send
810
-        );
811
-
812
-        $this->_views = array(
813
-            'all'   => array(
814
-                'slug'        => 'all',
815
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
-                'count'       => 0,
817
-                'bulk_action' => array_merge(
818
-                    $def_reg_status_actions,
819
-                    array(
820
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
-                    )
822
-                ),
823
-            ),
824
-            'month' => array(
825
-                'slug'        => 'month',
826
-                'label'       => esc_html__('This Month', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge(
829
-                    $def_reg_status_actions,
830
-                    array(
831
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
-                    )
833
-                ),
834
-            ),
835
-            'today' => array(
836
-                'slug'        => 'today',
837
-                'label'       => sprintf(
838
-                    esc_html__('Today - %s', 'event_espresso'),
839
-                    date('M d, Y', current_time('timestamp'))
840
-                ),
841
-                'count'       => 0,
842
-                'bulk_action' => array_merge(
843
-                    $def_reg_status_actions,
844
-                    array(
845
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
-                    )
847
-                ),
848
-            ),
849
-        );
850
-        if (EE_Registry::instance()->CAP->current_user_can(
851
-            'ee_delete_registrations',
852
-            'espresso_registrations_delete_registration'
853
-        )) {
854
-            $this->_views['incomplete'] = array(
855
-                'slug'        => 'incomplete',
856
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => array(
859
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
-                ),
861
-            );
862
-            $this->_views['trash'] = array(
863
-                'slug'        => 'trash',
864
-                'label'       => esc_html__('Trash', 'event_espresso'),
865
-                'count'       => 0,
866
-                'bulk_action' => array(
867
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
-                ),
870
-            );
871
-        }
872
-    }
873
-
874
-
875
-    protected function _set_list_table_views_contact_list()
876
-    {
877
-        $this->_views = array(
878
-            'in_use' => array(
879
-                'slug'        => 'in_use',
880
-                'label'       => esc_html__('In Use', 'event_espresso'),
881
-                'count'       => 0,
882
-                'bulk_action' => array(
883
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
-                ),
885
-            ),
886
-        );
887
-        if (EE_Registry::instance()->CAP->current_user_can(
888
-            'ee_delete_contacts',
889
-            'espresso_registrations_trash_attendees'
890
-        )
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post'   => $ATT_ID,
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                    . EE_Admin_Page::add_query_args_and_nonce(
1070
-                        array(
1071
-                            'action' => 'edit',
1072
-                            'post'   => $event->ID(),
1073
-                        ),
1074
-                        EVENTS_ADMIN_URL
1075
-                    )
1076
-                    . '">&nbsp;'
1077
-                    . $event->get('EVT_name')
1078
-                    . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        // get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         *
1166
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
-         *                             or if you have the development copy of EE you can view this at the path:
1169
-         *                             /docs/G--Model-System/model-query-params.md
1170
-         */
1171
-        $query_params['group_by'] = '';
1172
-
1173
-        return $count
1174
-            ? EEM_Registration::instance()->count($query_params)
1175
-            /** @type EE_Registration[] */
1176
-            : EEM_Registration::instance()->get_all($query_params);
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
-     * Note: this listens to values on the request for some of the query parameters.
1183
-     *
1184
-     * @param array $request
1185
-     * @param int   $per_page
1186
-     * @param bool  $count
1187
-     * @return array
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _get_registration_query_parameters(
1191
-        $request = array(),
1192
-        $per_page = 10,
1193
-        $count = false
1194
-    ) {
1195
-
1196
-        $query_params = array(
1197
-            0                          => $this->_get_where_conditions_for_registrations_query(
1198
-                $request
1199
-            ),
1200
-            'caps'                     => EEM_Registration::caps_read_admin,
1201
-            'default_where_conditions' => 'this_model_only',
1202
-        );
1203
-        if (! $count) {
1204
-            $query_params = array_merge(
1205
-                $query_params,
1206
-                $this->_get_orderby_for_registrations_query(),
1207
-                $this->_get_limit($per_page)
1208
-            );
1209
-        }
1210
-
1211
-        return $query_params;
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
-     *
1218
-     * @param array $request usually the same as $this->_req_data but not necessarily
1219
-     * @return array
1220
-     */
1221
-    protected function addAttendeeIdToWhereConditions(array $request)
1222
-    {
1223
-        $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1225
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1226
-        }
1227
-        return $where;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
-     *
1234
-     * @param array $request usually the same as $this->_req_data but not necessarily
1235
-     * @return array
1236
-     */
1237
-    protected function _add_event_id_to_where_conditions(array $request)
1238
-    {
1239
-        $where = array();
1240
-        if (! empty($request['event_id'])) {
1241
-            $where['EVT_ID'] = absint($request['event_id']);
1242
-        }
1243
-        return $where;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
-     *
1250
-     * @param array $request usually the same as $this->_req_data but not necessarily
1251
-     * @return array
1252
-     */
1253
-    protected function _add_category_id_to_where_conditions(array $request)
1254
-    {
1255
-        $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
-        }
1259
-        return $where;
1260
-    }
1261
-
1262
-
1263
-    /**
1264
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
-     *
1266
-     * @param array $request usually the same as $this->_req_data but not necessarily
1267
-     * @return array
1268
-     */
1269
-    protected function _add_datetime_id_to_where_conditions(array $request)
1270
-    {
1271
-        $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
-        }
1275
-        if (! empty($request['DTT_ID'])) {
1276
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
-        }
1278
-        return $where;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * Adds the correct registration status to the where conditions for the registrations query.
1284
-     *
1285
-     * @param array $request usually the same as $this->_req_data but not necessarily
1286
-     * @return array
1287
-     */
1288
-    protected function _add_registration_status_to_where_conditions(array $request)
1289
-    {
1290
-        $where = array();
1291
-        $view = EEH_Array::is_set($request, 'status', '');
1292
-        $registration_status = ! empty($request['_reg_status'])
1293
-            ? sanitize_text_field($request['_reg_status'])
1294
-            : '';
1295
-
1296
-        /*
22
+	/**
23
+	 * @var EE_Registration
24
+	 */
25
+	private $_registration;
26
+
27
+	/**
28
+	 * @var EE_Event
29
+	 */
30
+	private $_reg_event;
31
+
32
+	/**
33
+	 * @var EE_Session
34
+	 */
35
+	private $_session;
36
+
37
+	private static $_reg_status;
38
+
39
+	/**
40
+	 * Form for displaying the custom questions for this registration.
41
+	 * This gets used a few times throughout the request so its best to cache it
42
+	 *
43
+	 * @var EE_Registration_Custom_Questions_Form
44
+	 */
45
+	protected $_reg_custom_questions_form = null;
46
+
47
+
48
+	/**
49
+	 *        constructor
50
+	 *
51
+	 * @Constructor
52
+	 * @access public
53
+	 * @param bool $routing
54
+	 * @return Registrations_Admin_Page
55
+	 */
56
+	public function __construct($routing = true)
57
+	{
58
+		parent::__construct($routing);
59
+		add_action('wp_loaded', array($this, 'wp_loaded'));
60
+	}
61
+
62
+
63
+	public function wp_loaded()
64
+	{
65
+		// when adding a new registration...
66
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
+			EE_System::do_not_cache();
68
+			if (! isset($this->_req_data['processing_registration'])
69
+				|| absint($this->_req_data['processing_registration']) !== 1
70
+			) {
71
+				// and it's NOT the attendee information reg step
72
+				// force cookie expiration by setting time to last week
73
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
+				// and update the global
75
+				$_COOKIE['ee_registration_added'] = 0;
76
+			}
77
+		}
78
+	}
79
+
80
+
81
+	protected function _init_page_props()
82
+	{
83
+		$this->page_slug = REG_PG_SLUG;
84
+		$this->_admin_base_url = REG_ADMIN_URL;
85
+		$this->_admin_base_path = REG_ADMIN;
86
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
87
+		$this->_cpt_routes = array(
88
+			'add_new_attendee' => 'espresso_attendees',
89
+			'edit_attendee'    => 'espresso_attendees',
90
+			'insert_attendee'  => 'espresso_attendees',
91
+			'update_attendee'  => 'espresso_attendees',
92
+		);
93
+		$this->_cpt_model_names = array(
94
+			'add_new_attendee' => 'EEM_Attendee',
95
+			'edit_attendee'    => 'EEM_Attendee',
96
+		);
97
+		$this->_cpt_edit_routes = array(
98
+			'espresso_attendees' => 'edit_attendee',
99
+		);
100
+		$this->_pagenow_map = array(
101
+			'add_new_attendee' => 'post-new.php',
102
+			'edit_attendee'    => 'post.php',
103
+			'trash'            => 'post.php',
104
+		);
105
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
+		// add filters so that the comment urls don't take users to a confusing 404 page
107
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
+	}
109
+
110
+
111
+	public function clear_comment_link($link, $comment, $args)
112
+	{
113
+		// gotta make sure this only happens on this route
114
+		$post_type = get_post_type($comment->comment_post_ID);
115
+		if ($post_type === 'espresso_attendees') {
116
+			return '#commentsdiv';
117
+		}
118
+		return $link;
119
+	}
120
+
121
+
122
+	protected function _ajax_hooks()
123
+	{
124
+		// todo: all hooks for registrations ajax goes in here
125
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
+	}
127
+
128
+
129
+	protected function _define_page_props()
130
+	{
131
+		$this->_admin_page_title = $this->page_label;
132
+		$this->_labels = array(
133
+			'buttons'                      => array(
134
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
+			),
143
+			'publishbox'                   => array(
144
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
+			),
147
+			'hide_add_button_on_cpt_route' => array(
148
+				'edit_attendee' => true,
149
+			),
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 *        grab url requests and route them
156
+	 *
157
+	 * @access private
158
+	 * @return void
159
+	 */
160
+	public function _set_page_routes()
161
+	{
162
+		$this->_get_registration_status_array();
163
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
+			? $this->_req_data['_REG_ID'] : 0;
165
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
+			? $this->_req_data['reg_status_change_form']['REG_ID']
167
+			: $reg_id;
168
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
+			? $this->_req_data['ATT_ID'] : 0;
170
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
+			? $this->_req_data['post']
172
+			: $att_id;
173
+		$this->_page_routes = array(
174
+			'default'                             => array(
175
+				'func'       => '_registrations_overview_list_table',
176
+				'capability' => 'ee_read_registrations',
177
+			),
178
+			'view_registration'                   => array(
179
+				'func'       => '_registration_details',
180
+				'capability' => 'ee_read_registration',
181
+				'obj_id'     => $reg_id,
182
+			),
183
+			'edit_registration'                   => array(
184
+				'func'               => '_update_attendee_registration_form',
185
+				'noheader'           => true,
186
+				'headers_sent_route' => 'view_registration',
187
+				'capability'         => 'ee_edit_registration',
188
+				'obj_id'             => $reg_id,
189
+				'_REG_ID'            => $reg_id,
190
+			),
191
+			'trash_registrations'                 => array(
192
+				'func'       => '_trash_or_restore_registrations',
193
+				'args'       => array('trash' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_delete_registrations',
196
+			),
197
+			'restore_registrations'               => array(
198
+				'func'       => '_trash_or_restore_registrations',
199
+				'args'       => array('trash' => false),
200
+				'noheader'   => true,
201
+				'capability' => 'ee_delete_registrations',
202
+			),
203
+			'delete_registrations'                => array(
204
+				'func'       => '_delete_registrations',
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'new_registration'                    => array(
209
+				'func'       => 'new_registration',
210
+				'capability' => 'ee_edit_registrations',
211
+			),
212
+			'process_reg_step'                    => array(
213
+				'func'       => 'process_reg_step',
214
+				'noheader'   => true,
215
+				'capability' => 'ee_edit_registrations',
216
+			),
217
+			'redirect_to_txn'                     => array(
218
+				'func'       => 'redirect_to_txn',
219
+				'noheader'   => true,
220
+				'capability' => 'ee_edit_registrations',
221
+			),
222
+			'change_reg_status'                   => array(
223
+				'func'       => '_change_reg_status',
224
+				'noheader'   => true,
225
+				'capability' => 'ee_edit_registration',
226
+				'obj_id'     => $reg_id,
227
+			),
228
+			'approve_registration'                => array(
229
+				'func'       => 'approve_registration',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registration',
232
+				'obj_id'     => $reg_id,
233
+			),
234
+			'approve_and_notify_registration'     => array(
235
+				'func'       => 'approve_registration',
236
+				'noheader'   => true,
237
+				'args'       => array(true),
238
+				'capability' => 'ee_edit_registration',
239
+				'obj_id'     => $reg_id,
240
+			),
241
+			'approve_registrations'               => array(
242
+				'func'       => 'bulk_action_on_registrations',
243
+				'noheader'   => true,
244
+				'capability' => 'ee_edit_registrations',
245
+				'args'       => array('approve'),
246
+			),
247
+			'approve_and_notify_registrations'    => array(
248
+				'func'       => 'bulk_action_on_registrations',
249
+				'noheader'   => true,
250
+				'capability' => 'ee_edit_registrations',
251
+				'args'       => array('approve', true),
252
+			),
253
+			'decline_registration'                => array(
254
+				'func'       => 'decline_registration',
255
+				'noheader'   => true,
256
+				'capability' => 'ee_edit_registration',
257
+				'obj_id'     => $reg_id,
258
+			),
259
+			'decline_and_notify_registration'     => array(
260
+				'func'       => 'decline_registration',
261
+				'noheader'   => true,
262
+				'args'       => array(true),
263
+				'capability' => 'ee_edit_registration',
264
+				'obj_id'     => $reg_id,
265
+			),
266
+			'decline_registrations'               => array(
267
+				'func'       => 'bulk_action_on_registrations',
268
+				'noheader'   => true,
269
+				'capability' => 'ee_edit_registrations',
270
+				'args'       => array('decline'),
271
+			),
272
+			'decline_and_notify_registrations'    => array(
273
+				'func'       => 'bulk_action_on_registrations',
274
+				'noheader'   => true,
275
+				'capability' => 'ee_edit_registrations',
276
+				'args'       => array('decline', true),
277
+			),
278
+			'pending_registration'                => array(
279
+				'func'       => 'pending_registration',
280
+				'noheader'   => true,
281
+				'capability' => 'ee_edit_registration',
282
+				'obj_id'     => $reg_id,
283
+			),
284
+			'pending_and_notify_registration'     => array(
285
+				'func'       => 'pending_registration',
286
+				'noheader'   => true,
287
+				'args'       => array(true),
288
+				'capability' => 'ee_edit_registration',
289
+				'obj_id'     => $reg_id,
290
+			),
291
+			'pending_registrations'               => array(
292
+				'func'       => 'bulk_action_on_registrations',
293
+				'noheader'   => true,
294
+				'capability' => 'ee_edit_registrations',
295
+				'args'       => array('pending'),
296
+			),
297
+			'pending_and_notify_registrations'    => array(
298
+				'func'       => 'bulk_action_on_registrations',
299
+				'noheader'   => true,
300
+				'capability' => 'ee_edit_registrations',
301
+				'args'       => array('pending', true),
302
+			),
303
+			'no_approve_registration'             => array(
304
+				'func'       => 'not_approve_registration',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'no_approve_and_notify_registration'  => array(
310
+				'func'       => 'not_approve_registration',
311
+				'noheader'   => true,
312
+				'args'       => array(true),
313
+				'capability' => 'ee_edit_registration',
314
+				'obj_id'     => $reg_id,
315
+			),
316
+			'no_approve_registrations'            => array(
317
+				'func'       => 'bulk_action_on_registrations',
318
+				'noheader'   => true,
319
+				'capability' => 'ee_edit_registrations',
320
+				'args'       => array('not_approve'),
321
+			),
322
+			'no_approve_and_notify_registrations' => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('not_approve', true),
327
+			),
328
+			'cancel_registration'                 => array(
329
+				'func'       => 'cancel_registration',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registration',
332
+				'obj_id'     => $reg_id,
333
+			),
334
+			'cancel_and_notify_registration'      => array(
335
+				'func'       => 'cancel_registration',
336
+				'noheader'   => true,
337
+				'args'       => array(true),
338
+				'capability' => 'ee_edit_registration',
339
+				'obj_id'     => $reg_id,
340
+			),
341
+			'cancel_registrations'                => array(
342
+				'func'       => 'bulk_action_on_registrations',
343
+				'noheader'   => true,
344
+				'capability' => 'ee_edit_registrations',
345
+				'args'       => array('cancel'),
346
+			),
347
+			'cancel_and_notify_registrations'     => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('cancel', true),
352
+			),
353
+			'wait_list_registration'              => array(
354
+				'func'       => 'wait_list_registration',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registration',
357
+				'obj_id'     => $reg_id,
358
+			),
359
+			'wait_list_and_notify_registration'   => array(
360
+				'func'       => 'wait_list_registration',
361
+				'noheader'   => true,
362
+				'args'       => array(true),
363
+				'capability' => 'ee_edit_registration',
364
+				'obj_id'     => $reg_id,
365
+			),
366
+			'contact_list'                        => array(
367
+				'func'       => '_attendee_contact_list_table',
368
+				'capability' => 'ee_read_contacts',
369
+			),
370
+			'add_new_attendee'                    => array(
371
+				'func' => '_create_new_cpt_item',
372
+				'args' => array(
373
+					'new_attendee' => true,
374
+					'capability'   => 'ee_edit_contacts',
375
+				),
376
+			),
377
+			'edit_attendee'                       => array(
378
+				'func'       => '_edit_cpt_item',
379
+				'capability' => 'ee_edit_contacts',
380
+				'obj_id'     => $att_id,
381
+			),
382
+			'duplicate_attendee'                  => array(
383
+				'func'       => '_duplicate_attendee',
384
+				'noheader'   => true,
385
+				'capability' => 'ee_edit_contacts',
386
+				'obj_id'     => $att_id,
387
+			),
388
+			'insert_attendee'                     => array(
389
+				'func'       => '_insert_or_update_attendee',
390
+				'args'       => array(
391
+					'new_attendee' => true,
392
+				),
393
+				'noheader'   => true,
394
+				'capability' => 'ee_edit_contacts',
395
+			),
396
+			'update_attendee'                     => array(
397
+				'func'       => '_insert_or_update_attendee',
398
+				'args'       => array(
399
+					'new_attendee' => false,
400
+				),
401
+				'noheader'   => true,
402
+				'capability' => 'ee_edit_contacts',
403
+				'obj_id'     => $att_id,
404
+			),
405
+			'trash_attendees'                     => array(
406
+				'func'       => '_trash_or_restore_attendees',
407
+				'args'       => array(
408
+					'trash' => 'true',
409
+				),
410
+				'noheader'   => true,
411
+				'capability' => 'ee_delete_contacts',
412
+			),
413
+			'trash_attendee'                      => array(
414
+				'func'       => '_trash_or_restore_attendees',
415
+				'args'       => array(
416
+					'trash' => true,
417
+				),
418
+				'noheader'   => true,
419
+				'capability' => 'ee_delete_contacts',
420
+				'obj_id'     => $att_id,
421
+			),
422
+			'restore_attendees'                   => array(
423
+				'func'       => '_trash_or_restore_attendees',
424
+				'args'       => array(
425
+					'trash' => false,
426
+				),
427
+				'noheader'   => true,
428
+				'capability' => 'ee_delete_contacts',
429
+				'obj_id'     => $att_id,
430
+			),
431
+			'resend_registration'                 => array(
432
+				'func'       => '_resend_registration',
433
+				'noheader'   => true,
434
+				'capability' => 'ee_send_message',
435
+			),
436
+			'registrations_report'                => array(
437
+				'func'       => '_registrations_report',
438
+				'noheader'   => true,
439
+				'capability' => 'ee_read_registrations',
440
+			),
441
+			'contact_list_export'                 => array(
442
+				'func'       => '_contact_list_export',
443
+				'noheader'   => true,
444
+				'capability' => 'export',
445
+			),
446
+			'contact_list_report'                 => array(
447
+				'func'       => '_contact_list_report',
448
+				'noheader'   => true,
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+		);
452
+	}
453
+
454
+
455
+	protected function _set_page_config()
456
+	{
457
+		$this->_page_config = array(
458
+			'default'           => array(
459
+				'nav'           => array(
460
+					'label' => esc_html__('Overview', 'event_espresso'),
461
+					'order' => 5,
462
+				),
463
+				'help_tabs'     => array(
464
+					'registrations_overview_help_tab'                       => array(
465
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
+						'filename' => 'registrations_overview',
467
+					),
468
+					'registrations_overview_table_column_headings_help_tab' => array(
469
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
+						'filename' => 'registrations_overview_table_column_headings',
471
+					),
472
+					'registrations_overview_filters_help_tab'               => array(
473
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
+						'filename' => 'registrations_overview_filters',
475
+					),
476
+					'registrations_overview_views_help_tab'                 => array(
477
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
478
+						'filename' => 'registrations_overview_views',
479
+					),
480
+					'registrations_regoverview_other_help_tab'              => array(
481
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
+						'filename' => 'registrations_overview_other',
483
+					),
484
+				),
485
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
486
+				'qtips'         => array('Registration_List_Table_Tips'),
487
+				'list_table'    => 'EE_Registrations_List_Table',
488
+				'require_nonce' => false,
489
+			),
490
+			'view_registration' => array(
491
+				'nav'           => array(
492
+					'label'      => esc_html__('REG Details', 'event_espresso'),
493
+					'order'      => 15,
494
+					'url'        => isset($this->_req_data['_REG_ID'])
495
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
+						: $this->_admin_base_url,
497
+					'persistent' => false,
498
+				),
499
+				'help_tabs'     => array(
500
+					'registrations_details_help_tab'                    => array(
501
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
502
+						'filename' => 'registrations_details',
503
+					),
504
+					'registrations_details_table_help_tab'              => array(
505
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
+						'filename' => 'registrations_details_table',
507
+					),
508
+					'registrations_details_form_answers_help_tab'       => array(
509
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
+						'filename' => 'registrations_details_form_answers',
511
+					),
512
+					'registrations_details_registrant_details_help_tab' => array(
513
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
514
+						'filename' => 'registrations_details_registrant_details',
515
+					),
516
+				),
517
+				'help_tour'     => array('Registration_Details_Help_Tour'),
518
+				'metaboxes'     => array_merge(
519
+					$this->_default_espresso_metaboxes,
520
+					array('_registration_details_metaboxes')
521
+				),
522
+				'require_nonce' => false,
523
+			),
524
+			'new_registration'  => array(
525
+				'nav'           => array(
526
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
+					'url'        => '#',
528
+					'order'      => 15,
529
+					'persistent' => false,
530
+				),
531
+				'metaboxes'     => $this->_default_espresso_metaboxes,
532
+				'labels'        => array(
533
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
+				),
535
+				'require_nonce' => false,
536
+			),
537
+			'add_new_attendee'  => array(
538
+				'nav'           => array(
539
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
540
+					'order'      => 15,
541
+					'persistent' => false,
542
+				),
543
+				'metaboxes'     => array_merge(
544
+					$this->_default_espresso_metaboxes,
545
+					array('_publish_post_box', 'attendee_editor_metaboxes')
546
+				),
547
+				'require_nonce' => false,
548
+			),
549
+			'edit_attendee'     => array(
550
+				'nav'           => array(
551
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
+					'order'      => 15,
553
+					'persistent' => false,
554
+					'url'        => isset($this->_req_data['ATT_ID'])
555
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
+						: $this->_admin_base_url,
557
+				),
558
+				'metaboxes'     => array('attendee_editor_metaboxes'),
559
+				'require_nonce' => false,
560
+			),
561
+			'contact_list'      => array(
562
+				'nav'           => array(
563
+					'label' => esc_html__('Contact List', 'event_espresso'),
564
+					'order' => 20,
565
+				),
566
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
567
+				'help_tabs'     => array(
568
+					'registrations_contact_list_help_tab'                       => array(
569
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
+						'filename' => 'registrations_contact_list',
571
+					),
572
+					'registrations_contact-list_table_column_headings_help_tab' => array(
573
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
+						'filename' => 'registrations_contact_list_table_column_headings',
575
+					),
576
+					'registrations_contact_list_views_help_tab'                 => array(
577
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
+						'filename' => 'registrations_contact_list_views',
579
+					),
580
+					'registrations_contact_list_other_help_tab'                 => array(
581
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
+						'filename' => 'registrations_contact_list_other',
583
+					),
584
+				),
585
+				'help_tour'     => array('Contact_List_Help_Tour'),
586
+				'metaboxes'     => array(),
587
+				'require_nonce' => false,
588
+			),
589
+			// override default cpt routes
590
+			'create_new'        => '',
591
+			'edit'              => '',
592
+		);
593
+	}
594
+
595
+
596
+	/**
597
+	 * The below methods aren't used by this class currently
598
+	 */
599
+	protected function _add_screen_options()
600
+	{
601
+	}
602
+
603
+
604
+	protected function _add_feature_pointers()
605
+	{
606
+	}
607
+
608
+
609
+	public function admin_init()
610
+	{
611
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
+			'click "Update Registration Questions" to save your changes',
613
+			'event_espresso'
614
+		);
615
+	}
616
+
617
+
618
+	public function admin_notices()
619
+	{
620
+	}
621
+
622
+
623
+	public function admin_footer_scripts()
624
+	{
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get list of registration statuses
630
+	 *
631
+	 * @access private
632
+	 * @return void
633
+	 * @throws EE_Error
634
+	 */
635
+	private function _get_registration_status_array()
636
+	{
637
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
+	}
639
+
640
+
641
+	protected function _add_screen_options_default()
642
+	{
643
+		$this->_per_page_screen_option();
644
+	}
645
+
646
+
647
+	protected function _add_screen_options_contact_list()
648
+	{
649
+		$page_title = $this->_admin_page_title;
650
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
+		$this->_per_page_screen_option();
652
+		$this->_admin_page_title = $page_title;
653
+	}
654
+
655
+
656
+	public function load_scripts_styles()
657
+	{
658
+		// style
659
+		wp_register_style(
660
+			'espresso_reg',
661
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
+			array('ee-admin-css'),
663
+			EVENT_ESPRESSO_VERSION
664
+		);
665
+		wp_enqueue_style('espresso_reg');
666
+		// script
667
+		wp_register_script(
668
+			'espresso_reg',
669
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
+			EVENT_ESPRESSO_VERSION,
672
+			true
673
+		);
674
+		wp_enqueue_script('espresso_reg');
675
+	}
676
+
677
+
678
+	public function load_scripts_styles_edit_attendee()
679
+	{
680
+		// stuff to only show up on our attendee edit details page.
681
+		$attendee_details_translations = array(
682
+			'att_publish_text' => sprintf(
683
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
+				$this->_cpt_model_obj->get_datetime('ATT_created')
685
+			),
686
+		);
687
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
+		wp_enqueue_script('jquery-validate');
689
+	}
690
+
691
+
692
+	public function load_scripts_styles_view_registration()
693
+	{
694
+		// styles
695
+		wp_enqueue_style('espresso-ui-theme');
696
+		// scripts
697
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
698
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
+	}
700
+
701
+
702
+	public function load_scripts_styles_contact_list()
703
+	{
704
+		wp_dequeue_style('espresso_reg');
705
+		wp_register_style(
706
+			'espresso_att',
707
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
+			array('ee-admin-css'),
709
+			EVENT_ESPRESSO_VERSION
710
+		);
711
+		wp_enqueue_style('espresso_att');
712
+	}
713
+
714
+
715
+	public function load_scripts_styles_new_registration()
716
+	{
717
+		wp_register_script(
718
+			'ee-spco-for-admin',
719
+			REG_ASSETS_URL . 'spco_for_admin.js',
720
+			array('underscore', 'jquery'),
721
+			EVENT_ESPRESSO_VERSION,
722
+			true
723
+		);
724
+		wp_enqueue_script('ee-spco-for-admin');
725
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
+		EE_Form_Section_Proper::wp_enqueue_scripts();
727
+		EED_Ticket_Selector::load_tckt_slctr_assets();
728
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
729
+	}
730
+
731
+
732
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
+	{
734
+		add_filter('FHEE_load_EE_messages', '__return_true');
735
+	}
736
+
737
+
738
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
+	{
740
+		add_filter('FHEE_load_EE_messages', '__return_true');
741
+	}
742
+
743
+
744
+	protected function _set_list_table_views_default()
745
+	{
746
+		// for notification related bulk actions we need to make sure only active messengers have an option.
747
+		EED_Messages::set_autoloaders();
748
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
749
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
+		$active_mts = $message_resource_manager->list_of_active_message_types();
751
+		// key= bulk_action_slug, value= message type.
752
+		$match_array = array(
753
+			'approve_registrations'    => 'registration',
754
+			'decline_registrations'    => 'declined_registration',
755
+			'pending_registrations'    => 'pending_approval',
756
+			'no_approve_registrations' => 'not_approved_registration',
757
+			'cancel_registrations'     => 'cancelled_registration',
758
+		);
759
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
760
+			'ee_send_message',
761
+			'batch_send_messages'
762
+		);
763
+		/** setup reg status bulk actions **/
764
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
+				'Approve and Notify Registrations',
768
+				'event_espresso'
769
+			);
770
+		}
771
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
+				'Decline and Notify Registrations',
775
+				'event_espresso'
776
+			);
777
+		}
778
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
779
+			'Set Registrations to Pending Payment',
780
+			'event_espresso'
781
+		);
782
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
+				'Set Registrations to Pending Payment and Notify',
785
+				'event_espresso'
786
+			);
787
+		}
788
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
+			'Set Registrations to Not Approved',
790
+			'event_espresso'
791
+		);
792
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
+				'Set Registrations to Not Approved and Notify',
795
+				'event_espresso'
796
+			);
797
+		}
798
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
+				'Cancel Registrations and Notify',
802
+				'event_espresso'
803
+			);
804
+		}
805
+		$def_reg_status_actions = apply_filters(
806
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
+			$def_reg_status_actions,
808
+			$active_mts,
809
+			$can_send
810
+		);
811
+
812
+		$this->_views = array(
813
+			'all'   => array(
814
+				'slug'        => 'all',
815
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
+				'count'       => 0,
817
+				'bulk_action' => array_merge(
818
+					$def_reg_status_actions,
819
+					array(
820
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
+					)
822
+				),
823
+			),
824
+			'month' => array(
825
+				'slug'        => 'month',
826
+				'label'       => esc_html__('This Month', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge(
829
+					$def_reg_status_actions,
830
+					array(
831
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
+					)
833
+				),
834
+			),
835
+			'today' => array(
836
+				'slug'        => 'today',
837
+				'label'       => sprintf(
838
+					esc_html__('Today - %s', 'event_espresso'),
839
+					date('M d, Y', current_time('timestamp'))
840
+				),
841
+				'count'       => 0,
842
+				'bulk_action' => array_merge(
843
+					$def_reg_status_actions,
844
+					array(
845
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
+					)
847
+				),
848
+			),
849
+		);
850
+		if (EE_Registry::instance()->CAP->current_user_can(
851
+			'ee_delete_registrations',
852
+			'espresso_registrations_delete_registration'
853
+		)) {
854
+			$this->_views['incomplete'] = array(
855
+				'slug'        => 'incomplete',
856
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => array(
859
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
+				),
861
+			);
862
+			$this->_views['trash'] = array(
863
+				'slug'        => 'trash',
864
+				'label'       => esc_html__('Trash', 'event_espresso'),
865
+				'count'       => 0,
866
+				'bulk_action' => array(
867
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
+				),
870
+			);
871
+		}
872
+	}
873
+
874
+
875
+	protected function _set_list_table_views_contact_list()
876
+	{
877
+		$this->_views = array(
878
+			'in_use' => array(
879
+				'slug'        => 'in_use',
880
+				'label'       => esc_html__('In Use', 'event_espresso'),
881
+				'count'       => 0,
882
+				'bulk_action' => array(
883
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
+				),
885
+			),
886
+		);
887
+		if (EE_Registry::instance()->CAP->current_user_can(
888
+			'ee_delete_contacts',
889
+			'espresso_registrations_trash_attendees'
890
+		)
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post'   => $ATT_ID,
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+					. EE_Admin_Page::add_query_args_and_nonce(
1070
+						array(
1071
+							'action' => 'edit',
1072
+							'post'   => $event->ID(),
1073
+						),
1074
+						EVENTS_ADMIN_URL
1075
+					)
1076
+					. '">&nbsp;'
1077
+					. $event->get('EVT_name')
1078
+					. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		// get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG = EEM_Registration::instance();
1119
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 *
1166
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
+		 *                             or if you have the development copy of EE you can view this at the path:
1169
+		 *                             /docs/G--Model-System/model-query-params.md
1170
+		 */
1171
+		$query_params['group_by'] = '';
1172
+
1173
+		return $count
1174
+			? EEM_Registration::instance()->count($query_params)
1175
+			/** @type EE_Registration[] */
1176
+			: EEM_Registration::instance()->get_all($query_params);
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
+	 * Note: this listens to values on the request for some of the query parameters.
1183
+	 *
1184
+	 * @param array $request
1185
+	 * @param int   $per_page
1186
+	 * @param bool  $count
1187
+	 * @return array
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _get_registration_query_parameters(
1191
+		$request = array(),
1192
+		$per_page = 10,
1193
+		$count = false
1194
+	) {
1195
+
1196
+		$query_params = array(
1197
+			0                          => $this->_get_where_conditions_for_registrations_query(
1198
+				$request
1199
+			),
1200
+			'caps'                     => EEM_Registration::caps_read_admin,
1201
+			'default_where_conditions' => 'this_model_only',
1202
+		);
1203
+		if (! $count) {
1204
+			$query_params = array_merge(
1205
+				$query_params,
1206
+				$this->_get_orderby_for_registrations_query(),
1207
+				$this->_get_limit($per_page)
1208
+			);
1209
+		}
1210
+
1211
+		return $query_params;
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
+	 *
1218
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1219
+	 * @return array
1220
+	 */
1221
+	protected function addAttendeeIdToWhereConditions(array $request)
1222
+	{
1223
+		$where = array();
1224
+		if (! empty($request['ATT_ID'])) {
1225
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1226
+		}
1227
+		return $where;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
+	 *
1234
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1235
+	 * @return array
1236
+	 */
1237
+	protected function _add_event_id_to_where_conditions(array $request)
1238
+	{
1239
+		$where = array();
1240
+		if (! empty($request['event_id'])) {
1241
+			$where['EVT_ID'] = absint($request['event_id']);
1242
+		}
1243
+		return $where;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
+	 *
1250
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1251
+	 * @return array
1252
+	 */
1253
+	protected function _add_category_id_to_where_conditions(array $request)
1254
+	{
1255
+		$where = array();
1256
+		if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
+		}
1259
+		return $where;
1260
+	}
1261
+
1262
+
1263
+	/**
1264
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
+	 *
1266
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1267
+	 * @return array
1268
+	 */
1269
+	protected function _add_datetime_id_to_where_conditions(array $request)
1270
+	{
1271
+		$where = array();
1272
+		if (! empty($request['datetime_id'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
+		}
1275
+		if (! empty($request['DTT_ID'])) {
1276
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
+		}
1278
+		return $where;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * Adds the correct registration status to the where conditions for the registrations query.
1284
+	 *
1285
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1286
+	 * @return array
1287
+	 */
1288
+	protected function _add_registration_status_to_where_conditions(array $request)
1289
+	{
1290
+		$where = array();
1291
+		$view = EEH_Array::is_set($request, 'status', '');
1292
+		$registration_status = ! empty($request['_reg_status'])
1293
+			? sanitize_text_field($request['_reg_status'])
1294
+			: '';
1295
+
1296
+		/*
1297 1297
          * If filtering by registration status, then we show registrations matching that status.
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1302
-            $where['STS_ID'] = $registration_status;
1303
-        } else {
1304
-            // make sure we exclude incomplete registrations, but only if not trashed.
1305
-            if ($view === 'trash') {
1306
-                $where['REG_deleted'] = true;
1307
-            } elseif ($view === 'incomplete') {
1308
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
-            } else {
1310
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
-            }
1312
-        }
1313
-        return $where;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Adds any provided date restraints to the where conditions for the registrations query.
1319
-     *
1320
-     * @param array $request usually the same as $this->_req_data but not necessarily
1321
-     * @return array
1322
-     * @throws EE_Error
1323
-     * @throws InvalidArgumentException
1324
-     * @throws InvalidDataTypeException
1325
-     * @throws InvalidInterfaceException
1326
-     */
1327
-    protected function _add_date_to_where_conditions(array $request)
1328
-    {
1329
-        $where = array();
1330
-        $view = EEH_Array::is_set($request, 'status', '');
1331
-        $month_range = ! empty($request['month_range'])
1332
-            ? sanitize_text_field($request['month_range'])
1333
-            : '';
1334
-        $retrieve_for_today = $view === 'today';
1335
-        $retrieve_for_this_month = $view === 'month';
1336
-
1337
-        if ($retrieve_for_today) {
1338
-            $now = date('Y-m-d', current_time('timestamp'));
1339
-            $where['REG_date'] = array(
1340
-                'BETWEEN',
1341
-                array(
1342
-                    EEM_Registration::instance()->convert_datetime_for_query(
1343
-                        'REG_date',
1344
-                        $now . ' 00:00:00',
1345
-                        'Y-m-d H:i:s'
1346
-                    ),
1347
-                    EEM_Registration::instance()->convert_datetime_for_query(
1348
-                        'REG_date',
1349
-                        $now . ' 23:59:59',
1350
-                        'Y-m-d H:i:s'
1351
-                    ),
1352
-                ),
1353
-            );
1354
-        } elseif ($retrieve_for_this_month) {
1355
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1356
-            $days_this_month = date('t', current_time('timestamp'));
1357
-            $where['REG_date'] = array(
1358
-                'BETWEEN',
1359
-                array(
1360
-                    EEM_Registration::instance()->convert_datetime_for_query(
1361
-                        'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1363
-                        'Y-m-d H:i:s'
1364
-                    ),
1365
-                    EEM_Registration::instance()->convert_datetime_for_query(
1366
-                        'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
-                        'Y-m-d H:i:s'
1369
-                    ),
1370
-                ),
1371
-            );
1372
-        } elseif ($month_range) {
1373
-            $pieces = explode(' ', $month_range, 3);
1374
-            $month_requested = ! empty($pieces[0])
1375
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
-                : '';
1377
-            $year_requested = ! empty($pieces[1])
1378
-                ? $pieces[1]
1379
-                : '';
1380
-            // if there is not a month or year then we can't go further
1381
-            if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
-                $where['REG_date'] = array(
1384
-                    'BETWEEN',
1385
-                    array(
1386
-                        EEM_Registration::instance()->convert_datetime_for_query(
1387
-                            'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1389
-                            'Y-m-d H:i:s'
1390
-                        ),
1391
-                        EEM_Registration::instance()->convert_datetime_for_query(
1392
-                            'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
-                            'Y-m-d H:i:s'
1395
-                        ),
1396
-                    ),
1397
-                );
1398
-            }
1399
-        }
1400
-        return $where;
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * Adds any provided search restraints to the where conditions for the registrations query
1406
-     *
1407
-     * @param array $request usually the same as $this->_req_data but not necessarily
1408
-     * @return array
1409
-     */
1410
-    protected function _add_search_to_where_conditions(array $request)
1411
-    {
1412
-        $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
-            $where['OR*search_conditions'] = array(
1416
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1417
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
-                'REG_final_price'                         => array('LIKE', $search_string),
1428
-                'REG_code'                                => array('LIKE', $search_string),
1429
-                'REG_count'                               => array('LIKE', $search_string),
1430
-                'REG_group_size'                          => array('LIKE', $search_string),
1431
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
-            );
1435
-        }
1436
-        return $where;
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Sets up the where conditions for the registrations query.
1442
-     *
1443
-     * @param array $request
1444
-     * @return array
1445
-     * @throws EE_Error
1446
-     */
1447
-    protected function _get_where_conditions_for_registrations_query($request)
1448
-    {
1449
-        return apply_filters(
1450
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
-            array_merge(
1452
-                $this->addAttendeeIdToWhereConditions($request),
1453
-                $this->_add_event_id_to_where_conditions($request),
1454
-                $this->_add_category_id_to_where_conditions($request),
1455
-                $this->_add_datetime_id_to_where_conditions($request),
1456
-                $this->_add_registration_status_to_where_conditions($request),
1457
-                $this->_add_date_to_where_conditions($request),
1458
-                $this->_add_search_to_where_conditions($request)
1459
-            ),
1460
-            $request
1461
-        );
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * Sets up the orderby for the registrations query.
1467
-     *
1468
-     * @return array
1469
-     */
1470
-    protected function _get_orderby_for_registrations_query()
1471
-    {
1472
-        $orderby_field = ! empty($this->_req_data['orderby'])
1473
-            ? sanitize_text_field($this->_req_data['orderby'])
1474
-            : '_REG_date';
1475
-        switch ($orderby_field) {
1476
-            case '_REG_ID':
1477
-                $orderby = array('REG_ID');
1478
-                break;
1479
-            case '_Reg_status':
1480
-                $orderby = array('STS_ID');
1481
-                break;
1482
-            case 'ATT_fname':
1483
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
-                break;
1485
-            case 'ATT_lname':
1486
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
-                break;
1488
-            case 'event_name':
1489
-                $orderby = array('Event.EVT_name');
1490
-                break;
1491
-            case 'DTT_EVT_start':
1492
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1493
-                break;
1494
-            case '_REG_date':
1495
-                $orderby = array('REG_date');
1496
-                break;
1497
-            default:
1498
-                $orderby = array($orderby_field);
1499
-                break;
1500
-        }
1501
-
1502
-        // order
1503
-        $order = ! empty($this->_req_data['order'])
1504
-            ? sanitize_text_field($this->_req_data['order'])
1505
-            : 'DESC';
1506
-        $orderby = array_combine(
1507
-            $orderby,
1508
-            array_fill(0, count($orderby), $order)
1509
-        );
1510
-        // because there are many registrations with the same date, define
1511
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
1512
-        if (empty($orderby['REG_ID'])) {
1513
-            $orderby['REG_ID'] = $order;
1514
-        }
1515
-
1516
-        $orderby = apply_filters(
1517
-            'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
-            $orderby,
1519
-            $this->_req_data
1520
-        );
1521
-
1522
-        return array('order_by' => $orderby);
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * Sets up the limit for the registrations query.
1528
-     *
1529
-     * @param $per_page
1530
-     * @return array
1531
-     */
1532
-    protected function _get_limit($per_page)
1533
-    {
1534
-        $current_page = ! empty($this->_req_data['paged'])
1535
-            ? absint($this->_req_data['paged'])
1536
-            : 1;
1537
-        $per_page = ! empty($this->_req_data['perpage'])
1538
-            ? $this->_req_data['perpage']
1539
-            : $per_page;
1540
-
1541
-        // -1 means return all results so get out if that's set.
1542
-        if ((int) $per_page === -1) {
1543
-            return array();
1544
-        }
1545
-        $per_page = absint($per_page);
1546
-        $offset = ($current_page - 1) * $per_page;
1547
-        return array('limit' => array($offset, $per_page));
1548
-    }
1549
-
1550
-
1551
-    public function get_registration_status_array()
1552
-    {
1553
-        return self::$_reg_status;
1554
-    }
1555
-
1556
-
1557
-
1558
-
1559
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1560
-    /**
1561
-     *        generates HTML for the View Registration Details Admin page
1562
-     *
1563
-     * @access protected
1564
-     * @return void
1565
-     * @throws DomainException
1566
-     * @throws EE_Error
1567
-     * @throws InvalidArgumentException
1568
-     * @throws InvalidDataTypeException
1569
-     * @throws InvalidInterfaceException
1570
-     * @throws EntityNotFoundException
1571
-     */
1572
-    protected function _registration_details()
1573
-    {
1574
-        $this->_template_args = array();
1575
-        $this->_set_registration_object();
1576
-        if (is_object($this->_registration)) {
1577
-            $transaction = $this->_registration->transaction()
1578
-                ? $this->_registration->transaction()
1579
-                : EE_Transaction::new_instance();
1580
-            $this->_session = $transaction->session_data();
1581
-            $event_id = $this->_registration->event_ID();
1582
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
-            $this->_template_args['grand_total'] = $transaction->total();
1587
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
-            // link back to overview
1589
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
-            $this->_template_args['registration'] = $this->_registration;
1591
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
-                array(
1593
-                    'action'   => 'default',
1594
-                    'event_id' => $event_id,
1595
-                ),
1596
-                REG_ADMIN_URL
1597
-            );
1598
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
-                array(
1600
-                    'action' => 'default',
1601
-                    'EVT_ID' => $event_id,
1602
-                    'page'   => 'espresso_transactions',
1603
-                ),
1604
-                admin_url('admin.php')
1605
-            );
1606
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
-                array(
1608
-                    'page'   => 'espresso_events',
1609
-                    'action' => 'edit',
1610
-                    'post'   => $event_id,
1611
-                ),
1612
-                admin_url('admin.php')
1613
-            );
1614
-            // next and previous links
1615
-            $next_reg = $this->_registration->next(
1616
-                null,
1617
-                array(),
1618
-                'REG_ID'
1619
-            );
1620
-            $this->_template_args['next_registration'] = $next_reg
1621
-                ? $this->_next_link(
1622
-                    EE_Admin_Page::add_query_args_and_nonce(
1623
-                        array(
1624
-                            'action'  => 'view_registration',
1625
-                            '_REG_ID' => $next_reg['REG_ID'],
1626
-                        ),
1627
-                        REG_ADMIN_URL
1628
-                    ),
1629
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1630
-                )
1631
-                : '';
1632
-            $previous_reg = $this->_registration->previous(
1633
-                null,
1634
-                array(),
1635
-                'REG_ID'
1636
-            );
1637
-            $this->_template_args['previous_registration'] = $previous_reg
1638
-                ? $this->_previous_link(
1639
-                    EE_Admin_Page::add_query_args_and_nonce(
1640
-                        array(
1641
-                            'action'  => 'view_registration',
1642
-                            '_REG_ID' => $previous_reg['REG_ID'],
1643
-                        ),
1644
-                        REG_ADMIN_URL
1645
-                    ),
1646
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1647
-                )
1648
-                : '';
1649
-            // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1652
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
-                $template_path,
1654
-                $this->_template_args,
1655
-                true
1656
-            );
1657
-        } else {
1658
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
-        }
1660
-        // the details template wrapper
1661
-        $this->display_admin_page_with_sidebar();
1662
-    }
1663
-
1664
-
1665
-    protected function _registration_details_metaboxes()
1666
-    {
1667
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
-        $this->_set_registration_object();
1669
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
-        add_meta_box(
1671
-            'edit-reg-status-mbox',
1672
-            esc_html__('Registration Status', 'event_espresso'),
1673
-            array($this, 'set_reg_status_buttons_metabox'),
1674
-            $this->wp_page_slug,
1675
-            'normal',
1676
-            'high'
1677
-        );
1678
-        add_meta_box(
1679
-            'edit-reg-details-mbox',
1680
-            esc_html__('Registration Details', 'event_espresso'),
1681
-            array($this, '_reg_details_meta_box'),
1682
-            $this->wp_page_slug,
1683
-            'normal',
1684
-            'high'
1685
-        );
1686
-        if ($attendee instanceof EE_Attendee
1687
-            && EE_Registry::instance()->CAP->current_user_can(
1688
-                'ee_read_registration',
1689
-                'edit-reg-questions-mbox',
1690
-                $this->_registration->ID()
1691
-            )
1692
-        ) {
1693
-            add_meta_box(
1694
-                'edit-reg-questions-mbox',
1695
-                esc_html__('Registration Form Answers', 'event_espresso'),
1696
-                array($this, '_reg_questions_meta_box'),
1697
-                $this->wp_page_slug,
1698
-                'normal',
1699
-                'high'
1700
-            );
1701
-        }
1702
-        add_meta_box(
1703
-            'edit-reg-registrant-mbox',
1704
-            esc_html__('Contact Details', 'event_espresso'),
1705
-            array($this, '_reg_registrant_side_meta_box'),
1706
-            $this->wp_page_slug,
1707
-            'side',
1708
-            'high'
1709
-        );
1710
-        if ($this->_registration->group_size() > 1) {
1711
-            add_meta_box(
1712
-                'edit-reg-attendees-mbox',
1713
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
-                array($this, '_reg_attendees_meta_box'),
1715
-                $this->wp_page_slug,
1716
-                'normal',
1717
-                'high'
1718
-            );
1719
-        }
1720
-    }
1721
-
1722
-
1723
-    /**
1724
-     * set_reg_status_buttons_metabox
1725
-     *
1726
-     * @access protected
1727
-     * @return string
1728
-     * @throws \EE_Error
1729
-     */
1730
-    public function set_reg_status_buttons_metabox()
1731
-    {
1732
-        $this->_set_registration_object();
1733
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1734
-        echo $change_reg_status_form->form_open(
1735
-            self::add_query_args_and_nonce(
1736
-                array(
1737
-                    'action' => 'change_reg_status',
1738
-                ),
1739
-                REG_ADMIN_URL
1740
-            )
1741
-        );
1742
-        echo $change_reg_status_form->get_html();
1743
-        echo $change_reg_status_form->form_close();
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     * @return EE_Form_Section_Proper
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
-     */
1755
-    protected function _generate_reg_status_change_form()
1756
-    {
1757
-        $reg_status_change_form_array = array(
1758
-            'name'            => 'reg_status_change_form',
1759
-            'html_id'         => 'reg-status-change-form',
1760
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
-            'subsections'     => array(
1762
-                'return'             => new EE_Hidden_Input(
1763
-                    array(
1764
-                        'name'    => 'return',
1765
-                        'default' => 'view_registration',
1766
-                    )
1767
-                ),
1768
-                'REG_ID'             => new EE_Hidden_Input(
1769
-                    array(
1770
-                        'name'    => 'REG_ID',
1771
-                        'default' => $this->_registration->ID(),
1772
-                    )
1773
-                ),
1774
-                'current_status'     => new EE_Form_Section_HTML(
1775
-                    EEH_HTML::table(
1776
-                        EEH_HTML::tr(
1777
-                            EEH_HTML::th(
1778
-                                EEH_HTML::label(
1779
-                                    EEH_HTML::strong(
1780
-                                        esc_html__('Current Registration Status', 'event_espresso')
1781
-                                    )
1782
-                                )
1783
-                            )
1784
-                            . EEH_HTML::td(
1785
-                                EEH_HTML::strong(
1786
-                                    $this->_registration->pretty_status(),
1787
-                                    '',
1788
-                                    'status-' . $this->_registration->status_ID(),
1789
-                                    'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1790
-                                )
1791
-                            )
1792
-                        )
1793
-                    )
1794
-                )
1795
-            )
1796
-        );
1797
-        if (EE_Registry::instance()->CAP->current_user_can(
1798
-            'ee_edit_registration',
1799
-            'toggle_registration_status',
1800
-            $this->_registration->ID()
1801
-        )) {
1802
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1803
-                $this->_get_reg_statuses(),
1804
-                array(
1805
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1806
-                    'default'         => $this->_registration->status_ID(),
1807
-                )
1808
-            );
1809
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1810
-                array(
1811
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1812
-                    'default'         => false,
1813
-                    'html_help_text'  => esc_html__(
1814
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1815
-                        'event_espresso'
1816
-                    )
1817
-                )
1818
-            );
1819
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1820
-                array(
1821
-                    'html_class'      => 'button-primary',
1822
-                    'html_label_text' => '&nbsp;',
1823
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1824
-                )
1825
-            );
1826
-        }
1827
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1828
-    }
1829
-
1830
-
1831
-    /**
1832
-     * Returns an array of all the buttons for the various statuses and switch status actions
1833
-     *
1834
-     * @return array
1835
-     * @throws EE_Error
1836
-     * @throws InvalidArgumentException
1837
-     * @throws InvalidDataTypeException
1838
-     * @throws InvalidInterfaceException
1839
-     * @throws EntityNotFoundException
1840
-     */
1841
-    protected function _get_reg_statuses()
1842
-    {
1843
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1844
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1845
-        // get current reg status
1846
-        $current_status = $this->_registration->status_ID();
1847
-        // is registration for free event? This will determine whether to display the pending payment option
1848
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1849
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1850
-        ) {
1851
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1852
-        }
1853
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1854
-    }
1855
-
1856
-
1857
-    /**
1858
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1859
-     *
1860
-     * @param bool $status REG status given for changing registrations to.
1861
-     * @param bool $notify Whether to send messages notifications or not.
1862
-     * @return array (array with reg_id(s) updated and whether update was successful.
1863
-     * @throws EE_Error
1864
-     * @throws InvalidArgumentException
1865
-     * @throws InvalidDataTypeException
1866
-     * @throws InvalidInterfaceException
1867
-     * @throws ReflectionException
1868
-     * @throws RuntimeException
1869
-     * @throws EntityNotFoundException
1870
-     */
1871
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1872
-    {
1873
-        if (isset($this->_req_data['reg_status_change_form'])) {
1874
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1875
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1876
-                : array();
1877
-        } else {
1878
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1879
-                ? (array) $this->_req_data['_REG_ID']
1880
-                : array();
1881
-        }
1882
-        // sanitize $REG_IDs
1883
-        $REG_IDs = array_map('absint', $REG_IDs);
1884
-        // and remove empty entries
1885
-        $REG_IDs = array_filter($REG_IDs);
1886
-
1887
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1888
-
1889
-        /**
1890
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1891
-         * Currently this value is used downstream by the _process_resend_registration method.
1892
-         *
1893
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1894
-         * @param bool                     $status           The status registrations were changed to.
1895
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1896
-         * @param Registrations_Admin_Page $admin_page_object
1897
-         */
1898
-        $this->_req_data['_REG_ID'] = apply_filters(
1899
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1900
-            $result['REG_ID'],
1901
-            $status,
1902
-            $result['success'],
1903
-            $this
1904
-        );
1905
-
1906
-        // notify?
1907
-        if ($notify
1908
-            && $result['success']
1909
-            && ! empty($this->_req_data['_REG_ID'])
1910
-            && EE_Registry::instance()->CAP->current_user_can(
1911
-                'ee_send_message',
1912
-                'espresso_registrations_resend_registration'
1913
-            )
1914
-        ) {
1915
-            $this->_process_resend_registration();
1916
-        }
1917
-        return $result;
1918
-    }
1919
-
1920
-
1921
-    /**
1922
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1923
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1924
-     *
1925
-     * @param array  $REG_IDs
1926
-     * @param string $status
1927
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1928
-     *                        slug sent with setting the registration status.
1929
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1930
-     * @throws EE_Error
1931
-     * @throws InvalidArgumentException
1932
-     * @throws InvalidDataTypeException
1933
-     * @throws InvalidInterfaceException
1934
-     * @throws ReflectionException
1935
-     * @throws RuntimeException
1936
-     * @throws EntityNotFoundException
1937
-     */
1938
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1939
-    {
1940
-        $success = false;
1941
-        // typecast $REG_IDs
1942
-        $REG_IDs = (array) $REG_IDs;
1943
-        if (! empty($REG_IDs)) {
1944
-            $success = true;
1945
-            // set default status if none is passed
1946
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1947
-            $status_context = $notify
1948
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1949
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1950
-            // loop through REG_ID's and change status
1951
-            foreach ($REG_IDs as $REG_ID) {
1952
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1953
-                if ($registration instanceof EE_Registration) {
1954
-                    $registration->set_status(
1955
-                        $status,
1956
-                        false,
1957
-                        new Context(
1958
-                            $status_context,
1959
-                            esc_html__(
1960
-                                'Manually triggered status change on a Registration Admin Page route.',
1961
-                                'event_espresso'
1962
-                            )
1963
-                        )
1964
-                    );
1965
-                    $result = $registration->save();
1966
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1967
-                    $success = $result !== false ? $success : false;
1968
-                }
1969
-            }
1970
-        }
1971
-
1972
-        // return $success and processed registrations
1973
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1974
-    }
1975
-
1976
-
1977
-    /**
1978
-     * Common logic for setting up success message and redirecting to appropriate route
1979
-     *
1980
-     * @param  string $STS_ID status id for the registration changed to
1981
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1982
-     * @return void
1983
-     * @throws EE_Error
1984
-     */
1985
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1986
-    {
1987
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1988
-            : array('success' => false);
1989
-        $success = isset($result['success']) && $result['success'];
1990
-        // setup success message
1991
-        if ($success) {
1992
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1993
-                $msg = sprintf(
1994
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1995
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1996
-                );
1997
-            } else {
1998
-                $msg = sprintf(
1999
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
2000
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
2001
-                );
2002
-            }
2003
-            EE_Error::add_success($msg);
2004
-        } else {
2005
-            EE_Error::add_error(
2006
-                esc_html__(
2007
-                    'Something went wrong, and the status was not changed',
2008
-                    'event_espresso'
2009
-                ),
2010
-                __FILE__,
2011
-                __LINE__,
2012
-                __FUNCTION__
2013
-            );
2014
-        }
2015
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2016
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2017
-        } else {
2018
-            $route = array('action' => 'default');
2019
-        }
2020
-        $route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2021
-        $this->_redirect_after_action($success, '', '', $route, true);
2022
-    }
2023
-
2024
-
2025
-    /**
2026
-     * incoming reg status change from reg details page.
2027
-     *
2028
-     * @return void
2029
-     */
2030
-    protected function _change_reg_status()
2031
-    {
2032
-        $this->_req_data['return'] = 'view_registration';
2033
-        // set notify based on whether the send notifications toggle is set or not
2034
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2035
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2036
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2037
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2038
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2039
-            case EEM_Registration::status_id_approved:
2040
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2041
-                $this->approve_registration($notify);
2042
-                break;
2043
-            case EEM_Registration::status_id_pending_payment:
2044
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2045
-                $this->pending_registration($notify);
2046
-                break;
2047
-            case EEM_Registration::status_id_not_approved:
2048
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2049
-                $this->not_approve_registration($notify);
2050
-                break;
2051
-            case EEM_Registration::status_id_declined:
2052
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2053
-                $this->decline_registration($notify);
2054
-                break;
2055
-            case EEM_Registration::status_id_cancelled:
2056
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2057
-                $this->cancel_registration($notify);
2058
-                break;
2059
-            case EEM_Registration::status_id_wait_list:
2060
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2061
-                $this->wait_list_registration($notify);
2062
-                break;
2063
-            case EEM_Registration::status_id_incomplete:
2064
-            default:
2065
-                $result['success'] = false;
2066
-                unset($this->_req_data['return']);
2067
-                $this->_reg_status_change_return('', false);
2068
-                break;
2069
-        }
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     * Callback for bulk action routes.
2075
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2076
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2077
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2078
-     * when an action is happening on just a single registration).
2079
-     *
2080
-     * @param      $action
2081
-     * @param bool $notify
2082
-     */
2083
-    protected function bulk_action_on_registrations($action, $notify = false)
2084
-    {
2085
-        do_action(
2086
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2087
-            $this,
2088
-            $action,
2089
-            $notify
2090
-        );
2091
-        $method = $action . '_registration';
2092
-        if (method_exists($this, $method)) {
2093
-            $this->$method($notify);
2094
-        }
2095
-    }
2096
-
2097
-
2098
-    /**
2099
-     * approve_registration
2100
-     *
2101
-     * @access protected
2102
-     * @param bool $notify whether or not to notify the registrant about their approval.
2103
-     * @return void
2104
-     */
2105
-    protected function approve_registration($notify = false)
2106
-    {
2107
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2108
-    }
2109
-
2110
-
2111
-    /**
2112
-     *        decline_registration
2113
-     *
2114
-     * @access protected
2115
-     * @param bool $notify whether or not to notify the registrant about their status change.
2116
-     * @return void
2117
-     */
2118
-    protected function decline_registration($notify = false)
2119
-    {
2120
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2121
-    }
2122
-
2123
-
2124
-    /**
2125
-     *        cancel_registration
2126
-     *
2127
-     * @access protected
2128
-     * @param bool $notify whether or not to notify the registrant about their status change.
2129
-     * @return void
2130
-     */
2131
-    protected function cancel_registration($notify = false)
2132
-    {
2133
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2134
-    }
2135
-
2136
-
2137
-    /**
2138
-     *        not_approve_registration
2139
-     *
2140
-     * @access protected
2141
-     * @param bool $notify whether or not to notify the registrant about their status change.
2142
-     * @return void
2143
-     */
2144
-    protected function not_approve_registration($notify = false)
2145
-    {
2146
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2147
-    }
2148
-
2149
-
2150
-    /**
2151
-     *        decline_registration
2152
-     *
2153
-     * @access protected
2154
-     * @param bool $notify whether or not to notify the registrant about their status change.
2155
-     * @return void
2156
-     */
2157
-    protected function pending_registration($notify = false)
2158
-    {
2159
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2160
-    }
2161
-
2162
-
2163
-    /**
2164
-     * waitlist_registration
2165
-     *
2166
-     * @access protected
2167
-     * @param bool $notify whether or not to notify the registrant about their status change.
2168
-     * @return void
2169
-     */
2170
-    protected function wait_list_registration($notify = false)
2171
-    {
2172
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2173
-    }
2174
-
2175
-
2176
-    /**
2177
-     *        generates HTML for the Registration main meta box
2178
-     *
2179
-     * @access public
2180
-     * @return void
2181
-     * @throws DomainException
2182
-     * @throws EE_Error
2183
-     * @throws InvalidArgumentException
2184
-     * @throws InvalidDataTypeException
2185
-     * @throws InvalidInterfaceException
2186
-     * @throws ReflectionException
2187
-     * @throws EntityNotFoundException
2188
-     */
2189
-    public function _reg_details_meta_box()
2190
-    {
2191
-        EEH_Autoloader::register_line_item_display_autoloaders();
2192
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2193
-        EE_Registry::instance()->load_helper('Line_Item');
2194
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2195
-            : EE_Transaction::new_instance();
2196
-        $this->_session = $transaction->session_data();
2197
-        $filters = new EE_Line_Item_Filter_Collection();
2198
-        // $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2199
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2200
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2201
-            $filters,
2202
-            $transaction->total_line_item()
2203
-        );
2204
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2205
-        $line_item_display = new EE_Line_Item_Display(
2206
-            'reg_admin_table',
2207
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2208
-        );
2209
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2210
-            $filtered_line_item_tree,
2211
-            array('EE_Registration' => $this->_registration)
2212
-        );
2213
-        $attendee = $this->_registration->attendee();
2214
-        if (EE_Registry::instance()->CAP->current_user_can(
2215
-            'ee_read_transaction',
2216
-            'espresso_transactions_view_transaction'
2217
-        )) {
2218
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2219
-                EE_Admin_Page::add_query_args_and_nonce(
2220
-                    array(
2221
-                        'action' => 'view_transaction',
2222
-                        'TXN_ID' => $transaction->ID(),
2223
-                    ),
2224
-                    TXN_ADMIN_URL
2225
-                ),
2226
-                esc_html__(' View Transaction', 'event_espresso'),
2227
-                'button secondary-button right',
2228
-                'dashicons dashicons-cart'
2229
-            );
2230
-        } else {
2231
-            $this->_template_args['view_transaction_button'] = '';
2232
-        }
2233
-        if ($attendee instanceof EE_Attendee
2234
-            && EE_Registry::instance()->CAP->current_user_can(
2235
-                'ee_send_message',
2236
-                'espresso_registrations_resend_registration'
2237
-            )
2238
-        ) {
2239
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2240
-                EE_Admin_Page::add_query_args_and_nonce(
2241
-                    array(
2242
-                        'action'      => 'resend_registration',
2243
-                        '_REG_ID'     => $this->_registration->ID(),
2244
-                        'redirect_to' => 'view_registration',
2245
-                    ),
2246
-                    REG_ADMIN_URL
2247
-                ),
2248
-                esc_html__(' Resend Registration', 'event_espresso'),
2249
-                'button secondary-button right',
2250
-                'dashicons dashicons-email-alt'
2251
-            );
2252
-        } else {
2253
-            $this->_template_args['resend_registration_button'] = '';
2254
-        }
2255
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2256
-        $payment = $transaction->get_first_related('Payment');
2257
-        $payment = ! $payment instanceof EE_Payment
2258
-            ? EE_Payment::new_instance()
2259
-            : $payment;
2260
-        $payment_method = $payment->get_first_related('Payment_Method');
2261
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2262
-            ? EE_Payment_Method::new_instance()
2263
-            : $payment_method;
2264
-        $reg_details = array(
2265
-            'payment_method'       => $payment_method->name(),
2266
-            'response_msg'         => $payment->gateway_response(),
2267
-            'registration_id'      => $this->_registration->get('REG_code'),
2268
-            'registration_session' => $this->_registration->session_ID(),
2269
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2270
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2271
-        );
2272
-        if (isset($reg_details['registration_id'])) {
2273
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2274
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2275
-                'Registration ID',
2276
-                'event_espresso'
2277
-            );
2278
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2279
-        }
2280
-        if (isset($reg_details['payment_method'])) {
2281
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2282
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2283
-                'Most Recent Payment Method',
2284
-                'event_espresso'
2285
-            );
2286
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2287
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2288
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2289
-                'Payment method response',
2290
-                'event_espresso'
2291
-            );
2292
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2293
-        }
2294
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2295
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2296
-            'Registration Session',
2297
-            'event_espresso'
2298
-        );
2299
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2300
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2301
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2302
-            'Registration placed from IP',
2303
-            'event_espresso'
2304
-        );
2305
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2306
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2307
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2308
-            'Registrant User Agent',
2309
-            'event_espresso'
2310
-        );
2311
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2312
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2313
-            array(
2314
-                'action'   => 'default',
2315
-                'event_id' => $this->_registration->event_ID(),
2316
-            ),
2317
-            REG_ADMIN_URL
2318
-        );
2319
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2320
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2321
-        $template_path =
2322
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2323
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2324
-    }
2325
-
2326
-
2327
-    /**
2328
-     * generates HTML for the Registration Questions meta box.
2329
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2330
-     * otherwise uses new forms system
2331
-     *
2332
-     * @access public
2333
-     * @return void
2334
-     * @throws DomainException
2335
-     * @throws EE_Error
2336
-     */
2337
-    public function _reg_questions_meta_box()
2338
-    {
2339
-        // allow someone to override this method entirely
2340
-        if (apply_filters(
2341
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2342
-            true,
2343
-            $this,
2344
-            $this->_registration
2345
-        )) {
2346
-            $form = $this->_get_reg_custom_questions_form(
2347
-                $this->_registration->ID()
2348
-            );
2349
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2350
-                ? $form->get_html_and_js()
2351
-                : '';
2352
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2353
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2354
-            $template_path =
2355
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2356
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2357
-        }
2358
-    }
2359
-
2360
-
2361
-    /**
2362
-     * form_before_question_group
2363
-     *
2364
-     * @deprecated    as of 4.8.32.rc.000
2365
-     * @access        public
2366
-     * @param        string $output
2367
-     * @return        string
2368
-     */
2369
-    public function form_before_question_group($output)
2370
-    {
2371
-        EE_Error::doing_it_wrong(
2372
-            __CLASS__ . '::' . __FUNCTION__,
2373
-            esc_html__(
2374
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2375
-                'event_espresso'
2376
-            ),
2377
-            '4.8.32.rc.000'
2378
-        );
2379
-        return '
1301
+		if (! empty($registration_status)) {
1302
+			$where['STS_ID'] = $registration_status;
1303
+		} else {
1304
+			// make sure we exclude incomplete registrations, but only if not trashed.
1305
+			if ($view === 'trash') {
1306
+				$where['REG_deleted'] = true;
1307
+			} elseif ($view === 'incomplete') {
1308
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
+			} else {
1310
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
+			}
1312
+		}
1313
+		return $where;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1319
+	 *
1320
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1321
+	 * @return array
1322
+	 * @throws EE_Error
1323
+	 * @throws InvalidArgumentException
1324
+	 * @throws InvalidDataTypeException
1325
+	 * @throws InvalidInterfaceException
1326
+	 */
1327
+	protected function _add_date_to_where_conditions(array $request)
1328
+	{
1329
+		$where = array();
1330
+		$view = EEH_Array::is_set($request, 'status', '');
1331
+		$month_range = ! empty($request['month_range'])
1332
+			? sanitize_text_field($request['month_range'])
1333
+			: '';
1334
+		$retrieve_for_today = $view === 'today';
1335
+		$retrieve_for_this_month = $view === 'month';
1336
+
1337
+		if ($retrieve_for_today) {
1338
+			$now = date('Y-m-d', current_time('timestamp'));
1339
+			$where['REG_date'] = array(
1340
+				'BETWEEN',
1341
+				array(
1342
+					EEM_Registration::instance()->convert_datetime_for_query(
1343
+						'REG_date',
1344
+						$now . ' 00:00:00',
1345
+						'Y-m-d H:i:s'
1346
+					),
1347
+					EEM_Registration::instance()->convert_datetime_for_query(
1348
+						'REG_date',
1349
+						$now . ' 23:59:59',
1350
+						'Y-m-d H:i:s'
1351
+					),
1352
+				),
1353
+			);
1354
+		} elseif ($retrieve_for_this_month) {
1355
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1356
+			$days_this_month = date('t', current_time('timestamp'));
1357
+			$where['REG_date'] = array(
1358
+				'BETWEEN',
1359
+				array(
1360
+					EEM_Registration::instance()->convert_datetime_for_query(
1361
+						'REG_date',
1362
+						$current_year_and_month . '-01 00:00:00',
1363
+						'Y-m-d H:i:s'
1364
+					),
1365
+					EEM_Registration::instance()->convert_datetime_for_query(
1366
+						'REG_date',
1367
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
+						'Y-m-d H:i:s'
1369
+					),
1370
+				),
1371
+			);
1372
+		} elseif ($month_range) {
1373
+			$pieces = explode(' ', $month_range, 3);
1374
+			$month_requested = ! empty($pieces[0])
1375
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
+				: '';
1377
+			$year_requested = ! empty($pieces[1])
1378
+				? $pieces[1]
1379
+				: '';
1380
+			// if there is not a month or year then we can't go further
1381
+			if ($month_requested && $year_requested) {
1382
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
+				$where['REG_date'] = array(
1384
+					'BETWEEN',
1385
+					array(
1386
+						EEM_Registration::instance()->convert_datetime_for_query(
1387
+							'REG_date',
1388
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1389
+							'Y-m-d H:i:s'
1390
+						),
1391
+						EEM_Registration::instance()->convert_datetime_for_query(
1392
+							'REG_date',
1393
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
+							'Y-m-d H:i:s'
1395
+						),
1396
+					),
1397
+				);
1398
+			}
1399
+		}
1400
+		return $where;
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * Adds any provided search restraints to the where conditions for the registrations query
1406
+	 *
1407
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1408
+	 * @return array
1409
+	 */
1410
+	protected function _add_search_to_where_conditions(array $request)
1411
+	{
1412
+		$where = array();
1413
+		if (! empty($request['s'])) {
1414
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
+			$where['OR*search_conditions'] = array(
1416
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1417
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
+				'REG_final_price'                         => array('LIKE', $search_string),
1428
+				'REG_code'                                => array('LIKE', $search_string),
1429
+				'REG_count'                               => array('LIKE', $search_string),
1430
+				'REG_group_size'                          => array('LIKE', $search_string),
1431
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
+			);
1435
+		}
1436
+		return $where;
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Sets up the where conditions for the registrations query.
1442
+	 *
1443
+	 * @param array $request
1444
+	 * @return array
1445
+	 * @throws EE_Error
1446
+	 */
1447
+	protected function _get_where_conditions_for_registrations_query($request)
1448
+	{
1449
+		return apply_filters(
1450
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
+			array_merge(
1452
+				$this->addAttendeeIdToWhereConditions($request),
1453
+				$this->_add_event_id_to_where_conditions($request),
1454
+				$this->_add_category_id_to_where_conditions($request),
1455
+				$this->_add_datetime_id_to_where_conditions($request),
1456
+				$this->_add_registration_status_to_where_conditions($request),
1457
+				$this->_add_date_to_where_conditions($request),
1458
+				$this->_add_search_to_where_conditions($request)
1459
+			),
1460
+			$request
1461
+		);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * Sets up the orderby for the registrations query.
1467
+	 *
1468
+	 * @return array
1469
+	 */
1470
+	protected function _get_orderby_for_registrations_query()
1471
+	{
1472
+		$orderby_field = ! empty($this->_req_data['orderby'])
1473
+			? sanitize_text_field($this->_req_data['orderby'])
1474
+			: '_REG_date';
1475
+		switch ($orderby_field) {
1476
+			case '_REG_ID':
1477
+				$orderby = array('REG_ID');
1478
+				break;
1479
+			case '_Reg_status':
1480
+				$orderby = array('STS_ID');
1481
+				break;
1482
+			case 'ATT_fname':
1483
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
+				break;
1485
+			case 'ATT_lname':
1486
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
+				break;
1488
+			case 'event_name':
1489
+				$orderby = array('Event.EVT_name');
1490
+				break;
1491
+			case 'DTT_EVT_start':
1492
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1493
+				break;
1494
+			case '_REG_date':
1495
+				$orderby = array('REG_date');
1496
+				break;
1497
+			default:
1498
+				$orderby = array($orderby_field);
1499
+				break;
1500
+		}
1501
+
1502
+		// order
1503
+		$order = ! empty($this->_req_data['order'])
1504
+			? sanitize_text_field($this->_req_data['order'])
1505
+			: 'DESC';
1506
+		$orderby = array_combine(
1507
+			$orderby,
1508
+			array_fill(0, count($orderby), $order)
1509
+		);
1510
+		// because there are many registrations with the same date, define
1511
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
1512
+		if (empty($orderby['REG_ID'])) {
1513
+			$orderby['REG_ID'] = $order;
1514
+		}
1515
+
1516
+		$orderby = apply_filters(
1517
+			'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
+			$orderby,
1519
+			$this->_req_data
1520
+		);
1521
+
1522
+		return array('order_by' => $orderby);
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * Sets up the limit for the registrations query.
1528
+	 *
1529
+	 * @param $per_page
1530
+	 * @return array
1531
+	 */
1532
+	protected function _get_limit($per_page)
1533
+	{
1534
+		$current_page = ! empty($this->_req_data['paged'])
1535
+			? absint($this->_req_data['paged'])
1536
+			: 1;
1537
+		$per_page = ! empty($this->_req_data['perpage'])
1538
+			? $this->_req_data['perpage']
1539
+			: $per_page;
1540
+
1541
+		// -1 means return all results so get out if that's set.
1542
+		if ((int) $per_page === -1) {
1543
+			return array();
1544
+		}
1545
+		$per_page = absint($per_page);
1546
+		$offset = ($current_page - 1) * $per_page;
1547
+		return array('limit' => array($offset, $per_page));
1548
+	}
1549
+
1550
+
1551
+	public function get_registration_status_array()
1552
+	{
1553
+		return self::$_reg_status;
1554
+	}
1555
+
1556
+
1557
+
1558
+
1559
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1560
+	/**
1561
+	 *        generates HTML for the View Registration Details Admin page
1562
+	 *
1563
+	 * @access protected
1564
+	 * @return void
1565
+	 * @throws DomainException
1566
+	 * @throws EE_Error
1567
+	 * @throws InvalidArgumentException
1568
+	 * @throws InvalidDataTypeException
1569
+	 * @throws InvalidInterfaceException
1570
+	 * @throws EntityNotFoundException
1571
+	 */
1572
+	protected function _registration_details()
1573
+	{
1574
+		$this->_template_args = array();
1575
+		$this->_set_registration_object();
1576
+		if (is_object($this->_registration)) {
1577
+			$transaction = $this->_registration->transaction()
1578
+				? $this->_registration->transaction()
1579
+				: EE_Transaction::new_instance();
1580
+			$this->_session = $transaction->session_data();
1581
+			$event_id = $this->_registration->event_ID();
1582
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
+			$this->_template_args['grand_total'] = $transaction->total();
1587
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
+			// link back to overview
1589
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
+			$this->_template_args['registration'] = $this->_registration;
1591
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
+				array(
1593
+					'action'   => 'default',
1594
+					'event_id' => $event_id,
1595
+				),
1596
+				REG_ADMIN_URL
1597
+			);
1598
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
+				array(
1600
+					'action' => 'default',
1601
+					'EVT_ID' => $event_id,
1602
+					'page'   => 'espresso_transactions',
1603
+				),
1604
+				admin_url('admin.php')
1605
+			);
1606
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
+				array(
1608
+					'page'   => 'espresso_events',
1609
+					'action' => 'edit',
1610
+					'post'   => $event_id,
1611
+				),
1612
+				admin_url('admin.php')
1613
+			);
1614
+			// next and previous links
1615
+			$next_reg = $this->_registration->next(
1616
+				null,
1617
+				array(),
1618
+				'REG_ID'
1619
+			);
1620
+			$this->_template_args['next_registration'] = $next_reg
1621
+				? $this->_next_link(
1622
+					EE_Admin_Page::add_query_args_and_nonce(
1623
+						array(
1624
+							'action'  => 'view_registration',
1625
+							'_REG_ID' => $next_reg['REG_ID'],
1626
+						),
1627
+						REG_ADMIN_URL
1628
+					),
1629
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1630
+				)
1631
+				: '';
1632
+			$previous_reg = $this->_registration->previous(
1633
+				null,
1634
+				array(),
1635
+				'REG_ID'
1636
+			);
1637
+			$this->_template_args['previous_registration'] = $previous_reg
1638
+				? $this->_previous_link(
1639
+					EE_Admin_Page::add_query_args_and_nonce(
1640
+						array(
1641
+							'action'  => 'view_registration',
1642
+							'_REG_ID' => $previous_reg['REG_ID'],
1643
+						),
1644
+						REG_ADMIN_URL
1645
+					),
1646
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1647
+				)
1648
+				: '';
1649
+			// grab header
1650
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1652
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
+				$template_path,
1654
+				$this->_template_args,
1655
+				true
1656
+			);
1657
+		} else {
1658
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
+		}
1660
+		// the details template wrapper
1661
+		$this->display_admin_page_with_sidebar();
1662
+	}
1663
+
1664
+
1665
+	protected function _registration_details_metaboxes()
1666
+	{
1667
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
+		$this->_set_registration_object();
1669
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
+		add_meta_box(
1671
+			'edit-reg-status-mbox',
1672
+			esc_html__('Registration Status', 'event_espresso'),
1673
+			array($this, 'set_reg_status_buttons_metabox'),
1674
+			$this->wp_page_slug,
1675
+			'normal',
1676
+			'high'
1677
+		);
1678
+		add_meta_box(
1679
+			'edit-reg-details-mbox',
1680
+			esc_html__('Registration Details', 'event_espresso'),
1681
+			array($this, '_reg_details_meta_box'),
1682
+			$this->wp_page_slug,
1683
+			'normal',
1684
+			'high'
1685
+		);
1686
+		if ($attendee instanceof EE_Attendee
1687
+			&& EE_Registry::instance()->CAP->current_user_can(
1688
+				'ee_read_registration',
1689
+				'edit-reg-questions-mbox',
1690
+				$this->_registration->ID()
1691
+			)
1692
+		) {
1693
+			add_meta_box(
1694
+				'edit-reg-questions-mbox',
1695
+				esc_html__('Registration Form Answers', 'event_espresso'),
1696
+				array($this, '_reg_questions_meta_box'),
1697
+				$this->wp_page_slug,
1698
+				'normal',
1699
+				'high'
1700
+			);
1701
+		}
1702
+		add_meta_box(
1703
+			'edit-reg-registrant-mbox',
1704
+			esc_html__('Contact Details', 'event_espresso'),
1705
+			array($this, '_reg_registrant_side_meta_box'),
1706
+			$this->wp_page_slug,
1707
+			'side',
1708
+			'high'
1709
+		);
1710
+		if ($this->_registration->group_size() > 1) {
1711
+			add_meta_box(
1712
+				'edit-reg-attendees-mbox',
1713
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
+				array($this, '_reg_attendees_meta_box'),
1715
+				$this->wp_page_slug,
1716
+				'normal',
1717
+				'high'
1718
+			);
1719
+		}
1720
+	}
1721
+
1722
+
1723
+	/**
1724
+	 * set_reg_status_buttons_metabox
1725
+	 *
1726
+	 * @access protected
1727
+	 * @return string
1728
+	 * @throws \EE_Error
1729
+	 */
1730
+	public function set_reg_status_buttons_metabox()
1731
+	{
1732
+		$this->_set_registration_object();
1733
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1734
+		echo $change_reg_status_form->form_open(
1735
+			self::add_query_args_and_nonce(
1736
+				array(
1737
+					'action' => 'change_reg_status',
1738
+				),
1739
+				REG_ADMIN_URL
1740
+			)
1741
+		);
1742
+		echo $change_reg_status_form->get_html();
1743
+		echo $change_reg_status_form->form_close();
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 * @return EE_Form_Section_Proper
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
+	 */
1755
+	protected function _generate_reg_status_change_form()
1756
+	{
1757
+		$reg_status_change_form_array = array(
1758
+			'name'            => 'reg_status_change_form',
1759
+			'html_id'         => 'reg-status-change-form',
1760
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
+			'subsections'     => array(
1762
+				'return'             => new EE_Hidden_Input(
1763
+					array(
1764
+						'name'    => 'return',
1765
+						'default' => 'view_registration',
1766
+					)
1767
+				),
1768
+				'REG_ID'             => new EE_Hidden_Input(
1769
+					array(
1770
+						'name'    => 'REG_ID',
1771
+						'default' => $this->_registration->ID(),
1772
+					)
1773
+				),
1774
+				'current_status'     => new EE_Form_Section_HTML(
1775
+					EEH_HTML::table(
1776
+						EEH_HTML::tr(
1777
+							EEH_HTML::th(
1778
+								EEH_HTML::label(
1779
+									EEH_HTML::strong(
1780
+										esc_html__('Current Registration Status', 'event_espresso')
1781
+									)
1782
+								)
1783
+							)
1784
+							. EEH_HTML::td(
1785
+								EEH_HTML::strong(
1786
+									$this->_registration->pretty_status(),
1787
+									'',
1788
+									'status-' . $this->_registration->status_ID(),
1789
+									'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1790
+								)
1791
+							)
1792
+						)
1793
+					)
1794
+				)
1795
+			)
1796
+		);
1797
+		if (EE_Registry::instance()->CAP->current_user_can(
1798
+			'ee_edit_registration',
1799
+			'toggle_registration_status',
1800
+			$this->_registration->ID()
1801
+		)) {
1802
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1803
+				$this->_get_reg_statuses(),
1804
+				array(
1805
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1806
+					'default'         => $this->_registration->status_ID(),
1807
+				)
1808
+			);
1809
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1810
+				array(
1811
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1812
+					'default'         => false,
1813
+					'html_help_text'  => esc_html__(
1814
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1815
+						'event_espresso'
1816
+					)
1817
+				)
1818
+			);
1819
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1820
+				array(
1821
+					'html_class'      => 'button-primary',
1822
+					'html_label_text' => '&nbsp;',
1823
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1824
+				)
1825
+			);
1826
+		}
1827
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1828
+	}
1829
+
1830
+
1831
+	/**
1832
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1833
+	 *
1834
+	 * @return array
1835
+	 * @throws EE_Error
1836
+	 * @throws InvalidArgumentException
1837
+	 * @throws InvalidDataTypeException
1838
+	 * @throws InvalidInterfaceException
1839
+	 * @throws EntityNotFoundException
1840
+	 */
1841
+	protected function _get_reg_statuses()
1842
+	{
1843
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1844
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1845
+		// get current reg status
1846
+		$current_status = $this->_registration->status_ID();
1847
+		// is registration for free event? This will determine whether to display the pending payment option
1848
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1849
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1850
+		) {
1851
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1852
+		}
1853
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1854
+	}
1855
+
1856
+
1857
+	/**
1858
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1859
+	 *
1860
+	 * @param bool $status REG status given for changing registrations to.
1861
+	 * @param bool $notify Whether to send messages notifications or not.
1862
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1863
+	 * @throws EE_Error
1864
+	 * @throws InvalidArgumentException
1865
+	 * @throws InvalidDataTypeException
1866
+	 * @throws InvalidInterfaceException
1867
+	 * @throws ReflectionException
1868
+	 * @throws RuntimeException
1869
+	 * @throws EntityNotFoundException
1870
+	 */
1871
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1872
+	{
1873
+		if (isset($this->_req_data['reg_status_change_form'])) {
1874
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1875
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1876
+				: array();
1877
+		} else {
1878
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1879
+				? (array) $this->_req_data['_REG_ID']
1880
+				: array();
1881
+		}
1882
+		// sanitize $REG_IDs
1883
+		$REG_IDs = array_map('absint', $REG_IDs);
1884
+		// and remove empty entries
1885
+		$REG_IDs = array_filter($REG_IDs);
1886
+
1887
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1888
+
1889
+		/**
1890
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1891
+		 * Currently this value is used downstream by the _process_resend_registration method.
1892
+		 *
1893
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1894
+		 * @param bool                     $status           The status registrations were changed to.
1895
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1896
+		 * @param Registrations_Admin_Page $admin_page_object
1897
+		 */
1898
+		$this->_req_data['_REG_ID'] = apply_filters(
1899
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1900
+			$result['REG_ID'],
1901
+			$status,
1902
+			$result['success'],
1903
+			$this
1904
+		);
1905
+
1906
+		// notify?
1907
+		if ($notify
1908
+			&& $result['success']
1909
+			&& ! empty($this->_req_data['_REG_ID'])
1910
+			&& EE_Registry::instance()->CAP->current_user_can(
1911
+				'ee_send_message',
1912
+				'espresso_registrations_resend_registration'
1913
+			)
1914
+		) {
1915
+			$this->_process_resend_registration();
1916
+		}
1917
+		return $result;
1918
+	}
1919
+
1920
+
1921
+	/**
1922
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1923
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1924
+	 *
1925
+	 * @param array  $REG_IDs
1926
+	 * @param string $status
1927
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1928
+	 *                        slug sent with setting the registration status.
1929
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1930
+	 * @throws EE_Error
1931
+	 * @throws InvalidArgumentException
1932
+	 * @throws InvalidDataTypeException
1933
+	 * @throws InvalidInterfaceException
1934
+	 * @throws ReflectionException
1935
+	 * @throws RuntimeException
1936
+	 * @throws EntityNotFoundException
1937
+	 */
1938
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1939
+	{
1940
+		$success = false;
1941
+		// typecast $REG_IDs
1942
+		$REG_IDs = (array) $REG_IDs;
1943
+		if (! empty($REG_IDs)) {
1944
+			$success = true;
1945
+			// set default status if none is passed
1946
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1947
+			$status_context = $notify
1948
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1949
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1950
+			// loop through REG_ID's and change status
1951
+			foreach ($REG_IDs as $REG_ID) {
1952
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1953
+				if ($registration instanceof EE_Registration) {
1954
+					$registration->set_status(
1955
+						$status,
1956
+						false,
1957
+						new Context(
1958
+							$status_context,
1959
+							esc_html__(
1960
+								'Manually triggered status change on a Registration Admin Page route.',
1961
+								'event_espresso'
1962
+							)
1963
+						)
1964
+					);
1965
+					$result = $registration->save();
1966
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1967
+					$success = $result !== false ? $success : false;
1968
+				}
1969
+			}
1970
+		}
1971
+
1972
+		// return $success and processed registrations
1973
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1974
+	}
1975
+
1976
+
1977
+	/**
1978
+	 * Common logic for setting up success message and redirecting to appropriate route
1979
+	 *
1980
+	 * @param  string $STS_ID status id for the registration changed to
1981
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1982
+	 * @return void
1983
+	 * @throws EE_Error
1984
+	 */
1985
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1986
+	{
1987
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1988
+			: array('success' => false);
1989
+		$success = isset($result['success']) && $result['success'];
1990
+		// setup success message
1991
+		if ($success) {
1992
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1993
+				$msg = sprintf(
1994
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1995
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1996
+				);
1997
+			} else {
1998
+				$msg = sprintf(
1999
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
2000
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
2001
+				);
2002
+			}
2003
+			EE_Error::add_success($msg);
2004
+		} else {
2005
+			EE_Error::add_error(
2006
+				esc_html__(
2007
+					'Something went wrong, and the status was not changed',
2008
+					'event_espresso'
2009
+				),
2010
+				__FILE__,
2011
+				__LINE__,
2012
+				__FUNCTION__
2013
+			);
2014
+		}
2015
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2016
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2017
+		} else {
2018
+			$route = array('action' => 'default');
2019
+		}
2020
+		$route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2021
+		$this->_redirect_after_action($success, '', '', $route, true);
2022
+	}
2023
+
2024
+
2025
+	/**
2026
+	 * incoming reg status change from reg details page.
2027
+	 *
2028
+	 * @return void
2029
+	 */
2030
+	protected function _change_reg_status()
2031
+	{
2032
+		$this->_req_data['return'] = 'view_registration';
2033
+		// set notify based on whether the send notifications toggle is set or not
2034
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2035
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2036
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2037
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2038
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2039
+			case EEM_Registration::status_id_approved:
2040
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2041
+				$this->approve_registration($notify);
2042
+				break;
2043
+			case EEM_Registration::status_id_pending_payment:
2044
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2045
+				$this->pending_registration($notify);
2046
+				break;
2047
+			case EEM_Registration::status_id_not_approved:
2048
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2049
+				$this->not_approve_registration($notify);
2050
+				break;
2051
+			case EEM_Registration::status_id_declined:
2052
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2053
+				$this->decline_registration($notify);
2054
+				break;
2055
+			case EEM_Registration::status_id_cancelled:
2056
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2057
+				$this->cancel_registration($notify);
2058
+				break;
2059
+			case EEM_Registration::status_id_wait_list:
2060
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2061
+				$this->wait_list_registration($notify);
2062
+				break;
2063
+			case EEM_Registration::status_id_incomplete:
2064
+			default:
2065
+				$result['success'] = false;
2066
+				unset($this->_req_data['return']);
2067
+				$this->_reg_status_change_return('', false);
2068
+				break;
2069
+		}
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 * Callback for bulk action routes.
2075
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2076
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2077
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2078
+	 * when an action is happening on just a single registration).
2079
+	 *
2080
+	 * @param      $action
2081
+	 * @param bool $notify
2082
+	 */
2083
+	protected function bulk_action_on_registrations($action, $notify = false)
2084
+	{
2085
+		do_action(
2086
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2087
+			$this,
2088
+			$action,
2089
+			$notify
2090
+		);
2091
+		$method = $action . '_registration';
2092
+		if (method_exists($this, $method)) {
2093
+			$this->$method($notify);
2094
+		}
2095
+	}
2096
+
2097
+
2098
+	/**
2099
+	 * approve_registration
2100
+	 *
2101
+	 * @access protected
2102
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2103
+	 * @return void
2104
+	 */
2105
+	protected function approve_registration($notify = false)
2106
+	{
2107
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2108
+	}
2109
+
2110
+
2111
+	/**
2112
+	 *        decline_registration
2113
+	 *
2114
+	 * @access protected
2115
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2116
+	 * @return void
2117
+	 */
2118
+	protected function decline_registration($notify = false)
2119
+	{
2120
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2121
+	}
2122
+
2123
+
2124
+	/**
2125
+	 *        cancel_registration
2126
+	 *
2127
+	 * @access protected
2128
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2129
+	 * @return void
2130
+	 */
2131
+	protected function cancel_registration($notify = false)
2132
+	{
2133
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2134
+	}
2135
+
2136
+
2137
+	/**
2138
+	 *        not_approve_registration
2139
+	 *
2140
+	 * @access protected
2141
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2142
+	 * @return void
2143
+	 */
2144
+	protected function not_approve_registration($notify = false)
2145
+	{
2146
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2147
+	}
2148
+
2149
+
2150
+	/**
2151
+	 *        decline_registration
2152
+	 *
2153
+	 * @access protected
2154
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2155
+	 * @return void
2156
+	 */
2157
+	protected function pending_registration($notify = false)
2158
+	{
2159
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2160
+	}
2161
+
2162
+
2163
+	/**
2164
+	 * waitlist_registration
2165
+	 *
2166
+	 * @access protected
2167
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2168
+	 * @return void
2169
+	 */
2170
+	protected function wait_list_registration($notify = false)
2171
+	{
2172
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2173
+	}
2174
+
2175
+
2176
+	/**
2177
+	 *        generates HTML for the Registration main meta box
2178
+	 *
2179
+	 * @access public
2180
+	 * @return void
2181
+	 * @throws DomainException
2182
+	 * @throws EE_Error
2183
+	 * @throws InvalidArgumentException
2184
+	 * @throws InvalidDataTypeException
2185
+	 * @throws InvalidInterfaceException
2186
+	 * @throws ReflectionException
2187
+	 * @throws EntityNotFoundException
2188
+	 */
2189
+	public function _reg_details_meta_box()
2190
+	{
2191
+		EEH_Autoloader::register_line_item_display_autoloaders();
2192
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2193
+		EE_Registry::instance()->load_helper('Line_Item');
2194
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2195
+			: EE_Transaction::new_instance();
2196
+		$this->_session = $transaction->session_data();
2197
+		$filters = new EE_Line_Item_Filter_Collection();
2198
+		// $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2199
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2200
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2201
+			$filters,
2202
+			$transaction->total_line_item()
2203
+		);
2204
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2205
+		$line_item_display = new EE_Line_Item_Display(
2206
+			'reg_admin_table',
2207
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2208
+		);
2209
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2210
+			$filtered_line_item_tree,
2211
+			array('EE_Registration' => $this->_registration)
2212
+		);
2213
+		$attendee = $this->_registration->attendee();
2214
+		if (EE_Registry::instance()->CAP->current_user_can(
2215
+			'ee_read_transaction',
2216
+			'espresso_transactions_view_transaction'
2217
+		)) {
2218
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2219
+				EE_Admin_Page::add_query_args_and_nonce(
2220
+					array(
2221
+						'action' => 'view_transaction',
2222
+						'TXN_ID' => $transaction->ID(),
2223
+					),
2224
+					TXN_ADMIN_URL
2225
+				),
2226
+				esc_html__(' View Transaction', 'event_espresso'),
2227
+				'button secondary-button right',
2228
+				'dashicons dashicons-cart'
2229
+			);
2230
+		} else {
2231
+			$this->_template_args['view_transaction_button'] = '';
2232
+		}
2233
+		if ($attendee instanceof EE_Attendee
2234
+			&& EE_Registry::instance()->CAP->current_user_can(
2235
+				'ee_send_message',
2236
+				'espresso_registrations_resend_registration'
2237
+			)
2238
+		) {
2239
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2240
+				EE_Admin_Page::add_query_args_and_nonce(
2241
+					array(
2242
+						'action'      => 'resend_registration',
2243
+						'_REG_ID'     => $this->_registration->ID(),
2244
+						'redirect_to' => 'view_registration',
2245
+					),
2246
+					REG_ADMIN_URL
2247
+				),
2248
+				esc_html__(' Resend Registration', 'event_espresso'),
2249
+				'button secondary-button right',
2250
+				'dashicons dashicons-email-alt'
2251
+			);
2252
+		} else {
2253
+			$this->_template_args['resend_registration_button'] = '';
2254
+		}
2255
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2256
+		$payment = $transaction->get_first_related('Payment');
2257
+		$payment = ! $payment instanceof EE_Payment
2258
+			? EE_Payment::new_instance()
2259
+			: $payment;
2260
+		$payment_method = $payment->get_first_related('Payment_Method');
2261
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2262
+			? EE_Payment_Method::new_instance()
2263
+			: $payment_method;
2264
+		$reg_details = array(
2265
+			'payment_method'       => $payment_method->name(),
2266
+			'response_msg'         => $payment->gateway_response(),
2267
+			'registration_id'      => $this->_registration->get('REG_code'),
2268
+			'registration_session' => $this->_registration->session_ID(),
2269
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2270
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2271
+		);
2272
+		if (isset($reg_details['registration_id'])) {
2273
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2274
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2275
+				'Registration ID',
2276
+				'event_espresso'
2277
+			);
2278
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2279
+		}
2280
+		if (isset($reg_details['payment_method'])) {
2281
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2282
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2283
+				'Most Recent Payment Method',
2284
+				'event_espresso'
2285
+			);
2286
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2287
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2288
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2289
+				'Payment method response',
2290
+				'event_espresso'
2291
+			);
2292
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2293
+		}
2294
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2295
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2296
+			'Registration Session',
2297
+			'event_espresso'
2298
+		);
2299
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2300
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2301
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2302
+			'Registration placed from IP',
2303
+			'event_espresso'
2304
+		);
2305
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2306
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2307
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2308
+			'Registrant User Agent',
2309
+			'event_espresso'
2310
+		);
2311
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2312
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2313
+			array(
2314
+				'action'   => 'default',
2315
+				'event_id' => $this->_registration->event_ID(),
2316
+			),
2317
+			REG_ADMIN_URL
2318
+		);
2319
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2320
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2321
+		$template_path =
2322
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2323
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2324
+	}
2325
+
2326
+
2327
+	/**
2328
+	 * generates HTML for the Registration Questions meta box.
2329
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2330
+	 * otherwise uses new forms system
2331
+	 *
2332
+	 * @access public
2333
+	 * @return void
2334
+	 * @throws DomainException
2335
+	 * @throws EE_Error
2336
+	 */
2337
+	public function _reg_questions_meta_box()
2338
+	{
2339
+		// allow someone to override this method entirely
2340
+		if (apply_filters(
2341
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2342
+			true,
2343
+			$this,
2344
+			$this->_registration
2345
+		)) {
2346
+			$form = $this->_get_reg_custom_questions_form(
2347
+				$this->_registration->ID()
2348
+			);
2349
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2350
+				? $form->get_html_and_js()
2351
+				: '';
2352
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2353
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2354
+			$template_path =
2355
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2356
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2357
+		}
2358
+	}
2359
+
2360
+
2361
+	/**
2362
+	 * form_before_question_group
2363
+	 *
2364
+	 * @deprecated    as of 4.8.32.rc.000
2365
+	 * @access        public
2366
+	 * @param        string $output
2367
+	 * @return        string
2368
+	 */
2369
+	public function form_before_question_group($output)
2370
+	{
2371
+		EE_Error::doing_it_wrong(
2372
+			__CLASS__ . '::' . __FUNCTION__,
2373
+			esc_html__(
2374
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2375
+				'event_espresso'
2376
+			),
2377
+			'4.8.32.rc.000'
2378
+		);
2379
+		return '
2380 2380
 	<table class="form-table ee-width-100">
2381 2381
 		<tbody>
2382 2382
 			';
2383
-    }
2384
-
2385
-
2386
-    /**
2387
-     * form_after_question_group
2388
-     *
2389
-     * @deprecated    as of 4.8.32.rc.000
2390
-     * @access        public
2391
-     * @param        string $output
2392
-     * @return        string
2393
-     */
2394
-    public function form_after_question_group($output)
2395
-    {
2396
-        EE_Error::doing_it_wrong(
2397
-            __CLASS__ . '::' . __FUNCTION__,
2398
-            esc_html__(
2399
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2400
-                'event_espresso'
2401
-            ),
2402
-            '4.8.32.rc.000'
2403
-        );
2404
-        return '
2383
+	}
2384
+
2385
+
2386
+	/**
2387
+	 * form_after_question_group
2388
+	 *
2389
+	 * @deprecated    as of 4.8.32.rc.000
2390
+	 * @access        public
2391
+	 * @param        string $output
2392
+	 * @return        string
2393
+	 */
2394
+	public function form_after_question_group($output)
2395
+	{
2396
+		EE_Error::doing_it_wrong(
2397
+			__CLASS__ . '::' . __FUNCTION__,
2398
+			esc_html__(
2399
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2400
+				'event_espresso'
2401
+			),
2402
+			'4.8.32.rc.000'
2403
+		);
2404
+		return '
2405 2405
 			<tr class="hide-if-no-js">
2406 2406
 				<th> </th>
2407 2407
 				<td class="reg-admin-edit-attendee-question-td">
2408 2408
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2409
-               . esc_attr__('click to edit question', 'event_espresso')
2410
-               . '">
2409
+			   . esc_attr__('click to edit question', 'event_espresso')
2410
+			   . '">
2411 2411
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2412
-               . esc_html__('edit the above question group', 'event_espresso')
2413
-               . '</span>
2412
+			   . esc_html__('edit the above question group', 'event_espresso')
2413
+			   . '</span>
2414 2414
 						<div class="dashicons dashicons-edit"></div>
2415 2415
 					</a>
2416 2416
 				</td>
@@ -2418,609 +2418,609 @@  discard block
 block discarded – undo
2418 2418
 		</tbody>
2419 2419
 	</table>
2420 2420
 ';
2421
-    }
2422
-
2423
-
2424
-    /**
2425
-     * form_form_field_label_wrap
2426
-     *
2427
-     * @deprecated    as of 4.8.32.rc.000
2428
-     * @access        public
2429
-     * @param        string $label
2430
-     * @return        string
2431
-     */
2432
-    public function form_form_field_label_wrap($label)
2433
-    {
2434
-        EE_Error::doing_it_wrong(
2435
-            __CLASS__ . '::' . __FUNCTION__,
2436
-            esc_html__(
2437
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2438
-                'event_espresso'
2439
-            ),
2440
-            '4.8.32.rc.000'
2441
-        );
2442
-        return '
2421
+	}
2422
+
2423
+
2424
+	/**
2425
+	 * form_form_field_label_wrap
2426
+	 *
2427
+	 * @deprecated    as of 4.8.32.rc.000
2428
+	 * @access        public
2429
+	 * @param        string $label
2430
+	 * @return        string
2431
+	 */
2432
+	public function form_form_field_label_wrap($label)
2433
+	{
2434
+		EE_Error::doing_it_wrong(
2435
+			__CLASS__ . '::' . __FUNCTION__,
2436
+			esc_html__(
2437
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2438
+				'event_espresso'
2439
+			),
2440
+			'4.8.32.rc.000'
2441
+		);
2442
+		return '
2443 2443
 			<tr>
2444 2444
 				<th>
2445 2445
 					' . $label . '
2446 2446
 				</th>';
2447
-    }
2448
-
2449
-
2450
-    /**
2451
-     * form_form_field_input__wrap
2452
-     *
2453
-     * @deprecated    as of 4.8.32.rc.000
2454
-     * @access        public
2455
-     * @param        string $input
2456
-     * @return        string
2457
-     */
2458
-    public function form_form_field_input__wrap($input)
2459
-    {
2460
-        EE_Error::doing_it_wrong(
2461
-            __CLASS__ . '::' . __FUNCTION__,
2462
-            esc_html__(
2463
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2464
-                'event_espresso'
2465
-            ),
2466
-            '4.8.32.rc.000'
2467
-        );
2468
-        return '
2447
+	}
2448
+
2449
+
2450
+	/**
2451
+	 * form_form_field_input__wrap
2452
+	 *
2453
+	 * @deprecated    as of 4.8.32.rc.000
2454
+	 * @access        public
2455
+	 * @param        string $input
2456
+	 * @return        string
2457
+	 */
2458
+	public function form_form_field_input__wrap($input)
2459
+	{
2460
+		EE_Error::doing_it_wrong(
2461
+			__CLASS__ . '::' . __FUNCTION__,
2462
+			esc_html__(
2463
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2464
+				'event_espresso'
2465
+			),
2466
+			'4.8.32.rc.000'
2467
+		);
2468
+		return '
2469 2469
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2470 2470
 					' . $input . '
2471 2471
 				</td>
2472 2472
 			</tr>';
2473
-    }
2474
-
2475
-
2476
-    /**
2477
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2478
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2479
-     * to display the page
2480
-     *
2481
-     * @access protected
2482
-     * @return void
2483
-     * @throws EE_Error
2484
-     */
2485
-    protected function _update_attendee_registration_form()
2486
-    {
2487
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2488
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2489
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2490
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2491
-            if ($success) {
2492
-                $what = esc_html__('Registration Form', 'event_espresso');
2493
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2494
-                    : array('action' => 'default');
2495
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2496
-            }
2497
-        }
2498
-    }
2499
-
2500
-
2501
-    /**
2502
-     * Gets the form for saving registrations custom questions (if done
2503
-     * previously retrieves the cached form object, which may have validation errors in it)
2504
-     *
2505
-     * @param int $REG_ID
2506
-     * @return EE_Registration_Custom_Questions_Form
2507
-     * @throws EE_Error
2508
-     * @throws InvalidArgumentException
2509
-     * @throws InvalidDataTypeException
2510
-     * @throws InvalidInterfaceException
2511
-     */
2512
-    protected function _get_reg_custom_questions_form($REG_ID)
2513
-    {
2514
-        if (! $this->_reg_custom_questions_form) {
2515
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2516
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2517
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2518
-            );
2519
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2520
-        }
2521
-        return $this->_reg_custom_questions_form;
2522
-    }
2523
-
2524
-
2525
-    /**
2526
-     * Saves
2527
-     *
2528
-     * @access private
2529
-     * @param bool $REG_ID
2530
-     * @return bool
2531
-     * @throws EE_Error
2532
-     * @throws InvalidArgumentException
2533
-     * @throws InvalidDataTypeException
2534
-     * @throws InvalidInterfaceException
2535
-     */
2536
-    private function _save_reg_custom_questions_form($REG_ID = false)
2537
-    {
2538
-        if (! $REG_ID) {
2539
-            EE_Error::add_error(
2540
-                esc_html__(
2541
-                    'An error occurred. No registration ID was received.',
2542
-                    'event_espresso'
2543
-                ),
2544
-                __FILE__,
2545
-                __FUNCTION__,
2546
-                __LINE__
2547
-            );
2548
-        }
2549
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2550
-        $form->receive_form_submission($this->_req_data);
2551
-        $success = false;
2552
-        if ($form->is_valid()) {
2553
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2554
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2555
-                    $where_conditions = array(
2556
-                        'QST_ID' => $question_id,
2557
-                        'REG_ID' => $REG_ID,
2558
-                    );
2559
-                    $possibly_new_values = array(
2560
-                        'ANS_value' => $input->normalized_value(),
2561
-                    );
2562
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2563
-                    if ($answer instanceof EE_Answer) {
2564
-                        $success = $answer->save($possibly_new_values);
2565
-                    } else {
2566
-                        // insert it then
2567
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2568
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2569
-                        $success = $answer->save();
2570
-                    }
2571
-                }
2572
-            }
2573
-        } else {
2574
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2575
-        }
2576
-        return $success;
2577
-    }
2578
-
2579
-
2580
-    /**
2581
-     *        generates HTML for the Registration main meta box
2582
-     *
2583
-     * @access public
2584
-     * @return void
2585
-     * @throws DomainException
2586
-     * @throws EE_Error
2587
-     * @throws InvalidArgumentException
2588
-     * @throws InvalidDataTypeException
2589
-     * @throws InvalidInterfaceException
2590
-     */
2591
-    public function _reg_attendees_meta_box()
2592
-    {
2593
-        $REG = EEM_Registration::instance();
2594
-        // get all other registrations on this transaction, and cache
2595
-        // the attendees for them so we don't have to run another query using force_join
2596
-        $registrations = $REG->get_all(
2597
-            array(
2598
-                array(
2599
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2600
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2601
-                ),
2602
-                'force_join' => array('Attendee'),
2603
-                'default_where_conditions' => 'other_models_only',
2604
-            )
2605
-        );
2606
-        $this->_template_args['attendees'] = array();
2607
-        $this->_template_args['attendee_notice'] = '';
2608
-        if (empty($registrations)
2609
-            || (is_array($registrations)
2610
-                && ! EEH_Array::get_one_item_from_array($registrations))
2611
-        ) {
2612
-            EE_Error::add_error(
2613
-                esc_html__(
2614
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2615
-                    'event_espresso'
2616
-                ),
2617
-                __FILE__,
2618
-                __FUNCTION__,
2619
-                __LINE__
2620
-            );
2621
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2622
-        } else {
2623
-            $att_nmbr = 1;
2624
-            foreach ($registrations as $registration) {
2625
-                /* @var $registration EE_Registration */
2626
-                $attendee = $registration->attendee()
2627
-                    ? $registration->attendee()
2628
-                    : EEM_Attendee::instance()
2629
-                                  ->create_default_object();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2633
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2634
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2635
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2636
-                    ', ',
2637
-                    $attendee->full_address_as_array()
2638
-                );
2639
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2640
-                    array(
2641
-                        'action' => 'edit_attendee',
2642
-                        'post'   => $attendee->ID(),
2643
-                    ),
2644
-                    REG_ADMIN_URL
2645
-                );
2646
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2647
-                    ? $registration->event_obj()->name()
2648
-                    : '';
2649
-                $att_nmbr++;
2650
-            }
2651
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2652
-        }
2653
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2654
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2655
-    }
2656
-
2657
-
2658
-    /**
2659
-     *        generates HTML for the Edit Registration side meta box
2660
-     *
2661
-     * @access public
2662
-     * @return void
2663
-     * @throws DomainException
2664
-     * @throws EE_Error
2665
-     * @throws InvalidArgumentException
2666
-     * @throws InvalidDataTypeException
2667
-     * @throws InvalidInterfaceException
2668
-     */
2669
-    public function _reg_registrant_side_meta_box()
2670
-    {
2671
-        /*@var $attendee EE_Attendee */
2672
-        $att_check = $this->_registration->attendee();
2673
-        $attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2674
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2675
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2676
-        // primary registration object (that way we know if we need to show create button or not)
2677
-        if (! $this->_registration->is_primary_registrant()) {
2678
-            $primary_registration = $this->_registration->get_primary_registration();
2679
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2680
-                : null;
2681
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2682
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2683
-                // custom attendee object so let's not worry about the primary reg.
2684
-                $primary_registration = null;
2685
-            }
2686
-        } else {
2687
-            $primary_registration = null;
2688
-        }
2689
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2690
-        $this->_template_args['fname'] = $attendee->fname();
2691
-        $this->_template_args['lname'] = $attendee->lname();
2692
-        $this->_template_args['email'] = $attendee->email();
2693
-        $this->_template_args['phone'] = $attendee->phone();
2694
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2695
-        // edit link
2696
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2697
-            array(
2698
-                'action' => 'edit_attendee',
2699
-                'post'   => $attendee->ID(),
2700
-            ),
2701
-            REG_ADMIN_URL
2702
-        );
2703
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2704
-        // create link
2705
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2706
-            ? EE_Admin_Page::add_query_args_and_nonce(
2707
-                array(
2708
-                    'action'  => 'duplicate_attendee',
2709
-                    '_REG_ID' => $this->_registration->ID(),
2710
-                ),
2711
-                REG_ADMIN_URL
2712
-            ) : '';
2713
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2714
-        $this->_template_args['att_check'] = $att_check;
2715
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2716
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2717
-    }
2718
-
2719
-
2720
-    /**
2721
-     * trash or restore registrations
2722
-     *
2723
-     * @param  boolean $trash whether to archive or restore
2724
-     * @return void
2725
-     * @throws EE_Error
2726
-     * @throws InvalidArgumentException
2727
-     * @throws InvalidDataTypeException
2728
-     * @throws InvalidInterfaceException
2729
-     * @throws RuntimeException
2730
-     * @access protected
2731
-     */
2732
-    protected function _trash_or_restore_registrations($trash = true)
2733
-    {
2734
-        // if empty _REG_ID then get out because there's nothing to do
2735
-        if (empty($this->_req_data['_REG_ID'])) {
2736
-            EE_Error::add_error(
2737
-                sprintf(
2738
-                    esc_html__(
2739
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2740
-                        'event_espresso'
2741
-                    ),
2742
-                    $trash ? 'trash' : 'restore'
2743
-                ),
2744
-                __FILE__,
2745
-                __LINE__,
2746
-                __FUNCTION__
2747
-            );
2748
-            $this->_redirect_after_action(false, '', '', array(), true);
2749
-        }
2750
-        $success = 0;
2751
-        $overwrite_msgs = false;
2752
-        // Checkboxes
2753
-        if (! is_array($this->_req_data['_REG_ID'])) {
2754
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2755
-        }
2756
-        $reg_count = count($this->_req_data['_REG_ID']);
2757
-        // cycle thru checkboxes
2758
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2759
-            /** @var EE_Registration $REG */
2760
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2761
-            $payments = $REG->registration_payments();
2762
-            if (! empty($payments)) {
2763
-                $name = $REG->attendee() instanceof EE_Attendee
2764
-                    ? $REG->attendee()->full_name()
2765
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2766
-                $overwrite_msgs = true;
2767
-                EE_Error::add_error(
2768
-                    sprintf(
2769
-                        esc_html__(
2770
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2771
-                            'event_espresso'
2772
-                        ),
2773
-                        $name
2774
-                    ),
2775
-                    __FILE__,
2776
-                    __FUNCTION__,
2777
-                    __LINE__
2778
-                );
2779
-                // can't trash this registration because it has payments.
2780
-                continue;
2781
-            }
2782
-            $updated = $trash ? $REG->delete() : $REG->restore();
2783
-            if ($updated) {
2784
-                $success++;
2785
-            }
2786
-        }
2787
-        $this->_redirect_after_action(
2788
-            $success === $reg_count, // were ALL registrations affected?
2789
-            $success > 1
2790
-                ? esc_html__('Registrations', 'event_espresso')
2791
-                : esc_html__('Registration', 'event_espresso'),
2792
-            $trash
2793
-                ? esc_html__('moved to the trash', 'event_espresso')
2794
-                : esc_html__('restored', 'event_espresso'),
2795
-            $this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2796
-            $overwrite_msgs
2797
-        );
2798
-    }
2799
-
2800
-
2801
-    /**
2802
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2803
-     * registration but also.
2804
-     * 1. Removing relations to EE_Attendee
2805
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2806
-     * ALSO trashed.
2807
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2808
-     * 4. Removing relationships between all tickets and the related registrations
2809
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2810
-     * 6. Deleting permanently any related Checkins.
2811
-     *
2812
-     * @return void
2813
-     * @throws EE_Error
2814
-     * @throws InvalidArgumentException
2815
-     * @throws InvalidDataTypeException
2816
-     * @throws InvalidInterfaceException
2817
-     */
2818
-    protected function _delete_registrations()
2819
-    {
2820
-        $REG_MDL = EEM_Registration::instance();
2821
-        $success = 1;
2822
-        // Checkboxes
2823
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2824
-            // if array has more than one element than success message should be plural
2825
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2826
-            // cycle thru checkboxes
2827
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2828
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2829
-                if (! $REG instanceof EE_Registration) {
2830
-                    continue;
2831
-                }
2832
-                $deleted = $this->_delete_registration($REG);
2833
-                if (! $deleted) {
2834
-                    $success = 0;
2835
-                }
2836
-            }
2837
-        } else {
2838
-            // grab single id and delete
2839
-            $REG_ID = $this->_req_data['_REG_ID'];
2840
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2841
-            $deleted = $this->_delete_registration($REG);
2842
-            if (! $deleted) {
2843
-                $success = 0;
2844
-            }
2845
-        }
2846
-        $what = $success > 1
2847
-            ? esc_html__('Registrations', 'event_espresso')
2848
-            : esc_html__('Registration', 'event_espresso');
2849
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2850
-        $this->_redirect_after_action(
2851
-            $success,
2852
-            $what,
2853
-            $action_desc,
2854
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2855
-            true
2856
-        );
2857
-    }
2858
-
2859
-
2860
-    /**
2861
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2862
-     * models get affected.
2863
-     *
2864
-     * @param  EE_Registration $REG registration to be deleted permenantly
2865
-     * @return bool true = successful deletion, false = fail.
2866
-     * @throws EE_Error
2867
-     */
2868
-    protected function _delete_registration(EE_Registration $REG)
2869
-    {
2870
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2871
-        // registrations on the transaction that are NOT trashed.
2872
-        $TXN = $REG->get_first_related('Transaction');
2873
-        $REGS = $TXN->get_many_related('Registration');
2874
-        $all_trashed = true;
2875
-        foreach ($REGS as $registration) {
2876
-            if (! $registration->get('REG_deleted')) {
2877
-                $all_trashed = false;
2878
-            }
2879
-        }
2880
-        if (! $all_trashed) {
2881
-            EE_Error::add_error(
2882
-                esc_html__(
2883
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2884
-                    'event_espresso'
2885
-                ),
2886
-                __FILE__,
2887
-                __FUNCTION__,
2888
-                __LINE__
2889
-            );
2890
-            return false;
2891
-        }
2892
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2893
-        // separately from THIS one).
2894
-        foreach ($REGS as $registration) {
2895
-            // delete related answers
2896
-            $registration->delete_related_permanently('Answer');
2897
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2898
-            $attendee = $registration->get_first_related('Attendee');
2899
-            if ($attendee instanceof EE_Attendee) {
2900
-                $registration->_remove_relation_to($attendee, 'Attendee');
2901
-            }
2902
-            // now remove relationships to tickets on this registration.
2903
-            $registration->_remove_relations('Ticket');
2904
-            // now delete permanently the checkins related to this registration.
2905
-            $registration->delete_related_permanently('Checkin');
2906
-            if ($registration->ID() === $REG->ID()) {
2907
-                continue;
2908
-            } //we don't want to delete permanently the existing registration just yet.
2909
-            // remove relation to transaction for these registrations if NOT the existing registrations
2910
-            $registration->_remove_relations('Transaction');
2911
-            // delete permanently any related messages.
2912
-            $registration->delete_related_permanently('Message');
2913
-            // now delete this registration permanently
2914
-            $registration->delete_permanently();
2915
-        }
2916
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2917
-        // (the transaction and line items should be all that's left).
2918
-        // delete the line items related to the transaction for this registration.
2919
-        $TXN->delete_related_permanently('Line_Item');
2920
-        // we need to remove all the relationships on the transaction
2921
-        $TXN->delete_related_permanently('Payment');
2922
-        $TXN->delete_related_permanently('Extra_Meta');
2923
-        $TXN->delete_related_permanently('Message');
2924
-        // now we can delete this REG permanently (and the transaction of course)
2925
-        $REG->delete_related_permanently('Transaction');
2926
-        return $REG->delete_permanently();
2927
-    }
2928
-
2929
-
2930
-    /**
2931
-     *    generates HTML for the Register New Attendee Admin page
2932
-     *
2933
-     * @access private
2934
-     * @throws DomainException
2935
-     * @throws EE_Error
2936
-     */
2937
-    public function new_registration()
2938
-    {
2939
-        if (! $this->_set_reg_event()) {
2940
-            throw new EE_Error(
2941
-                esc_html__(
2942
-                    'Unable to continue with registering because there is no Event ID in the request',
2943
-                    'event_espresso'
2944
-                )
2945
-            );
2946
-        }
2947
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2948
-        // gotta start with a clean slate if we're not coming here via ajax
2949
-        if (! defined('DOING_AJAX')
2950
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2951
-        ) {
2952
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2953
-        }
2954
-        $this->_template_args['event_name'] = '';
2955
-        // event name
2956
-        if ($this->_reg_event) {
2957
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2958
-            $edit_event_url = self::add_query_args_and_nonce(
2959
-                array(
2960
-                    'action' => 'edit',
2961
-                    'post'   => $this->_reg_event->ID(),
2962
-                ),
2963
-                EVENTS_ADMIN_URL
2964
-            );
2965
-            $edit_event_lnk = '<a href="'
2966
-                              . $edit_event_url
2967
-                              . '" title="'
2968
-                              . esc_attr__('Edit ', 'event_espresso')
2969
-                              . $this->_reg_event->name()
2970
-                              . '">'
2971
-                              . esc_html__('Edit Event', 'event_espresso')
2972
-                              . '</a>';
2973
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2974
-                                                   . $edit_event_lnk
2975
-                                                   . '</span>';
2976
-        }
2977
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2978
-        if (defined('DOING_AJAX')) {
2979
-            $this->_return_json();
2980
-        }
2981
-        // grab header
2982
-        $template_path =
2983
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2984
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2985
-            $template_path,
2986
-            $this->_template_args,
2987
-            true
2988
-        );
2989
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2990
-        // the details template wrapper
2991
-        $this->display_admin_page_with_sidebar();
2992
-    }
2993
-
2994
-
2995
-    /**
2996
-     * This returns the content for a registration step
2997
-     *
2998
-     * @access protected
2999
-     * @return string html
3000
-     * @throws DomainException
3001
-     * @throws EE_Error
3002
-     * @throws InvalidArgumentException
3003
-     * @throws InvalidDataTypeException
3004
-     * @throws InvalidInterfaceException
3005
-     */
3006
-    protected function _get_registration_step_content()
3007
-    {
3008
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3009
-            $warning_msg = sprintf(
3010
-                esc_html__(
3011
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3012
-                    'event_espresso'
3013
-                ),
3014
-                '<br />',
3015
-                '<h3 class="important-notice">',
3016
-                '</h3>',
3017
-                '<div class="float-right">',
3018
-                '<span id="redirect_timer" class="important-notice">30</span>',
3019
-                '</div>',
3020
-                '<b>',
3021
-                '</b>'
3022
-            );
3023
-            return '
2473
+	}
2474
+
2475
+
2476
+	/**
2477
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2478
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2479
+	 * to display the page
2480
+	 *
2481
+	 * @access protected
2482
+	 * @return void
2483
+	 * @throws EE_Error
2484
+	 */
2485
+	protected function _update_attendee_registration_form()
2486
+	{
2487
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2488
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2489
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2490
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2491
+			if ($success) {
2492
+				$what = esc_html__('Registration Form', 'event_espresso');
2493
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2494
+					: array('action' => 'default');
2495
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2496
+			}
2497
+		}
2498
+	}
2499
+
2500
+
2501
+	/**
2502
+	 * Gets the form for saving registrations custom questions (if done
2503
+	 * previously retrieves the cached form object, which may have validation errors in it)
2504
+	 *
2505
+	 * @param int $REG_ID
2506
+	 * @return EE_Registration_Custom_Questions_Form
2507
+	 * @throws EE_Error
2508
+	 * @throws InvalidArgumentException
2509
+	 * @throws InvalidDataTypeException
2510
+	 * @throws InvalidInterfaceException
2511
+	 */
2512
+	protected function _get_reg_custom_questions_form($REG_ID)
2513
+	{
2514
+		if (! $this->_reg_custom_questions_form) {
2515
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2516
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2517
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2518
+			);
2519
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2520
+		}
2521
+		return $this->_reg_custom_questions_form;
2522
+	}
2523
+
2524
+
2525
+	/**
2526
+	 * Saves
2527
+	 *
2528
+	 * @access private
2529
+	 * @param bool $REG_ID
2530
+	 * @return bool
2531
+	 * @throws EE_Error
2532
+	 * @throws InvalidArgumentException
2533
+	 * @throws InvalidDataTypeException
2534
+	 * @throws InvalidInterfaceException
2535
+	 */
2536
+	private function _save_reg_custom_questions_form($REG_ID = false)
2537
+	{
2538
+		if (! $REG_ID) {
2539
+			EE_Error::add_error(
2540
+				esc_html__(
2541
+					'An error occurred. No registration ID was received.',
2542
+					'event_espresso'
2543
+				),
2544
+				__FILE__,
2545
+				__FUNCTION__,
2546
+				__LINE__
2547
+			);
2548
+		}
2549
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2550
+		$form->receive_form_submission($this->_req_data);
2551
+		$success = false;
2552
+		if ($form->is_valid()) {
2553
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2554
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2555
+					$where_conditions = array(
2556
+						'QST_ID' => $question_id,
2557
+						'REG_ID' => $REG_ID,
2558
+					);
2559
+					$possibly_new_values = array(
2560
+						'ANS_value' => $input->normalized_value(),
2561
+					);
2562
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2563
+					if ($answer instanceof EE_Answer) {
2564
+						$success = $answer->save($possibly_new_values);
2565
+					} else {
2566
+						// insert it then
2567
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2568
+						$answer = EE_Answer::new_instance($cols_n_vals);
2569
+						$success = $answer->save();
2570
+					}
2571
+				}
2572
+			}
2573
+		} else {
2574
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2575
+		}
2576
+		return $success;
2577
+	}
2578
+
2579
+
2580
+	/**
2581
+	 *        generates HTML for the Registration main meta box
2582
+	 *
2583
+	 * @access public
2584
+	 * @return void
2585
+	 * @throws DomainException
2586
+	 * @throws EE_Error
2587
+	 * @throws InvalidArgumentException
2588
+	 * @throws InvalidDataTypeException
2589
+	 * @throws InvalidInterfaceException
2590
+	 */
2591
+	public function _reg_attendees_meta_box()
2592
+	{
2593
+		$REG = EEM_Registration::instance();
2594
+		// get all other registrations on this transaction, and cache
2595
+		// the attendees for them so we don't have to run another query using force_join
2596
+		$registrations = $REG->get_all(
2597
+			array(
2598
+				array(
2599
+					'TXN_ID' => $this->_registration->transaction_ID(),
2600
+					'REG_ID' => array('!=', $this->_registration->ID()),
2601
+				),
2602
+				'force_join' => array('Attendee'),
2603
+				'default_where_conditions' => 'other_models_only',
2604
+			)
2605
+		);
2606
+		$this->_template_args['attendees'] = array();
2607
+		$this->_template_args['attendee_notice'] = '';
2608
+		if (empty($registrations)
2609
+			|| (is_array($registrations)
2610
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2611
+		) {
2612
+			EE_Error::add_error(
2613
+				esc_html__(
2614
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2615
+					'event_espresso'
2616
+				),
2617
+				__FILE__,
2618
+				__FUNCTION__,
2619
+				__LINE__
2620
+			);
2621
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2622
+		} else {
2623
+			$att_nmbr = 1;
2624
+			foreach ($registrations as $registration) {
2625
+				/* @var $registration EE_Registration */
2626
+				$attendee = $registration->attendee()
2627
+					? $registration->attendee()
2628
+					: EEM_Attendee::instance()
2629
+								  ->create_default_object();
2630
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2631
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2632
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2633
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2634
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2635
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2636
+					', ',
2637
+					$attendee->full_address_as_array()
2638
+				);
2639
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2640
+					array(
2641
+						'action' => 'edit_attendee',
2642
+						'post'   => $attendee->ID(),
2643
+					),
2644
+					REG_ADMIN_URL
2645
+				);
2646
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2647
+					? $registration->event_obj()->name()
2648
+					: '';
2649
+				$att_nmbr++;
2650
+			}
2651
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2652
+		}
2653
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2654
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2655
+	}
2656
+
2657
+
2658
+	/**
2659
+	 *        generates HTML for the Edit Registration side meta box
2660
+	 *
2661
+	 * @access public
2662
+	 * @return void
2663
+	 * @throws DomainException
2664
+	 * @throws EE_Error
2665
+	 * @throws InvalidArgumentException
2666
+	 * @throws InvalidDataTypeException
2667
+	 * @throws InvalidInterfaceException
2668
+	 */
2669
+	public function _reg_registrant_side_meta_box()
2670
+	{
2671
+		/*@var $attendee EE_Attendee */
2672
+		$att_check = $this->_registration->attendee();
2673
+		$attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2674
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2675
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2676
+		// primary registration object (that way we know if we need to show create button or not)
2677
+		if (! $this->_registration->is_primary_registrant()) {
2678
+			$primary_registration = $this->_registration->get_primary_registration();
2679
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2680
+				: null;
2681
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2682
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2683
+				// custom attendee object so let's not worry about the primary reg.
2684
+				$primary_registration = null;
2685
+			}
2686
+		} else {
2687
+			$primary_registration = null;
2688
+		}
2689
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2690
+		$this->_template_args['fname'] = $attendee->fname();
2691
+		$this->_template_args['lname'] = $attendee->lname();
2692
+		$this->_template_args['email'] = $attendee->email();
2693
+		$this->_template_args['phone'] = $attendee->phone();
2694
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2695
+		// edit link
2696
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2697
+			array(
2698
+				'action' => 'edit_attendee',
2699
+				'post'   => $attendee->ID(),
2700
+			),
2701
+			REG_ADMIN_URL
2702
+		);
2703
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2704
+		// create link
2705
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2706
+			? EE_Admin_Page::add_query_args_and_nonce(
2707
+				array(
2708
+					'action'  => 'duplicate_attendee',
2709
+					'_REG_ID' => $this->_registration->ID(),
2710
+				),
2711
+				REG_ADMIN_URL
2712
+			) : '';
2713
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2714
+		$this->_template_args['att_check'] = $att_check;
2715
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2716
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2717
+	}
2718
+
2719
+
2720
+	/**
2721
+	 * trash or restore registrations
2722
+	 *
2723
+	 * @param  boolean $trash whether to archive or restore
2724
+	 * @return void
2725
+	 * @throws EE_Error
2726
+	 * @throws InvalidArgumentException
2727
+	 * @throws InvalidDataTypeException
2728
+	 * @throws InvalidInterfaceException
2729
+	 * @throws RuntimeException
2730
+	 * @access protected
2731
+	 */
2732
+	protected function _trash_or_restore_registrations($trash = true)
2733
+	{
2734
+		// if empty _REG_ID then get out because there's nothing to do
2735
+		if (empty($this->_req_data['_REG_ID'])) {
2736
+			EE_Error::add_error(
2737
+				sprintf(
2738
+					esc_html__(
2739
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2740
+						'event_espresso'
2741
+					),
2742
+					$trash ? 'trash' : 'restore'
2743
+				),
2744
+				__FILE__,
2745
+				__LINE__,
2746
+				__FUNCTION__
2747
+			);
2748
+			$this->_redirect_after_action(false, '', '', array(), true);
2749
+		}
2750
+		$success = 0;
2751
+		$overwrite_msgs = false;
2752
+		// Checkboxes
2753
+		if (! is_array($this->_req_data['_REG_ID'])) {
2754
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2755
+		}
2756
+		$reg_count = count($this->_req_data['_REG_ID']);
2757
+		// cycle thru checkboxes
2758
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2759
+			/** @var EE_Registration $REG */
2760
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2761
+			$payments = $REG->registration_payments();
2762
+			if (! empty($payments)) {
2763
+				$name = $REG->attendee() instanceof EE_Attendee
2764
+					? $REG->attendee()->full_name()
2765
+					: esc_html__('Unknown Attendee', 'event_espresso');
2766
+				$overwrite_msgs = true;
2767
+				EE_Error::add_error(
2768
+					sprintf(
2769
+						esc_html__(
2770
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2771
+							'event_espresso'
2772
+						),
2773
+						$name
2774
+					),
2775
+					__FILE__,
2776
+					__FUNCTION__,
2777
+					__LINE__
2778
+				);
2779
+				// can't trash this registration because it has payments.
2780
+				continue;
2781
+			}
2782
+			$updated = $trash ? $REG->delete() : $REG->restore();
2783
+			if ($updated) {
2784
+				$success++;
2785
+			}
2786
+		}
2787
+		$this->_redirect_after_action(
2788
+			$success === $reg_count, // were ALL registrations affected?
2789
+			$success > 1
2790
+				? esc_html__('Registrations', 'event_espresso')
2791
+				: esc_html__('Registration', 'event_espresso'),
2792
+			$trash
2793
+				? esc_html__('moved to the trash', 'event_espresso')
2794
+				: esc_html__('restored', 'event_espresso'),
2795
+			$this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2796
+			$overwrite_msgs
2797
+		);
2798
+	}
2799
+
2800
+
2801
+	/**
2802
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2803
+	 * registration but also.
2804
+	 * 1. Removing relations to EE_Attendee
2805
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2806
+	 * ALSO trashed.
2807
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2808
+	 * 4. Removing relationships between all tickets and the related registrations
2809
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2810
+	 * 6. Deleting permanently any related Checkins.
2811
+	 *
2812
+	 * @return void
2813
+	 * @throws EE_Error
2814
+	 * @throws InvalidArgumentException
2815
+	 * @throws InvalidDataTypeException
2816
+	 * @throws InvalidInterfaceException
2817
+	 */
2818
+	protected function _delete_registrations()
2819
+	{
2820
+		$REG_MDL = EEM_Registration::instance();
2821
+		$success = 1;
2822
+		// Checkboxes
2823
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2824
+			// if array has more than one element than success message should be plural
2825
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2826
+			// cycle thru checkboxes
2827
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2828
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2829
+				if (! $REG instanceof EE_Registration) {
2830
+					continue;
2831
+				}
2832
+				$deleted = $this->_delete_registration($REG);
2833
+				if (! $deleted) {
2834
+					$success = 0;
2835
+				}
2836
+			}
2837
+		} else {
2838
+			// grab single id and delete
2839
+			$REG_ID = $this->_req_data['_REG_ID'];
2840
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2841
+			$deleted = $this->_delete_registration($REG);
2842
+			if (! $deleted) {
2843
+				$success = 0;
2844
+			}
2845
+		}
2846
+		$what = $success > 1
2847
+			? esc_html__('Registrations', 'event_espresso')
2848
+			: esc_html__('Registration', 'event_espresso');
2849
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2850
+		$this->_redirect_after_action(
2851
+			$success,
2852
+			$what,
2853
+			$action_desc,
2854
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2855
+			true
2856
+		);
2857
+	}
2858
+
2859
+
2860
+	/**
2861
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2862
+	 * models get affected.
2863
+	 *
2864
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2865
+	 * @return bool true = successful deletion, false = fail.
2866
+	 * @throws EE_Error
2867
+	 */
2868
+	protected function _delete_registration(EE_Registration $REG)
2869
+	{
2870
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2871
+		// registrations on the transaction that are NOT trashed.
2872
+		$TXN = $REG->get_first_related('Transaction');
2873
+		$REGS = $TXN->get_many_related('Registration');
2874
+		$all_trashed = true;
2875
+		foreach ($REGS as $registration) {
2876
+			if (! $registration->get('REG_deleted')) {
2877
+				$all_trashed = false;
2878
+			}
2879
+		}
2880
+		if (! $all_trashed) {
2881
+			EE_Error::add_error(
2882
+				esc_html__(
2883
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2884
+					'event_espresso'
2885
+				),
2886
+				__FILE__,
2887
+				__FUNCTION__,
2888
+				__LINE__
2889
+			);
2890
+			return false;
2891
+		}
2892
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2893
+		// separately from THIS one).
2894
+		foreach ($REGS as $registration) {
2895
+			// delete related answers
2896
+			$registration->delete_related_permanently('Answer');
2897
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2898
+			$attendee = $registration->get_first_related('Attendee');
2899
+			if ($attendee instanceof EE_Attendee) {
2900
+				$registration->_remove_relation_to($attendee, 'Attendee');
2901
+			}
2902
+			// now remove relationships to tickets on this registration.
2903
+			$registration->_remove_relations('Ticket');
2904
+			// now delete permanently the checkins related to this registration.
2905
+			$registration->delete_related_permanently('Checkin');
2906
+			if ($registration->ID() === $REG->ID()) {
2907
+				continue;
2908
+			} //we don't want to delete permanently the existing registration just yet.
2909
+			// remove relation to transaction for these registrations if NOT the existing registrations
2910
+			$registration->_remove_relations('Transaction');
2911
+			// delete permanently any related messages.
2912
+			$registration->delete_related_permanently('Message');
2913
+			// now delete this registration permanently
2914
+			$registration->delete_permanently();
2915
+		}
2916
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2917
+		// (the transaction and line items should be all that's left).
2918
+		// delete the line items related to the transaction for this registration.
2919
+		$TXN->delete_related_permanently('Line_Item');
2920
+		// we need to remove all the relationships on the transaction
2921
+		$TXN->delete_related_permanently('Payment');
2922
+		$TXN->delete_related_permanently('Extra_Meta');
2923
+		$TXN->delete_related_permanently('Message');
2924
+		// now we can delete this REG permanently (and the transaction of course)
2925
+		$REG->delete_related_permanently('Transaction');
2926
+		return $REG->delete_permanently();
2927
+	}
2928
+
2929
+
2930
+	/**
2931
+	 *    generates HTML for the Register New Attendee Admin page
2932
+	 *
2933
+	 * @access private
2934
+	 * @throws DomainException
2935
+	 * @throws EE_Error
2936
+	 */
2937
+	public function new_registration()
2938
+	{
2939
+		if (! $this->_set_reg_event()) {
2940
+			throw new EE_Error(
2941
+				esc_html__(
2942
+					'Unable to continue with registering because there is no Event ID in the request',
2943
+					'event_espresso'
2944
+				)
2945
+			);
2946
+		}
2947
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2948
+		// gotta start with a clean slate if we're not coming here via ajax
2949
+		if (! defined('DOING_AJAX')
2950
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2951
+		) {
2952
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2953
+		}
2954
+		$this->_template_args['event_name'] = '';
2955
+		// event name
2956
+		if ($this->_reg_event) {
2957
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2958
+			$edit_event_url = self::add_query_args_and_nonce(
2959
+				array(
2960
+					'action' => 'edit',
2961
+					'post'   => $this->_reg_event->ID(),
2962
+				),
2963
+				EVENTS_ADMIN_URL
2964
+			);
2965
+			$edit_event_lnk = '<a href="'
2966
+							  . $edit_event_url
2967
+							  . '" title="'
2968
+							  . esc_attr__('Edit ', 'event_espresso')
2969
+							  . $this->_reg_event->name()
2970
+							  . '">'
2971
+							  . esc_html__('Edit Event', 'event_espresso')
2972
+							  . '</a>';
2973
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2974
+												   . $edit_event_lnk
2975
+												   . '</span>';
2976
+		}
2977
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2978
+		if (defined('DOING_AJAX')) {
2979
+			$this->_return_json();
2980
+		}
2981
+		// grab header
2982
+		$template_path =
2983
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2984
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2985
+			$template_path,
2986
+			$this->_template_args,
2987
+			true
2988
+		);
2989
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2990
+		// the details template wrapper
2991
+		$this->display_admin_page_with_sidebar();
2992
+	}
2993
+
2994
+
2995
+	/**
2996
+	 * This returns the content for a registration step
2997
+	 *
2998
+	 * @access protected
2999
+	 * @return string html
3000
+	 * @throws DomainException
3001
+	 * @throws EE_Error
3002
+	 * @throws InvalidArgumentException
3003
+	 * @throws InvalidDataTypeException
3004
+	 * @throws InvalidInterfaceException
3005
+	 */
3006
+	protected function _get_registration_step_content()
3007
+	{
3008
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3009
+			$warning_msg = sprintf(
3010
+				esc_html__(
3011
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3012
+					'event_espresso'
3013
+				),
3014
+				'<br />',
3015
+				'<h3 class="important-notice">',
3016
+				'</h3>',
3017
+				'<div class="float-right">',
3018
+				'<span id="redirect_timer" class="important-notice">30</span>',
3019
+				'</div>',
3020
+				'<b>',
3021
+				'</b>'
3022
+			);
3023
+			return '
3024 3024
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3025 3025
 	<script >
3026 3026
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -3033,855 +3033,855 @@  discard block
 block discarded – undo
3033 3033
 	        }
3034 3034
 	    }, 800 );
3035 3035
 	</script >';
3036
-        }
3037
-        $template_args = array(
3038
-            'title'                    => '',
3039
-            'content'                  => '',
3040
-            'step_button_text'         => '',
3041
-            'show_notification_toggle' => false,
3042
-        );
3043
-        // to indicate we're processing a new registration
3044
-        $hidden_fields = array(
3045
-            'processing_registration' => array(
3046
-                'type'  => 'hidden',
3047
-                'value' => 0,
3048
-            ),
3049
-            'event_id'                => array(
3050
-                'type'  => 'hidden',
3051
-                'value' => $this->_reg_event->ID(),
3052
-            ),
3053
-        );
3054
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
3055
-        $cart = EE_Registry::instance()->SSN->cart();
3056
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3057
-        switch ($step) {
3058
-            case 'ticket':
3059
-                $hidden_fields['processing_registration']['value'] = 1;
3060
-                $template_args['title'] = esc_html__(
3061
-                    'Step One: Select the Ticket for this registration',
3062
-                    'event_espresso'
3063
-                );
3064
-                $template_args['content'] =
3065
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3066
-                $template_args['step_button_text'] = esc_html__(
3067
-                    'Add Tickets and Continue to Registrant Details',
3068
-                    'event_espresso'
3069
-                );
3070
-                $template_args['show_notification_toggle'] = false;
3071
-                break;
3072
-            case 'questions':
3073
-                $hidden_fields['processing_registration']['value'] = 2;
3074
-                $template_args['title'] = esc_html__(
3075
-                    'Step Two: Add Registrant Details for this Registration',
3076
-                    'event_espresso'
3077
-                );
3078
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3079
-                // properly by the first process_reg_step run.
3080
-                $template_args['content'] =
3081
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3082
-                $template_args['step_button_text'] = esc_html__(
3083
-                    'Save Registration and Continue to Details',
3084
-                    'event_espresso'
3085
-                );
3086
-                $template_args['show_notification_toggle'] = true;
3087
-                break;
3088
-        }
3089
-        // we come back to the process_registration_step route.
3090
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3091
-        return EEH_Template::display_template(
3092
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3093
-            $template_args,
3094
-            true
3095
-        );
3096
-    }
3097
-
3098
-
3099
-    /**
3100
-     *        set_reg_event
3101
-     *
3102
-     * @access private
3103
-     * @return bool
3104
-     * @throws EE_Error
3105
-     * @throws InvalidArgumentException
3106
-     * @throws InvalidDataTypeException
3107
-     * @throws InvalidInterfaceException
3108
-     */
3109
-    private function _set_reg_event()
3110
-    {
3111
-        if (is_object($this->_reg_event)) {
3112
-            return true;
3113
-        }
3114
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3115
-        if (! $EVT_ID) {
3116
-            return false;
3117
-        }
3118
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3119
-        return true;
3120
-    }
3121
-
3122
-
3123
-    /**
3124
-     * process_reg_step
3125
-     *
3126
-     * @access        public
3127
-     * @return string
3128
-     * @throws DomainException
3129
-     * @throws EE_Error
3130
-     * @throws InvalidArgumentException
3131
-     * @throws InvalidDataTypeException
3132
-     * @throws InvalidInterfaceException
3133
-     * @throws ReflectionException
3134
-     * @throws RuntimeException
3135
-     */
3136
-    public function process_reg_step()
3137
-    {
3138
-        EE_System::do_not_cache();
3139
-        $this->_set_reg_event();
3140
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3141
-        EE_Registry::instance()->REQ->set('uts', time());
3142
-        // what step are we on?
3143
-        $cart = EE_Registry::instance()->SSN->cart();
3144
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3145
-        // if doing ajax then we need to verify the nonce
3146
-        if (defined('DOING_AJAX')) {
3147
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3148
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3149
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3150
-        }
3151
-        switch ($step) {
3152
-            case 'ticket':
3153
-                // process ticket selection
3154
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3155
-                if ($success) {
3156
-                    EE_Error::add_success(
3157
-                        esc_html__(
3158
-                            'Tickets Selected. Now complete the registration.',
3159
-                            'event_espresso'
3160
-                        )
3161
-                    );
3162
-                } else {
3163
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3164
-                }
3165
-                if (defined('DOING_AJAX')) {
3166
-                    $this->new_registration(); // display next step
3167
-                } else {
3168
-                    $query_args = array(
3169
-                        'action'                  => 'new_registration',
3170
-                        'processing_registration' => 1,
3171
-                        'event_id'                => $this->_reg_event->ID(),
3172
-                        'uts'                     => time(),
3173
-                    );
3174
-                    $this->_redirect_after_action(
3175
-                        false,
3176
-                        '',
3177
-                        '',
3178
-                        $query_args,
3179
-                        true
3180
-                    );
3181
-                }
3182
-                break;
3183
-            case 'questions':
3184
-                if (! isset(
3185
-                    $this->_req_data['txn_reg_status_change'],
3186
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3187
-                )
3188
-                ) {
3189
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3190
-                }
3191
-                // process registration
3192
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3193
-                if ($cart instanceof EE_Cart) {
3194
-                    $grand_total = $cart->get_cart_grand_total();
3195
-                    if ($grand_total instanceof EE_Line_Item) {
3196
-                        $grand_total->save_this_and_descendants_to_txn();
3197
-                    }
3198
-                }
3199
-                if (! $transaction instanceof EE_Transaction) {
3200
-                    $query_args = array(
3201
-                        'action'                  => 'new_registration',
3202
-                        'processing_registration' => 2,
3203
-                        'event_id'                => $this->_reg_event->ID(),
3204
-                        'uts'                     => time(),
3205
-                    );
3206
-                    if (defined('DOING_AJAX')) {
3207
-                        // display registration form again because there are errors (maybe validation?)
3208
-                        $this->new_registration();
3209
-                        return;
3210
-                    } else {
3211
-                        $this->_redirect_after_action(
3212
-                            false,
3213
-                            '',
3214
-                            '',
3215
-                            $query_args,
3216
-                            true
3217
-                        );
3218
-                        return;
3219
-                    }
3220
-                }
3221
-                // maybe update status, and make sure to save transaction if not done already
3222
-                if (! $transaction->update_status_based_on_total_paid()) {
3223
-                    $transaction->save();
3224
-                }
3225
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3226
-                $this->_req_data = array();
3227
-                $query_args = array(
3228
-                    'action'        => 'redirect_to_txn',
3229
-                    'TXN_ID'        => $transaction->ID(),
3230
-                    'EVT_ID'        => $this->_reg_event->ID(),
3231
-                    'event_name'    => urlencode($this->_reg_event->name()),
3232
-                    'redirect_from' => 'new_registration',
3233
-                );
3234
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3235
-                break;
3236
-        }
3237
-        // what are you looking here for?  Should be nothing to do at this point.
3238
-    }
3239
-
3240
-
3241
-    /**
3242
-     * redirect_to_txn
3243
-     *
3244
-     * @access public
3245
-     * @return void
3246
-     * @throws EE_Error
3247
-     * @throws InvalidArgumentException
3248
-     * @throws InvalidDataTypeException
3249
-     * @throws InvalidInterfaceException
3250
-     */
3251
-    public function redirect_to_txn()
3252
-    {
3253
-        EE_System::do_not_cache();
3254
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3255
-        $query_args = array(
3256
-            'action' => 'view_transaction',
3257
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3258
-            'page'   => 'espresso_transactions',
3259
-        );
3260
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3261
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3262
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3263
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3264
-        }
3265
-        EE_Error::add_success(
3266
-            esc_html__(
3267
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3268
-                'event_espresso'
3269
-            )
3270
-        );
3271
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3272
-    }
3273
-
3274
-
3275
-    /**
3276
-     *        generates HTML for the Attendee Contact List
3277
-     *
3278
-     * @access protected
3279
-     * @return void
3280
-     */
3281
-    protected function _attendee_contact_list_table()
3282
-    {
3283
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3284
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3285
-        $this->display_admin_list_table_page_with_no_sidebar();
3286
-    }
3287
-
3288
-
3289
-    /**
3290
-     *        get_attendees
3291
-     *
3292
-     * @param      $per_page
3293
-     * @param bool $count whether to return count or data.
3294
-     * @param bool $trash
3295
-     * @return array
3296
-     * @throws EE_Error
3297
-     * @throws InvalidArgumentException
3298
-     * @throws InvalidDataTypeException
3299
-     * @throws InvalidInterfaceException
3300
-     * @access public
3301
-     */
3302
-    public function get_attendees($per_page, $count = false, $trash = false)
3303
-    {
3304
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3305
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3306
-        $ATT_MDL = EEM_Attendee::instance();
3307
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3308
-        switch ($this->_req_data['orderby']) {
3309
-            case 'ATT_ID':
3310
-                $orderby = 'ATT_ID';
3311
-                break;
3312
-            case 'ATT_fname':
3313
-                $orderby = 'ATT_fname';
3314
-                break;
3315
-            case 'ATT_email':
3316
-                $orderby = 'ATT_email';
3317
-                break;
3318
-            case 'ATT_city':
3319
-                $orderby = 'ATT_city';
3320
-                break;
3321
-            case 'STA_ID':
3322
-                $orderby = 'STA_ID';
3323
-                break;
3324
-            case 'CNT_ID':
3325
-                $orderby = 'CNT_ID';
3326
-                break;
3327
-            case 'Registration_Count':
3328
-                $orderby = 'Registration_Count';
3329
-                break;
3330
-            default:
3331
-                $orderby = 'ATT_lname';
3332
-        }
3333
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3334
-            ? $this->_req_data['order']
3335
-            : 'ASC';
3336
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3337
-            ? $this->_req_data['paged']
3338
-            : 1;
3339
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3340
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3341
-            ? $this->_req_data['perpage']
3342
-            : $per_page;
3343
-        $_where = array();
3344
-        if (! empty($this->_req_data['s'])) {
3345
-            $sstr = '%' . $this->_req_data['s'] . '%';
3346
-            $_where['OR'] = array(
3347
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3348
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3349
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3350
-                'ATT_fname'                         => array('LIKE', $sstr),
3351
-                'ATT_lname'                         => array('LIKE', $sstr),
3352
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3353
-                'ATT_email'                         => array('LIKE', $sstr),
3354
-                'ATT_address'                       => array('LIKE', $sstr),
3355
-                'ATT_address2'                      => array('LIKE', $sstr),
3356
-                'ATT_city'                          => array('LIKE', $sstr),
3357
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3358
-                'State.STA_name'                    => array('LIKE', $sstr),
3359
-                'ATT_phone'                         => array('LIKE', $sstr),
3360
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3361
-                'Registration.REG_code'             => array('LIKE', $sstr),
3362
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3363
-            );
3364
-        }
3365
-        $offset = ($current_page - 1) * $per_page;
3366
-        $limit = $count ? null : array($offset, $per_page);
3367
-        $query_args = array(
3368
-            $_where,
3369
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3370
-            'limit'         => $limit,
3371
-        );
3372
-        if (! $count) {
3373
-            $query_args['order_by'] = array($orderby => $sort);
3374
-        }
3375
-        if ($trash) {
3376
-            $query_args[0]['status'] = array('!=', 'publish');
3377
-            $all_attendees = $count
3378
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3379
-                : $ATT_MDL->get_all($query_args);
3380
-        } else {
3381
-            $query_args[0]['status'] = array('IN', array('publish'));
3382
-            $all_attendees = $count
3383
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3384
-                : $ATT_MDL->get_all($query_args);
3385
-        }
3386
-        return $all_attendees;
3387
-    }
3388
-
3389
-
3390
-    /**
3391
-     * This is just taking care of resending the registration confirmation
3392
-     *
3393
-     * @access protected
3394
-     * @return void
3395
-     */
3396
-    protected function _resend_registration()
3397
-    {
3398
-        $this->_process_resend_registration();
3399
-        $query_args = isset($this->_req_data['redirect_to'])
3400
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3401
-            : array('action' => 'default');
3402
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3403
-    }
3404
-
3405
-    /**
3406
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3407
-     * to use when selecting registrations
3408
-     *
3409
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3410
-     *                                                     the query parameters from the request
3411
-     * @return void ends the request with a redirect or download
3412
-     */
3413
-    public function _registrations_report_base($method_name_for_getting_query_params)
3414
-    {
3415
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3416
-            wp_redirect(
3417
-                EE_Admin_Page::add_query_args_and_nonce(
3418
-                    array(
3419
-                        'page'        => 'espresso_batch',
3420
-                        'batch'       => 'file',
3421
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3422
-                        'filters'     => urlencode(
3423
-                            serialize(
3424
-                                call_user_func(
3425
-                                    array($this, $method_name_for_getting_query_params),
3426
-                                    EEH_Array::is_set(
3427
-                                        $this->_req_data,
3428
-                                        'filters',
3429
-                                        array()
3430
-                                    )
3431
-                                )
3432
-                            )
3433
-                        ),
3434
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3435
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3436
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3437
-                    )
3438
-                )
3439
-            );
3440
-        } else {
3441
-            $new_request_args = array(
3442
-                'export' => 'report',
3443
-                'action' => 'registrations_report_for_event',
3444
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3445
-            );
3446
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3447
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3448
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3449
-                $EE_Export = EE_Export::instance($this->_req_data);
3450
-                $EE_Export->export();
3451
-            }
3452
-        }
3453
-    }
3454
-
3455
-
3456
-    /**
3457
-     * Creates a registration report using only query parameters in the request
3458
-     *
3459
-     * @return void
3460
-     */
3461
-    public function _registrations_report()
3462
-    {
3463
-        $this->_registrations_report_base('_get_registration_query_parameters');
3464
-    }
3465
-
3466
-
3467
-    public function _contact_list_export()
3468
-    {
3469
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3470
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3471
-            $EE_Export = EE_Export::instance($this->_req_data);
3472
-            $EE_Export->export_attendees();
3473
-        }
3474
-    }
3475
-
3476
-
3477
-    public function _contact_list_report()
3478
-    {
3479
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3480
-            wp_redirect(
3481
-                EE_Admin_Page::add_query_args_and_nonce(
3482
-                    array(
3483
-                        'page'        => 'espresso_batch',
3484
-                        'batch'       => 'file',
3485
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3486
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3487
-                    )
3488
-                )
3489
-            );
3490
-        } else {
3491
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3492
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3493
-                $EE_Export = EE_Export::instance($this->_req_data);
3494
-                $EE_Export->report_attendees();
3495
-            }
3496
-        }
3497
-    }
3498
-
3499
-
3500
-
3501
-
3502
-
3503
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3504
-    /**
3505
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3506
-     *
3507
-     * @return void
3508
-     * @throws EE_Error
3509
-     * @throws InvalidArgumentException
3510
-     * @throws InvalidDataTypeException
3511
-     * @throws InvalidInterfaceException
3512
-     */
3513
-    protected function _duplicate_attendee()
3514
-    {
3515
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3516
-        // verify we have necessary info
3517
-        if (empty($this->_req_data['_REG_ID'])) {
3518
-            EE_Error::add_error(
3519
-                esc_html__(
3520
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3521
-                    'event_espresso'
3522
-                ),
3523
-                __FILE__,
3524
-                __LINE__,
3525
-                __FUNCTION__
3526
-            );
3527
-            $query_args = array('action' => $action);
3528
-            $this->_redirect_after_action('', '', '', $query_args, true);
3529
-        }
3530
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3531
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3532
-        $attendee = $registration->attendee();
3533
-        // remove relation of existing attendee on registration
3534
-        $registration->_remove_relation_to($attendee, 'Attendee');
3535
-        // new attendee
3536
-        $new_attendee = clone $attendee;
3537
-        $new_attendee->set('ATT_ID', 0);
3538
-        $new_attendee->save();
3539
-        // add new attendee to reg
3540
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3541
-        EE_Error::add_success(
3542
-            esc_html__(
3543
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3544
-                'event_espresso'
3545
-            )
3546
-        );
3547
-        // redirect to edit page for attendee
3548
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3549
-        $this->_redirect_after_action('', '', '', $query_args, true);
3550
-    }
3551
-
3552
-
3553
-    /**
3554
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3555
-     *
3556
-     * @param int     $post_id
3557
-     * @param WP_POST $post
3558
-     * @throws DomainException
3559
-     * @throws EE_Error
3560
-     * @throws InvalidArgumentException
3561
-     * @throws InvalidDataTypeException
3562
-     * @throws InvalidInterfaceException
3563
-     * @throws LogicException
3564
-     * @throws InvalidFormSubmissionException
3565
-     */
3566
-    protected function _insert_update_cpt_item($post_id, $post)
3567
-    {
3568
-        $success = true;
3569
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3570
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3571
-            : null;
3572
-        // for attendee updates
3573
-        if ($attendee instanceof EE_Attendee) {
3574
-            // note we should only be UPDATING attendees at this point.
3575
-            $updated_fields = array(
3576
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3577
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3578
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3579
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3580
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3581
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3582
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3583
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3584
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3585
-            );
3586
-            foreach ($updated_fields as $field => $value) {
3587
-                $attendee->set($field, $value);
3588
-            }
3589
-
3590
-            // process contact details metabox form handler (which will also save the attendee)
3591
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3592
-            $success = $contact_details_form->process($this->_req_data);
3593
-
3594
-            $attendee_update_callbacks = apply_filters(
3595
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3596
-                array()
3597
-            );
3598
-            foreach ($attendee_update_callbacks as $a_callback) {
3599
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3600
-                    throw new EE_Error(
3601
-                        sprintf(
3602
-                            esc_html__(
3603
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3604
-                                'event_espresso'
3605
-                            ),
3606
-                            $a_callback
3607
-                        )
3608
-                    );
3609
-                }
3610
-            }
3611
-        }
3612
-
3613
-        if ($success === false) {
3614
-            EE_Error::add_error(
3615
-                esc_html__(
3616
-                    'Something went wrong with updating the meta table data for the registration.',
3617
-                    'event_espresso'
3618
-                ),
3619
-                __FILE__,
3620
-                __FUNCTION__,
3621
-                __LINE__
3622
-            );
3623
-        }
3624
-    }
3625
-
3626
-
3627
-    public function trash_cpt_item($post_id)
3628
-    {
3629
-    }
3630
-
3631
-
3632
-    public function delete_cpt_item($post_id)
3633
-    {
3634
-    }
3635
-
3636
-
3637
-    public function restore_cpt_item($post_id)
3638
-    {
3639
-    }
3640
-
3641
-
3642
-    protected function _restore_cpt_item($post_id, $revision_id)
3643
-    {
3644
-    }
3645
-
3646
-
3647
-    public function attendee_editor_metaboxes()
3648
-    {
3649
-        $this->verify_cpt_object();
3650
-        remove_meta_box(
3651
-            'postexcerpt',
3652
-            esc_html__('Excerpt', 'event_espresso'),
3653
-            'post_excerpt_meta_box',
3654
-            $this->_cpt_routes[ $this->_req_action ],
3655
-            'normal',
3656
-            'core'
3657
-        );
3658
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3659
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3660
-            add_meta_box(
3661
-                'postexcerpt',
3662
-                esc_html__('Short Biography', 'event_espresso'),
3663
-                'post_excerpt_meta_box',
3664
-                $this->_cpt_routes[ $this->_req_action ],
3665
-                'normal'
3666
-            );
3667
-        }
3668
-        if (post_type_supports('espresso_attendees', 'comments')) {
3669
-            add_meta_box(
3670
-                'commentsdiv',
3671
-                esc_html__('Notes on the Contact', 'event_espresso'),
3672
-                'post_comment_meta_box',
3673
-                $this->_cpt_routes[ $this->_req_action ],
3674
-                'normal',
3675
-                'core'
3676
-            );
3677
-        }
3678
-        add_meta_box(
3679
-            'attendee_contact_info',
3680
-            esc_html__('Contact Info', 'event_espresso'),
3681
-            array($this, 'attendee_contact_info'),
3682
-            $this->_cpt_routes[ $this->_req_action ],
3683
-            'side',
3684
-            'core'
3685
-        );
3686
-        add_meta_box(
3687
-            'attendee_details_address',
3688
-            esc_html__('Address Details', 'event_espresso'),
3689
-            array($this, 'attendee_address_details'),
3690
-            $this->_cpt_routes[ $this->_req_action ],
3691
-            'normal',
3692
-            'core'
3693
-        );
3694
-        add_meta_box(
3695
-            'attendee_registrations',
3696
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3697
-            array($this, 'attendee_registrations_meta_box'),
3698
-            $this->_cpt_routes[ $this->_req_action ],
3699
-            'normal',
3700
-            'high'
3701
-        );
3702
-    }
3703
-
3704
-
3705
-    /**
3706
-     * Metabox for attendee contact info
3707
-     *
3708
-     * @param  WP_Post $post wp post object
3709
-     * @return string attendee contact info ( and form )
3710
-     * @throws EE_Error
3711
-     * @throws InvalidArgumentException
3712
-     * @throws InvalidDataTypeException
3713
-     * @throws InvalidInterfaceException
3714
-     * @throws LogicException
3715
-     * @throws DomainException
3716
-     */
3717
-    public function attendee_contact_info($post)
3718
-    {
3719
-        // get attendee object ( should already have it )
3720
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3721
-        $form->enqueueStylesAndScripts();
3722
-        echo $form->display();
3723
-    }
3724
-
3725
-
3726
-    /**
3727
-     * Return form handler for the contact details metabox
3728
-     *
3729
-     * @param EE_Attendee $attendee
3730
-     * @return AttendeeContactDetailsMetaboxFormHandler
3731
-     * @throws DomainException
3732
-     * @throws InvalidArgumentException
3733
-     * @throws InvalidDataTypeException
3734
-     * @throws InvalidInterfaceException
3735
-     */
3736
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3737
-    {
3738
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3739
-    }
3740
-
3741
-
3742
-    /**
3743
-     * Metabox for attendee details
3744
-     *
3745
-     * @param  WP_Post $post wp post object
3746
-     * @throws DomainException
3747
-     */
3748
-    public function attendee_address_details($post)
3749
-    {
3750
-        // get attendee object (should already have it)
3751
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3752
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3753
-            new EE_Question_Form_Input(
3754
-                EE_Question::new_instance(
3755
-                    array(
3756
-                        'QST_ID'           => 0,
3757
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3758
-                        'QST_system'       => 'admin-state',
3759
-                    )
3760
-                ),
3761
-                EE_Answer::new_instance(
3762
-                    array(
3763
-                        'ANS_ID'    => 0,
3764
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3765
-                    )
3766
-                ),
3767
-                array(
3768
-                    'input_id'       => 'STA_ID',
3769
-                    'input_name'     => 'STA_ID',
3770
-                    'input_prefix'   => '',
3771
-                    'append_qstn_id' => false,
3772
-                )
3773
-            )
3774
-        );
3775
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3776
-            new EE_Question_Form_Input(
3777
-                EE_Question::new_instance(
3778
-                    array(
3779
-                        'QST_ID'           => 0,
3780
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3781
-                        'QST_system'       => 'admin-country',
3782
-                    )
3783
-                ),
3784
-                EE_Answer::new_instance(
3785
-                    array(
3786
-                        'ANS_ID'    => 0,
3787
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3788
-                    )
3789
-                ),
3790
-                array(
3791
-                    'input_id'       => 'CNT_ISO',
3792
-                    'input_name'     => 'CNT_ISO',
3793
-                    'input_prefix'   => '',
3794
-                    'append_qstn_id' => false,
3795
-                )
3796
-            )
3797
-        );
3798
-        $template =
3799
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3800
-        EEH_Template::display_template($template, $this->_template_args);
3801
-    }
3802
-
3803
-
3804
-    /**
3805
-     *        _attendee_details
3806
-     *
3807
-     * @access protected
3808
-     * @param $post
3809
-     * @return void
3810
-     * @throws DomainException
3811
-     * @throws EE_Error
3812
-     */
3813
-    public function attendee_registrations_meta_box($post)
3814
-    {
3815
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3816
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3817
-        $template =
3818
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3819
-        EEH_Template::display_template($template, $this->_template_args);
3820
-    }
3821
-
3822
-
3823
-    /**
3824
-     * add in the form fields for the attendee edit
3825
-     *
3826
-     * @param  WP_Post $post wp post object
3827
-     * @return string html for new form.
3828
-     * @throws DomainException
3829
-     */
3830
-    public function after_title_form_fields($post)
3831
-    {
3832
-        if ($post->post_type == 'espresso_attendees') {
3833
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3834
-            $template_args['attendee'] = $this->_cpt_model_obj;
3835
-            EEH_Template::display_template($template, $template_args);
3836
-        }
3837
-    }
3838
-
3839
-
3840
-    /**
3841
-     *        _trash_or_restore_attendee
3842
-     *
3843
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3844
-     * @return void
3845
-     * @throws EE_Error
3846
-     * @throws InvalidArgumentException
3847
-     * @throws InvalidDataTypeException
3848
-     * @throws InvalidInterfaceException
3849
-     * @access protected
3850
-     */
3851
-    protected function _trash_or_restore_attendees($trash = true)
3852
-    {
3853
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3854
-        $ATT_MDL = EEM_Attendee::instance();
3855
-        $success = 1;
3856
-        // Checkboxes
3857
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3858
-            // if array has more than one element than success message should be plural
3859
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3860
-            // cycle thru checkboxes
3861
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3862
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3863
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3864
-                if (! $updated) {
3865
-                    $success = 0;
3866
-                }
3867
-            }
3868
-        } else {
3869
-            // grab single id and delete
3870
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3871
-            // get attendee
3872
-            $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3873
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3874
-            $updated = $att->save();
3875
-            if (! $updated) {
3876
-                $success = 0;
3877
-            }
3878
-        }
3879
-        $what = $success > 1
3880
-            ? esc_html__('Contacts', 'event_espresso')
3881
-            : esc_html__('Contact', 'event_espresso');
3882
-        $action_desc = $trash
3883
-            ? esc_html__('moved to the trash', 'event_espresso')
3884
-            : esc_html__('restored', 'event_espresso');
3885
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3886
-    }
3036
+		}
3037
+		$template_args = array(
3038
+			'title'                    => '',
3039
+			'content'                  => '',
3040
+			'step_button_text'         => '',
3041
+			'show_notification_toggle' => false,
3042
+		);
3043
+		// to indicate we're processing a new registration
3044
+		$hidden_fields = array(
3045
+			'processing_registration' => array(
3046
+				'type'  => 'hidden',
3047
+				'value' => 0,
3048
+			),
3049
+			'event_id'                => array(
3050
+				'type'  => 'hidden',
3051
+				'value' => $this->_reg_event->ID(),
3052
+			),
3053
+		);
3054
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
3055
+		$cart = EE_Registry::instance()->SSN->cart();
3056
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3057
+		switch ($step) {
3058
+			case 'ticket':
3059
+				$hidden_fields['processing_registration']['value'] = 1;
3060
+				$template_args['title'] = esc_html__(
3061
+					'Step One: Select the Ticket for this registration',
3062
+					'event_espresso'
3063
+				);
3064
+				$template_args['content'] =
3065
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3066
+				$template_args['step_button_text'] = esc_html__(
3067
+					'Add Tickets and Continue to Registrant Details',
3068
+					'event_espresso'
3069
+				);
3070
+				$template_args['show_notification_toggle'] = false;
3071
+				break;
3072
+			case 'questions':
3073
+				$hidden_fields['processing_registration']['value'] = 2;
3074
+				$template_args['title'] = esc_html__(
3075
+					'Step Two: Add Registrant Details for this Registration',
3076
+					'event_espresso'
3077
+				);
3078
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3079
+				// properly by the first process_reg_step run.
3080
+				$template_args['content'] =
3081
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3082
+				$template_args['step_button_text'] = esc_html__(
3083
+					'Save Registration and Continue to Details',
3084
+					'event_espresso'
3085
+				);
3086
+				$template_args['show_notification_toggle'] = true;
3087
+				break;
3088
+		}
3089
+		// we come back to the process_registration_step route.
3090
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3091
+		return EEH_Template::display_template(
3092
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3093
+			$template_args,
3094
+			true
3095
+		);
3096
+	}
3097
+
3098
+
3099
+	/**
3100
+	 *        set_reg_event
3101
+	 *
3102
+	 * @access private
3103
+	 * @return bool
3104
+	 * @throws EE_Error
3105
+	 * @throws InvalidArgumentException
3106
+	 * @throws InvalidDataTypeException
3107
+	 * @throws InvalidInterfaceException
3108
+	 */
3109
+	private function _set_reg_event()
3110
+	{
3111
+		if (is_object($this->_reg_event)) {
3112
+			return true;
3113
+		}
3114
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3115
+		if (! $EVT_ID) {
3116
+			return false;
3117
+		}
3118
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3119
+		return true;
3120
+	}
3121
+
3122
+
3123
+	/**
3124
+	 * process_reg_step
3125
+	 *
3126
+	 * @access        public
3127
+	 * @return string
3128
+	 * @throws DomainException
3129
+	 * @throws EE_Error
3130
+	 * @throws InvalidArgumentException
3131
+	 * @throws InvalidDataTypeException
3132
+	 * @throws InvalidInterfaceException
3133
+	 * @throws ReflectionException
3134
+	 * @throws RuntimeException
3135
+	 */
3136
+	public function process_reg_step()
3137
+	{
3138
+		EE_System::do_not_cache();
3139
+		$this->_set_reg_event();
3140
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3141
+		EE_Registry::instance()->REQ->set('uts', time());
3142
+		// what step are we on?
3143
+		$cart = EE_Registry::instance()->SSN->cart();
3144
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3145
+		// if doing ajax then we need to verify the nonce
3146
+		if (defined('DOING_AJAX')) {
3147
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3148
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3149
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3150
+		}
3151
+		switch ($step) {
3152
+			case 'ticket':
3153
+				// process ticket selection
3154
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3155
+				if ($success) {
3156
+					EE_Error::add_success(
3157
+						esc_html__(
3158
+							'Tickets Selected. Now complete the registration.',
3159
+							'event_espresso'
3160
+						)
3161
+					);
3162
+				} else {
3163
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3164
+				}
3165
+				if (defined('DOING_AJAX')) {
3166
+					$this->new_registration(); // display next step
3167
+				} else {
3168
+					$query_args = array(
3169
+						'action'                  => 'new_registration',
3170
+						'processing_registration' => 1,
3171
+						'event_id'                => $this->_reg_event->ID(),
3172
+						'uts'                     => time(),
3173
+					);
3174
+					$this->_redirect_after_action(
3175
+						false,
3176
+						'',
3177
+						'',
3178
+						$query_args,
3179
+						true
3180
+					);
3181
+				}
3182
+				break;
3183
+			case 'questions':
3184
+				if (! isset(
3185
+					$this->_req_data['txn_reg_status_change'],
3186
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3187
+				)
3188
+				) {
3189
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3190
+				}
3191
+				// process registration
3192
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3193
+				if ($cart instanceof EE_Cart) {
3194
+					$grand_total = $cart->get_cart_grand_total();
3195
+					if ($grand_total instanceof EE_Line_Item) {
3196
+						$grand_total->save_this_and_descendants_to_txn();
3197
+					}
3198
+				}
3199
+				if (! $transaction instanceof EE_Transaction) {
3200
+					$query_args = array(
3201
+						'action'                  => 'new_registration',
3202
+						'processing_registration' => 2,
3203
+						'event_id'                => $this->_reg_event->ID(),
3204
+						'uts'                     => time(),
3205
+					);
3206
+					if (defined('DOING_AJAX')) {
3207
+						// display registration form again because there are errors (maybe validation?)
3208
+						$this->new_registration();
3209
+						return;
3210
+					} else {
3211
+						$this->_redirect_after_action(
3212
+							false,
3213
+							'',
3214
+							'',
3215
+							$query_args,
3216
+							true
3217
+						);
3218
+						return;
3219
+					}
3220
+				}
3221
+				// maybe update status, and make sure to save transaction if not done already
3222
+				if (! $transaction->update_status_based_on_total_paid()) {
3223
+					$transaction->save();
3224
+				}
3225
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3226
+				$this->_req_data = array();
3227
+				$query_args = array(
3228
+					'action'        => 'redirect_to_txn',
3229
+					'TXN_ID'        => $transaction->ID(),
3230
+					'EVT_ID'        => $this->_reg_event->ID(),
3231
+					'event_name'    => urlencode($this->_reg_event->name()),
3232
+					'redirect_from' => 'new_registration',
3233
+				);
3234
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3235
+				break;
3236
+		}
3237
+		// what are you looking here for?  Should be nothing to do at this point.
3238
+	}
3239
+
3240
+
3241
+	/**
3242
+	 * redirect_to_txn
3243
+	 *
3244
+	 * @access public
3245
+	 * @return void
3246
+	 * @throws EE_Error
3247
+	 * @throws InvalidArgumentException
3248
+	 * @throws InvalidDataTypeException
3249
+	 * @throws InvalidInterfaceException
3250
+	 */
3251
+	public function redirect_to_txn()
3252
+	{
3253
+		EE_System::do_not_cache();
3254
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3255
+		$query_args = array(
3256
+			'action' => 'view_transaction',
3257
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3258
+			'page'   => 'espresso_transactions',
3259
+		);
3260
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3261
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3262
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3263
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3264
+		}
3265
+		EE_Error::add_success(
3266
+			esc_html__(
3267
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3268
+				'event_espresso'
3269
+			)
3270
+		);
3271
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3272
+	}
3273
+
3274
+
3275
+	/**
3276
+	 *        generates HTML for the Attendee Contact List
3277
+	 *
3278
+	 * @access protected
3279
+	 * @return void
3280
+	 */
3281
+	protected function _attendee_contact_list_table()
3282
+	{
3283
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3284
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3285
+		$this->display_admin_list_table_page_with_no_sidebar();
3286
+	}
3287
+
3288
+
3289
+	/**
3290
+	 *        get_attendees
3291
+	 *
3292
+	 * @param      $per_page
3293
+	 * @param bool $count whether to return count or data.
3294
+	 * @param bool $trash
3295
+	 * @return array
3296
+	 * @throws EE_Error
3297
+	 * @throws InvalidArgumentException
3298
+	 * @throws InvalidDataTypeException
3299
+	 * @throws InvalidInterfaceException
3300
+	 * @access public
3301
+	 */
3302
+	public function get_attendees($per_page, $count = false, $trash = false)
3303
+	{
3304
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3305
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3306
+		$ATT_MDL = EEM_Attendee::instance();
3307
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3308
+		switch ($this->_req_data['orderby']) {
3309
+			case 'ATT_ID':
3310
+				$orderby = 'ATT_ID';
3311
+				break;
3312
+			case 'ATT_fname':
3313
+				$orderby = 'ATT_fname';
3314
+				break;
3315
+			case 'ATT_email':
3316
+				$orderby = 'ATT_email';
3317
+				break;
3318
+			case 'ATT_city':
3319
+				$orderby = 'ATT_city';
3320
+				break;
3321
+			case 'STA_ID':
3322
+				$orderby = 'STA_ID';
3323
+				break;
3324
+			case 'CNT_ID':
3325
+				$orderby = 'CNT_ID';
3326
+				break;
3327
+			case 'Registration_Count':
3328
+				$orderby = 'Registration_Count';
3329
+				break;
3330
+			default:
3331
+				$orderby = 'ATT_lname';
3332
+		}
3333
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3334
+			? $this->_req_data['order']
3335
+			: 'ASC';
3336
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3337
+			? $this->_req_data['paged']
3338
+			: 1;
3339
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3340
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3341
+			? $this->_req_data['perpage']
3342
+			: $per_page;
3343
+		$_where = array();
3344
+		if (! empty($this->_req_data['s'])) {
3345
+			$sstr = '%' . $this->_req_data['s'] . '%';
3346
+			$_where['OR'] = array(
3347
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3348
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3349
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3350
+				'ATT_fname'                         => array('LIKE', $sstr),
3351
+				'ATT_lname'                         => array('LIKE', $sstr),
3352
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3353
+				'ATT_email'                         => array('LIKE', $sstr),
3354
+				'ATT_address'                       => array('LIKE', $sstr),
3355
+				'ATT_address2'                      => array('LIKE', $sstr),
3356
+				'ATT_city'                          => array('LIKE', $sstr),
3357
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3358
+				'State.STA_name'                    => array('LIKE', $sstr),
3359
+				'ATT_phone'                         => array('LIKE', $sstr),
3360
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3361
+				'Registration.REG_code'             => array('LIKE', $sstr),
3362
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3363
+			);
3364
+		}
3365
+		$offset = ($current_page - 1) * $per_page;
3366
+		$limit = $count ? null : array($offset, $per_page);
3367
+		$query_args = array(
3368
+			$_where,
3369
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3370
+			'limit'         => $limit,
3371
+		);
3372
+		if (! $count) {
3373
+			$query_args['order_by'] = array($orderby => $sort);
3374
+		}
3375
+		if ($trash) {
3376
+			$query_args[0]['status'] = array('!=', 'publish');
3377
+			$all_attendees = $count
3378
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3379
+				: $ATT_MDL->get_all($query_args);
3380
+		} else {
3381
+			$query_args[0]['status'] = array('IN', array('publish'));
3382
+			$all_attendees = $count
3383
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3384
+				: $ATT_MDL->get_all($query_args);
3385
+		}
3386
+		return $all_attendees;
3387
+	}
3388
+
3389
+
3390
+	/**
3391
+	 * This is just taking care of resending the registration confirmation
3392
+	 *
3393
+	 * @access protected
3394
+	 * @return void
3395
+	 */
3396
+	protected function _resend_registration()
3397
+	{
3398
+		$this->_process_resend_registration();
3399
+		$query_args = isset($this->_req_data['redirect_to'])
3400
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3401
+			: array('action' => 'default');
3402
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3403
+	}
3404
+
3405
+	/**
3406
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3407
+	 * to use when selecting registrations
3408
+	 *
3409
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3410
+	 *                                                     the query parameters from the request
3411
+	 * @return void ends the request with a redirect or download
3412
+	 */
3413
+	public function _registrations_report_base($method_name_for_getting_query_params)
3414
+	{
3415
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3416
+			wp_redirect(
3417
+				EE_Admin_Page::add_query_args_and_nonce(
3418
+					array(
3419
+						'page'        => 'espresso_batch',
3420
+						'batch'       => 'file',
3421
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3422
+						'filters'     => urlencode(
3423
+							serialize(
3424
+								call_user_func(
3425
+									array($this, $method_name_for_getting_query_params),
3426
+									EEH_Array::is_set(
3427
+										$this->_req_data,
3428
+										'filters',
3429
+										array()
3430
+									)
3431
+								)
3432
+							)
3433
+						),
3434
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3435
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3436
+						'return_url'  => urlencode($this->_req_data['return_url']),
3437
+					)
3438
+				)
3439
+			);
3440
+		} else {
3441
+			$new_request_args = array(
3442
+				'export' => 'report',
3443
+				'action' => 'registrations_report_for_event',
3444
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3445
+			);
3446
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3447
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3448
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3449
+				$EE_Export = EE_Export::instance($this->_req_data);
3450
+				$EE_Export->export();
3451
+			}
3452
+		}
3453
+	}
3454
+
3455
+
3456
+	/**
3457
+	 * Creates a registration report using only query parameters in the request
3458
+	 *
3459
+	 * @return void
3460
+	 */
3461
+	public function _registrations_report()
3462
+	{
3463
+		$this->_registrations_report_base('_get_registration_query_parameters');
3464
+	}
3465
+
3466
+
3467
+	public function _contact_list_export()
3468
+	{
3469
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3470
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3471
+			$EE_Export = EE_Export::instance($this->_req_data);
3472
+			$EE_Export->export_attendees();
3473
+		}
3474
+	}
3475
+
3476
+
3477
+	public function _contact_list_report()
3478
+	{
3479
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3480
+			wp_redirect(
3481
+				EE_Admin_Page::add_query_args_and_nonce(
3482
+					array(
3483
+						'page'        => 'espresso_batch',
3484
+						'batch'       => 'file',
3485
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3486
+						'return_url'  => urlencode($this->_req_data['return_url']),
3487
+					)
3488
+				)
3489
+			);
3490
+		} else {
3491
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3492
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3493
+				$EE_Export = EE_Export::instance($this->_req_data);
3494
+				$EE_Export->report_attendees();
3495
+			}
3496
+		}
3497
+	}
3498
+
3499
+
3500
+
3501
+
3502
+
3503
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3504
+	/**
3505
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3506
+	 *
3507
+	 * @return void
3508
+	 * @throws EE_Error
3509
+	 * @throws InvalidArgumentException
3510
+	 * @throws InvalidDataTypeException
3511
+	 * @throws InvalidInterfaceException
3512
+	 */
3513
+	protected function _duplicate_attendee()
3514
+	{
3515
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3516
+		// verify we have necessary info
3517
+		if (empty($this->_req_data['_REG_ID'])) {
3518
+			EE_Error::add_error(
3519
+				esc_html__(
3520
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3521
+					'event_espresso'
3522
+				),
3523
+				__FILE__,
3524
+				__LINE__,
3525
+				__FUNCTION__
3526
+			);
3527
+			$query_args = array('action' => $action);
3528
+			$this->_redirect_after_action('', '', '', $query_args, true);
3529
+		}
3530
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3531
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3532
+		$attendee = $registration->attendee();
3533
+		// remove relation of existing attendee on registration
3534
+		$registration->_remove_relation_to($attendee, 'Attendee');
3535
+		// new attendee
3536
+		$new_attendee = clone $attendee;
3537
+		$new_attendee->set('ATT_ID', 0);
3538
+		$new_attendee->save();
3539
+		// add new attendee to reg
3540
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3541
+		EE_Error::add_success(
3542
+			esc_html__(
3543
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3544
+				'event_espresso'
3545
+			)
3546
+		);
3547
+		// redirect to edit page for attendee
3548
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3549
+		$this->_redirect_after_action('', '', '', $query_args, true);
3550
+	}
3551
+
3552
+
3553
+	/**
3554
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3555
+	 *
3556
+	 * @param int     $post_id
3557
+	 * @param WP_POST $post
3558
+	 * @throws DomainException
3559
+	 * @throws EE_Error
3560
+	 * @throws InvalidArgumentException
3561
+	 * @throws InvalidDataTypeException
3562
+	 * @throws InvalidInterfaceException
3563
+	 * @throws LogicException
3564
+	 * @throws InvalidFormSubmissionException
3565
+	 */
3566
+	protected function _insert_update_cpt_item($post_id, $post)
3567
+	{
3568
+		$success = true;
3569
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3570
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3571
+			: null;
3572
+		// for attendee updates
3573
+		if ($attendee instanceof EE_Attendee) {
3574
+			// note we should only be UPDATING attendees at this point.
3575
+			$updated_fields = array(
3576
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3577
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3578
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3579
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3580
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3581
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3582
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3583
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3584
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3585
+			);
3586
+			foreach ($updated_fields as $field => $value) {
3587
+				$attendee->set($field, $value);
3588
+			}
3589
+
3590
+			// process contact details metabox form handler (which will also save the attendee)
3591
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3592
+			$success = $contact_details_form->process($this->_req_data);
3593
+
3594
+			$attendee_update_callbacks = apply_filters(
3595
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3596
+				array()
3597
+			);
3598
+			foreach ($attendee_update_callbacks as $a_callback) {
3599
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3600
+					throw new EE_Error(
3601
+						sprintf(
3602
+							esc_html__(
3603
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3604
+								'event_espresso'
3605
+							),
3606
+							$a_callback
3607
+						)
3608
+					);
3609
+				}
3610
+			}
3611
+		}
3612
+
3613
+		if ($success === false) {
3614
+			EE_Error::add_error(
3615
+				esc_html__(
3616
+					'Something went wrong with updating the meta table data for the registration.',
3617
+					'event_espresso'
3618
+				),
3619
+				__FILE__,
3620
+				__FUNCTION__,
3621
+				__LINE__
3622
+			);
3623
+		}
3624
+	}
3625
+
3626
+
3627
+	public function trash_cpt_item($post_id)
3628
+	{
3629
+	}
3630
+
3631
+
3632
+	public function delete_cpt_item($post_id)
3633
+	{
3634
+	}
3635
+
3636
+
3637
+	public function restore_cpt_item($post_id)
3638
+	{
3639
+	}
3640
+
3641
+
3642
+	protected function _restore_cpt_item($post_id, $revision_id)
3643
+	{
3644
+	}
3645
+
3646
+
3647
+	public function attendee_editor_metaboxes()
3648
+	{
3649
+		$this->verify_cpt_object();
3650
+		remove_meta_box(
3651
+			'postexcerpt',
3652
+			esc_html__('Excerpt', 'event_espresso'),
3653
+			'post_excerpt_meta_box',
3654
+			$this->_cpt_routes[ $this->_req_action ],
3655
+			'normal',
3656
+			'core'
3657
+		);
3658
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3659
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3660
+			add_meta_box(
3661
+				'postexcerpt',
3662
+				esc_html__('Short Biography', 'event_espresso'),
3663
+				'post_excerpt_meta_box',
3664
+				$this->_cpt_routes[ $this->_req_action ],
3665
+				'normal'
3666
+			);
3667
+		}
3668
+		if (post_type_supports('espresso_attendees', 'comments')) {
3669
+			add_meta_box(
3670
+				'commentsdiv',
3671
+				esc_html__('Notes on the Contact', 'event_espresso'),
3672
+				'post_comment_meta_box',
3673
+				$this->_cpt_routes[ $this->_req_action ],
3674
+				'normal',
3675
+				'core'
3676
+			);
3677
+		}
3678
+		add_meta_box(
3679
+			'attendee_contact_info',
3680
+			esc_html__('Contact Info', 'event_espresso'),
3681
+			array($this, 'attendee_contact_info'),
3682
+			$this->_cpt_routes[ $this->_req_action ],
3683
+			'side',
3684
+			'core'
3685
+		);
3686
+		add_meta_box(
3687
+			'attendee_details_address',
3688
+			esc_html__('Address Details', 'event_espresso'),
3689
+			array($this, 'attendee_address_details'),
3690
+			$this->_cpt_routes[ $this->_req_action ],
3691
+			'normal',
3692
+			'core'
3693
+		);
3694
+		add_meta_box(
3695
+			'attendee_registrations',
3696
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3697
+			array($this, 'attendee_registrations_meta_box'),
3698
+			$this->_cpt_routes[ $this->_req_action ],
3699
+			'normal',
3700
+			'high'
3701
+		);
3702
+	}
3703
+
3704
+
3705
+	/**
3706
+	 * Metabox for attendee contact info
3707
+	 *
3708
+	 * @param  WP_Post $post wp post object
3709
+	 * @return string attendee contact info ( and form )
3710
+	 * @throws EE_Error
3711
+	 * @throws InvalidArgumentException
3712
+	 * @throws InvalidDataTypeException
3713
+	 * @throws InvalidInterfaceException
3714
+	 * @throws LogicException
3715
+	 * @throws DomainException
3716
+	 */
3717
+	public function attendee_contact_info($post)
3718
+	{
3719
+		// get attendee object ( should already have it )
3720
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3721
+		$form->enqueueStylesAndScripts();
3722
+		echo $form->display();
3723
+	}
3724
+
3725
+
3726
+	/**
3727
+	 * Return form handler for the contact details metabox
3728
+	 *
3729
+	 * @param EE_Attendee $attendee
3730
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3731
+	 * @throws DomainException
3732
+	 * @throws InvalidArgumentException
3733
+	 * @throws InvalidDataTypeException
3734
+	 * @throws InvalidInterfaceException
3735
+	 */
3736
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3737
+	{
3738
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3739
+	}
3740
+
3741
+
3742
+	/**
3743
+	 * Metabox for attendee details
3744
+	 *
3745
+	 * @param  WP_Post $post wp post object
3746
+	 * @throws DomainException
3747
+	 */
3748
+	public function attendee_address_details($post)
3749
+	{
3750
+		// get attendee object (should already have it)
3751
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3752
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3753
+			new EE_Question_Form_Input(
3754
+				EE_Question::new_instance(
3755
+					array(
3756
+						'QST_ID'           => 0,
3757
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3758
+						'QST_system'       => 'admin-state',
3759
+					)
3760
+				),
3761
+				EE_Answer::new_instance(
3762
+					array(
3763
+						'ANS_ID'    => 0,
3764
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3765
+					)
3766
+				),
3767
+				array(
3768
+					'input_id'       => 'STA_ID',
3769
+					'input_name'     => 'STA_ID',
3770
+					'input_prefix'   => '',
3771
+					'append_qstn_id' => false,
3772
+				)
3773
+			)
3774
+		);
3775
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3776
+			new EE_Question_Form_Input(
3777
+				EE_Question::new_instance(
3778
+					array(
3779
+						'QST_ID'           => 0,
3780
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3781
+						'QST_system'       => 'admin-country',
3782
+					)
3783
+				),
3784
+				EE_Answer::new_instance(
3785
+					array(
3786
+						'ANS_ID'    => 0,
3787
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3788
+					)
3789
+				),
3790
+				array(
3791
+					'input_id'       => 'CNT_ISO',
3792
+					'input_name'     => 'CNT_ISO',
3793
+					'input_prefix'   => '',
3794
+					'append_qstn_id' => false,
3795
+				)
3796
+			)
3797
+		);
3798
+		$template =
3799
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3800
+		EEH_Template::display_template($template, $this->_template_args);
3801
+	}
3802
+
3803
+
3804
+	/**
3805
+	 *        _attendee_details
3806
+	 *
3807
+	 * @access protected
3808
+	 * @param $post
3809
+	 * @return void
3810
+	 * @throws DomainException
3811
+	 * @throws EE_Error
3812
+	 */
3813
+	public function attendee_registrations_meta_box($post)
3814
+	{
3815
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3816
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3817
+		$template =
3818
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3819
+		EEH_Template::display_template($template, $this->_template_args);
3820
+	}
3821
+
3822
+
3823
+	/**
3824
+	 * add in the form fields for the attendee edit
3825
+	 *
3826
+	 * @param  WP_Post $post wp post object
3827
+	 * @return string html for new form.
3828
+	 * @throws DomainException
3829
+	 */
3830
+	public function after_title_form_fields($post)
3831
+	{
3832
+		if ($post->post_type == 'espresso_attendees') {
3833
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3834
+			$template_args['attendee'] = $this->_cpt_model_obj;
3835
+			EEH_Template::display_template($template, $template_args);
3836
+		}
3837
+	}
3838
+
3839
+
3840
+	/**
3841
+	 *        _trash_or_restore_attendee
3842
+	 *
3843
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3844
+	 * @return void
3845
+	 * @throws EE_Error
3846
+	 * @throws InvalidArgumentException
3847
+	 * @throws InvalidDataTypeException
3848
+	 * @throws InvalidInterfaceException
3849
+	 * @access protected
3850
+	 */
3851
+	protected function _trash_or_restore_attendees($trash = true)
3852
+	{
3853
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3854
+		$ATT_MDL = EEM_Attendee::instance();
3855
+		$success = 1;
3856
+		// Checkboxes
3857
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3858
+			// if array has more than one element than success message should be plural
3859
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3860
+			// cycle thru checkboxes
3861
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3862
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3863
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3864
+				if (! $updated) {
3865
+					$success = 0;
3866
+				}
3867
+			}
3868
+		} else {
3869
+			// grab single id and delete
3870
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3871
+			// get attendee
3872
+			$att = $ATT_MDL->get_one_by_ID($ATT_ID);
3873
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3874
+			$updated = $att->save();
3875
+			if (! $updated) {
3876
+				$success = 0;
3877
+			}
3878
+		}
3879
+		$what = $success > 1
3880
+			? esc_html__('Contacts', 'event_espresso')
3881
+			: esc_html__('Contact', 'event_espresso');
3882
+		$action_desc = $trash
3883
+			? esc_html__('moved to the trash', 'event_espresso')
3884
+			: esc_html__('restored', 'event_espresso');
3885
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3886
+	}
3887 3887
 }
Please login to merge, or discard this patch.
Spacing   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
         // when adding a new registration...
66 66
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67 67
             EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
68
+            if ( ! isset($this->_req_data['processing_registration'])
69 69
                 || absint($this->_req_data['processing_registration']) !== 1
70 70
             ) {
71 71
                 // and it's NOT the attendee information reg step
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
         // style
659 659
         wp_register_style(
660 660
             'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
661
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
662 662
             array('ee-admin-css'),
663 663
             EVENT_ESPRESSO_VERSION
664 664
         );
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
         // script
667 667
         wp_register_script(
668 668
             'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
669
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
670 670
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671 671
             EVENT_ESPRESSO_VERSION,
672 672
             true
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
         wp_dequeue_style('espresso_reg');
705 705
         wp_register_style(
706 706
             'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
707
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
708 708
             array('ee-admin-css'),
709 709
             EVENT_ESPRESSO_VERSION
710 710
         );
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
     {
717 717
         wp_register_script(
718 718
             'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
719
+            REG_ASSETS_URL.'spco_for_admin.js',
720 720
             array('underscore', 'jquery'),
721 721
             EVENT_ESPRESSO_VERSION,
722 722
             true
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post'   => $ATT_ID,
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
             return true;
1117 1117
         }
1118 1118
         $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1119
+        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120 1120
         if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121 1121
             return true;
1122 1122
         } else {
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
             'caps'                     => EEM_Registration::caps_read_admin,
1201 1201
             'default_where_conditions' => 'this_model_only',
1202 1202
         );
1203
-        if (! $count) {
1203
+        if ( ! $count) {
1204 1204
             $query_params = array_merge(
1205 1205
                 $query_params,
1206 1206
                 $this->_get_orderby_for_registrations_query(),
@@ -1221,7 +1221,7 @@  discard block
 block discarded – undo
1221 1221
     protected function addAttendeeIdToWhereConditions(array $request)
1222 1222
     {
1223 1223
         $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1224
+        if ( ! empty($request['ATT_ID'])) {
1225 1225
             $where['ATT_ID'] = absint($request['ATT_ID']);
1226 1226
         }
1227 1227
         return $where;
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
     protected function _add_event_id_to_where_conditions(array $request)
1238 1238
     {
1239 1239
         $where = array();
1240
-        if (! empty($request['event_id'])) {
1240
+        if ( ! empty($request['event_id'])) {
1241 1241
             $where['EVT_ID'] = absint($request['event_id']);
1242 1242
         }
1243 1243
         return $where;
@@ -1253,7 +1253,7 @@  discard block
 block discarded – undo
1253 1253
     protected function _add_category_id_to_where_conditions(array $request)
1254 1254
     {
1255 1255
         $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1256
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257 1257
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258 1258
         }
1259 1259
         return $where;
@@ -1269,10 +1269,10 @@  discard block
 block discarded – undo
1269 1269
     protected function _add_datetime_id_to_where_conditions(array $request)
1270 1270
     {
1271 1271
         $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1272
+        if ( ! empty($request['datetime_id'])) {
1273 1273
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274 1274
         }
1275
-        if (! empty($request['DTT_ID'])) {
1275
+        if ( ! empty($request['DTT_ID'])) {
1276 1276
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277 1277
         }
1278 1278
         return $where;
@@ -1298,7 +1298,7 @@  discard block
 block discarded – undo
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1301
+        if ( ! empty($registration_status)) {
1302 1302
             $where['STS_ID'] = $registration_status;
1303 1303
         } else {
1304 1304
             // make sure we exclude incomplete registrations, but only if not trashed.
@@ -1341,12 +1341,12 @@  discard block
 block discarded – undo
1341 1341
                 array(
1342 1342
                     EEM_Registration::instance()->convert_datetime_for_query(
1343 1343
                         'REG_date',
1344
-                        $now . ' 00:00:00',
1344
+                        $now.' 00:00:00',
1345 1345
                         'Y-m-d H:i:s'
1346 1346
                     ),
1347 1347
                     EEM_Registration::instance()->convert_datetime_for_query(
1348 1348
                         'REG_date',
1349
-                        $now . ' 23:59:59',
1349
+                        $now.' 23:59:59',
1350 1350
                         'Y-m-d H:i:s'
1351 1351
                     ),
1352 1352
                 ),
@@ -1359,12 +1359,12 @@  discard block
 block discarded – undo
1359 1359
                 array(
1360 1360
                     EEM_Registration::instance()->convert_datetime_for_query(
1361 1361
                         'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1362
+                        $current_year_and_month.'-01 00:00:00',
1363 1363
                         'Y-m-d H:i:s'
1364 1364
                     ),
1365 1365
                     EEM_Registration::instance()->convert_datetime_for_query(
1366 1366
                         'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1367
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1368 1368
                         'Y-m-d H:i:s'
1369 1369
                     ),
1370 1370
                 ),
@@ -1379,18 +1379,18 @@  discard block
 block discarded – undo
1379 1379
                 : '';
1380 1380
             // if there is not a month or year then we can't go further
1381 1381
             if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1382
+                $days_in_month = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1383 1383
                 $where['REG_date'] = array(
1384 1384
                     'BETWEEN',
1385 1385
                     array(
1386 1386
                         EEM_Registration::instance()->convert_datetime_for_query(
1387 1387
                             'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1388
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1389 1389
                             'Y-m-d H:i:s'
1390 1390
                         ),
1391 1391
                         EEM_Registration::instance()->convert_datetime_for_query(
1392 1392
                             'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1393
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1394 1394
                             'Y-m-d H:i:s'
1395 1395
                         ),
1396 1396
                     ),
@@ -1410,8 +1410,8 @@  discard block
 block discarded – undo
1410 1410
     protected function _add_search_to_where_conditions(array $request)
1411 1411
     {
1412 1412
         $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1413
+        if ( ! empty($request['s'])) {
1414
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1415 1415
             $where['OR*search_conditions'] = array(
1416 1416
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1417 1417
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1647,7 +1647,7 @@  discard block
 block discarded – undo
1647 1647
                 )
1648 1648
                 : '';
1649 1649
             // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1650
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1651 1651
             $this->_template_args['REG_ID'] = $this->_registration->ID();
1652 1652
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653 1653
                 $template_path,
@@ -1785,7 +1785,7 @@  discard block
 block discarded – undo
1785 1785
                                 EEH_HTML::strong(
1786 1786
                                     $this->_registration->pretty_status(),
1787 1787
                                     '',
1788
-                                    'status-' . $this->_registration->status_ID(),
1788
+                                    'status-'.$this->_registration->status_ID(),
1789 1789
                                     'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1790 1790
                                 )
1791 1791
                             )
@@ -1841,14 +1841,14 @@  discard block
 block discarded – undo
1841 1841
     protected function _get_reg_statuses()
1842 1842
     {
1843 1843
         $reg_status_array = EEM_Registration::instance()->reg_status_array();
1844
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1844
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1845 1845
         // get current reg status
1846 1846
         $current_status = $this->_registration->status_ID();
1847 1847
         // is registration for free event? This will determine whether to display the pending payment option
1848 1848
         if ($current_status !== EEM_Registration::status_id_pending_payment
1849 1849
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1850 1850
         ) {
1851
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1851
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1852 1852
         }
1853 1853
         return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1854 1854
     }
@@ -1940,7 +1940,7 @@  discard block
 block discarded – undo
1940 1940
         $success = false;
1941 1941
         // typecast $REG_IDs
1942 1942
         $REG_IDs = (array) $REG_IDs;
1943
-        if (! empty($REG_IDs)) {
1943
+        if ( ! empty($REG_IDs)) {
1944 1944
             $success = true;
1945 1945
             // set default status if none is passed
1946 1946
             $status = $status ? $status : EEM_Registration::status_id_pending_payment;
@@ -2088,7 +2088,7 @@  discard block
 block discarded – undo
2088 2088
             $action,
2089 2089
             $notify
2090 2090
         );
2091
-        $method = $action . '_registration';
2091
+        $method = $action.'_registration';
2092 2092
         if (method_exists($this, $method)) {
2093 2093
             $this->$method($notify);
2094 2094
         }
@@ -2319,7 +2319,7 @@  discard block
 block discarded – undo
2319 2319
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2320 2320
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2321 2321
         $template_path =
2322
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2322
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2323 2323
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2324 2324
     }
2325 2325
 
@@ -2352,7 +2352,7 @@  discard block
 block discarded – undo
2352 2352
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2353 2353
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2354 2354
             $template_path =
2355
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2355
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2356 2356
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2357 2357
         }
2358 2358
     }
@@ -2369,7 +2369,7 @@  discard block
 block discarded – undo
2369 2369
     public function form_before_question_group($output)
2370 2370
     {
2371 2371
         EE_Error::doing_it_wrong(
2372
-            __CLASS__ . '::' . __FUNCTION__,
2372
+            __CLASS__.'::'.__FUNCTION__,
2373 2373
             esc_html__(
2374 2374
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2375 2375
                 'event_espresso'
@@ -2394,7 +2394,7 @@  discard block
 block discarded – undo
2394 2394
     public function form_after_question_group($output)
2395 2395
     {
2396 2396
         EE_Error::doing_it_wrong(
2397
-            __CLASS__ . '::' . __FUNCTION__,
2397
+            __CLASS__.'::'.__FUNCTION__,
2398 2398
             esc_html__(
2399 2399
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2400 2400
                 'event_espresso'
@@ -2432,7 +2432,7 @@  discard block
 block discarded – undo
2432 2432
     public function form_form_field_label_wrap($label)
2433 2433
     {
2434 2434
         EE_Error::doing_it_wrong(
2435
-            __CLASS__ . '::' . __FUNCTION__,
2435
+            __CLASS__.'::'.__FUNCTION__,
2436 2436
             esc_html__(
2437 2437
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2438 2438
                 'event_espresso'
@@ -2442,7 +2442,7 @@  discard block
 block discarded – undo
2442 2442
         return '
2443 2443
 			<tr>
2444 2444
 				<th>
2445
-					' . $label . '
2445
+					' . $label.'
2446 2446
 				</th>';
2447 2447
     }
2448 2448
 
@@ -2458,7 +2458,7 @@  discard block
 block discarded – undo
2458 2458
     public function form_form_field_input__wrap($input)
2459 2459
     {
2460 2460
         EE_Error::doing_it_wrong(
2461
-            __CLASS__ . '::' . __FUNCTION__,
2461
+            __CLASS__.'::'.__FUNCTION__,
2462 2462
             esc_html__(
2463 2463
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2464 2464
                 'event_espresso'
@@ -2467,7 +2467,7 @@  discard block
 block discarded – undo
2467 2467
         );
2468 2468
         return '
2469 2469
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2470
-					' . $input . '
2470
+					' . $input.'
2471 2471
 				</td>
2472 2472
 			</tr>';
2473 2473
     }
@@ -2511,8 +2511,8 @@  discard block
 block discarded – undo
2511 2511
      */
2512 2512
     protected function _get_reg_custom_questions_form($REG_ID)
2513 2513
     {
2514
-        if (! $this->_reg_custom_questions_form) {
2515
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2514
+        if ( ! $this->_reg_custom_questions_form) {
2515
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2516 2516
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2517 2517
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2518 2518
             );
@@ -2535,7 +2535,7 @@  discard block
 block discarded – undo
2535 2535
      */
2536 2536
     private function _save_reg_custom_questions_form($REG_ID = false)
2537 2537
     {
2538
-        if (! $REG_ID) {
2538
+        if ( ! $REG_ID) {
2539 2539
             EE_Error::add_error(
2540 2540
                 esc_html__(
2541 2541
                     'An error occurred. No registration ID was received.',
@@ -2627,30 +2627,30 @@  discard block
 block discarded – undo
2627 2627
                     ? $registration->attendee()
2628 2628
                     : EEM_Attendee::instance()
2629 2629
                                   ->create_default_object();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2633
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2634
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2635
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2630
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID'] = $registration->status_ID();
2631
+                $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
2632
+                $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
2633
+                $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
2634
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2635
+                $this->_template_args['attendees'][$att_nmbr]['address'] = implode(
2636 2636
                     ', ',
2637 2637
                     $attendee->full_address_as_array()
2638 2638
                 );
2639
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2639
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2640 2640
                     array(
2641 2641
                         'action' => 'edit_attendee',
2642 2642
                         'post'   => $attendee->ID(),
2643 2643
                     ),
2644 2644
                     REG_ADMIN_URL
2645 2645
                 );
2646
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2646
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj() instanceof EE_Event
2647 2647
                     ? $registration->event_obj()->name()
2648 2648
                     : '';
2649 2649
                 $att_nmbr++;
2650 2650
             }
2651 2651
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2652 2652
         }
2653
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2653
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2654 2654
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2655 2655
     }
2656 2656
 
@@ -2674,11 +2674,11 @@  discard block
 block discarded – undo
2674 2674
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2675 2675
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2676 2676
         // primary registration object (that way we know if we need to show create button or not)
2677
-        if (! $this->_registration->is_primary_registrant()) {
2677
+        if ( ! $this->_registration->is_primary_registrant()) {
2678 2678
             $primary_registration = $this->_registration->get_primary_registration();
2679 2679
             $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2680 2680
                 : null;
2681
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2681
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2682 2682
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2683 2683
                 // custom attendee object so let's not worry about the primary reg.
2684 2684
                 $primary_registration = null;
@@ -2712,7 +2712,7 @@  discard block
 block discarded – undo
2712 2712
             ) : '';
2713 2713
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2714 2714
         $this->_template_args['att_check'] = $att_check;
2715
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2715
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2716 2716
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2717 2717
     }
2718 2718
 
@@ -2750,7 +2750,7 @@  discard block
 block discarded – undo
2750 2750
         $success = 0;
2751 2751
         $overwrite_msgs = false;
2752 2752
         // Checkboxes
2753
-        if (! is_array($this->_req_data['_REG_ID'])) {
2753
+        if ( ! is_array($this->_req_data['_REG_ID'])) {
2754 2754
             $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2755 2755
         }
2756 2756
         $reg_count = count($this->_req_data['_REG_ID']);
@@ -2759,7 +2759,7 @@  discard block
 block discarded – undo
2759 2759
             /** @var EE_Registration $REG */
2760 2760
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2761 2761
             $payments = $REG->registration_payments();
2762
-            if (! empty($payments)) {
2762
+            if ( ! empty($payments)) {
2763 2763
                 $name = $REG->attendee() instanceof EE_Attendee
2764 2764
                     ? $REG->attendee()->full_name()
2765 2765
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2820,17 +2820,17 @@  discard block
 block discarded – undo
2820 2820
         $REG_MDL = EEM_Registration::instance();
2821 2821
         $success = 1;
2822 2822
         // Checkboxes
2823
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2823
+        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2824 2824
             // if array has more than one element than success message should be plural
2825 2825
             $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2826 2826
             // cycle thru checkboxes
2827 2827
             while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2828 2828
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2829
-                if (! $REG instanceof EE_Registration) {
2829
+                if ( ! $REG instanceof EE_Registration) {
2830 2830
                     continue;
2831 2831
                 }
2832 2832
                 $deleted = $this->_delete_registration($REG);
2833
-                if (! $deleted) {
2833
+                if ( ! $deleted) {
2834 2834
                     $success = 0;
2835 2835
                 }
2836 2836
             }
@@ -2839,7 +2839,7 @@  discard block
 block discarded – undo
2839 2839
             $REG_ID = $this->_req_data['_REG_ID'];
2840 2840
             $REG = $REG_MDL->get_one_by_ID($REG_ID);
2841 2841
             $deleted = $this->_delete_registration($REG);
2842
-            if (! $deleted) {
2842
+            if ( ! $deleted) {
2843 2843
                 $success = 0;
2844 2844
             }
2845 2845
         }
@@ -2873,11 +2873,11 @@  discard block
 block discarded – undo
2873 2873
         $REGS = $TXN->get_many_related('Registration');
2874 2874
         $all_trashed = true;
2875 2875
         foreach ($REGS as $registration) {
2876
-            if (! $registration->get('REG_deleted')) {
2876
+            if ( ! $registration->get('REG_deleted')) {
2877 2877
                 $all_trashed = false;
2878 2878
             }
2879 2879
         }
2880
-        if (! $all_trashed) {
2880
+        if ( ! $all_trashed) {
2881 2881
             EE_Error::add_error(
2882 2882
                 esc_html__(
2883 2883
                     'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
@@ -2936,7 +2936,7 @@  discard block
 block discarded – undo
2936 2936
      */
2937 2937
     public function new_registration()
2938 2938
     {
2939
-        if (! $this->_set_reg_event()) {
2939
+        if ( ! $this->_set_reg_event()) {
2940 2940
             throw new EE_Error(
2941 2941
                 esc_html__(
2942 2942
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2946,8 +2946,8 @@  discard block
 block discarded – undo
2946 2946
         }
2947 2947
         EE_Registry::instance()->REQ->set_espresso_page(true);
2948 2948
         // gotta start with a clean slate if we're not coming here via ajax
2949
-        if (! defined('DOING_AJAX')
2950
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2949
+        if ( ! defined('DOING_AJAX')
2950
+            && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2951 2951
         ) {
2952 2952
             EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2953 2953
         }
@@ -2980,7 +2980,7 @@  discard block
 block discarded – undo
2980 2980
         }
2981 2981
         // grab header
2982 2982
         $template_path =
2983
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2983
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2984 2984
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2985 2985
             $template_path,
2986 2986
             $this->_template_args,
@@ -3021,7 +3021,7 @@  discard block
 block discarded – undo
3021 3021
                 '</b>'
3022 3022
             );
3023 3023
             return '
3024
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3024
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
3025 3025
 	<script >
3026 3026
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
3027 3027
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3089,7 +3089,7 @@  discard block
 block discarded – undo
3089 3089
         // we come back to the process_registration_step route.
3090 3090
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3091 3091
         return EEH_Template::display_template(
3092
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3092
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3093 3093
             $template_args,
3094 3094
             true
3095 3095
         );
@@ -3111,8 +3111,8 @@  discard block
 block discarded – undo
3111 3111
         if (is_object($this->_reg_event)) {
3112 3112
             return true;
3113 3113
         }
3114
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3115
-        if (! $EVT_ID) {
3114
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3115
+        if ( ! $EVT_ID) {
3116 3116
             return false;
3117 3117
         }
3118 3118
         $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
@@ -3144,8 +3144,8 @@  discard block
 block discarded – undo
3144 3144
         $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3145 3145
         // if doing ajax then we need to verify the nonce
3146 3146
         if (defined('DOING_AJAX')) {
3147
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3148
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3147
+            $nonce = isset($this->_req_data[$this->_req_nonce])
3148
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3149 3149
             $this->_verify_nonce($nonce, $this->_req_nonce);
3150 3150
         }
3151 3151
         switch ($step) {
@@ -3181,7 +3181,7 @@  discard block
 block discarded – undo
3181 3181
                 }
3182 3182
                 break;
3183 3183
             case 'questions':
3184
-                if (! isset(
3184
+                if ( ! isset(
3185 3185
                     $this->_req_data['txn_reg_status_change'],
3186 3186
                     $this->_req_data['txn_reg_status_change']['send_notifications']
3187 3187
                 )
@@ -3196,7 +3196,7 @@  discard block
 block discarded – undo
3196 3196
                         $grand_total->save_this_and_descendants_to_txn();
3197 3197
                     }
3198 3198
                 }
3199
-                if (! $transaction instanceof EE_Transaction) {
3199
+                if ( ! $transaction instanceof EE_Transaction) {
3200 3200
                     $query_args = array(
3201 3201
                         'action'                  => 'new_registration',
3202 3202
                         'processing_registration' => 2,
@@ -3219,7 +3219,7 @@  discard block
 block discarded – undo
3219 3219
                     }
3220 3220
                 }
3221 3221
                 // maybe update status, and make sure to save transaction if not done already
3222
-                if (! $transaction->update_status_based_on_total_paid()) {
3222
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3223 3223
                     $transaction->save();
3224 3224
                 }
3225 3225
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3302,7 +3302,7 @@  discard block
 block discarded – undo
3302 3302
     public function get_attendees($per_page, $count = false, $trash = false)
3303 3303
     {
3304 3304
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3305
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3305
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3306 3306
         $ATT_MDL = EEM_Attendee::instance();
3307 3307
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3308 3308
         switch ($this->_req_data['orderby']) {
@@ -3341,8 +3341,8 @@  discard block
 block discarded – undo
3341 3341
             ? $this->_req_data['perpage']
3342 3342
             : $per_page;
3343 3343
         $_where = array();
3344
-        if (! empty($this->_req_data['s'])) {
3345
-            $sstr = '%' . $this->_req_data['s'] . '%';
3344
+        if ( ! empty($this->_req_data['s'])) {
3345
+            $sstr = '%'.$this->_req_data['s'].'%';
3346 3346
             $_where['OR'] = array(
3347 3347
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3348 3348
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3369,7 +3369,7 @@  discard block
 block discarded – undo
3369 3369
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3370 3370
             'limit'         => $limit,
3371 3371
         );
3372
-        if (! $count) {
3372
+        if ( ! $count) {
3373 3373
             $query_args['order_by'] = array($orderby => $sort);
3374 3374
         }
3375 3375
         if ($trash) {
@@ -3412,7 +3412,7 @@  discard block
 block discarded – undo
3412 3412
      */
3413 3413
     public function _registrations_report_base($method_name_for_getting_query_params)
3414 3414
     {
3415
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3415
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3416 3416
             wp_redirect(
3417 3417
                 EE_Admin_Page::add_query_args_and_nonce(
3418 3418
                     array(
@@ -3444,8 +3444,8 @@  discard block
 block discarded – undo
3444 3444
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3445 3445
             );
3446 3446
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3447
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3448
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3447
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3448
+                require_once(EE_CLASSES.'EE_Export.class.php');
3449 3449
                 $EE_Export = EE_Export::instance($this->_req_data);
3450 3450
                 $EE_Export->export();
3451 3451
             }
@@ -3466,8 +3466,8 @@  discard block
 block discarded – undo
3466 3466
 
3467 3467
     public function _contact_list_export()
3468 3468
     {
3469
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3470
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3469
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3470
+            require_once(EE_CLASSES.'EE_Export.class.php');
3471 3471
             $EE_Export = EE_Export::instance($this->_req_data);
3472 3472
             $EE_Export->export_attendees();
3473 3473
         }
@@ -3476,7 +3476,7 @@  discard block
 block discarded – undo
3476 3476
 
3477 3477
     public function _contact_list_report()
3478 3478
     {
3479
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3479
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3480 3480
             wp_redirect(
3481 3481
                 EE_Admin_Page::add_query_args_and_nonce(
3482 3482
                     array(
@@ -3488,8 +3488,8 @@  discard block
 block discarded – undo
3488 3488
                 )
3489 3489
             );
3490 3490
         } else {
3491
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3492
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3491
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3492
+                require_once(EE_CLASSES.'EE_Export.class.php');
3493 3493
                 $EE_Export = EE_Export::instance($this->_req_data);
3494 3494
                 $EE_Export->report_attendees();
3495 3495
             }
@@ -3575,7 +3575,7 @@  discard block
 block discarded – undo
3575 3575
             $updated_fields = array(
3576 3576
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3577 3577
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3578
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3578
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3579 3579
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3580 3580
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3581 3581
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3651,17 +3651,17 @@  discard block
 block discarded – undo
3651 3651
             'postexcerpt',
3652 3652
             esc_html__('Excerpt', 'event_espresso'),
3653 3653
             'post_excerpt_meta_box',
3654
-            $this->_cpt_routes[ $this->_req_action ],
3654
+            $this->_cpt_routes[$this->_req_action],
3655 3655
             'normal',
3656 3656
             'core'
3657 3657
         );
3658
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3658
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3659 3659
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3660 3660
             add_meta_box(
3661 3661
                 'postexcerpt',
3662 3662
                 esc_html__('Short Biography', 'event_espresso'),
3663 3663
                 'post_excerpt_meta_box',
3664
-                $this->_cpt_routes[ $this->_req_action ],
3664
+                $this->_cpt_routes[$this->_req_action],
3665 3665
                 'normal'
3666 3666
             );
3667 3667
         }
@@ -3670,7 +3670,7 @@  discard block
 block discarded – undo
3670 3670
                 'commentsdiv',
3671 3671
                 esc_html__('Notes on the Contact', 'event_espresso'),
3672 3672
                 'post_comment_meta_box',
3673
-                $this->_cpt_routes[ $this->_req_action ],
3673
+                $this->_cpt_routes[$this->_req_action],
3674 3674
                 'normal',
3675 3675
                 'core'
3676 3676
             );
@@ -3679,7 +3679,7 @@  discard block
 block discarded – undo
3679 3679
             'attendee_contact_info',
3680 3680
             esc_html__('Contact Info', 'event_espresso'),
3681 3681
             array($this, 'attendee_contact_info'),
3682
-            $this->_cpt_routes[ $this->_req_action ],
3682
+            $this->_cpt_routes[$this->_req_action],
3683 3683
             'side',
3684 3684
             'core'
3685 3685
         );
@@ -3687,7 +3687,7 @@  discard block
 block discarded – undo
3687 3687
             'attendee_details_address',
3688 3688
             esc_html__('Address Details', 'event_espresso'),
3689 3689
             array($this, 'attendee_address_details'),
3690
-            $this->_cpt_routes[ $this->_req_action ],
3690
+            $this->_cpt_routes[$this->_req_action],
3691 3691
             'normal',
3692 3692
             'core'
3693 3693
         );
@@ -3695,7 +3695,7 @@  discard block
 block discarded – undo
3695 3695
             'attendee_registrations',
3696 3696
             esc_html__('Registrations for this Contact', 'event_espresso'),
3697 3697
             array($this, 'attendee_registrations_meta_box'),
3698
-            $this->_cpt_routes[ $this->_req_action ],
3698
+            $this->_cpt_routes[$this->_req_action],
3699 3699
             'normal',
3700 3700
             'high'
3701 3701
         );
@@ -3796,7 +3796,7 @@  discard block
 block discarded – undo
3796 3796
             )
3797 3797
         );
3798 3798
         $template =
3799
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3799
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3800 3800
         EEH_Template::display_template($template, $this->_template_args);
3801 3801
     }
3802 3802
 
@@ -3815,7 +3815,7 @@  discard block
 block discarded – undo
3815 3815
         $this->_template_args['attendee'] = $this->_cpt_model_obj;
3816 3816
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3817 3817
         $template =
3818
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3818
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3819 3819
         EEH_Template::display_template($template, $this->_template_args);
3820 3820
     }
3821 3821
 
@@ -3830,7 +3830,7 @@  discard block
 block discarded – undo
3830 3830
     public function after_title_form_fields($post)
3831 3831
     {
3832 3832
         if ($post->post_type == 'espresso_attendees') {
3833
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3833
+            $template = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3834 3834
             $template_args['attendee'] = $this->_cpt_model_obj;
3835 3835
             EEH_Template::display_template($template, $template_args);
3836 3836
         }
@@ -3854,14 +3854,14 @@  discard block
 block discarded – undo
3854 3854
         $ATT_MDL = EEM_Attendee::instance();
3855 3855
         $success = 1;
3856 3856
         // Checkboxes
3857
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3857
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3858 3858
             // if array has more than one element than success message should be plural
3859 3859
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3860 3860
             // cycle thru checkboxes
3861 3861
             while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3862 3862
                 $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3863 3863
                     : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3864
-                if (! $updated) {
3864
+                if ( ! $updated) {
3865 3865
                     $success = 0;
3866 3866
                 }
3867 3867
             }
@@ -3872,7 +3872,7 @@  discard block
 block discarded – undo
3872 3872
             $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3873 3873
             $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3874 3874
             $updated = $att->save();
3875
-            if (! $updated) {
3875
+            if ( ! $updated) {
3876 3876
                 $success = 0;
3877 3877
             }
3878 3878
         }
Please login to merge, or discard this patch.
core/db_classes/EE_Message.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -697,7 +697,7 @@
 block discarded – undo
697 697
     /**
698 698
      * Gets any error message.
699 699
      *
700
-     * @return mixed|null
700
+     * @return string
701 701
      */
702 702
     public function error_message()
703 703
     {
Please login to merge, or discard this patch.
Indentation   +867 added lines, -867 removed lines patch added patch discarded remove patch
@@ -10,875 +10,875 @@
 block discarded – undo
10 10
 class EE_Message extends EE_Base_Class implements EEI_Admin_Links
11 11
 {
12 12
 
13
-    /**
14
-     * @deprecated 4.9.0  Added for backward compat with add-on's
15
-     * @type null
16
-     */
17
-    public $template_pack;
18
-
19
-    /**
20
-     * @deprecated 4.9.0 Added for backward compat with add-on's
21
-     * @type null
22
-     */
23
-    public $template_variation;
24
-
25
-    /**
26
-     * @deprecated 4.9.0 Added for backward compat with add-on's
27
-     * @type string
28
-     */
29
-    public $content = '';
30
-
31
-
32
-    /**
33
-     * @type EE_messenger $_messenger
34
-     */
35
-    protected $_messenger = null;
36
-
37
-    /**
38
-     * @type EE_message_type $_message_type
39
-     */
40
-    protected $_message_type = null;
41
-
42
-
43
-    /**
44
-     * @param array  $props_n_values
45
-     * @param string $timezone
46
-     * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
47
-     *                             format.
48
-     * @return EE_Message
49
-     */
50
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
51
-    {
52
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
53
-        // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
-        if (! $has_object) {
55
-            EE_Registry::instance()->load_helper('URL');
56
-            $props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57
-        }
58
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
59
-    }
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values
64
-     * @param string $timezone
65
-     * @return EE_Message
66
-     */
67
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
-    {
69
-        return new self($props_n_values, true, $timezone);
70
-    }
71
-
72
-
73
-    /**
74
-     * Gets MSG_token
75
-     *
76
-     * @return int
77
-     */
78
-    public function MSG_token()
79
-    {
80
-        return $this->get('MSG_token');
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets MSG_token
86
-     *
87
-     * @param int $MSG_token
88
-     */
89
-    public function set_MSG_token($MSG_token)
90
-    {
91
-        $this->set('MSG_token', $MSG_token);
92
-    }
93
-
94
-
95
-    /**
96
-     * Gets GRP_ID
97
-     *
98
-     * @return int
99
-     */
100
-    public function GRP_ID()
101
-    {
102
-        return $this->get('GRP_ID');
103
-    }
104
-
105
-
106
-    /**
107
-     * Sets GRP_ID
108
-     *
109
-     * @param int $GRP_ID
110
-     */
111
-    public function set_GRP_ID($GRP_ID)
112
-    {
113
-        $this->set('GRP_ID', $GRP_ID);
114
-    }
115
-
116
-
117
-    /**
118
-     * Gets TXN_ID
119
-     *
120
-     * @return int
121
-     */
122
-    public function TXN_ID()
123
-    {
124
-        return $this->get('TXN_ID');
125
-    }
126
-
127
-
128
-    /**
129
-     * Sets TXN_ID
130
-     *
131
-     * @param int $TXN_ID
132
-     */
133
-    public function set_TXN_ID($TXN_ID)
134
-    {
135
-        $this->set('TXN_ID', $TXN_ID);
136
-    }
137
-
138
-
139
-    /**
140
-     * Gets messenger
141
-     *
142
-     * @return string
143
-     */
144
-    public function messenger()
145
-    {
146
-        return $this->get('MSG_messenger');
147
-    }
148
-
149
-
150
-    /**
151
-     * Sets messenger
152
-     *
153
-     * @param string $messenger
154
-     */
155
-    public function set_messenger($messenger)
156
-    {
157
-        $this->set('MSG_messenger', $messenger);
158
-    }
159
-
160
-
161
-    /**
162
-     * Returns corresponding messenger object for the set messenger on this message
163
-     *
164
-     * @return EE_messenger | null
165
-     */
166
-    public function messenger_object()
167
-    {
168
-        return $this->_messenger;
169
-    }
170
-
171
-
172
-    /**
173
-     * Sets messenger
174
-     *
175
-     * @param EE_messenger $messenger
176
-     */
177
-    public function set_messenger_object(EE_messenger $messenger)
178
-    {
179
-        $this->_messenger = $messenger;
180
-    }
181
-
182
-
183
-    /**
184
-     * validates messenger
185
-     *
186
-     * @param bool $throw_exceptions
187
-     * @return bool
188
-     * @throws \EE_Error
189
-     */
190
-    public function valid_messenger($throw_exceptions = false)
191
-    {
192
-        if ($this->_messenger instanceof EE_messenger) {
193
-            return true;
194
-        }
195
-        if ($throw_exceptions) {
196
-            throw new EE_Error(
197
-                sprintf(
198
-                    __(
199
-                        'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
200
-                        'event_espresso'
201
-                    ),
202
-                    $this->messenger()
203
-                )
204
-            );
205
-        }
206
-        return false;
207
-    }
208
-
209
-
210
-    /**
211
-     * This returns the set localized label for the messenger on this message.
212
-     * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
213
-     * with this message.
214
-     *
215
-     * @param   bool $plural whether to return the plural label or not.
216
-     * @return string
217
-     */
218
-    public function messenger_label($plural = false)
219
-    {
220
-        $label_type = $plural ? 'plural' : 'singular';
221
-        $messenger = $this->messenger_object();
222
-        return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets message_type
228
-     *
229
-     * @return string
230
-     */
231
-    public function message_type()
232
-    {
233
-        return $this->get('MSG_message_type');
234
-    }
235
-
236
-
237
-    /**
238
-     * Sets message_type
239
-     *
240
-     * @param string $message_type
241
-     */
242
-    public function set_message_type($message_type)
243
-    {
244
-        $this->set('MSG_message_type', $message_type);
245
-    }
246
-
247
-
248
-    /**
249
-     * Returns the message type object for the set message type on this message
250
-     *
251
-     * @return EE_message_type | null
252
-     */
253
-    public function message_type_object()
254
-    {
255
-        return $this->_message_type;
256
-    }
257
-
258
-
259
-    /**
260
-     * Sets message_type
261
-     *
262
-     * @param EE_message_type $message_type
263
-     * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
264
-     *                                        the message type or not.
265
-     */
266
-    public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
267
-    {
268
-        $this->_message_type = $message_type;
269
-        if ($set_priority) {
270
-            $this->set_priority($this->_message_type->get_priority());
271
-        }
272
-    }
273
-
274
-
275
-    /**
276
-     * validates message_type
277
-     *
278
-     * @param bool $throw_exceptions
279
-     * @return bool
280
-     * @throws \EE_Error
281
-     */
282
-    public function valid_message_type($throw_exceptions = false)
283
-    {
284
-        if ($this->_message_type instanceof EE_message_type) {
285
-            return true;
286
-        }
287
-        if ($throw_exceptions) {
288
-            throw new EE_Error(
289
-                sprintf(
290
-                    __(
291
-                        'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
292
-                        'event_espresso'
293
-                    ),
294
-                    $this->message_type()
295
-                )
296
-            );
297
-        }
298
-        return false;
299
-    }
300
-
301
-
302
-    /**
303
-     * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
304
-     *
305
-     * @param bool $throw_exceptions
306
-     * @return bool
307
-     * @throws \EE_Error
308
-     */
309
-    public function is_valid($throw_exceptions = false)
310
-    {
311
-        if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
312
-            return true;
313
-        }
314
-        return false;
315
-    }
316
-
317
-
318
-    /**
319
-     * This validates whether the internal messenger and message type objects are valid for sending.
320
-     * Three checks are done:
321
-     * 1. There is a valid messenger object.
322
-     * 2. There is a valid message type object.
323
-     * 3. The message type object is active for the messenger.
324
-     *
325
-     * @throws EE_Error  But only if $throw_exceptions is set to true.
326
-     * @param bool $throw_exceptions
327
-     * @return bool
328
-     */
329
-    public function is_valid_for_sending_or_generation($throw_exceptions = false)
330
-    {
331
-        $valid = false;
332
-        if ($this->is_valid($throw_exceptions)) {
333
-            /** @var EE_Message_Resource_Manager $message_resource_manager */
334
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
335
-            $valid = $message_resource_manager->is_message_type_active_for_messenger(
336
-                $this->messenger(),
337
-                $this->message_type()
338
-            );
339
-            if (! $valid && $throw_exceptions) {
340
-                throw new EE_Error(
341
-                    sprintf(
342
-                        __(
343
-                            'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
344
-                            'event_espresso'
345
-                        ),
346
-                        $this->message_type(),
347
-                        $this->messenger()
348
-                    )
349
-                );
350
-            }
351
-        }
352
-        return $valid;
353
-    }
354
-
355
-
356
-    /**
357
-     * This returns the set localized label for the message type on this message.
358
-     * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
359
-     * with this message.
360
-     *
361
-     * @param   bool $plural whether to return the plural label or not.
362
-     * @return string
363
-     */
364
-    public function message_type_label($plural = false)
365
-    {
366
-        $label_type = $plural ? 'plural' : 'singular';
367
-        $message_type = $this->message_type_object();
368
-        return $message_type instanceof EE_message_type
369
-            ? $message_type->label[ $label_type ]
370
-            : str_replace(
371
-                '_',
372
-                ' ',
373
-                $this->message_type()
374
-            );
375
-    }
376
-
377
-
378
-    /**
379
-     * Gets context
380
-     *
381
-     * @return string
382
-     */
383
-    public function context()
384
-    {
385
-        return $this->get('MSG_context');
386
-    }
387
-
388
-
389
-    /**
390
-     * This returns the corresponding localized label for the given context slug, if possible from installed message
391
-     * types. Otherwise, this will just return the set context slug on this object.
392
-     *
393
-     * @return string
394
-     */
395
-    public function context_label()
396
-    {
397
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
398
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399
-        $contexts = $message_resource_manager->get_all_contexts();
400
-        return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
401
-    }
402
-
403
-
404
-    /**
405
-     * Sets context
406
-     *
407
-     * @param string $context
408
-     */
409
-    public function set_context($context)
410
-    {
411
-        $this->set('MSG_context', $context);
412
-    }
413
-
414
-
415
-    /**
416
-     * Gets recipient_ID
417
-     *
418
-     * @return int
419
-     */
420
-    public function recipient_ID()
421
-    {
422
-        return $this->get('MSG_recipient_ID');
423
-    }
424
-
425
-
426
-    /**
427
-     * Sets recipient_ID
428
-     *
429
-     * @param string $recipient_ID
430
-     */
431
-    public function set_recipient_ID($recipient_ID)
432
-    {
433
-        $this->set('MSG_recipient_ID', $recipient_ID);
434
-    }
435
-
436
-
437
-    /**
438
-     * Gets recipient_type
439
-     *
440
-     * @return string
441
-     */
442
-    public function recipient_type()
443
-    {
444
-        return $this->get('MSG_recipient_type');
445
-    }
446
-
447
-
448
-    /**
449
-     * Return the related object matching the recipient type and ID.
450
-     *
451
-     * @return EE_Base_Class | null
452
-     */
453
-    public function recipient_object()
454
-    {
455
-        if (! $this->recipient_type() || ! $this->recipient_ID()) {
456
-            return null;
457
-        }
458
-
459
-        return $this->get_first_related($this->recipient_type());
460
-    }
461
-
462
-
463
-    /**
464
-     * Sets recipient_type
465
-     *
466
-     * @param string $recipient_type
467
-     */
468
-    public function set_recipient_type($recipient_type)
469
-    {
470
-        $this->set('MSG_recipient_type', $recipient_type);
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets content
476
-     *
477
-     * @return string
478
-     */
479
-    public function content()
480
-    {
481
-        return $this->get('MSG_content');
482
-    }
483
-
484
-
485
-    /**
486
-     * Sets content
487
-     *
488
-     * @param string $content
489
-     */
490
-    public function set_content($content)
491
-    {
492
-        $this->set('MSG_content', $content);
493
-    }
494
-
495
-
496
-    /**
497
-     * Gets subject
498
-     *
499
-     * @return string
500
-     */
501
-    public function subject()
502
-    {
503
-        return $this->get('MSG_subject');
504
-    }
505
-
506
-
507
-    /**
508
-     * Sets subject
509
-     *
510
-     * @param string $subject
511
-     */
512
-    public function set_subject($subject)
513
-    {
514
-        $this->set('MSG_subject', $subject);
515
-    }
516
-
517
-
518
-    /**
519
-     * Gets to
520
-     *
521
-     * @return string
522
-     */
523
-    public function to()
524
-    {
525
-        $to = $this->get('MSG_to');
526
-        return empty($to) ? __('No recipient', 'event_espresso') : $to;
527
-    }
528
-
529
-
530
-    /**
531
-     * Sets to
532
-     *
533
-     * @param string $to
534
-     */
535
-    public function set_to($to)
536
-    {
537
-        $this->set('MSG_to', $to);
538
-    }
539
-
540
-
541
-    /**
542
-     * Gets from
543
-     *
544
-     * @return string
545
-     */
546
-    public function from()
547
-    {
548
-        return $this->get('MSG_from');
549
-    }
550
-
551
-
552
-    /**
553
-     * Sets from
554
-     *
555
-     * @param string $from
556
-     */
557
-    public function set_from($from)
558
-    {
559
-        $this->set('MSG_from', $from);
560
-    }
561
-
562
-
563
-    /**
564
-     * Gets priority
565
-     *
566
-     * @return int
567
-     */
568
-    public function priority()
569
-    {
570
-        return $this->get('MSG_priority');
571
-    }
572
-
573
-
574
-    /**
575
-     * Sets priority
576
-     * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
577
-     * this method calls the send_now method to verify that.
578
-     *
579
-     * @param int $priority
580
-     */
581
-    public function set_priority($priority)
582
-    {
583
-        $priority = $this->send_now() ? EEM_Message::priority_high : $priority;
584
-        parent::set('MSG_priority', $priority);
585
-    }
586
-
587
-
588
-    /**
589
-     * Overrides parent::set method so we can capture any sets for priority.
590
-     *
591
-     * @see parent::set() for phpdocs
592
-     * @param string $field_name
593
-     * @param mixed  $field_value
594
-     * @param bool   $use_default
595
-     * @throws EE_Error
596
-     */
597
-    public function set($field_name, $field_value, $use_default = false)
598
-    {
599
-        if ($field_name === 'MSG_priority') {
600
-            $this->set_priority($field_value);
601
-        }
602
-        parent::set($field_name, $field_value, $use_default);
603
-    }
604
-
605
-
606
-    /**
607
-     * @return bool
608
-     * @throws \EE_Error
609
-     */
610
-    public function send_now()
611
-    {
612
-        $send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high
613
-            : $this->priority();
614
-        return $send_now === EEM_Message::priority_high ? true : false;
615
-    }
616
-
617
-
618
-    /**
619
-     * Gets STS_ID
620
-     *
621
-     * @return string
622
-     */
623
-    public function STS_ID()
624
-    {
625
-        return $this->get('STS_ID');
626
-    }
627
-
628
-
629
-    /**
630
-     * Sets STS_ID
631
-     *
632
-     * @param string $STS_ID
633
-     */
634
-    public function set_STS_ID($STS_ID)
635
-    {
636
-        $this->set('STS_ID', $STS_ID);
637
-    }
638
-
639
-
640
-    /**
641
-     * Gets created
642
-     *
643
-     * @return string
644
-     */
645
-    public function created()
646
-    {
647
-        return $this->get('MSG_created');
648
-    }
649
-
650
-
651
-    /**
652
-     * Sets created
653
-     *
654
-     * @param string $created
655
-     */
656
-    public function set_created($created)
657
-    {
658
-        $this->set('MSG_created', $created);
659
-    }
660
-
661
-
662
-    /**
663
-     * Gets modified
664
-     *
665
-     * @return string
666
-     */
667
-    public function modified()
668
-    {
669
-        return $this->get('MSG_modified');
670
-    }
671
-
672
-
673
-    /**
674
-     * Sets modified
675
-     *
676
-     * @param string $modified
677
-     */
678
-    public function set_modified($modified)
679
-    {
680
-        $this->set('MSG_modified', $modified);
681
-    }
682
-
683
-
684
-    /**
685
-     * Sets generation data for this message.
686
-     *
687
-     * @param mixed $data
688
-     */
689
-    public function set_generation_data($data)
690
-    {
691
-        $this->set_field_or_extra_meta('MSG_generation_data', $data);
692
-    }
693
-
694
-
695
-    /**
696
-     * Returns any set generation data for this message.
697
-     *
698
-     * @return mixed|null
699
-     */
700
-    public function get_generation_data()
701
-    {
702
-        return $this->get_field_or_extra_meta('MSG_generation_data');
703
-    }
704
-
705
-
706
-    /**
707
-     * Gets any error message.
708
-     *
709
-     * @return mixed|null
710
-     */
711
-    public function error_message()
712
-    {
713
-        return $this->get_field_or_extra_meta('MSG_error');
714
-    }
715
-
716
-
717
-    /**
718
-     * Sets an error message.
719
-     *
720
-     * @param $message
721
-     * @return bool|int
722
-     */
723
-    public function set_error_message($message)
724
-    {
725
-        return $this->set_field_or_extra_meta('MSG_error', $message);
726
-    }
727
-
728
-
729
-    /**
730
-     * This retrieves the associated template pack with this message.
731
-     *
732
-     * @return EE_Messages_Template_Pack | null
733
-     */
734
-    public function get_template_pack()
735
-    {
736
-        /**
737
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738
-         */
739
-        if (! empty($this->template_pack)) {
740
-            return $this->template_pack;
741
-        }
742
-        /** @type EE_Message_Template_Group $grp */
743
-        $grp = $this->get_first_related('Message_Template_Group');
744
-        // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
-        if (! $grp instanceof EE_Message_Template_Group) {
746
-            $grp = EEM_Message_Template_Group::instance()->get_one(
747
-                array(
748
-                    array(
749
-                        'MTP_messenger'    => $this->messenger(),
750
-                        'MTP_message_type' => $this->message_type(),
751
-                        'MTP_is_global'    => true,
752
-                    ),
753
-                )
754
-            );
755
-        }
756
-
757
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
758
-    }
759
-
760
-
761
-    /**
762
-     * Retrieves the variation used for generating this message.
763
-     *
764
-     * @return string
765
-     */
766
-    public function get_template_pack_variation()
767
-    {
768
-        /**
769
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770
-         */
771
-        if (! empty($this->template_variation)) {
772
-            return $this->template_variation;
773
-        }
774
-
775
-        /** @type EE_Message_Template_Group $grp */
776
-        $grp = $this->get_first_related('Message_Template_Group');
777
-
778
-        // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
-        if (! $grp instanceof EE_Message_Template_Group) {
780
-            $grp = EEM_Message_Template_Group::instance()->get_one(
781
-                array(
782
-                    array(
783
-                        'MTP_messenger'    => $this->messenger(),
784
-                        'MTP_message_type' => $this->message_type(),
785
-                        'MTP_is_global'    => true,
786
-                    ),
787
-                )
788
-            );
789
-        }
790
-
791
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
792
-    }
793
-
794
-    /**
795
-     * Return the link to the admin details for the object.
796
-     *
797
-     * @return string
798
-     */
799
-    public function get_admin_details_link()
800
-    {
801
-        EE_Registry::instance()->load_helper('URL');
802
-        EE_Registry::instance()->load_helper('MSG_Template');
803
-        switch ($this->STS_ID()) {
804
-            case EEM_Message::status_failed:
805
-            case EEM_Message::status_debug_only:
806
-                return EEH_MSG_Template::generate_error_display_trigger($this);
807
-                break;
808
-
809
-            case EEM_Message::status_sent:
810
-                return EEH_MSG_Template::generate_browser_trigger($this);
811
-                break;
812
-
813
-            default:
814
-                return '';
815
-        }
816
-    }
817
-
818
-    /**
819
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
820
-     *
821
-     * @return string
822
-     */
823
-    public function get_admin_edit_link()
824
-    {
825
-        return $this->get_admin_details_link();
826
-    }
827
-
828
-    /**
829
-     * Returns the link to a settings page for the object.
830
-     *
831
-     * @return string
832
-     */
833
-    public function get_admin_settings_link()
834
-    {
835
-        EE_Registry::instance()->load_helper('URL');
836
-        return EEH_URL::add_query_args_and_nonce(
837
-            array(
838
-                'page'   => 'espresso_messages',
839
-                'action' => 'settings',
840
-            ),
841
-            admin_url('admin.php')
842
-        );
843
-    }
844
-
845
-    /**
846
-     * Returns the link to the "overview" for the object (typically the "list table" view).
847
-     *
848
-     * @return string
849
-     */
850
-    public function get_admin_overview_link()
851
-    {
852
-        EE_Registry::instance()->load_helper('URL');
853
-        return EEH_URL::add_query_args_and_nonce(
854
-            array(
855
-                'page'   => 'espresso_messages',
856
-                'action' => 'default',
857
-            ),
858
-            admin_url('admin.php')
859
-        );
860
-    }
861
-
862
-
863
-    /**
864
-     * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
865
-     * it.
866
-     * Note this also SAVES the current message object to the db because it adds an error message to accompany the
867
-     * status.
868
-     *
869
-     */
870
-    public function set_messenger_is_executing()
871
-    {
872
-        $this->set_STS_ID(EEM_Message::status_messenger_executing);
873
-        $this->set_error_message(
874
-            esc_html__(
875
-                'A message with this status indicates that there was a problem that occurred while the message was being
13
+	/**
14
+	 * @deprecated 4.9.0  Added for backward compat with add-on's
15
+	 * @type null
16
+	 */
17
+	public $template_pack;
18
+
19
+	/**
20
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
21
+	 * @type null
22
+	 */
23
+	public $template_variation;
24
+
25
+	/**
26
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
27
+	 * @type string
28
+	 */
29
+	public $content = '';
30
+
31
+
32
+	/**
33
+	 * @type EE_messenger $_messenger
34
+	 */
35
+	protected $_messenger = null;
36
+
37
+	/**
38
+	 * @type EE_message_type $_message_type
39
+	 */
40
+	protected $_message_type = null;
41
+
42
+
43
+	/**
44
+	 * @param array  $props_n_values
45
+	 * @param string $timezone
46
+	 * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
47
+	 *                             format.
48
+	 * @return EE_Message
49
+	 */
50
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
51
+	{
52
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
53
+		// if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
+		if (! $has_object) {
55
+			EE_Registry::instance()->load_helper('URL');
56
+			$props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57
+		}
58
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values
64
+	 * @param string $timezone
65
+	 * @return EE_Message
66
+	 */
67
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
+	{
69
+		return new self($props_n_values, true, $timezone);
70
+	}
71
+
72
+
73
+	/**
74
+	 * Gets MSG_token
75
+	 *
76
+	 * @return int
77
+	 */
78
+	public function MSG_token()
79
+	{
80
+		return $this->get('MSG_token');
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets MSG_token
86
+	 *
87
+	 * @param int $MSG_token
88
+	 */
89
+	public function set_MSG_token($MSG_token)
90
+	{
91
+		$this->set('MSG_token', $MSG_token);
92
+	}
93
+
94
+
95
+	/**
96
+	 * Gets GRP_ID
97
+	 *
98
+	 * @return int
99
+	 */
100
+	public function GRP_ID()
101
+	{
102
+		return $this->get('GRP_ID');
103
+	}
104
+
105
+
106
+	/**
107
+	 * Sets GRP_ID
108
+	 *
109
+	 * @param int $GRP_ID
110
+	 */
111
+	public function set_GRP_ID($GRP_ID)
112
+	{
113
+		$this->set('GRP_ID', $GRP_ID);
114
+	}
115
+
116
+
117
+	/**
118
+	 * Gets TXN_ID
119
+	 *
120
+	 * @return int
121
+	 */
122
+	public function TXN_ID()
123
+	{
124
+		return $this->get('TXN_ID');
125
+	}
126
+
127
+
128
+	/**
129
+	 * Sets TXN_ID
130
+	 *
131
+	 * @param int $TXN_ID
132
+	 */
133
+	public function set_TXN_ID($TXN_ID)
134
+	{
135
+		$this->set('TXN_ID', $TXN_ID);
136
+	}
137
+
138
+
139
+	/**
140
+	 * Gets messenger
141
+	 *
142
+	 * @return string
143
+	 */
144
+	public function messenger()
145
+	{
146
+		return $this->get('MSG_messenger');
147
+	}
148
+
149
+
150
+	/**
151
+	 * Sets messenger
152
+	 *
153
+	 * @param string $messenger
154
+	 */
155
+	public function set_messenger($messenger)
156
+	{
157
+		$this->set('MSG_messenger', $messenger);
158
+	}
159
+
160
+
161
+	/**
162
+	 * Returns corresponding messenger object for the set messenger on this message
163
+	 *
164
+	 * @return EE_messenger | null
165
+	 */
166
+	public function messenger_object()
167
+	{
168
+		return $this->_messenger;
169
+	}
170
+
171
+
172
+	/**
173
+	 * Sets messenger
174
+	 *
175
+	 * @param EE_messenger $messenger
176
+	 */
177
+	public function set_messenger_object(EE_messenger $messenger)
178
+	{
179
+		$this->_messenger = $messenger;
180
+	}
181
+
182
+
183
+	/**
184
+	 * validates messenger
185
+	 *
186
+	 * @param bool $throw_exceptions
187
+	 * @return bool
188
+	 * @throws \EE_Error
189
+	 */
190
+	public function valid_messenger($throw_exceptions = false)
191
+	{
192
+		if ($this->_messenger instanceof EE_messenger) {
193
+			return true;
194
+		}
195
+		if ($throw_exceptions) {
196
+			throw new EE_Error(
197
+				sprintf(
198
+					__(
199
+						'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
200
+						'event_espresso'
201
+					),
202
+					$this->messenger()
203
+				)
204
+			);
205
+		}
206
+		return false;
207
+	}
208
+
209
+
210
+	/**
211
+	 * This returns the set localized label for the messenger on this message.
212
+	 * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
213
+	 * with this message.
214
+	 *
215
+	 * @param   bool $plural whether to return the plural label or not.
216
+	 * @return string
217
+	 */
218
+	public function messenger_label($plural = false)
219
+	{
220
+		$label_type = $plural ? 'plural' : 'singular';
221
+		$messenger = $this->messenger_object();
222
+		return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets message_type
228
+	 *
229
+	 * @return string
230
+	 */
231
+	public function message_type()
232
+	{
233
+		return $this->get('MSG_message_type');
234
+	}
235
+
236
+
237
+	/**
238
+	 * Sets message_type
239
+	 *
240
+	 * @param string $message_type
241
+	 */
242
+	public function set_message_type($message_type)
243
+	{
244
+		$this->set('MSG_message_type', $message_type);
245
+	}
246
+
247
+
248
+	/**
249
+	 * Returns the message type object for the set message type on this message
250
+	 *
251
+	 * @return EE_message_type | null
252
+	 */
253
+	public function message_type_object()
254
+	{
255
+		return $this->_message_type;
256
+	}
257
+
258
+
259
+	/**
260
+	 * Sets message_type
261
+	 *
262
+	 * @param EE_message_type $message_type
263
+	 * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
264
+	 *                                        the message type or not.
265
+	 */
266
+	public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
267
+	{
268
+		$this->_message_type = $message_type;
269
+		if ($set_priority) {
270
+			$this->set_priority($this->_message_type->get_priority());
271
+		}
272
+	}
273
+
274
+
275
+	/**
276
+	 * validates message_type
277
+	 *
278
+	 * @param bool $throw_exceptions
279
+	 * @return bool
280
+	 * @throws \EE_Error
281
+	 */
282
+	public function valid_message_type($throw_exceptions = false)
283
+	{
284
+		if ($this->_message_type instanceof EE_message_type) {
285
+			return true;
286
+		}
287
+		if ($throw_exceptions) {
288
+			throw new EE_Error(
289
+				sprintf(
290
+					__(
291
+						'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
292
+						'event_espresso'
293
+					),
294
+					$this->message_type()
295
+				)
296
+			);
297
+		}
298
+		return false;
299
+	}
300
+
301
+
302
+	/**
303
+	 * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
304
+	 *
305
+	 * @param bool $throw_exceptions
306
+	 * @return bool
307
+	 * @throws \EE_Error
308
+	 */
309
+	public function is_valid($throw_exceptions = false)
310
+	{
311
+		if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
312
+			return true;
313
+		}
314
+		return false;
315
+	}
316
+
317
+
318
+	/**
319
+	 * This validates whether the internal messenger and message type objects are valid for sending.
320
+	 * Three checks are done:
321
+	 * 1. There is a valid messenger object.
322
+	 * 2. There is a valid message type object.
323
+	 * 3. The message type object is active for the messenger.
324
+	 *
325
+	 * @throws EE_Error  But only if $throw_exceptions is set to true.
326
+	 * @param bool $throw_exceptions
327
+	 * @return bool
328
+	 */
329
+	public function is_valid_for_sending_or_generation($throw_exceptions = false)
330
+	{
331
+		$valid = false;
332
+		if ($this->is_valid($throw_exceptions)) {
333
+			/** @var EE_Message_Resource_Manager $message_resource_manager */
334
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
335
+			$valid = $message_resource_manager->is_message_type_active_for_messenger(
336
+				$this->messenger(),
337
+				$this->message_type()
338
+			);
339
+			if (! $valid && $throw_exceptions) {
340
+				throw new EE_Error(
341
+					sprintf(
342
+						__(
343
+							'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
344
+							'event_espresso'
345
+						),
346
+						$this->message_type(),
347
+						$this->messenger()
348
+					)
349
+				);
350
+			}
351
+		}
352
+		return $valid;
353
+	}
354
+
355
+
356
+	/**
357
+	 * This returns the set localized label for the message type on this message.
358
+	 * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
359
+	 * with this message.
360
+	 *
361
+	 * @param   bool $plural whether to return the plural label or not.
362
+	 * @return string
363
+	 */
364
+	public function message_type_label($plural = false)
365
+	{
366
+		$label_type = $plural ? 'plural' : 'singular';
367
+		$message_type = $this->message_type_object();
368
+		return $message_type instanceof EE_message_type
369
+			? $message_type->label[ $label_type ]
370
+			: str_replace(
371
+				'_',
372
+				' ',
373
+				$this->message_type()
374
+			);
375
+	}
376
+
377
+
378
+	/**
379
+	 * Gets context
380
+	 *
381
+	 * @return string
382
+	 */
383
+	public function context()
384
+	{
385
+		return $this->get('MSG_context');
386
+	}
387
+
388
+
389
+	/**
390
+	 * This returns the corresponding localized label for the given context slug, if possible from installed message
391
+	 * types. Otherwise, this will just return the set context slug on this object.
392
+	 *
393
+	 * @return string
394
+	 */
395
+	public function context_label()
396
+	{
397
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
398
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399
+		$contexts = $message_resource_manager->get_all_contexts();
400
+		return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
401
+	}
402
+
403
+
404
+	/**
405
+	 * Sets context
406
+	 *
407
+	 * @param string $context
408
+	 */
409
+	public function set_context($context)
410
+	{
411
+		$this->set('MSG_context', $context);
412
+	}
413
+
414
+
415
+	/**
416
+	 * Gets recipient_ID
417
+	 *
418
+	 * @return int
419
+	 */
420
+	public function recipient_ID()
421
+	{
422
+		return $this->get('MSG_recipient_ID');
423
+	}
424
+
425
+
426
+	/**
427
+	 * Sets recipient_ID
428
+	 *
429
+	 * @param string $recipient_ID
430
+	 */
431
+	public function set_recipient_ID($recipient_ID)
432
+	{
433
+		$this->set('MSG_recipient_ID', $recipient_ID);
434
+	}
435
+
436
+
437
+	/**
438
+	 * Gets recipient_type
439
+	 *
440
+	 * @return string
441
+	 */
442
+	public function recipient_type()
443
+	{
444
+		return $this->get('MSG_recipient_type');
445
+	}
446
+
447
+
448
+	/**
449
+	 * Return the related object matching the recipient type and ID.
450
+	 *
451
+	 * @return EE_Base_Class | null
452
+	 */
453
+	public function recipient_object()
454
+	{
455
+		if (! $this->recipient_type() || ! $this->recipient_ID()) {
456
+			return null;
457
+		}
458
+
459
+		return $this->get_first_related($this->recipient_type());
460
+	}
461
+
462
+
463
+	/**
464
+	 * Sets recipient_type
465
+	 *
466
+	 * @param string $recipient_type
467
+	 */
468
+	public function set_recipient_type($recipient_type)
469
+	{
470
+		$this->set('MSG_recipient_type', $recipient_type);
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets content
476
+	 *
477
+	 * @return string
478
+	 */
479
+	public function content()
480
+	{
481
+		return $this->get('MSG_content');
482
+	}
483
+
484
+
485
+	/**
486
+	 * Sets content
487
+	 *
488
+	 * @param string $content
489
+	 */
490
+	public function set_content($content)
491
+	{
492
+		$this->set('MSG_content', $content);
493
+	}
494
+
495
+
496
+	/**
497
+	 * Gets subject
498
+	 *
499
+	 * @return string
500
+	 */
501
+	public function subject()
502
+	{
503
+		return $this->get('MSG_subject');
504
+	}
505
+
506
+
507
+	/**
508
+	 * Sets subject
509
+	 *
510
+	 * @param string $subject
511
+	 */
512
+	public function set_subject($subject)
513
+	{
514
+		$this->set('MSG_subject', $subject);
515
+	}
516
+
517
+
518
+	/**
519
+	 * Gets to
520
+	 *
521
+	 * @return string
522
+	 */
523
+	public function to()
524
+	{
525
+		$to = $this->get('MSG_to');
526
+		return empty($to) ? __('No recipient', 'event_espresso') : $to;
527
+	}
528
+
529
+
530
+	/**
531
+	 * Sets to
532
+	 *
533
+	 * @param string $to
534
+	 */
535
+	public function set_to($to)
536
+	{
537
+		$this->set('MSG_to', $to);
538
+	}
539
+
540
+
541
+	/**
542
+	 * Gets from
543
+	 *
544
+	 * @return string
545
+	 */
546
+	public function from()
547
+	{
548
+		return $this->get('MSG_from');
549
+	}
550
+
551
+
552
+	/**
553
+	 * Sets from
554
+	 *
555
+	 * @param string $from
556
+	 */
557
+	public function set_from($from)
558
+	{
559
+		$this->set('MSG_from', $from);
560
+	}
561
+
562
+
563
+	/**
564
+	 * Gets priority
565
+	 *
566
+	 * @return int
567
+	 */
568
+	public function priority()
569
+	{
570
+		return $this->get('MSG_priority');
571
+	}
572
+
573
+
574
+	/**
575
+	 * Sets priority
576
+	 * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
577
+	 * this method calls the send_now method to verify that.
578
+	 *
579
+	 * @param int $priority
580
+	 */
581
+	public function set_priority($priority)
582
+	{
583
+		$priority = $this->send_now() ? EEM_Message::priority_high : $priority;
584
+		parent::set('MSG_priority', $priority);
585
+	}
586
+
587
+
588
+	/**
589
+	 * Overrides parent::set method so we can capture any sets for priority.
590
+	 *
591
+	 * @see parent::set() for phpdocs
592
+	 * @param string $field_name
593
+	 * @param mixed  $field_value
594
+	 * @param bool   $use_default
595
+	 * @throws EE_Error
596
+	 */
597
+	public function set($field_name, $field_value, $use_default = false)
598
+	{
599
+		if ($field_name === 'MSG_priority') {
600
+			$this->set_priority($field_value);
601
+		}
602
+		parent::set($field_name, $field_value, $use_default);
603
+	}
604
+
605
+
606
+	/**
607
+	 * @return bool
608
+	 * @throws \EE_Error
609
+	 */
610
+	public function send_now()
611
+	{
612
+		$send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high
613
+			: $this->priority();
614
+		return $send_now === EEM_Message::priority_high ? true : false;
615
+	}
616
+
617
+
618
+	/**
619
+	 * Gets STS_ID
620
+	 *
621
+	 * @return string
622
+	 */
623
+	public function STS_ID()
624
+	{
625
+		return $this->get('STS_ID');
626
+	}
627
+
628
+
629
+	/**
630
+	 * Sets STS_ID
631
+	 *
632
+	 * @param string $STS_ID
633
+	 */
634
+	public function set_STS_ID($STS_ID)
635
+	{
636
+		$this->set('STS_ID', $STS_ID);
637
+	}
638
+
639
+
640
+	/**
641
+	 * Gets created
642
+	 *
643
+	 * @return string
644
+	 */
645
+	public function created()
646
+	{
647
+		return $this->get('MSG_created');
648
+	}
649
+
650
+
651
+	/**
652
+	 * Sets created
653
+	 *
654
+	 * @param string $created
655
+	 */
656
+	public function set_created($created)
657
+	{
658
+		$this->set('MSG_created', $created);
659
+	}
660
+
661
+
662
+	/**
663
+	 * Gets modified
664
+	 *
665
+	 * @return string
666
+	 */
667
+	public function modified()
668
+	{
669
+		return $this->get('MSG_modified');
670
+	}
671
+
672
+
673
+	/**
674
+	 * Sets modified
675
+	 *
676
+	 * @param string $modified
677
+	 */
678
+	public function set_modified($modified)
679
+	{
680
+		$this->set('MSG_modified', $modified);
681
+	}
682
+
683
+
684
+	/**
685
+	 * Sets generation data for this message.
686
+	 *
687
+	 * @param mixed $data
688
+	 */
689
+	public function set_generation_data($data)
690
+	{
691
+		$this->set_field_or_extra_meta('MSG_generation_data', $data);
692
+	}
693
+
694
+
695
+	/**
696
+	 * Returns any set generation data for this message.
697
+	 *
698
+	 * @return mixed|null
699
+	 */
700
+	public function get_generation_data()
701
+	{
702
+		return $this->get_field_or_extra_meta('MSG_generation_data');
703
+	}
704
+
705
+
706
+	/**
707
+	 * Gets any error message.
708
+	 *
709
+	 * @return mixed|null
710
+	 */
711
+	public function error_message()
712
+	{
713
+		return $this->get_field_or_extra_meta('MSG_error');
714
+	}
715
+
716
+
717
+	/**
718
+	 * Sets an error message.
719
+	 *
720
+	 * @param $message
721
+	 * @return bool|int
722
+	 */
723
+	public function set_error_message($message)
724
+	{
725
+		return $this->set_field_or_extra_meta('MSG_error', $message);
726
+	}
727
+
728
+
729
+	/**
730
+	 * This retrieves the associated template pack with this message.
731
+	 *
732
+	 * @return EE_Messages_Template_Pack | null
733
+	 */
734
+	public function get_template_pack()
735
+	{
736
+		/**
737
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738
+		 */
739
+		if (! empty($this->template_pack)) {
740
+			return $this->template_pack;
741
+		}
742
+		/** @type EE_Message_Template_Group $grp */
743
+		$grp = $this->get_first_related('Message_Template_Group');
744
+		// if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
+		if (! $grp instanceof EE_Message_Template_Group) {
746
+			$grp = EEM_Message_Template_Group::instance()->get_one(
747
+				array(
748
+					array(
749
+						'MTP_messenger'    => $this->messenger(),
750
+						'MTP_message_type' => $this->message_type(),
751
+						'MTP_is_global'    => true,
752
+					),
753
+				)
754
+			);
755
+		}
756
+
757
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
758
+	}
759
+
760
+
761
+	/**
762
+	 * Retrieves the variation used for generating this message.
763
+	 *
764
+	 * @return string
765
+	 */
766
+	public function get_template_pack_variation()
767
+	{
768
+		/**
769
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770
+		 */
771
+		if (! empty($this->template_variation)) {
772
+			return $this->template_variation;
773
+		}
774
+
775
+		/** @type EE_Message_Template_Group $grp */
776
+		$grp = $this->get_first_related('Message_Template_Group');
777
+
778
+		// if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
+		if (! $grp instanceof EE_Message_Template_Group) {
780
+			$grp = EEM_Message_Template_Group::instance()->get_one(
781
+				array(
782
+					array(
783
+						'MTP_messenger'    => $this->messenger(),
784
+						'MTP_message_type' => $this->message_type(),
785
+						'MTP_is_global'    => true,
786
+					),
787
+				)
788
+			);
789
+		}
790
+
791
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
792
+	}
793
+
794
+	/**
795
+	 * Return the link to the admin details for the object.
796
+	 *
797
+	 * @return string
798
+	 */
799
+	public function get_admin_details_link()
800
+	{
801
+		EE_Registry::instance()->load_helper('URL');
802
+		EE_Registry::instance()->load_helper('MSG_Template');
803
+		switch ($this->STS_ID()) {
804
+			case EEM_Message::status_failed:
805
+			case EEM_Message::status_debug_only:
806
+				return EEH_MSG_Template::generate_error_display_trigger($this);
807
+				break;
808
+
809
+			case EEM_Message::status_sent:
810
+				return EEH_MSG_Template::generate_browser_trigger($this);
811
+				break;
812
+
813
+			default:
814
+				return '';
815
+		}
816
+	}
817
+
818
+	/**
819
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
820
+	 *
821
+	 * @return string
822
+	 */
823
+	public function get_admin_edit_link()
824
+	{
825
+		return $this->get_admin_details_link();
826
+	}
827
+
828
+	/**
829
+	 * Returns the link to a settings page for the object.
830
+	 *
831
+	 * @return string
832
+	 */
833
+	public function get_admin_settings_link()
834
+	{
835
+		EE_Registry::instance()->load_helper('URL');
836
+		return EEH_URL::add_query_args_and_nonce(
837
+			array(
838
+				'page'   => 'espresso_messages',
839
+				'action' => 'settings',
840
+			),
841
+			admin_url('admin.php')
842
+		);
843
+	}
844
+
845
+	/**
846
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
847
+	 *
848
+	 * @return string
849
+	 */
850
+	public function get_admin_overview_link()
851
+	{
852
+		EE_Registry::instance()->load_helper('URL');
853
+		return EEH_URL::add_query_args_and_nonce(
854
+			array(
855
+				'page'   => 'espresso_messages',
856
+				'action' => 'default',
857
+			),
858
+			admin_url('admin.php')
859
+		);
860
+	}
861
+
862
+
863
+	/**
864
+	 * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
865
+	 * it.
866
+	 * Note this also SAVES the current message object to the db because it adds an error message to accompany the
867
+	 * status.
868
+	 *
869
+	 */
870
+	public function set_messenger_is_executing()
871
+	{
872
+		$this->set_STS_ID(EEM_Message::status_messenger_executing);
873
+		$this->set_error_message(
874
+			esc_html__(
875
+				'A message with this status indicates that there was a problem that occurred while the message was being
876 876
                 processed by the messenger.  It is still possible that the message was sent successfully, but at some
877 877
                 point during the processing there was a failure.  This usually is indicative of a timeout issue with PHP 
878 878
                 or memory limits being reached.  If you see this repeatedly you may want to consider upgrading the memory 
879 879
                 available to PHP on your server.',
880
-                'event_espresso'
881
-            )
882
-        );
883
-    }
880
+				'event_espresso'
881
+			)
882
+		);
883
+	}
884 884
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
     {
52 52
         $has_object = parent::_check_for_object($props_n_values, __CLASS__);
53 53
         // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
-        if (! $has_object) {
54
+        if ( ! $has_object) {
55 55
             EE_Registry::instance()->load_helper('URL');
56 56
             $props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57 57
         }
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
     {
220 220
         $label_type = $plural ? 'plural' : 'singular';
221 221
         $messenger = $this->messenger_object();
222
-        return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
222
+        return $messenger instanceof EE_messenger ? $messenger->label[$label_type] : $this->messenger();
223 223
     }
224 224
 
225 225
 
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
                 $this->messenger(),
337 337
                 $this->message_type()
338 338
             );
339
-            if (! $valid && $throw_exceptions) {
339
+            if ( ! $valid && $throw_exceptions) {
340 340
                 throw new EE_Error(
341 341
                     sprintf(
342 342
                         __(
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
         $label_type = $plural ? 'plural' : 'singular';
367 367
         $message_type = $this->message_type_object();
368 368
         return $message_type instanceof EE_message_type
369
-            ? $message_type->label[ $label_type ]
369
+            ? $message_type->label[$label_type]
370 370
             : str_replace(
371 371
                 '_',
372 372
                 ' ',
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
         /** @type EE_Message_Resource_Manager $message_resource_manager */
398 398
         $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399 399
         $contexts = $message_resource_manager->get_all_contexts();
400
-        return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
400
+        return isset($contexts[$this->context()]) ? $contexts[$this->context()] : $this->context();
401 401
     }
402 402
 
403 403
 
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
      */
453 453
     public function recipient_object()
454 454
     {
455
-        if (! $this->recipient_type() || ! $this->recipient_ID()) {
455
+        if ( ! $this->recipient_type() || ! $this->recipient_ID()) {
456 456
             return null;
457 457
         }
458 458
 
@@ -736,13 +736,13 @@  discard block
 block discarded – undo
736 736
         /**
737 737
          * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738 738
          */
739
-        if (! empty($this->template_pack)) {
739
+        if ( ! empty($this->template_pack)) {
740 740
             return $this->template_pack;
741 741
         }
742 742
         /** @type EE_Message_Template_Group $grp */
743 743
         $grp = $this->get_first_related('Message_Template_Group');
744 744
         // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
-        if (! $grp instanceof EE_Message_Template_Group) {
745
+        if ( ! $grp instanceof EE_Message_Template_Group) {
746 746
             $grp = EEM_Message_Template_Group::instance()->get_one(
747 747
                 array(
748 748
                     array(
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
         /**
769 769
          * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770 770
          */
771
-        if (! empty($this->template_variation)) {
771
+        if ( ! empty($this->template_variation)) {
772 772
             return $this->template_variation;
773 773
         }
774 774
 
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
         $grp = $this->get_first_related('Message_Template_Group');
777 777
 
778 778
         // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
-        if (! $grp instanceof EE_Message_Template_Group) {
779
+        if ( ! $grp instanceof EE_Message_Template_Group) {
780 780
             $grp = EEM_Message_Template_Group::instance()->get_one(
781 781
                 array(
782 782
                     array(
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Queue.lib.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -603,7 +603,7 @@
 block discarded – undo
603 603
      * @param EE_Message      $message
604 604
      * @param EE_messenger    $messenger
605 605
      * @param EE_message_type $message_type
606
-     * @param                 $test_send
606
+     * @param                 boolean $test_send
607 607
      * @return bool   true means all went well, false means, not so much.
608 608
      */
609 609
     protected function _do_preview(
Please login to merge, or discard this patch.
Indentation   +690 added lines, -690 removed lines patch added patch discarded remove patch
@@ -14,694 +14,694 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * @type    string  reference for sending action
19
-     */
20
-    const action_sending = 'sending';
21
-
22
-    /**
23
-     * @type    string  reference for generation action
24
-     */
25
-    const action_generating = 'generation';
26
-
27
-
28
-    /**
29
-     * @type EE_Message_Repository $_message_repository
30
-     */
31
-    protected $_message_repository;
32
-
33
-    /**
34
-     * Sets the limit of how many messages are generated per process.
35
-     *
36
-     * @type int
37
-     */
38
-    protected $_batch_count;
39
-
40
-
41
-    /**
42
-     * This is an array of cached queue items being stored in this object.
43
-     * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
44
-     * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
45
-     *
46
-     * @type EE_Message[]
47
-     */
48
-    protected $_cached_queue_items;
49
-
50
-    /**
51
-     * Tracks the number of unsaved queue items.
52
-     *
53
-     * @type int
54
-     */
55
-    protected $_unsaved_count = 0;
56
-
57
-    /**
58
-     * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
59
-     * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
60
-     *
61
-     * @type array
62
-     */
63
-    protected $_did_hook = array();
64
-
65
-
66
-    /**
67
-     * Constructor.
68
-     * Setup all the initial properties and load a EE_Message_Repository.
69
-     *
70
-     * @param \EE_Message_Repository $message_repository
71
-     */
72
-    public function __construct(EE_Message_Repository $message_repository)
73
-    {
74
-        $this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
75
-        $this->_message_repository = $message_repository;
76
-    }
77
-
78
-
79
-    /**
80
-     * Add a EE_Message object to the queue
81
-     *
82
-     * @param EE_Message $message
83
-     * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
84
-     *                                 object is persisted, this data will be saved on an extra_meta object related to
85
-     *                                 EE_Message.
86
-     * @param  bool      $preview      Whether this EE_Message represents a preview or not.
87
-     * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
88
-     *                                 use the messenger send method but typically is based on preview data.
89
-     * @return bool          Whether the message was successfully added to the repository or not.
90
-     */
91
-    public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
92
-    {
93
-        $data['preview']   = $preview;
94
-        $data['test_send'] = $test_send;
95
-        return $this->_message_repository->add($message, $data);
96
-    }
97
-
98
-
99
-    /**
100
-     * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
101
-     *
102
-     * @param EE_Message $message The message to detach from the queue
103
-     * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
104
-     * @return bool
105
-     */
106
-    public function remove(EE_Message $message, $persist = false)
107
-    {
108
-        if ($persist && $this->_message_repository->current() !== $message) {
109
-            // get pointer on right message
110
-            if ($this->_message_repository->has($message)) {
111
-                $this->_message_repository->rewind();
112
-                while ($this->_message_repository->valid()) {
113
-                    if ($this->_message_repository->current() === $message) {
114
-                        break;
115
-                    }
116
-                    $this->_message_repository->next();
117
-                }
118
-            } else {
119
-                return false;
120
-            }
121
-        }
122
-        return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
123
-    }
124
-
125
-
126
-    /**
127
-     * Persists all queued EE_Message objects to the db.
128
-     *
129
-     * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
130
-     * @return array @see EE_Messages_Repository::saveAll() for return values.
131
-     */
132
-    public function save($do_hooks_only = false)
133
-    {
134
-        return $this->_message_repository->saveAll($do_hooks_only);
135
-    }
136
-
137
-
138
-    /**
139
-     * @return EE_Message_Repository
140
-     */
141
-    public function get_message_repository()
142
-    {
143
-        return $this->_message_repository;
144
-    }
145
-
146
-
147
-    /**
148
-     * This does the following things:
149
-     * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
150
-     * false).
151
-     * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
152
-     * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
153
-     * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
154
-     * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
155
-     * removed.
156
-     *
157
-     * @return bool  true if successfully retrieved batch, false no batch ready.
158
-     */
159
-    public function get_batch_to_generate()
160
-    {
161
-        if ($this->is_locked(EE_Messages_Queue::action_generating)) {
162
-            return false;
163
-        }
164
-
165
-        // lock batch generation to prevent race conditions.
166
-        $this->lock_queue(EE_Messages_Queue::action_generating);
167
-
168
-        $query_args = array(
169
-            // key 0 = where conditions
170
-            0          => array('STS_ID' => EEM_Message::status_incomplete),
171
-            'order_by' => $this->_get_priority_orderby(),
172
-            'limit'    => $this->_batch_count,
173
-        );
174
-        $messages   = EEM_Message::instance()->get_all($query_args);
175
-
176
-        if (! $messages) {
177
-            return false; // nothing to generate
178
-        }
179
-
180
-        foreach ($messages as $message) {
181
-            if ($message instanceof EE_Message) {
182
-                $data = $message->all_extra_meta_array();
183
-                $this->add($message, $data);
184
-            }
185
-        }
186
-        return true;
187
-    }
188
-
189
-
190
-    /**
191
-     * This does the following things:
192
-     * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
193
-     * false).
194
-     * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
195
-     * return false.
196
-     * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
197
-     * 3. On success or unsuccessful send, sets status appropriately.
198
-     * 4. Saves messages via the queue
199
-     * 5. Releases lock.
200
-     *
201
-     * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
202
-     *               necessarily mean that all messages were successfully sent.  It just means that this method
203
-     *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
204
-     *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
205
-     *               will also have a saved error message on it to assist with notifying user.
206
-     */
207
-    public function get_to_send_batch_and_send()
208
-    {
209
-        $rate_limit = $this->get_rate_limit();
210
-        if ($rate_limit < 1
211
-            || $this->is_locked(EE_Messages_Queue::action_sending)) {
212
-            return false;
213
-        }
214
-
215
-        $this->lock_queue(EE_Messages_Queue::action_sending);
216
-
217
-        $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
218
-
219
-        $query_args = array(
220
-            // key 0 = where conditions
221
-            0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
222
-            'order_by' => $this->_get_priority_orderby(),
223
-            'limit'    => $batch,
224
-        );
225
-
226
-        $messages_to_send = EEM_Message::instance()->get_all($query_args);
227
-
228
-
229
-        // any to send?
230
-        if (! $messages_to_send) {
231
-            $this->unlock_queue(EE_Messages_Queue::action_sending);
232
-            return false;
233
-        }
234
-
235
-        $queue_count = 0;
236
-
237
-        // add to queue.
238
-        foreach ($messages_to_send as $message) {
239
-            if ($message instanceof EE_Message) {
240
-                $queue_count++;
241
-                $this->add($message);
242
-            }
243
-        }
244
-
245
-        // send messages  (this also updates the rate limit)
246
-        $this->execute();
247
-
248
-        // release lock
249
-        $this->unlock_queue(EE_Messages_Queue::action_sending);
250
-        // update rate limit
251
-        $this->set_rate_limit($queue_count);
252
-        return true;
253
-    }
254
-
255
-
256
-    /**
257
-     * Locks the queue so that no other queues can call the "batch" methods.
258
-     *
259
-     * @param   string $type The type of queue being locked.
260
-     */
261
-    public function lock_queue($type = EE_Messages_Queue::action_generating)
262
-    {
263
-        update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
264
-    }
265
-
266
-
267
-    /**
268
-     * Unlocks the queue so that batch methods can be used.
269
-     *
270
-     * @param   string $type The type of queue being unlocked.
271
-     */
272
-    public function unlock_queue($type = EE_Messages_Queue::action_generating)
273
-    {
274
-        delete_option($this->_get_lock_key($type));
275
-    }
276
-
277
-
278
-    /**
279
-     * Retrieve the key used for the lock transient.
280
-     *
281
-     * @param string $type The type of lock.
282
-     * @return string
283
-     */
284
-    protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
285
-    {
286
-        return '_ee_lock_' . $type;
287
-    }
288
-
289
-
290
-    /**
291
-     * Retrieve the expiry time for the lock transient.
292
-     *
293
-     * @param string $type The type of lock
294
-     * @return int   time to expiry in seconds.
295
-     */
296
-    protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
297
-    {
298
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
299
-    }
300
-
301
-
302
-    /**
303
-     * Returns the key used for rate limit transient.
304
-     *
305
-     * @return string
306
-     */
307
-    protected function _get_rate_limit_key()
308
-    {
309
-        return '_ee_rate_limit';
310
-    }
311
-
312
-
313
-    /**
314
-     * Returns the rate limit expiry time.
315
-     *
316
-     * @return int
317
-     */
318
-    protected function _get_rate_limit_expiry()
319
-    {
320
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
321
-    }
322
-
323
-
324
-    /**
325
-     * Returns the default rate limit for sending messages.
326
-     *
327
-     * @return int
328
-     */
329
-    protected function _default_rate_limit()
330
-    {
331
-        return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
332
-    }
333
-
334
-
335
-    /**
336
-     * Return the orderby array for priority.
337
-     *
338
-     * @return array
339
-     */
340
-    protected function _get_priority_orderby()
341
-    {
342
-        return array(
343
-            'MSG_priority' => 'ASC',
344
-            'MSG_modified' => 'DESC',
345
-        );
346
-    }
347
-
348
-
349
-    /**
350
-     * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
351
-     * Return true when batch methods should not be used; returns false when they can be.
352
-     *
353
-     * @param  string $type The type of lock being checked for.
354
-     * @return bool
355
-     */
356
-    public function is_locked($type = EE_Messages_Queue::action_generating)
357
-    {
358
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
359
-            return true;
360
-        }
361
-        $lock = (int) get_option($this->_get_lock_key($type), 0);
362
-        /**
363
-         * This filters the default is_locked behaviour.
364
-         */
365
-        $is_locked = filter_var(
366
-            apply_filters(
367
-                'FHEE__EE_Messages_Queue__is_locked',
368
-                $lock > time(),
369
-                $this
370
-            ),
371
-            FILTER_VALIDATE_BOOLEAN
372
-        );
373
-
374
-        /**
375
-         * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
376
-         *            Also implemented here because messages processed on the same request should not have any locks applied.
377
-         */
378
-        if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
379
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
380
-        ) {
381
-            $is_locked = false;
382
-        }
383
-
384
-
385
-        return $is_locked;
386
-    }
387
-
388
-
389
-    /**
390
-     * Retrieves the rate limit that may be cached as a transient.
391
-     * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
392
-     *
393
-     * @param bool $return_expiry  If true then return the expiry time not the rate_limit.
394
-     * @return int
395
-     */
396
-    protected function get_rate_limit($return_expiry = false)
397
-    {
398
-        $stored_rate_info = get_option($this->_get_rate_limit_key(), array());
399
-        $rate_limit = isset($stored_rate_info[0])
400
-            ? (int) $stored_rate_info[0]
401
-            : 0;
402
-        $expiry = isset($stored_rate_info[1])
403
-            ? (int) $stored_rate_info[1]
404
-            : 0;
405
-        // set the default for tracking?
406
-        if (empty($stored_rate_info) || time() > $expiry) {
407
-            $expiry = $this->_get_rate_limit_expiry();
408
-            $rate_limit = $this->_default_rate_limit();
409
-            update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry));
410
-        }
411
-        return $return_expiry ? $expiry : $rate_limit;
412
-    }
413
-
414
-
415
-    /**
416
-     * This updates existing rate limit with the new limit which is the old minus the batch.
417
-     *
418
-     * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
419
-     */
420
-    protected function set_rate_limit($batch_completed)
421
-    {
422
-        // first get the most up to date rate limit (in case its expired and reset)
423
-        $rate_limit = $this->get_rate_limit();
424
-        $expiry = $this->get_rate_limit(true);
425
-        $new_limit  = $rate_limit - $batch_completed;
426
-        // updating the transient option directly to avoid resetting the expiry.
427
-
428
-        update_option($this->_get_rate_limit_key(), array($new_limit, $expiry));
429
-    }
430
-
431
-
432
-    /**
433
-     * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
434
-     * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
435
-     * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
436
-     * request running on a queue for the given task.
437
-     *
438
-     * @param string $task     This indicates what type of request is going to be initiated.
439
-     * @param int    $priority This indicates the priority that triggers initiating the request.
440
-     */
441
-    public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
442
-    {
443
-        // determine what status is matched with the priority as part of the trigger conditions.
444
-        $status = $task == 'generate'
445
-            ? EEM_Message::status_incomplete
446
-            : EEM_Message::instance()->stati_indicating_to_send();
447
-        // always make sure we save because either this will get executed immediately on a separate request
448
-        // or remains in the queue for the regularly scheduled queue batch.
449
-        $this->save();
450
-        /**
451
-         * This filter/option allows users to override processing of messages on separate requests and instead have everything
452
-         * happen on the same request.  If this is utilized remember:
453
-         * - message priorities don't matter
454
-         * - existing unprocessed messages in the queue will not get processed unless manually triggered.
455
-         * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
456
-         *   processing happening on the same request.
457
-         * - any race condition protection (locks) are removed because they don't apply when things are processed on
458
-         *   the same request.
459
-         */
460
-        if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
461
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
462
-        ) {
463
-            $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
464
-            if ($messages_processor instanceof EE_Messages_Processor) {
465
-                return $messages_processor->process_immediately_from_queue($this);
466
-            }
467
-            // if we get here then that means the messages processor couldn't be loaded so messages will just remain
468
-            // queued for manual triggering by end user.
469
-        }
470
-
471
-        if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
472
-            EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
473
-        }
474
-    }
475
-
476
-
477
-    /**
478
-     *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
479
-     *
480
-     * @param   bool     $save                    Used to indicate whether to save the message queue after sending
481
-     *                                            (default will save).
482
-     * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
483
-     *                                            what is on the EE_Message object in the queue.
484
-     *                                            For instance, showing the browser view of an email message,
485
-     *                                            or giving a pdf generated view of an html document.
486
-     *                                            This should be an instance of EE_messenger but if you call this
487
-     *                                            method
488
-     *                                            intending it to be a sending messenger but a valid one could not be
489
-     *                                            retrieved then send in an instance of EE_Error that contains the
490
-     *                                            related error message.
491
-     * @param   bool|int $by_priority             When set, this indicates that only messages
492
-     *                                            matching the given priority should be executed.
493
-     * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
494
-     *                                            Also, if the messenger is an request type messenger (or a preview),
495
-     *                                            its entirely possible that the messenger will exit before
496
-     */
497
-    public function execute($save = true, $sending_messenger = null, $by_priority = false)
498
-    {
499
-        $messages_sent   = 0;
500
-        $this->_did_hook = array();
501
-        $this->_message_repository->rewind();
502
-
503
-        while ($this->_message_repository->valid()) {
504
-            $error_messages = array();
505
-            /** @type EE_Message $message */
506
-            $message = $this->_message_repository->current();
507
-            // only process things that are queued for sending
508
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
509
-                $this->_message_repository->next();
510
-                continue;
511
-            }
512
-            // if $by_priority is set and does not match then continue;
513
-            if ($by_priority && $by_priority != $message->priority()) {
514
-                $this->_message_repository->next();
515
-                continue;
516
-            }
517
-            // error checking
518
-            if (! $message->valid_messenger()) {
519
-                $error_messages[] = sprintf(
520
-                    __('The %s messenger is not active at time of sending.', 'event_espresso'),
521
-                    $message->messenger()
522
-                );
523
-            }
524
-            if (! $message->valid_message_type()) {
525
-                $error_messages[] = sprintf(
526
-                    __('The %s message type is not active at the time of sending.', 'event_espresso'),
527
-                    $message->message_type()
528
-                );
529
-            }
530
-            // if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
531
-            // then it will instead be an EE_Error object, so let's check for that
532
-            if ($sending_messenger instanceof EE_Error) {
533
-                $error_messages[] = $sending_messenger->getMessage();
534
-            }
535
-            // if there are no errors, then let's process the message
536
-            if (empty($error_messages)) {
537
-                if ($save) {
538
-                    $message->set_messenger_is_executing();
539
-                }
540
-                if ($this->_process_message($message, $sending_messenger)) {
541
-                    $messages_sent++;
542
-                }
543
-            }
544
-            $this->_set_error_message($message, $error_messages);
545
-            // add modified time
546
-            $message->set_modified(time());
547
-            // we save each message after its processed to make sure its status persists in case PHP times-out or runs
548
-            // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
549
-            if ($save) {
550
-                $message->save();
551
-            }
552
-
553
-            $this->_message_repository->next();
554
-        }
555
-        if ($save) {
556
-            $this->save(true);
557
-        }
558
-        return $messages_sent;
559
-    }
560
-
561
-
562
-    /**
563
-     * _process_message
564
-     *
565
-     * @param EE_Message $message
566
-     * @param mixed      $sending_messenger (optional)
567
-     * @return bool
568
-     */
569
-    protected function _process_message(EE_Message $message, $sending_messenger = null)
570
-    {
571
-        // these *should* have been validated in the execute() method above
572
-        $messenger    = $message->messenger_object();
573
-        $message_type = $message->message_type_object();
574
-        // do actions for sending messenger if it differs from generating messenger and swap values.
575
-        if ($sending_messenger instanceof EE_messenger
576
-            && $messenger instanceof EE_messenger
577
-            && $sending_messenger->name != $messenger->name
578
-        ) {
579
-            $messenger->do_secondary_messenger_hooks($sending_messenger->name);
580
-            $messenger = $sending_messenger;
581
-        }
582
-        // send using messenger, but double check objects
583
-        if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
584
-            // set hook for message type (but only if not using another messenger to send).
585
-            if (! isset($this->_did_hook[ $message_type->name ])) {
586
-                $message_type->do_messenger_hooks($messenger);
587
-                $this->_did_hook[ $message_type->name ] = 1;
588
-            }
589
-            // if preview then use preview method
590
-            return $this->_message_repository->is_preview()
591
-                ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
592
-                : $this->_do_send($message, $messenger, $message_type);
593
-        }
594
-        return false;
595
-    }
596
-
597
-
598
-    /**
599
-     * The intention of this method is to count how many EE_Message objects
600
-     * are in the queue with a given status.
601
-     * Example usage:
602
-     * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
603
-     * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
604
-     *
605
-     * @param array|string $status Stati to check for in queue
606
-     * @return int  Count of EE_Message's matching the given status.
607
-     */
608
-    public function count_STS_in_queue($status)
609
-    {
610
-        $count  = 0;
611
-        $status = is_array($status) ? $status : array($status);
612
-        $this->_message_repository->rewind();
613
-        foreach ($this->_message_repository as $message) {
614
-            if (in_array($message->STS_ID(), $status)) {
615
-                $count++;
616
-            }
617
-        }
618
-        return $count;
619
-    }
620
-
621
-
622
-    /**
623
-     * Executes the get_preview method on the provided messenger.
624
-     *
625
-     * @param EE_Message      $message
626
-     * @param EE_messenger    $messenger
627
-     * @param EE_message_type $message_type
628
-     * @param                 $test_send
629
-     * @return bool   true means all went well, false means, not so much.
630
-     */
631
-    protected function _do_preview(
632
-        EE_Message $message,
633
-        EE_messenger $messenger,
634
-        EE_message_type $message_type,
635
-        $test_send
636
-    ) {
637
-        if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
638
-            if (! $test_send) {
639
-                $message->set_content($preview);
640
-            }
641
-            $message->set_STS_ID(EEM_Message::status_sent);
642
-            return true;
643
-        } else {
644
-            $message->set_STS_ID(EEM_Message::status_failed);
645
-            return false;
646
-        }
647
-    }
648
-
649
-
650
-    /**
651
-     * Executes the send method on the provided messenger
652
-     * EE_Messengers are expected to:
653
-     * - return true if the send was successful.
654
-     * - return false if the send was unsuccessful but can be tried again.
655
-     * - throw an Exception if the send was unsuccessful and cannot be tried again.
656
-     *
657
-     * @param EE_Message      $message
658
-     * @param EE_messenger    $messenger
659
-     * @param EE_message_type $message_type
660
-     * @return bool true means all went well, false means, not so much.
661
-     */
662
-    protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
663
-    {
664
-        try {
665
-            if ($messenger->send_message($message, $message_type)) {
666
-                $message->set_STS_ID(EEM_Message::status_sent);
667
-                return true;
668
-            } else {
669
-                $message->set_STS_ID(EEM_Message::status_retry);
670
-                return false;
671
-            }
672
-        } catch (SendMessageException $e) {
673
-            $message->set_STS_ID(EEM_Message::status_failed);
674
-            $message->set_error_message($e->getMessage());
675
-            return false;
676
-        }
677
-    }
678
-
679
-
680
-    /**
681
-     * This sets any necessary error messages on the message object and its status to failed.
682
-     *
683
-     * @param EE_Message $message
684
-     * @param array      $error_messages the response from the messenger.
685
-     */
686
-    protected function _set_error_message(EE_Message $message, $error_messages)
687
-    {
688
-        $error_messages = (array) $error_messages;
689
-        if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
690
-            $notices          = EE_Error::has_notices();
691
-            $error_messages[] = __(
692
-                'Messenger and Message Type were valid and active, but the messenger send method failed.',
693
-                'event_espresso'
694
-            );
695
-            if ($notices === 1) {
696
-                $notices           = EE_Error::get_vanilla_notices();
697
-                $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
698
-                $error_messages[]  = implode("\n", $notices['errors']);
699
-            }
700
-        }
701
-        if (count($error_messages) > 0) {
702
-            $msg = __('Message was not executed successfully.', 'event_espresso');
703
-            $msg = $msg . "\n" . implode("\n", $error_messages);
704
-            $message->set_error_message($msg);
705
-        }
706
-    }
17
+	/**
18
+	 * @type    string  reference for sending action
19
+	 */
20
+	const action_sending = 'sending';
21
+
22
+	/**
23
+	 * @type    string  reference for generation action
24
+	 */
25
+	const action_generating = 'generation';
26
+
27
+
28
+	/**
29
+	 * @type EE_Message_Repository $_message_repository
30
+	 */
31
+	protected $_message_repository;
32
+
33
+	/**
34
+	 * Sets the limit of how many messages are generated per process.
35
+	 *
36
+	 * @type int
37
+	 */
38
+	protected $_batch_count;
39
+
40
+
41
+	/**
42
+	 * This is an array of cached queue items being stored in this object.
43
+	 * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
44
+	 * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
45
+	 *
46
+	 * @type EE_Message[]
47
+	 */
48
+	protected $_cached_queue_items;
49
+
50
+	/**
51
+	 * Tracks the number of unsaved queue items.
52
+	 *
53
+	 * @type int
54
+	 */
55
+	protected $_unsaved_count = 0;
56
+
57
+	/**
58
+	 * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
59
+	 * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
60
+	 *
61
+	 * @type array
62
+	 */
63
+	protected $_did_hook = array();
64
+
65
+
66
+	/**
67
+	 * Constructor.
68
+	 * Setup all the initial properties and load a EE_Message_Repository.
69
+	 *
70
+	 * @param \EE_Message_Repository $message_repository
71
+	 */
72
+	public function __construct(EE_Message_Repository $message_repository)
73
+	{
74
+		$this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
75
+		$this->_message_repository = $message_repository;
76
+	}
77
+
78
+
79
+	/**
80
+	 * Add a EE_Message object to the queue
81
+	 *
82
+	 * @param EE_Message $message
83
+	 * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
84
+	 *                                 object is persisted, this data will be saved on an extra_meta object related to
85
+	 *                                 EE_Message.
86
+	 * @param  bool      $preview      Whether this EE_Message represents a preview or not.
87
+	 * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
88
+	 *                                 use the messenger send method but typically is based on preview data.
89
+	 * @return bool          Whether the message was successfully added to the repository or not.
90
+	 */
91
+	public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
92
+	{
93
+		$data['preview']   = $preview;
94
+		$data['test_send'] = $test_send;
95
+		return $this->_message_repository->add($message, $data);
96
+	}
97
+
98
+
99
+	/**
100
+	 * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
101
+	 *
102
+	 * @param EE_Message $message The message to detach from the queue
103
+	 * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
104
+	 * @return bool
105
+	 */
106
+	public function remove(EE_Message $message, $persist = false)
107
+	{
108
+		if ($persist && $this->_message_repository->current() !== $message) {
109
+			// get pointer on right message
110
+			if ($this->_message_repository->has($message)) {
111
+				$this->_message_repository->rewind();
112
+				while ($this->_message_repository->valid()) {
113
+					if ($this->_message_repository->current() === $message) {
114
+						break;
115
+					}
116
+					$this->_message_repository->next();
117
+				}
118
+			} else {
119
+				return false;
120
+			}
121
+		}
122
+		return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
123
+	}
124
+
125
+
126
+	/**
127
+	 * Persists all queued EE_Message objects to the db.
128
+	 *
129
+	 * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
130
+	 * @return array @see EE_Messages_Repository::saveAll() for return values.
131
+	 */
132
+	public function save($do_hooks_only = false)
133
+	{
134
+		return $this->_message_repository->saveAll($do_hooks_only);
135
+	}
136
+
137
+
138
+	/**
139
+	 * @return EE_Message_Repository
140
+	 */
141
+	public function get_message_repository()
142
+	{
143
+		return $this->_message_repository;
144
+	}
145
+
146
+
147
+	/**
148
+	 * This does the following things:
149
+	 * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
150
+	 * false).
151
+	 * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
152
+	 * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
153
+	 * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
154
+	 * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
155
+	 * removed.
156
+	 *
157
+	 * @return bool  true if successfully retrieved batch, false no batch ready.
158
+	 */
159
+	public function get_batch_to_generate()
160
+	{
161
+		if ($this->is_locked(EE_Messages_Queue::action_generating)) {
162
+			return false;
163
+		}
164
+
165
+		// lock batch generation to prevent race conditions.
166
+		$this->lock_queue(EE_Messages_Queue::action_generating);
167
+
168
+		$query_args = array(
169
+			// key 0 = where conditions
170
+			0          => array('STS_ID' => EEM_Message::status_incomplete),
171
+			'order_by' => $this->_get_priority_orderby(),
172
+			'limit'    => $this->_batch_count,
173
+		);
174
+		$messages   = EEM_Message::instance()->get_all($query_args);
175
+
176
+		if (! $messages) {
177
+			return false; // nothing to generate
178
+		}
179
+
180
+		foreach ($messages as $message) {
181
+			if ($message instanceof EE_Message) {
182
+				$data = $message->all_extra_meta_array();
183
+				$this->add($message, $data);
184
+			}
185
+		}
186
+		return true;
187
+	}
188
+
189
+
190
+	/**
191
+	 * This does the following things:
192
+	 * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
193
+	 * false).
194
+	 * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
195
+	 * return false.
196
+	 * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
197
+	 * 3. On success or unsuccessful send, sets status appropriately.
198
+	 * 4. Saves messages via the queue
199
+	 * 5. Releases lock.
200
+	 *
201
+	 * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
202
+	 *               necessarily mean that all messages were successfully sent.  It just means that this method
203
+	 *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
204
+	 *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
205
+	 *               will also have a saved error message on it to assist with notifying user.
206
+	 */
207
+	public function get_to_send_batch_and_send()
208
+	{
209
+		$rate_limit = $this->get_rate_limit();
210
+		if ($rate_limit < 1
211
+			|| $this->is_locked(EE_Messages_Queue::action_sending)) {
212
+			return false;
213
+		}
214
+
215
+		$this->lock_queue(EE_Messages_Queue::action_sending);
216
+
217
+		$batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
218
+
219
+		$query_args = array(
220
+			// key 0 = where conditions
221
+			0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
222
+			'order_by' => $this->_get_priority_orderby(),
223
+			'limit'    => $batch,
224
+		);
225
+
226
+		$messages_to_send = EEM_Message::instance()->get_all($query_args);
227
+
228
+
229
+		// any to send?
230
+		if (! $messages_to_send) {
231
+			$this->unlock_queue(EE_Messages_Queue::action_sending);
232
+			return false;
233
+		}
234
+
235
+		$queue_count = 0;
236
+
237
+		// add to queue.
238
+		foreach ($messages_to_send as $message) {
239
+			if ($message instanceof EE_Message) {
240
+				$queue_count++;
241
+				$this->add($message);
242
+			}
243
+		}
244
+
245
+		// send messages  (this also updates the rate limit)
246
+		$this->execute();
247
+
248
+		// release lock
249
+		$this->unlock_queue(EE_Messages_Queue::action_sending);
250
+		// update rate limit
251
+		$this->set_rate_limit($queue_count);
252
+		return true;
253
+	}
254
+
255
+
256
+	/**
257
+	 * Locks the queue so that no other queues can call the "batch" methods.
258
+	 *
259
+	 * @param   string $type The type of queue being locked.
260
+	 */
261
+	public function lock_queue($type = EE_Messages_Queue::action_generating)
262
+	{
263
+		update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
264
+	}
265
+
266
+
267
+	/**
268
+	 * Unlocks the queue so that batch methods can be used.
269
+	 *
270
+	 * @param   string $type The type of queue being unlocked.
271
+	 */
272
+	public function unlock_queue($type = EE_Messages_Queue::action_generating)
273
+	{
274
+		delete_option($this->_get_lock_key($type));
275
+	}
276
+
277
+
278
+	/**
279
+	 * Retrieve the key used for the lock transient.
280
+	 *
281
+	 * @param string $type The type of lock.
282
+	 * @return string
283
+	 */
284
+	protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
285
+	{
286
+		return '_ee_lock_' . $type;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Retrieve the expiry time for the lock transient.
292
+	 *
293
+	 * @param string $type The type of lock
294
+	 * @return int   time to expiry in seconds.
295
+	 */
296
+	protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
297
+	{
298
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
299
+	}
300
+
301
+
302
+	/**
303
+	 * Returns the key used for rate limit transient.
304
+	 *
305
+	 * @return string
306
+	 */
307
+	protected function _get_rate_limit_key()
308
+	{
309
+		return '_ee_rate_limit';
310
+	}
311
+
312
+
313
+	/**
314
+	 * Returns the rate limit expiry time.
315
+	 *
316
+	 * @return int
317
+	 */
318
+	protected function _get_rate_limit_expiry()
319
+	{
320
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
321
+	}
322
+
323
+
324
+	/**
325
+	 * Returns the default rate limit for sending messages.
326
+	 *
327
+	 * @return int
328
+	 */
329
+	protected function _default_rate_limit()
330
+	{
331
+		return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
332
+	}
333
+
334
+
335
+	/**
336
+	 * Return the orderby array for priority.
337
+	 *
338
+	 * @return array
339
+	 */
340
+	protected function _get_priority_orderby()
341
+	{
342
+		return array(
343
+			'MSG_priority' => 'ASC',
344
+			'MSG_modified' => 'DESC',
345
+		);
346
+	}
347
+
348
+
349
+	/**
350
+	 * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
351
+	 * Return true when batch methods should not be used; returns false when they can be.
352
+	 *
353
+	 * @param  string $type The type of lock being checked for.
354
+	 * @return bool
355
+	 */
356
+	public function is_locked($type = EE_Messages_Queue::action_generating)
357
+	{
358
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
359
+			return true;
360
+		}
361
+		$lock = (int) get_option($this->_get_lock_key($type), 0);
362
+		/**
363
+		 * This filters the default is_locked behaviour.
364
+		 */
365
+		$is_locked = filter_var(
366
+			apply_filters(
367
+				'FHEE__EE_Messages_Queue__is_locked',
368
+				$lock > time(),
369
+				$this
370
+			),
371
+			FILTER_VALIDATE_BOOLEAN
372
+		);
373
+
374
+		/**
375
+		 * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
376
+		 *            Also implemented here because messages processed on the same request should not have any locks applied.
377
+		 */
378
+		if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
379
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
380
+		) {
381
+			$is_locked = false;
382
+		}
383
+
384
+
385
+		return $is_locked;
386
+	}
387
+
388
+
389
+	/**
390
+	 * Retrieves the rate limit that may be cached as a transient.
391
+	 * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
392
+	 *
393
+	 * @param bool $return_expiry  If true then return the expiry time not the rate_limit.
394
+	 * @return int
395
+	 */
396
+	protected function get_rate_limit($return_expiry = false)
397
+	{
398
+		$stored_rate_info = get_option($this->_get_rate_limit_key(), array());
399
+		$rate_limit = isset($stored_rate_info[0])
400
+			? (int) $stored_rate_info[0]
401
+			: 0;
402
+		$expiry = isset($stored_rate_info[1])
403
+			? (int) $stored_rate_info[1]
404
+			: 0;
405
+		// set the default for tracking?
406
+		if (empty($stored_rate_info) || time() > $expiry) {
407
+			$expiry = $this->_get_rate_limit_expiry();
408
+			$rate_limit = $this->_default_rate_limit();
409
+			update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry));
410
+		}
411
+		return $return_expiry ? $expiry : $rate_limit;
412
+	}
413
+
414
+
415
+	/**
416
+	 * This updates existing rate limit with the new limit which is the old minus the batch.
417
+	 *
418
+	 * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
419
+	 */
420
+	protected function set_rate_limit($batch_completed)
421
+	{
422
+		// first get the most up to date rate limit (in case its expired and reset)
423
+		$rate_limit = $this->get_rate_limit();
424
+		$expiry = $this->get_rate_limit(true);
425
+		$new_limit  = $rate_limit - $batch_completed;
426
+		// updating the transient option directly to avoid resetting the expiry.
427
+
428
+		update_option($this->_get_rate_limit_key(), array($new_limit, $expiry));
429
+	}
430
+
431
+
432
+	/**
433
+	 * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
434
+	 * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
435
+	 * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
436
+	 * request running on a queue for the given task.
437
+	 *
438
+	 * @param string $task     This indicates what type of request is going to be initiated.
439
+	 * @param int    $priority This indicates the priority that triggers initiating the request.
440
+	 */
441
+	public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
442
+	{
443
+		// determine what status is matched with the priority as part of the trigger conditions.
444
+		$status = $task == 'generate'
445
+			? EEM_Message::status_incomplete
446
+			: EEM_Message::instance()->stati_indicating_to_send();
447
+		// always make sure we save because either this will get executed immediately on a separate request
448
+		// or remains in the queue for the regularly scheduled queue batch.
449
+		$this->save();
450
+		/**
451
+		 * This filter/option allows users to override processing of messages on separate requests and instead have everything
452
+		 * happen on the same request.  If this is utilized remember:
453
+		 * - message priorities don't matter
454
+		 * - existing unprocessed messages in the queue will not get processed unless manually triggered.
455
+		 * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
456
+		 *   processing happening on the same request.
457
+		 * - any race condition protection (locks) are removed because they don't apply when things are processed on
458
+		 *   the same request.
459
+		 */
460
+		if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
461
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
462
+		) {
463
+			$messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
464
+			if ($messages_processor instanceof EE_Messages_Processor) {
465
+				return $messages_processor->process_immediately_from_queue($this);
466
+			}
467
+			// if we get here then that means the messages processor couldn't be loaded so messages will just remain
468
+			// queued for manual triggering by end user.
469
+		}
470
+
471
+		if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
472
+			EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
473
+		}
474
+	}
475
+
476
+
477
+	/**
478
+	 *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
479
+	 *
480
+	 * @param   bool     $save                    Used to indicate whether to save the message queue after sending
481
+	 *                                            (default will save).
482
+	 * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
483
+	 *                                            what is on the EE_Message object in the queue.
484
+	 *                                            For instance, showing the browser view of an email message,
485
+	 *                                            or giving a pdf generated view of an html document.
486
+	 *                                            This should be an instance of EE_messenger but if you call this
487
+	 *                                            method
488
+	 *                                            intending it to be a sending messenger but a valid one could not be
489
+	 *                                            retrieved then send in an instance of EE_Error that contains the
490
+	 *                                            related error message.
491
+	 * @param   bool|int $by_priority             When set, this indicates that only messages
492
+	 *                                            matching the given priority should be executed.
493
+	 * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
494
+	 *                                            Also, if the messenger is an request type messenger (or a preview),
495
+	 *                                            its entirely possible that the messenger will exit before
496
+	 */
497
+	public function execute($save = true, $sending_messenger = null, $by_priority = false)
498
+	{
499
+		$messages_sent   = 0;
500
+		$this->_did_hook = array();
501
+		$this->_message_repository->rewind();
502
+
503
+		while ($this->_message_repository->valid()) {
504
+			$error_messages = array();
505
+			/** @type EE_Message $message */
506
+			$message = $this->_message_repository->current();
507
+			// only process things that are queued for sending
508
+			if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
509
+				$this->_message_repository->next();
510
+				continue;
511
+			}
512
+			// if $by_priority is set and does not match then continue;
513
+			if ($by_priority && $by_priority != $message->priority()) {
514
+				$this->_message_repository->next();
515
+				continue;
516
+			}
517
+			// error checking
518
+			if (! $message->valid_messenger()) {
519
+				$error_messages[] = sprintf(
520
+					__('The %s messenger is not active at time of sending.', 'event_espresso'),
521
+					$message->messenger()
522
+				);
523
+			}
524
+			if (! $message->valid_message_type()) {
525
+				$error_messages[] = sprintf(
526
+					__('The %s message type is not active at the time of sending.', 'event_espresso'),
527
+					$message->message_type()
528
+				);
529
+			}
530
+			// if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
531
+			// then it will instead be an EE_Error object, so let's check for that
532
+			if ($sending_messenger instanceof EE_Error) {
533
+				$error_messages[] = $sending_messenger->getMessage();
534
+			}
535
+			// if there are no errors, then let's process the message
536
+			if (empty($error_messages)) {
537
+				if ($save) {
538
+					$message->set_messenger_is_executing();
539
+				}
540
+				if ($this->_process_message($message, $sending_messenger)) {
541
+					$messages_sent++;
542
+				}
543
+			}
544
+			$this->_set_error_message($message, $error_messages);
545
+			// add modified time
546
+			$message->set_modified(time());
547
+			// we save each message after its processed to make sure its status persists in case PHP times-out or runs
548
+			// out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
549
+			if ($save) {
550
+				$message->save();
551
+			}
552
+
553
+			$this->_message_repository->next();
554
+		}
555
+		if ($save) {
556
+			$this->save(true);
557
+		}
558
+		return $messages_sent;
559
+	}
560
+
561
+
562
+	/**
563
+	 * _process_message
564
+	 *
565
+	 * @param EE_Message $message
566
+	 * @param mixed      $sending_messenger (optional)
567
+	 * @return bool
568
+	 */
569
+	protected function _process_message(EE_Message $message, $sending_messenger = null)
570
+	{
571
+		// these *should* have been validated in the execute() method above
572
+		$messenger    = $message->messenger_object();
573
+		$message_type = $message->message_type_object();
574
+		// do actions for sending messenger if it differs from generating messenger and swap values.
575
+		if ($sending_messenger instanceof EE_messenger
576
+			&& $messenger instanceof EE_messenger
577
+			&& $sending_messenger->name != $messenger->name
578
+		) {
579
+			$messenger->do_secondary_messenger_hooks($sending_messenger->name);
580
+			$messenger = $sending_messenger;
581
+		}
582
+		// send using messenger, but double check objects
583
+		if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
584
+			// set hook for message type (but only if not using another messenger to send).
585
+			if (! isset($this->_did_hook[ $message_type->name ])) {
586
+				$message_type->do_messenger_hooks($messenger);
587
+				$this->_did_hook[ $message_type->name ] = 1;
588
+			}
589
+			// if preview then use preview method
590
+			return $this->_message_repository->is_preview()
591
+				? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
592
+				: $this->_do_send($message, $messenger, $message_type);
593
+		}
594
+		return false;
595
+	}
596
+
597
+
598
+	/**
599
+	 * The intention of this method is to count how many EE_Message objects
600
+	 * are in the queue with a given status.
601
+	 * Example usage:
602
+	 * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
603
+	 * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
604
+	 *
605
+	 * @param array|string $status Stati to check for in queue
606
+	 * @return int  Count of EE_Message's matching the given status.
607
+	 */
608
+	public function count_STS_in_queue($status)
609
+	{
610
+		$count  = 0;
611
+		$status = is_array($status) ? $status : array($status);
612
+		$this->_message_repository->rewind();
613
+		foreach ($this->_message_repository as $message) {
614
+			if (in_array($message->STS_ID(), $status)) {
615
+				$count++;
616
+			}
617
+		}
618
+		return $count;
619
+	}
620
+
621
+
622
+	/**
623
+	 * Executes the get_preview method on the provided messenger.
624
+	 *
625
+	 * @param EE_Message      $message
626
+	 * @param EE_messenger    $messenger
627
+	 * @param EE_message_type $message_type
628
+	 * @param                 $test_send
629
+	 * @return bool   true means all went well, false means, not so much.
630
+	 */
631
+	protected function _do_preview(
632
+		EE_Message $message,
633
+		EE_messenger $messenger,
634
+		EE_message_type $message_type,
635
+		$test_send
636
+	) {
637
+		if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
638
+			if (! $test_send) {
639
+				$message->set_content($preview);
640
+			}
641
+			$message->set_STS_ID(EEM_Message::status_sent);
642
+			return true;
643
+		} else {
644
+			$message->set_STS_ID(EEM_Message::status_failed);
645
+			return false;
646
+		}
647
+	}
648
+
649
+
650
+	/**
651
+	 * Executes the send method on the provided messenger
652
+	 * EE_Messengers are expected to:
653
+	 * - return true if the send was successful.
654
+	 * - return false if the send was unsuccessful but can be tried again.
655
+	 * - throw an Exception if the send was unsuccessful and cannot be tried again.
656
+	 *
657
+	 * @param EE_Message      $message
658
+	 * @param EE_messenger    $messenger
659
+	 * @param EE_message_type $message_type
660
+	 * @return bool true means all went well, false means, not so much.
661
+	 */
662
+	protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
663
+	{
664
+		try {
665
+			if ($messenger->send_message($message, $message_type)) {
666
+				$message->set_STS_ID(EEM_Message::status_sent);
667
+				return true;
668
+			} else {
669
+				$message->set_STS_ID(EEM_Message::status_retry);
670
+				return false;
671
+			}
672
+		} catch (SendMessageException $e) {
673
+			$message->set_STS_ID(EEM_Message::status_failed);
674
+			$message->set_error_message($e->getMessage());
675
+			return false;
676
+		}
677
+	}
678
+
679
+
680
+	/**
681
+	 * This sets any necessary error messages on the message object and its status to failed.
682
+	 *
683
+	 * @param EE_Message $message
684
+	 * @param array      $error_messages the response from the messenger.
685
+	 */
686
+	protected function _set_error_message(EE_Message $message, $error_messages)
687
+	{
688
+		$error_messages = (array) $error_messages;
689
+		if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
690
+			$notices          = EE_Error::has_notices();
691
+			$error_messages[] = __(
692
+				'Messenger and Message Type were valid and active, but the messenger send method failed.',
693
+				'event_espresso'
694
+			);
695
+			if ($notices === 1) {
696
+				$notices           = EE_Error::get_vanilla_notices();
697
+				$notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
698
+				$error_messages[]  = implode("\n", $notices['errors']);
699
+			}
700
+		}
701
+		if (count($error_messages) > 0) {
702
+			$msg = __('Message was not executed successfully.', 'event_espresso');
703
+			$msg = $msg . "\n" . implode("\n", $error_messages);
704
+			$message->set_error_message($msg);
705
+		}
706
+	}
707 707
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -171,9 +171,9 @@  discard block
 block discarded – undo
171 171
             'order_by' => $this->_get_priority_orderby(),
172 172
             'limit'    => $this->_batch_count,
173 173
         );
174
-        $messages   = EEM_Message::instance()->get_all($query_args);
174
+        $messages = EEM_Message::instance()->get_all($query_args);
175 175
 
176
-        if (! $messages) {
176
+        if ( ! $messages) {
177 177
             return false; // nothing to generate
178 178
         }
179 179
 
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
 
228 228
 
229 229
         // any to send?
230
-        if (! $messages_to_send) {
230
+        if ( ! $messages_to_send) {
231 231
             $this->unlock_queue(EE_Messages_Queue::action_sending);
232 232
             return false;
233 233
         }
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
      */
284 284
     protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
285 285
     {
286
-        return '_ee_lock_' . $type;
286
+        return '_ee_lock_'.$type;
287 287
     }
288 288
 
289 289
 
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
      */
356 356
     public function is_locked($type = EE_Messages_Queue::action_generating)
357 357
     {
358
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
358
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
359 359
             return true;
360 360
         }
361 361
         $lock = (int) get_option($this->_get_lock_key($type), 0);
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
             /** @type EE_Message $message */
506 506
             $message = $this->_message_repository->current();
507 507
             // only process things that are queued for sending
508
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
508
+            if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
509 509
                 $this->_message_repository->next();
510 510
                 continue;
511 511
             }
@@ -515,13 +515,13 @@  discard block
 block discarded – undo
515 515
                 continue;
516 516
             }
517 517
             // error checking
518
-            if (! $message->valid_messenger()) {
518
+            if ( ! $message->valid_messenger()) {
519 519
                 $error_messages[] = sprintf(
520 520
                     __('The %s messenger is not active at time of sending.', 'event_espresso'),
521 521
                     $message->messenger()
522 522
                 );
523 523
             }
524
-            if (! $message->valid_message_type()) {
524
+            if ( ! $message->valid_message_type()) {
525 525
                 $error_messages[] = sprintf(
526 526
                     __('The %s message type is not active at the time of sending.', 'event_espresso'),
527 527
                     $message->message_type()
@@ -582,9 +582,9 @@  discard block
 block discarded – undo
582 582
         // send using messenger, but double check objects
583 583
         if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
584 584
             // set hook for message type (but only if not using another messenger to send).
585
-            if (! isset($this->_did_hook[ $message_type->name ])) {
585
+            if ( ! isset($this->_did_hook[$message_type->name])) {
586 586
                 $message_type->do_messenger_hooks($messenger);
587
-                $this->_did_hook[ $message_type->name ] = 1;
587
+                $this->_did_hook[$message_type->name] = 1;
588 588
             }
589 589
             // if preview then use preview method
590 590
             return $this->_message_repository->is_preview()
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
         $test_send
636 636
     ) {
637 637
         if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
638
-            if (! $test_send) {
638
+            if ( ! $test_send) {
639 639
                 $message->set_content($preview);
640 640
             }
641 641
             $message->set_STS_ID(EEM_Message::status_sent);
@@ -700,7 +700,7 @@  discard block
 block discarded – undo
700 700
         }
701 701
         if (count($error_messages) > 0) {
702 702
             $msg = __('Message was not executed successfully.', 'event_espresso');
703
-            $msg = $msg . "\n" . implode("\n", $error_messages);
703
+            $msg = $msg."\n".implode("\n", $error_messages);
704 704
             $message->set_error_message($msg);
705 705
         }
706 706
     }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Field_With_Model_Name.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -70,10 +70,10 @@
 block discarded – undo
70 70
         $model_names = array();
71 71
         if (is_array($this->_model_name_pointed_to)) {
72 72
             foreach ($this->_model_name_pointed_to as $model_name) {
73
-                $model_names[] = "EE_" . $model_name;
73
+                $model_names[] = "EE_".$model_name;
74 74
             }
75 75
         } else {
76
-            $model_names = array("EE_" . $this->_model_name_pointed_to);
76
+            $model_names = array("EE_".$this->_model_name_pointed_to);
77 77
         }
78 78
         return $model_names;
79 79
     }
Please login to merge, or discard this patch.
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -8,88 +8,88 @@
 block discarded – undo
8 8
  */
9 9
 abstract class EE_Field_With_Model_Name extends EE_Model_Field_Base
10 10
 {
11
-    /**
12
-     * Usually the name of a single model. However, as in the case for custom post types,
13
-     * it can actually be an array of models
14
-     *
15
-     * @var string or array
16
-     */
17
-    protected $_model_name_pointed_to;
11
+	/**
12
+	 * Usually the name of a single model. However, as in the case for custom post types,
13
+	 * it can actually be an array of models
14
+	 *
15
+	 * @var string or array
16
+	 */
17
+	protected $_model_name_pointed_to;
18 18
 
19
-    /**
20
-     * @param string  $table_column  name fo column for field
21
-     * @param string  $nicename      should eb internationalized with __('blah','event_espresso')
22
-     * @param boolean $nullable
23
-     * @param mixed   $default_value if this is a integer field, it shoudl be an int. if it's a string field, it shoul
24
-     *                               dbe a string
25
-     * @param string  $model_name    eg 'Event','Answer','Term', etc. Basically its the model class's name without the
26
-     *                               "EEM_"
27
-     */
28
-    public function __construct($table_column, $nicename, $nullable, $default_value, $model_name)
29
-    {
30
-        $this->_model_name_pointed_to = $model_name;
31
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
32
-    }
19
+	/**
20
+	 * @param string  $table_column  name fo column for field
21
+	 * @param string  $nicename      should eb internationalized with __('blah','event_espresso')
22
+	 * @param boolean $nullable
23
+	 * @param mixed   $default_value if this is a integer field, it shoudl be an int. if it's a string field, it shoul
24
+	 *                               dbe a string
25
+	 * @param string  $model_name    eg 'Event','Answer','Term', etc. Basically its the model class's name without the
26
+	 *                               "EEM_"
27
+	 */
28
+	public function __construct($table_column, $nicename, $nullable, $default_value, $model_name)
29
+	{
30
+		$this->_model_name_pointed_to = $model_name;
31
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
32
+	}
33 33
 
34
-    /**
35
-     * Returns the name of the model(s) pointed to
36
-     *
37
-     * @deprecated since version 4.6.7
38
-     * @return mixed string or array of strings
39
-     */
40
-    public function get_model_name_pointed_to()
41
-    {
42
-        EE_Error::doing_it_wrong(
43
-            'get_model_name_pointed_to',
44
-            __(
45
-                'This method has been deprecated in favour of instead using get_model_names_pointed_to, which consistently returns an array',
46
-                'event_espresso'
47
-            ),
48
-            '4.6.7'
49
-        );
50
-        return $this->_model_name_pointed_to;
51
-    }
34
+	/**
35
+	 * Returns the name of the model(s) pointed to
36
+	 *
37
+	 * @deprecated since version 4.6.7
38
+	 * @return mixed string or array of strings
39
+	 */
40
+	public function get_model_name_pointed_to()
41
+	{
42
+		EE_Error::doing_it_wrong(
43
+			'get_model_name_pointed_to',
44
+			__(
45
+				'This method has been deprecated in favour of instead using get_model_names_pointed_to, which consistently returns an array',
46
+				'event_espresso'
47
+			),
48
+			'4.6.7'
49
+		);
50
+		return $this->_model_name_pointed_to;
51
+	}
52 52
 
53
-    /**
54
-     * Gets the model names pointed to by this field, always as an array
55
-     * (even if there's only one)
56
-     *
57
-     * @return array of model names pointed to by this field
58
-     */
59
-    public function get_model_names_pointed_to()
60
-    {
61
-        if (is_array($this->_model_name_pointed_to)) {
62
-            return $this->_model_name_pointed_to;
63
-        } else {
64
-            return array($this->_model_name_pointed_to);
65
-        }
66
-    }
53
+	/**
54
+	 * Gets the model names pointed to by this field, always as an array
55
+	 * (even if there's only one)
56
+	 *
57
+	 * @return array of model names pointed to by this field
58
+	 */
59
+	public function get_model_names_pointed_to()
60
+	{
61
+		if (is_array($this->_model_name_pointed_to)) {
62
+			return $this->_model_name_pointed_to;
63
+		} else {
64
+			return array($this->_model_name_pointed_to);
65
+		}
66
+	}
67 67
 
68
-    /**
69
-     * Returns the model's classname (eg EE_Event instead of just Event)
70
-     *
71
-     * @return array
72
-     */
73
-    public function get_model_class_names_pointed_to()
74
-    {
75
-        $model_names = array();
76
-        if (is_array($this->_model_name_pointed_to)) {
77
-            foreach ($this->_model_name_pointed_to as $model_name) {
78
-                $model_names[] = "EE_" . $model_name;
79
-            }
80
-        } else {
81
-            $model_names = array("EE_" . $this->_model_name_pointed_to);
82
-        }
83
-        return $model_names;
84
-    }
68
+	/**
69
+	 * Returns the model's classname (eg EE_Event instead of just Event)
70
+	 *
71
+	 * @return array
72
+	 */
73
+	public function get_model_class_names_pointed_to()
74
+	{
75
+		$model_names = array();
76
+		if (is_array($this->_model_name_pointed_to)) {
77
+			foreach ($this->_model_name_pointed_to as $model_name) {
78
+				$model_names[] = "EE_" . $model_name;
79
+			}
80
+		} else {
81
+			$model_names = array("EE_" . $this->_model_name_pointed_to);
82
+		}
83
+		return $model_names;
84
+	}
85 85
 
86
-    public function is_model_obj_of_type_pointed_to($model_obj_or_ID)
87
-    {
88
-        foreach ($this->get_model_class_names_pointed_to() as $model_obj_classname) {
89
-            if ($model_obj_or_ID instanceof $model_obj_classname) {
90
-                return true;
91
-            }
92
-        }
93
-        return false;
94
-    }
86
+	public function is_model_obj_of_type_pointed_to($model_obj_or_ID)
87
+	{
88
+		foreach ($this->get_model_class_names_pointed_to() as $model_obj_classname) {
89
+			if ($model_obj_or_ID instanceof $model_obj_classname) {
90
+				return true;
91
+			}
92
+		}
93
+		return false;
94
+	}
95 95
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Model_Relation_Base.php 3 patches
Doc Comments   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -133,9 +133,9 @@  discard block
 block discarded – undo
133 133
 
134 134
     /**
135 135
      * @param        $other_table
136
-     * @param        $other_table_alias
136
+     * @param        string $other_table_alias
137 137
      * @param        $other_table_column
138
-     * @param        $this_table_alias
138
+     * @param        string $this_table_alias
139 139
      * @param        $this_table_join_column
140 140
      * @param string $extra_join_sql
141 141
      * @return string
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
      * Alters the $query_params to disable default where conditions, unless otherwise specified
190 190
      *
191 191
      * @param string $query_params
192
-     * @return array
192
+     * @return string
193 193
      */
194 194
     protected function _disable_default_where_conditions_on_query_param($query_params)
195 195
     {
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
      * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
207 207
      * model objects will only be soft-deleted.
208 208
      *
209
-     * @param EE_Base_Class|int|string $model_object_or_id
209
+     * @param EE_Base_Class|null $model_object_or_id
210 210
      * @param array                    $query_params
211 211
      * @return int of how many related models got deleted
212 212
      * @throws \EE_Error
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
      * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
238 238
      * model objects will only be soft-deleted.
239 239
      *
240
-     * @param EE_Base_Class|int|string $model_object_or_id
240
+     * @param EE_Base_Class|null $model_object_or_id
241 241
      * @param array                    $query_params
242 242
      * @return int of how many related models got deleted
243 243
      * @throws \EE_Error
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -156,7 +156,7 @@  discard block
 block discarded – undo
156 156
         $this_table_join_column,
157 157
         $extra_join_sql = ''
158 158
     ) {
159
-        return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
159
+        return " LEFT JOIN ".$other_table." AS ".$other_table_alias." ON ".$other_table_alias.".".$other_table_column."=".$this_table_alias.".".$this_table_join_column.($extra_join_sql ? " AND $extra_join_sql" : '');
160 160
     }
161 161
 
162 162
 
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
                                                              . "."
191 191
                                                              . $this->get_this_model()->get_primary_key_field()->get_name();
192 192
         $model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
-        $query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
193
+        $query_params[0][$query_param_where_this_model_pk] = $model_object_id;
194 194
         return $this->get_other_model()->get_all($query_params);
195 195
     }
196 196
 
@@ -203,7 +203,7 @@  discard block
 block discarded – undo
203 203
      */
204 204
     protected function _disable_default_where_conditions_on_query_param($query_params)
205 205
     {
206
-        if (! isset($query_params['default_where_conditions'])) {
206
+        if ( ! isset($query_params['default_where_conditions'])) {
207 207
             $query_params['default_where_conditions'] = 'none';
208 208
         }
209 209
         return $query_params;
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
                 $model_object_or_id
234 234
             );
235 235
             /* @var $model_object_or_id EE_Base_Class */
236
-            if (! $delete_is_blocked) {
236
+            if ( ! $delete_is_blocked) {
237 237
                 $this->remove_relation_to($model_object_or_id, $related_model_object);
238 238
                 $related_model_object->delete();
239 239
                 $deleted_count++;
@@ -269,7 +269,7 @@  discard block
 block discarded – undo
269 269
             if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270 270
                 $this->remove_relation_to($model_object_or_id, $related_model_object);
271 271
                 $deleted_count++;
272
-                if (! $delete_is_blocked) {
272
+                if ( ! $delete_is_blocked) {
273 273
                     $related_model_object->delete_permanently();
274 274
                 } else {
275 275
                     // delete is blocked
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
                 }
279 279
             } else {
280 280
                 // its not a soft-deletable thing anyways. do the normal logic.
281
-                if (! $delete_is_blocked) {
281
+                if ( ! $delete_is_blocked) {
282 282
                     $this->remove_relation_to($model_object_or_id, $related_model_object);
283 283
                     $related_model_object->delete();
284 284
                     $deleted_count++;
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
         if ($model_object_or_id instanceof EE_Base_Class) {
303 303
             $model_object_id = $model_object_or_id->ID();
304 304
         }
305
-        if (! $model_object_id) {
305
+        if ( ! $model_object_id) {
306 306
             throw new EE_Error(sprintf(
307 307
                 __(
308 308
                     "Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
Please login to merge, or discard this patch.
Indentation   +497 added lines, -497 removed lines patch added patch discarded remove patch
@@ -15,502 +15,502 @@
 block discarded – undo
15 15
  */
16 16
 abstract class EE_Model_Relation_Base implements HasSchemaInterface
17 17
 {
18
-    /**
19
-     * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
-     *
21
-     * @var string eg Event, Question_Group, Registration
22
-     */
23
-    private $_this_model_name;
24
-    /**
25
-     * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
-     *
27
-     * @var string eg Event, Question_Group, Registration
28
-     */
29
-    private $_other_model_name;
30
-
31
-    /**
32
-     * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
-     * initiating model.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $_timezone;
38
-
39
-    /**
40
-     * If you try to delete "this_model", and there are related "other_models",
41
-     * and this isn't null, then abandon the deletion and add this warning.
42
-     * This effectively makes it impossible to delete "this_model" while there are
43
-     * related "other_models" along this relation.
44
-     *
45
-     * @var string (internationalized)
46
-     */
47
-    protected $_blocking_delete_error_message;
48
-
49
-    protected $_blocking_delete = false;
50
-
51
-    /**
52
-     * Object representing the relationship between two models. This knows how to join the models,
53
-     * get related models across the relation, and add-and-remove the relationships.
54
-     *
55
-     * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
-     *                                               and add an error) the deletion of this model
57
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
-     *                                               default
59
-     */
60
-    public function __construct($block_deletes, $blocking_delete_error_message)
61
-    {
62
-        $this->_blocking_delete               = $block_deletes;
63
-        $this->_blocking_delete_error_message = $blocking_delete_error_message;
64
-    }
65
-
66
-
67
-    /**
68
-     * @param $this_model_name
69
-     * @param $other_model_name
70
-     * @throws EE_Error
71
-     */
72
-    public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
-    {
74
-        $this->_this_model_name  = $this_model_name;
75
-        $this->_other_model_name = $other_model_name;
76
-        if (is_string($this->_blocking_delete)) {
77
-            throw new EE_Error(sprintf(
78
-                __(
79
-                    "When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
-                    "event_espresso"
81
-                ),
82
-                get_class($this),
83
-                $this_model_name,
84
-                $other_model_name,
85
-                $this->_blocking_delete
86
-            ));
87
-        }
88
-    }
89
-
90
-
91
-    /**
92
-     * Gets the model where this relation is defined.
93
-     *
94
-     * @return EEM_Base
95
-     */
96
-    public function get_this_model()
97
-    {
98
-        return $this->_get_model($this->_this_model_name);
99
-    }
100
-
101
-
102
-    /**
103
-     * Gets the model which this relation establishes the relation TO (ie,
104
-     * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
-     *
106
-     * @return EEM_Base
107
-     */
108
-    public function get_other_model()
109
-    {
110
-        return $this->_get_model($this->_other_model_name);
111
-    }
112
-
113
-
114
-    /**
115
-     * Internally used by get_this_model() and get_other_model()
116
-     *
117
-     * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
-     * @return EEM_Base
119
-     */
120
-    protected function _get_model($model_name)
121
-    {
122
-        $modelInstance = EE_Registry::instance()->load_model($model_name);
123
-        $modelInstance->set_timezone($this->_timezone);
124
-        return $modelInstance;
125
-    }
126
-
127
-
128
-    /**
129
-     * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
-     * timezone set correctly.
131
-     *
132
-     * @param string $timezone timezone to set.
133
-     */
134
-    public function set_timezone($timezone)
135
-    {
136
-        if ($timezone !== null) {
137
-            $this->_timezone = $timezone;
138
-        }
139
-    }
140
-
141
-
142
-    /**
143
-     * @param        $other_table
144
-     * @param        $other_table_alias
145
-     * @param        $other_table_column
146
-     * @param        $this_table_alias
147
-     * @param        $this_table_join_column
148
-     * @param string $extra_join_sql
149
-     * @return string
150
-     */
151
-    protected function _left_join(
152
-        $other_table,
153
-        $other_table_alias,
154
-        $other_table_column,
155
-        $this_table_alias,
156
-        $this_table_join_column,
157
-        $extra_join_sql = ''
158
-    ) {
159
-        return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
-    }
161
-
162
-
163
-    /**
164
-     * Gets all the model objects of type of other model related to $model_object,
165
-     * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
-     * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
-     * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
-     * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
-     *
170
-     * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
-     * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
-     * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
-     * @return EE_Base_Class[]
174
-     * @throws \EE_Error
175
-     */
176
-    public function get_all_related(
177
-        $model_object_or_id,
178
-        $query_params = array(),
179
-        $values_already_prepared_by_model_object = false
180
-    ) {
181
-        if ($values_already_prepared_by_model_object !== false) {
182
-            EE_Error::doing_it_wrong(
183
-                'EE_Model_Relation_Base::get_all_related',
184
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
-                '4.8.1'
186
-            );
187
-        }
188
-        $query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
-        $query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
-                                                             . "."
191
-                                                             . $this->get_this_model()->get_primary_key_field()->get_name();
192
-        $model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
-        $query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
-        return $this->get_other_model()->get_all($query_params);
195
-    }
196
-
197
-
198
-    /**
199
-     * Alters the $query_params to disable default where conditions, unless otherwise specified
200
-     *
201
-     * @param string $query_params
202
-     * @return array
203
-     */
204
-    protected function _disable_default_where_conditions_on_query_param($query_params)
205
-    {
206
-        if (! isset($query_params['default_where_conditions'])) {
207
-            $query_params['default_where_conditions'] = 'none';
208
-        }
209
-        return $query_params;
210
-    }
211
-
212
-
213
-    /**
214
-     * Deletes the related model objects which meet the query parameters. If no
215
-     * parameters are specified, then all related model objects will be deleted.
216
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
-     * model objects will only be soft-deleted.
218
-     *
219
-     * @param EE_Base_Class|int|string $model_object_or_id
220
-     * @param array                    $query_params
221
-     * @return int of how many related models got deleted
222
-     * @throws \EE_Error
223
-     */
224
-    public function delete_all_related($model_object_or_id, $query_params = array())
225
-    {
226
-        // for each thing we would delete,
227
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
-        // determine if it's blocked by anything else before it can be deleted
229
-        $deleted_count = 0;
230
-        foreach ($related_model_objects as $related_model_object) {
231
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
-                $related_model_object,
233
-                $model_object_or_id
234
-            );
235
-            /* @var $model_object_or_id EE_Base_Class */
236
-            if (! $delete_is_blocked) {
237
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
238
-                $related_model_object->delete();
239
-                $deleted_count++;
240
-            }
241
-        }
242
-        return $deleted_count;
243
-    }
244
-
245
-
246
-    /**
247
-     * Deletes the related model objects which meet the query parameters. If no
248
-     * parameters are specified, then all related model objects will be deleted.
249
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
-     * model objects will only be soft-deleted.
251
-     *
252
-     * @param EE_Base_Class|int|string $model_object_or_id
253
-     * @param array                    $query_params
254
-     * @return int of how many related models got deleted
255
-     * @throws \EE_Error
256
-     */
257
-    public function delete_related_permanently($model_object_or_id, $query_params = array())
258
-    {
259
-        // for each thing we would delete,
260
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
-        // determine if it's blocked by anything else before it can be deleted
262
-        $deleted_count = 0;
263
-        foreach ($related_model_objects as $related_model_object) {
264
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
-                $related_model_object,
266
-                $model_object_or_id
267
-            );
268
-            /* @var $model_object_or_id EE_Base_Class */
269
-            if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
271
-                $deleted_count++;
272
-                if (! $delete_is_blocked) {
273
-                    $related_model_object->delete_permanently();
274
-                } else {
275
-                    // delete is blocked
276
-                    // brent and darren, in this case, wanted to just soft delete it then
277
-                    $related_model_object->delete();
278
-                }
279
-            } else {
280
-                // its not a soft-deletable thing anyways. do the normal logic.
281
-                if (! $delete_is_blocked) {
282
-                    $this->remove_relation_to($model_object_or_id, $related_model_object);
283
-                    $related_model_object->delete();
284
-                    $deleted_count++;
285
-                }
286
-            }
287
-        }
288
-        return $deleted_count;
289
-    }
290
-
291
-
292
-    /**
293
-     * this just returns a model_object_id for incoming item that could be an object or id.
294
-     *
295
-     * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
-     * @throws EE_Error
297
-     * @return int
298
-     */
299
-    protected function _get_model_object_id($model_object_or_id)
300
-    {
301
-        $model_object_id = $model_object_or_id;
302
-        if ($model_object_or_id instanceof EE_Base_Class) {
303
-            $model_object_id = $model_object_or_id->ID();
304
-        }
305
-        if (! $model_object_id) {
306
-            throw new EE_Error(sprintf(
307
-                __(
308
-                    "Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
-                    "event_espresso"
310
-                ),
311
-                $this->get_other_model()->get_this_model_name(),
312
-                $this->get_this_model()->get_this_model_name()
313
-            ));
314
-        }
315
-        return $model_object_id;
316
-    }
317
-
318
-
319
-    /**
320
-     * Gets the SQL string for performing the join between this model and the other model.
321
-     *
322
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
-     * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
-     *                other_model_primary_table.fk" etc
325
-     */
326
-    abstract public function get_join_statement($model_relation_chain);
327
-
328
-
329
-    /**
330
-     * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
-     * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
-     * relationship only allows this model to be related to a single other model of this type)
333
-     *
334
-     * @param       $this_obj_or_id
335
-     * @param       $other_obj_or_id
336
-     * @param array $extra_join_model_fields_n_values
337
-     * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
-     *                        $other_obj_or_id)
339
-     */
340
-    abstract public function add_relation_to(
341
-        $this_obj_or_id,
342
-        $other_obj_or_id,
343
-        $extra_join_model_fields_n_values = array()
344
-    );
345
-
346
-
347
-    /**
348
-     * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
-     * model objects
350
-     *
351
-     * @param       $this_obj_or_id
352
-     * @param       $other_obj_or_id
353
-     * @param array $where_query
354
-     * @return bool
355
-     */
356
-    abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
-
358
-
359
-    /**
360
-     * Removes ALL relation instances for this relation obj
361
-     *
362
-     * @param EE_Base_Class|int $this_obj_or_id
363
-     * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
-     * @return EE_Base_Class[]
365
-     * @throws \EE_Error
366
-     */
367
-    public function remove_relations($this_obj_or_id, $where_query_param = array())
368
-    {
369
-        $related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
-        $objs_removed   = array();
371
-        foreach ($related_things as $related_thing) {
372
-            $objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
-        }
374
-        return $objs_removed;
375
-    }
376
-
377
-
378
-    /**
379
-     * If you aren't allowed to delete this model when there are related models across this
380
-     * relation object, return true. Otherwise, if you can delete this model even though
381
-     * related objects exist, returns false.
382
-     *
383
-     * @return boolean
384
-     */
385
-    public function block_delete_if_related_models_exist()
386
-    {
387
-        return $this->_blocking_delete;
388
-    }
389
-
390
-
391
-    /**
392
-     * Gets the error message to show
393
-     *
394
-     * @return string
395
-     */
396
-    public function get_deletion_error_message()
397
-    {
398
-        if ($this->_blocking_delete_error_message) {
399
-            return $this->_blocking_delete_error_message;
400
-        } else {
18
+	/**
19
+	 * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
+	 *
21
+	 * @var string eg Event, Question_Group, Registration
22
+	 */
23
+	private $_this_model_name;
24
+	/**
25
+	 * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
+	 *
27
+	 * @var string eg Event, Question_Group, Registration
28
+	 */
29
+	private $_other_model_name;
30
+
31
+	/**
32
+	 * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
+	 * initiating model.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $_timezone;
38
+
39
+	/**
40
+	 * If you try to delete "this_model", and there are related "other_models",
41
+	 * and this isn't null, then abandon the deletion and add this warning.
42
+	 * This effectively makes it impossible to delete "this_model" while there are
43
+	 * related "other_models" along this relation.
44
+	 *
45
+	 * @var string (internationalized)
46
+	 */
47
+	protected $_blocking_delete_error_message;
48
+
49
+	protected $_blocking_delete = false;
50
+
51
+	/**
52
+	 * Object representing the relationship between two models. This knows how to join the models,
53
+	 * get related models across the relation, and add-and-remove the relationships.
54
+	 *
55
+	 * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
+	 *                                               and add an error) the deletion of this model
57
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
+	 *                                               default
59
+	 */
60
+	public function __construct($block_deletes, $blocking_delete_error_message)
61
+	{
62
+		$this->_blocking_delete               = $block_deletes;
63
+		$this->_blocking_delete_error_message = $blocking_delete_error_message;
64
+	}
65
+
66
+
67
+	/**
68
+	 * @param $this_model_name
69
+	 * @param $other_model_name
70
+	 * @throws EE_Error
71
+	 */
72
+	public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
+	{
74
+		$this->_this_model_name  = $this_model_name;
75
+		$this->_other_model_name = $other_model_name;
76
+		if (is_string($this->_blocking_delete)) {
77
+			throw new EE_Error(sprintf(
78
+				__(
79
+					"When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
+					"event_espresso"
81
+				),
82
+				get_class($this),
83
+				$this_model_name,
84
+				$other_model_name,
85
+				$this->_blocking_delete
86
+			));
87
+		}
88
+	}
89
+
90
+
91
+	/**
92
+	 * Gets the model where this relation is defined.
93
+	 *
94
+	 * @return EEM_Base
95
+	 */
96
+	public function get_this_model()
97
+	{
98
+		return $this->_get_model($this->_this_model_name);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Gets the model which this relation establishes the relation TO (ie,
104
+	 * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
+	 *
106
+	 * @return EEM_Base
107
+	 */
108
+	public function get_other_model()
109
+	{
110
+		return $this->_get_model($this->_other_model_name);
111
+	}
112
+
113
+
114
+	/**
115
+	 * Internally used by get_this_model() and get_other_model()
116
+	 *
117
+	 * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
+	 * @return EEM_Base
119
+	 */
120
+	protected function _get_model($model_name)
121
+	{
122
+		$modelInstance = EE_Registry::instance()->load_model($model_name);
123
+		$modelInstance->set_timezone($this->_timezone);
124
+		return $modelInstance;
125
+	}
126
+
127
+
128
+	/**
129
+	 * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
+	 * timezone set correctly.
131
+	 *
132
+	 * @param string $timezone timezone to set.
133
+	 */
134
+	public function set_timezone($timezone)
135
+	{
136
+		if ($timezone !== null) {
137
+			$this->_timezone = $timezone;
138
+		}
139
+	}
140
+
141
+
142
+	/**
143
+	 * @param        $other_table
144
+	 * @param        $other_table_alias
145
+	 * @param        $other_table_column
146
+	 * @param        $this_table_alias
147
+	 * @param        $this_table_join_column
148
+	 * @param string $extra_join_sql
149
+	 * @return string
150
+	 */
151
+	protected function _left_join(
152
+		$other_table,
153
+		$other_table_alias,
154
+		$other_table_column,
155
+		$this_table_alias,
156
+		$this_table_join_column,
157
+		$extra_join_sql = ''
158
+	) {
159
+		return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
+	}
161
+
162
+
163
+	/**
164
+	 * Gets all the model objects of type of other model related to $model_object,
165
+	 * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
+	 * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
+	 * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
+	 * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
+	 *
170
+	 * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
+	 * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
+	 * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
+	 * @return EE_Base_Class[]
174
+	 * @throws \EE_Error
175
+	 */
176
+	public function get_all_related(
177
+		$model_object_or_id,
178
+		$query_params = array(),
179
+		$values_already_prepared_by_model_object = false
180
+	) {
181
+		if ($values_already_prepared_by_model_object !== false) {
182
+			EE_Error::doing_it_wrong(
183
+				'EE_Model_Relation_Base::get_all_related',
184
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
+				'4.8.1'
186
+			);
187
+		}
188
+		$query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
+		$query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
+															 . "."
191
+															 . $this->get_this_model()->get_primary_key_field()->get_name();
192
+		$model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
+		$query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
+		return $this->get_other_model()->get_all($query_params);
195
+	}
196
+
197
+
198
+	/**
199
+	 * Alters the $query_params to disable default where conditions, unless otherwise specified
200
+	 *
201
+	 * @param string $query_params
202
+	 * @return array
203
+	 */
204
+	protected function _disable_default_where_conditions_on_query_param($query_params)
205
+	{
206
+		if (! isset($query_params['default_where_conditions'])) {
207
+			$query_params['default_where_conditions'] = 'none';
208
+		}
209
+		return $query_params;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Deletes the related model objects which meet the query parameters. If no
215
+	 * parameters are specified, then all related model objects will be deleted.
216
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
+	 * model objects will only be soft-deleted.
218
+	 *
219
+	 * @param EE_Base_Class|int|string $model_object_or_id
220
+	 * @param array                    $query_params
221
+	 * @return int of how many related models got deleted
222
+	 * @throws \EE_Error
223
+	 */
224
+	public function delete_all_related($model_object_or_id, $query_params = array())
225
+	{
226
+		// for each thing we would delete,
227
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
+		// determine if it's blocked by anything else before it can be deleted
229
+		$deleted_count = 0;
230
+		foreach ($related_model_objects as $related_model_object) {
231
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
+				$related_model_object,
233
+				$model_object_or_id
234
+			);
235
+			/* @var $model_object_or_id EE_Base_Class */
236
+			if (! $delete_is_blocked) {
237
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
238
+				$related_model_object->delete();
239
+				$deleted_count++;
240
+			}
241
+		}
242
+		return $deleted_count;
243
+	}
244
+
245
+
246
+	/**
247
+	 * Deletes the related model objects which meet the query parameters. If no
248
+	 * parameters are specified, then all related model objects will be deleted.
249
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
+	 * model objects will only be soft-deleted.
251
+	 *
252
+	 * @param EE_Base_Class|int|string $model_object_or_id
253
+	 * @param array                    $query_params
254
+	 * @return int of how many related models got deleted
255
+	 * @throws \EE_Error
256
+	 */
257
+	public function delete_related_permanently($model_object_or_id, $query_params = array())
258
+	{
259
+		// for each thing we would delete,
260
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
+		// determine if it's blocked by anything else before it can be deleted
262
+		$deleted_count = 0;
263
+		foreach ($related_model_objects as $related_model_object) {
264
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
+				$related_model_object,
266
+				$model_object_or_id
267
+			);
268
+			/* @var $model_object_or_id EE_Base_Class */
269
+			if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
271
+				$deleted_count++;
272
+				if (! $delete_is_blocked) {
273
+					$related_model_object->delete_permanently();
274
+				} else {
275
+					// delete is blocked
276
+					// brent and darren, in this case, wanted to just soft delete it then
277
+					$related_model_object->delete();
278
+				}
279
+			} else {
280
+				// its not a soft-deletable thing anyways. do the normal logic.
281
+				if (! $delete_is_blocked) {
282
+					$this->remove_relation_to($model_object_or_id, $related_model_object);
283
+					$related_model_object->delete();
284
+					$deleted_count++;
285
+				}
286
+			}
287
+		}
288
+		return $deleted_count;
289
+	}
290
+
291
+
292
+	/**
293
+	 * this just returns a model_object_id for incoming item that could be an object or id.
294
+	 *
295
+	 * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
+	 * @throws EE_Error
297
+	 * @return int
298
+	 */
299
+	protected function _get_model_object_id($model_object_or_id)
300
+	{
301
+		$model_object_id = $model_object_or_id;
302
+		if ($model_object_or_id instanceof EE_Base_Class) {
303
+			$model_object_id = $model_object_or_id->ID();
304
+		}
305
+		if (! $model_object_id) {
306
+			throw new EE_Error(sprintf(
307
+				__(
308
+					"Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
+					"event_espresso"
310
+				),
311
+				$this->get_other_model()->get_this_model_name(),
312
+				$this->get_this_model()->get_this_model_name()
313
+			));
314
+		}
315
+		return $model_object_id;
316
+	}
317
+
318
+
319
+	/**
320
+	 * Gets the SQL string for performing the join between this model and the other model.
321
+	 *
322
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
+	 * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
+	 *                other_model_primary_table.fk" etc
325
+	 */
326
+	abstract public function get_join_statement($model_relation_chain);
327
+
328
+
329
+	/**
330
+	 * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
+	 * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
+	 * relationship only allows this model to be related to a single other model of this type)
333
+	 *
334
+	 * @param       $this_obj_or_id
335
+	 * @param       $other_obj_or_id
336
+	 * @param array $extra_join_model_fields_n_values
337
+	 * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
+	 *                        $other_obj_or_id)
339
+	 */
340
+	abstract public function add_relation_to(
341
+		$this_obj_or_id,
342
+		$other_obj_or_id,
343
+		$extra_join_model_fields_n_values = array()
344
+	);
345
+
346
+
347
+	/**
348
+	 * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
+	 * model objects
350
+	 *
351
+	 * @param       $this_obj_or_id
352
+	 * @param       $other_obj_or_id
353
+	 * @param array $where_query
354
+	 * @return bool
355
+	 */
356
+	abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
+
358
+
359
+	/**
360
+	 * Removes ALL relation instances for this relation obj
361
+	 *
362
+	 * @param EE_Base_Class|int $this_obj_or_id
363
+	 * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
+	 * @return EE_Base_Class[]
365
+	 * @throws \EE_Error
366
+	 */
367
+	public function remove_relations($this_obj_or_id, $where_query_param = array())
368
+	{
369
+		$related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
+		$objs_removed   = array();
371
+		foreach ($related_things as $related_thing) {
372
+			$objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
+		}
374
+		return $objs_removed;
375
+	}
376
+
377
+
378
+	/**
379
+	 * If you aren't allowed to delete this model when there are related models across this
380
+	 * relation object, return true. Otherwise, if you can delete this model even though
381
+	 * related objects exist, returns false.
382
+	 *
383
+	 * @return boolean
384
+	 */
385
+	public function block_delete_if_related_models_exist()
386
+	{
387
+		return $this->_blocking_delete;
388
+	}
389
+
390
+
391
+	/**
392
+	 * Gets the error message to show
393
+	 *
394
+	 * @return string
395
+	 */
396
+	public function get_deletion_error_message()
397
+	{
398
+		if ($this->_blocking_delete_error_message) {
399
+			return $this->_blocking_delete_error_message;
400
+		} else {
401 401
 //          return sprintf(__('Cannot delete %1$s when there are related %2$s', "event_espresso"),$this->get_this_model()->item_name(2),$this->get_other_model()->item_name(2));
402
-            return sprintf(
403
-                __(
404
-                    'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
-                    "event_espresso"
406
-                ),
407
-                $this->get_this_model()->item_name(1),
408
-                $this->get_other_model()->item_name(1),
409
-                $this->get_other_model()->item_name(2)
410
-            );
411
-        }
412
-    }
413
-
414
-    /**
415
-     * Returns whatever is set as the nicename for the object.
416
-     *
417
-     * @return string
418
-     */
419
-    public function getSchemaDescription()
420
-    {
421
-        $description = $this instanceof EE_Belongs_To_Relation
422
-            ? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
-            : esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
-        return sprintf(
425
-            $description,
426
-            $this->get_other_model()->get_this_model_name(),
427
-            $this->get_this_model()->get_this_model_name()
428
-        );
429
-    }
430
-
431
-    /**
432
-     * Returns whatever is set as the $_schema_type property for the object.
433
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
-     *
435
-     * @return string|array
436
-     */
437
-    public function getSchemaType()
438
-    {
439
-        return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
-    }
441
-
442
-    /**
443
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
-     * this method and return the properties for the schema.
445
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
446
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
-     *
448
-     * @return array
449
-     */
450
-    public function getSchemaProperties()
451
-    {
452
-        return array();
453
-    }
454
-
455
-    /**
456
-     * If a child class has enum values, they should override this method and provide a simple array
457
-     * of the enum values.
458
-     * The reason this is not a property on the class is because there may be filterable enum values that
459
-     * are set on the instantiated object that could be filtered after construct.
460
-     *
461
-     * @return array
462
-     */
463
-    public function getSchemaEnum()
464
-    {
465
-        return array();
466
-    }
467
-
468
-    /**
469
-     * This returns the value of the $_schema_format property on the object.
470
-     *
471
-     * @return string
472
-     */
473
-    public function getSchemaFormat()
474
-    {
475
-        return array();
476
-    }
477
-
478
-    /**
479
-     * This returns the value of the $_schema_readonly property on the object.
480
-     *
481
-     * @return bool
482
-     */
483
-    public function getSchemaReadonly()
484
-    {
485
-        return true;
486
-    }
487
-
488
-    /**
489
-     * This returns elements used to represent this field in the json schema.
490
-     *
491
-     * @link http://json-schema.org/
492
-     * @return array
493
-     */
494
-    public function getSchema()
495
-    {
496
-        $schema = array(
497
-            'description' => $this->getSchemaDescription(),
498
-            'type' => $this->getSchemaType(),
499
-            'relation' => true,
500
-            'relation_type' => get_class($this),
501
-            'readonly' => $this->getSchemaReadonly()
502
-        );
503
-
504
-        if ($this instanceof EE_HABTM_Relation) {
505
-            $schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
-        }
507
-
508
-        if ($this->getSchemaType() === 'array') {
509
-            $schema['items'] = array(
510
-                'type' => 'object'
511
-            );
512
-        }
513
-
514
-        return $schema;
515
-    }
402
+			return sprintf(
403
+				__(
404
+					'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
+					"event_espresso"
406
+				),
407
+				$this->get_this_model()->item_name(1),
408
+				$this->get_other_model()->item_name(1),
409
+				$this->get_other_model()->item_name(2)
410
+			);
411
+		}
412
+	}
413
+
414
+	/**
415
+	 * Returns whatever is set as the nicename for the object.
416
+	 *
417
+	 * @return string
418
+	 */
419
+	public function getSchemaDescription()
420
+	{
421
+		$description = $this instanceof EE_Belongs_To_Relation
422
+			? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
+			: esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
+		return sprintf(
425
+			$description,
426
+			$this->get_other_model()->get_this_model_name(),
427
+			$this->get_this_model()->get_this_model_name()
428
+		);
429
+	}
430
+
431
+	/**
432
+	 * Returns whatever is set as the $_schema_type property for the object.
433
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
+	 *
435
+	 * @return string|array
436
+	 */
437
+	public function getSchemaType()
438
+	{
439
+		return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
+	}
441
+
442
+	/**
443
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
+	 * this method and return the properties for the schema.
445
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
446
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
+	 *
448
+	 * @return array
449
+	 */
450
+	public function getSchemaProperties()
451
+	{
452
+		return array();
453
+	}
454
+
455
+	/**
456
+	 * If a child class has enum values, they should override this method and provide a simple array
457
+	 * of the enum values.
458
+	 * The reason this is not a property on the class is because there may be filterable enum values that
459
+	 * are set on the instantiated object that could be filtered after construct.
460
+	 *
461
+	 * @return array
462
+	 */
463
+	public function getSchemaEnum()
464
+	{
465
+		return array();
466
+	}
467
+
468
+	/**
469
+	 * This returns the value of the $_schema_format property on the object.
470
+	 *
471
+	 * @return string
472
+	 */
473
+	public function getSchemaFormat()
474
+	{
475
+		return array();
476
+	}
477
+
478
+	/**
479
+	 * This returns the value of the $_schema_readonly property on the object.
480
+	 *
481
+	 * @return bool
482
+	 */
483
+	public function getSchemaReadonly()
484
+	{
485
+		return true;
486
+	}
487
+
488
+	/**
489
+	 * This returns elements used to represent this field in the json schema.
490
+	 *
491
+	 * @link http://json-schema.org/
492
+	 * @return array
493
+	 */
494
+	public function getSchema()
495
+	{
496
+		$schema = array(
497
+			'description' => $this->getSchemaDescription(),
498
+			'type' => $this->getSchemaType(),
499
+			'relation' => true,
500
+			'relation_type' => get_class($this),
501
+			'readonly' => $this->getSchemaReadonly()
502
+		);
503
+
504
+		if ($this instanceof EE_HABTM_Relation) {
505
+			$schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
+		}
507
+
508
+		if ($this->getSchemaType() === 'array') {
509
+			$schema['items'] = array(
510
+				'type' => 'object'
511
+			);
512
+		}
513
+
514
+		return $schema;
515
+	}
516 516
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Model_Field_Base.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -582,7 +582,7 @@
 block discarded – undo
582 582
     /**
583 583
      * Validates that the incoming format is an allowable string to use for the _schema_format property
584 584
      * @throws InvalidArgumentException
585
-     * @param $format
585
+     * @param string $format
586 586
      */
587 587
     private function validateSchemaFormat($format)
588 588
     {
Please login to merge, or discard this patch.
Indentation   +646 added lines, -647 removed lines patch added patch discarded remove patch
@@ -19,651 +19,650 @@
 block discarded – undo
19 19
  */
20 20
 abstract class EE_Model_Field_Base implements HasSchemaInterface
21 21
 {
22
-    /**
23
-     * The alias for the table the column belongs to.
24
-     * @var string
25
-     */
26
-    protected $_table_alias;
27
-
28
-    /**
29
-     * The actual db column name for the table
30
-     * @var string
31
-     */
32
-    protected $_table_column;
33
-
34
-
35
-    /**
36
-     * The authoritative name for the table column (used by client code to reference the field).
37
-     * @var string
38
-     */
39
-    protected $_name;
40
-
41
-
42
-    /**
43
-     * A description for the field.
44
-     * @var string
45
-     */
46
-    protected $_nicename;
47
-
48
-
49
-    /**
50
-     * Whether the field is nullable or not
51
-     * @var bool
52
-     */
53
-    protected $_nullable;
54
-
55
-
56
-    /**
57
-     * What the default value for the field should be.
58
-     * @var mixed
59
-     */
60
-    protected $_default_value;
61
-
62
-
63
-    /**
64
-     * Other configuration for the field
65
-     * @var mixed
66
-     */
67
-    protected $_other_config;
68
-
69
-
70
-    /**
71
-     * The name of the model this field is instantiated for.
72
-     * @var string
73
-     */
74
-    protected $_model_name;
75
-
76
-
77
-    /**
78
-     * This should be a json-schema valid data type for the field.
79
-     * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
80
-     * @var string
81
-     */
82
-    private $_schema_type = 'string';
83
-
84
-
85
-    /**
86
-     * If the schema has a defined format then it should be defined via this property.
87
-     * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
88
-     * @var string
89
-     */
90
-    private $_schema_format = '';
91
-
92
-
93
-    /**
94
-     * Indicates that the value of the field is managed exclusively by the server/model and not something
95
-     * settable by client code.
96
-     * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
97
-     * @var bool
98
-     */
99
-    private $_schema_readonly = false;
100
-
101
-
102
-    /**
103
-     * @param string $table_column
104
-     * @param string $nicename
105
-     * @param bool   $nullable
106
-     * @param null   $default_value
107
-     */
108
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
109
-    {
110
-        $this->_table_column  = $table_column;
111
-        $this->_nicename      = $nicename;
112
-        $this->_nullable      = $nullable;
113
-        $this->_default_value = $default_value;
114
-    }
115
-
116
-
117
-    /**
118
-     * @param $table_alias
119
-     * @param $name
120
-     * @param $model_name
121
-     */
122
-    public function _construct_finalize($table_alias, $name, $model_name)
123
-    {
124
-        $this->_table_alias = $table_alias;
125
-        $this->_name        = $name;
126
-        $this->_model_name  = $model_name;
127
-        /**
128
-         * allow for changing the defaults
129
-         */
130
-        $this->_nicename      = apply_filters(
131
-            'FHEE__EE_Model_Field_Base___construct_finalize___nicename',
132
-            $this->_nicename,
133
-            $this
134
-        );
135
-        $this->_default_value = apply_filters(
136
-            'FHEE__EE_Model_Field_Base___construct_finalize___default_value',
137
-            $this->_default_value,
138
-            $this
139
-        );
140
-    }
141
-
142
-    public function get_table_alias()
143
-    {
144
-        return $this->_table_alias;
145
-    }
146
-
147
-    public function get_table_column()
148
-    {
149
-        return $this->_table_column;
150
-    }
151
-
152
-    /**
153
-     * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
154
-     *
155
-     * @return string
156
-     */
157
-    public function get_model_name()
158
-    {
159
-        return $this->_model_name;
160
-    }
161
-
162
-    /**
163
-     * @throws \EE_Error
164
-     * @return string
165
-     */
166
-    public function get_name()
167
-    {
168
-        if ($this->_name) {
169
-            return $this->_name;
170
-        } else {
171
-            throw new EE_Error(sprintf(__(
172
-                "Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
173
-                "event_espresso"
174
-            ), get_class($this)));
175
-        }
176
-    }
177
-
178
-    public function get_nicename()
179
-    {
180
-        return $this->_nicename;
181
-    }
182
-
183
-    public function is_nullable()
184
-    {
185
-        return $this->_nullable;
186
-    }
187
-
188
-    /**
189
-     * returns whether this field is an auto-increment field or not. If it is, then
190
-     * on insertion it can be null. However, on updates it must be present.
191
-     *
192
-     * @return boolean
193
-     */
194
-    public function is_auto_increment()
195
-    {
196
-        return false;
197
-    }
198
-
199
-    /**
200
-     * The default value in the model object's value domain. See lengthy comment about
201
-     * value domains at the top of EEM_Base
202
-     *
203
-     * @return mixed
204
-     */
205
-    public function get_default_value()
206
-    {
207
-        return $this->_default_value;
208
-    }
209
-
210
-    /**
211
-     * Returns the table alias joined to the table column, however this isn't the right
212
-     * table alias if the aliased table is being joined to. In that case, you can use
213
-     * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
214
-     * in the current query
215
-     *
216
-     * @return string
217
-     */
218
-    public function get_qualified_column()
219
-    {
220
-        return $this->get_table_alias() . "." . $this->get_table_column();
221
-    }
222
-
223
-    /**
224
-     * When get() is called on a model object (eg EE_Event), before returning its value,
225
-     * call this function on it, allowing us to customize the returned value based on
226
-     * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
227
-     * we simply return it.
228
-     *
229
-     * @param mixed $value_of_field_on_model_object
230
-     * @return mixed
231
-     */
232
-    public function prepare_for_get($value_of_field_on_model_object)
233
-    {
234
-        return $value_of_field_on_model_object;
235
-    }
236
-
237
-    /**
238
-     * When inserting or updating a field on a model object, run this function on each
239
-     * value to prepare it for insertion into the db. Generally this converts
240
-     * the validated input on the model object into the format used in the DB.
241
-     *
242
-     * @param mixed $value_of_field_on_model_object
243
-     * @return mixed
244
-     */
245
-    public function prepare_for_use_in_db($value_of_field_on_model_object)
246
-    {
247
-        return $value_of_field_on_model_object;
248
-    }
249
-
250
-    /**
251
-     * When creating a brand-new model object, or setting a particular value for one of its fields, this function
252
-     * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
253
-     * By default, we do nothing.
254
-     *
255
-     * If the model field is going to perform any validation on the input, this is where it should be done
256
-     * (once the value is on the model object, it may be used in other ways besides putting it into the DB
257
-     * so it's best to validate it right away).
258
-     *
259
-     * @param mixed $value_inputted_for_field_on_model_object
260
-     * @return mixed
261
-     */
262
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
263
-    {
264
-        return $value_inputted_for_field_on_model_object;
265
-    }
266
-
267
-
268
-    /**
269
-     * When instantiating a model object from DB results, this function is called before setting each field.
270
-     * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
271
-     * is the one child classes will most often define.
272
-     *
273
-     * @param mixed $value_found_in_db_for_model_object
274
-     * @return mixed
275
-     */
276
-    public function prepare_for_set_from_db($value_found_in_db_for_model_object)
277
-    {
278
-        return $this->prepare_for_set($value_found_in_db_for_model_object);
279
-    }
280
-
281
-    /**
282
-     * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
283
-     * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
284
-     * 2013, at 3:23pm" instead of
285
-     * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
286
-     *
287
-     * @param mixed $value_on_field_to_be_outputted
288
-     * @return mixed
289
-     */
290
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
291
-    {
292
-        return $value_on_field_to_be_outputted;
293
-    }
294
-
295
-
296
-    /**
297
-     * Returns whatever is set as the nicename for the object.
298
-     * @return string
299
-     */
300
-    public function getSchemaDescription()
301
-    {
302
-        return $this->get_nicename();
303
-    }
304
-
305
-
306
-    /**
307
-     * Returns whatever is set as the $_schema_type property for the object.
308
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
309
-     * @return string|array
310
-     */
311
-    public function getSchemaType()
312
-    {
313
-        if ($this->is_nullable()) {
314
-            $this->_schema_type = (array) $this->_schema_type;
315
-            if (! in_array('null', $this->_schema_type)) {
316
-                $this->_schema_type[] = 'null';
317
-            };
318
-        }
319
-        return $this->_schema_type;
320
-    }
321
-
322
-
323
-    /**
324
-     * Sets the _schema_type property.  Child classes should call this in their constructors to override the default state
325
-     * for this property.
326
-     * @param string|array $type
327
-     * @throws InvalidArgumentException
328
-     */
329
-    protected function setSchemaType($type)
330
-    {
331
-        $this->validateSchemaType($type);
332
-        $this->_schema_type = $type;
333
-    }
334
-
335
-
336
-    /**
337
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
338
-     * this method and return the properties for the schema.
339
-     *
340
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
341
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
342
-     *
343
-     * @return array
344
-     */
345
-    public function getSchemaProperties()
346
-    {
347
-        return array();
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * By default this returns the scalar default value that was sent in on the class prepped according to the class type
354
-     * as the default.  However, when there are schema properties, then the default property is setup to mirror the
355
-     * property keys and correctly prepare the default according to that expected property value.
356
-     * The getSchema method validates whether the schema for default is setup correctly or not according to the schema type
357
-     *
358
-     * @return mixed
359
-     */
360
-    public function getSchemaDefault()
361
-    {
362
-        $default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
363
-        $schema_properties = $this->getSchemaProperties();
364
-
365
-        // if this schema has properties than shape the default value to match the properties shape.
366
-        if ($schema_properties) {
367
-            $value_to_return = array();
368
-            foreach ($schema_properties as $property_key => $property_schema) {
369
-                switch ($property_key) {
370
-                    case 'pretty':
371
-                    case 'rendered':
372
-                        $value_to_return[ $property_key ] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
373
-                        break;
374
-                    default:
375
-                        $value_to_return[ $property_key ] = $default_value;
376
-                        break;
377
-                }
378
-            }
379
-            $default_value = $value_to_return;
380
-        }
381
-        return $default_value;
382
-    }
383
-
384
-
385
-
386
-
387
-    /**
388
-     * If a child class has enum values, they should override this method and provide a simple array
389
-     * of the enum values.
390
-
391
-     * The reason this is not a property on the class is because there may be filterable enum values that
392
-     * are set on the instantiated object that could be filtered after construct.
393
-     *
394
-     * @return array
395
-     */
396
-    public function getSchemaEnum()
397
-    {
398
-        return array();
399
-    }
400
-
401
-
402
-    /**
403
-     * This returns the value of the $_schema_format property on the object.
404
-     * @return string
405
-     */
406
-    public function getSchemaFormat()
407
-    {
408
-        return $this->_schema_format;
409
-    }
410
-
411
-
412
-    /**
413
-     * Sets the schema format property.
414
-     * @throws InvalidArgumentException
415
-     * @param string $format
416
-     */
417
-    protected function setSchemaFormat($format)
418
-    {
419
-        $this->validateSchemaFormat($format);
420
-        $this->_schema_format = $format;
421
-    }
422
-
423
-
424
-    /**
425
-     * This returns the value of the $_schema_readonly property on the object.
426
-     * @return bool
427
-     */
428
-    public function getSchemaReadonly()
429
-    {
430
-        return $this->_schema_readonly;
431
-    }
432
-
433
-
434
-    /**
435
-     * This sets the value for the $_schema_readonly property.
436
-     * @param bool $readonly  (only explicit boolean values are accepted)
437
-     */
438
-    protected function setSchemaReadOnly($readonly)
439
-    {
440
-        if (! is_bool($readonly)) {
441
-            throw new InvalidArgumentException(
442
-                sprintf(
443
-                    esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
444
-                    print_r($readonly, true)
445
-                )
446
-            );
447
-        }
448
-
449
-        $this->_schema_readonly = $readonly;
450
-    }
451
-
452
-
453
-
454
-
455
-    /**
456
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field.
457
-     * @uses _get_wpdb_data_type()
458
-     *
459
-     * @return string
460
-     */
461
-    public function get_wpdb_data_type()
462
-    {
463
-        return $this->_get_wpdb_data_type();
464
-    }
465
-
466
-
467
-    /**
468
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
469
-     * @param string $type  Included if a specific type is requested.
470
-     * @uses get_schema_type()
471
-     * @return string
472
-     */
473
-    protected function _get_wpdb_data_type($type = '')
474
-    {
475
-        $type = empty($type) ? $this->getSchemaType() : $type;
476
-
477
-        // if type is an array, then different parsing is required.
478
-        if (is_array($type)) {
479
-            return $this->_get_wpdb_data_type_for_type_array($type);
480
-        }
481
-
482
-        $wpdb_type = '%s';
483
-        switch ($type) {
484
-            case 'number':
485
-                $wpdb_type = '%f';
486
-                break;
487
-            case 'integer':
488
-            case 'boolean':
489
-                $wpdb_type = '%d';
490
-                break;
491
-            case 'object':
492
-                $properties = $this->getSchemaProperties();
493
-                if (isset($properties['raw'], $properties['raw']['type'])) {
494
-                    $wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
495
-                }
496
-                break; // leave at default
497
-        }
498
-        return $wpdb_type;
499
-    }
500
-
501
-
502
-
503
-    protected function _get_wpdb_data_type_for_type_array($type)
504
-    {
505
-        $type = (array) $type;
506
-        // first let's flip because then we can do a faster key check
507
-        $type = array_flip($type);
508
-
509
-        // check for things that mean '%s'
510
-        if (isset($type['string'], $type['object'], $type['array'])) {
511
-            return '%s';
512
-        }
513
-
514
-        // if makes it past the above condition and there's float in the array
515
-        // then the type is %f
516
-        if (isset($type['number'])) {
517
-            return '%f';
518
-        }
519
-
520
-        // if it makes it above the above conditions and there is an integer in the array
521
-        // then the type is %d
522
-        if (isset($type['integer'])) {
523
-            return '%d';
524
-        }
525
-
526
-        // anything else is a string
527
-        return '%s';
528
-    }
529
-
530
-
531
-    /**
532
-     * This returns elements used to represent this field in the json schema.
533
-     *
534
-     * @link http://json-schema.org/
535
-     * @return array
536
-     */
537
-    public function getSchema()
538
-    {
539
-        $schema = array(
540
-            'description' => $this->getSchemaDescription(),
541
-            'type' => $this->getSchemaType(),
542
-            'readonly' => $this->getSchemaReadonly(),
543
-            'default' => $this->getSchemaDefault()
544
-        );
545
-
546
-        // optional properties of the schema
547
-        $enum = $this->getSchemaEnum();
548
-        $properties = $this->getSchemaProperties();
549
-        $format = $this->getSchemaFormat();
550
-        if ($enum) {
551
-            $schema['enum'] = $enum;
552
-        }
553
-
554
-        if ($properties) {
555
-            $schema['properties'] = $properties;
556
-        }
557
-
558
-        if ($format) {
559
-            $schema['format'] = $format;
560
-        }
561
-        return $schema;
562
-    }
563
-
564
-    /**
565
-     * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
566
-     * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
567
-     * want to see their value, then they shouldn't be db-only fields!)
568
-     * Eg, when doing events as custom post types, querying the post_type is essential, but
569
-     * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
570
-     * By default, all fields aren't db-only.
571
-     *
572
-     * @return boolean
573
-     */
574
-    public function is_db_only_field()
575
-    {
576
-        return false;
577
-    }
578
-
579
-
580
-    /**
581
-     * Validates the incoming string|array to ensure its an allowable type.
582
-     * @throws InvalidArgumentException
583
-     * @param string|array $type
584
-     */
585
-    private function validateSchemaType($type)
586
-    {
587
-        if (! (is_string($type) || is_array($type))) {
588
-            throw new InvalidArgumentException(
589
-                sprintf(
590
-                    esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
591
-                    print_r($type, true)
592
-                )
593
-            );
594
-        }
595
-
596
-        // validate allowable types.
597
-        // @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
598
-        $allowable_types = array_flip(
599
-            array(
600
-                'string',
601
-                'number',
602
-                'null',
603
-                'object',
604
-                'array',
605
-                'boolean',
606
-                'integer'
607
-            )
608
-        );
609
-
610
-        if (is_array($type)) {
611
-            foreach ($type as $item_in_type) {
612
-                $this->validateSchemaType($item_in_type);
613
-            }
614
-            return;
615
-        }
616
-
617
-        if (! isset($allowable_types[ $type ])) {
618
-            throw new InvalidArgumentException(
619
-                sprintf(
620
-                    esc_html__('The incoming argument (%1$s) must be one of the allowable types: %2$s', 'event_espresso'),
621
-                    $type,
622
-                    implode(',', array_flip($allowable_types))
623
-                )
624
-            );
625
-        }
626
-    }
627
-
628
-
629
-    /**
630
-     * Validates that the incoming format is an allowable string to use for the _schema_format property
631
-     * @throws InvalidArgumentException
632
-     * @param $format
633
-     */
634
-    private function validateSchemaFormat($format)
635
-    {
636
-        if (! is_string($format)) {
637
-            throw new InvalidArgumentException(
638
-                sprintf(
639
-                    esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
640
-                    print_r($format, true)
641
-                )
642
-            );
643
-        }
644
-
645
-        // validate allowable format values
646
-        // @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
647
-        $allowable_formats = array_flip(
648
-            array(
649
-                'date-time',
650
-                'email',
651
-                'hostname',
652
-                'ipv4',
653
-                'ipv6',
654
-                'uri',
655
-                'uriref'
656
-            )
657
-        );
658
-
659
-        if (! isset($allowable_formats[ $format ])) {
660
-            throw new InvalidArgumentException(
661
-                sprintf(
662
-                    esc_html__('The incoming argument (%1$s) must be one of the allowable formats: %2$s', 'event_espresso'),
663
-                    $format,
664
-                    implode(',', array_flip($allowable_formats))
665
-                )
666
-            );
667
-        }
668
-    }
22
+	/**
23
+	 * The alias for the table the column belongs to.
24
+	 * @var string
25
+	 */
26
+	protected $_table_alias;
27
+
28
+	/**
29
+	 * The actual db column name for the table
30
+	 * @var string
31
+	 */
32
+	protected $_table_column;
33
+
34
+
35
+	/**
36
+	 * The authoritative name for the table column (used by client code to reference the field).
37
+	 * @var string
38
+	 */
39
+	protected $_name;
40
+
41
+
42
+	/**
43
+	 * A description for the field.
44
+	 * @var string
45
+	 */
46
+	protected $_nicename;
47
+
48
+
49
+	/**
50
+	 * Whether the field is nullable or not
51
+	 * @var bool
52
+	 */
53
+	protected $_nullable;
54
+
55
+
56
+	/**
57
+	 * What the default value for the field should be.
58
+	 * @var mixed
59
+	 */
60
+	protected $_default_value;
61
+
62
+
63
+	/**
64
+	 * Other configuration for the field
65
+	 * @var mixed
66
+	 */
67
+	protected $_other_config;
68
+
69
+
70
+	/**
71
+	 * The name of the model this field is instantiated for.
72
+	 * @var string
73
+	 */
74
+	protected $_model_name;
75
+
76
+
77
+	/**
78
+	 * This should be a json-schema valid data type for the field.
79
+	 * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
80
+	 * @var string
81
+	 */
82
+	private $_schema_type = 'string';
83
+
84
+
85
+	/**
86
+	 * If the schema has a defined format then it should be defined via this property.
87
+	 * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
88
+	 * @var string
89
+	 */
90
+	private $_schema_format = '';
91
+
92
+
93
+	/**
94
+	 * Indicates that the value of the field is managed exclusively by the server/model and not something
95
+	 * settable by client code.
96
+	 * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
97
+	 * @var bool
98
+	 */
99
+	private $_schema_readonly = false;
100
+
101
+
102
+	/**
103
+	 * @param string $table_column
104
+	 * @param string $nicename
105
+	 * @param bool   $nullable
106
+	 * @param null   $default_value
107
+	 */
108
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
109
+	{
110
+		$this->_table_column  = $table_column;
111
+		$this->_nicename      = $nicename;
112
+		$this->_nullable      = $nullable;
113
+		$this->_default_value = $default_value;
114
+	}
115
+
116
+
117
+	/**
118
+	 * @param $table_alias
119
+	 * @param $name
120
+	 * @param $model_name
121
+	 */
122
+	public function _construct_finalize($table_alias, $name, $model_name)
123
+	{
124
+		$this->_table_alias = $table_alias;
125
+		$this->_name        = $name;
126
+		$this->_model_name  = $model_name;
127
+		/**
128
+		 * allow for changing the defaults
129
+		 */
130
+		$this->_nicename      = apply_filters(
131
+			'FHEE__EE_Model_Field_Base___construct_finalize___nicename',
132
+			$this->_nicename,
133
+			$this
134
+		);
135
+		$this->_default_value = apply_filters(
136
+			'FHEE__EE_Model_Field_Base___construct_finalize___default_value',
137
+			$this->_default_value,
138
+			$this
139
+		);
140
+	}
141
+
142
+	public function get_table_alias()
143
+	{
144
+		return $this->_table_alias;
145
+	}
146
+
147
+	public function get_table_column()
148
+	{
149
+		return $this->_table_column;
150
+	}
151
+
152
+	/**
153
+	 * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
154
+	 *
155
+	 * @return string
156
+	 */
157
+	public function get_model_name()
158
+	{
159
+		return $this->_model_name;
160
+	}
161
+
162
+	/**
163
+	 * @throws \EE_Error
164
+	 * @return string
165
+	 */
166
+	public function get_name()
167
+	{
168
+		if ($this->_name) {
169
+			return $this->_name;
170
+		} else {
171
+			throw new EE_Error(sprintf(__(
172
+				"Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
173
+				"event_espresso"
174
+			), get_class($this)));
175
+		}
176
+	}
177
+
178
+	public function get_nicename()
179
+	{
180
+		return $this->_nicename;
181
+	}
182
+
183
+	public function is_nullable()
184
+	{
185
+		return $this->_nullable;
186
+	}
187
+
188
+	/**
189
+	 * returns whether this field is an auto-increment field or not. If it is, then
190
+	 * on insertion it can be null. However, on updates it must be present.
191
+	 *
192
+	 * @return boolean
193
+	 */
194
+	public function is_auto_increment()
195
+	{
196
+		return false;
197
+	}
198
+
199
+	/**
200
+	 * The default value in the model object's value domain. See lengthy comment about
201
+	 * value domains at the top of EEM_Base
202
+	 *
203
+	 * @return mixed
204
+	 */
205
+	public function get_default_value()
206
+	{
207
+		return $this->_default_value;
208
+	}
209
+
210
+	/**
211
+	 * Returns the table alias joined to the table column, however this isn't the right
212
+	 * table alias if the aliased table is being joined to. In that case, you can use
213
+	 * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
214
+	 * in the current query
215
+	 *
216
+	 * @return string
217
+	 */
218
+	public function get_qualified_column()
219
+	{
220
+		return $this->get_table_alias() . "." . $this->get_table_column();
221
+	}
222
+
223
+	/**
224
+	 * When get() is called on a model object (eg EE_Event), before returning its value,
225
+	 * call this function on it, allowing us to customize the returned value based on
226
+	 * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
227
+	 * we simply return it.
228
+	 *
229
+	 * @param mixed $value_of_field_on_model_object
230
+	 * @return mixed
231
+	 */
232
+	public function prepare_for_get($value_of_field_on_model_object)
233
+	{
234
+		return $value_of_field_on_model_object;
235
+	}
236
+
237
+	/**
238
+	 * When inserting or updating a field on a model object, run this function on each
239
+	 * value to prepare it for insertion into the db. Generally this converts
240
+	 * the validated input on the model object into the format used in the DB.
241
+	 *
242
+	 * @param mixed $value_of_field_on_model_object
243
+	 * @return mixed
244
+	 */
245
+	public function prepare_for_use_in_db($value_of_field_on_model_object)
246
+	{
247
+		return $value_of_field_on_model_object;
248
+	}
249
+
250
+	/**
251
+	 * When creating a brand-new model object, or setting a particular value for one of its fields, this function
252
+	 * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
253
+	 * By default, we do nothing.
254
+	 *
255
+	 * If the model field is going to perform any validation on the input, this is where it should be done
256
+	 * (once the value is on the model object, it may be used in other ways besides putting it into the DB
257
+	 * so it's best to validate it right away).
258
+	 *
259
+	 * @param mixed $value_inputted_for_field_on_model_object
260
+	 * @return mixed
261
+	 */
262
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
263
+	{
264
+		return $value_inputted_for_field_on_model_object;
265
+	}
266
+
267
+
268
+	/**
269
+	 * When instantiating a model object from DB results, this function is called before setting each field.
270
+	 * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
271
+	 * is the one child classes will most often define.
272
+	 *
273
+	 * @param mixed $value_found_in_db_for_model_object
274
+	 * @return mixed
275
+	 */
276
+	public function prepare_for_set_from_db($value_found_in_db_for_model_object)
277
+	{
278
+		return $this->prepare_for_set($value_found_in_db_for_model_object);
279
+	}
280
+
281
+	/**
282
+	 * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
283
+	 * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
284
+	 * 2013, at 3:23pm" instead of
285
+	 * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
286
+	 *
287
+	 * @param mixed $value_on_field_to_be_outputted
288
+	 * @return mixed
289
+	 */
290
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
291
+	{
292
+		return $value_on_field_to_be_outputted;
293
+	}
294
+
295
+
296
+	/**
297
+	 * Returns whatever is set as the nicename for the object.
298
+	 * @return string
299
+	 */
300
+	public function getSchemaDescription()
301
+	{
302
+		return $this->get_nicename();
303
+	}
304
+
305
+
306
+	/**
307
+	 * Returns whatever is set as the $_schema_type property for the object.
308
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
309
+	 * @return string|array
310
+	 */
311
+	public function getSchemaType()
312
+	{
313
+		if ($this->is_nullable()) {
314
+			$this->_schema_type = (array) $this->_schema_type;
315
+			if (! in_array('null', $this->_schema_type)) {
316
+				$this->_schema_type[] = 'null';
317
+			};
318
+		}
319
+		return $this->_schema_type;
320
+	}
321
+
322
+
323
+	/**
324
+	 * Sets the _schema_type property.  Child classes should call this in their constructors to override the default state
325
+	 * for this property.
326
+	 * @param string|array $type
327
+	 * @throws InvalidArgumentException
328
+	 */
329
+	protected function setSchemaType($type)
330
+	{
331
+		$this->validateSchemaType($type);
332
+		$this->_schema_type = $type;
333
+	}
334
+
335
+
336
+	/**
337
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
338
+	 * this method and return the properties for the schema.
339
+	 *
340
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
341
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
342
+	 *
343
+	 * @return array
344
+	 */
345
+	public function getSchemaProperties()
346
+	{
347
+		return array();
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * By default this returns the scalar default value that was sent in on the class prepped according to the class type
354
+	 * as the default.  However, when there are schema properties, then the default property is setup to mirror the
355
+	 * property keys and correctly prepare the default according to that expected property value.
356
+	 * The getSchema method validates whether the schema for default is setup correctly or not according to the schema type
357
+	 *
358
+	 * @return mixed
359
+	 */
360
+	public function getSchemaDefault()
361
+	{
362
+		$default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
363
+		$schema_properties = $this->getSchemaProperties();
364
+
365
+		// if this schema has properties than shape the default value to match the properties shape.
366
+		if ($schema_properties) {
367
+			$value_to_return = array();
368
+			foreach ($schema_properties as $property_key => $property_schema) {
369
+				switch ($property_key) {
370
+					case 'pretty':
371
+					case 'rendered':
372
+						$value_to_return[ $property_key ] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
373
+						break;
374
+					default:
375
+						$value_to_return[ $property_key ] = $default_value;
376
+						break;
377
+				}
378
+			}
379
+			$default_value = $value_to_return;
380
+		}
381
+		return $default_value;
382
+	}
383
+
384
+
385
+
386
+
387
+	/**
388
+	 * If a child class has enum values, they should override this method and provide a simple array
389
+	 * of the enum values.
390
+	 * The reason this is not a property on the class is because there may be filterable enum values that
391
+	 * are set on the instantiated object that could be filtered after construct.
392
+	 *
393
+	 * @return array
394
+	 */
395
+	public function getSchemaEnum()
396
+	{
397
+		return array();
398
+	}
399
+
400
+
401
+	/**
402
+	 * This returns the value of the $_schema_format property on the object.
403
+	 * @return string
404
+	 */
405
+	public function getSchemaFormat()
406
+	{
407
+		return $this->_schema_format;
408
+	}
409
+
410
+
411
+	/**
412
+	 * Sets the schema format property.
413
+	 * @throws InvalidArgumentException
414
+	 * @param string $format
415
+	 */
416
+	protected function setSchemaFormat($format)
417
+	{
418
+		$this->validateSchemaFormat($format);
419
+		$this->_schema_format = $format;
420
+	}
421
+
422
+
423
+	/**
424
+	 * This returns the value of the $_schema_readonly property on the object.
425
+	 * @return bool
426
+	 */
427
+	public function getSchemaReadonly()
428
+	{
429
+		return $this->_schema_readonly;
430
+	}
431
+
432
+
433
+	/**
434
+	 * This sets the value for the $_schema_readonly property.
435
+	 * @param bool $readonly  (only explicit boolean values are accepted)
436
+	 */
437
+	protected function setSchemaReadOnly($readonly)
438
+	{
439
+		if (! is_bool($readonly)) {
440
+			throw new InvalidArgumentException(
441
+				sprintf(
442
+					esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
443
+					print_r($readonly, true)
444
+				)
445
+			);
446
+		}
447
+
448
+		$this->_schema_readonly = $readonly;
449
+	}
450
+
451
+
452
+
453
+
454
+	/**
455
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field.
456
+	 * @uses _get_wpdb_data_type()
457
+	 *
458
+	 * @return string
459
+	 */
460
+	public function get_wpdb_data_type()
461
+	{
462
+		return $this->_get_wpdb_data_type();
463
+	}
464
+
465
+
466
+	/**
467
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
468
+	 * @param string $type  Included if a specific type is requested.
469
+	 * @uses get_schema_type()
470
+	 * @return string
471
+	 */
472
+	protected function _get_wpdb_data_type($type = '')
473
+	{
474
+		$type = empty($type) ? $this->getSchemaType() : $type;
475
+
476
+		// if type is an array, then different parsing is required.
477
+		if (is_array($type)) {
478
+			return $this->_get_wpdb_data_type_for_type_array($type);
479
+		}
480
+
481
+		$wpdb_type = '%s';
482
+		switch ($type) {
483
+			case 'number':
484
+				$wpdb_type = '%f';
485
+				break;
486
+			case 'integer':
487
+			case 'boolean':
488
+				$wpdb_type = '%d';
489
+				break;
490
+			case 'object':
491
+				$properties = $this->getSchemaProperties();
492
+				if (isset($properties['raw'], $properties['raw']['type'])) {
493
+					$wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
494
+				}
495
+				break; // leave at default
496
+		}
497
+		return $wpdb_type;
498
+	}
499
+
500
+
501
+
502
+	protected function _get_wpdb_data_type_for_type_array($type)
503
+	{
504
+		$type = (array) $type;
505
+		// first let's flip because then we can do a faster key check
506
+		$type = array_flip($type);
507
+
508
+		// check for things that mean '%s'
509
+		if (isset($type['string'], $type['object'], $type['array'])) {
510
+			return '%s';
511
+		}
512
+
513
+		// if makes it past the above condition and there's float in the array
514
+		// then the type is %f
515
+		if (isset($type['number'])) {
516
+			return '%f';
517
+		}
518
+
519
+		// if it makes it above the above conditions and there is an integer in the array
520
+		// then the type is %d
521
+		if (isset($type['integer'])) {
522
+			return '%d';
523
+		}
524
+
525
+		// anything else is a string
526
+		return '%s';
527
+	}
528
+
529
+
530
+	/**
531
+	 * This returns elements used to represent this field in the json schema.
532
+	 *
533
+	 * @link http://json-schema.org/
534
+	 * @return array
535
+	 */
536
+	public function getSchema()
537
+	{
538
+		$schema = array(
539
+			'description' => $this->getSchemaDescription(),
540
+			'type' => $this->getSchemaType(),
541
+			'readonly' => $this->getSchemaReadonly(),
542
+			'default' => $this->getSchemaDefault()
543
+		);
544
+
545
+		// optional properties of the schema
546
+		$enum = $this->getSchemaEnum();
547
+		$properties = $this->getSchemaProperties();
548
+		$format = $this->getSchemaFormat();
549
+		if ($enum) {
550
+			$schema['enum'] = $enum;
551
+		}
552
+
553
+		if ($properties) {
554
+			$schema['properties'] = $properties;
555
+		}
556
+
557
+		if ($format) {
558
+			$schema['format'] = $format;
559
+		}
560
+		return $schema;
561
+	}
562
+
563
+	/**
564
+	 * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
565
+	 * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
566
+	 * want to see their value, then they shouldn't be db-only fields!)
567
+	 * Eg, when doing events as custom post types, querying the post_type is essential, but
568
+	 * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
569
+	 * By default, all fields aren't db-only.
570
+	 *
571
+	 * @return boolean
572
+	 */
573
+	public function is_db_only_field()
574
+	{
575
+		return false;
576
+	}
577
+
578
+
579
+	/**
580
+	 * Validates the incoming string|array to ensure its an allowable type.
581
+	 * @throws InvalidArgumentException
582
+	 * @param string|array $type
583
+	 */
584
+	private function validateSchemaType($type)
585
+	{
586
+		if (! (is_string($type) || is_array($type))) {
587
+			throw new InvalidArgumentException(
588
+				sprintf(
589
+					esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
590
+					print_r($type, true)
591
+				)
592
+			);
593
+		}
594
+
595
+		// validate allowable types.
596
+		// @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
597
+		$allowable_types = array_flip(
598
+			array(
599
+				'string',
600
+				'number',
601
+				'null',
602
+				'object',
603
+				'array',
604
+				'boolean',
605
+				'integer'
606
+			)
607
+		);
608
+
609
+		if (is_array($type)) {
610
+			foreach ($type as $item_in_type) {
611
+				$this->validateSchemaType($item_in_type);
612
+			}
613
+			return;
614
+		}
615
+
616
+		if (! isset($allowable_types[ $type ])) {
617
+			throw new InvalidArgumentException(
618
+				sprintf(
619
+					esc_html__('The incoming argument (%1$s) must be one of the allowable types: %2$s', 'event_espresso'),
620
+					$type,
621
+					implode(',', array_flip($allowable_types))
622
+				)
623
+			);
624
+		}
625
+	}
626
+
627
+
628
+	/**
629
+	 * Validates that the incoming format is an allowable string to use for the _schema_format property
630
+	 * @throws InvalidArgumentException
631
+	 * @param $format
632
+	 */
633
+	private function validateSchemaFormat($format)
634
+	{
635
+		if (! is_string($format)) {
636
+			throw new InvalidArgumentException(
637
+				sprintf(
638
+					esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
639
+					print_r($format, true)
640
+				)
641
+			);
642
+		}
643
+
644
+		// validate allowable format values
645
+		// @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
646
+		$allowable_formats = array_flip(
647
+			array(
648
+				'date-time',
649
+				'email',
650
+				'hostname',
651
+				'ipv4',
652
+				'ipv6',
653
+				'uri',
654
+				'uriref'
655
+			)
656
+		);
657
+
658
+		if (! isset($allowable_formats[ $format ])) {
659
+			throw new InvalidArgumentException(
660
+				sprintf(
661
+					esc_html__('The incoming argument (%1$s) must be one of the allowable formats: %2$s', 'event_espresso'),
662
+					$format,
663
+					implode(',', array_flip($allowable_formats))
664
+				)
665
+			);
666
+		}
667
+	}
669 668
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
         /**
128 128
          * allow for changing the defaults
129 129
          */
130
-        $this->_nicename      = apply_filters(
130
+        $this->_nicename = apply_filters(
131 131
             'FHEE__EE_Model_Field_Base___construct_finalize___nicename',
132 132
             $this->_nicename,
133 133
             $this
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
      */
218 218
     public function get_qualified_column()
219 219
     {
220
-        return $this->get_table_alias() . "." . $this->get_table_column();
220
+        return $this->get_table_alias().".".$this->get_table_column();
221 221
     }
222 222
 
223 223
     /**
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
     {
313 313
         if ($this->is_nullable()) {
314 314
             $this->_schema_type = (array) $this->_schema_type;
315
-            if (! in_array('null', $this->_schema_type)) {
315
+            if ( ! in_array('null', $this->_schema_type)) {
316 316
                 $this->_schema_type[] = 'null';
317 317
             };
318 318
         }
@@ -369,10 +369,10 @@  discard block
 block discarded – undo
369 369
                 switch ($property_key) {
370 370
                     case 'pretty':
371 371
                     case 'rendered':
372
-                        $value_to_return[ $property_key ] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
372
+                        $value_to_return[$property_key] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
373 373
                         break;
374 374
                     default:
375
-                        $value_to_return[ $property_key ] = $default_value;
375
+                        $value_to_return[$property_key] = $default_value;
376 376
                         break;
377 377
                 }
378 378
             }
@@ -437,7 +437,7 @@  discard block
 block discarded – undo
437 437
      */
438 438
     protected function setSchemaReadOnly($readonly)
439 439
     {
440
-        if (! is_bool($readonly)) {
440
+        if ( ! is_bool($readonly)) {
441 441
             throw new InvalidArgumentException(
442 442
                 sprintf(
443 443
                     esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
@@ -584,7 +584,7 @@  discard block
 block discarded – undo
584 584
      */
585 585
     private function validateSchemaType($type)
586 586
     {
587
-        if (! (is_string($type) || is_array($type))) {
587
+        if ( ! (is_string($type) || is_array($type))) {
588 588
             throw new InvalidArgumentException(
589 589
                 sprintf(
590 590
                     esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
             return;
615 615
         }
616 616
 
617
-        if (! isset($allowable_types[ $type ])) {
617
+        if ( ! isset($allowable_types[$type])) {
618 618
             throw new InvalidArgumentException(
619 619
                 sprintf(
620 620
                     esc_html__('The incoming argument (%1$s) must be one of the allowable types: %2$s', 'event_espresso'),
@@ -633,7 +633,7 @@  discard block
 block discarded – undo
633 633
      */
634 634
     private function validateSchemaFormat($format)
635 635
     {
636
-        if (! is_string($format)) {
636
+        if ( ! is_string($format)) {
637 637
             throw new InvalidArgumentException(
638 638
                 sprintf(
639 639
                     esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
@@ -656,7 +656,7 @@  discard block
 block discarded – undo
656 656
             )
657 657
         );
658 658
 
659
-        if (! isset($allowable_formats[ $format ])) {
659
+        if ( ! isset($allowable_formats[$format])) {
660 660
             throw new InvalidArgumentException(
661 661
                 sprintf(
662 662
                     esc_html__('The incoming argument (%1$s) must be one of the allowable formats: %2$s', 'event_espresso'),
Please login to merge, or discard this patch.
core/db_models/fields/EE_Money_Field.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -12,7 +12,7 @@
 block discarded – undo
12 12
      * @param string $table_column
13 13
      * @param string $nicename
14 14
      * @param bool   $nullable
15
-     * @param null   $default_value
15
+     * @param integer   $default_value
16 16
      */
17 17
     public function __construct($table_column, $nicename, $nullable, $default_value = null)
18 18
     {
Please login to merge, or discard this patch.
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -7,92 +7,92 @@
 block discarded – undo
7 7
 class EE_Money_Field extends EE_Float_Field
8 8
 {
9 9
 
10
-    /**
11
-     * @param string $table_column
12
-     * @param string $nicename
13
-     * @param bool   $nullable
14
-     * @param null   $default_value
15
-     */
16
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
17
-    {
18
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
19
-        $this->setSchemaType('object');
20
-    }
10
+	/**
11
+	 * @param string $table_column
12
+	 * @param string $nicename
13
+	 * @param bool   $nullable
14
+	 * @param null   $default_value
15
+	 */
16
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
17
+	{
18
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
19
+		$this->setSchemaType('object');
20
+	}
21 21
 
22 22
 
23
-    /**
24
-     * Schemas:
25
-     *    'localized_float': "3,023.00"
26
-     *    'no_currency_code': "$3,023.00"
27
-     *    null: "$3,023.00<span>USD</span>"
28
-     *
29
-     * @param string $value_on_field_to_be_outputted
30
-     * @param string $schema
31
-     * @return string
32
-     */
33
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
34
-    {
35
-        $pretty_float = parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted);
23
+	/**
24
+	 * Schemas:
25
+	 *    'localized_float': "3,023.00"
26
+	 *    'no_currency_code': "$3,023.00"
27
+	 *    null: "$3,023.00<span>USD</span>"
28
+	 *
29
+	 * @param string $value_on_field_to_be_outputted
30
+	 * @param string $schema
31
+	 * @return string
32
+	 */
33
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
34
+	{
35
+		$pretty_float = parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted);
36 36
 
37
-        if ($schema == 'localized_float') {
38
-            return $pretty_float;
39
-        }
40
-        if ($schema == 'no_currency_code') {
37
+		if ($schema == 'localized_float') {
38
+			return $pretty_float;
39
+		}
40
+		if ($schema == 'no_currency_code') {
41 41
 //          echo "schema no currency!";
42
-            $display_code = false;
43
-        } else {
44
-            $display_code = true;
45
-        }
46
-        // we don't use the $pretty_float because format_currency will take care of it.
47
-        return EEH_Template::format_currency($value_on_field_to_be_outputted, false, $display_code);
48
-    }
42
+			$display_code = false;
43
+		} else {
44
+			$display_code = true;
45
+		}
46
+		// we don't use the $pretty_float because format_currency will take care of it.
47
+		return EEH_Template::format_currency($value_on_field_to_be_outputted, false, $display_code);
48
+	}
49 49
 
50
-    /**
51
-     * If provided with a string, strips out money-related formatting to turn it into a proper float.
52
-     * Rounds the float to the correct number of decimal places for this country's currency.
53
-     * Also, interprets periods and commas according to the country's currency settings.
54
-     * So if you want to pass in a string that NEEDS to interpret periods as decimal marks, call floatval() on it first.
55
-     *
56
-     * @param string $value_inputted_for_field_on_model_object
57
-     * @return float
58
-     */
59
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
60
-    {
61
-        // remove any currencies etc.
50
+	/**
51
+	 * If provided with a string, strips out money-related formatting to turn it into a proper float.
52
+	 * Rounds the float to the correct number of decimal places for this country's currency.
53
+	 * Also, interprets periods and commas according to the country's currency settings.
54
+	 * So if you want to pass in a string that NEEDS to interpret periods as decimal marks, call floatval() on it first.
55
+	 *
56
+	 * @param string $value_inputted_for_field_on_model_object
57
+	 * @return float
58
+	 */
59
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
60
+	{
61
+		// remove any currencies etc.
62 62
 //      if(is_string($value_inputted_for_field_on_model_object)){
63 63
 //          $value_inputted_for_field_on_model_object = preg_replace("/[^0-9,.]/", "", $value_inputted_for_field_on_model_object);
64 64
 //      }
65
-        // now it's a float-style string or number
66
-        $float_val = parent::prepare_for_set($value_inputted_for_field_on_model_object);
67
-        // round to the correctly number of decimal places for this  currency
68
-        $rounded_value = round($float_val, EE_Registry::instance()->CFG->currency->dec_plc);
69
-        return $rounded_value;
70
-    }
65
+		// now it's a float-style string or number
66
+		$float_val = parent::prepare_for_set($value_inputted_for_field_on_model_object);
67
+		// round to the correctly number of decimal places for this  currency
68
+		$rounded_value = round($float_val, EE_Registry::instance()->CFG->currency->dec_plc);
69
+		return $rounded_value;
70
+	}
71 71
 
72
-    public function prepare_for_get($value_of_field_on_model_object)
73
-    {
74
-        $c = EE_Registry::instance()->CFG->currency;
75
-        return round(parent::prepare_for_get($value_of_field_on_model_object), $c->dec_plc);
76
-    }
72
+	public function prepare_for_get($value_of_field_on_model_object)
73
+	{
74
+		$c = EE_Registry::instance()->CFG->currency;
75
+		return round(parent::prepare_for_get($value_of_field_on_model_object), $c->dec_plc);
76
+	}
77 77
 
78
-    public function getSchemaProperties()
79
-    {
80
-        return array(
81
-            'raw' => array(
82
-                'description' =>  sprintf(
83
-                    __('%s - the raw value as it exists in the database as a simple float.', 'event_espresso'),
84
-                    $this->get_nicename()
85
-                ),
86
-                'type' => 'number',
87
-            ),
88
-            'pretty' => array(
89
-                'description' =>  sprintf(
90
-                    __('%s - formatted for display in the set currency and decimal places.', 'event_espresso'),
91
-                    $this->get_nicename()
92
-                ),
93
-                'type' => 'string',
94
-                'format' => 'money'
95
-            )
96
-        );
97
-    }
78
+	public function getSchemaProperties()
79
+	{
80
+		return array(
81
+			'raw' => array(
82
+				'description' =>  sprintf(
83
+					__('%s - the raw value as it exists in the database as a simple float.', 'event_espresso'),
84
+					$this->get_nicename()
85
+				),
86
+				'type' => 'number',
87
+			),
88
+			'pretty' => array(
89
+				'description' =>  sprintf(
90
+					__('%s - formatted for display in the set currency and decimal places.', 'event_espresso'),
91
+					$this->get_nicename()
92
+				),
93
+				'type' => 'string',
94
+				'format' => 'money'
95
+			)
96
+		);
97
+	}
98 98
 }
Please login to merge, or discard this patch.