Completed
Branch CASC/base (79f9d1)
by
unknown
17:51 queued 09:38
created
core/services/orm/tree_traversal/BaseNode.php 3 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@
 block discarded – undo
68 68
      */
69 69
     public function visit($model_objects_to_identify)
70 70
     {
71
-        if (! $this->isDiscovered()) {
71
+        if ( ! $this->isDiscovered()) {
72 72
             $this->discover();
73 73
         }
74 74
         if ($this->isComplete()) {
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@
 block discarded – undo
102 102
     /**
103 103
      * Make sure we encode whether its complete or not, but don't use such a long name.
104 104
      * @since $VID:$
105
-     * @return array
105
+     * @return string[]
106 106
      */
107 107
     public function __sleep()
108 108
     {
Please login to merge, or discard this patch.
Indentation   +88 added lines, -88 removed lines patch added patch discarded remove patch
@@ -31,105 +31,105 @@
 block discarded – undo
31 31
  */
32 32
 abstract class BaseNode
33 33
 {
34
-    /**
35
-     * @var boolean
36
-     */
37
-    protected $complete;
34
+	/**
35
+	 * @var boolean
36
+	 */
37
+	protected $complete;
38 38
 
39 39
 
40
-    /**
41
-     * @var array of model names we don't want to traverse
42
-     */
43
-    protected $dont_traverse_models;
40
+	/**
41
+	 * @var array of model names we don't want to traverse
42
+	 */
43
+	protected $dont_traverse_models;
44 44
 
45
-    /**
46
-     * Whether this item has already been initialized
47
-     */
48
-    abstract protected function isDiscovered();
45
+	/**
46
+	 * Whether this item has already been initialized
47
+	 */
48
+	abstract protected function isDiscovered();
49 49
 
50
-    /**
51
-     * Determines if the work is done yet or not. Requires you to have first discovered what work exists by calling
52
-     * discover().
53
-     * @since $VID:$
54
-     * @return boolean
55
-     */
56
-    abstract public function isComplete();
50
+	/**
51
+	 * Determines if the work is done yet or not. Requires you to have first discovered what work exists by calling
52
+	 * discover().
53
+	 * @since $VID:$
54
+	 * @return boolean
55
+	 */
56
+	abstract public function isComplete();
57 57
 
58
-    /**
59
-     * Discovers what work needs to be done to complete traversing this node and its children.
60
-     * Note that this is separate from the constructor, so we can create child nodes without
61
-     * discovering them immediately.
62
-     * @since $VID:$
63
-     * @return mixed
64
-     */
65
-    abstract protected function discover();
58
+	/**
59
+	 * Discovers what work needs to be done to complete traversing this node and its children.
60
+	 * Note that this is separate from the constructor, so we can create child nodes without
61
+	 * discovering them immediately.
62
+	 * @since $VID:$
63
+	 * @return mixed
64
+	 */
65
+	abstract protected function discover();
66 66
 
67
-    /**
68
-     * Identifies model objects, up to the limit $model_objects_to_identify.
69
-     * @since $VID:$
70
-     * @param int $model_objects_to_identify
71
-     * @return int units of work done
72
-     */
73
-    abstract protected function work($model_objects_to_identify);
67
+	/**
68
+	 * Identifies model objects, up to the limit $model_objects_to_identify.
69
+	 * @since $VID:$
70
+	 * @param int $model_objects_to_identify
71
+	 * @return int units of work done
72
+	 */
73
+	abstract protected function work($model_objects_to_identify);
74 74
 
75
-    /**
76
-     * Shows the entity/relation node as an array.
77
-     * @since $VID:$
78
-     * @return array
79
-     */
80
-    abstract public function toArray();
75
+	/**
76
+	 * Shows the entity/relation node as an array.
77
+	 * @since $VID:$
78
+	 * @return array
79
+	 */
80
+	abstract public function toArray();
81 81
 
82
-    /**
83
-     * Discovers how much work there is to do, double-checks the work isn't already finished, and then does the work.
84
-     * Note: do not call when site is in maintenance mode level 2.
85
-     *
86
-     * @since $VID:$
87
-     * @param $model_objects_to_identify
88
-     * @return int number of model objects we want to identify during this call. On subsequent calls we'll continue
89
-     * where we left off.
90
-     */
91
-    public function visit($model_objects_to_identify)
92
-    {
93
-        if (! $this->isDiscovered()) {
94
-            $this->discover();
95
-        }
96
-        if ($this->isComplete()) {
97
-            return 0;
98
-        }
99
-        return $this->work($model_objects_to_identify);
100
-    }
82
+	/**
83
+	 * Discovers how much work there is to do, double-checks the work isn't already finished, and then does the work.
84
+	 * Note: do not call when site is in maintenance mode level 2.
85
+	 *
86
+	 * @since $VID:$
87
+	 * @param $model_objects_to_identify
88
+	 * @return int number of model objects we want to identify during this call. On subsequent calls we'll continue
89
+	 * where we left off.
90
+	 */
91
+	public function visit($model_objects_to_identify)
92
+	{
93
+		if (! $this->isDiscovered()) {
94
+			$this->discover();
95
+		}
96
+		if ($this->isComplete()) {
97
+			return 0;
98
+		}
99
+		return $this->work($model_objects_to_identify);
100
+	}
101 101
 
102
-    /**
103
-     * Gets the IDs of completely identified model objects that can be deleted.
104
-     * @since $VID:$
105
-     * @return mixed
106
-     */
107
-    abstract public function getIds();
102
+	/**
103
+	 * Gets the IDs of completely identified model objects that can be deleted.
104
+	 * @since $VID:$
105
+	 * @return mixed
106
+	 */
107
+	abstract public function getIds();
108 108
 
109
-    /**
110
-     * Make sure we encode whether its complete or not, but don't use such a long name.
111
-     * @since $VID:$
112
-     * @return array
113
-     */
114
-    public function __sleep()
115
-    {
116
-        $this->c = $this->complete;
117
-        $this->dtm = $this->dont_traverse_models;
118
-        return [
119
-            'c',
120
-            'dtm'
121
-        ];
122
-    }
109
+	/**
110
+	 * Make sure we encode whether its complete or not, but don't use such a long name.
111
+	 * @since $VID:$
112
+	 * @return array
113
+	 */
114
+	public function __sleep()
115
+	{
116
+		$this->c = $this->complete;
117
+		$this->dtm = $this->dont_traverse_models;
118
+		return [
119
+			'c',
120
+			'dtm'
121
+		];
122
+	}
123 123
 
124
-    /**
125
-     * Use the dynamic property to set the "complete" property.
126
-     * @since $VID:$
127
-     */
128
-    public function __wakeup()
129
-    {
130
-        $this->complete = $this->c;
131
-        $this->dont_traverse_models = $this->dtm;
132
-    }
124
+	/**
125
+	 * Use the dynamic property to set the "complete" property.
126
+	 * @since $VID:$
127
+	 */
128
+	public function __wakeup()
129
+	{
130
+		$this->complete = $this->c;
131
+		$this->dont_traverse_models = $this->dtm;
132
+	}
133 133
 }
134 134
 // End of file BaseNode.php
135 135
 // Location: EventEspresso\core\services\orm\tree_traversal/BaseNode.php
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 4 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -2086,7 +2086,6 @@
 block discarded – undo
2086 2086
      * _delete_event
2087 2087
      *
2088 2088
      * @access protected
2089
-     * @param bool $redirect_after
2090 2089
      */
2091 2090
     protected function _delete_event()
2092 2091
     {
Please login to merge, or discard this patch.
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -1,11 +1,8 @@
 block discarded – undo
1 1
 <?php
2 2
 
3
-use EventEspresso\admin_pages\events\form_sections\ConfirmEventDeletionForm;
4 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
5 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
6
-use EventEspresso\core\exceptions\UnexpectedEntityException;
7 5
 use EventEspresso\core\services\orm\tree_traversal\NodeGroupDao;
8
-use EventEspresso\core\services\orm\tree_traversal\ModelObjNode;
9 6
 
10 7
 /**
11 8
  * Events_Admin_Page
Please login to merge, or discard this patch.
Spacing   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -577,11 +577,11 @@  discard block
 block discarded – undo
577 577
     {
578 578
         wp_register_style(
579 579
             'events-admin-css',
580
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
580
+            EVENTS_ASSETS_URL.'events-admin-page.css',
581 581
             array(),
582 582
             EVENT_ESPRESSO_VERSION
583 583
         );
584
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
584
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
585 585
         wp_enqueue_style('events-admin-css');
586 586
         wp_enqueue_style('ee-cat-admin');
587 587
         // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
         // scripts
590 590
         wp_register_script(
591 591
             'event_editor_js',
592
-            EVENTS_ASSETS_URL . 'event_editor.js',
592
+            EVENTS_ASSETS_URL.'event_editor.js',
593 593
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
594 594
             EVENT_ESPRESSO_VERSION,
595 595
             true
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
         wp_enqueue_style('espresso-ui-theme');
616 616
         wp_register_style(
617 617
             'event-editor-css',
618
-            EVENTS_ASSETS_URL . 'event-editor.css',
618
+            EVENTS_ASSETS_URL.'event-editor.css',
619 619
             array('ee-admin-css'),
620 620
             EVENT_ESPRESSO_VERSION
621 621
         );
@@ -623,7 +623,7 @@  discard block
 block discarded – undo
623 623
         // scripts
624 624
         wp_register_script(
625 625
             'event-datetime-metabox',
626
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
626
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
627 627
             array('event_editor_js', 'ee-datepicker'),
628 628
             EVENT_ESPRESSO_VERSION
629 629
         );
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
     public function verify_event_edit($event = null, $req_type = '')
693 693
     {
694 694
         // don't need to do this when processing
695
-        if (! empty($req_type)) {
695
+        if ( ! empty($req_type)) {
696 696
             return;
697 697
         }
698 698
         // no event?
@@ -701,7 +701,7 @@  discard block
 block discarded – undo
701 701
             $event = $this->_cpt_model_obj;
702 702
         }
703 703
         // STILL no event?
704
-        if (! $event instanceof EE_Event) {
704
+        if ( ! $event instanceof EE_Event) {
705 705
             return;
706 706
         }
707 707
         $orig_status = $event->status();
@@ -739,7 +739,7 @@  discard block
 block discarded – undo
739 739
             );
740 740
         }
741 741
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
742
-        if (! $event->tickets_on_sale()) {
742
+        if ( ! $event->tickets_on_sale()) {
743 743
             return;
744 744
         }
745 745
         // made it here so show warning
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
     {
785 785
         $has_timezone_string = get_option('timezone_string');
786 786
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
787
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
787
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
788 788
             EE_Error::add_attention(
789 789
                 sprintf(
790 790
                     __(
@@ -868,31 +868,31 @@  discard block
 block discarded – undo
868 868
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
869 869
         $statuses = array(
870 870
             'sold_out_status'  => array(
871
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
871
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
872 872
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
873 873
             ),
874 874
             'active_status'    => array(
875
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
875
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
876 876
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
877 877
             ),
878 878
             'upcoming_status'  => array(
879
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
879
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
880 880
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
881 881
             ),
882 882
             'postponed_status' => array(
883
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
883
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
884 884
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
885 885
             ),
886 886
             'cancelled_status' => array(
887
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
887
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
888 888
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
889 889
             ),
890 890
             'expired_status'   => array(
891
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
891
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
892 892
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
893 893
             ),
894 894
             'inactive_status'  => array(
895
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
895
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
896 896
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
897 897
             ),
898 898
         );
@@ -906,7 +906,7 @@  discard block
 block discarded – undo
906 906
      */
907 907
     private function _event_model()
908 908
     {
909
-        if (! $this->_event_model instanceof EEM_Event) {
909
+        if ( ! $this->_event_model instanceof EEM_Event) {
910 910
             $this->_event_model = EE_Registry::instance()->load_model('Event');
911 911
         }
912 912
         return $this->_event_model;
@@ -926,7 +926,7 @@  discard block
 block discarded – undo
926 926
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
927 927
     {
928 928
         // make sure this is only when editing
929
-        if (! empty($id)) {
929
+        if ( ! empty($id)) {
930 930
             $post = get_post($id);
931 931
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
932 932
                        . esc_html__('Shortcode', 'event_espresso')
@@ -960,7 +960,7 @@  discard block
 block discarded – undo
960 960
                     'button'
961 961
                 );
962 962
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
963
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
963
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
964 964
             'create_new',
965 965
             'add',
966 966
             array(),
@@ -1100,7 +1100,7 @@  discard block
 block discarded – undo
1100 1100
      */
1101 1101
     protected function _default_venue_update(\EE_Event $evtobj, $data)
1102 1102
     {
1103
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1103
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1104 1104
         $venue_model = EE_Registry::instance()->load_model('Venue');
1105 1105
         $rows_affected = null;
1106 1106
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1131,7 +1131,7 @@  discard block
 block discarded – undo
1131 1131
             'status'              => 'publish',
1132 1132
         );
1133 1133
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1134
-        if (! empty($venue_id)) {
1134
+        if ( ! empty($venue_id)) {
1135 1135
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1136 1136
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1137 1137
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1173,7 +1173,7 @@  discard block
 block discarded – undo
1173 1173
                 'DTT_order'     => $row,
1174 1174
             );
1175 1175
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1176
-            if (! empty($dtt['DTT_ID'])) {
1176
+            if ( ! empty($dtt['DTT_ID'])) {
1177 1177
                 $DTM = EE_Registry::instance()
1178 1178
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1179 1179
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1183,7 +1183,7 @@  discard block
 block discarded – undo
1183 1183
                     $DTM->set($field, $value);
1184 1184
                 }
1185 1185
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1186
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1186
+                $saved_dtts[$DTM->ID()] = $DTM;
1187 1187
             } else {
1188 1188
                 $DTM = EE_Registry::instance()->load_class(
1189 1189
                     'Datetime',
@@ -1216,14 +1216,14 @@  discard block
 block discarded – undo
1216 1216
         foreach ($data['edit_tickets'] as $row => $tkt) {
1217 1217
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1218 1218
             $update_prices = false;
1219
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1220
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1219
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1220
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1221 1221
             // trim inputs to ensure any excess whitespace is removed.
1222 1222
             $tkt = array_map('trim', $tkt);
1223 1223
             if (empty($tkt['TKT_start_date'])) {
1224 1224
                 // let's use now in the set timezone.
1225 1225
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1226
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1226
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1227 1227
             }
1228 1228
             if (empty($tkt['TKT_end_date'])) {
1229 1229
                 // use the start date of the first datetime
@@ -1258,7 +1258,7 @@  discard block
 block discarded – undo
1258 1258
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1259 1259
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1260 1260
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1261
-            if (! empty($tkt['TKT_ID'])) {
1261
+            if ( ! empty($tkt['TKT_ID'])) {
1262 1262
                 $TKT = EE_Registry::instance()
1263 1263
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1264 1264
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1293,7 +1293,7 @@  discard block
 block discarded – undo
1293 1293
                         $TKT->set('TKT_deleted', 1);
1294 1294
                         $TKT->save();
1295 1295
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1296
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1296
+                        $saved_tickets[$TKT->ID()] = $TKT;
1297 1297
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1298 1298
                         $TKT = clone $TKT;
1299 1299
                         $TKT->set('TKT_ID', 0);
@@ -1338,9 +1338,9 @@  discard block
 block discarded – undo
1338 1338
             }
1339 1339
             // initially let's add the ticket to the dtt
1340 1340
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1341
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1341
+            $saved_tickets[$TKT->ID()] = $TKT;
1342 1342
             // add prices to ticket
1343
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1343
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1344 1344
         }
1345 1345
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1346 1346
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
@@ -1497,7 +1497,7 @@  discard block
 block discarded – undo
1497 1497
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1498 1498
         // load template
1499 1499
         EEH_Template::display_template(
1500
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1500
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1501 1501
             $publish_box_extra_args
1502 1502
         );
1503 1503
     }
@@ -1589,7 +1589,7 @@  discard block
 block discarded – undo
1589 1589
                     'default_where_conditions' => 'none',
1590 1590
                 )
1591 1591
             );
1592
-            if (! empty($related_tickets)) {
1592
+            if ( ! empty($related_tickets)) {
1593 1593
                 $template_args['total_ticket_rows'] = count($related_tickets);
1594 1594
                 $row = 0;
1595 1595
                 foreach ($related_tickets as $ticket) {
@@ -1623,7 +1623,7 @@  discard block
 block discarded – undo
1623 1623
         );
1624 1624
         $template = apply_filters(
1625 1625
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1626
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1626
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1627 1627
         );
1628 1628
         EEH_Template::display_template($template, $template_args);
1629 1629
     }
@@ -1641,7 +1641,7 @@  discard block
 block discarded – undo
1641 1641
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1642 1642
     {
1643 1643
         $template_args = array(
1644
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1644
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1645 1645
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1646 1646
                 : '',
1647 1647
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1653,10 +1653,10 @@  discard block
 block discarded – undo
1653 1653
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1654 1654
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1655 1655
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1656
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1657
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1656
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1657
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1658 1658
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1659
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1659
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1660 1660
                 : ' disabled=disabled',
1661 1661
         );
1662 1662
         $price = $ticket->ID() !== 0
@@ -1683,7 +1683,7 @@  discard block
 block discarded – undo
1683 1683
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1684 1684
                 )
1685 1685
                 : null;
1686
-            if (! empty($earliest_dtt)) {
1686
+            if ( ! empty($earliest_dtt)) {
1687 1687
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1688 1688
             } else {
1689 1689
                 $template_args['TKT_end_date'] = date(
@@ -1695,7 +1695,7 @@  discard block
 block discarded – undo
1695 1695
         $template_args = array_merge($template_args, $price_args);
1696 1696
         $template = apply_filters(
1697 1697
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1698
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1698
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1699 1699
             $ticket
1700 1700
         );
1701 1701
         return EEH_Template::display_template($template, $template_args, true);
@@ -1749,7 +1749,7 @@  discard block
 block discarded – undo
1749 1749
             $default_reg_status_values
1750 1750
         );
1751 1751
         EEH_Template::display_template(
1752
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1752
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1753 1753
             $template_args
1754 1754
         );
1755 1755
     }
@@ -1771,7 +1771,7 @@  discard block
 block discarded – undo
1771 1771
     {
1772 1772
         $EEME = $this->_event_model();
1773 1773
         $offset = ($current_page - 1) * $per_page;
1774
-        $limit = $count ? null : $offset . ',' . $per_page;
1774
+        $limit = $count ? null : $offset.','.$per_page;
1775 1775
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1776 1776
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1777 1777
         if (isset($this->_req_data['month_range'])) {
@@ -1800,7 +1800,7 @@  discard block
 block discarded – undo
1800 1800
         // categories?
1801 1801
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1802 1802
             ? $this->_req_data['EVT_CAT'] : null;
1803
-        if (! empty($category)) {
1803
+        if ( ! empty($category)) {
1804 1804
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1805 1805
             $where['Term_Taxonomy.term_id'] = $category;
1806 1806
         }
@@ -1808,7 +1808,7 @@  discard block
 block discarded – undo
1808 1808
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1809 1809
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1810 1810
             $DateTime = new DateTime(
1811
-                $year_r . '-' . $month_r . '-01 00:00:00',
1811
+                $year_r.'-'.$month_r.'-01 00:00:00',
1812 1812
                 new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1813 1813
             );
1814 1814
             $start = $DateTime->format(implode(' ', $start_formats));
@@ -1834,11 +1834,11 @@  discard block
 block discarded – undo
1834 1834
                             ->format(implode(' ', $start_formats));
1835 1835
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1836 1836
         }
1837
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1837
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1838 1838
             $where['EVT_wp_user'] = get_current_user_id();
1839 1839
         } else {
1840
-            if (! isset($where['status'])) {
1841
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1840
+            if ( ! isset($where['status'])) {
1841
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1842 1842
                     $where['OR'] = array(
1843 1843
                         'status*restrict_private' => array('!=', 'private'),
1844 1844
                         'AND'                     => array(
@@ -1858,7 +1858,7 @@  discard block
 block discarded – undo
1858 1858
         }
1859 1859
         // search query handling
1860 1860
         if (isset($this->_req_data['s'])) {
1861
-            $search_string = '%' . $this->_req_data['s'] . '%';
1861
+            $search_string = '%'.$this->_req_data['s'].'%';
1862 1862
             $where['OR'] = array(
1863 1863
                 'EVT_name'       => array('LIKE', $search_string),
1864 1864
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -1953,7 +1953,7 @@  discard block
 block discarded – undo
1953 1953
             // clean status
1954 1954
             $event_status = sanitize_key($event_status);
1955 1955
             // grab status
1956
-            if (! empty($event_status)) {
1956
+            if ( ! empty($event_status)) {
1957 1957
                 $success = $this->_change_event_status($EVT_ID, $event_status);
1958 1958
             } else {
1959 1959
                 $success = false;
@@ -1990,7 +1990,7 @@  discard block
 block discarded – undo
1990 1990
         // clean status
1991 1991
         $event_status = sanitize_key($event_status);
1992 1992
         // grab status
1993
-        if (! empty($event_status)) {
1993
+        if ( ! empty($event_status)) {
1994 1994
             $success = true;
1995 1995
             // determine the event id and set to array.
1996 1996
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2037,7 +2037,7 @@  discard block
 block discarded – undo
2037 2037
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2038 2038
     {
2039 2039
         // grab event id
2040
-        if (! $EVT_ID) {
2040
+        if ( ! $EVT_ID) {
2041 2041
             $msg = esc_html__(
2042 2042
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2043 2043
                 'event_espresso'
@@ -2107,7 +2107,7 @@  discard block
 block discarded – undo
2107 2107
      */
2108 2108
     protected function getModelObjNodeGroupPersister()
2109 2109
     {
2110
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2110
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2111 2111
             $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2112 2112
         }
2113 2113
         return $this->model_obj_node_group_persister;
@@ -2358,7 +2358,7 @@  discard block
 block discarded – undo
2358 2358
                                                 . esc_html__(
2359 2359
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2360 2360
                                                     'event_espresso'
2361
-                                                ) . '</strong>';
2361
+                                                ).'</strong>';
2362 2362
         $this->display_admin_caf_preview_page('template_settings_tab');
2363 2363
     }
2364 2364
 
@@ -2378,12 +2378,12 @@  discard block
 block discarded – undo
2378 2378
         // set default category object
2379 2379
         $this->_set_empty_category_object();
2380 2380
         // only set if we've got an id
2381
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2381
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2382 2382
             return;
2383 2383
         }
2384 2384
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2385 2385
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2386
-        if (! empty($term)) {
2386
+        if ( ! empty($term)) {
2387 2387
             $this->_category->category_name = $term->name;
2388 2388
             $this->_category->category_identifier = $term->slug;
2389 2389
             $this->_category->category_desc = $term->description;
@@ -2411,7 +2411,7 @@  discard block
 block discarded – undo
2411 2411
     {
2412 2412
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2413 2413
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2414
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2414
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2415 2415
             'add_category',
2416 2416
             'add_category',
2417 2417
             array(),
@@ -2485,7 +2485,7 @@  discard block
 block discarded – undo
2485 2485
             'disable'                  => '',
2486 2486
             'disabled_message'         => false,
2487 2487
         );
2488
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2488
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2489 2489
         return EEH_Template::display_template($template, $template_args, true);
2490 2490
     }
2491 2491
 
@@ -2570,7 +2570,7 @@  discard block
 block discarded – undo
2570 2570
         $insert_ids = $update
2571 2571
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2572 2572
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2573
-        if (! is_array($insert_ids)) {
2573
+        if ( ! is_array($insert_ids)) {
2574 2574
             $msg = esc_html__(
2575 2575
                 'An error occurred and the category has not been saved to the database.',
2576 2576
                 'event_espresso'
@@ -2601,7 +2601,7 @@  discard block
 block discarded – undo
2601 2601
         $limit = ($current_page - 1) * $per_page;
2602 2602
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2603 2603
         if (isset($this->_req_data['s'])) {
2604
-            $sstr = '%' . $this->_req_data['s'] . '%';
2604
+            $sstr = '%'.$this->_req_data['s'].'%';
2605 2605
             $where['OR'] = array(
2606 2606
                 'Term.name'   => array('LIKE', $sstr),
2607 2607
                 'description' => array('LIKE', $sstr),
@@ -2610,7 +2610,7 @@  discard block
 block discarded – undo
2610 2610
         $query_params = array(
2611 2611
             $where,
2612 2612
             'order_by'   => array($orderby => $order),
2613
-            'limit'      => $limit . ',' . $per_page,
2613
+            'limit'      => $limit.','.$per_page,
2614 2614
             'force_join' => array('Term'),
2615 2615
         );
2616 2616
         $categories = $count
Please login to merge, or discard this patch.
Indentation   +2633 added lines, -2633 removed lines patch added patch discarded remove patch
@@ -19,2637 +19,2637 @@
 block discarded – undo
19 19
 class Events_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * This will hold the event object for event_details screen.
24
-     *
25
-     * @access protected
26
-     * @var EE_Event $_event
27
-     */
28
-    protected $_event;
29
-
30
-
31
-    /**
32
-     * This will hold the category object for category_details screen.
33
-     *
34
-     * @var stdClass $_category
35
-     */
36
-    protected $_category;
37
-
38
-
39
-    /**
40
-     * This will hold the event model instance
41
-     *
42
-     * @var EEM_Event $_event_model
43
-     */
44
-    protected $_event_model;
45
-
46
-
47
-    /**
48
-     * @var EE_Event
49
-     */
50
-    protected $_cpt_model_obj = false;
51
-
52
-
53
-    /**
54
-     * @var NodeGroupDao
55
-     */
56
-    protected $model_obj_node_group_persister;
57
-
58
-    /**
59
-     * Initialize page props for this admin page group.
60
-     */
61
-    protected function _init_page_props()
62
-    {
63
-        $this->page_slug = EVENTS_PG_SLUG;
64
-        $this->page_label = EVENTS_LABEL;
65
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
66
-        $this->_admin_base_path = EVENTS_ADMIN;
67
-        $this->_cpt_model_names = array(
68
-            'create_new' => 'EEM_Event',
69
-            'edit'       => 'EEM_Event',
70
-        );
71
-        $this->_cpt_edit_routes = array(
72
-            'espresso_events' => 'edit',
73
-        );
74
-        add_action(
75
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
76
-            array($this, 'verify_event_edit'),
77
-            10,
78
-            2
79
-        );
80
-    }
81
-
82
-
83
-    /**
84
-     * Sets the ajax hooks used for this admin page group.
85
-     */
86
-    protected function _ajax_hooks()
87
-    {
88
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
89
-    }
90
-
91
-
92
-    /**
93
-     * Sets the page properties for this admin page group.
94
-     */
95
-    protected function _define_page_props()
96
-    {
97
-        $this->_admin_page_title = EVENTS_LABEL;
98
-        $this->_labels = array(
99
-            'buttons'      => array(
100
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
101
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
102
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
103
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
104
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
105
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
106
-            ),
107
-            'editor_title' => array(
108
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
109
-            ),
110
-            'publishbox'   => array(
111
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
112
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
113
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
114
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
115
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
116
-            ),
117
-        );
118
-    }
119
-
120
-
121
-    /**
122
-     * Sets the page routes property for this admin page group.
123
-     */
124
-    protected function _set_page_routes()
125
-    {
126
-        // load formatter helper
127
-        // load field generator helper
128
-        // is there a evt_id in the request?
129
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
130
-            ? $this->_req_data['EVT_ID']
131
-            : 0;
132
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
133
-        $this->_page_routes = array(
134
-            'default'                       => array(
135
-                'func'       => '_events_overview_list_table',
136
-                'capability' => 'ee_read_events',
137
-            ),
138
-            'create_new'                    => array(
139
-                'func'       => '_create_new_cpt_item',
140
-                'capability' => 'ee_edit_events',
141
-            ),
142
-            'edit'                          => array(
143
-                'func'       => '_edit_cpt_item',
144
-                'capability' => 'ee_edit_event',
145
-                'obj_id'     => $evt_id,
146
-            ),
147
-            'copy_event'                    => array(
148
-                'func'       => '_copy_events',
149
-                'capability' => 'ee_edit_event',
150
-                'obj_id'     => $evt_id,
151
-                'noheader'   => true,
152
-            ),
153
-            'trash_event'                   => array(
154
-                'func'       => '_trash_or_restore_event',
155
-                'args'       => array('event_status' => 'trash'),
156
-                'capability' => 'ee_delete_event',
157
-                'obj_id'     => $evt_id,
158
-                'noheader'   => true,
159
-            ),
160
-            'trash_events'                  => array(
161
-                'func'       => '_trash_or_restore_events',
162
-                'args'       => array('event_status' => 'trash'),
163
-                'capability' => 'ee_delete_events',
164
-                'noheader'   => true,
165
-            ),
166
-            'restore_event'                 => array(
167
-                'func'       => '_trash_or_restore_event',
168
-                'args'       => array('event_status' => 'draft'),
169
-                'capability' => 'ee_delete_event',
170
-                'obj_id'     => $evt_id,
171
-                'noheader'   => true,
172
-            ),
173
-            'restore_events'                => array(
174
-                'func'       => '_trash_or_restore_events',
175
-                'args'       => array('event_status' => 'draft'),
176
-                'capability' => 'ee_delete_events',
177
-                'noheader'   => true,
178
-            ),
179
-            'delete_event'                  => array(
180
-                'func'       => '_delete_event',
181
-                'capability' => 'ee_delete_event',
182
-                'obj_id'     => $evt_id,
183
-                'noheader'   => true,
184
-            ),
185
-            'delete_events'                 => array(
186
-                'func'       => '_delete_events',
187
-                'capability' => 'ee_delete_events',
188
-                'noheader'   => true,
189
-            ),
190
-            'view_report'                   => array(
191
-                'func'      => '_view_report',
192
-                'capablity' => 'ee_edit_events',
193
-            ),
194
-            'default_event_settings'        => array(
195
-                'func'       => '_default_event_settings',
196
-                'capability' => 'manage_options',
197
-            ),
198
-            'update_default_event_settings' => array(
199
-                'func'       => '_update_default_event_settings',
200
-                'capability' => 'manage_options',
201
-                'noheader'   => true,
202
-            ),
203
-            'template_settings'             => array(
204
-                'func'       => '_template_settings',
205
-                'capability' => 'manage_options',
206
-            ),
207
-            // event category tab related
208
-            'add_category'                  => array(
209
-                'func'       => '_category_details',
210
-                'capability' => 'ee_edit_event_category',
211
-                'args'       => array('add'),
212
-            ),
213
-            'edit_category'                 => array(
214
-                'func'       => '_category_details',
215
-                'capability' => 'ee_edit_event_category',
216
-                'args'       => array('edit'),
217
-            ),
218
-            'delete_categories'             => array(
219
-                'func'       => '_delete_categories',
220
-                'capability' => 'ee_delete_event_category',
221
-                'noheader'   => true,
222
-            ),
223
-            'delete_category'               => array(
224
-                'func'       => '_delete_categories',
225
-                'capability' => 'ee_delete_event_category',
226
-                'noheader'   => true,
227
-            ),
228
-            'insert_category'               => array(
229
-                'func'       => '_insert_or_update_category',
230
-                'args'       => array('new_category' => true),
231
-                'capability' => 'ee_edit_event_category',
232
-                'noheader'   => true,
233
-            ),
234
-            'update_category'               => array(
235
-                'func'       => '_insert_or_update_category',
236
-                'args'       => array('new_category' => false),
237
-                'capability' => 'ee_edit_event_category',
238
-                'noheader'   => true,
239
-            ),
240
-            'category_list'                 => array(
241
-                'func'       => '_category_list_table',
242
-                'capability' => 'ee_manage_event_categories',
243
-            ),
244
-            'preview_deletion' => [
245
-                'func' => 'previewDeletion',
246
-                'capability' => 'ee_delete_events',
247
-            ],
248
-            'confirm_deletion' => [
249
-                'func' => 'confirmDeletion',
250
-                'capability' => 'ee_delete_events',
251
-                'noheader' => true,
252
-            ]
253
-        );
254
-    }
255
-
256
-
257
-    /**
258
-     * Set the _page_config property for this admin page group.
259
-     */
260
-    protected function _set_page_config()
261
-    {
262
-        $this->_page_config = array(
263
-            'default'                => array(
264
-                'nav'           => array(
265
-                    'label' => esc_html__('Overview', 'event_espresso'),
266
-                    'order' => 10,
267
-                ),
268
-                'list_table'    => 'Events_Admin_List_Table',
269
-                'help_tabs'     => array(
270
-                    'events_overview_help_tab'                       => array(
271
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
272
-                        'filename' => 'events_overview',
273
-                    ),
274
-                    'events_overview_table_column_headings_help_tab' => array(
275
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
276
-                        'filename' => 'events_overview_table_column_headings',
277
-                    ),
278
-                    'events_overview_filters_help_tab'               => array(
279
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
280
-                        'filename' => 'events_overview_filters',
281
-                    ),
282
-                    'events_overview_view_help_tab'                  => array(
283
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
284
-                        'filename' => 'events_overview_views',
285
-                    ),
286
-                    'events_overview_other_help_tab'                 => array(
287
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
288
-                        'filename' => 'events_overview_other',
289
-                    ),
290
-                ),
291
-                'help_tour'     => array(
292
-                    'Event_Overview_Help_Tour',
293
-                    // 'New_Features_Test_Help_Tour' for testing multiple help tour
294
-                ),
295
-                'qtips'         => array(
296
-                    'EE_Event_List_Table_Tips',
297
-                ),
298
-                'require_nonce' => false,
299
-            ),
300
-            'create_new'             => array(
301
-                'nav'           => array(
302
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
303
-                    'order'      => 5,
304
-                    'persistent' => false,
305
-                ),
306
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
307
-                'help_tabs'     => array(
308
-                    'event_editor_help_tab'                            => array(
309
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
310
-                        'filename' => 'event_editor',
311
-                    ),
312
-                    'event_editor_title_richtexteditor_help_tab'       => array(
313
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
-                        'filename' => 'event_editor_title_richtexteditor',
315
-                    ),
316
-                    'event_editor_venue_details_help_tab'              => array(
317
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
-                        'filename' => 'event_editor_venue_details',
319
-                    ),
320
-                    'event_editor_event_datetimes_help_tab'            => array(
321
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
-                        'filename' => 'event_editor_event_datetimes',
323
-                    ),
324
-                    'event_editor_event_tickets_help_tab'              => array(
325
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
-                        'filename' => 'event_editor_event_tickets',
327
-                    ),
328
-                    'event_editor_event_registration_options_help_tab' => array(
329
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
-                        'filename' => 'event_editor_event_registration_options',
331
-                    ),
332
-                    'event_editor_tags_categories_help_tab'            => array(
333
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
-                        'filename' => 'event_editor_tags_categories',
335
-                    ),
336
-                    'event_editor_questions_registrants_help_tab'      => array(
337
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
-                        'filename' => 'event_editor_questions_registrants',
339
-                    ),
340
-                    'event_editor_save_new_event_help_tab'             => array(
341
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
342
-                        'filename' => 'event_editor_save_new_event',
343
-                    ),
344
-                    'event_editor_other_help_tab'                      => array(
345
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
346
-                        'filename' => 'event_editor_other',
347
-                    ),
348
-                ),
349
-                'help_tour'     => array(
350
-                    'Event_Editor_Help_Tour',
351
-                ),
352
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
353
-                'require_nonce' => false,
354
-            ),
355
-            'edit'                   => array(
356
-                'nav'           => array(
357
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
358
-                    'order'      => 5,
359
-                    'persistent' => false,
360
-                    'url'        => isset($this->_req_data['post'])
361
-                        ? EE_Admin_Page::add_query_args_and_nonce(
362
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
363
-                            $this->_current_page_view_url
364
-                        )
365
-                        : $this->_admin_base_url,
366
-                ),
367
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
368
-                'help_tabs'     => array(
369
-                    'event_editor_help_tab'                            => array(
370
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
371
-                        'filename' => 'event_editor',
372
-                    ),
373
-                    'event_editor_title_richtexteditor_help_tab'       => array(
374
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
375
-                        'filename' => 'event_editor_title_richtexteditor',
376
-                    ),
377
-                    'event_editor_venue_details_help_tab'              => array(
378
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
379
-                        'filename' => 'event_editor_venue_details',
380
-                    ),
381
-                    'event_editor_event_datetimes_help_tab'            => array(
382
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
383
-                        'filename' => 'event_editor_event_datetimes',
384
-                    ),
385
-                    'event_editor_event_tickets_help_tab'              => array(
386
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
387
-                        'filename' => 'event_editor_event_tickets',
388
-                    ),
389
-                    'event_editor_event_registration_options_help_tab' => array(
390
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
391
-                        'filename' => 'event_editor_event_registration_options',
392
-                    ),
393
-                    'event_editor_tags_categories_help_tab'            => array(
394
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
395
-                        'filename' => 'event_editor_tags_categories',
396
-                    ),
397
-                    'event_editor_questions_registrants_help_tab'      => array(
398
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
399
-                        'filename' => 'event_editor_questions_registrants',
400
-                    ),
401
-                    'event_editor_save_new_event_help_tab'             => array(
402
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
403
-                        'filename' => 'event_editor_save_new_event',
404
-                    ),
405
-                    'event_editor_other_help_tab'                      => array(
406
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
407
-                        'filename' => 'event_editor_other',
408
-                    ),
409
-                ),
410
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
411
-                'require_nonce' => false,
412
-            ),
413
-            'default_event_settings' => array(
414
-                'nav'           => array(
415
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
416
-                    'order' => 40,
417
-                ),
418
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
419
-                'labels'        => array(
420
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
421
-                ),
422
-                'help_tabs'     => array(
423
-                    'default_settings_help_tab'        => array(
424
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
425
-                        'filename' => 'events_default_settings',
426
-                    ),
427
-                    'default_settings_status_help_tab' => array(
428
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
429
-                        'filename' => 'events_default_settings_status',
430
-                    ),
431
-                    'default_maximum_tickets_help_tab' => array(
432
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
433
-                        'filename' => 'events_default_settings_max_tickets',
434
-                    ),
435
-                ),
436
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
437
-                'require_nonce' => false,
438
-            ),
439
-            // template settings
440
-            'template_settings'      => array(
441
-                'nav'           => array(
442
-                    'label' => esc_html__('Templates', 'event_espresso'),
443
-                    'order' => 30,
444
-                ),
445
-                'metaboxes'     => $this->_default_espresso_metaboxes,
446
-                'help_tabs'     => array(
447
-                    'general_settings_templates_help_tab' => array(
448
-                        'title'    => esc_html__('Templates', 'event_espresso'),
449
-                        'filename' => 'general_settings_templates',
450
-                    ),
451
-                ),
452
-                'help_tour'     => array('Templates_Help_Tour'),
453
-                'require_nonce' => false,
454
-            ),
455
-            // event category stuff
456
-            'add_category'           => array(
457
-                'nav'           => array(
458
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
459
-                    'order'      => 15,
460
-                    'persistent' => false,
461
-                ),
462
-                'help_tabs'     => array(
463
-                    'add_category_help_tab' => array(
464
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
465
-                        'filename' => 'events_add_category',
466
-                    ),
467
-                ),
468
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
469
-                'metaboxes'     => array('_publish_post_box'),
470
-                'require_nonce' => false,
471
-            ),
472
-            'edit_category'          => array(
473
-                'nav'           => array(
474
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
475
-                    'order'      => 15,
476
-                    'persistent' => false,
477
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
478
-                        ? add_query_arg(
479
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
480
-                            $this->_current_page_view_url
481
-                        )
482
-                        : $this->_admin_base_url,
483
-                ),
484
-                'help_tabs'     => array(
485
-                    'edit_category_help_tab' => array(
486
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
487
-                        'filename' => 'events_edit_category',
488
-                    ),
489
-                ),
490
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
491
-                'metaboxes'     => array('_publish_post_box'),
492
-                'require_nonce' => false,
493
-            ),
494
-            'category_list'          => array(
495
-                'nav'           => array(
496
-                    'label' => esc_html__('Categories', 'event_espresso'),
497
-                    'order' => 20,
498
-                ),
499
-                'list_table'    => 'Event_Categories_Admin_List_Table',
500
-                'help_tabs'     => array(
501
-                    'events_categories_help_tab'                       => array(
502
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
503
-                        'filename' => 'events_categories',
504
-                    ),
505
-                    'events_categories_table_column_headings_help_tab' => array(
506
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
507
-                        'filename' => 'events_categories_table_column_headings',
508
-                    ),
509
-                    'events_categories_view_help_tab'                  => array(
510
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
511
-                        'filename' => 'events_categories_views',
512
-                    ),
513
-                    'events_categories_other_help_tab'                 => array(
514
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
515
-                        'filename' => 'events_categories_other',
516
-                    ),
517
-                ),
518
-                'help_tour'     => array(
519
-                    'Event_Categories_Help_Tour',
520
-                ),
521
-                'metaboxes'     => $this->_default_espresso_metaboxes,
522
-                'require_nonce' => false,
523
-            ),
524
-            'preview_deletion'           => array(
525
-                'nav'           => array(
526
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
527
-                    'order'      => 15,
528
-                    'persistent' => false,
529
-                ),
530
-                'require_nonce' => false
531
-            )
532
-        );
533
-    }
534
-
535
-
536
-    /**
537
-     * Used to register any global screen options if necessary for every route in this admin page group.
538
-     */
539
-    protected function _add_screen_options()
540
-    {
541
-    }
542
-
543
-
544
-    /**
545
-     * Implementing the screen options for the 'default' route.
546
-     */
547
-    protected function _add_screen_options_default()
548
-    {
549
-        $this->_per_page_screen_option();
550
-    }
551
-
552
-
553
-    /**
554
-     * Implementing screen options for the category list route.
555
-     */
556
-    protected function _add_screen_options_category_list()
557
-    {
558
-        $page_title = $this->_admin_page_title;
559
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
560
-        $this->_per_page_screen_option();
561
-        $this->_admin_page_title = $page_title;
562
-    }
563
-
564
-
565
-    /**
566
-     * Used to register any global feature pointers for the admin page group.
567
-     */
568
-    protected function _add_feature_pointers()
569
-    {
570
-    }
571
-
572
-
573
-    /**
574
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
575
-     */
576
-    public function load_scripts_styles()
577
-    {
578
-        wp_register_style(
579
-            'events-admin-css',
580
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
581
-            array(),
582
-            EVENT_ESPRESSO_VERSION
583
-        );
584
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
585
-        wp_enqueue_style('events-admin-css');
586
-        wp_enqueue_style('ee-cat-admin');
587
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
588
-        // registers for all views
589
-        // scripts
590
-        wp_register_script(
591
-            'event_editor_js',
592
-            EVENTS_ASSETS_URL . 'event_editor.js',
593
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
594
-            EVENT_ESPRESSO_VERSION,
595
-            true
596
-        );
597
-    }
598
-
599
-
600
-    /**
601
-     * Enqueuing scripts and styles specific to this view
602
-     */
603
-    public function load_scripts_styles_create_new()
604
-    {
605
-        $this->load_scripts_styles_edit();
606
-    }
607
-
608
-
609
-    /**
610
-     * Enqueuing scripts and styles specific to this view
611
-     */
612
-    public function load_scripts_styles_edit()
613
-    {
614
-        // styles
615
-        wp_enqueue_style('espresso-ui-theme');
616
-        wp_register_style(
617
-            'event-editor-css',
618
-            EVENTS_ASSETS_URL . 'event-editor.css',
619
-            array('ee-admin-css'),
620
-            EVENT_ESPRESSO_VERSION
621
-        );
622
-        wp_enqueue_style('event-editor-css');
623
-        // scripts
624
-        wp_register_script(
625
-            'event-datetime-metabox',
626
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
-            array('event_editor_js', 'ee-datepicker'),
628
-            EVENT_ESPRESSO_VERSION
629
-        );
630
-        wp_enqueue_script('event-datetime-metabox');
631
-    }
632
-
633
-
634
-    /**
635
-     * Populating the _views property for the category list table view.
636
-     */
637
-    protected function _set_list_table_views_category_list()
638
-    {
639
-        $this->_views = array(
640
-            'all' => array(
641
-                'slug'        => 'all',
642
-                'label'       => esc_html__('All', 'event_espresso'),
643
-                'count'       => 0,
644
-                'bulk_action' => array(
645
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
-                ),
647
-            ),
648
-        );
649
-    }
650
-
651
-
652
-    /**
653
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
-     */
655
-    public function admin_init()
656
-    {
657
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
658
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
659
-            'event_espresso'
660
-        );
661
-    }
662
-
663
-
664
-    /**
665
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
666
-     * group.
667
-     */
668
-    public function admin_notices()
669
-    {
670
-    }
671
-
672
-
673
-    /**
674
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
675
-     * this admin page group.
676
-     */
677
-    public function admin_footer_scripts()
678
-    {
679
-    }
680
-
681
-
682
-    /**
683
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
684
-     * warning (via EE_Error::add_error());
685
-     *
686
-     * @param  EE_Event $event Event object
687
-     * @param string    $req_type
688
-     * @return void
689
-     * @throws EE_Error
690
-     * @access public
691
-     */
692
-    public function verify_event_edit($event = null, $req_type = '')
693
-    {
694
-        // don't need to do this when processing
695
-        if (! empty($req_type)) {
696
-            return;
697
-        }
698
-        // no event?
699
-        if (empty($event)) {
700
-            // set event
701
-            $event = $this->_cpt_model_obj;
702
-        }
703
-        // STILL no event?
704
-        if (! $event instanceof EE_Event) {
705
-            return;
706
-        }
707
-        $orig_status = $event->status();
708
-        // first check if event is active.
709
-        if ($orig_status === EEM_Event::cancelled
710
-            || $orig_status === EEM_Event::postponed
711
-            || $event->is_expired()
712
-            || $event->is_inactive()
713
-        ) {
714
-            return;
715
-        }
716
-        // made it here so it IS active... next check that any of the tickets are sold.
717
-        if ($event->is_sold_out(true)) {
718
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
719
-                EE_Error::add_attention(
720
-                    sprintf(
721
-                        esc_html__(
722
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
723
-                            'event_espresso'
724
-                        ),
725
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
726
-                    )
727
-                );
728
-            }
729
-            return;
730
-        } elseif ($orig_status === EEM_Event::sold_out) {
731
-            EE_Error::add_attention(
732
-                sprintf(
733
-                    esc_html__(
734
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
735
-                        'event_espresso'
736
-                    ),
737
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
738
-                )
739
-            );
740
-        }
741
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
742
-        if (! $event->tickets_on_sale()) {
743
-            return;
744
-        }
745
-        // made it here so show warning
746
-        $this->_edit_event_warning();
747
-    }
748
-
749
-
750
-    /**
751
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
752
-     * When needed, hook this into a EE_Error::add_error() notice.
753
-     *
754
-     * @access protected
755
-     * @return void
756
-     */
757
-    protected function _edit_event_warning()
758
-    {
759
-        // we don't want to add warnings during these requests
760
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
761
-            return;
762
-        }
763
-        EE_Error::add_attention(
764
-            sprintf(
765
-                esc_html__(
766
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
767
-                    'event_espresso'
768
-                ),
769
-                '<a class="espresso-help-tab-lnk">',
770
-                '</a>'
771
-            )
772
-        );
773
-    }
774
-
775
-
776
-    /**
777
-     * When a user is creating a new event, notify them if they haven't set their timezone.
778
-     * Otherwise, do the normal logic
779
-     *
780
-     * @return string
781
-     * @throws \EE_Error
782
-     */
783
-    protected function _create_new_cpt_item()
784
-    {
785
-        $has_timezone_string = get_option('timezone_string');
786
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
787
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
788
-            EE_Error::add_attention(
789
-                sprintf(
790
-                    __(
791
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
792
-                        'event_espresso'
793
-                    ),
794
-                    '<br>',
795
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
796
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
797
-                    . '</select>',
798
-                    '<button class="button button-secondary timezone-submit">',
799
-                    '</button><span class="spinner"></span>'
800
-                ),
801
-                __FILE__,
802
-                __FUNCTION__,
803
-                __LINE__
804
-            );
805
-        }
806
-        return parent::_create_new_cpt_item();
807
-    }
808
-
809
-
810
-    /**
811
-     * Sets the _views property for the default route in this admin page group.
812
-     */
813
-    protected function _set_list_table_views_default()
814
-    {
815
-        $this->_views = array(
816
-            'all'   => array(
817
-                'slug'        => 'all',
818
-                'label'       => esc_html__('View All Events', 'event_espresso'),
819
-                'count'       => 0,
820
-                'bulk_action' => array(
821
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
822
-                ),
823
-            ),
824
-            'draft' => array(
825
-                'slug'        => 'draft',
826
-                'label'       => esc_html__('Draft', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array(
829
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
830
-                ),
831
-            ),
832
-        );
833
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
834
-            $this->_views['trash'] = array(
835
-                'slug'        => 'trash',
836
-                'label'       => esc_html__('Trash', 'event_espresso'),
837
-                'count'       => 0,
838
-                'bulk_action' => array(
839
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
840
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
841
-                ),
842
-            );
843
-        }
844
-    }
845
-
846
-
847
-    /**
848
-     * Provides the legend item array for the default list table view.
849
-     *
850
-     * @return array
851
-     */
852
-    protected function _event_legend_items()
853
-    {
854
-        $items = array(
855
-            'view_details'   => array(
856
-                'class' => 'dashicons dashicons-search',
857
-                'desc'  => esc_html__('View Event', 'event_espresso'),
858
-            ),
859
-            'edit_event'     => array(
860
-                'class' => 'ee-icon ee-icon-calendar-edit',
861
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
862
-            ),
863
-            'view_attendees' => array(
864
-                'class' => 'dashicons dashicons-groups',
865
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
866
-            ),
867
-        );
868
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
869
-        $statuses = array(
870
-            'sold_out_status'  => array(
871
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
872
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
873
-            ),
874
-            'active_status'    => array(
875
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
876
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
877
-            ),
878
-            'upcoming_status'  => array(
879
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
880
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
881
-            ),
882
-            'postponed_status' => array(
883
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
884
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
885
-            ),
886
-            'cancelled_status' => array(
887
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
888
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
889
-            ),
890
-            'expired_status'   => array(
891
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
892
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
893
-            ),
894
-            'inactive_status'  => array(
895
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
896
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
897
-            ),
898
-        );
899
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
900
-        return array_merge($items, $statuses);
901
-    }
902
-
903
-
904
-    /**
905
-     * @return EEM_Event
906
-     */
907
-    private function _event_model()
908
-    {
909
-        if (! $this->_event_model instanceof EEM_Event) {
910
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
911
-        }
912
-        return $this->_event_model;
913
-    }
914
-
915
-
916
-    /**
917
-     * Adds extra buttons to the WP CPT permalink field row.
918
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
919
-     *
920
-     * @param  string $return    the current html
921
-     * @param  int    $id        the post id for the page
922
-     * @param  string $new_title What the title is
923
-     * @param  string $new_slug  what the slug is
924
-     * @return string            The new html string for the permalink area
925
-     */
926
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
927
-    {
928
-        // make sure this is only when editing
929
-        if (! empty($id)) {
930
-            $post = get_post($id);
931
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
932
-                       . esc_html__('Shortcode', 'event_espresso')
933
-                       . '</a> ';
934
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
935
-                       . $post->ID
936
-                       . ']">';
937
-        }
938
-        return $return;
939
-    }
940
-
941
-
942
-    /**
943
-     * _events_overview_list_table
944
-     * This contains the logic for showing the events_overview list
945
-     *
946
-     * @access protected
947
-     * @return void
948
-     * @throws \EE_Error
949
-     */
950
-    protected function _events_overview_list_table()
951
-    {
952
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
953
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
954
-            ? (array) $this->_template_args['after_list_table']
955
-            : array();
956
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
957
-                . EEH_Template::get_button_or_link(
958
-                    get_post_type_archive_link('espresso_events'),
959
-                    esc_html__("View Event Archive Page", "event_espresso"),
960
-                    'button'
961
-                );
962
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
963
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
964
-            'create_new',
965
-            'add',
966
-            array(),
967
-            'add-new-h2'
968
-        );
969
-        $this->display_admin_list_table_page_with_no_sidebar();
970
-    }
971
-
972
-
973
-    /**
974
-     * this allows for extra misc actions in the default WP publish box
975
-     *
976
-     * @return void
977
-     */
978
-    public function extra_misc_actions_publish_box()
979
-    {
980
-        $this->_generate_publish_box_extra_content();
981
-    }
982
-
983
-
984
-    /**
985
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
986
-     * saved.
987
-     * Typically you would use this to save any additional data.
988
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
989
-     * ALSO very important.  When a post transitions from scheduled to published,
990
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
991
-     * other meta saves. So MAKE sure that you handle this accordingly.
992
-     *
993
-     * @access protected
994
-     * @abstract
995
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
996
-     * @param  object $post    The post object of the cpt that was saved.
997
-     * @return void
998
-     * @throws \EE_Error
999
-     */
1000
-    protected function _insert_update_cpt_item($post_id, $post)
1001
-    {
1002
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1003
-            // get out we're not processing an event save.
1004
-            return;
1005
-        }
1006
-        $event_values = array(
1007
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1008
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1009
-            'EVT_additional_limit'            => min(
1010
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1011
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1012
-            ),
1013
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1014
-                ? $this->_req_data['EVT_default_registration_status']
1015
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
1016
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1017
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1018
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1019
-                ? $this->_req_data['timezone_string'] : null,
1020
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1021
-                ? $this->_req_data['externalURL'] : null,
1022
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1023
-                ? $this->_req_data['event_phone'] : null,
1024
-        );
1025
-        // update event
1026
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1027
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1028
-        $get_one_where = array(
1029
-            $this->_event_model()->primary_key_name() => $post_id,
1030
-            'OR'                                      => array(
1031
-                'status'   => $post->post_status,
1032
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1033
-                // but the returned object here has a status of "publish", so use the original post status as well
1034
-                'status*1' => $this->_req_data['original_post_status'],
1035
-            ),
1036
-        );
1037
-        $event = $this->_event_model()->get_one(array($get_one_where));
1038
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1039
-        $event_update_callbacks = apply_filters(
1040
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1041
-            array(
1042
-                array($this, '_default_venue_update'),
1043
-                array($this, '_default_tickets_update'),
1044
-            )
1045
-        );
1046
-        $att_success = true;
1047
-        foreach ($event_update_callbacks as $e_callback) {
1048
-            $_success = is_callable($e_callback)
1049
-                ? call_user_func($e_callback, $event, $this->_req_data)
1050
-                : false;
1051
-            // if ANY of these updates fail then we want the appropriate global error message
1052
-            $att_success = ! $att_success ? $att_success : $_success;
1053
-        }
1054
-        // any errors?
1055
-        if ($success && false === $att_success) {
1056
-            EE_Error::add_error(
1057
-                esc_html__(
1058
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1059
-                    'event_espresso'
1060
-                ),
1061
-                __FILE__,
1062
-                __FUNCTION__,
1063
-                __LINE__
1064
-            );
1065
-        } elseif ($success === false) {
1066
-            EE_Error::add_error(
1067
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1068
-                __FILE__,
1069
-                __FUNCTION__,
1070
-                __LINE__
1071
-            );
1072
-        }
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * @see parent::restore_item()
1078
-     * @param int $post_id
1079
-     * @param int $revision_id
1080
-     */
1081
-    protected function _restore_cpt_item($post_id, $revision_id)
1082
-    {
1083
-        // copy existing event meta to new post
1084
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1085
-        if ($post_evt instanceof EE_Event) {
1086
-            // meta revision restore
1087
-            $post_evt->restore_revision($revision_id);
1088
-            // related objs restore
1089
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1090
-        }
1091
-    }
1092
-
1093
-
1094
-    /**
1095
-     * Attach the venue to the Event
1096
-     *
1097
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1098
-     * @param  array     $data   The request data from the form
1099
-     * @return bool           Success or fail.
1100
-     */
1101
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1102
-    {
1103
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1104
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1105
-        $rows_affected = null;
1106
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1107
-        // very important.  If we don't have a venue name...
1108
-        // then we'll get out because not necessary to create empty venue
1109
-        if (empty($data['venue_title'])) {
1110
-            return false;
1111
-        }
1112
-        $venue_array = array(
1113
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1114
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1115
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1116
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1117
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1118
-                : null,
1119
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1120
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1121
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1122
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1123
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1124
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1125
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1126
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1127
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1128
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1129
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1130
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1131
-            'status'              => 'publish',
1132
-        );
1133
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1134
-        if (! empty($venue_id)) {
1135
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1136
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1137
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1138
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1139
-            return $rows_affected > 0 ? true : false;
1140
-        } else {
1141
-            // we insert the venue
1142
-            $venue_id = $venue_model->insert($venue_array);
1143
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1144
-            return ! empty($venue_id) ? true : false;
1145
-        }
1146
-        // when we have the ancestor come in it's already been handled by the revision save.
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1152
-     *
1153
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1154
-     * @param  array    $data   The request data from the form
1155
-     * @return array
1156
-     */
1157
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1158
-    {
1159
-        $success = true;
1160
-        $saved_dtt = null;
1161
-        $saved_tickets = array();
1162
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1163
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1164
-            // trim all values to ensure any excess whitespace is removed.
1165
-            $dtt = array_map('trim', $dtt);
1166
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1167
-                : $dtt['DTT_EVT_start'];
1168
-            $datetime_values = array(
1169
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1170
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1171
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1172
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1173
-                'DTT_order'     => $row,
1174
-            );
1175
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1176
-            if (! empty($dtt['DTT_ID'])) {
1177
-                $DTM = EE_Registry::instance()
1178
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1179
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1180
-                $DTM->set_date_format($incoming_date_formats[0]);
1181
-                $DTM->set_time_format($incoming_date_formats[1]);
1182
-                foreach ($datetime_values as $field => $value) {
1183
-                    $DTM->set($field, $value);
1184
-                }
1185
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1186
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1187
-            } else {
1188
-                $DTM = EE_Registry::instance()->load_class(
1189
-                    'Datetime',
1190
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1191
-                    false,
1192
-                    false
1193
-                );
1194
-                foreach ($datetime_values as $field => $value) {
1195
-                    $DTM->set($field, $value);
1196
-                }
1197
-            }
1198
-            $DTM->save();
1199
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1200
-            // load DTT helper
1201
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1202
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1203
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1204
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1205
-                $DTT->save();
1206
-            }
1207
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1208
-            $saved_dtt = $DTT;
1209
-            $success = ! $success ? $success : $DTT;
1210
-            // if ANY of these updates fail then we want the appropriate global error message.
1211
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1212
-        }
1213
-        // no dtts get deleted so we don't do any of that logic here.
1214
-        // update tickets next
1215
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1216
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1217
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1218
-            $update_prices = false;
1219
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1220
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1221
-            // trim inputs to ensure any excess whitespace is removed.
1222
-            $tkt = array_map('trim', $tkt);
1223
-            if (empty($tkt['TKT_start_date'])) {
1224
-                // let's use now in the set timezone.
1225
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1226
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1227
-            }
1228
-            if (empty($tkt['TKT_end_date'])) {
1229
-                // use the start date of the first datetime
1230
-                $dtt = $evtobj->first_datetime();
1231
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1232
-                    $incoming_date_formats[0],
1233
-                    $incoming_date_formats[1]
1234
-                );
1235
-            }
1236
-            $TKT_values = array(
1237
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1238
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1239
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1240
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1241
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1242
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1243
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1244
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1245
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1246
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1247
-                'TKT_row'         => $row,
1248
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1249
-                'TKT_price'       => $ticket_price,
1250
-            );
1251
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1252
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1253
-                $TKT_values['TKT_ID'] = 0;
1254
-                $TKT_values['TKT_is_default'] = 0;
1255
-                $TKT_values['TKT_price'] = $ticket_price;
1256
-                $update_prices = true;
1257
-            }
1258
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1259
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1260
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1261
-            if (! empty($tkt['TKT_ID'])) {
1262
-                $TKT = EE_Registry::instance()
1263
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1264
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1265
-                if ($TKT instanceof EE_Ticket) {
1266
-                    $ticket_sold = $TKT->count_related(
1267
-                        'Registration',
1268
-                        array(
1269
-                            array(
1270
-                                'STS_ID' => array(
1271
-                                    'NOT IN',
1272
-                                    array(EEM_Registration::status_id_incomplete),
1273
-                                ),
1274
-                            ),
1275
-                        )
1276
-                    ) > 0 ? true : false;
1277
-                    // let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1278
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1279
-                                      && ! $TKT->get('TKT_deleted');
1280
-                    $TKT->set_date_format($incoming_date_formats[0]);
1281
-                    $TKT->set_time_format($incoming_date_formats[1]);
1282
-                    // set new values
1283
-                    foreach ($TKT_values as $field => $value) {
1284
-                        if ($field == 'TKT_qty') {
1285
-                            $TKT->set_qty($value);
1286
-                        } else {
1287
-                            $TKT->set($field, $value);
1288
-                        }
1289
-                    }
1290
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1291
-                    if ($create_new_TKT) {
1292
-                        // archive the old ticket first
1293
-                        $TKT->set('TKT_deleted', 1);
1294
-                        $TKT->save();
1295
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1296
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1297
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1298
-                        $TKT = clone $TKT;
1299
-                        $TKT->set('TKT_ID', 0);
1300
-                        $TKT->set('TKT_deleted', 0);
1301
-                        $TKT->set('TKT_price', $ticket_price);
1302
-                        $TKT->set('TKT_sold', 0);
1303
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1304
-                        $update_prices = true;
1305
-                    }
1306
-                    // make sure price is set if it hasn't been already
1307
-                    $TKT->set('TKT_price', $ticket_price);
1308
-                }
1309
-            } else {
1310
-                // no TKT_id so a new TKT
1311
-                $TKT_values['TKT_price'] = $ticket_price;
1312
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1313
-                if ($TKT instanceof EE_Ticket) {
1314
-                    // need to reset values to properly account for the date formats
1315
-                    $TKT->set_date_format($incoming_date_formats[0]);
1316
-                    $TKT->set_time_format($incoming_date_formats[1]);
1317
-                    $TKT->set_timezone($evtobj->get_timezone());
1318
-                    // set new values
1319
-                    foreach ($TKT_values as $field => $value) {
1320
-                        if ($field == 'TKT_qty') {
1321
-                            $TKT->set_qty($value);
1322
-                        } else {
1323
-                            $TKT->set($field, $value);
1324
-                        }
1325
-                    }
1326
-                    $update_prices = true;
1327
-                }
1328
-            }
1329
-            // cap ticket qty by datetime reg limits
1330
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1331
-            // update ticket.
1332
-            $TKT->save();
1333
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1334
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1335
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1336
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1337
-                $TKT->save();
1338
-            }
1339
-            // initially let's add the ticket to the dtt
1340
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1341
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1342
-            // add prices to ticket
1343
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1344
-        }
1345
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1346
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1347
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1348
-        foreach ($tickets_removed as $id) {
1349
-            $id = absint($id);
1350
-            // get the ticket for this id
1351
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1352
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1353
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1354
-            foreach ($dtts as $dtt) {
1355
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1356
-            }
1357
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1358
-            $tkt_to_remove->delete_related_permanently('Price');
1359
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1360
-            $tkt_to_remove->delete_permanently();
1361
-        }
1362
-        return array($saved_dtt, $saved_tickets);
1363
-    }
1364
-
1365
-
1366
-    /**
1367
-     * This attaches a list of given prices to a ticket.
1368
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1369
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1370
-     * price info and prices are automatically "archived" via the ticket.
1371
-     *
1372
-     * @access  private
1373
-     * @param array     $prices     Array of prices from the form.
1374
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1375
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1376
-     * @return  void
1377
-     */
1378
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1379
-    {
1380
-        foreach ($prices as $row => $prc) {
1381
-            $PRC_values = array(
1382
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1383
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1384
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1385
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1386
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1387
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1388
-                'PRC_order'      => $row,
1389
-            );
1390
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1391
-                $PRC_values['PRC_ID'] = 0;
1392
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1393
-            } else {
1394
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1395
-                // update this price with new values
1396
-                foreach ($PRC_values as $field => $newprc) {
1397
-                    $PRC->set($field, $newprc);
1398
-                }
1399
-                $PRC->save();
1400
-            }
1401
-            $ticket->_add_relation_to($PRC, 'Price');
1402
-        }
1403
-    }
1404
-
1405
-
1406
-    /**
1407
-     * Add in our autosave ajax handlers
1408
-     *
1409
-     */
1410
-    protected function _ee_autosave_create_new()
1411
-    {
1412
-    }
1413
-
1414
-
1415
-    /**
1416
-     * More autosave handlers.
1417
-     */
1418
-    protected function _ee_autosave_edit()
1419
-    {
1420
-        return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     *    _generate_publish_box_extra_content
1426
-     */
1427
-    private function _generate_publish_box_extra_content()
1428
-    {
1429
-        // load formatter helper
1430
-        // args for getting related registrations
1431
-        $approved_query_args = array(
1432
-            array(
1433
-                'REG_deleted' => 0,
1434
-                'STS_ID'      => EEM_Registration::status_id_approved,
1435
-            ),
1436
-        );
1437
-        $not_approved_query_args = array(
1438
-            array(
1439
-                'REG_deleted' => 0,
1440
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1441
-            ),
1442
-        );
1443
-        $pending_payment_query_args = array(
1444
-            array(
1445
-                'REG_deleted' => 0,
1446
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1447
-            ),
1448
-        );
1449
-        // publish box
1450
-        $publish_box_extra_args = array(
1451
-            'view_approved_reg_url'        => add_query_arg(
1452
-                array(
1453
-                    'action'      => 'default',
1454
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1455
-                    '_reg_status' => EEM_Registration::status_id_approved,
1456
-                ),
1457
-                REG_ADMIN_URL
1458
-            ),
1459
-            'view_not_approved_reg_url'    => add_query_arg(
1460
-                array(
1461
-                    'action'      => 'default',
1462
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1463
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1464
-                ),
1465
-                REG_ADMIN_URL
1466
-            ),
1467
-            'view_pending_payment_reg_url' => add_query_arg(
1468
-                array(
1469
-                    'action'      => 'default',
1470
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1471
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1472
-                ),
1473
-                REG_ADMIN_URL
1474
-            ),
1475
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1476
-                'Registration',
1477
-                $approved_query_args
1478
-            ),
1479
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1480
-                'Registration',
1481
-                $not_approved_query_args
1482
-            ),
1483
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1484
-                'Registration',
1485
-                $pending_payment_query_args
1486
-            ),
1487
-            'misc_pub_section_class'       => apply_filters(
1488
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1489
-                'misc-pub-section'
1490
-            ),
1491
-        );
1492
-        ob_start();
1493
-        do_action(
1494
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1495
-            $this->_cpt_model_obj
1496
-        );
1497
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1498
-        // load template
1499
-        EEH_Template::display_template(
1500
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1501
-            $publish_box_extra_args
1502
-        );
1503
-    }
1504
-
1505
-
1506
-    /**
1507
-     * @return EE_Event
1508
-     */
1509
-    public function get_event_object()
1510
-    {
1511
-        return $this->_cpt_model_obj;
1512
-    }
1513
-
1514
-
1515
-
1516
-
1517
-    /** METABOXES * */
1518
-    /**
1519
-     * _register_event_editor_meta_boxes
1520
-     * add all metaboxes related to the event_editor
1521
-     *
1522
-     * @return void
1523
-     */
1524
-    protected function _register_event_editor_meta_boxes()
1525
-    {
1526
-        $this->verify_cpt_object();
1527
-        add_meta_box(
1528
-            'espresso_event_editor_tickets',
1529
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1530
-            array($this, 'ticket_metabox'),
1531
-            $this->page_slug,
1532
-            'normal',
1533
-            'high'
1534
-        );
1535
-        add_meta_box(
1536
-            'espresso_event_editor_event_options',
1537
-            esc_html__('Event Registration Options', 'event_espresso'),
1538
-            array($this, 'registration_options_meta_box'),
1539
-            $this->page_slug,
1540
-            'side',
1541
-            'default'
1542
-        );
1543
-        // NOTE: if you're looking for other metaboxes in here,
1544
-        // where a metabox has a related management page in the admin
1545
-        // you will find it setup in the related management page's "_Hooks" file.
1546
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1547
-    }
1548
-
1549
-
1550
-    /**
1551
-     * @throws DomainException
1552
-     * @throws EE_Error
1553
-     */
1554
-    public function ticket_metabox()
1555
-    {
1556
-        $existing_datetime_ids = $existing_ticket_ids = array();
1557
-        // defaults for template args
1558
-        $template_args = array(
1559
-            'existing_datetime_ids'    => '',
1560
-            'event_datetime_help_link' => '',
1561
-            'ticket_options_help_link' => '',
1562
-            'time'                     => null,
1563
-            'ticket_rows'              => '',
1564
-            'existing_ticket_ids'      => '',
1565
-            'total_ticket_rows'        => 1,
1566
-            'ticket_js_structure'      => '',
1567
-            'trash_icon'               => 'ee-lock-icon',
1568
-            'disabled'                 => '',
1569
-        );
1570
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1571
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1572
-        /**
1573
-         * 1. Start with retrieving Datetimes
1574
-         * 2. Fore each datetime get related tickets
1575
-         * 3. For each ticket get related prices
1576
-         */
1577
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1578
-        /** @type EE_Datetime $first_datetime */
1579
-        $first_datetime = reset($times);
1580
-        // do we get related tickets?
1581
-        if ($first_datetime instanceof EE_Datetime
1582
-            && $first_datetime->ID() !== 0
1583
-        ) {
1584
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1585
-            $template_args['time'] = $first_datetime;
1586
-            $related_tickets = $first_datetime->tickets(
1587
-                array(
1588
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1589
-                    'default_where_conditions' => 'none',
1590
-                )
1591
-            );
1592
-            if (! empty($related_tickets)) {
1593
-                $template_args['total_ticket_rows'] = count($related_tickets);
1594
-                $row = 0;
1595
-                foreach ($related_tickets as $ticket) {
1596
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1597
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1598
-                    $row++;
1599
-                }
1600
-            } else {
1601
-                $template_args['total_ticket_rows'] = 1;
1602
-                /** @type EE_Ticket $ticket */
1603
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1604
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1605
-            }
1606
-        } else {
1607
-            $template_args['time'] = $times[0];
1608
-            /** @type EE_Ticket $ticket */
1609
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1610
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1611
-            // NOTE: we're just sending the first default row
1612
-            // (decaf can't manage default tickets so this should be sufficient);
1613
-        }
1614
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1615
-            'event_editor_event_datetimes_help_tab'
1616
-        );
1617
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1618
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1619
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1620
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1621
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1622
-            true
1623
-        );
1624
-        $template = apply_filters(
1625
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1626
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1627
-        );
1628
-        EEH_Template::display_template($template, $template_args);
1629
-    }
1630
-
1631
-
1632
-    /**
1633
-     * Setup an individual ticket form for the decaf event editor page
1634
-     *
1635
-     * @access private
1636
-     * @param  EE_Ticket $ticket   the ticket object
1637
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1638
-     * @param int        $row
1639
-     * @return string generated html for the ticket row.
1640
-     */
1641
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1642
-    {
1643
-        $template_args = array(
1644
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1645
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1646
-                : '',
1647
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1648
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1649
-            'TKT_name'            => $ticket->get('TKT_name'),
1650
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1651
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1652
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1653
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1654
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1655
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1656
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1657
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1658
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1659
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1660
-                : ' disabled=disabled',
1661
-        );
1662
-        $price = $ticket->ID() !== 0
1663
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1664
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1665
-        $price_args = array(
1666
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1667
-            'PRC_amount'            => $price->get('PRC_amount'),
1668
-            'PRT_ID'                => $price->get('PRT_ID'),
1669
-            'PRC_ID'                => $price->get('PRC_ID'),
1670
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1671
-        );
1672
-        // make sure we have default start and end dates if skeleton
1673
-        // handle rows that should NOT be empty
1674
-        if (empty($template_args['TKT_start_date'])) {
1675
-            // if empty then the start date will be now.
1676
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1677
-        }
1678
-        if (empty($template_args['TKT_end_date'])) {
1679
-            // get the earliest datetime (if present);
1680
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1681
-                ? $this->_cpt_model_obj->get_first_related(
1682
-                    'Datetime',
1683
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1684
-                )
1685
-                : null;
1686
-            if (! empty($earliest_dtt)) {
1687
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1688
-            } else {
1689
-                $template_args['TKT_end_date'] = date(
1690
-                    'Y-m-d h:i a',
1691
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1692
-                );
1693
-            }
1694
-        }
1695
-        $template_args = array_merge($template_args, $price_args);
1696
-        $template = apply_filters(
1697
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1698
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1699
-            $ticket
1700
-        );
1701
-        return EEH_Template::display_template($template, $template_args, true);
1702
-    }
1703
-
1704
-
1705
-    /**
1706
-     * @throws DomainException
1707
-     */
1708
-    public function registration_options_meta_box()
1709
-    {
1710
-        $yes_no_values = array(
1711
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1712
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1713
-        );
1714
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1715
-            array(
1716
-                EEM_Registration::status_id_cancelled,
1717
-                EEM_Registration::status_id_declined,
1718
-                EEM_Registration::status_id_incomplete,
1719
-            ),
1720
-            true
1721
-        );
1722
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1723
-        $template_args['_event'] = $this->_cpt_model_obj;
1724
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1725
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1726
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1727
-            'default_reg_status',
1728
-            $default_reg_status_values,
1729
-            $this->_cpt_model_obj->default_registration_status()
1730
-        );
1731
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1732
-            'display_desc',
1733
-            $yes_no_values,
1734
-            $this->_cpt_model_obj->display_description()
1735
-        );
1736
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1737
-            'display_ticket_selector',
1738
-            $yes_no_values,
1739
-            $this->_cpt_model_obj->display_ticket_selector(),
1740
-            '',
1741
-            '',
1742
-            false
1743
-        );
1744
-        $template_args['additional_registration_options'] = apply_filters(
1745
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1746
-            '',
1747
-            $template_args,
1748
-            $yes_no_values,
1749
-            $default_reg_status_values
1750
-        );
1751
-        EEH_Template::display_template(
1752
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1753
-            $template_args
1754
-        );
1755
-    }
1756
-
1757
-
1758
-    /**
1759
-     * _get_events()
1760
-     * This method simply returns all the events (for the given _view and paging)
1761
-     *
1762
-     * @access public
1763
-     * @param int  $per_page     count of items per page (20 default);
1764
-     * @param int  $current_page what is the current page being viewed.
1765
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1766
-     *                           If FALSE then we return an array of event objects
1767
-     *                           that match the given _view and paging parameters.
1768
-     * @return array an array of event objects.
1769
-     */
1770
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1771
-    {
1772
-        $EEME = $this->_event_model();
1773
-        $offset = ($current_page - 1) * $per_page;
1774
-        $limit = $count ? null : $offset . ',' . $per_page;
1775
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1776
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1777
-        if (isset($this->_req_data['month_range'])) {
1778
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1779
-            // simulate the FIRST day of the month, that fixes issues for months like February
1780
-            // where PHP doesn't know what to assume for date.
1781
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1782
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1783
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1784
-        }
1785
-        $where = array();
1786
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1787
-        // determine what post_status our condition will have for the query.
1788
-        switch ($status) {
1789
-            case 'month':
1790
-            case 'today':
1791
-            case null:
1792
-            case 'all':
1793
-                break;
1794
-            case 'draft':
1795
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1796
-                break;
1797
-            default:
1798
-                $where['status'] = $status;
1799
-        }
1800
-        // categories?
1801
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1802
-            ? $this->_req_data['EVT_CAT'] : null;
1803
-        if (! empty($category)) {
1804
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1805
-            $where['Term_Taxonomy.term_id'] = $category;
1806
-        }
1807
-        // date where conditions
1808
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1809
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1810
-            $DateTime = new DateTime(
1811
-                $year_r . '-' . $month_r . '-01 00:00:00',
1812
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1813
-            );
1814
-            $start = $DateTime->format(implode(' ', $start_formats));
1815
-            $end = $DateTime->setDate(
1816
-                $year_r,
1817
-                $month_r,
1818
-                $DateTime
1819
-                    ->format('t')
1820
-            )->setTime(23, 59, 59)
1821
-                            ->format(implode(' ', $start_formats));
1822
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1823
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1824
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1825
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1826
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1827
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1828
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1829
-            $now = date('Y-m-01');
1830
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1831
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1832
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1833
-                            ->setTime(23, 59, 59)
1834
-                            ->format(implode(' ', $start_formats));
1835
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1836
-        }
1837
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1838
-            $where['EVT_wp_user'] = get_current_user_id();
1839
-        } else {
1840
-            if (! isset($where['status'])) {
1841
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1842
-                    $where['OR'] = array(
1843
-                        'status*restrict_private' => array('!=', 'private'),
1844
-                        'AND'                     => array(
1845
-                            'status*inclusive' => array('=', 'private'),
1846
-                            'EVT_wp_user'      => get_current_user_id(),
1847
-                        ),
1848
-                    );
1849
-                }
1850
-            }
1851
-        }
1852
-        if (isset($this->_req_data['EVT_wp_user'])) {
1853
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1854
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1855
-            ) {
1856
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1857
-            }
1858
-        }
1859
-        // search query handling
1860
-        if (isset($this->_req_data['s'])) {
1861
-            $search_string = '%' . $this->_req_data['s'] . '%';
1862
-            $where['OR'] = array(
1863
-                'EVT_name'       => array('LIKE', $search_string),
1864
-                'EVT_desc'       => array('LIKE', $search_string),
1865
-                'EVT_short_desc' => array('LIKE', $search_string),
1866
-            );
1867
-        }
1868
-        // filter events by venue.
1869
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1870
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1871
-        }
1872
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1873
-        $query_params = apply_filters(
1874
-            'FHEE__Events_Admin_Page__get_events__query_params',
1875
-            array(
1876
-                $where,
1877
-                'limit'    => $limit,
1878
-                'order_by' => $orderby,
1879
-                'order'    => $order,
1880
-                'group_by' => 'EVT_ID',
1881
-            ),
1882
-            $this->_req_data
1883
-        );
1884
-        // let's first check if we have special requests coming in.
1885
-        if (isset($this->_req_data['active_status'])) {
1886
-            switch ($this->_req_data['active_status']) {
1887
-                case 'upcoming':
1888
-                    return $EEME->get_upcoming_events($query_params, $count);
1889
-                    break;
1890
-                case 'expired':
1891
-                    return $EEME->get_expired_events($query_params, $count);
1892
-                    break;
1893
-                case 'active':
1894
-                    return $EEME->get_active_events($query_params, $count);
1895
-                    break;
1896
-                case 'inactive':
1897
-                    return $EEME->get_inactive_events($query_params, $count);
1898
-                    break;
1899
-            }
1900
-        }
1901
-
1902
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1903
-        return $events;
1904
-    }
1905
-
1906
-
1907
-    /**
1908
-     * handling for WordPress CPT actions (trash, restore, delete)
1909
-     *
1910
-     * @param string $post_id
1911
-     */
1912
-    public function trash_cpt_item($post_id)
1913
-    {
1914
-        $this->_req_data['EVT_ID'] = $post_id;
1915
-        $this->_trash_or_restore_event('trash', false);
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * @param string $post_id
1921
-     */
1922
-    public function restore_cpt_item($post_id)
1923
-    {
1924
-        $this->_req_data['EVT_ID'] = $post_id;
1925
-        $this->_trash_or_restore_event('draft', false);
1926
-    }
1927
-
1928
-
1929
-    /**
1930
-     * @param string $post_id
1931
-     */
1932
-    public function delete_cpt_item($post_id)
1933
-    {
1934
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1935
-        $this->_req_data['EVT_ID'] = $post_id;
1936
-        $this->_delete_event();
1937
-    }
1938
-
1939
-
1940
-    /**
1941
-     * _trash_or_restore_event
1942
-     *
1943
-     * @access protected
1944
-     * @param  string $event_status
1945
-     * @param bool    $redirect_after
1946
-     */
1947
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1948
-    {
1949
-        // determine the event id and set to array.
1950
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1951
-        // loop thru events
1952
-        if ($EVT_ID) {
1953
-            // clean status
1954
-            $event_status = sanitize_key($event_status);
1955
-            // grab status
1956
-            if (! empty($event_status)) {
1957
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1958
-            } else {
1959
-                $success = false;
1960
-                $msg = esc_html__(
1961
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1962
-                    'event_espresso'
1963
-                );
1964
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1965
-            }
1966
-        } else {
1967
-            $success = false;
1968
-            $msg = esc_html__(
1969
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1970
-                'event_espresso'
1971
-            );
1972
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1973
-        }
1974
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1975
-        if ($redirect_after) {
1976
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1977
-        }
1978
-    }
1979
-
1980
-
1981
-    /**
1982
-     * _trash_or_restore_events
1983
-     *
1984
-     * @access protected
1985
-     * @param  string $event_status
1986
-     * @return void
1987
-     */
1988
-    protected function _trash_or_restore_events($event_status = 'trash')
1989
-    {
1990
-        // clean status
1991
-        $event_status = sanitize_key($event_status);
1992
-        // grab status
1993
-        if (! empty($event_status)) {
1994
-            $success = true;
1995
-            // determine the event id and set to array.
1996
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1997
-            // loop thru events
1998
-            foreach ($EVT_IDs as $EVT_ID) {
1999
-                if ($EVT_ID = absint($EVT_ID)) {
2000
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2001
-                    $success = $results !== false ? $success : false;
2002
-                } else {
2003
-                    $msg = sprintf(
2004
-                        esc_html__(
2005
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2006
-                            'event_espresso'
2007
-                        ),
2008
-                        $EVT_ID
2009
-                    );
2010
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2011
-                    $success = false;
2012
-                }
2013
-            }
2014
-        } else {
2015
-            $success = false;
2016
-            $msg = esc_html__(
2017
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2018
-                'event_espresso'
2019
-            );
2020
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2021
-        }
2022
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2023
-        $success = $success ? 2 : false;
2024
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2025
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2026
-    }
2027
-
2028
-
2029
-    /**
2030
-     * _trash_or_restore_events
2031
-     *
2032
-     * @access  private
2033
-     * @param  int    $EVT_ID
2034
-     * @param  string $event_status
2035
-     * @return bool
2036
-     */
2037
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2038
-    {
2039
-        // grab event id
2040
-        if (! $EVT_ID) {
2041
-            $msg = esc_html__(
2042
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2043
-                'event_espresso'
2044
-            );
2045
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
-            return false;
2047
-        }
2048
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2049
-        // clean status
2050
-        $event_status = sanitize_key($event_status);
2051
-        // grab status
2052
-        if (empty($event_status)) {
2053
-            $msg = esc_html__(
2054
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2055
-                'event_espresso'
2056
-            );
2057
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2058
-            return false;
2059
-        }
2060
-        // was event trashed or restored ?
2061
-        switch ($event_status) {
2062
-            case 'draft':
2063
-                $action = 'restored from the trash';
2064
-                $hook = 'AHEE_event_restored_from_trash';
2065
-                break;
2066
-            case 'trash':
2067
-                $action = 'moved to the trash';
2068
-                $hook = 'AHEE_event_moved_to_trash';
2069
-                break;
2070
-            default:
2071
-                $action = 'updated';
2072
-                $hook = false;
2073
-        }
2074
-        // use class to change status
2075
-        $this->_cpt_model_obj->set_status($event_status);
2076
-        $success = $this->_cpt_model_obj->save();
2077
-        if ($success === false) {
2078
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2079
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2080
-            return false;
2081
-        }
2082
-        if ($hook) {
2083
-            do_action($hook);
2084
-        }
2085
-        return true;
2086
-    }
2087
-
2088
-
2089
-    /**
2090
-     * _delete_event
2091
-     *
2092
-     * @access protected
2093
-     * @param bool $redirect_after
2094
-     */
2095
-    protected function _delete_event()
2096
-    {
2097
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : array());
2098
-    }
2099
-
2100
-    /**
2101
-     * Gets the tree traversal batch persister.
2102
-     * @since $VID:$
2103
-     * @return NodeGroupDao
2104
-     * @throws InvalidArgumentException
2105
-     * @throws InvalidDataTypeException
2106
-     * @throws InvalidInterfaceException
2107
-     */
2108
-    protected function getModelObjNodeGroupPersister()
2109
-    {
2110
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2111
-            $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2112
-        }
2113
-        return $this->model_obj_node_group_persister;
2114
-    }
2115
-
2116
-    /**
2117
-     * _delete_events
2118
-     *
2119
-     * @access protected
2120
-     * @return void
2121
-     */
2122
-    protected function _delete_events()
2123
-    {
2124
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array());
2125
-    }
2126
-
2127
-    protected function generateDeletionPreview($event_ids)
2128
-    {
2129
-        $event_ids = (array) $event_ids;
2130
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2131
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2132
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2133
-            [
2134
-                'action' => 'preview_deletion',
2135
-                'deletion_job_code' => $deletion_job_code,
2136
-            ],
2137
-            $this->_admin_base_url
2138
-        );
2139
-        $event_ids = array_map(
2140
-            'intval',
2141
-            $event_ids
2142
-        );
2143
-
2144
-        EEH_URL::safeRedirectAndExit(
2145
-            EE_Admin_Page::add_query_args_and_nonce(
2146
-                array(
2147
-                    'page'        => 'espresso_batch',
2148
-                    'batch'       => EED_Batch::batch_job,
2149
-                    'EVT_IDs'      => $event_ids,
2150
-                    'deletion_job_code' => $deletion_job_code,
2151
-                    'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2152
-                    'return_url'  => urlencode($return_url),
2153
-                ),
2154
-                admin_url()
2155
-            )
2156
-        );
2157
-    }
2158
-
2159
-    /**
2160
-     * Checks for a POST submission
2161
-     * @since $VID:$
2162
-     */
2163
-    protected function confirmDeletion()
2164
-    {
2165
-        $deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2166
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2167
-    }
2168
-
2169
-    /**
2170
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2171
-     * @since $VID:$
2172
-     * @throws EE_Error
2173
-     */
2174
-    protected function previewDeletion()
2175
-    {
2176
-        $preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2177
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2178
-        $this->display_admin_page_with_no_sidebar();
2179
-    }
2180
-
2181
-    /**
2182
-     * get total number of events
2183
-     *
2184
-     * @access public
2185
-     * @return int
2186
-     */
2187
-    public function total_events()
2188
-    {
2189
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2190
-        return $count;
2191
-    }
2192
-
2193
-
2194
-    /**
2195
-     * get total number of draft events
2196
-     *
2197
-     * @access public
2198
-     * @return int
2199
-     */
2200
-    public function total_events_draft()
2201
-    {
2202
-        $where = array(
2203
-            'status' => array('IN', array('draft', 'auto-draft')),
2204
-        );
2205
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2206
-        return $count;
2207
-    }
2208
-
2209
-
2210
-    /**
2211
-     * get total number of trashed events
2212
-     *
2213
-     * @access public
2214
-     * @return int
2215
-     */
2216
-    public function total_trashed_events()
2217
-    {
2218
-        $where = array(
2219
-            'status' => 'trash',
2220
-        );
2221
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2222
-        return $count;
2223
-    }
2224
-
2225
-
2226
-    /**
2227
-     *    _default_event_settings
2228
-     *    This generates the Default Settings Tab
2229
-     *
2230
-     * @return void
2231
-     * @throws EE_Error
2232
-     */
2233
-    protected function _default_event_settings()
2234
-    {
2235
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2236
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2237
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2238
-        $this->display_admin_page_with_sidebar();
2239
-    }
2240
-
2241
-
2242
-    /**
2243
-     * Return the form for event settings.
2244
-     *
2245
-     * @return EE_Form_Section_Proper
2246
-     * @throws EE_Error
2247
-     */
2248
-    protected function _default_event_settings_form()
2249
-    {
2250
-        $registration_config = EE_Registry::instance()->CFG->registration;
2251
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2252
-            // exclude
2253
-            array(
2254
-                EEM_Registration::status_id_cancelled,
2255
-                EEM_Registration::status_id_declined,
2256
-                EEM_Registration::status_id_incomplete,
2257
-                EEM_Registration::status_id_wait_list,
2258
-            ),
2259
-            true
2260
-        );
2261
-        return new EE_Form_Section_Proper(
2262
-            array(
2263
-                'name'            => 'update_default_event_settings',
2264
-                'html_id'         => 'update_default_event_settings',
2265
-                'html_class'      => 'form-table',
2266
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2267
-                'subsections'     => apply_filters(
2268
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2269
-                    array(
2270
-                        'default_reg_status'  => new EE_Select_Input(
2271
-                            $registration_stati_for_selection,
2272
-                            array(
2273
-                                'default'         => isset($registration_config->default_STS_ID)
2274
-                                                     && array_key_exists(
2275
-                                                         $registration_config->default_STS_ID,
2276
-                                                         $registration_stati_for_selection
2277
-                                                     )
2278
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2279
-                                    : EEM_Registration::status_id_pending_payment,
2280
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2281
-                                                     . EEH_Template::get_help_tab_link(
2282
-                                                         'default_settings_status_help_tab'
2283
-                                                     ),
2284
-                                'html_help_text'  => esc_html__(
2285
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2286
-                                    'event_espresso'
2287
-                                ),
2288
-                            )
2289
-                        ),
2290
-                        'default_max_tickets' => new EE_Integer_Input(
2291
-                            array(
2292
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2293
-                                    ? $registration_config->default_maximum_number_of_tickets
2294
-                                    : EEM_Event::get_default_additional_limit(),
2295
-                                'html_label_text' => esc_html__(
2296
-                                    'Default Maximum Tickets Allowed Per Order:',
2297
-                                    'event_espresso'
2298
-                                )
2299
-                                                     . EEH_Template::get_help_tab_link(
2300
-                                                         'default_maximum_tickets_help_tab"'
2301
-                                                     ),
2302
-                                'html_help_text'  => esc_html__(
2303
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2304
-                                    'event_espresso'
2305
-                                ),
2306
-                            )
2307
-                        ),
2308
-                    )
2309
-                ),
2310
-            )
2311
-        );
2312
-    }
2313
-
2314
-
2315
-    /**
2316
-     * _update_default_event_settings
2317
-     *
2318
-     * @access protected
2319
-     * @return void
2320
-     * @throws EE_Error
2321
-     */
2322
-    protected function _update_default_event_settings()
2323
-    {
2324
-        $registration_config = EE_Registry::instance()->CFG->registration;
2325
-        $form = $this->_default_event_settings_form();
2326
-        if ($form->was_submitted()) {
2327
-            $form->receive_form_submission();
2328
-            if ($form->is_valid()) {
2329
-                $valid_data = $form->valid_data();
2330
-                if (isset($valid_data['default_reg_status'])) {
2331
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2332
-                }
2333
-                if (isset($valid_data['default_max_tickets'])) {
2334
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2335
-                }
2336
-                // update because data was valid!
2337
-                EE_Registry::instance()->CFG->update_espresso_config();
2338
-                EE_Error::overwrite_success();
2339
-                EE_Error::add_success(
2340
-                    __('Default Event Settings were updated', 'event_espresso')
2341
-                );
2342
-            }
2343
-        }
2344
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2345
-    }
2346
-
2347
-
2348
-    /*************        Templates        *************/
2349
-    protected function _template_settings()
2350
-    {
2351
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2352
-        $this->_template_args['preview_img'] = '<img src="'
2353
-                                               . EVENTS_ASSETS_URL
2354
-                                               . '/images/'
2355
-                                               . 'caffeinated_template_features.jpg" alt="'
2356
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2357
-                                               . '" />';
2358
-        $this->_template_args['preview_text'] = '<strong>'
2359
-                                                . esc_html__(
2360
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2361
-                                                    'event_espresso'
2362
-                                                ) . '</strong>';
2363
-        $this->display_admin_caf_preview_page('template_settings_tab');
2364
-    }
2365
-
2366
-
2367
-    /** Event Category Stuff **/
2368
-    /**
2369
-     * set the _category property with the category object for the loaded page.
2370
-     *
2371
-     * @access private
2372
-     * @return void
2373
-     */
2374
-    private function _set_category_object()
2375
-    {
2376
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2377
-            return;
2378
-        } //already have the category object so get out.
2379
-        // set default category object
2380
-        $this->_set_empty_category_object();
2381
-        // only set if we've got an id
2382
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2383
-            return;
2384
-        }
2385
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2386
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2387
-        if (! empty($term)) {
2388
-            $this->_category->category_name = $term->name;
2389
-            $this->_category->category_identifier = $term->slug;
2390
-            $this->_category->category_desc = $term->description;
2391
-            $this->_category->id = $term->term_id;
2392
-            $this->_category->parent = $term->parent;
2393
-        }
2394
-    }
2395
-
2396
-
2397
-    /**
2398
-     * Clears out category properties.
2399
-     */
2400
-    private function _set_empty_category_object()
2401
-    {
2402
-        $this->_category = new stdClass();
2403
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2404
-        $this->_category->id = $this->_category->parent = 0;
2405
-    }
2406
-
2407
-
2408
-    /**
2409
-     * @throws EE_Error
2410
-     */
2411
-    protected function _category_list_table()
2412
-    {
2413
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2414
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2415
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2416
-            'add_category',
2417
-            'add_category',
2418
-            array(),
2419
-            'add-new-h2'
2420
-        );
2421
-        $this->display_admin_list_table_page_with_sidebar();
2422
-    }
2423
-
2424
-
2425
-    /**
2426
-     * Output category details view.
2427
-     */
2428
-    protected function _category_details($view)
2429
-    {
2430
-        // load formatter helper
2431
-        // load field generator helper
2432
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2433
-        $this->_set_add_edit_form_tags($route);
2434
-        $this->_set_category_object();
2435
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2436
-        $delete_action = 'delete_category';
2437
-        // custom redirect
2438
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2439
-            array('action' => 'category_list'),
2440
-            $this->_admin_base_url
2441
-        );
2442
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2443
-        // take care of contents
2444
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2445
-        $this->display_admin_page_with_sidebar();
2446
-    }
2447
-
2448
-
2449
-    /**
2450
-     * Output category details content.
2451
-     */
2452
-    protected function _category_details_content()
2453
-    {
2454
-        $editor_args['category_desc'] = array(
2455
-            'type'          => 'wp_editor',
2456
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2457
-            'class'         => 'my_editor_custom',
2458
-            'wpeditor_args' => array('media_buttons' => false),
2459
-        );
2460
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2461
-        $all_terms = get_terms(
2462
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2463
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2464
-        );
2465
-        // setup category select for term parents.
2466
-        $category_select_values[] = array(
2467
-            'text' => esc_html__('No Parent', 'event_espresso'),
2468
-            'id'   => 0,
2469
-        );
2470
-        foreach ($all_terms as $term) {
2471
-            $category_select_values[] = array(
2472
-                'text' => $term->name,
2473
-                'id'   => $term->term_id,
2474
-            );
2475
-        }
2476
-        $category_select = EEH_Form_Fields::select_input(
2477
-            'category_parent',
2478
-            $category_select_values,
2479
-            $this->_category->parent
2480
-        );
2481
-        $template_args = array(
2482
-            'category'                 => $this->_category,
2483
-            'category_select'          => $category_select,
2484
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2485
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2486
-            'disable'                  => '',
2487
-            'disabled_message'         => false,
2488
-        );
2489
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2490
-        return EEH_Template::display_template($template, $template_args, true);
2491
-    }
2492
-
2493
-
2494
-    /**
2495
-     * Handles deleting categories.
2496
-     */
2497
-    protected function _delete_categories()
2498
-    {
2499
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2500
-            : (array) $this->_req_data['category_id'];
2501
-        foreach ($cat_ids as $cat_id) {
2502
-            $this->_delete_category($cat_id);
2503
-        }
2504
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2505
-        $query_args = array(
2506
-            'action' => 'category_list',
2507
-        );
2508
-        $this->_redirect_after_action(0, '', '', $query_args);
2509
-    }
2510
-
2511
-
2512
-    /**
2513
-     * Handles deleting specific category.
2514
-     *
2515
-     * @param int $cat_id
2516
-     */
2517
-    protected function _delete_category($cat_id)
2518
-    {
2519
-        $cat_id = absint($cat_id);
2520
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2521
-    }
2522
-
2523
-
2524
-    /**
2525
-     * Handles triggering the update or insertion of a new category.
2526
-     *
2527
-     * @param bool $new_category true means we're triggering the insert of a new category.
2528
-     */
2529
-    protected function _insert_or_update_category($new_category)
2530
-    {
2531
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2532
-        $success = 0; // we already have a success message so lets not send another.
2533
-        if ($cat_id) {
2534
-            $query_args = array(
2535
-                'action'     => 'edit_category',
2536
-                'EVT_CAT_ID' => $cat_id,
2537
-            );
2538
-        } else {
2539
-            $query_args = array('action' => 'add_category');
2540
-        }
2541
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2542
-    }
2543
-
2544
-
2545
-    /**
2546
-     * Inserts or updates category
2547
-     *
2548
-     * @param bool $update (true indicates we're updating a category).
2549
-     * @return bool|mixed|string
2550
-     */
2551
-    private function _insert_category($update = false)
2552
-    {
2553
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2554
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2555
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2556
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2557
-        if (empty($category_name)) {
2558
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2559
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2560
-            return false;
2561
-        }
2562
-        $term_args = array(
2563
-            'name'        => $category_name,
2564
-            'description' => $category_desc,
2565
-            'parent'      => $category_parent,
2566
-        );
2567
-        // was the category_identifier input disabled?
2568
-        if (isset($this->_req_data['category_identifier'])) {
2569
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2570
-        }
2571
-        $insert_ids = $update
2572
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2573
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2574
-        if (! is_array($insert_ids)) {
2575
-            $msg = esc_html__(
2576
-                'An error occurred and the category has not been saved to the database.',
2577
-                'event_espresso'
2578
-            );
2579
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2580
-        } else {
2581
-            $cat_id = $insert_ids['term_id'];
2582
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2583
-            EE_Error::add_success($msg);
2584
-        }
2585
-        return $cat_id;
2586
-    }
2587
-
2588
-
2589
-    /**
2590
-     * Gets categories or count of categories matching the arguments in the request.
2591
-     *
2592
-     * @param int  $per_page
2593
-     * @param int  $current_page
2594
-     * @param bool $count
2595
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2596
-     */
2597
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2598
-    {
2599
-        // testing term stuff
2600
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2601
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2602
-        $limit = ($current_page - 1) * $per_page;
2603
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2604
-        if (isset($this->_req_data['s'])) {
2605
-            $sstr = '%' . $this->_req_data['s'] . '%';
2606
-            $where['OR'] = array(
2607
-                'Term.name'   => array('LIKE', $sstr),
2608
-                'description' => array('LIKE', $sstr),
2609
-            );
2610
-        }
2611
-        $query_params = array(
2612
-            $where,
2613
-            'order_by'   => array($orderby => $order),
2614
-            'limit'      => $limit . ',' . $per_page,
2615
-            'force_join' => array('Term'),
2616
-        );
2617
-        $categories = $count
2618
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2619
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2620
-        return $categories;
2621
-    }
2622
-
2623
-    /* end category stuff */
2624
-    /**************/
2625
-
2626
-
2627
-    /**
2628
-     * Callback for the `ee_save_timezone_setting` ajax action.
2629
-     *
2630
-     * @throws EE_Error
2631
-     */
2632
-    public function save_timezonestring_setting()
2633
-    {
2634
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2635
-            ? $this->_req_data['timezone_selected']
2636
-            : '';
2637
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2638
-            EE_Error::add_error(
2639
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2640
-                __FILE__,
2641
-                __FUNCTION__,
2642
-                __LINE__
2643
-            );
2644
-            $this->_template_args['error'] = true;
2645
-            $this->_return_json();
2646
-        }
2647
-
2648
-        update_option('timezone_string', $timezone_string);
2649
-        EE_Error::add_success(
2650
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2651
-        );
2652
-        $this->_template_args['success'] = true;
2653
-        $this->_return_json(true, array('action' => 'create_new'));
2654
-    }
22
+	/**
23
+	 * This will hold the event object for event_details screen.
24
+	 *
25
+	 * @access protected
26
+	 * @var EE_Event $_event
27
+	 */
28
+	protected $_event;
29
+
30
+
31
+	/**
32
+	 * This will hold the category object for category_details screen.
33
+	 *
34
+	 * @var stdClass $_category
35
+	 */
36
+	protected $_category;
37
+
38
+
39
+	/**
40
+	 * This will hold the event model instance
41
+	 *
42
+	 * @var EEM_Event $_event_model
43
+	 */
44
+	protected $_event_model;
45
+
46
+
47
+	/**
48
+	 * @var EE_Event
49
+	 */
50
+	protected $_cpt_model_obj = false;
51
+
52
+
53
+	/**
54
+	 * @var NodeGroupDao
55
+	 */
56
+	protected $model_obj_node_group_persister;
57
+
58
+	/**
59
+	 * Initialize page props for this admin page group.
60
+	 */
61
+	protected function _init_page_props()
62
+	{
63
+		$this->page_slug = EVENTS_PG_SLUG;
64
+		$this->page_label = EVENTS_LABEL;
65
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
66
+		$this->_admin_base_path = EVENTS_ADMIN;
67
+		$this->_cpt_model_names = array(
68
+			'create_new' => 'EEM_Event',
69
+			'edit'       => 'EEM_Event',
70
+		);
71
+		$this->_cpt_edit_routes = array(
72
+			'espresso_events' => 'edit',
73
+		);
74
+		add_action(
75
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
76
+			array($this, 'verify_event_edit'),
77
+			10,
78
+			2
79
+		);
80
+	}
81
+
82
+
83
+	/**
84
+	 * Sets the ajax hooks used for this admin page group.
85
+	 */
86
+	protected function _ajax_hooks()
87
+	{
88
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
89
+	}
90
+
91
+
92
+	/**
93
+	 * Sets the page properties for this admin page group.
94
+	 */
95
+	protected function _define_page_props()
96
+	{
97
+		$this->_admin_page_title = EVENTS_LABEL;
98
+		$this->_labels = array(
99
+			'buttons'      => array(
100
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
101
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
102
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
103
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
104
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
105
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
106
+			),
107
+			'editor_title' => array(
108
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
109
+			),
110
+			'publishbox'   => array(
111
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
112
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
113
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
114
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
115
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
116
+			),
117
+		);
118
+	}
119
+
120
+
121
+	/**
122
+	 * Sets the page routes property for this admin page group.
123
+	 */
124
+	protected function _set_page_routes()
125
+	{
126
+		// load formatter helper
127
+		// load field generator helper
128
+		// is there a evt_id in the request?
129
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
130
+			? $this->_req_data['EVT_ID']
131
+			: 0;
132
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
133
+		$this->_page_routes = array(
134
+			'default'                       => array(
135
+				'func'       => '_events_overview_list_table',
136
+				'capability' => 'ee_read_events',
137
+			),
138
+			'create_new'                    => array(
139
+				'func'       => '_create_new_cpt_item',
140
+				'capability' => 'ee_edit_events',
141
+			),
142
+			'edit'                          => array(
143
+				'func'       => '_edit_cpt_item',
144
+				'capability' => 'ee_edit_event',
145
+				'obj_id'     => $evt_id,
146
+			),
147
+			'copy_event'                    => array(
148
+				'func'       => '_copy_events',
149
+				'capability' => 'ee_edit_event',
150
+				'obj_id'     => $evt_id,
151
+				'noheader'   => true,
152
+			),
153
+			'trash_event'                   => array(
154
+				'func'       => '_trash_or_restore_event',
155
+				'args'       => array('event_status' => 'trash'),
156
+				'capability' => 'ee_delete_event',
157
+				'obj_id'     => $evt_id,
158
+				'noheader'   => true,
159
+			),
160
+			'trash_events'                  => array(
161
+				'func'       => '_trash_or_restore_events',
162
+				'args'       => array('event_status' => 'trash'),
163
+				'capability' => 'ee_delete_events',
164
+				'noheader'   => true,
165
+			),
166
+			'restore_event'                 => array(
167
+				'func'       => '_trash_or_restore_event',
168
+				'args'       => array('event_status' => 'draft'),
169
+				'capability' => 'ee_delete_event',
170
+				'obj_id'     => $evt_id,
171
+				'noheader'   => true,
172
+			),
173
+			'restore_events'                => array(
174
+				'func'       => '_trash_or_restore_events',
175
+				'args'       => array('event_status' => 'draft'),
176
+				'capability' => 'ee_delete_events',
177
+				'noheader'   => true,
178
+			),
179
+			'delete_event'                  => array(
180
+				'func'       => '_delete_event',
181
+				'capability' => 'ee_delete_event',
182
+				'obj_id'     => $evt_id,
183
+				'noheader'   => true,
184
+			),
185
+			'delete_events'                 => array(
186
+				'func'       => '_delete_events',
187
+				'capability' => 'ee_delete_events',
188
+				'noheader'   => true,
189
+			),
190
+			'view_report'                   => array(
191
+				'func'      => '_view_report',
192
+				'capablity' => 'ee_edit_events',
193
+			),
194
+			'default_event_settings'        => array(
195
+				'func'       => '_default_event_settings',
196
+				'capability' => 'manage_options',
197
+			),
198
+			'update_default_event_settings' => array(
199
+				'func'       => '_update_default_event_settings',
200
+				'capability' => 'manage_options',
201
+				'noheader'   => true,
202
+			),
203
+			'template_settings'             => array(
204
+				'func'       => '_template_settings',
205
+				'capability' => 'manage_options',
206
+			),
207
+			// event category tab related
208
+			'add_category'                  => array(
209
+				'func'       => '_category_details',
210
+				'capability' => 'ee_edit_event_category',
211
+				'args'       => array('add'),
212
+			),
213
+			'edit_category'                 => array(
214
+				'func'       => '_category_details',
215
+				'capability' => 'ee_edit_event_category',
216
+				'args'       => array('edit'),
217
+			),
218
+			'delete_categories'             => array(
219
+				'func'       => '_delete_categories',
220
+				'capability' => 'ee_delete_event_category',
221
+				'noheader'   => true,
222
+			),
223
+			'delete_category'               => array(
224
+				'func'       => '_delete_categories',
225
+				'capability' => 'ee_delete_event_category',
226
+				'noheader'   => true,
227
+			),
228
+			'insert_category'               => array(
229
+				'func'       => '_insert_or_update_category',
230
+				'args'       => array('new_category' => true),
231
+				'capability' => 'ee_edit_event_category',
232
+				'noheader'   => true,
233
+			),
234
+			'update_category'               => array(
235
+				'func'       => '_insert_or_update_category',
236
+				'args'       => array('new_category' => false),
237
+				'capability' => 'ee_edit_event_category',
238
+				'noheader'   => true,
239
+			),
240
+			'category_list'                 => array(
241
+				'func'       => '_category_list_table',
242
+				'capability' => 'ee_manage_event_categories',
243
+			),
244
+			'preview_deletion' => [
245
+				'func' => 'previewDeletion',
246
+				'capability' => 'ee_delete_events',
247
+			],
248
+			'confirm_deletion' => [
249
+				'func' => 'confirmDeletion',
250
+				'capability' => 'ee_delete_events',
251
+				'noheader' => true,
252
+			]
253
+		);
254
+	}
255
+
256
+
257
+	/**
258
+	 * Set the _page_config property for this admin page group.
259
+	 */
260
+	protected function _set_page_config()
261
+	{
262
+		$this->_page_config = array(
263
+			'default'                => array(
264
+				'nav'           => array(
265
+					'label' => esc_html__('Overview', 'event_espresso'),
266
+					'order' => 10,
267
+				),
268
+				'list_table'    => 'Events_Admin_List_Table',
269
+				'help_tabs'     => array(
270
+					'events_overview_help_tab'                       => array(
271
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
272
+						'filename' => 'events_overview',
273
+					),
274
+					'events_overview_table_column_headings_help_tab' => array(
275
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
276
+						'filename' => 'events_overview_table_column_headings',
277
+					),
278
+					'events_overview_filters_help_tab'               => array(
279
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
280
+						'filename' => 'events_overview_filters',
281
+					),
282
+					'events_overview_view_help_tab'                  => array(
283
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
284
+						'filename' => 'events_overview_views',
285
+					),
286
+					'events_overview_other_help_tab'                 => array(
287
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
288
+						'filename' => 'events_overview_other',
289
+					),
290
+				),
291
+				'help_tour'     => array(
292
+					'Event_Overview_Help_Tour',
293
+					// 'New_Features_Test_Help_Tour' for testing multiple help tour
294
+				),
295
+				'qtips'         => array(
296
+					'EE_Event_List_Table_Tips',
297
+				),
298
+				'require_nonce' => false,
299
+			),
300
+			'create_new'             => array(
301
+				'nav'           => array(
302
+					'label'      => esc_html__('Add Event', 'event_espresso'),
303
+					'order'      => 5,
304
+					'persistent' => false,
305
+				),
306
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
307
+				'help_tabs'     => array(
308
+					'event_editor_help_tab'                            => array(
309
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
310
+						'filename' => 'event_editor',
311
+					),
312
+					'event_editor_title_richtexteditor_help_tab'       => array(
313
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
+						'filename' => 'event_editor_title_richtexteditor',
315
+					),
316
+					'event_editor_venue_details_help_tab'              => array(
317
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
+						'filename' => 'event_editor_venue_details',
319
+					),
320
+					'event_editor_event_datetimes_help_tab'            => array(
321
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
+						'filename' => 'event_editor_event_datetimes',
323
+					),
324
+					'event_editor_event_tickets_help_tab'              => array(
325
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
+						'filename' => 'event_editor_event_tickets',
327
+					),
328
+					'event_editor_event_registration_options_help_tab' => array(
329
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
+						'filename' => 'event_editor_event_registration_options',
331
+					),
332
+					'event_editor_tags_categories_help_tab'            => array(
333
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
+						'filename' => 'event_editor_tags_categories',
335
+					),
336
+					'event_editor_questions_registrants_help_tab'      => array(
337
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
+						'filename' => 'event_editor_questions_registrants',
339
+					),
340
+					'event_editor_save_new_event_help_tab'             => array(
341
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
342
+						'filename' => 'event_editor_save_new_event',
343
+					),
344
+					'event_editor_other_help_tab'                      => array(
345
+						'title'    => esc_html__('Event Other', 'event_espresso'),
346
+						'filename' => 'event_editor_other',
347
+					),
348
+				),
349
+				'help_tour'     => array(
350
+					'Event_Editor_Help_Tour',
351
+				),
352
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
353
+				'require_nonce' => false,
354
+			),
355
+			'edit'                   => array(
356
+				'nav'           => array(
357
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
358
+					'order'      => 5,
359
+					'persistent' => false,
360
+					'url'        => isset($this->_req_data['post'])
361
+						? EE_Admin_Page::add_query_args_and_nonce(
362
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
363
+							$this->_current_page_view_url
364
+						)
365
+						: $this->_admin_base_url,
366
+				),
367
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
368
+				'help_tabs'     => array(
369
+					'event_editor_help_tab'                            => array(
370
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
371
+						'filename' => 'event_editor',
372
+					),
373
+					'event_editor_title_richtexteditor_help_tab'       => array(
374
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
375
+						'filename' => 'event_editor_title_richtexteditor',
376
+					),
377
+					'event_editor_venue_details_help_tab'              => array(
378
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
379
+						'filename' => 'event_editor_venue_details',
380
+					),
381
+					'event_editor_event_datetimes_help_tab'            => array(
382
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
383
+						'filename' => 'event_editor_event_datetimes',
384
+					),
385
+					'event_editor_event_tickets_help_tab'              => array(
386
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
387
+						'filename' => 'event_editor_event_tickets',
388
+					),
389
+					'event_editor_event_registration_options_help_tab' => array(
390
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
391
+						'filename' => 'event_editor_event_registration_options',
392
+					),
393
+					'event_editor_tags_categories_help_tab'            => array(
394
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
395
+						'filename' => 'event_editor_tags_categories',
396
+					),
397
+					'event_editor_questions_registrants_help_tab'      => array(
398
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
399
+						'filename' => 'event_editor_questions_registrants',
400
+					),
401
+					'event_editor_save_new_event_help_tab'             => array(
402
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
403
+						'filename' => 'event_editor_save_new_event',
404
+					),
405
+					'event_editor_other_help_tab'                      => array(
406
+						'title'    => esc_html__('Event Other', 'event_espresso'),
407
+						'filename' => 'event_editor_other',
408
+					),
409
+				),
410
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
411
+				'require_nonce' => false,
412
+			),
413
+			'default_event_settings' => array(
414
+				'nav'           => array(
415
+					'label' => esc_html__('Default Settings', 'event_espresso'),
416
+					'order' => 40,
417
+				),
418
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
419
+				'labels'        => array(
420
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
421
+				),
422
+				'help_tabs'     => array(
423
+					'default_settings_help_tab'        => array(
424
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
425
+						'filename' => 'events_default_settings',
426
+					),
427
+					'default_settings_status_help_tab' => array(
428
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
429
+						'filename' => 'events_default_settings_status',
430
+					),
431
+					'default_maximum_tickets_help_tab' => array(
432
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
433
+						'filename' => 'events_default_settings_max_tickets',
434
+					),
435
+				),
436
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
437
+				'require_nonce' => false,
438
+			),
439
+			// template settings
440
+			'template_settings'      => array(
441
+				'nav'           => array(
442
+					'label' => esc_html__('Templates', 'event_espresso'),
443
+					'order' => 30,
444
+				),
445
+				'metaboxes'     => $this->_default_espresso_metaboxes,
446
+				'help_tabs'     => array(
447
+					'general_settings_templates_help_tab' => array(
448
+						'title'    => esc_html__('Templates', 'event_espresso'),
449
+						'filename' => 'general_settings_templates',
450
+					),
451
+				),
452
+				'help_tour'     => array('Templates_Help_Tour'),
453
+				'require_nonce' => false,
454
+			),
455
+			// event category stuff
456
+			'add_category'           => array(
457
+				'nav'           => array(
458
+					'label'      => esc_html__('Add Category', 'event_espresso'),
459
+					'order'      => 15,
460
+					'persistent' => false,
461
+				),
462
+				'help_tabs'     => array(
463
+					'add_category_help_tab' => array(
464
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
465
+						'filename' => 'events_add_category',
466
+					),
467
+				),
468
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
469
+				'metaboxes'     => array('_publish_post_box'),
470
+				'require_nonce' => false,
471
+			),
472
+			'edit_category'          => array(
473
+				'nav'           => array(
474
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
475
+					'order'      => 15,
476
+					'persistent' => false,
477
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
478
+						? add_query_arg(
479
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
480
+							$this->_current_page_view_url
481
+						)
482
+						: $this->_admin_base_url,
483
+				),
484
+				'help_tabs'     => array(
485
+					'edit_category_help_tab' => array(
486
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
487
+						'filename' => 'events_edit_category',
488
+					),
489
+				),
490
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
491
+				'metaboxes'     => array('_publish_post_box'),
492
+				'require_nonce' => false,
493
+			),
494
+			'category_list'          => array(
495
+				'nav'           => array(
496
+					'label' => esc_html__('Categories', 'event_espresso'),
497
+					'order' => 20,
498
+				),
499
+				'list_table'    => 'Event_Categories_Admin_List_Table',
500
+				'help_tabs'     => array(
501
+					'events_categories_help_tab'                       => array(
502
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
503
+						'filename' => 'events_categories',
504
+					),
505
+					'events_categories_table_column_headings_help_tab' => array(
506
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
507
+						'filename' => 'events_categories_table_column_headings',
508
+					),
509
+					'events_categories_view_help_tab'                  => array(
510
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
511
+						'filename' => 'events_categories_views',
512
+					),
513
+					'events_categories_other_help_tab'                 => array(
514
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
515
+						'filename' => 'events_categories_other',
516
+					),
517
+				),
518
+				'help_tour'     => array(
519
+					'Event_Categories_Help_Tour',
520
+				),
521
+				'metaboxes'     => $this->_default_espresso_metaboxes,
522
+				'require_nonce' => false,
523
+			),
524
+			'preview_deletion'           => array(
525
+				'nav'           => array(
526
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
527
+					'order'      => 15,
528
+					'persistent' => false,
529
+				),
530
+				'require_nonce' => false
531
+			)
532
+		);
533
+	}
534
+
535
+
536
+	/**
537
+	 * Used to register any global screen options if necessary for every route in this admin page group.
538
+	 */
539
+	protected function _add_screen_options()
540
+	{
541
+	}
542
+
543
+
544
+	/**
545
+	 * Implementing the screen options for the 'default' route.
546
+	 */
547
+	protected function _add_screen_options_default()
548
+	{
549
+		$this->_per_page_screen_option();
550
+	}
551
+
552
+
553
+	/**
554
+	 * Implementing screen options for the category list route.
555
+	 */
556
+	protected function _add_screen_options_category_list()
557
+	{
558
+		$page_title = $this->_admin_page_title;
559
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
560
+		$this->_per_page_screen_option();
561
+		$this->_admin_page_title = $page_title;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Used to register any global feature pointers for the admin page group.
567
+	 */
568
+	protected function _add_feature_pointers()
569
+	{
570
+	}
571
+
572
+
573
+	/**
574
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
575
+	 */
576
+	public function load_scripts_styles()
577
+	{
578
+		wp_register_style(
579
+			'events-admin-css',
580
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
581
+			array(),
582
+			EVENT_ESPRESSO_VERSION
583
+		);
584
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
585
+		wp_enqueue_style('events-admin-css');
586
+		wp_enqueue_style('ee-cat-admin');
587
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
588
+		// registers for all views
589
+		// scripts
590
+		wp_register_script(
591
+			'event_editor_js',
592
+			EVENTS_ASSETS_URL . 'event_editor.js',
593
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
594
+			EVENT_ESPRESSO_VERSION,
595
+			true
596
+		);
597
+	}
598
+
599
+
600
+	/**
601
+	 * Enqueuing scripts and styles specific to this view
602
+	 */
603
+	public function load_scripts_styles_create_new()
604
+	{
605
+		$this->load_scripts_styles_edit();
606
+	}
607
+
608
+
609
+	/**
610
+	 * Enqueuing scripts and styles specific to this view
611
+	 */
612
+	public function load_scripts_styles_edit()
613
+	{
614
+		// styles
615
+		wp_enqueue_style('espresso-ui-theme');
616
+		wp_register_style(
617
+			'event-editor-css',
618
+			EVENTS_ASSETS_URL . 'event-editor.css',
619
+			array('ee-admin-css'),
620
+			EVENT_ESPRESSO_VERSION
621
+		);
622
+		wp_enqueue_style('event-editor-css');
623
+		// scripts
624
+		wp_register_script(
625
+			'event-datetime-metabox',
626
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
+			array('event_editor_js', 'ee-datepicker'),
628
+			EVENT_ESPRESSO_VERSION
629
+		);
630
+		wp_enqueue_script('event-datetime-metabox');
631
+	}
632
+
633
+
634
+	/**
635
+	 * Populating the _views property for the category list table view.
636
+	 */
637
+	protected function _set_list_table_views_category_list()
638
+	{
639
+		$this->_views = array(
640
+			'all' => array(
641
+				'slug'        => 'all',
642
+				'label'       => esc_html__('All', 'event_espresso'),
643
+				'count'       => 0,
644
+				'bulk_action' => array(
645
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
+				),
647
+			),
648
+		);
649
+	}
650
+
651
+
652
+	/**
653
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
+	 */
655
+	public function admin_init()
656
+	{
657
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
658
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
659
+			'event_espresso'
660
+		);
661
+	}
662
+
663
+
664
+	/**
665
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
666
+	 * group.
667
+	 */
668
+	public function admin_notices()
669
+	{
670
+	}
671
+
672
+
673
+	/**
674
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
675
+	 * this admin page group.
676
+	 */
677
+	public function admin_footer_scripts()
678
+	{
679
+	}
680
+
681
+
682
+	/**
683
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
684
+	 * warning (via EE_Error::add_error());
685
+	 *
686
+	 * @param  EE_Event $event Event object
687
+	 * @param string    $req_type
688
+	 * @return void
689
+	 * @throws EE_Error
690
+	 * @access public
691
+	 */
692
+	public function verify_event_edit($event = null, $req_type = '')
693
+	{
694
+		// don't need to do this when processing
695
+		if (! empty($req_type)) {
696
+			return;
697
+		}
698
+		// no event?
699
+		if (empty($event)) {
700
+			// set event
701
+			$event = $this->_cpt_model_obj;
702
+		}
703
+		// STILL no event?
704
+		if (! $event instanceof EE_Event) {
705
+			return;
706
+		}
707
+		$orig_status = $event->status();
708
+		// first check if event is active.
709
+		if ($orig_status === EEM_Event::cancelled
710
+			|| $orig_status === EEM_Event::postponed
711
+			|| $event->is_expired()
712
+			|| $event->is_inactive()
713
+		) {
714
+			return;
715
+		}
716
+		// made it here so it IS active... next check that any of the tickets are sold.
717
+		if ($event->is_sold_out(true)) {
718
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
719
+				EE_Error::add_attention(
720
+					sprintf(
721
+						esc_html__(
722
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
723
+							'event_espresso'
724
+						),
725
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
726
+					)
727
+				);
728
+			}
729
+			return;
730
+		} elseif ($orig_status === EEM_Event::sold_out) {
731
+			EE_Error::add_attention(
732
+				sprintf(
733
+					esc_html__(
734
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
735
+						'event_espresso'
736
+					),
737
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
738
+				)
739
+			);
740
+		}
741
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
742
+		if (! $event->tickets_on_sale()) {
743
+			return;
744
+		}
745
+		// made it here so show warning
746
+		$this->_edit_event_warning();
747
+	}
748
+
749
+
750
+	/**
751
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
752
+	 * When needed, hook this into a EE_Error::add_error() notice.
753
+	 *
754
+	 * @access protected
755
+	 * @return void
756
+	 */
757
+	protected function _edit_event_warning()
758
+	{
759
+		// we don't want to add warnings during these requests
760
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
761
+			return;
762
+		}
763
+		EE_Error::add_attention(
764
+			sprintf(
765
+				esc_html__(
766
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
767
+					'event_espresso'
768
+				),
769
+				'<a class="espresso-help-tab-lnk">',
770
+				'</a>'
771
+			)
772
+		);
773
+	}
774
+
775
+
776
+	/**
777
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
778
+	 * Otherwise, do the normal logic
779
+	 *
780
+	 * @return string
781
+	 * @throws \EE_Error
782
+	 */
783
+	protected function _create_new_cpt_item()
784
+	{
785
+		$has_timezone_string = get_option('timezone_string');
786
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
787
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
788
+			EE_Error::add_attention(
789
+				sprintf(
790
+					__(
791
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
792
+						'event_espresso'
793
+					),
794
+					'<br>',
795
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
796
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
797
+					. '</select>',
798
+					'<button class="button button-secondary timezone-submit">',
799
+					'</button><span class="spinner"></span>'
800
+				),
801
+				__FILE__,
802
+				__FUNCTION__,
803
+				__LINE__
804
+			);
805
+		}
806
+		return parent::_create_new_cpt_item();
807
+	}
808
+
809
+
810
+	/**
811
+	 * Sets the _views property for the default route in this admin page group.
812
+	 */
813
+	protected function _set_list_table_views_default()
814
+	{
815
+		$this->_views = array(
816
+			'all'   => array(
817
+				'slug'        => 'all',
818
+				'label'       => esc_html__('View All Events', 'event_espresso'),
819
+				'count'       => 0,
820
+				'bulk_action' => array(
821
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
822
+				),
823
+			),
824
+			'draft' => array(
825
+				'slug'        => 'draft',
826
+				'label'       => esc_html__('Draft', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array(
829
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
830
+				),
831
+			),
832
+		);
833
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
834
+			$this->_views['trash'] = array(
835
+				'slug'        => 'trash',
836
+				'label'       => esc_html__('Trash', 'event_espresso'),
837
+				'count'       => 0,
838
+				'bulk_action' => array(
839
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
840
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
841
+				),
842
+			);
843
+		}
844
+	}
845
+
846
+
847
+	/**
848
+	 * Provides the legend item array for the default list table view.
849
+	 *
850
+	 * @return array
851
+	 */
852
+	protected function _event_legend_items()
853
+	{
854
+		$items = array(
855
+			'view_details'   => array(
856
+				'class' => 'dashicons dashicons-search',
857
+				'desc'  => esc_html__('View Event', 'event_espresso'),
858
+			),
859
+			'edit_event'     => array(
860
+				'class' => 'ee-icon ee-icon-calendar-edit',
861
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
862
+			),
863
+			'view_attendees' => array(
864
+				'class' => 'dashicons dashicons-groups',
865
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
866
+			),
867
+		);
868
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
869
+		$statuses = array(
870
+			'sold_out_status'  => array(
871
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
872
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
873
+			),
874
+			'active_status'    => array(
875
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
876
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
877
+			),
878
+			'upcoming_status'  => array(
879
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
880
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
881
+			),
882
+			'postponed_status' => array(
883
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
884
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
885
+			),
886
+			'cancelled_status' => array(
887
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
888
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
889
+			),
890
+			'expired_status'   => array(
891
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
892
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
893
+			),
894
+			'inactive_status'  => array(
895
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
896
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
897
+			),
898
+		);
899
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
900
+		return array_merge($items, $statuses);
901
+	}
902
+
903
+
904
+	/**
905
+	 * @return EEM_Event
906
+	 */
907
+	private function _event_model()
908
+	{
909
+		if (! $this->_event_model instanceof EEM_Event) {
910
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
911
+		}
912
+		return $this->_event_model;
913
+	}
914
+
915
+
916
+	/**
917
+	 * Adds extra buttons to the WP CPT permalink field row.
918
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
919
+	 *
920
+	 * @param  string $return    the current html
921
+	 * @param  int    $id        the post id for the page
922
+	 * @param  string $new_title What the title is
923
+	 * @param  string $new_slug  what the slug is
924
+	 * @return string            The new html string for the permalink area
925
+	 */
926
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
927
+	{
928
+		// make sure this is only when editing
929
+		if (! empty($id)) {
930
+			$post = get_post($id);
931
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
932
+					   . esc_html__('Shortcode', 'event_espresso')
933
+					   . '</a> ';
934
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
935
+					   . $post->ID
936
+					   . ']">';
937
+		}
938
+		return $return;
939
+	}
940
+
941
+
942
+	/**
943
+	 * _events_overview_list_table
944
+	 * This contains the logic for showing the events_overview list
945
+	 *
946
+	 * @access protected
947
+	 * @return void
948
+	 * @throws \EE_Error
949
+	 */
950
+	protected function _events_overview_list_table()
951
+	{
952
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
953
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
954
+			? (array) $this->_template_args['after_list_table']
955
+			: array();
956
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
957
+				. EEH_Template::get_button_or_link(
958
+					get_post_type_archive_link('espresso_events'),
959
+					esc_html__("View Event Archive Page", "event_espresso"),
960
+					'button'
961
+				);
962
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
963
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
964
+			'create_new',
965
+			'add',
966
+			array(),
967
+			'add-new-h2'
968
+		);
969
+		$this->display_admin_list_table_page_with_no_sidebar();
970
+	}
971
+
972
+
973
+	/**
974
+	 * this allows for extra misc actions in the default WP publish box
975
+	 *
976
+	 * @return void
977
+	 */
978
+	public function extra_misc_actions_publish_box()
979
+	{
980
+		$this->_generate_publish_box_extra_content();
981
+	}
982
+
983
+
984
+	/**
985
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
986
+	 * saved.
987
+	 * Typically you would use this to save any additional data.
988
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
989
+	 * ALSO very important.  When a post transitions from scheduled to published,
990
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
991
+	 * other meta saves. So MAKE sure that you handle this accordingly.
992
+	 *
993
+	 * @access protected
994
+	 * @abstract
995
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
996
+	 * @param  object $post    The post object of the cpt that was saved.
997
+	 * @return void
998
+	 * @throws \EE_Error
999
+	 */
1000
+	protected function _insert_update_cpt_item($post_id, $post)
1001
+	{
1002
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1003
+			// get out we're not processing an event save.
1004
+			return;
1005
+		}
1006
+		$event_values = array(
1007
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1008
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1009
+			'EVT_additional_limit'            => min(
1010
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1011
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1012
+			),
1013
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1014
+				? $this->_req_data['EVT_default_registration_status']
1015
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
1016
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1017
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1018
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1019
+				? $this->_req_data['timezone_string'] : null,
1020
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1021
+				? $this->_req_data['externalURL'] : null,
1022
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1023
+				? $this->_req_data['event_phone'] : null,
1024
+		);
1025
+		// update event
1026
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1027
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1028
+		$get_one_where = array(
1029
+			$this->_event_model()->primary_key_name() => $post_id,
1030
+			'OR'                                      => array(
1031
+				'status'   => $post->post_status,
1032
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1033
+				// but the returned object here has a status of "publish", so use the original post status as well
1034
+				'status*1' => $this->_req_data['original_post_status'],
1035
+			),
1036
+		);
1037
+		$event = $this->_event_model()->get_one(array($get_one_where));
1038
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1039
+		$event_update_callbacks = apply_filters(
1040
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1041
+			array(
1042
+				array($this, '_default_venue_update'),
1043
+				array($this, '_default_tickets_update'),
1044
+			)
1045
+		);
1046
+		$att_success = true;
1047
+		foreach ($event_update_callbacks as $e_callback) {
1048
+			$_success = is_callable($e_callback)
1049
+				? call_user_func($e_callback, $event, $this->_req_data)
1050
+				: false;
1051
+			// if ANY of these updates fail then we want the appropriate global error message
1052
+			$att_success = ! $att_success ? $att_success : $_success;
1053
+		}
1054
+		// any errors?
1055
+		if ($success && false === $att_success) {
1056
+			EE_Error::add_error(
1057
+				esc_html__(
1058
+					'Event Details saved successfully but something went wrong with saving attachments.',
1059
+					'event_espresso'
1060
+				),
1061
+				__FILE__,
1062
+				__FUNCTION__,
1063
+				__LINE__
1064
+			);
1065
+		} elseif ($success === false) {
1066
+			EE_Error::add_error(
1067
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1068
+				__FILE__,
1069
+				__FUNCTION__,
1070
+				__LINE__
1071
+			);
1072
+		}
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * @see parent::restore_item()
1078
+	 * @param int $post_id
1079
+	 * @param int $revision_id
1080
+	 */
1081
+	protected function _restore_cpt_item($post_id, $revision_id)
1082
+	{
1083
+		// copy existing event meta to new post
1084
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1085
+		if ($post_evt instanceof EE_Event) {
1086
+			// meta revision restore
1087
+			$post_evt->restore_revision($revision_id);
1088
+			// related objs restore
1089
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1090
+		}
1091
+	}
1092
+
1093
+
1094
+	/**
1095
+	 * Attach the venue to the Event
1096
+	 *
1097
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1098
+	 * @param  array     $data   The request data from the form
1099
+	 * @return bool           Success or fail.
1100
+	 */
1101
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1102
+	{
1103
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1104
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1105
+		$rows_affected = null;
1106
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1107
+		// very important.  If we don't have a venue name...
1108
+		// then we'll get out because not necessary to create empty venue
1109
+		if (empty($data['venue_title'])) {
1110
+			return false;
1111
+		}
1112
+		$venue_array = array(
1113
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1114
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1115
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1116
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1117
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1118
+				: null,
1119
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1120
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1121
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1122
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1123
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1124
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1125
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1126
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1127
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1128
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1129
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1130
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1131
+			'status'              => 'publish',
1132
+		);
1133
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1134
+		if (! empty($venue_id)) {
1135
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1136
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1137
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1138
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1139
+			return $rows_affected > 0 ? true : false;
1140
+		} else {
1141
+			// we insert the venue
1142
+			$venue_id = $venue_model->insert($venue_array);
1143
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1144
+			return ! empty($venue_id) ? true : false;
1145
+		}
1146
+		// when we have the ancestor come in it's already been handled by the revision save.
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1152
+	 *
1153
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1154
+	 * @param  array    $data   The request data from the form
1155
+	 * @return array
1156
+	 */
1157
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1158
+	{
1159
+		$success = true;
1160
+		$saved_dtt = null;
1161
+		$saved_tickets = array();
1162
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1163
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1164
+			// trim all values to ensure any excess whitespace is removed.
1165
+			$dtt = array_map('trim', $dtt);
1166
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1167
+				: $dtt['DTT_EVT_start'];
1168
+			$datetime_values = array(
1169
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1170
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1171
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1172
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1173
+				'DTT_order'     => $row,
1174
+			);
1175
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1176
+			if (! empty($dtt['DTT_ID'])) {
1177
+				$DTM = EE_Registry::instance()
1178
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1179
+								  ->get_one_by_ID($dtt['DTT_ID']);
1180
+				$DTM->set_date_format($incoming_date_formats[0]);
1181
+				$DTM->set_time_format($incoming_date_formats[1]);
1182
+				foreach ($datetime_values as $field => $value) {
1183
+					$DTM->set($field, $value);
1184
+				}
1185
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1186
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1187
+			} else {
1188
+				$DTM = EE_Registry::instance()->load_class(
1189
+					'Datetime',
1190
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1191
+					false,
1192
+					false
1193
+				);
1194
+				foreach ($datetime_values as $field => $value) {
1195
+					$DTM->set($field, $value);
1196
+				}
1197
+			}
1198
+			$DTM->save();
1199
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1200
+			// load DTT helper
1201
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1202
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1203
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1204
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1205
+				$DTT->save();
1206
+			}
1207
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1208
+			$saved_dtt = $DTT;
1209
+			$success = ! $success ? $success : $DTT;
1210
+			// if ANY of these updates fail then we want the appropriate global error message.
1211
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1212
+		}
1213
+		// no dtts get deleted so we don't do any of that logic here.
1214
+		// update tickets next
1215
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1216
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1217
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1218
+			$update_prices = false;
1219
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1220
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1221
+			// trim inputs to ensure any excess whitespace is removed.
1222
+			$tkt = array_map('trim', $tkt);
1223
+			if (empty($tkt['TKT_start_date'])) {
1224
+				// let's use now in the set timezone.
1225
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1226
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1227
+			}
1228
+			if (empty($tkt['TKT_end_date'])) {
1229
+				// use the start date of the first datetime
1230
+				$dtt = $evtobj->first_datetime();
1231
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1232
+					$incoming_date_formats[0],
1233
+					$incoming_date_formats[1]
1234
+				);
1235
+			}
1236
+			$TKT_values = array(
1237
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1238
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1239
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1240
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1241
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1242
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1243
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1244
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1245
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1246
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1247
+				'TKT_row'         => $row,
1248
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1249
+				'TKT_price'       => $ticket_price,
1250
+			);
1251
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1252
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1253
+				$TKT_values['TKT_ID'] = 0;
1254
+				$TKT_values['TKT_is_default'] = 0;
1255
+				$TKT_values['TKT_price'] = $ticket_price;
1256
+				$update_prices = true;
1257
+			}
1258
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1259
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1260
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1261
+			if (! empty($tkt['TKT_ID'])) {
1262
+				$TKT = EE_Registry::instance()
1263
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1264
+								  ->get_one_by_ID($tkt['TKT_ID']);
1265
+				if ($TKT instanceof EE_Ticket) {
1266
+					$ticket_sold = $TKT->count_related(
1267
+						'Registration',
1268
+						array(
1269
+							array(
1270
+								'STS_ID' => array(
1271
+									'NOT IN',
1272
+									array(EEM_Registration::status_id_incomplete),
1273
+								),
1274
+							),
1275
+						)
1276
+					) > 0 ? true : false;
1277
+					// let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1278
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1279
+									  && ! $TKT->get('TKT_deleted');
1280
+					$TKT->set_date_format($incoming_date_formats[0]);
1281
+					$TKT->set_time_format($incoming_date_formats[1]);
1282
+					// set new values
1283
+					foreach ($TKT_values as $field => $value) {
1284
+						if ($field == 'TKT_qty') {
1285
+							$TKT->set_qty($value);
1286
+						} else {
1287
+							$TKT->set($field, $value);
1288
+						}
1289
+					}
1290
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1291
+					if ($create_new_TKT) {
1292
+						// archive the old ticket first
1293
+						$TKT->set('TKT_deleted', 1);
1294
+						$TKT->save();
1295
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1296
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1297
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1298
+						$TKT = clone $TKT;
1299
+						$TKT->set('TKT_ID', 0);
1300
+						$TKT->set('TKT_deleted', 0);
1301
+						$TKT->set('TKT_price', $ticket_price);
1302
+						$TKT->set('TKT_sold', 0);
1303
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1304
+						$update_prices = true;
1305
+					}
1306
+					// make sure price is set if it hasn't been already
1307
+					$TKT->set('TKT_price', $ticket_price);
1308
+				}
1309
+			} else {
1310
+				// no TKT_id so a new TKT
1311
+				$TKT_values['TKT_price'] = $ticket_price;
1312
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1313
+				if ($TKT instanceof EE_Ticket) {
1314
+					// need to reset values to properly account for the date formats
1315
+					$TKT->set_date_format($incoming_date_formats[0]);
1316
+					$TKT->set_time_format($incoming_date_formats[1]);
1317
+					$TKT->set_timezone($evtobj->get_timezone());
1318
+					// set new values
1319
+					foreach ($TKT_values as $field => $value) {
1320
+						if ($field == 'TKT_qty') {
1321
+							$TKT->set_qty($value);
1322
+						} else {
1323
+							$TKT->set($field, $value);
1324
+						}
1325
+					}
1326
+					$update_prices = true;
1327
+				}
1328
+			}
1329
+			// cap ticket qty by datetime reg limits
1330
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1331
+			// update ticket.
1332
+			$TKT->save();
1333
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1334
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1335
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1336
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1337
+				$TKT->save();
1338
+			}
1339
+			// initially let's add the ticket to the dtt
1340
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1341
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1342
+			// add prices to ticket
1343
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1344
+		}
1345
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1346
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1347
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1348
+		foreach ($tickets_removed as $id) {
1349
+			$id = absint($id);
1350
+			// get the ticket for this id
1351
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1352
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1353
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1354
+			foreach ($dtts as $dtt) {
1355
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1356
+			}
1357
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1358
+			$tkt_to_remove->delete_related_permanently('Price');
1359
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1360
+			$tkt_to_remove->delete_permanently();
1361
+		}
1362
+		return array($saved_dtt, $saved_tickets);
1363
+	}
1364
+
1365
+
1366
+	/**
1367
+	 * This attaches a list of given prices to a ticket.
1368
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1369
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1370
+	 * price info and prices are automatically "archived" via the ticket.
1371
+	 *
1372
+	 * @access  private
1373
+	 * @param array     $prices     Array of prices from the form.
1374
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1375
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1376
+	 * @return  void
1377
+	 */
1378
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1379
+	{
1380
+		foreach ($prices as $row => $prc) {
1381
+			$PRC_values = array(
1382
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1383
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1384
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1385
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1386
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1387
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1388
+				'PRC_order'      => $row,
1389
+			);
1390
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1391
+				$PRC_values['PRC_ID'] = 0;
1392
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1393
+			} else {
1394
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1395
+				// update this price with new values
1396
+				foreach ($PRC_values as $field => $newprc) {
1397
+					$PRC->set($field, $newprc);
1398
+				}
1399
+				$PRC->save();
1400
+			}
1401
+			$ticket->_add_relation_to($PRC, 'Price');
1402
+		}
1403
+	}
1404
+
1405
+
1406
+	/**
1407
+	 * Add in our autosave ajax handlers
1408
+	 *
1409
+	 */
1410
+	protected function _ee_autosave_create_new()
1411
+	{
1412
+	}
1413
+
1414
+
1415
+	/**
1416
+	 * More autosave handlers.
1417
+	 */
1418
+	protected function _ee_autosave_edit()
1419
+	{
1420
+		return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 *    _generate_publish_box_extra_content
1426
+	 */
1427
+	private function _generate_publish_box_extra_content()
1428
+	{
1429
+		// load formatter helper
1430
+		// args for getting related registrations
1431
+		$approved_query_args = array(
1432
+			array(
1433
+				'REG_deleted' => 0,
1434
+				'STS_ID'      => EEM_Registration::status_id_approved,
1435
+			),
1436
+		);
1437
+		$not_approved_query_args = array(
1438
+			array(
1439
+				'REG_deleted' => 0,
1440
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1441
+			),
1442
+		);
1443
+		$pending_payment_query_args = array(
1444
+			array(
1445
+				'REG_deleted' => 0,
1446
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1447
+			),
1448
+		);
1449
+		// publish box
1450
+		$publish_box_extra_args = array(
1451
+			'view_approved_reg_url'        => add_query_arg(
1452
+				array(
1453
+					'action'      => 'default',
1454
+					'event_id'    => $this->_cpt_model_obj->ID(),
1455
+					'_reg_status' => EEM_Registration::status_id_approved,
1456
+				),
1457
+				REG_ADMIN_URL
1458
+			),
1459
+			'view_not_approved_reg_url'    => add_query_arg(
1460
+				array(
1461
+					'action'      => 'default',
1462
+					'event_id'    => $this->_cpt_model_obj->ID(),
1463
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1464
+				),
1465
+				REG_ADMIN_URL
1466
+			),
1467
+			'view_pending_payment_reg_url' => add_query_arg(
1468
+				array(
1469
+					'action'      => 'default',
1470
+					'event_id'    => $this->_cpt_model_obj->ID(),
1471
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1472
+				),
1473
+				REG_ADMIN_URL
1474
+			),
1475
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1476
+				'Registration',
1477
+				$approved_query_args
1478
+			),
1479
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1480
+				'Registration',
1481
+				$not_approved_query_args
1482
+			),
1483
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1484
+				'Registration',
1485
+				$pending_payment_query_args
1486
+			),
1487
+			'misc_pub_section_class'       => apply_filters(
1488
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1489
+				'misc-pub-section'
1490
+			),
1491
+		);
1492
+		ob_start();
1493
+		do_action(
1494
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1495
+			$this->_cpt_model_obj
1496
+		);
1497
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1498
+		// load template
1499
+		EEH_Template::display_template(
1500
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1501
+			$publish_box_extra_args
1502
+		);
1503
+	}
1504
+
1505
+
1506
+	/**
1507
+	 * @return EE_Event
1508
+	 */
1509
+	public function get_event_object()
1510
+	{
1511
+		return $this->_cpt_model_obj;
1512
+	}
1513
+
1514
+
1515
+
1516
+
1517
+	/** METABOXES * */
1518
+	/**
1519
+	 * _register_event_editor_meta_boxes
1520
+	 * add all metaboxes related to the event_editor
1521
+	 *
1522
+	 * @return void
1523
+	 */
1524
+	protected function _register_event_editor_meta_boxes()
1525
+	{
1526
+		$this->verify_cpt_object();
1527
+		add_meta_box(
1528
+			'espresso_event_editor_tickets',
1529
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1530
+			array($this, 'ticket_metabox'),
1531
+			$this->page_slug,
1532
+			'normal',
1533
+			'high'
1534
+		);
1535
+		add_meta_box(
1536
+			'espresso_event_editor_event_options',
1537
+			esc_html__('Event Registration Options', 'event_espresso'),
1538
+			array($this, 'registration_options_meta_box'),
1539
+			$this->page_slug,
1540
+			'side',
1541
+			'default'
1542
+		);
1543
+		// NOTE: if you're looking for other metaboxes in here,
1544
+		// where a metabox has a related management page in the admin
1545
+		// you will find it setup in the related management page's "_Hooks" file.
1546
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1547
+	}
1548
+
1549
+
1550
+	/**
1551
+	 * @throws DomainException
1552
+	 * @throws EE_Error
1553
+	 */
1554
+	public function ticket_metabox()
1555
+	{
1556
+		$existing_datetime_ids = $existing_ticket_ids = array();
1557
+		// defaults for template args
1558
+		$template_args = array(
1559
+			'existing_datetime_ids'    => '',
1560
+			'event_datetime_help_link' => '',
1561
+			'ticket_options_help_link' => '',
1562
+			'time'                     => null,
1563
+			'ticket_rows'              => '',
1564
+			'existing_ticket_ids'      => '',
1565
+			'total_ticket_rows'        => 1,
1566
+			'ticket_js_structure'      => '',
1567
+			'trash_icon'               => 'ee-lock-icon',
1568
+			'disabled'                 => '',
1569
+		);
1570
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1571
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1572
+		/**
1573
+		 * 1. Start with retrieving Datetimes
1574
+		 * 2. Fore each datetime get related tickets
1575
+		 * 3. For each ticket get related prices
1576
+		 */
1577
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1578
+		/** @type EE_Datetime $first_datetime */
1579
+		$first_datetime = reset($times);
1580
+		// do we get related tickets?
1581
+		if ($first_datetime instanceof EE_Datetime
1582
+			&& $first_datetime->ID() !== 0
1583
+		) {
1584
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1585
+			$template_args['time'] = $first_datetime;
1586
+			$related_tickets = $first_datetime->tickets(
1587
+				array(
1588
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1589
+					'default_where_conditions' => 'none',
1590
+				)
1591
+			);
1592
+			if (! empty($related_tickets)) {
1593
+				$template_args['total_ticket_rows'] = count($related_tickets);
1594
+				$row = 0;
1595
+				foreach ($related_tickets as $ticket) {
1596
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1597
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1598
+					$row++;
1599
+				}
1600
+			} else {
1601
+				$template_args['total_ticket_rows'] = 1;
1602
+				/** @type EE_Ticket $ticket */
1603
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1604
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1605
+			}
1606
+		} else {
1607
+			$template_args['time'] = $times[0];
1608
+			/** @type EE_Ticket $ticket */
1609
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1610
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1611
+			// NOTE: we're just sending the first default row
1612
+			// (decaf can't manage default tickets so this should be sufficient);
1613
+		}
1614
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1615
+			'event_editor_event_datetimes_help_tab'
1616
+		);
1617
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1618
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1619
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1620
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1621
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1622
+			true
1623
+		);
1624
+		$template = apply_filters(
1625
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1626
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1627
+		);
1628
+		EEH_Template::display_template($template, $template_args);
1629
+	}
1630
+
1631
+
1632
+	/**
1633
+	 * Setup an individual ticket form for the decaf event editor page
1634
+	 *
1635
+	 * @access private
1636
+	 * @param  EE_Ticket $ticket   the ticket object
1637
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1638
+	 * @param int        $row
1639
+	 * @return string generated html for the ticket row.
1640
+	 */
1641
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1642
+	{
1643
+		$template_args = array(
1644
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1645
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1646
+				: '',
1647
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1648
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1649
+			'TKT_name'            => $ticket->get('TKT_name'),
1650
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1651
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1652
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1653
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1654
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1655
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1656
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1657
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1658
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1659
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1660
+				: ' disabled=disabled',
1661
+		);
1662
+		$price = $ticket->ID() !== 0
1663
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1664
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1665
+		$price_args = array(
1666
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1667
+			'PRC_amount'            => $price->get('PRC_amount'),
1668
+			'PRT_ID'                => $price->get('PRT_ID'),
1669
+			'PRC_ID'                => $price->get('PRC_ID'),
1670
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1671
+		);
1672
+		// make sure we have default start and end dates if skeleton
1673
+		// handle rows that should NOT be empty
1674
+		if (empty($template_args['TKT_start_date'])) {
1675
+			// if empty then the start date will be now.
1676
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1677
+		}
1678
+		if (empty($template_args['TKT_end_date'])) {
1679
+			// get the earliest datetime (if present);
1680
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1681
+				? $this->_cpt_model_obj->get_first_related(
1682
+					'Datetime',
1683
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1684
+				)
1685
+				: null;
1686
+			if (! empty($earliest_dtt)) {
1687
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1688
+			} else {
1689
+				$template_args['TKT_end_date'] = date(
1690
+					'Y-m-d h:i a',
1691
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1692
+				);
1693
+			}
1694
+		}
1695
+		$template_args = array_merge($template_args, $price_args);
1696
+		$template = apply_filters(
1697
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1698
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1699
+			$ticket
1700
+		);
1701
+		return EEH_Template::display_template($template, $template_args, true);
1702
+	}
1703
+
1704
+
1705
+	/**
1706
+	 * @throws DomainException
1707
+	 */
1708
+	public function registration_options_meta_box()
1709
+	{
1710
+		$yes_no_values = array(
1711
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1712
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1713
+		);
1714
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1715
+			array(
1716
+				EEM_Registration::status_id_cancelled,
1717
+				EEM_Registration::status_id_declined,
1718
+				EEM_Registration::status_id_incomplete,
1719
+			),
1720
+			true
1721
+		);
1722
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1723
+		$template_args['_event'] = $this->_cpt_model_obj;
1724
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1725
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1726
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1727
+			'default_reg_status',
1728
+			$default_reg_status_values,
1729
+			$this->_cpt_model_obj->default_registration_status()
1730
+		);
1731
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1732
+			'display_desc',
1733
+			$yes_no_values,
1734
+			$this->_cpt_model_obj->display_description()
1735
+		);
1736
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1737
+			'display_ticket_selector',
1738
+			$yes_no_values,
1739
+			$this->_cpt_model_obj->display_ticket_selector(),
1740
+			'',
1741
+			'',
1742
+			false
1743
+		);
1744
+		$template_args['additional_registration_options'] = apply_filters(
1745
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1746
+			'',
1747
+			$template_args,
1748
+			$yes_no_values,
1749
+			$default_reg_status_values
1750
+		);
1751
+		EEH_Template::display_template(
1752
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1753
+			$template_args
1754
+		);
1755
+	}
1756
+
1757
+
1758
+	/**
1759
+	 * _get_events()
1760
+	 * This method simply returns all the events (for the given _view and paging)
1761
+	 *
1762
+	 * @access public
1763
+	 * @param int  $per_page     count of items per page (20 default);
1764
+	 * @param int  $current_page what is the current page being viewed.
1765
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1766
+	 *                           If FALSE then we return an array of event objects
1767
+	 *                           that match the given _view and paging parameters.
1768
+	 * @return array an array of event objects.
1769
+	 */
1770
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1771
+	{
1772
+		$EEME = $this->_event_model();
1773
+		$offset = ($current_page - 1) * $per_page;
1774
+		$limit = $count ? null : $offset . ',' . $per_page;
1775
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1776
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1777
+		if (isset($this->_req_data['month_range'])) {
1778
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1779
+			// simulate the FIRST day of the month, that fixes issues for months like February
1780
+			// where PHP doesn't know what to assume for date.
1781
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1782
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1783
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1784
+		}
1785
+		$where = array();
1786
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1787
+		// determine what post_status our condition will have for the query.
1788
+		switch ($status) {
1789
+			case 'month':
1790
+			case 'today':
1791
+			case null:
1792
+			case 'all':
1793
+				break;
1794
+			case 'draft':
1795
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1796
+				break;
1797
+			default:
1798
+				$where['status'] = $status;
1799
+		}
1800
+		// categories?
1801
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1802
+			? $this->_req_data['EVT_CAT'] : null;
1803
+		if (! empty($category)) {
1804
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1805
+			$where['Term_Taxonomy.term_id'] = $category;
1806
+		}
1807
+		// date where conditions
1808
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1809
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1810
+			$DateTime = new DateTime(
1811
+				$year_r . '-' . $month_r . '-01 00:00:00',
1812
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1813
+			);
1814
+			$start = $DateTime->format(implode(' ', $start_formats));
1815
+			$end = $DateTime->setDate(
1816
+				$year_r,
1817
+				$month_r,
1818
+				$DateTime
1819
+					->format('t')
1820
+			)->setTime(23, 59, 59)
1821
+							->format(implode(' ', $start_formats));
1822
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1823
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1824
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1825
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1826
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1827
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1828
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1829
+			$now = date('Y-m-01');
1830
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1831
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1832
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1833
+							->setTime(23, 59, 59)
1834
+							->format(implode(' ', $start_formats));
1835
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1836
+		}
1837
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1838
+			$where['EVT_wp_user'] = get_current_user_id();
1839
+		} else {
1840
+			if (! isset($where['status'])) {
1841
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1842
+					$where['OR'] = array(
1843
+						'status*restrict_private' => array('!=', 'private'),
1844
+						'AND'                     => array(
1845
+							'status*inclusive' => array('=', 'private'),
1846
+							'EVT_wp_user'      => get_current_user_id(),
1847
+						),
1848
+					);
1849
+				}
1850
+			}
1851
+		}
1852
+		if (isset($this->_req_data['EVT_wp_user'])) {
1853
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1854
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1855
+			) {
1856
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1857
+			}
1858
+		}
1859
+		// search query handling
1860
+		if (isset($this->_req_data['s'])) {
1861
+			$search_string = '%' . $this->_req_data['s'] . '%';
1862
+			$where['OR'] = array(
1863
+				'EVT_name'       => array('LIKE', $search_string),
1864
+				'EVT_desc'       => array('LIKE', $search_string),
1865
+				'EVT_short_desc' => array('LIKE', $search_string),
1866
+			);
1867
+		}
1868
+		// filter events by venue.
1869
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1870
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1871
+		}
1872
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1873
+		$query_params = apply_filters(
1874
+			'FHEE__Events_Admin_Page__get_events__query_params',
1875
+			array(
1876
+				$where,
1877
+				'limit'    => $limit,
1878
+				'order_by' => $orderby,
1879
+				'order'    => $order,
1880
+				'group_by' => 'EVT_ID',
1881
+			),
1882
+			$this->_req_data
1883
+		);
1884
+		// let's first check if we have special requests coming in.
1885
+		if (isset($this->_req_data['active_status'])) {
1886
+			switch ($this->_req_data['active_status']) {
1887
+				case 'upcoming':
1888
+					return $EEME->get_upcoming_events($query_params, $count);
1889
+					break;
1890
+				case 'expired':
1891
+					return $EEME->get_expired_events($query_params, $count);
1892
+					break;
1893
+				case 'active':
1894
+					return $EEME->get_active_events($query_params, $count);
1895
+					break;
1896
+				case 'inactive':
1897
+					return $EEME->get_inactive_events($query_params, $count);
1898
+					break;
1899
+			}
1900
+		}
1901
+
1902
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1903
+		return $events;
1904
+	}
1905
+
1906
+
1907
+	/**
1908
+	 * handling for WordPress CPT actions (trash, restore, delete)
1909
+	 *
1910
+	 * @param string $post_id
1911
+	 */
1912
+	public function trash_cpt_item($post_id)
1913
+	{
1914
+		$this->_req_data['EVT_ID'] = $post_id;
1915
+		$this->_trash_or_restore_event('trash', false);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * @param string $post_id
1921
+	 */
1922
+	public function restore_cpt_item($post_id)
1923
+	{
1924
+		$this->_req_data['EVT_ID'] = $post_id;
1925
+		$this->_trash_or_restore_event('draft', false);
1926
+	}
1927
+
1928
+
1929
+	/**
1930
+	 * @param string $post_id
1931
+	 */
1932
+	public function delete_cpt_item($post_id)
1933
+	{
1934
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1935
+		$this->_req_data['EVT_ID'] = $post_id;
1936
+		$this->_delete_event();
1937
+	}
1938
+
1939
+
1940
+	/**
1941
+	 * _trash_or_restore_event
1942
+	 *
1943
+	 * @access protected
1944
+	 * @param  string $event_status
1945
+	 * @param bool    $redirect_after
1946
+	 */
1947
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1948
+	{
1949
+		// determine the event id and set to array.
1950
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1951
+		// loop thru events
1952
+		if ($EVT_ID) {
1953
+			// clean status
1954
+			$event_status = sanitize_key($event_status);
1955
+			// grab status
1956
+			if (! empty($event_status)) {
1957
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1958
+			} else {
1959
+				$success = false;
1960
+				$msg = esc_html__(
1961
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1962
+					'event_espresso'
1963
+				);
1964
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1965
+			}
1966
+		} else {
1967
+			$success = false;
1968
+			$msg = esc_html__(
1969
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1970
+				'event_espresso'
1971
+			);
1972
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1973
+		}
1974
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1975
+		if ($redirect_after) {
1976
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1977
+		}
1978
+	}
1979
+
1980
+
1981
+	/**
1982
+	 * _trash_or_restore_events
1983
+	 *
1984
+	 * @access protected
1985
+	 * @param  string $event_status
1986
+	 * @return void
1987
+	 */
1988
+	protected function _trash_or_restore_events($event_status = 'trash')
1989
+	{
1990
+		// clean status
1991
+		$event_status = sanitize_key($event_status);
1992
+		// grab status
1993
+		if (! empty($event_status)) {
1994
+			$success = true;
1995
+			// determine the event id and set to array.
1996
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1997
+			// loop thru events
1998
+			foreach ($EVT_IDs as $EVT_ID) {
1999
+				if ($EVT_ID = absint($EVT_ID)) {
2000
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2001
+					$success = $results !== false ? $success : false;
2002
+				} else {
2003
+					$msg = sprintf(
2004
+						esc_html__(
2005
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2006
+							'event_espresso'
2007
+						),
2008
+						$EVT_ID
2009
+					);
2010
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2011
+					$success = false;
2012
+				}
2013
+			}
2014
+		} else {
2015
+			$success = false;
2016
+			$msg = esc_html__(
2017
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2018
+				'event_espresso'
2019
+			);
2020
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2021
+		}
2022
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2023
+		$success = $success ? 2 : false;
2024
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2025
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2026
+	}
2027
+
2028
+
2029
+	/**
2030
+	 * _trash_or_restore_events
2031
+	 *
2032
+	 * @access  private
2033
+	 * @param  int    $EVT_ID
2034
+	 * @param  string $event_status
2035
+	 * @return bool
2036
+	 */
2037
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2038
+	{
2039
+		// grab event id
2040
+		if (! $EVT_ID) {
2041
+			$msg = esc_html__(
2042
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2043
+				'event_espresso'
2044
+			);
2045
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
+			return false;
2047
+		}
2048
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2049
+		// clean status
2050
+		$event_status = sanitize_key($event_status);
2051
+		// grab status
2052
+		if (empty($event_status)) {
2053
+			$msg = esc_html__(
2054
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2055
+				'event_espresso'
2056
+			);
2057
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2058
+			return false;
2059
+		}
2060
+		// was event trashed or restored ?
2061
+		switch ($event_status) {
2062
+			case 'draft':
2063
+				$action = 'restored from the trash';
2064
+				$hook = 'AHEE_event_restored_from_trash';
2065
+				break;
2066
+			case 'trash':
2067
+				$action = 'moved to the trash';
2068
+				$hook = 'AHEE_event_moved_to_trash';
2069
+				break;
2070
+			default:
2071
+				$action = 'updated';
2072
+				$hook = false;
2073
+		}
2074
+		// use class to change status
2075
+		$this->_cpt_model_obj->set_status($event_status);
2076
+		$success = $this->_cpt_model_obj->save();
2077
+		if ($success === false) {
2078
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2079
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2080
+			return false;
2081
+		}
2082
+		if ($hook) {
2083
+			do_action($hook);
2084
+		}
2085
+		return true;
2086
+	}
2087
+
2088
+
2089
+	/**
2090
+	 * _delete_event
2091
+	 *
2092
+	 * @access protected
2093
+	 * @param bool $redirect_after
2094
+	 */
2095
+	protected function _delete_event()
2096
+	{
2097
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : array());
2098
+	}
2099
+
2100
+	/**
2101
+	 * Gets the tree traversal batch persister.
2102
+	 * @since $VID:$
2103
+	 * @return NodeGroupDao
2104
+	 * @throws InvalidArgumentException
2105
+	 * @throws InvalidDataTypeException
2106
+	 * @throws InvalidInterfaceException
2107
+	 */
2108
+	protected function getModelObjNodeGroupPersister()
2109
+	{
2110
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2111
+			$this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2112
+		}
2113
+		return $this->model_obj_node_group_persister;
2114
+	}
2115
+
2116
+	/**
2117
+	 * _delete_events
2118
+	 *
2119
+	 * @access protected
2120
+	 * @return void
2121
+	 */
2122
+	protected function _delete_events()
2123
+	{
2124
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array());
2125
+	}
2126
+
2127
+	protected function generateDeletionPreview($event_ids)
2128
+	{
2129
+		$event_ids = (array) $event_ids;
2130
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2131
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2132
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2133
+			[
2134
+				'action' => 'preview_deletion',
2135
+				'deletion_job_code' => $deletion_job_code,
2136
+			],
2137
+			$this->_admin_base_url
2138
+		);
2139
+		$event_ids = array_map(
2140
+			'intval',
2141
+			$event_ids
2142
+		);
2143
+
2144
+		EEH_URL::safeRedirectAndExit(
2145
+			EE_Admin_Page::add_query_args_and_nonce(
2146
+				array(
2147
+					'page'        => 'espresso_batch',
2148
+					'batch'       => EED_Batch::batch_job,
2149
+					'EVT_IDs'      => $event_ids,
2150
+					'deletion_job_code' => $deletion_job_code,
2151
+					'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2152
+					'return_url'  => urlencode($return_url),
2153
+				),
2154
+				admin_url()
2155
+			)
2156
+		);
2157
+	}
2158
+
2159
+	/**
2160
+	 * Checks for a POST submission
2161
+	 * @since $VID:$
2162
+	 */
2163
+	protected function confirmDeletion()
2164
+	{
2165
+		$deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2166
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2167
+	}
2168
+
2169
+	/**
2170
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2171
+	 * @since $VID:$
2172
+	 * @throws EE_Error
2173
+	 */
2174
+	protected function previewDeletion()
2175
+	{
2176
+		$preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2177
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2178
+		$this->display_admin_page_with_no_sidebar();
2179
+	}
2180
+
2181
+	/**
2182
+	 * get total number of events
2183
+	 *
2184
+	 * @access public
2185
+	 * @return int
2186
+	 */
2187
+	public function total_events()
2188
+	{
2189
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2190
+		return $count;
2191
+	}
2192
+
2193
+
2194
+	/**
2195
+	 * get total number of draft events
2196
+	 *
2197
+	 * @access public
2198
+	 * @return int
2199
+	 */
2200
+	public function total_events_draft()
2201
+	{
2202
+		$where = array(
2203
+			'status' => array('IN', array('draft', 'auto-draft')),
2204
+		);
2205
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2206
+		return $count;
2207
+	}
2208
+
2209
+
2210
+	/**
2211
+	 * get total number of trashed events
2212
+	 *
2213
+	 * @access public
2214
+	 * @return int
2215
+	 */
2216
+	public function total_trashed_events()
2217
+	{
2218
+		$where = array(
2219
+			'status' => 'trash',
2220
+		);
2221
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2222
+		return $count;
2223
+	}
2224
+
2225
+
2226
+	/**
2227
+	 *    _default_event_settings
2228
+	 *    This generates the Default Settings Tab
2229
+	 *
2230
+	 * @return void
2231
+	 * @throws EE_Error
2232
+	 */
2233
+	protected function _default_event_settings()
2234
+	{
2235
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2236
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2237
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2238
+		$this->display_admin_page_with_sidebar();
2239
+	}
2240
+
2241
+
2242
+	/**
2243
+	 * Return the form for event settings.
2244
+	 *
2245
+	 * @return EE_Form_Section_Proper
2246
+	 * @throws EE_Error
2247
+	 */
2248
+	protected function _default_event_settings_form()
2249
+	{
2250
+		$registration_config = EE_Registry::instance()->CFG->registration;
2251
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2252
+			// exclude
2253
+			array(
2254
+				EEM_Registration::status_id_cancelled,
2255
+				EEM_Registration::status_id_declined,
2256
+				EEM_Registration::status_id_incomplete,
2257
+				EEM_Registration::status_id_wait_list,
2258
+			),
2259
+			true
2260
+		);
2261
+		return new EE_Form_Section_Proper(
2262
+			array(
2263
+				'name'            => 'update_default_event_settings',
2264
+				'html_id'         => 'update_default_event_settings',
2265
+				'html_class'      => 'form-table',
2266
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2267
+				'subsections'     => apply_filters(
2268
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2269
+					array(
2270
+						'default_reg_status'  => new EE_Select_Input(
2271
+							$registration_stati_for_selection,
2272
+							array(
2273
+								'default'         => isset($registration_config->default_STS_ID)
2274
+													 && array_key_exists(
2275
+														 $registration_config->default_STS_ID,
2276
+														 $registration_stati_for_selection
2277
+													 )
2278
+									? sanitize_text_field($registration_config->default_STS_ID)
2279
+									: EEM_Registration::status_id_pending_payment,
2280
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2281
+													 . EEH_Template::get_help_tab_link(
2282
+														 'default_settings_status_help_tab'
2283
+													 ),
2284
+								'html_help_text'  => esc_html__(
2285
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2286
+									'event_espresso'
2287
+								),
2288
+							)
2289
+						),
2290
+						'default_max_tickets' => new EE_Integer_Input(
2291
+							array(
2292
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2293
+									? $registration_config->default_maximum_number_of_tickets
2294
+									: EEM_Event::get_default_additional_limit(),
2295
+								'html_label_text' => esc_html__(
2296
+									'Default Maximum Tickets Allowed Per Order:',
2297
+									'event_espresso'
2298
+								)
2299
+													 . EEH_Template::get_help_tab_link(
2300
+														 'default_maximum_tickets_help_tab"'
2301
+													 ),
2302
+								'html_help_text'  => esc_html__(
2303
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2304
+									'event_espresso'
2305
+								),
2306
+							)
2307
+						),
2308
+					)
2309
+				),
2310
+			)
2311
+		);
2312
+	}
2313
+
2314
+
2315
+	/**
2316
+	 * _update_default_event_settings
2317
+	 *
2318
+	 * @access protected
2319
+	 * @return void
2320
+	 * @throws EE_Error
2321
+	 */
2322
+	protected function _update_default_event_settings()
2323
+	{
2324
+		$registration_config = EE_Registry::instance()->CFG->registration;
2325
+		$form = $this->_default_event_settings_form();
2326
+		if ($form->was_submitted()) {
2327
+			$form->receive_form_submission();
2328
+			if ($form->is_valid()) {
2329
+				$valid_data = $form->valid_data();
2330
+				if (isset($valid_data['default_reg_status'])) {
2331
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2332
+				}
2333
+				if (isset($valid_data['default_max_tickets'])) {
2334
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2335
+				}
2336
+				// update because data was valid!
2337
+				EE_Registry::instance()->CFG->update_espresso_config();
2338
+				EE_Error::overwrite_success();
2339
+				EE_Error::add_success(
2340
+					__('Default Event Settings were updated', 'event_espresso')
2341
+				);
2342
+			}
2343
+		}
2344
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2345
+	}
2346
+
2347
+
2348
+	/*************        Templates        *************/
2349
+	protected function _template_settings()
2350
+	{
2351
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2352
+		$this->_template_args['preview_img'] = '<img src="'
2353
+											   . EVENTS_ASSETS_URL
2354
+											   . '/images/'
2355
+											   . 'caffeinated_template_features.jpg" alt="'
2356
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2357
+											   . '" />';
2358
+		$this->_template_args['preview_text'] = '<strong>'
2359
+												. esc_html__(
2360
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2361
+													'event_espresso'
2362
+												) . '</strong>';
2363
+		$this->display_admin_caf_preview_page('template_settings_tab');
2364
+	}
2365
+
2366
+
2367
+	/** Event Category Stuff **/
2368
+	/**
2369
+	 * set the _category property with the category object for the loaded page.
2370
+	 *
2371
+	 * @access private
2372
+	 * @return void
2373
+	 */
2374
+	private function _set_category_object()
2375
+	{
2376
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2377
+			return;
2378
+		} //already have the category object so get out.
2379
+		// set default category object
2380
+		$this->_set_empty_category_object();
2381
+		// only set if we've got an id
2382
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2383
+			return;
2384
+		}
2385
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2386
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2387
+		if (! empty($term)) {
2388
+			$this->_category->category_name = $term->name;
2389
+			$this->_category->category_identifier = $term->slug;
2390
+			$this->_category->category_desc = $term->description;
2391
+			$this->_category->id = $term->term_id;
2392
+			$this->_category->parent = $term->parent;
2393
+		}
2394
+	}
2395
+
2396
+
2397
+	/**
2398
+	 * Clears out category properties.
2399
+	 */
2400
+	private function _set_empty_category_object()
2401
+	{
2402
+		$this->_category = new stdClass();
2403
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2404
+		$this->_category->id = $this->_category->parent = 0;
2405
+	}
2406
+
2407
+
2408
+	/**
2409
+	 * @throws EE_Error
2410
+	 */
2411
+	protected function _category_list_table()
2412
+	{
2413
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2414
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2415
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2416
+			'add_category',
2417
+			'add_category',
2418
+			array(),
2419
+			'add-new-h2'
2420
+		);
2421
+		$this->display_admin_list_table_page_with_sidebar();
2422
+	}
2423
+
2424
+
2425
+	/**
2426
+	 * Output category details view.
2427
+	 */
2428
+	protected function _category_details($view)
2429
+	{
2430
+		// load formatter helper
2431
+		// load field generator helper
2432
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2433
+		$this->_set_add_edit_form_tags($route);
2434
+		$this->_set_category_object();
2435
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2436
+		$delete_action = 'delete_category';
2437
+		// custom redirect
2438
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2439
+			array('action' => 'category_list'),
2440
+			$this->_admin_base_url
2441
+		);
2442
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2443
+		// take care of contents
2444
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2445
+		$this->display_admin_page_with_sidebar();
2446
+	}
2447
+
2448
+
2449
+	/**
2450
+	 * Output category details content.
2451
+	 */
2452
+	protected function _category_details_content()
2453
+	{
2454
+		$editor_args['category_desc'] = array(
2455
+			'type'          => 'wp_editor',
2456
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2457
+			'class'         => 'my_editor_custom',
2458
+			'wpeditor_args' => array('media_buttons' => false),
2459
+		);
2460
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2461
+		$all_terms = get_terms(
2462
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2463
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2464
+		);
2465
+		// setup category select for term parents.
2466
+		$category_select_values[] = array(
2467
+			'text' => esc_html__('No Parent', 'event_espresso'),
2468
+			'id'   => 0,
2469
+		);
2470
+		foreach ($all_terms as $term) {
2471
+			$category_select_values[] = array(
2472
+				'text' => $term->name,
2473
+				'id'   => $term->term_id,
2474
+			);
2475
+		}
2476
+		$category_select = EEH_Form_Fields::select_input(
2477
+			'category_parent',
2478
+			$category_select_values,
2479
+			$this->_category->parent
2480
+		);
2481
+		$template_args = array(
2482
+			'category'                 => $this->_category,
2483
+			'category_select'          => $category_select,
2484
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2485
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2486
+			'disable'                  => '',
2487
+			'disabled_message'         => false,
2488
+		);
2489
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2490
+		return EEH_Template::display_template($template, $template_args, true);
2491
+	}
2492
+
2493
+
2494
+	/**
2495
+	 * Handles deleting categories.
2496
+	 */
2497
+	protected function _delete_categories()
2498
+	{
2499
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2500
+			: (array) $this->_req_data['category_id'];
2501
+		foreach ($cat_ids as $cat_id) {
2502
+			$this->_delete_category($cat_id);
2503
+		}
2504
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2505
+		$query_args = array(
2506
+			'action' => 'category_list',
2507
+		);
2508
+		$this->_redirect_after_action(0, '', '', $query_args);
2509
+	}
2510
+
2511
+
2512
+	/**
2513
+	 * Handles deleting specific category.
2514
+	 *
2515
+	 * @param int $cat_id
2516
+	 */
2517
+	protected function _delete_category($cat_id)
2518
+	{
2519
+		$cat_id = absint($cat_id);
2520
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2521
+	}
2522
+
2523
+
2524
+	/**
2525
+	 * Handles triggering the update or insertion of a new category.
2526
+	 *
2527
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2528
+	 */
2529
+	protected function _insert_or_update_category($new_category)
2530
+	{
2531
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2532
+		$success = 0; // we already have a success message so lets not send another.
2533
+		if ($cat_id) {
2534
+			$query_args = array(
2535
+				'action'     => 'edit_category',
2536
+				'EVT_CAT_ID' => $cat_id,
2537
+			);
2538
+		} else {
2539
+			$query_args = array('action' => 'add_category');
2540
+		}
2541
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2542
+	}
2543
+
2544
+
2545
+	/**
2546
+	 * Inserts or updates category
2547
+	 *
2548
+	 * @param bool $update (true indicates we're updating a category).
2549
+	 * @return bool|mixed|string
2550
+	 */
2551
+	private function _insert_category($update = false)
2552
+	{
2553
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2554
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2555
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2556
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2557
+		if (empty($category_name)) {
2558
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2559
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2560
+			return false;
2561
+		}
2562
+		$term_args = array(
2563
+			'name'        => $category_name,
2564
+			'description' => $category_desc,
2565
+			'parent'      => $category_parent,
2566
+		);
2567
+		// was the category_identifier input disabled?
2568
+		if (isset($this->_req_data['category_identifier'])) {
2569
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2570
+		}
2571
+		$insert_ids = $update
2572
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2573
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2574
+		if (! is_array($insert_ids)) {
2575
+			$msg = esc_html__(
2576
+				'An error occurred and the category has not been saved to the database.',
2577
+				'event_espresso'
2578
+			);
2579
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2580
+		} else {
2581
+			$cat_id = $insert_ids['term_id'];
2582
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2583
+			EE_Error::add_success($msg);
2584
+		}
2585
+		return $cat_id;
2586
+	}
2587
+
2588
+
2589
+	/**
2590
+	 * Gets categories or count of categories matching the arguments in the request.
2591
+	 *
2592
+	 * @param int  $per_page
2593
+	 * @param int  $current_page
2594
+	 * @param bool $count
2595
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2596
+	 */
2597
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2598
+	{
2599
+		// testing term stuff
2600
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2601
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2602
+		$limit = ($current_page - 1) * $per_page;
2603
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2604
+		if (isset($this->_req_data['s'])) {
2605
+			$sstr = '%' . $this->_req_data['s'] . '%';
2606
+			$where['OR'] = array(
2607
+				'Term.name'   => array('LIKE', $sstr),
2608
+				'description' => array('LIKE', $sstr),
2609
+			);
2610
+		}
2611
+		$query_params = array(
2612
+			$where,
2613
+			'order_by'   => array($orderby => $order),
2614
+			'limit'      => $limit . ',' . $per_page,
2615
+			'force_join' => array('Term'),
2616
+		);
2617
+		$categories = $count
2618
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2619
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2620
+		return $categories;
2621
+	}
2622
+
2623
+	/* end category stuff */
2624
+	/**************/
2625
+
2626
+
2627
+	/**
2628
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2629
+	 *
2630
+	 * @throws EE_Error
2631
+	 */
2632
+	public function save_timezonestring_setting()
2633
+	{
2634
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2635
+			? $this->_req_data['timezone_selected']
2636
+			: '';
2637
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2638
+			EE_Error::add_error(
2639
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2640
+				__FILE__,
2641
+				__FUNCTION__,
2642
+				__LINE__
2643
+			);
2644
+			$this->_template_args['error'] = true;
2645
+			$this->_return_json();
2646
+		}
2647
+
2648
+		update_option('timezone_string', $timezone_string);
2649
+		EE_Error::add_success(
2650
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2651
+		);
2652
+		$this->_template_args['success'] = true;
2653
+		$this->_return_json(true, array('action' => 'create_new'));
2654
+	}
2655 2655
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_List_Table.class.php 2 patches
Indentation   +544 added lines, -544 removed lines patch added patch discarded remove patch
@@ -15,548 +15,548 @@
 block discarded – undo
15 15
 class Events_Admin_List_Table extends EE_Admin_List_Table
16 16
 {
17 17
 
18
-    /**
19
-     * @var EE_Datetime
20
-     */
21
-    private $_dtt;
22
-
23
-
24
-    /**
25
-     * Initial setup of data properties for the list table.
26
-     */
27
-    protected function _setup_data()
28
-    {
29
-        $this->_data = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
30
-        $this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
31
-    }
32
-
33
-
34
-    /**
35
-     * Set up of additional properties for the list table.
36
-     */
37
-    protected function _set_properties()
38
-    {
39
-        $this->_wp_list_args = array(
40
-            'singular' => esc_html__('event', 'event_espresso'),
41
-            'plural'   => esc_html__('events', 'event_espresso'),
42
-            'ajax'     => true, // for now
43
-            'screen'   => $this->_admin_page->get_current_screen()->id,
44
-        );
45
-        $this->_columns = array(
46
-            'cb'              => '<input type="checkbox" />',
47
-            'id'              => esc_html__('ID', 'event_espresso'),
48
-            'name'            => esc_html__('Name', 'event_espresso'),
49
-            'author'          => esc_html__('Author', 'event_espresso'),
50
-            'venue'           => esc_html__('Venue', 'event_espresso'),
51
-            'start_date_time' => esc_html__('Event Start', 'event_espresso'),
52
-            'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
53
-            'attendees'       => '<span class="dashicons dashicons-groups ee-icon-color-ee-green ee-icon-size-20">'
54
-                                 . '<span class="screen-reader-text">'
55
-                                 . esc_html__('Approved Registrations', 'event_espresso')
56
-                                 . '</span>'
57
-                                 . '</span>',
58
-            // 'tkts_sold' => esc_html__('Tickets Sold', 'event_espresso'),
59
-            'actions'         => esc_html__('Actions', 'event_espresso'),
60
-        );
61
-        $this->addConditionalColumns();
62
-        $this->_sortable_columns = array(
63
-            'id'              => array('EVT_ID' => true),
64
-            'name'            => array('EVT_name' => false),
65
-            'author'          => array('EVT_wp_user' => false),
66
-            'venue'           => array('Venue.VNU_name' => false),
67
-            'start_date_time' => array('Datetime.DTT_EVT_start' => false),
68
-            'reg_begins'      => array('Datetime.Ticket.TKT_start_date' => false),
69
-        );
70
-
71
-        $this->_primary_column = 'id';
72
-        $this->_hidden_columns = array('author', 'event_category');
73
-    }
74
-
75
-
76
-    /**
77
-     * @return array
78
-     */
79
-    protected function _get_table_filters()
80
-    {
81
-        return array(); // no filters with decaf
82
-    }
83
-
84
-
85
-    /**
86
-     * Setup of views properties.
87
-     *
88
-     * @throws InvalidDataTypeException
89
-     * @throws InvalidInterfaceException
90
-     * @throws InvalidArgumentException
91
-     */
92
-    protected function _add_view_counts()
93
-    {
94
-        $this->_views['all']['count'] = $this->_admin_page->total_events();
95
-        $this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
96
-        if (EE_Registry::instance()->CAP->current_user_can(
97
-            'ee_delete_events',
98
-            'espresso_events_trash_events'
99
-        )) {
100
-            $this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
101
-        }
102
-    }
103
-
104
-
105
-    /**
106
-     * @param EE_Event $item
107
-     * @return string
108
-     * @throws EE_Error
109
-     */
110
-    protected function _get_row_class($item)
111
-    {
112
-        $class = parent::_get_row_class($item);
113
-        // add status class
114
-        $class .= $item instanceof EE_Event
115
-            ? ' ee-status-strip event-status-' . $item->get_active_status()
116
-            : '';
117
-        if ($this->_has_checkbox_column) {
118
-            $class .= ' has-checkbox-column';
119
-        }
120
-        return $class;
121
-    }
122
-
123
-
124
-    /**
125
-     * @param EE_Event $item
126
-     * @return string
127
-     * @throws EE_Error
128
-     */
129
-    public function column_status(EE_Event $item)
130
-    {
131
-        return '<span class="ee-status-strip ee-status-strip-td event-status-'
132
-               . $item->get_active_status()
133
-               . '"></span>';
134
-    }
135
-
136
-
137
-    /**
138
-     * @param  EE_Event $item
139
-     * @return string
140
-     * @throws EE_Error
141
-     */
142
-    public function column_cb($item)
143
-    {
144
-        if (! $item instanceof EE_Event) {
145
-            return '';
146
-        }
147
-        $this->_dtt = $item->primary_datetime(); // set this for use in other columns
148
-        return sprintf(
149
-            '<input type="checkbox" name="EVT_IDs[]" value="%s" />',
150
-            $item->ID()
151
-        );
152
-    }
153
-
154
-
155
-    /**
156
-     * @param EE_Event $item
157
-     * @return mixed|string
158
-     * @throws EE_Error
159
-     */
160
-    public function column_id(EE_Event $item)
161
-    {
162
-        $content = $item->ID();
163
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
164
-        return $content;
165
-    }
166
-
167
-
168
-    /**
169
-     * @param EE_Event $item
170
-     * @return string
171
-     * @throws EE_Error
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     */
176
-    public function column_name(EE_Event $item)
177
-    {
178
-        $edit_query_args = array(
179
-            'action' => 'edit',
180
-            'post'   => $item->ID(),
181
-        );
182
-        $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
183
-        $actions = $this->_column_name_action_setup($item);
184
-        $status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
185
-        $content = '<strong><a class="row-title" href="'
186
-                   . $edit_link . '">'
187
-                   . $item->name()
188
-                   . '</a></strong>'
189
-                   . $status;
190
-        $content .= '<br><span class="ee-status-text-small">'
191
-                    . EEH_Template::pretty_status(
192
-                        $item->get_active_status(),
193
-                        false,
194
-                        'sentence'
195
-                    )
196
-                    . '</span>';
197
-        $content .= $this->row_actions($actions);
198
-        return $content;
199
-    }
200
-
201
-
202
-    /**
203
-     * Just a method for setting up the actions for the name column
204
-     *
205
-     * @param EE_Event $item
206
-     * @return array array of actions
207
-     * @throws EE_Error
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     */
212
-    protected function _column_name_action_setup(EE_Event $item)
213
-    {
214
-        // todo: remove when attendees is active
215
-        if (! defined('REG_ADMIN_URL')) {
216
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
217
-        }
218
-        $actions = array();
219
-        $restore_event_link = '';
220
-        $delete_event_link = '';
221
-        $trash_event_link = '';
222
-        if (EE_Registry::instance()->CAP->current_user_can(
223
-            'ee_edit_event',
224
-            'espresso_events_edit',
225
-            $item->ID()
226
-        )) {
227
-            $edit_query_args = array(
228
-                'action' => 'edit',
229
-                'post'   => $item->ID(),
230
-            );
231
-            $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
232
-            $actions['edit'] = '<a href="' . $edit_link . '"'
233
-                               . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
234
-                               . esc_html__('Edit', 'event_espresso')
235
-                               . '</a>';
236
-        }
237
-        if (EE_Registry::instance()->CAP->current_user_can(
238
-            'ee_read_registrations',
239
-            'espresso_registrations_view_registration'
240
-        )
241
-            && EE_Registry::instance()->CAP->current_user_can(
242
-                'ee_read_event',
243
-                'espresso_registrations_view_registration',
244
-                $item->ID()
245
-            )
246
-        ) {
247
-            $attendees_query_args = array(
248
-                'action'   => 'default',
249
-                'event_id' => $item->ID(),
250
-            );
251
-            $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
252
-            $actions['attendees'] = '<a href="' . $attendees_link . '"'
253
-                                    . ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
254
-                                    . esc_html__('Registrations', 'event_espresso')
255
-                                    . '</a>';
256
-        }
257
-        if (EE_Registry::instance()->CAP->current_user_can(
258
-            'ee_delete_event',
259
-            'espresso_events_trash_event',
260
-            $item->ID()
261
-        )) {
262
-            $trash_event_query_args = array(
263
-                'action' => 'trash_event',
264
-                'EVT_ID' => $item->ID(),
265
-            );
266
-            $trash_event_link = EE_Admin_Page::add_query_args_and_nonce(
267
-                $trash_event_query_args,
268
-                EVENTS_ADMIN_URL
269
-            );
270
-        }
271
-        if (EE_Registry::instance()->CAP->current_user_can(
272
-            'ee_delete_event',
273
-            'espresso_events_restore_event',
274
-            $item->ID()
275
-        )) {
276
-            $restore_event_query_args = array(
277
-                'action' => 'restore_event',
278
-                'EVT_ID' => $item->ID(),
279
-            );
280
-            $restore_event_link = EE_Admin_Page::add_query_args_and_nonce(
281
-                $restore_event_query_args,
282
-                EVENTS_ADMIN_URL
283
-            );
284
-        }
285
-        if (EE_Registry::instance()->CAP->current_user_can(
286
-            'ee_delete_event',
287
-            'espresso_events_delete_event',
288
-            $item->ID()
289
-        )) {
290
-            $delete_event_query_args = array(
291
-                'action' => 'delete_event',
292
-                'EVT_ID' => $item->ID(),
293
-            );
294
-            $delete_event_link = EE_Admin_Page::add_query_args_and_nonce(
295
-                $delete_event_query_args,
296
-                EVENTS_ADMIN_URL
297
-            );
298
-        }
299
-        $view_link = get_permalink($item->ID());
300
-        $actions['view'] = '<a href="' . $view_link . '"'
301
-                           . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
302
-                           . esc_html__('View', 'event_espresso')
303
-                           . '</a>';
304
-        if ($item->get('status') === 'trash') {
305
-            if (EE_Registry::instance()->CAP->current_user_can(
306
-                'ee_delete_event',
307
-                'espresso_events_restore_event',
308
-                $item->ID()
309
-            )) {
310
-                $actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
311
-                                                 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
312
-                                                 . '">'
313
-                                                 . esc_html__('Restore from Trash', 'event_espresso')
314
-                                                 . '</a>';
315
-            }
316
-            if (EE_Registry::instance()->CAP->current_user_can(
317
-                'ee_delete_event',
318
-                'espresso_events_delete_event',
319
-                $item->ID()
320
-            )
321
-            ) {
322
-                $actions['delete'] = '<a href="' . $delete_event_link . '"'
323
-                                     . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
324
-                                     . esc_html__('Delete Permanently', 'event_espresso')
325
-                                     . '</a>';
326
-            }
327
-        } else {
328
-            if (EE_Registry::instance()->CAP->current_user_can(
329
-                'ee_delete_event',
330
-                'espresso_events_trash_event',
331
-                $item->ID()
332
-            )) {
333
-                $actions['move to trash'] = '<a href="' . $trash_event_link . '"'
334
-                                            . ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
335
-                                            . esc_html__('Trash', 'event_espresso')
336
-                                            . '</a>';
337
-            }
338
-        }
339
-        return $actions;
340
-    }
341
-
342
-
343
-    /**
344
-     * @param EE_Event $item
345
-     * @return string
346
-     * @throws EE_Error
347
-     */
348
-    public function column_author(EE_Event $item)
349
-    {
350
-        // user author info
351
-        $event_author = get_userdata($item->wp_user());
352
-        $gravatar = get_avatar($item->wp_user(), '15');
353
-        // filter link
354
-        $query_args = array(
355
-            'action'      => 'default',
356
-            'EVT_wp_user' => $item->wp_user(),
357
-        );
358
-        $filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
359
-        return $gravatar . '  <a href="' . $filter_url . '"'
360
-               . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
361
-               . $event_author->display_name
362
-               . '</a>';
363
-    }
364
-
365
-
366
-    /**
367
-     * @param EE_Event $event
368
-     * @return string
369
-     * @throws EE_Error
370
-     */
371
-    public function column_event_category(EE_Event $event)
372
-    {
373
-        $event_categories = $event->get_all_event_categories();
374
-        return implode(
375
-            ', ',
376
-            array_map(
377
-                function (EE_Term $category) {
378
-                    return $category->name();
379
-                },
380
-                $event_categories
381
-            )
382
-        );
383
-    }
384
-
385
-
386
-    /**
387
-     * @param EE_Event $item
388
-     * @return string
389
-     * @throws EE_Error
390
-     */
391
-    public function column_venue(EE_Event $item)
392
-    {
393
-        $venue = $item->get_first_related('Venue');
394
-        return ! empty($venue)
395
-            ? $venue->name()
396
-            : '';
397
-    }
398
-
399
-
400
-    /**
401
-     * @param EE_Event $item
402
-     * @return string
403
-     * @throws EE_Error
404
-     */
405
-    public function column_start_date_time(EE_Event $item)
406
-    {
407
-        return $this->_dtt instanceof EE_Datetime
408
-            ? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
409
-            : esc_html__('No Date was saved for this Event', 'event_espresso');
410
-    }
411
-
412
-
413
-    /**
414
-     * @param EE_Event $item
415
-     * @return string
416
-     * @throws EE_Error
417
-     */
418
-    public function column_reg_begins(EE_Event $item)
419
-    {
420
-        $reg_start = $item->get_ticket_with_earliest_start_time();
421
-        return $reg_start instanceof EE_Ticket
422
-            ? $reg_start->get_i18n_datetime('TKT_start_date')
423
-            : esc_html__('No Tickets have been setup for this Event', 'event_espresso');
424
-    }
425
-
426
-
427
-    /**
428
-     * @param EE_Event $item
429
-     * @return int|string
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws InvalidDataTypeException
433
-     * @throws InvalidInterfaceException
434
-     */
435
-    public function column_attendees(EE_Event $item)
436
-    {
437
-        $attendees_query_args = array(
438
-            'action'   => 'default',
439
-            'event_id' => $item->ID(),
440
-        );
441
-        $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
442
-        $registered_attendees = EEM_Registration::instance()->get_event_registration_count($item->ID());
443
-        return EE_Registry::instance()->CAP->current_user_can(
444
-            'ee_read_event',
445
-            'espresso_registrations_view_registration',
446
-            $item->ID()
447
-        )
448
-               && EE_Registry::instance()->CAP->current_user_can(
449
-                   'ee_read_registrations',
450
-                   'espresso_registrations_view_registration'
451
-               )
452
-            ? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
453
-            : $registered_attendees;
454
-    }
455
-
456
-
457
-    /**
458
-     * @param EE_Event $item
459
-     * @return float
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidDataTypeException
463
-     * @throws InvalidInterfaceException
464
-     */
465
-    public function column_tkts_sold(EE_Event $item)
466
-    {
467
-        return EEM_Ticket::instance()->sum(array(array('Datetime.EVT_ID' => $item->ID())), 'TKT_sold');
468
-    }
469
-
470
-
471
-    /**
472
-     * @param EE_Event $item
473
-     * @return string
474
-     * @throws EE_Error
475
-     * @throws InvalidArgumentException
476
-     * @throws InvalidDataTypeException
477
-     * @throws InvalidInterfaceException
478
-     */
479
-    public function column_actions(EE_Event $item)
480
-    {
481
-        // todo: remove when attendees is active
482
-        if (! defined('REG_ADMIN_URL')) {
483
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
484
-        }
485
-        $action_links = array();
486
-        $view_link = get_permalink($item->ID());
487
-        $action_links[] = '<a href="' . $view_link . '"'
488
-                          . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
489
-        $action_links[] = '<div class="dashicons dashicons-search"></div></a>';
490
-        if (EE_Registry::instance()->CAP->current_user_can(
491
-            'ee_edit_event',
492
-            'espresso_events_edit',
493
-            $item->ID()
494
-        )) {
495
-            $edit_query_args = array(
496
-                'action' => 'edit',
497
-                'post'   => $item->ID(),
498
-            );
499
-            $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
500
-            $action_links[] = '<a href="' . $edit_link . '"'
501
-                              . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
502
-                              . '<div class="ee-icon ee-icon-calendar-edit"></div>'
503
-                              . '</a>';
504
-        }
505
-        if (EE_Registry::instance()->CAP->current_user_can(
506
-            'ee_read_registrations',
507
-            'espresso_registrations_view_registration'
508
-        ) && EE_Registry::instance()->CAP->current_user_can(
509
-            'ee_read_event',
510
-            'espresso_registrations_view_registration',
511
-            $item->ID()
512
-        )
513
-        ) {
514
-            $attendees_query_args = array(
515
-                'action'   => 'default',
516
-                'event_id' => $item->ID(),
517
-            );
518
-            $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
519
-            $action_links[] = '<a href="' . $attendees_link . '"'
520
-                              . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
521
-                              . '<div class="dashicons dashicons-groups"></div>'
522
-                              . '</a>';
523
-        }
524
-        $action_links = apply_filters(
525
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
526
-            $action_links,
527
-            $item
528
-        );
529
-        return $this->_action_string(
530
-            implode("\n\t", $action_links),
531
-            $item,
532
-            'div'
533
-        );
534
-    }
535
-
536
-
537
-    /**
538
-     * Helper for adding columns conditionally
539
-     *
540
-     * @throws EE_Error
541
-     * @throws InvalidArgumentException
542
-     * @throws InvalidDataTypeException
543
-     * @throws InvalidInterfaceException
544
-     */
545
-    private function addConditionalColumns()
546
-    {
547
-        $event_category_count = EEM_Term::instance()->count(
548
-            [['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
549
-        );
550
-        if ($event_category_count === 0) {
551
-            return;
552
-        }
553
-        $column_array = [];
554
-        foreach ($this->_columns as $column => $column_label) {
555
-            $column_array[ $column ] = $column_label;
556
-            if ($column === 'venue') {
557
-                $column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
558
-            }
559
-        }
560
-        $this->_columns = $column_array;
561
-    }
18
+	/**
19
+	 * @var EE_Datetime
20
+	 */
21
+	private $_dtt;
22
+
23
+
24
+	/**
25
+	 * Initial setup of data properties for the list table.
26
+	 */
27
+	protected function _setup_data()
28
+	{
29
+		$this->_data = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
30
+		$this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
31
+	}
32
+
33
+
34
+	/**
35
+	 * Set up of additional properties for the list table.
36
+	 */
37
+	protected function _set_properties()
38
+	{
39
+		$this->_wp_list_args = array(
40
+			'singular' => esc_html__('event', 'event_espresso'),
41
+			'plural'   => esc_html__('events', 'event_espresso'),
42
+			'ajax'     => true, // for now
43
+			'screen'   => $this->_admin_page->get_current_screen()->id,
44
+		);
45
+		$this->_columns = array(
46
+			'cb'              => '<input type="checkbox" />',
47
+			'id'              => esc_html__('ID', 'event_espresso'),
48
+			'name'            => esc_html__('Name', 'event_espresso'),
49
+			'author'          => esc_html__('Author', 'event_espresso'),
50
+			'venue'           => esc_html__('Venue', 'event_espresso'),
51
+			'start_date_time' => esc_html__('Event Start', 'event_espresso'),
52
+			'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
53
+			'attendees'       => '<span class="dashicons dashicons-groups ee-icon-color-ee-green ee-icon-size-20">'
54
+								 . '<span class="screen-reader-text">'
55
+								 . esc_html__('Approved Registrations', 'event_espresso')
56
+								 . '</span>'
57
+								 . '</span>',
58
+			// 'tkts_sold' => esc_html__('Tickets Sold', 'event_espresso'),
59
+			'actions'         => esc_html__('Actions', 'event_espresso'),
60
+		);
61
+		$this->addConditionalColumns();
62
+		$this->_sortable_columns = array(
63
+			'id'              => array('EVT_ID' => true),
64
+			'name'            => array('EVT_name' => false),
65
+			'author'          => array('EVT_wp_user' => false),
66
+			'venue'           => array('Venue.VNU_name' => false),
67
+			'start_date_time' => array('Datetime.DTT_EVT_start' => false),
68
+			'reg_begins'      => array('Datetime.Ticket.TKT_start_date' => false),
69
+		);
70
+
71
+		$this->_primary_column = 'id';
72
+		$this->_hidden_columns = array('author', 'event_category');
73
+	}
74
+
75
+
76
+	/**
77
+	 * @return array
78
+	 */
79
+	protected function _get_table_filters()
80
+	{
81
+		return array(); // no filters with decaf
82
+	}
83
+
84
+
85
+	/**
86
+	 * Setup of views properties.
87
+	 *
88
+	 * @throws InvalidDataTypeException
89
+	 * @throws InvalidInterfaceException
90
+	 * @throws InvalidArgumentException
91
+	 */
92
+	protected function _add_view_counts()
93
+	{
94
+		$this->_views['all']['count'] = $this->_admin_page->total_events();
95
+		$this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
96
+		if (EE_Registry::instance()->CAP->current_user_can(
97
+			'ee_delete_events',
98
+			'espresso_events_trash_events'
99
+		)) {
100
+			$this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
101
+		}
102
+	}
103
+
104
+
105
+	/**
106
+	 * @param EE_Event $item
107
+	 * @return string
108
+	 * @throws EE_Error
109
+	 */
110
+	protected function _get_row_class($item)
111
+	{
112
+		$class = parent::_get_row_class($item);
113
+		// add status class
114
+		$class .= $item instanceof EE_Event
115
+			? ' ee-status-strip event-status-' . $item->get_active_status()
116
+			: '';
117
+		if ($this->_has_checkbox_column) {
118
+			$class .= ' has-checkbox-column';
119
+		}
120
+		return $class;
121
+	}
122
+
123
+
124
+	/**
125
+	 * @param EE_Event $item
126
+	 * @return string
127
+	 * @throws EE_Error
128
+	 */
129
+	public function column_status(EE_Event $item)
130
+	{
131
+		return '<span class="ee-status-strip ee-status-strip-td event-status-'
132
+			   . $item->get_active_status()
133
+			   . '"></span>';
134
+	}
135
+
136
+
137
+	/**
138
+	 * @param  EE_Event $item
139
+	 * @return string
140
+	 * @throws EE_Error
141
+	 */
142
+	public function column_cb($item)
143
+	{
144
+		if (! $item instanceof EE_Event) {
145
+			return '';
146
+		}
147
+		$this->_dtt = $item->primary_datetime(); // set this for use in other columns
148
+		return sprintf(
149
+			'<input type="checkbox" name="EVT_IDs[]" value="%s" />',
150
+			$item->ID()
151
+		);
152
+	}
153
+
154
+
155
+	/**
156
+	 * @param EE_Event $item
157
+	 * @return mixed|string
158
+	 * @throws EE_Error
159
+	 */
160
+	public function column_id(EE_Event $item)
161
+	{
162
+		$content = $item->ID();
163
+		$content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
164
+		return $content;
165
+	}
166
+
167
+
168
+	/**
169
+	 * @param EE_Event $item
170
+	 * @return string
171
+	 * @throws EE_Error
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 */
176
+	public function column_name(EE_Event $item)
177
+	{
178
+		$edit_query_args = array(
179
+			'action' => 'edit',
180
+			'post'   => $item->ID(),
181
+		);
182
+		$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
183
+		$actions = $this->_column_name_action_setup($item);
184
+		$status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
185
+		$content = '<strong><a class="row-title" href="'
186
+				   . $edit_link . '">'
187
+				   . $item->name()
188
+				   . '</a></strong>'
189
+				   . $status;
190
+		$content .= '<br><span class="ee-status-text-small">'
191
+					. EEH_Template::pretty_status(
192
+						$item->get_active_status(),
193
+						false,
194
+						'sentence'
195
+					)
196
+					. '</span>';
197
+		$content .= $this->row_actions($actions);
198
+		return $content;
199
+	}
200
+
201
+
202
+	/**
203
+	 * Just a method for setting up the actions for the name column
204
+	 *
205
+	 * @param EE_Event $item
206
+	 * @return array array of actions
207
+	 * @throws EE_Error
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 */
212
+	protected function _column_name_action_setup(EE_Event $item)
213
+	{
214
+		// todo: remove when attendees is active
215
+		if (! defined('REG_ADMIN_URL')) {
216
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
217
+		}
218
+		$actions = array();
219
+		$restore_event_link = '';
220
+		$delete_event_link = '';
221
+		$trash_event_link = '';
222
+		if (EE_Registry::instance()->CAP->current_user_can(
223
+			'ee_edit_event',
224
+			'espresso_events_edit',
225
+			$item->ID()
226
+		)) {
227
+			$edit_query_args = array(
228
+				'action' => 'edit',
229
+				'post'   => $item->ID(),
230
+			);
231
+			$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
232
+			$actions['edit'] = '<a href="' . $edit_link . '"'
233
+							   . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
234
+							   . esc_html__('Edit', 'event_espresso')
235
+							   . '</a>';
236
+		}
237
+		if (EE_Registry::instance()->CAP->current_user_can(
238
+			'ee_read_registrations',
239
+			'espresso_registrations_view_registration'
240
+		)
241
+			&& EE_Registry::instance()->CAP->current_user_can(
242
+				'ee_read_event',
243
+				'espresso_registrations_view_registration',
244
+				$item->ID()
245
+			)
246
+		) {
247
+			$attendees_query_args = array(
248
+				'action'   => 'default',
249
+				'event_id' => $item->ID(),
250
+			);
251
+			$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
252
+			$actions['attendees'] = '<a href="' . $attendees_link . '"'
253
+									. ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
254
+									. esc_html__('Registrations', 'event_espresso')
255
+									. '</a>';
256
+		}
257
+		if (EE_Registry::instance()->CAP->current_user_can(
258
+			'ee_delete_event',
259
+			'espresso_events_trash_event',
260
+			$item->ID()
261
+		)) {
262
+			$trash_event_query_args = array(
263
+				'action' => 'trash_event',
264
+				'EVT_ID' => $item->ID(),
265
+			);
266
+			$trash_event_link = EE_Admin_Page::add_query_args_and_nonce(
267
+				$trash_event_query_args,
268
+				EVENTS_ADMIN_URL
269
+			);
270
+		}
271
+		if (EE_Registry::instance()->CAP->current_user_can(
272
+			'ee_delete_event',
273
+			'espresso_events_restore_event',
274
+			$item->ID()
275
+		)) {
276
+			$restore_event_query_args = array(
277
+				'action' => 'restore_event',
278
+				'EVT_ID' => $item->ID(),
279
+			);
280
+			$restore_event_link = EE_Admin_Page::add_query_args_and_nonce(
281
+				$restore_event_query_args,
282
+				EVENTS_ADMIN_URL
283
+			);
284
+		}
285
+		if (EE_Registry::instance()->CAP->current_user_can(
286
+			'ee_delete_event',
287
+			'espresso_events_delete_event',
288
+			$item->ID()
289
+		)) {
290
+			$delete_event_query_args = array(
291
+				'action' => 'delete_event',
292
+				'EVT_ID' => $item->ID(),
293
+			);
294
+			$delete_event_link = EE_Admin_Page::add_query_args_and_nonce(
295
+				$delete_event_query_args,
296
+				EVENTS_ADMIN_URL
297
+			);
298
+		}
299
+		$view_link = get_permalink($item->ID());
300
+		$actions['view'] = '<a href="' . $view_link . '"'
301
+						   . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
302
+						   . esc_html__('View', 'event_espresso')
303
+						   . '</a>';
304
+		if ($item->get('status') === 'trash') {
305
+			if (EE_Registry::instance()->CAP->current_user_can(
306
+				'ee_delete_event',
307
+				'espresso_events_restore_event',
308
+				$item->ID()
309
+			)) {
310
+				$actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
311
+												 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
312
+												 . '">'
313
+												 . esc_html__('Restore from Trash', 'event_espresso')
314
+												 . '</a>';
315
+			}
316
+			if (EE_Registry::instance()->CAP->current_user_can(
317
+				'ee_delete_event',
318
+				'espresso_events_delete_event',
319
+				$item->ID()
320
+			)
321
+			) {
322
+				$actions['delete'] = '<a href="' . $delete_event_link . '"'
323
+									 . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
324
+									 . esc_html__('Delete Permanently', 'event_espresso')
325
+									 . '</a>';
326
+			}
327
+		} else {
328
+			if (EE_Registry::instance()->CAP->current_user_can(
329
+				'ee_delete_event',
330
+				'espresso_events_trash_event',
331
+				$item->ID()
332
+			)) {
333
+				$actions['move to trash'] = '<a href="' . $trash_event_link . '"'
334
+											. ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
335
+											. esc_html__('Trash', 'event_espresso')
336
+											. '</a>';
337
+			}
338
+		}
339
+		return $actions;
340
+	}
341
+
342
+
343
+	/**
344
+	 * @param EE_Event $item
345
+	 * @return string
346
+	 * @throws EE_Error
347
+	 */
348
+	public function column_author(EE_Event $item)
349
+	{
350
+		// user author info
351
+		$event_author = get_userdata($item->wp_user());
352
+		$gravatar = get_avatar($item->wp_user(), '15');
353
+		// filter link
354
+		$query_args = array(
355
+			'action'      => 'default',
356
+			'EVT_wp_user' => $item->wp_user(),
357
+		);
358
+		$filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
359
+		return $gravatar . '  <a href="' . $filter_url . '"'
360
+			   . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
361
+			   . $event_author->display_name
362
+			   . '</a>';
363
+	}
364
+
365
+
366
+	/**
367
+	 * @param EE_Event $event
368
+	 * @return string
369
+	 * @throws EE_Error
370
+	 */
371
+	public function column_event_category(EE_Event $event)
372
+	{
373
+		$event_categories = $event->get_all_event_categories();
374
+		return implode(
375
+			', ',
376
+			array_map(
377
+				function (EE_Term $category) {
378
+					return $category->name();
379
+				},
380
+				$event_categories
381
+			)
382
+		);
383
+	}
384
+
385
+
386
+	/**
387
+	 * @param EE_Event $item
388
+	 * @return string
389
+	 * @throws EE_Error
390
+	 */
391
+	public function column_venue(EE_Event $item)
392
+	{
393
+		$venue = $item->get_first_related('Venue');
394
+		return ! empty($venue)
395
+			? $venue->name()
396
+			: '';
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param EE_Event $item
402
+	 * @return string
403
+	 * @throws EE_Error
404
+	 */
405
+	public function column_start_date_time(EE_Event $item)
406
+	{
407
+		return $this->_dtt instanceof EE_Datetime
408
+			? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
409
+			: esc_html__('No Date was saved for this Event', 'event_espresso');
410
+	}
411
+
412
+
413
+	/**
414
+	 * @param EE_Event $item
415
+	 * @return string
416
+	 * @throws EE_Error
417
+	 */
418
+	public function column_reg_begins(EE_Event $item)
419
+	{
420
+		$reg_start = $item->get_ticket_with_earliest_start_time();
421
+		return $reg_start instanceof EE_Ticket
422
+			? $reg_start->get_i18n_datetime('TKT_start_date')
423
+			: esc_html__('No Tickets have been setup for this Event', 'event_espresso');
424
+	}
425
+
426
+
427
+	/**
428
+	 * @param EE_Event $item
429
+	 * @return int|string
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws InvalidDataTypeException
433
+	 * @throws InvalidInterfaceException
434
+	 */
435
+	public function column_attendees(EE_Event $item)
436
+	{
437
+		$attendees_query_args = array(
438
+			'action'   => 'default',
439
+			'event_id' => $item->ID(),
440
+		);
441
+		$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
442
+		$registered_attendees = EEM_Registration::instance()->get_event_registration_count($item->ID());
443
+		return EE_Registry::instance()->CAP->current_user_can(
444
+			'ee_read_event',
445
+			'espresso_registrations_view_registration',
446
+			$item->ID()
447
+		)
448
+			   && EE_Registry::instance()->CAP->current_user_can(
449
+				   'ee_read_registrations',
450
+				   'espresso_registrations_view_registration'
451
+			   )
452
+			? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
453
+			: $registered_attendees;
454
+	}
455
+
456
+
457
+	/**
458
+	 * @param EE_Event $item
459
+	 * @return float
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidDataTypeException
463
+	 * @throws InvalidInterfaceException
464
+	 */
465
+	public function column_tkts_sold(EE_Event $item)
466
+	{
467
+		return EEM_Ticket::instance()->sum(array(array('Datetime.EVT_ID' => $item->ID())), 'TKT_sold');
468
+	}
469
+
470
+
471
+	/**
472
+	 * @param EE_Event $item
473
+	 * @return string
474
+	 * @throws EE_Error
475
+	 * @throws InvalidArgumentException
476
+	 * @throws InvalidDataTypeException
477
+	 * @throws InvalidInterfaceException
478
+	 */
479
+	public function column_actions(EE_Event $item)
480
+	{
481
+		// todo: remove when attendees is active
482
+		if (! defined('REG_ADMIN_URL')) {
483
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
484
+		}
485
+		$action_links = array();
486
+		$view_link = get_permalink($item->ID());
487
+		$action_links[] = '<a href="' . $view_link . '"'
488
+						  . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
489
+		$action_links[] = '<div class="dashicons dashicons-search"></div></a>';
490
+		if (EE_Registry::instance()->CAP->current_user_can(
491
+			'ee_edit_event',
492
+			'espresso_events_edit',
493
+			$item->ID()
494
+		)) {
495
+			$edit_query_args = array(
496
+				'action' => 'edit',
497
+				'post'   => $item->ID(),
498
+			);
499
+			$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
500
+			$action_links[] = '<a href="' . $edit_link . '"'
501
+							  . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
502
+							  . '<div class="ee-icon ee-icon-calendar-edit"></div>'
503
+							  . '</a>';
504
+		}
505
+		if (EE_Registry::instance()->CAP->current_user_can(
506
+			'ee_read_registrations',
507
+			'espresso_registrations_view_registration'
508
+		) && EE_Registry::instance()->CAP->current_user_can(
509
+			'ee_read_event',
510
+			'espresso_registrations_view_registration',
511
+			$item->ID()
512
+		)
513
+		) {
514
+			$attendees_query_args = array(
515
+				'action'   => 'default',
516
+				'event_id' => $item->ID(),
517
+			);
518
+			$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
519
+			$action_links[] = '<a href="' . $attendees_link . '"'
520
+							  . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
521
+							  . '<div class="dashicons dashicons-groups"></div>'
522
+							  . '</a>';
523
+		}
524
+		$action_links = apply_filters(
525
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
526
+			$action_links,
527
+			$item
528
+		);
529
+		return $this->_action_string(
530
+			implode("\n\t", $action_links),
531
+			$item,
532
+			'div'
533
+		);
534
+	}
535
+
536
+
537
+	/**
538
+	 * Helper for adding columns conditionally
539
+	 *
540
+	 * @throws EE_Error
541
+	 * @throws InvalidArgumentException
542
+	 * @throws InvalidDataTypeException
543
+	 * @throws InvalidInterfaceException
544
+	 */
545
+	private function addConditionalColumns()
546
+	{
547
+		$event_category_count = EEM_Term::instance()->count(
548
+			[['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
549
+		);
550
+		if ($event_category_count === 0) {
551
+			return;
552
+		}
553
+		$column_array = [];
554
+		foreach ($this->_columns as $column => $column_label) {
555
+			$column_array[ $column ] = $column_label;
556
+			if ($column === 'venue') {
557
+				$column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
558
+			}
559
+		}
560
+		$this->_columns = $column_array;
561
+	}
562 562
 }
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -112,7 +112,7 @@  discard block
 block discarded – undo
112 112
         $class = parent::_get_row_class($item);
113 113
         // add status class
114 114
         $class .= $item instanceof EE_Event
115
-            ? ' ee-status-strip event-status-' . $item->get_active_status()
115
+            ? ' ee-status-strip event-status-'.$item->get_active_status()
116 116
             : '';
117 117
         if ($this->_has_checkbox_column) {
118 118
             $class .= ' has-checkbox-column';
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
      */
142 142
     public function column_cb($item)
143 143
     {
144
-        if (! $item instanceof EE_Event) {
144
+        if ( ! $item instanceof EE_Event) {
145 145
             return '';
146 146
         }
147 147
         $this->_dtt = $item->primary_datetime(); // set this for use in other columns
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
     public function column_id(EE_Event $item)
161 161
     {
162 162
         $content = $item->ID();
163
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
163
+        $content .= '  <span class="show-on-mobile-view-only">'.$item->name().'</span>';
164 164
         return $content;
165 165
     }
166 166
 
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
         $actions = $this->_column_name_action_setup($item);
184 184
         $status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
185 185
         $content = '<strong><a class="row-title" href="'
186
-                   . $edit_link . '">'
186
+                   . $edit_link.'">'
187 187
                    . $item->name()
188 188
                    . '</a></strong>'
189 189
                    . $status;
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
     protected function _column_name_action_setup(EE_Event $item)
213 213
     {
214 214
         // todo: remove when attendees is active
215
-        if (! defined('REG_ADMIN_URL')) {
215
+        if ( ! defined('REG_ADMIN_URL')) {
216 216
             define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
217 217
         }
218 218
         $actions = array();
@@ -229,8 +229,8 @@  discard block
 block discarded – undo
229 229
                 'post'   => $item->ID(),
230 230
             );
231 231
             $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
232
-            $actions['edit'] = '<a href="' . $edit_link . '"'
233
-                               . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
232
+            $actions['edit'] = '<a href="'.$edit_link.'"'
233
+                               . ' title="'.esc_attr__('Edit Event', 'event_espresso').'">'
234 234
                                . esc_html__('Edit', 'event_espresso')
235 235
                                . '</a>';
236 236
         }
@@ -249,8 +249,8 @@  discard block
 block discarded – undo
249 249
                 'event_id' => $item->ID(),
250 250
             );
251 251
             $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
252
-            $actions['attendees'] = '<a href="' . $attendees_link . '"'
253
-                                    . ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
252
+            $actions['attendees'] = '<a href="'.$attendees_link.'"'
253
+                                    . ' title="'.esc_attr__('View Registrations', 'event_espresso').'">'
254 254
                                     . esc_html__('Registrations', 'event_espresso')
255 255
                                     . '</a>';
256 256
         }
@@ -297,8 +297,8 @@  discard block
 block discarded – undo
297 297
             );
298 298
         }
299 299
         $view_link = get_permalink($item->ID());
300
-        $actions['view'] = '<a href="' . $view_link . '"'
301
-                           . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
300
+        $actions['view'] = '<a href="'.$view_link.'"'
301
+                           . ' title="'.esc_attr__('View Event', 'event_espresso').'">'
302 302
                            . esc_html__('View', 'event_espresso')
303 303
                            . '</a>';
304 304
         if ($item->get('status') === 'trash') {
@@ -307,8 +307,8 @@  discard block
 block discarded – undo
307 307
                 'espresso_events_restore_event',
308 308
                 $item->ID()
309 309
             )) {
310
-                $actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
311
-                                                 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
310
+                $actions['restore_from_trash'] = '<a href="'.$restore_event_link.'"'
311
+                                                 . ' title="'.esc_attr__('Restore from Trash', 'event_espresso')
312 312
                                                  . '">'
313 313
                                                  . esc_html__('Restore from Trash', 'event_espresso')
314 314
                                                  . '</a>';
@@ -319,8 +319,8 @@  discard block
 block discarded – undo
319 319
                 $item->ID()
320 320
             )
321 321
             ) {
322
-                $actions['delete'] = '<a href="' . $delete_event_link . '"'
323
-                                     . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
322
+                $actions['delete'] = '<a href="'.$delete_event_link.'"'
323
+                                     . ' title="'.esc_attr__('Delete Permanently', 'event_espresso').'">'
324 324
                                      . esc_html__('Delete Permanently', 'event_espresso')
325 325
                                      . '</a>';
326 326
             }
@@ -330,8 +330,8 @@  discard block
 block discarded – undo
330 330
                 'espresso_events_trash_event',
331 331
                 $item->ID()
332 332
             )) {
333
-                $actions['move to trash'] = '<a href="' . $trash_event_link . '"'
334
-                                            . ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
333
+                $actions['move to trash'] = '<a href="'.$trash_event_link.'"'
334
+                                            . ' title="'.esc_attr__('Trash Event', 'event_espresso').'">'
335 335
                                             . esc_html__('Trash', 'event_espresso')
336 336
                                             . '</a>';
337 337
             }
@@ -356,8 +356,8 @@  discard block
 block discarded – undo
356 356
             'EVT_wp_user' => $item->wp_user(),
357 357
         );
358 358
         $filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
359
-        return $gravatar . '  <a href="' . $filter_url . '"'
360
-               . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
359
+        return $gravatar.'  <a href="'.$filter_url.'"'
360
+               . ' title="'.esc_attr__('Click to filter events by this author.', 'event_espresso').'">'
361 361
                . $event_author->display_name
362 362
                . '</a>';
363 363
     }
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
         return implode(
375 375
             ', ',
376 376
             array_map(
377
-                function (EE_Term $category) {
377
+                function(EE_Term $category) {
378 378
                     return $category->name();
379 379
                 },
380 380
                 $event_categories
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
                    'ee_read_registrations',
450 450
                    'espresso_registrations_view_registration'
451 451
                )
452
-            ? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
452
+            ? '<a href="'.$attendees_link.'">'.$registered_attendees.'</a>'
453 453
             : $registered_attendees;
454 454
     }
455 455
 
@@ -479,13 +479,13 @@  discard block
 block discarded – undo
479 479
     public function column_actions(EE_Event $item)
480 480
     {
481 481
         // todo: remove when attendees is active
482
-        if (! defined('REG_ADMIN_URL')) {
482
+        if ( ! defined('REG_ADMIN_URL')) {
483 483
             define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
484 484
         }
485 485
         $action_links = array();
486 486
         $view_link = get_permalink($item->ID());
487
-        $action_links[] = '<a href="' . $view_link . '"'
488
-                          . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
487
+        $action_links[] = '<a href="'.$view_link.'"'
488
+                          . ' title="'.esc_attr__('View Event', 'event_espresso').'" target="_blank">';
489 489
         $action_links[] = '<div class="dashicons dashicons-search"></div></a>';
490 490
         if (EE_Registry::instance()->CAP->current_user_can(
491 491
             'ee_edit_event',
@@ -497,8 +497,8 @@  discard block
 block discarded – undo
497 497
                 'post'   => $item->ID(),
498 498
             );
499 499
             $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
500
-            $action_links[] = '<a href="' . $edit_link . '"'
501
-                              . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
500
+            $action_links[] = '<a href="'.$edit_link.'"'
501
+                              . ' title="'.esc_attr__('Edit Event', 'event_espresso').'">'
502 502
                               . '<div class="ee-icon ee-icon-calendar-edit"></div>'
503 503
                               . '</a>';
504 504
         }
@@ -516,8 +516,8 @@  discard block
 block discarded – undo
516 516
                 'event_id' => $item->ID(),
517 517
             );
518 518
             $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
519
-            $action_links[] = '<a href="' . $attendees_link . '"'
520
-                              . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
519
+            $action_links[] = '<a href="'.$attendees_link.'"'
520
+                              . ' title="'.esc_attr__('View Registrants', 'event_espresso').'">'
521 521
                               . '<div class="dashicons dashicons-groups"></div>'
522 522
                               . '</a>';
523 523
         }
@@ -552,7 +552,7 @@  discard block
 block discarded – undo
552 552
         }
553 553
         $column_array = [];
554 554
         foreach ($this->_columns as $column => $column_label) {
555
-            $column_array[ $column ] = $column_label;
555
+            $column_array[$column] = $column_label;
556 556
             if ($column === 'venue') {
557 557
                 $column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
558 558
             }
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/RelationNode.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -130,7 +130,7 @@
 block discarded – undo
130 130
      * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
131 131
      * @since $VID:$
132 132
      * @param ModelObjNode[] $model_obj_nodes
133
-     * @param $work_budget
133
+     * @param integer $work_budget
134 134
      * @return int
135 135
      */
136 136
     protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
Please login to merge, or discard this patch.
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -2,15 +2,12 @@
 block discarded – undo
2 2
 
3 3
 namespace EventEspresso\core\services\orm\tree_traversal;
4 4
 
5
-use EE_Base_Class;
6 5
 use EE_Error;
7 6
 use EE_Has_Many_Any_Relation;
8
-use EE_Model_Relation_Base;
9 7
 use EE_Registry;
10 8
 use EEM_Base;
11 9
 use EventEspresso\core\exceptions\InvalidDataTypeException;
12 10
 use EventEspresso\core\exceptions\InvalidInterfaceException;
13
-use EventEspresso\core\services\payment_methods\forms\PayPalSettingsForm;
14 11
 use InvalidArgumentException;
15 12
 use ReflectionException;
16 13
 
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -93,8 +93,8 @@  discard block
 block discarded – undo
93 93
             // Add entity nodes for each of the model objects we fetched.
94 94
             foreach ($related_model_objs as $related_model_obj) {
95 95
                 $entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
96
-                $this->nodes[ $related_model_obj->ID() ] = $entity_node;
97
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
96
+                $this->nodes[$related_model_obj->ID()] = $entity_node;
97
+                $new_item_nodes[$related_model_obj->ID()] = $entity_node;
98 98
             }
99 99
             $num_identified += count($new_item_nodes);
100 100
             if ($num_identified < $model_objects_to_identify) {
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
     protected function allChildrenComplete()
121 121
     {
122 122
         foreach ($this->nodes as $model_obj_node) {
123
-            if (! $model_obj_node->isComplete()) {
123
+            if ( ! $model_obj_node->isComplete()) {
124 124
                 return false;
125 125
             }
126 126
         }
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
     protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
138 138
     {
139 139
         $work_done = 0;
140
-        if (! $model_obj_nodes) {
140
+        if ( ! $model_obj_nodes) {
141 141
             return 0;
142 142
         }
143 143
         foreach ($model_obj_nodes as $model_obj_node) {
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
      */
200 200
     protected function whereQueryParams()
201 201
     {
202
-        $where_params =  [
202
+        $where_params = [
203 203
             $this->related_model->get_foreign_key_to(
204 204
                 $this->main_model->get_this_model_name()
205 205
             )->get_name() => $this->id
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             $relation_settings = null;
213 213
         }
214 214
         if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
215
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
215
+            $where_params[$this->related_model->get_field_containing_related_model_name()->get_name()] = $this->main_model->get_this_model_name();
216 216
         }
217 217
         return $where_params;
218 218
     }
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
             'objs' => []
229 229
         ];
230 230
         foreach ($this->nodes as $id => $model_obj_node) {
231
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
231
+            $tree['objs'][$id] = $model_obj_node->toArray();
232 232
         }
233 233
         return $tree;
234 234
     }
Please login to merge, or discard this patch.
Indentation   +264 added lines, -264 removed lines patch added patch discarded remove patch
@@ -28,289 +28,289 @@
 block discarded – undo
28 28
 class RelationNode extends BaseNode
29 29
 {
30 30
 
31
-    /**
32
-     * @var string|int
33
-     */
34
-    protected $id;
31
+	/**
32
+	 * @var string|int
33
+	 */
34
+	protected $id;
35 35
 
36
-    /**
37
-     * @var EEM_Base
38
-     */
39
-    protected $main_model;
36
+	/**
37
+	 * @var EEM_Base
38
+	 */
39
+	protected $main_model;
40 40
 
41
-    /**
42
-     * @var int
43
-     */
44
-    protected $count;
41
+	/**
42
+	 * @var int
43
+	 */
44
+	protected $count;
45 45
 
46
-    /**
47
-     * @var EEM_Base
48
-     */
49
-    protected $related_model;
46
+	/**
47
+	 * @var EEM_Base
48
+	 */
49
+	protected $related_model;
50 50
 
51
-    /**
52
-     * @var ModelObjNode[]
53
-     */
54
-    protected $nodes;
51
+	/**
52
+	 * @var ModelObjNode[]
53
+	 */
54
+	protected $nodes;
55 55
 
56
-    /**
57
-     * RelationNode constructor.
58
-     * @param $main_model_obj_id
59
-     * @param EEM_Base $main_model
60
-     * @param EEM_Base $related_model
61
-     * @param array $dont_traverse_models array of model names we DON'T want to traverse
62
-     */
63
-    public function __construct(
64
-        $main_model_obj_id,
65
-        EEM_Base $main_model,
66
-        EEM_Base $related_model,
67
-        array $dont_traverse_models = []
68
-    ) {
69
-        $this->id = $main_model_obj_id;
70
-        $this->main_model = $main_model;
71
-        $this->related_model = $related_model;
72
-        $this->nodes = [];
73
-        $this->dont_traverse_models = $dont_traverse_models;
74
-    }
56
+	/**
57
+	 * RelationNode constructor.
58
+	 * @param $main_model_obj_id
59
+	 * @param EEM_Base $main_model
60
+	 * @param EEM_Base $related_model
61
+	 * @param array $dont_traverse_models array of model names we DON'T want to traverse
62
+	 */
63
+	public function __construct(
64
+		$main_model_obj_id,
65
+		EEM_Base $main_model,
66
+		EEM_Base $related_model,
67
+		array $dont_traverse_models = []
68
+	) {
69
+		$this->id = $main_model_obj_id;
70
+		$this->main_model = $main_model;
71
+		$this->related_model = $related_model;
72
+		$this->nodes = [];
73
+		$this->dont_traverse_models = $dont_traverse_models;
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
79
-     * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
80
-     * @since $VID:$
81
-     * @param int $model_objects_to_identify
82
-     * @return int
83
-     * @throws EE_Error
84
-     * @throws InvalidArgumentException
85
-     * @throws InvalidDataTypeException
86
-     * @throws InvalidInterfaceException
87
-     * @throws ReflectionException
88
-     */
89
-    protected function work($model_objects_to_identify)
90
-    {
91
-        $num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
92
-        if ($num_identified < $model_objects_to_identify) {
93
-            $related_model_objs = $this->related_model->get_all(
94
-                [
95
-                    $this->whereQueryParams(),
96
-                    'limit' => [
97
-                        count($this->nodes),
98
-                        $model_objects_to_identify - $num_identified
99
-                    ]
100
-                ]
101
-            );
102
-            $new_item_nodes = [];
77
+	/**
78
+	 * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
79
+	 * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
80
+	 * @since $VID:$
81
+	 * @param int $model_objects_to_identify
82
+	 * @return int
83
+	 * @throws EE_Error
84
+	 * @throws InvalidArgumentException
85
+	 * @throws InvalidDataTypeException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws ReflectionException
88
+	 */
89
+	protected function work($model_objects_to_identify)
90
+	{
91
+		$num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
92
+		if ($num_identified < $model_objects_to_identify) {
93
+			$related_model_objs = $this->related_model->get_all(
94
+				[
95
+					$this->whereQueryParams(),
96
+					'limit' => [
97
+						count($this->nodes),
98
+						$model_objects_to_identify - $num_identified
99
+					]
100
+				]
101
+			);
102
+			$new_item_nodes = [];
103 103
 
104
-            // Add entity nodes for each of the model objects we fetched.
105
-            foreach ($related_model_objs as $related_model_obj) {
106
-                $entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
107
-                $this->nodes[ $related_model_obj->ID() ] = $entity_node;
108
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
109
-            }
110
-            $num_identified += count($new_item_nodes);
111
-            if ($num_identified < $model_objects_to_identify) {
112
-                // And lastly do the work.
113
-                $num_identified += $this->visitAlreadyDiscoveredNodes(
114
-                    $new_item_nodes,
115
-                    $model_objects_to_identify - $num_identified
116
-                );
117
-            }
118
-        }
104
+			// Add entity nodes for each of the model objects we fetched.
105
+			foreach ($related_model_objs as $related_model_obj) {
106
+				$entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
107
+				$this->nodes[ $related_model_obj->ID() ] = $entity_node;
108
+				$new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
109
+			}
110
+			$num_identified += count($new_item_nodes);
111
+			if ($num_identified < $model_objects_to_identify) {
112
+				// And lastly do the work.
113
+				$num_identified += $this->visitAlreadyDiscoveredNodes(
114
+					$new_item_nodes,
115
+					$model_objects_to_identify - $num_identified
116
+				);
117
+			}
118
+		}
119 119
 
120
-        if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
121
-            $this->complete = true;
122
-        }
123
-        return $num_identified;
124
-    }
120
+		if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
121
+			$this->complete = true;
122
+		}
123
+		return $num_identified;
124
+	}
125 125
 
126
-    /**
127
-     * Checks if all the identified child nodes are complete or not.
128
-     * @since $VID:$
129
-     * @return bool
130
-     */
131
-    protected function allChildrenComplete()
132
-    {
133
-        foreach ($this->nodes as $model_obj_node) {
134
-            if (! $model_obj_node->isComplete()) {
135
-                return false;
136
-            }
137
-        }
138
-        return true;
139
-    }
126
+	/**
127
+	 * Checks if all the identified child nodes are complete or not.
128
+	 * @since $VID:$
129
+	 * @return bool
130
+	 */
131
+	protected function allChildrenComplete()
132
+	{
133
+		foreach ($this->nodes as $model_obj_node) {
134
+			if (! $model_obj_node->isComplete()) {
135
+				return false;
136
+			}
137
+		}
138
+		return true;
139
+	}
140 140
 
141
-    /**
142
-     * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
143
-     * @since $VID:$
144
-     * @param ModelObjNode[] $model_obj_nodes
145
-     * @param $work_budget
146
-     * @return int
147
-     */
148
-    protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
149
-    {
150
-        $work_done = 0;
151
-        if (! $model_obj_nodes) {
152
-            return 0;
153
-        }
154
-        foreach ($model_obj_nodes as $model_obj_node) {
155
-            if ($work_done >= $work_budget) {
156
-                break;
157
-            }
158
-            $work_done += $model_obj_node->visit($work_budget - $work_done);
159
-        }
160
-        return $work_done;
161
-    }
141
+	/**
142
+	 * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
143
+	 * @since $VID:$
144
+	 * @param ModelObjNode[] $model_obj_nodes
145
+	 * @param $work_budget
146
+	 * @return int
147
+	 */
148
+	protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
149
+	{
150
+		$work_done = 0;
151
+		if (! $model_obj_nodes) {
152
+			return 0;
153
+		}
154
+		foreach ($model_obj_nodes as $model_obj_node) {
155
+			if ($work_done >= $work_budget) {
156
+				break;
157
+			}
158
+			$work_done += $model_obj_node->visit($work_budget - $work_done);
159
+		}
160
+		return $work_done;
161
+	}
162 162
 
163
-    /**
164
-     * Whether this item has already been initialized
165
-     */
166
-    protected function isDiscovered()
167
-    {
168
-        return $this->count !== null;
169
-    }
163
+	/**
164
+	 * Whether this item has already been initialized
165
+	 */
166
+	protected function isDiscovered()
167
+	{
168
+		return $this->count !== null;
169
+	}
170 170
 
171
-    /**
172
-     * @since $VID:$
173
-     * @return boolean
174
-     */
175
-    public function isComplete()
176
-    {
177
-        if ($this->complete === null) {
178
-            if (count($this->nodes) === $this->count) {
179
-                $this->complete = true;
180
-            } else {
181
-                $this->complete = false;
182
-            }
183
-        }
184
-        return $this->complete;
185
-    }
171
+	/**
172
+	 * @since $VID:$
173
+	 * @return boolean
174
+	 */
175
+	public function isComplete()
176
+	{
177
+		if ($this->complete === null) {
178
+			if (count($this->nodes) === $this->count) {
179
+				$this->complete = true;
180
+			} else {
181
+				$this->complete = false;
182
+			}
183
+		}
184
+		return $this->complete;
185
+	}
186 186
 
187
-    /**
188
-     * Discovers how many related model objects exist.
189
-     * @since $VID:$
190
-     * @return mixed|void
191
-     * @throws EE_Error
192
-     * @throws InvalidArgumentException
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     * @throws ReflectionException
196
-     */
197
-    protected function discover()
198
-    {
199
-        $this->count = $this->related_model->count([$this->whereQueryParams()]);
200
-    }
187
+	/**
188
+	 * Discovers how many related model objects exist.
189
+	 * @since $VID:$
190
+	 * @return mixed|void
191
+	 * @throws EE_Error
192
+	 * @throws InvalidArgumentException
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 * @throws ReflectionException
196
+	 */
197
+	protected function discover()
198
+	{
199
+		$this->count = $this->related_model->count([$this->whereQueryParams()]);
200
+	}
201 201
 
202
-    /**
203
-     * @since $VID:$
204
-     * @return array
205
-     * @throws EE_Error
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     * @throws InvalidArgumentException
209
-     * @throws ReflectionException
210
-     */
211
-    protected function whereQueryParams()
212
-    {
213
-        $where_params =  [
214
-            $this->related_model->get_foreign_key_to(
215
-                $this->main_model->get_this_model_name()
216
-            )->get_name() => $this->id
217
-        ];
218
-        try {
219
-            $relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
220
-        } catch (EE_Error $e) {
221
-            // This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
222
-            // which hasn't been explicitly declared in the main model object's model's relations.
223
-            $relation_settings = null;
224
-        }
225
-        if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
226
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
227
-        }
228
-        return $where_params;
229
-    }
230
-    /**
231
-     * @since $VID:$
232
-     * @return array
233
-     */
234
-    public function toArray()
235
-    {
236
-        $tree = [
237
-            'count' => $this->count,
238
-            'complete' => $this->isComplete(),
239
-            'objs' => []
240
-        ];
241
-        foreach ($this->nodes as $id => $model_obj_node) {
242
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
243
-        }
244
-        return $tree;
245
-    }
202
+	/**
203
+	 * @since $VID:$
204
+	 * @return array
205
+	 * @throws EE_Error
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 * @throws InvalidArgumentException
209
+	 * @throws ReflectionException
210
+	 */
211
+	protected function whereQueryParams()
212
+	{
213
+		$where_params =  [
214
+			$this->related_model->get_foreign_key_to(
215
+				$this->main_model->get_this_model_name()
216
+			)->get_name() => $this->id
217
+		];
218
+		try {
219
+			$relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
220
+		} catch (EE_Error $e) {
221
+			// This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
222
+			// which hasn't been explicitly declared in the main model object's model's relations.
223
+			$relation_settings = null;
224
+		}
225
+		if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
226
+			$where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
227
+		}
228
+		return $where_params;
229
+	}
230
+	/**
231
+	 * @since $VID:$
232
+	 * @return array
233
+	 */
234
+	public function toArray()
235
+	{
236
+		$tree = [
237
+			'count' => $this->count,
238
+			'complete' => $this->isComplete(),
239
+			'objs' => []
240
+		];
241
+		foreach ($this->nodes as $id => $model_obj_node) {
242
+			$tree['objs'][ $id ] = $model_obj_node->toArray();
243
+		}
244
+		return $tree;
245
+	}
246 246
 
247
-    /**
248
-     * Gets the IDs of all the model objects to delete; indexed first by model object name.
249
-     * @since $VID:$
250
-     * @return array
251
-     */
252
-    public function getIds()
253
-    {
254
-        if (empty($this->nodes)) {
255
-            return [];
256
-        }
257
-        $ids = [
258
-            $this->related_model->get_this_model_name() => array_combine(
259
-                array_keys($this->nodes),
260
-                array_keys($this->nodes)
261
-            )
262
-        ];
263
-        foreach ($this->nodes as $model_obj_node) {
264
-            $ids = array_replace_recursive($ids, $model_obj_node->getIds());
265
-        }
266
-        return $ids;
267
-    }
247
+	/**
248
+	 * Gets the IDs of all the model objects to delete; indexed first by model object name.
249
+	 * @since $VID:$
250
+	 * @return array
251
+	 */
252
+	public function getIds()
253
+	{
254
+		if (empty($this->nodes)) {
255
+			return [];
256
+		}
257
+		$ids = [
258
+			$this->related_model->get_this_model_name() => array_combine(
259
+				array_keys($this->nodes),
260
+				array_keys($this->nodes)
261
+			)
262
+		];
263
+		foreach ($this->nodes as $model_obj_node) {
264
+			$ids = array_replace_recursive($ids, $model_obj_node->getIds());
265
+		}
266
+		return $ids;
267
+	}
268 268
 
269
-    /**
270
-     * Returns the number of sub-nodes found (ie, related model objects across this relation.)
271
-     * @since $VID:$
272
-     * @return int
273
-     */
274
-    public function countSubNodes()
275
-    {
276
-        return count($this->nodes);
277
-    }
269
+	/**
270
+	 * Returns the number of sub-nodes found (ie, related model objects across this relation.)
271
+	 * @since $VID:$
272
+	 * @return int
273
+	 */
274
+	public function countSubNodes()
275
+	{
276
+		return count($this->nodes);
277
+	}
278 278
 
279
-    /**
280
-     * Don't serialize the models. Just record their names on some dynamic properties.
281
-     * @since $VID:$
282
-     */
283
-    public function __sleep()
284
-    {
285
-        $this->m = $this->main_model->get_this_model_name();
286
-        $this->rm = $this->related_model->get_this_model_name();
287
-        return array_merge(
288
-            [
289
-                'm',
290
-                'rm',
291
-                'id',
292
-                'count',
293
-                'nodes',
294
-            ],
295
-            parent::__sleep()
296
-        );
297
-    }
279
+	/**
280
+	 * Don't serialize the models. Just record their names on some dynamic properties.
281
+	 * @since $VID:$
282
+	 */
283
+	public function __sleep()
284
+	{
285
+		$this->m = $this->main_model->get_this_model_name();
286
+		$this->rm = $this->related_model->get_this_model_name();
287
+		return array_merge(
288
+			[
289
+				'm',
290
+				'rm',
291
+				'id',
292
+				'count',
293
+				'nodes',
294
+			],
295
+			parent::__sleep()
296
+		);
297
+	}
298 298
 
299
-    /**
300
-     * Use the dynamic properties to instantiate the models we use.
301
-     * @since $VID:$
302
-     * @throws EE_Error
303
-     * @throws InvalidArgumentException
304
-     * @throws InvalidDataTypeException
305
-     * @throws InvalidInterfaceException
306
-     * @throws ReflectionException
307
-     */
308
-    public function __wakeup()
309
-    {
310
-        $this->main_model = EE_Registry::instance()->load_model($this->m);
311
-        $this->related_model = EE_Registry::instance()->load_model($this->rm);
312
-        parent::__wakeup();
313
-    }
299
+	/**
300
+	 * Use the dynamic properties to instantiate the models we use.
301
+	 * @since $VID:$
302
+	 * @throws EE_Error
303
+	 * @throws InvalidArgumentException
304
+	 * @throws InvalidDataTypeException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws ReflectionException
307
+	 */
308
+	public function __wakeup()
309
+	{
310
+		$this->main_model = EE_Registry::instance()->load_model($this->m);
311
+		$this->related_model = EE_Registry::instance()->load_model($this->rm);
312
+		parent::__wakeup();
313
+	}
314 314
 }
315 315
 // End of file RelationNode.php
316 316
 // Location: EventEspresso\core\services\orm\tree_traversal/RelationNode.php
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 1 patch
Indentation   +1524 added lines, -1524 removed lines patch added patch discarded remove patch
@@ -14,1528 +14,1528 @@
 block discarded – undo
14 14
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
15 15
 {
16 16
 
17
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
-
19
-    /**
20
-     * Subsections
21
-     *
22
-     * @var EE_Form_Section_Validatable[]
23
-     */
24
-    protected $_subsections = array();
25
-
26
-    /**
27
-     * Strategy for laying out the form
28
-     *
29
-     * @var EE_Form_Section_Layout_Base
30
-     */
31
-    protected $_layout_strategy;
32
-
33
-    /**
34
-     * Whether or not this form has received and validated a form submission yet
35
-     *
36
-     * @var boolean
37
-     */
38
-    protected $_received_submission = false;
39
-
40
-    /**
41
-     * message displayed to users upon successful form submission
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_form_submission_success_message = '';
46
-
47
-    /**
48
-     * message displayed to users upon unsuccessful form submission
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_form_submission_error_message = '';
53
-
54
-    /**
55
-     * @var array like $_REQUEST
56
-     */
57
-    protected $cached_request_data;
58
-
59
-    /**
60
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
61
-     * Starts off as null, but once the form is validated, it set to either true or false
62
-     * @var boolean|null
63
-     */
64
-    protected $is_valid;
65
-
66
-    /**
67
-     * Stores all the data that will localized for form validation
68
-     *
69
-     * @var array
70
-     */
71
-    static protected $_js_localization = array();
72
-
73
-    /**
74
-     * whether or not the form's localized validation JS vars have been set
75
-     *
76
-     * @type boolean
77
-     */
78
-    static protected $_scripts_localized = false;
79
-
80
-
81
-    /**
82
-     * when constructing a proper form section, calls _construct_finalize on children
83
-     * so that they know who their parent is, and what name they've been given.
84
-     *
85
-     * @param array[] $options_array   {
86
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
88
-     *                                 and in that order. This is handy if you want
89
-     *                                 the subsections to be ordered differently than the default, and if you override
90
-     *                                 which fields are shown
91
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
-     *                                 items from that list of inclusions)
95
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
-     *                                 } @see EE_Form_Section_Validatable::__construct()
97
-     * @throws EE_Error
98
-     */
99
-    public function __construct($options_array = array())
100
-    {
101
-        $options_array = (array) apply_filters(
102
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
103
-            $options_array,
104
-            $this
105
-        );
106
-        // call parent first, as it may be setting the name
107
-        parent::__construct($options_array);
108
-        // if they've included subsections in the constructor, add them now
109
-        if (isset($options_array['include'])) {
110
-            // we are going to make sure we ONLY have those subsections to include
111
-            // AND we are going to make sure they're in that specified order
112
-            $reordered_subsections = array();
113
-            foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
-                }
117
-            }
118
-            $this->_subsections = $reordered_subsections;
119
-        }
120
-        if (isset($options_array['exclude'])) {
121
-            $exclude            = $options_array['exclude'];
122
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
-        }
124
-        if (isset($options_array['layout_strategy'])) {
125
-            $this->_layout_strategy = $options_array['layout_strategy'];
126
-        }
127
-        if (! $this->_layout_strategy) {
128
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
-        }
130
-        $this->_layout_strategy->_construct_finalize($this);
131
-        // ok so we are definitely going to want the forms JS,
132
-        // so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
-            // ok so they've constructed this object after when they should have.
135
-            // just enqueue the generic form scripts and initialize the form immediately in the JS
136
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
-        } else {
138
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-        }
141
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
-        /**
143
-         * Gives other plugins a chance to hook in before construct finalize is called.
144
-         * The form probably doesn't yet have a parent form section.
145
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
-         *
149
-         * @since 4.9.32
150
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
-         *                                              except maybe calling _construct_finalize has been done
152
-         * @param array                  $options_array options passed into the constructor
153
-         */
154
-        do_action(
155
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
-            $this,
157
-            $options_array
158
-        );
159
-        if (isset($options_array['name'])) {
160
-            $this->_construct_finalize(null, $options_array['name']);
161
-        }
162
-    }
163
-
164
-
165
-    /**
166
-     * Finishes construction given the parent form section and this form section's name
167
-     *
168
-     * @param EE_Form_Section_Proper $parent_form_section
169
-     * @param string                 $name
170
-     * @throws EE_Error
171
-     */
172
-    public function _construct_finalize($parent_form_section, $name)
173
-    {
174
-        parent::_construct_finalize($parent_form_section, $name);
175
-        $this->_set_default_name_if_empty();
176
-        $this->_set_default_html_id_if_empty();
177
-        foreach ($this->_subsections as $subsection_name => $subsection) {
178
-            if ($subsection instanceof EE_Form_Section_Base) {
179
-                $subsection->_construct_finalize($this, $subsection_name);
180
-            } else {
181
-                throw new EE_Error(
182
-                    sprintf(
183
-                        esc_html__(
184
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
-                            'event_espresso'
186
-                        ),
187
-                        $subsection_name,
188
-                        get_class($this),
189
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
-                    )
191
-                );
192
-            }
193
-        }
194
-        /**
195
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
-         * This might only happen just before displaying the form, or just before it receives form submission data.
199
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
-         * ensured it has a name, HTML IDs, etc
201
-         *
202
-         * @param EE_Form_Section_Proper      $this
203
-         * @param EE_Form_Section_Proper|null $parent_form_section
204
-         * @param string                      $name
205
-         */
206
-        do_action(
207
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
-            $this,
209
-            $parent_form_section,
210
-            $name
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     * Gets the layout strategy for this form section
217
-     *
218
-     * @return EE_Form_Section_Layout_Base
219
-     */
220
-    public function get_layout_strategy()
221
-    {
222
-        return $this->_layout_strategy;
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets the HTML for a single input for this form section according
228
-     * to the layout strategy
229
-     *
230
-     * @param EE_Form_Input_Base $input
231
-     * @return string
232
-     */
233
-    public function get_html_for_input($input)
234
-    {
235
-        return $this->_layout_strategy->layout_input($input);
236
-    }
237
-
238
-
239
-    /**
240
-     * was_submitted - checks if form inputs are present in request data
241
-     * Basically an alias for form_data_present_in() (which is used by both
242
-     * proper form sections and form inputs)
243
-     *
244
-     * @param null $form_data
245
-     * @return boolean
246
-     * @throws EE_Error
247
-     */
248
-    public function was_submitted($form_data = null)
249
-    {
250
-        return $this->form_data_present_in($form_data);
251
-    }
252
-
253
-    /**
254
-     * Gets the cached request data; but if there is none, or $req_data was set with
255
-     * something different, refresh the cache, and then return it
256
-     * @param null $req_data
257
-     * @return array
258
-     */
259
-    protected function getCachedRequest($req_data = null)
260
-    {
261
-        if ($this->cached_request_data === null
262
-            || (
263
-                $req_data !== null &&
264
-                $req_data !== $this->cached_request_data
265
-            )
266
-        ) {
267
-            $req_data = apply_filters(
268
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
-                $req_data,
270
-                $this
271
-            );
272
-            if ($req_data === null) {
273
-                $req_data = array_merge($_GET, $_POST);
274
-            }
275
-            $req_data = apply_filters(
276
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
-                $req_data,
278
-                $this
279
-            );
280
-            $this->cached_request_data = (array) $req_data;
281
-        }
282
-        return $this->cached_request_data;
283
-    }
284
-
285
-
286
-    /**
287
-     * After the form section is initially created, call this to sanitize the data in the submission
288
-     * which relates to this form section, validate it, and set it as properties on the form.
289
-     *
290
-     * @param array|null $req_data should usually be $_POST (the default).
291
-     *                             However, you CAN supply a different array.
292
-     *                             Consider using set_defaults() instead however.
293
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
294
-     *                             the inputs will have the correct name in the request data for this function
295
-     *                             to find them and populate the form with them.
296
-     *                             If you have a flat form (with only input subsections),
297
-     *                             you can supply a flat array where keys
298
-     *                             are the form input names and values are their values)
299
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
-     *                             of course, to validate that data, and set errors on the invalid values.
301
-     *                             But if the data has already been validated
302
-     *                             (eg you validated the data then stored it in the DB)
303
-     *                             you may want to skip this step.
304
-     * @throws InvalidArgumentException
305
-     * @throws InvalidInterfaceException
306
-     * @throws InvalidDataTypeException
307
-     * @throws EE_Error
308
-     */
309
-    public function receive_form_submission($req_data = null, $validate = true)
310
-    {
311
-        $req_data = $this->getCachedRequest($req_data);
312
-        $this->_normalize($req_data);
313
-        if ($validate) {
314
-            $this->_validate();
315
-            // if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
317
-                $this->store_submitted_form_data_in_session();
318
-            }
319
-        }
320
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
-            $this->set_submission_error_message();
322
-        }
323
-        do_action(
324
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
-            $req_data,
326
-            $this,
327
-            $validate
328
-        );
329
-    }
330
-
331
-
332
-    /**
333
-     * caches the originally submitted input values in the session
334
-     * so that they can be used to repopulate the form if it failed validation
335
-     *
336
-     * @return boolean whether or not the data was successfully stored in the session
337
-     * @throws InvalidArgumentException
338
-     * @throws InvalidInterfaceException
339
-     * @throws InvalidDataTypeException
340
-     * @throws EE_Error
341
-     */
342
-    protected function store_submitted_form_data_in_session()
343
-    {
344
-        return EE_Registry::instance()->SSN->set_session_data(
345
-            array(
346
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
-            )
348
-        );
349
-    }
350
-
351
-
352
-    /**
353
-     * retrieves the originally submitted input values in the session
354
-     * so that they can be used to repopulate the form if it failed validation
355
-     *
356
-     * @return array
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidInterfaceException
359
-     * @throws InvalidDataTypeException
360
-     */
361
-    protected function get_submitted_form_data_from_session()
362
-    {
363
-        $session = EE_Registry::instance()->SSN;
364
-        if ($session instanceof EE_Session) {
365
-            return $session->get_session_data(
366
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
-            );
368
-        }
369
-        return array();
370
-    }
371
-
372
-
373
-    /**
374
-     * flushed the originally submitted input values from the session
375
-     *
376
-     * @return boolean whether or not the data was successfully removed from the session
377
-     * @throws InvalidArgumentException
378
-     * @throws InvalidInterfaceException
379
-     * @throws InvalidDataTypeException
380
-     */
381
-    public static function flush_submitted_form_data_from_session()
382
-    {
383
-        return EE_Registry::instance()->SSN->reset_data(
384
-            array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Populates this form and its subsections with data from the session.
391
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
-     * validation errors when displaying too)
393
-     * Returns true if the form was populated from the session, false otherwise
394
-     *
395
-     * @return boolean
396
-     * @throws InvalidArgumentException
397
-     * @throws InvalidInterfaceException
398
-     * @throws InvalidDataTypeException
399
-     * @throws EE_Error
400
-     */
401
-    public function populate_from_session()
402
-    {
403
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
404
-        if (empty($form_data_in_session)) {
405
-            return false;
406
-        }
407
-        $this->receive_form_submission($form_data_in_session);
408
-        add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
409
-        if ($this->form_data_present_in($form_data_in_session)) {
410
-            return true;
411
-        }
412
-        return false;
413
-    }
414
-
415
-
416
-    /**
417
-     * Populates the default data for the form, given an array where keys are
418
-     * the input names, and values are their values (preferably normalized to be their
419
-     * proper PHP types, not all strings... although that should be ok too).
420
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
421
-     * the value being an array formatted in teh same way
422
-     *
423
-     * @param array $default_data
424
-     * @throws EE_Error
425
-     */
426
-    public function populate_defaults($default_data)
427
-    {
428
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
430
-                if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
432
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
434
-                }
435
-            }
436
-        }
437
-    }
438
-
439
-
440
-    /**
441
-     * returns true if subsection exists
442
-     *
443
-     * @param string $name
444
-     * @return boolean
445
-     */
446
-    public function subsection_exists($name)
447
-    {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the subsection specified by its name
454
-     *
455
-     * @param string  $name
456
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
-     *                                                      so that the inputs will be properly configured.
458
-     *                                                      However, some client code may be ok
459
-     *                                                      with construction finalize being called later
460
-     *                                                      (realizing that the subsections' html names
461
-     *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
463
-     * @throws EE_Error
464
-     */
465
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
466
-    {
467
-        if ($require_construction_to_be_finalized) {
468
-            $this->ensure_construct_finalized_called();
469
-        }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets all the validatable subsections of this form section
476
-     *
477
-     * @return EE_Form_Section_Validatable[]
478
-     * @throws EE_Error
479
-     */
480
-    public function get_validatable_subsections()
481
-    {
482
-        $validatable_subsections = array();
483
-        foreach ($this->subsections() as $name => $obj) {
484
-            if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
486
-            }
487
-        }
488
-        return $validatable_subsections;
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
-     * throw an EE_Error.
495
-     *
496
-     * @param string  $name
497
-     * @param boolean $require_construction_to_be_finalized most client code should
498
-     *                                                      leave this as TRUE so that the inputs will be properly
499
-     *                                                      configured. However, some client code may be ok with
500
-     *                                                      construction finalize being called later
501
-     *                                                      (realizing that the subsections' html names might not be
502
-     *                                                      set yet, etc.)
503
-     * @return EE_Form_Input_Base
504
-     * @throws EE_Error
505
-     */
506
-    public function get_input($name, $require_construction_to_be_finalized = true)
507
-    {
508
-        $subsection = $this->get_subsection(
509
-            $name,
510
-            $require_construction_to_be_finalized
511
-        );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
513
-            throw new EE_Error(
514
-                sprintf(
515
-                    esc_html__(
516
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
-                        'event_espresso'
518
-                    ),
519
-                    $name,
520
-                    get_class($this),
521
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
-                )
523
-            );
524
-        }
525
-        return $subsection;
526
-    }
527
-
528
-
529
-    /**
530
-     * Like get_input(), gets the proper subsection of the form given the name,
531
-     * otherwise throws an EE_Error
532
-     *
533
-     * @param string  $name
534
-     * @param boolean $require_construction_to_be_finalized most client code should
535
-     *                                                      leave this as TRUE so that the inputs will be properly
536
-     *                                                      configured. However, some client code may be ok with
537
-     *                                                      construction finalize being called later
538
-     *                                                      (realizing that the subsections' html names might not be
539
-     *                                                      set yet, etc.)
540
-     * @return EE_Form_Section_Proper
541
-     * @throws EE_Error
542
-     */
543
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
-    {
545
-        $subsection = $this->get_subsection(
546
-            $name,
547
-            $require_construction_to_be_finalized
548
-        );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
550
-            throw new EE_Error(
551
-                sprintf(
552
-                    esc_html__(
553
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
-                        'event_espresso'
555
-                    ),
556
-                    $name,
557
-                    get_class($this)
558
-                )
559
-            );
560
-        }
561
-        return $subsection;
562
-    }
563
-
564
-
565
-    /**
566
-     * Gets the value of the specified input. Should be called after receive_form_submission()
567
-     * or populate_defaults() on the form, where the normalized value on the input is set.
568
-     *
569
-     * @param string $name
570
-     * @return mixed depending on the input's type and its normalization strategy
571
-     * @throws EE_Error
572
-     */
573
-    public function get_input_value($name)
574
-    {
575
-        $input = $this->get_input($name);
576
-        return $input->normalized_value();
577
-    }
578
-
579
-
580
-    /**
581
-     * Checks if this form section itself is valid, and then checks its subsections
582
-     *
583
-     * @throws EE_Error
584
-     * @return boolean
585
-     */
586
-    public function is_valid()
587
-    {
588
-        if ($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
590
-                throw new EE_Error(
591
-                    sprintf(
592
-                        esc_html__(
593
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
-                            'event_espresso'
595
-                        )
596
-                    )
597
-                );
598
-            }
599
-            if (! parent::is_valid()) {
600
-                $this->is_valid = false;
601
-            } else {
602
-                // ok so no general errors to this entire form section.
603
-                // so let's check the subsections, but only set errors if that hasn't been done yet
604
-                $this->is_valid = true;
605
-                foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
607
-                        $this->is_valid = false;
608
-                    }
609
-                }
610
-            }
611
-        }
612
-        return $this->is_valid;
613
-    }
614
-
615
-
616
-    /**
617
-     * gets the default name of this form section if none is specified
618
-     *
619
-     * @return void
620
-     */
621
-    protected function _set_default_name_if_empty()
622
-    {
623
-        if (! $this->_name) {
624
-            $classname    = get_class($this);
625
-            $default_name = str_replace('EE_', '', $classname);
626
-            $this->_name  = $default_name;
627
-        }
628
-    }
629
-
630
-
631
-    /**
632
-     * Returns the HTML for the form, except for the form opening and closing tags
633
-     * (as the form section doesn't know where you necessarily want to send the information to),
634
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
-     * Not doing_it_wrong because theoretically this CAN be used properly,
637
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
-     * any CSS.
639
-     *
640
-     * @throws InvalidArgumentException
641
-     * @throws InvalidInterfaceException
642
-     * @throws InvalidDataTypeException
643
-     * @throws EE_Error
644
-     */
645
-    public function get_html_and_js()
646
-    {
647
-        $this->enqueue_js();
648
-        return $this->get_html();
649
-    }
650
-
651
-
652
-    /**
653
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
-     *
655
-     * @param bool $display_previously_submitted_data
656
-     * @return string
657
-     * @throws InvalidArgumentException
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws EE_Error
662
-     * @throws EE_Error
663
-     */
664
-    public function get_html($display_previously_submitted_data = true)
665
-    {
666
-        $this->ensure_construct_finalized_called();
667
-        if ($display_previously_submitted_data) {
668
-            $this->populate_from_session();
669
-        }
670
-        return $this->_form_html_filter
671
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
-            : $this->_layout_strategy->layout_form();
673
-    }
674
-
675
-
676
-    /**
677
-     * enqueues JS and CSS for the form.
678
-     * It is preferred to call this before wp_enqueue_scripts so the
679
-     * scripts and styles can be put in the header, but if called later
680
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
-     * only be in the header; but in HTML5 its ok in the body.
682
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
-     *
685
-     * @return void
686
-     * @throws EE_Error
687
-     */
688
-    public function enqueue_js()
689
-    {
690
-        $this->_enqueue_and_localize_form_js();
691
-        foreach ($this->subsections() as $subsection) {
692
-            $subsection->enqueue_js();
693
-        }
694
-    }
695
-
696
-
697
-    /**
698
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
-     * the wp_enqueue_scripts hook.
701
-     * However, registering the form js and localizing it can happen when we
702
-     * actually output the form (which is preferred, seeing how teh form's fields
703
-     * could change until it's actually outputted)
704
-     *
705
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
-     *                                                    to be triggered automatically or not
707
-     * @return void
708
-     */
709
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
-    {
711
-        wp_register_script(
712
-            'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
714
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
-            EVENT_ESPRESSO_VERSION,
716
-            true
717
-        );
718
-        wp_localize_script(
719
-            'ee_form_section_validation',
720
-            'ee_form_section_validation_init',
721
-            array('init' => $init_form_validation_automatically ? '1' : '0')
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * gets the variables used by form_section_validation.js.
728
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
-     * but before the wordpress hook wp_loaded
730
-     *
731
-     * @throws EE_Error
732
-     */
733
-    public function _enqueue_and_localize_form_js()
734
-    {
735
-        $this->ensure_construct_finalized_called();
736
-        // actually, we don't want to localize just yet. There may be other forms on the page.
737
-        // so we need to add our form section data to a static variable accessible by all form sections
738
-        // and localize it just before the footer
739
-        $this->localize_validation_rules();
740
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
-    }
743
-
744
-
745
-    /**
746
-     * add our form section data to a static variable accessible by all form sections
747
-     *
748
-     * @param bool $return_for_subsection
749
-     * @return void
750
-     * @throws EE_Error
751
-     */
752
-    public function localize_validation_rules($return_for_subsection = false)
753
-    {
754
-        // we only want to localize vars ONCE for the entire form,
755
-        // so if the form section doesn't have a parent, then it must be the top dog
756
-        if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
-                'form_section_id'  => $this->html_id(true),
759
-                'validation_rules' => $this->get_jquery_validation_rules(),
760
-                'other_data'       => $this->get_other_js_data(),
761
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
762
-            );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
764
-        }
765
-    }
766
-
767
-
768
-    /**
769
-     * Gets an array of extra data that will be useful for client-side javascript.
770
-     * This is primarily data added by inputs and forms in addition to any
771
-     * scripts they might enqueue
772
-     *
773
-     * @param array $form_other_js_data
774
-     * @return array
775
-     * @throws EE_Error
776
-     */
777
-    public function get_other_js_data($form_other_js_data = array())
778
-    {
779
-        foreach ($this->subsections() as $subsection) {
780
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
-        }
782
-        return $form_other_js_data;
783
-    }
784
-
785
-
786
-    /**
787
-     * Gets a flat array of inputs for this form section and its subsections.
788
-     * Keys are their form names, and values are the inputs themselves
789
-     *
790
-     * @return EE_Form_Input_Base
791
-     * @throws EE_Error
792
-     */
793
-    public function inputs_in_subsections()
794
-    {
795
-        $inputs = array();
796
-        foreach ($this->subsections() as $subsection) {
797
-            if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
799
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
800
-                $inputs += $subsection->inputs_in_subsections();
801
-            }
802
-        }
803
-        return $inputs;
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets a flat array of all the validation errors.
809
-     * Keys are html names (because those should be unique)
810
-     * and values are a string of all their validation errors
811
-     *
812
-     * @return string[]
813
-     * @throws EE_Error
814
-     */
815
-    public function subsection_validation_errors_by_html_name()
816
-    {
817
-        $inputs = $this->inputs();
818
-        $errors = array();
819
-        foreach ($inputs as $form_input) {
820
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
-            }
823
-        }
824
-        return $errors;
825
-    }
826
-
827
-
828
-    /**
829
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
-     * Should be setup by each form during the _enqueues_and_localize_form_js
831
-     *
832
-     * @throws InvalidArgumentException
833
-     * @throws InvalidInterfaceException
834
-     * @throws InvalidDataTypeException
835
-     */
836
-    public static function localize_script_for_all_forms()
837
-    {
838
-        // allow inputs and stuff to hook in their JS and stuff here
839
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
843
-            : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
-        wp_enqueue_script('ee_form_section_validation');
846
-        wp_localize_script(
847
-            'ee_form_section_validation',
848
-            'ee_form_section_vars',
849
-            EE_Form_Section_Proper::$_js_localization
850
-        );
851
-    }
852
-
853
-
854
-    /**
855
-     * ensure_scripts_localized
856
-     *
857
-     * @throws EE_Error
858
-     */
859
-    public function ensure_scripts_localized()
860
-    {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
862
-            $this->_enqueue_and_localize_form_js();
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
869
-     * is that the key here should be the same as the custom validation rule put in the JS file
870
-     *
871
-     * @return array keys are custom validation rules, and values are internationalized strings
872
-     */
873
-    private static function _get_localized_error_messages()
874
-    {
875
-        return array(
876
-            'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
-            'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
-        );
879
-    }
880
-
881
-
882
-    /**
883
-     * @return array
884
-     */
885
-    public static function js_localization()
886
-    {
887
-        return self::$_js_localization;
888
-    }
889
-
890
-
891
-    /**
892
-     * @return void
893
-     */
894
-    public static function reset_js_localization()
895
-    {
896
-        self::$_js_localization = array();
897
-    }
898
-
899
-
900
-    /**
901
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
-     * See parent function for more...
903
-     *
904
-     * @return array
905
-     * @throws EE_Error
906
-     */
907
-    public function get_jquery_validation_rules()
908
-    {
909
-        $jquery_validation_rules = array();
910
-        foreach ($this->get_validatable_subsections() as $subsection) {
911
-            $jquery_validation_rules = array_merge(
912
-                $jquery_validation_rules,
913
-                $subsection->get_jquery_validation_rules()
914
-            );
915
-        }
916
-        return $jquery_validation_rules;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sanitizes all the data and sets the sanitized value of each field
922
-     *
923
-     * @param array $req_data like $_POST
924
-     * @return void
925
-     * @throws EE_Error
926
-     */
927
-    protected function _normalize($req_data)
928
-    {
929
-        $this->_received_submission = true;
930
-        $this->_validation_errors   = array();
931
-        foreach ($this->get_validatable_subsections() as $subsection) {
932
-            try {
933
-                $subsection->_normalize($req_data);
934
-            } catch (EE_Validation_Error $e) {
935
-                $subsection->add_validation_error($e);
936
-            }
937
-        }
938
-    }
939
-
940
-
941
-    /**
942
-     * Performs validation on this form section and its subsections.
943
-     * For each subsection,
944
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
945
-     * and passes it the subsection, then calls _validate on that subsection.
946
-     * If you need to perform validation on the form as a whole (considering multiple)
947
-     * you would be best to override this _validate method,
948
-     * calling parent::_validate() first.
949
-     *
950
-     * @throws EE_Error
951
-     */
952
-    protected function _validate()
953
-    {
954
-        // reset the cache of whether this form is valid or not- we're re-validating it now
955
-        $this->is_valid = null;
956
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
-            }
960
-            $subsection->_validate();
961
-        }
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets all the validated inputs for the form section
967
-     *
968
-     * @return array
969
-     * @throws EE_Error
970
-     */
971
-    public function valid_data()
972
-    {
973
-        $inputs = array();
974
-        foreach ($this->subsections() as $subsection_name => $subsection) {
975
-            if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
977
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
979
-            }
980
-        }
981
-        return $inputs;
982
-    }
983
-
984
-
985
-    /**
986
-     * Gets all the inputs on this form section
987
-     *
988
-     * @return EE_Form_Input_Base[]
989
-     * @throws EE_Error
990
-     */
991
-    public function inputs()
992
-    {
993
-        $inputs = array();
994
-        foreach ($this->subsections() as $subsection_name => $subsection) {
995
-            if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
997
-            }
998
-        }
999
-        return $inputs;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * Gets all the subsections which are a proper form
1005
-     *
1006
-     * @return EE_Form_Section_Proper[]
1007
-     * @throws EE_Error
1008
-     */
1009
-    public function subforms()
1010
-    {
1011
-        $form_sections = array();
1012
-        foreach ($this->subsections() as $name => $obj) {
1013
-            if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1015
-            }
1016
-        }
1017
-        return $form_sections;
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
-     * Consider using inputs() or subforms()
1024
-     * if you only want form inputs or proper form sections.
1025
-     *
1026
-     * @param boolean $require_construction_to_be_finalized most client code should
1027
-     *                                                      leave this as TRUE so that the inputs will be properly
1028
-     *                                                      configured. However, some client code may be ok with
1029
-     *                                                      construction finalize being called later
1030
-     *                                                      (realizing that the subsections' html names might not be
1031
-     *                                                      set yet, etc.)
1032
-     * @return EE_Form_Section_Proper[]
1033
-     * @throws EE_Error
1034
-     */
1035
-    public function subsections($require_construction_to_be_finalized = true)
1036
-    {
1037
-        if ($require_construction_to_be_finalized) {
1038
-            $this->ensure_construct_finalized_called();
1039
-        }
1040
-        return $this->_subsections;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * Returns whether this form has any subforms or inputs
1046
-     * @return bool
1047
-     */
1048
-    public function hasSubsections()
1049
-    {
1050
-        return ! empty($this->_subsections);
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Returns a simple array where keys are input names, and values are their normalized
1056
-     * values. (Similar to calling get_input_value on inputs)
1057
-     *
1058
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
-     *                                        or just this forms' direct children inputs
1060
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
-     *                                        or allow multidimensional array
1062
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
-     *                                        with array keys being input names
1064
-     *                                        (regardless of whether they are from a subsection or not),
1065
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1066
-     *                                        where keys are always subsection names and values are either
1067
-     *                                        the input's normalized value, or an array like the top-level array
1068
-     * @throws EE_Error
1069
-     */
1070
-    public function input_values($include_subform_inputs = false, $flatten = false)
1071
-    {
1072
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
-     * is not necessarily the value we want to display to users. This creates an array
1080
-     * where keys are the input names, and values are their display values
1081
-     *
1082
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
-     *                                        or just this forms' direct children inputs
1084
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
-     *                                        or allow multidimensional array
1086
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
-     *                                        with array keys being input names
1088
-     *                                        (regardless of whether they are from a subsection or not),
1089
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1090
-     *                                        where keys are always subsection names and values are either
1091
-     *                                        the input's normalized value, or an array like the top-level array
1092
-     * @throws EE_Error
1093
-     */
1094
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
-    {
1096
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * Gets the input values from the form
1102
-     *
1103
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
-     *                                        or just the normalized value
1105
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
-     *                                        or just this forms' direct children inputs
1107
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
-     *                                        or allow multidimensional array
1109
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
-     *                                        input names (regardless of whether they are from a subsection or not),
1111
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1112
-     *                                        where keys are always subsection names and values are either
1113
-     *                                        the input's normalized value, or an array like the top-level array
1114
-     * @throws EE_Error
1115
-     */
1116
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
-    {
1118
-        $input_values = array();
1119
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1120
-            if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1122
-                    ? $subsection->pretty_value()
1123
-                    : $subsection->normalized_value();
1124
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
-                $subform_input_values = $subsection->_input_values(
1126
-                    $pretty,
1127
-                    $include_subform_inputs,
1128
-                    $flatten
1129
-                );
1130
-                if ($flatten) {
1131
-                    $input_values = array_merge($input_values, $subform_input_values);
1132
-                } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1134
-                }
1135
-            }
1136
-        }
1137
-        return $input_values;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Gets the originally submitted input values from the form
1143
-     *
1144
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
-     *                                   or just this forms' direct children inputs
1146
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
-     *                                   with array keys being input names
1148
-     *                                   (regardless of whether they are from a subsection or not),
1149
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1150
-     *                                   where keys are always subsection names and values are either
1151
-     *                                   the input's normalized value, or an array like the top-level array
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function submitted_values($include_subforms = false)
1155
-    {
1156
-        $submitted_values = array();
1157
-        foreach ($this->subsections() as $subsection) {
1158
-            if ($subsection instanceof EE_Form_Input_Base) {
1159
-                // is this input part of an array of inputs?
1160
-                if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
-                        explode(
1163
-                            '[',
1164
-                            str_replace(']', '', $subsection->html_name())
1165
-                        ),
1166
-                        $subsection->raw_value()
1167
-                    );
1168
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
-                } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
-                }
1172
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1174
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
-            }
1176
-        }
1177
-        return $submitted_values;
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * Indicates whether or not this form has received a submission yet
1183
-     * (ie, had receive_form_submission called on it yet)
1184
-     *
1185
-     * @return boolean
1186
-     * @throws EE_Error
1187
-     */
1188
-    public function has_received_submission()
1189
-    {
1190
-        $this->ensure_construct_finalized_called();
1191
-        return $this->_received_submission;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Equivalent to passing 'exclude' in the constructor's options array.
1197
-     * Removes the listed inputs from the form
1198
-     *
1199
-     * @param array $inputs_to_exclude values are the input names
1200
-     * @return void
1201
-     */
1202
-    public function exclude(array $inputs_to_exclude = array())
1203
-    {
1204
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
-     * @param array $inputs_to_hide
1213
-     * @throws EE_Error
1214
-     */
1215
-    public function hide(array $inputs_to_hide = array())
1216
-    {
1217
-        foreach ($inputs_to_hide as $input_to_hide) {
1218
-            $input = $this->get_input($input_to_hide);
1219
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
-        }
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * add_subsections
1226
-     * Adds the listed subsections to the form section.
1227
-     * If $subsection_name_to_target is provided,
1228
-     * then new subsections are added before or after that subsection,
1229
-     * otherwise to the start or end of the entire subsections array.
1230
-     *
1231
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
-     *                                                          where keys are their names
1233
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
-     *                                                          should be added before or after
1235
-     *                                                          IF $subsection_name_to_target is null,
1236
-     *                                                          then $new_subsections will be added to
1237
-     *                                                          the beginning or end of the entire subsections array
1238
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
-     *                                                          $subsection_name_to_target,
1240
-     *                                                          or if $subsection_name_to_target is null,
1241
-     *                                                          before or after entire subsections array
1242
-     * @return void
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
-    {
1247
-        foreach ($new_subsections as $subsection_name => $subsection) {
1248
-            if (! $subsection instanceof EE_Form_Section_Base) {
1249
-                EE_Error::add_error(
1250
-                    sprintf(
1251
-                        esc_html__(
1252
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
-                            'event_espresso'
1254
-                        ),
1255
-                        get_class($subsection),
1256
-                        $subsection_name,
1257
-                        $this->name()
1258
-                    )
1259
-                );
1260
-                unset($new_subsections[ $subsection_name ]);
1261
-            }
1262
-        }
1263
-        $this->_subsections = EEH_Array::insert_into_array(
1264
-            $this->_subsections,
1265
-            $new_subsections,
1266
-            $subsection_name_to_target,
1267
-            $add_before
1268
-        );
1269
-        if ($this->_construction_finalized) {
1270
-            foreach ($this->_subsections as $name => $subsection) {
1271
-                $subsection->_construct_finalize($this, $name);
1272
-            }
1273
-        }
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * @param string $subsection_name
1279
-     * @param bool   $recursive
1280
-     * @return bool
1281
-     */
1282
-    public function has_subsection($subsection_name, $recursive = false)
1283
-    {
1284
-        foreach ($this->_subsections as $name => $subsection) {
1285
-            if ($name === $subsection_name
1286
-                || (
1287
-                    $recursive
1288
-                    && $subsection instanceof EE_Form_Section_Proper
1289
-                    && $subsection->has_subsection($subsection_name, $recursive)
1290
-                )
1291
-            ) {
1292
-                return true;
1293
-            }
1294
-        }
1295
-        return false;
1296
-    }
1297
-
1298
-
1299
-
1300
-    /**
1301
-     * Just gets all validatable subsections to clean their sensitive data
1302
-     *
1303
-     * @throws EE_Error
1304
-     */
1305
-    public function clean_sensitive_data()
1306
-    {
1307
-        foreach ($this->get_validatable_subsections() as $subsection) {
1308
-            $subsection->clean_sensitive_data();
1309
-        }
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1315
-     * @param string                           $form_submission_error_message
1316
-     * @param EE_Form_Section_Validatable $form_section unused
1317
-     * @throws EE_Error
1318
-     */
1319
-    public function set_submission_error_message(
1320
-        $form_submission_error_message = ''
1321
-    ) {
1322
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1323
-            ? $form_submission_error_message
1324
-            : $this->getAllValidationErrorsString();
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Returns the cached error message. A default value is set for this during _validate(),
1330
-     * (called during receive_form_submission) but it can be explicitly set using
1331
-     * set_submission_error_message
1332
-     *
1333
-     * @return string
1334
-     */
1335
-    public function submission_error_message()
1336
-    {
1337
-        return $this->_form_submission_error_message;
1338
-    }
1339
-
1340
-
1341
-    /**
1342
-     * Sets a message to display if the data submitted to the form was valid.
1343
-     * @param string $form_submission_success_message
1344
-     */
1345
-    public function set_submission_success_message($form_submission_success_message = '')
1346
-    {
1347
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1348
-            ? $form_submission_success_message
1349
-            : esc_html__('Form submitted successfully', 'event_espresso');
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Gets a message appropriate for display when the form is correctly submitted
1355
-     * @return string
1356
-     */
1357
-    public function submission_success_message()
1358
-    {
1359
-        return $this->_form_submission_success_message;
1360
-    }
1361
-
1362
-
1363
-    /**
1364
-     * Returns the prefix that should be used on child of this form section for
1365
-     * their html names. If this form section itself has a parent, prepends ITS
1366
-     * prefix onto this form section's prefix. Used primarily by
1367
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1368
-     *
1369
-     * @return string
1370
-     * @throws EE_Error
1371
-     */
1372
-    public function html_name_prefix()
1373
-    {
1374
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1375
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1376
-        }
1377
-        return $this->name();
1378
-    }
1379
-
1380
-
1381
-    /**
1382
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1383
-     * calls it (assumes there is no parent and that we want the name to be whatever
1384
-     * was set, which is probably nothing, or the classname)
1385
-     *
1386
-     * @return string
1387
-     * @throws EE_Error
1388
-     */
1389
-    public function name()
1390
-    {
1391
-        $this->ensure_construct_finalized_called();
1392
-        return parent::name();
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     * @return EE_Form_Section_Proper
1398
-     * @throws EE_Error
1399
-     */
1400
-    public function parent_section()
1401
-    {
1402
-        $this->ensure_construct_finalized_called();
1403
-        return parent::parent_section();
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * make sure construction finalized was called, otherwise children might not be ready
1409
-     *
1410
-     * @return void
1411
-     * @throws EE_Error
1412
-     */
1413
-    public function ensure_construct_finalized_called()
1414
-    {
1415
-        if (! $this->_construction_finalized) {
1416
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1417
-        }
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1423
-     * are in teh form data. If any are found, returns true. Else false
1424
-     *
1425
-     * @param array $req_data
1426
-     * @return boolean
1427
-     * @throws EE_Error
1428
-     */
1429
-    public function form_data_present_in($req_data = null)
1430
-    {
1431
-        $req_data = $this->getCachedRequest($req_data);
1432
-        foreach ($this->subsections() as $subsection) {
1433
-            if ($subsection instanceof EE_Form_Input_Base) {
1434
-                if ($subsection->form_data_present_in($req_data)) {
1435
-                    return true;
1436
-                }
1437
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1438
-                if ($subsection->form_data_present_in($req_data)) {
1439
-                    return true;
1440
-                }
1441
-            }
1442
-        }
1443
-        return false;
1444
-    }
1445
-
1446
-
1447
-    /**
1448
-     * Gets validation errors for this form section and subsections
1449
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1450
-     * gets the validation errors for ALL subsection
1451
-     *
1452
-     * @return EE_Validation_Error[]
1453
-     * @throws EE_Error
1454
-     */
1455
-    public function get_validation_errors_accumulated()
1456
-    {
1457
-        $validation_errors = $this->get_validation_errors();
1458
-        foreach ($this->get_validatable_subsections() as $subsection) {
1459
-            if ($subsection instanceof EE_Form_Section_Proper) {
1460
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1461
-            } else {
1462
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1463
-            }
1464
-            if ($validation_errors_on_this_subsection) {
1465
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1466
-            }
1467
-        }
1468
-        return $validation_errors;
1469
-    }
1470
-
1471
-    /**
1472
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1473
-     * This traverses the form section tree to generate this, but you probably want to instead use
1474
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1475
-     *
1476
-     * @return string
1477
-     * @since 4.9.59.p
1478
-     */
1479
-    protected function getAllValidationErrorsString()
1480
-    {
1481
-        $submission_error_messages = array();
1482
-        // bad, bad, bad registrant
1483
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1484
-            if ($validation_error instanceof EE_Validation_Error) {
1485
-                $form_section = $validation_error->get_form_section();
1486
-                if ($form_section instanceof EE_Form_Input_Base) {
1487
-                    $label = $validation_error->get_form_section()->html_label_text();
1488
-                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1489
-                    $label = $validation_error->get_form_section()->name();
1490
-                } else {
1491
-                    $label = esc_html__('Unknown', 'event_espresso');
1492
-                }
1493
-                $submission_error_messages[] = sprintf(
1494
-                    __('%s : %s', 'event_espresso'),
1495
-                    $label,
1496
-                    $validation_error->getMessage()
1497
-                );
1498
-            }
1499
-        }
1500
-        return implode('<br>', $submission_error_messages);
1501
-    }
1502
-
1503
-
1504
-    /**
1505
-     * This isn't just the name of an input, it's a path pointing to an input. The
1506
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1507
-     * dot-dot-slash (../) means to ascend into the parent section.
1508
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1509
-     * which will be returned.
1510
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1511
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1512
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1513
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1514
-     * Etc
1515
-     *
1516
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1517
-     * @return EE_Form_Section_Base
1518
-     * @throws EE_Error
1519
-     */
1520
-    public function find_section_from_path($form_section_path)
1521
-    {
1522
-        // check if we can find the input from purely going straight up the tree
1523
-        $input = parent::find_section_from_path($form_section_path);
1524
-        if ($input instanceof EE_Form_Section_Base) {
1525
-            return $input;
1526
-        }
1527
-        $next_slash_pos = strpos($form_section_path, '/');
1528
-        if ($next_slash_pos !== false) {
1529
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1530
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1531
-        } else {
1532
-            $child_section_name = $form_section_path;
1533
-            $subpath            = '';
1534
-        }
1535
-        $child_section = $this->get_subsection($child_section_name);
1536
-        if ($child_section instanceof EE_Form_Section_Base) {
1537
-            return $child_section->find_section_from_path($subpath);
1538
-        }
1539
-        return null;
1540
-    }
17
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
+
19
+	/**
20
+	 * Subsections
21
+	 *
22
+	 * @var EE_Form_Section_Validatable[]
23
+	 */
24
+	protected $_subsections = array();
25
+
26
+	/**
27
+	 * Strategy for laying out the form
28
+	 *
29
+	 * @var EE_Form_Section_Layout_Base
30
+	 */
31
+	protected $_layout_strategy;
32
+
33
+	/**
34
+	 * Whether or not this form has received and validated a form submission yet
35
+	 *
36
+	 * @var boolean
37
+	 */
38
+	protected $_received_submission = false;
39
+
40
+	/**
41
+	 * message displayed to users upon successful form submission
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_form_submission_success_message = '';
46
+
47
+	/**
48
+	 * message displayed to users upon unsuccessful form submission
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_form_submission_error_message = '';
53
+
54
+	/**
55
+	 * @var array like $_REQUEST
56
+	 */
57
+	protected $cached_request_data;
58
+
59
+	/**
60
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
61
+	 * Starts off as null, but once the form is validated, it set to either true or false
62
+	 * @var boolean|null
63
+	 */
64
+	protected $is_valid;
65
+
66
+	/**
67
+	 * Stores all the data that will localized for form validation
68
+	 *
69
+	 * @var array
70
+	 */
71
+	static protected $_js_localization = array();
72
+
73
+	/**
74
+	 * whether or not the form's localized validation JS vars have been set
75
+	 *
76
+	 * @type boolean
77
+	 */
78
+	static protected $_scripts_localized = false;
79
+
80
+
81
+	/**
82
+	 * when constructing a proper form section, calls _construct_finalize on children
83
+	 * so that they know who their parent is, and what name they've been given.
84
+	 *
85
+	 * @param array[] $options_array   {
86
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
88
+	 *                                 and in that order. This is handy if you want
89
+	 *                                 the subsections to be ordered differently than the default, and if you override
90
+	 *                                 which fields are shown
91
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
+	 *                                 items from that list of inclusions)
95
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
97
+	 * @throws EE_Error
98
+	 */
99
+	public function __construct($options_array = array())
100
+	{
101
+		$options_array = (array) apply_filters(
102
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
103
+			$options_array,
104
+			$this
105
+		);
106
+		// call parent first, as it may be setting the name
107
+		parent::__construct($options_array);
108
+		// if they've included subsections in the constructor, add them now
109
+		if (isset($options_array['include'])) {
110
+			// we are going to make sure we ONLY have those subsections to include
111
+			// AND we are going to make sure they're in that specified order
112
+			$reordered_subsections = array();
113
+			foreach ($options_array['include'] as $input_name) {
114
+				if (isset($this->_subsections[ $input_name ])) {
115
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
+				}
117
+			}
118
+			$this->_subsections = $reordered_subsections;
119
+		}
120
+		if (isset($options_array['exclude'])) {
121
+			$exclude            = $options_array['exclude'];
122
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
+		}
124
+		if (isset($options_array['layout_strategy'])) {
125
+			$this->_layout_strategy = $options_array['layout_strategy'];
126
+		}
127
+		if (! $this->_layout_strategy) {
128
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
+		}
130
+		$this->_layout_strategy->_construct_finalize($this);
131
+		// ok so we are definitely going to want the forms JS,
132
+		// so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
+			// ok so they've constructed this object after when they should have.
135
+			// just enqueue the generic form scripts and initialize the form immediately in the JS
136
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
+		} else {
138
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+		}
141
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
+		/**
143
+		 * Gives other plugins a chance to hook in before construct finalize is called.
144
+		 * The form probably doesn't yet have a parent form section.
145
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
+		 *
149
+		 * @since 4.9.32
150
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
+		 *                                              except maybe calling _construct_finalize has been done
152
+		 * @param array                  $options_array options passed into the constructor
153
+		 */
154
+		do_action(
155
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
+			$this,
157
+			$options_array
158
+		);
159
+		if (isset($options_array['name'])) {
160
+			$this->_construct_finalize(null, $options_array['name']);
161
+		}
162
+	}
163
+
164
+
165
+	/**
166
+	 * Finishes construction given the parent form section and this form section's name
167
+	 *
168
+	 * @param EE_Form_Section_Proper $parent_form_section
169
+	 * @param string                 $name
170
+	 * @throws EE_Error
171
+	 */
172
+	public function _construct_finalize($parent_form_section, $name)
173
+	{
174
+		parent::_construct_finalize($parent_form_section, $name);
175
+		$this->_set_default_name_if_empty();
176
+		$this->_set_default_html_id_if_empty();
177
+		foreach ($this->_subsections as $subsection_name => $subsection) {
178
+			if ($subsection instanceof EE_Form_Section_Base) {
179
+				$subsection->_construct_finalize($this, $subsection_name);
180
+			} else {
181
+				throw new EE_Error(
182
+					sprintf(
183
+						esc_html__(
184
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
+							'event_espresso'
186
+						),
187
+						$subsection_name,
188
+						get_class($this),
189
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
+					)
191
+				);
192
+			}
193
+		}
194
+		/**
195
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
199
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
+		 * ensured it has a name, HTML IDs, etc
201
+		 *
202
+		 * @param EE_Form_Section_Proper      $this
203
+		 * @param EE_Form_Section_Proper|null $parent_form_section
204
+		 * @param string                      $name
205
+		 */
206
+		do_action(
207
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
+			$this,
209
+			$parent_form_section,
210
+			$name
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 * Gets the layout strategy for this form section
217
+	 *
218
+	 * @return EE_Form_Section_Layout_Base
219
+	 */
220
+	public function get_layout_strategy()
221
+	{
222
+		return $this->_layout_strategy;
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets the HTML for a single input for this form section according
228
+	 * to the layout strategy
229
+	 *
230
+	 * @param EE_Form_Input_Base $input
231
+	 * @return string
232
+	 */
233
+	public function get_html_for_input($input)
234
+	{
235
+		return $this->_layout_strategy->layout_input($input);
236
+	}
237
+
238
+
239
+	/**
240
+	 * was_submitted - checks if form inputs are present in request data
241
+	 * Basically an alias for form_data_present_in() (which is used by both
242
+	 * proper form sections and form inputs)
243
+	 *
244
+	 * @param null $form_data
245
+	 * @return boolean
246
+	 * @throws EE_Error
247
+	 */
248
+	public function was_submitted($form_data = null)
249
+	{
250
+		return $this->form_data_present_in($form_data);
251
+	}
252
+
253
+	/**
254
+	 * Gets the cached request data; but if there is none, or $req_data was set with
255
+	 * something different, refresh the cache, and then return it
256
+	 * @param null $req_data
257
+	 * @return array
258
+	 */
259
+	protected function getCachedRequest($req_data = null)
260
+	{
261
+		if ($this->cached_request_data === null
262
+			|| (
263
+				$req_data !== null &&
264
+				$req_data !== $this->cached_request_data
265
+			)
266
+		) {
267
+			$req_data = apply_filters(
268
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
+				$req_data,
270
+				$this
271
+			);
272
+			if ($req_data === null) {
273
+				$req_data = array_merge($_GET, $_POST);
274
+			}
275
+			$req_data = apply_filters(
276
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
+				$req_data,
278
+				$this
279
+			);
280
+			$this->cached_request_data = (array) $req_data;
281
+		}
282
+		return $this->cached_request_data;
283
+	}
284
+
285
+
286
+	/**
287
+	 * After the form section is initially created, call this to sanitize the data in the submission
288
+	 * which relates to this form section, validate it, and set it as properties on the form.
289
+	 *
290
+	 * @param array|null $req_data should usually be $_POST (the default).
291
+	 *                             However, you CAN supply a different array.
292
+	 *                             Consider using set_defaults() instead however.
293
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
294
+	 *                             the inputs will have the correct name in the request data for this function
295
+	 *                             to find them and populate the form with them.
296
+	 *                             If you have a flat form (with only input subsections),
297
+	 *                             you can supply a flat array where keys
298
+	 *                             are the form input names and values are their values)
299
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
+	 *                             of course, to validate that data, and set errors on the invalid values.
301
+	 *                             But if the data has already been validated
302
+	 *                             (eg you validated the data then stored it in the DB)
303
+	 *                             you may want to skip this step.
304
+	 * @throws InvalidArgumentException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws InvalidDataTypeException
307
+	 * @throws EE_Error
308
+	 */
309
+	public function receive_form_submission($req_data = null, $validate = true)
310
+	{
311
+		$req_data = $this->getCachedRequest($req_data);
312
+		$this->_normalize($req_data);
313
+		if ($validate) {
314
+			$this->_validate();
315
+			// if it's invalid, we're going to want to re-display so remember what they submitted
316
+			if (! $this->is_valid()) {
317
+				$this->store_submitted_form_data_in_session();
318
+			}
319
+		}
320
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
+			$this->set_submission_error_message();
322
+		}
323
+		do_action(
324
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
+			$req_data,
326
+			$this,
327
+			$validate
328
+		);
329
+	}
330
+
331
+
332
+	/**
333
+	 * caches the originally submitted input values in the session
334
+	 * so that they can be used to repopulate the form if it failed validation
335
+	 *
336
+	 * @return boolean whether or not the data was successfully stored in the session
337
+	 * @throws InvalidArgumentException
338
+	 * @throws InvalidInterfaceException
339
+	 * @throws InvalidDataTypeException
340
+	 * @throws EE_Error
341
+	 */
342
+	protected function store_submitted_form_data_in_session()
343
+	{
344
+		return EE_Registry::instance()->SSN->set_session_data(
345
+			array(
346
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
+			)
348
+		);
349
+	}
350
+
351
+
352
+	/**
353
+	 * retrieves the originally submitted input values in the session
354
+	 * so that they can be used to repopulate the form if it failed validation
355
+	 *
356
+	 * @return array
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws InvalidDataTypeException
360
+	 */
361
+	protected function get_submitted_form_data_from_session()
362
+	{
363
+		$session = EE_Registry::instance()->SSN;
364
+		if ($session instanceof EE_Session) {
365
+			return $session->get_session_data(
366
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
+			);
368
+		}
369
+		return array();
370
+	}
371
+
372
+
373
+	/**
374
+	 * flushed the originally submitted input values from the session
375
+	 *
376
+	 * @return boolean whether or not the data was successfully removed from the session
377
+	 * @throws InvalidArgumentException
378
+	 * @throws InvalidInterfaceException
379
+	 * @throws InvalidDataTypeException
380
+	 */
381
+	public static function flush_submitted_form_data_from_session()
382
+	{
383
+		return EE_Registry::instance()->SSN->reset_data(
384
+			array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Populates this form and its subsections with data from the session.
391
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
+	 * validation errors when displaying too)
393
+	 * Returns true if the form was populated from the session, false otherwise
394
+	 *
395
+	 * @return boolean
396
+	 * @throws InvalidArgumentException
397
+	 * @throws InvalidInterfaceException
398
+	 * @throws InvalidDataTypeException
399
+	 * @throws EE_Error
400
+	 */
401
+	public function populate_from_session()
402
+	{
403
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
404
+		if (empty($form_data_in_session)) {
405
+			return false;
406
+		}
407
+		$this->receive_form_submission($form_data_in_session);
408
+		add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
409
+		if ($this->form_data_present_in($form_data_in_session)) {
410
+			return true;
411
+		}
412
+		return false;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Populates the default data for the form, given an array where keys are
418
+	 * the input names, and values are their values (preferably normalized to be their
419
+	 * proper PHP types, not all strings... although that should be ok too).
420
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
421
+	 * the value being an array formatted in teh same way
422
+	 *
423
+	 * @param array $default_data
424
+	 * @throws EE_Error
425
+	 */
426
+	public function populate_defaults($default_data)
427
+	{
428
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
+			if (isset($default_data[ $subsection_name ])) {
430
+				if ($subsection instanceof EE_Form_Input_Base) {
431
+					$subsection->set_default($default_data[ $subsection_name ]);
432
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
433
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
434
+				}
435
+			}
436
+		}
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns true if subsection exists
442
+	 *
443
+	 * @param string $name
444
+	 * @return boolean
445
+	 */
446
+	public function subsection_exists($name)
447
+	{
448
+		return isset($this->_subsections[ $name ]) ? true : false;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the subsection specified by its name
454
+	 *
455
+	 * @param string  $name
456
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
+	 *                                                      so that the inputs will be properly configured.
458
+	 *                                                      However, some client code may be ok
459
+	 *                                                      with construction finalize being called later
460
+	 *                                                      (realizing that the subsections' html names
461
+	 *                                                      might not be set yet, etc.)
462
+	 * @return EE_Form_Section_Base
463
+	 * @throws EE_Error
464
+	 */
465
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
466
+	{
467
+		if ($require_construction_to_be_finalized) {
468
+			$this->ensure_construct_finalized_called();
469
+		}
470
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets all the validatable subsections of this form section
476
+	 *
477
+	 * @return EE_Form_Section_Validatable[]
478
+	 * @throws EE_Error
479
+	 */
480
+	public function get_validatable_subsections()
481
+	{
482
+		$validatable_subsections = array();
483
+		foreach ($this->subsections() as $name => $obj) {
484
+			if ($obj instanceof EE_Form_Section_Validatable) {
485
+				$validatable_subsections[ $name ] = $obj;
486
+			}
487
+		}
488
+		return $validatable_subsections;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
+	 * throw an EE_Error.
495
+	 *
496
+	 * @param string  $name
497
+	 * @param boolean $require_construction_to_be_finalized most client code should
498
+	 *                                                      leave this as TRUE so that the inputs will be properly
499
+	 *                                                      configured. However, some client code may be ok with
500
+	 *                                                      construction finalize being called later
501
+	 *                                                      (realizing that the subsections' html names might not be
502
+	 *                                                      set yet, etc.)
503
+	 * @return EE_Form_Input_Base
504
+	 * @throws EE_Error
505
+	 */
506
+	public function get_input($name, $require_construction_to_be_finalized = true)
507
+	{
508
+		$subsection = $this->get_subsection(
509
+			$name,
510
+			$require_construction_to_be_finalized
511
+		);
512
+		if (! $subsection instanceof EE_Form_Input_Base) {
513
+			throw new EE_Error(
514
+				sprintf(
515
+					esc_html__(
516
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
+						'event_espresso'
518
+					),
519
+					$name,
520
+					get_class($this),
521
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
+				)
523
+			);
524
+		}
525
+		return $subsection;
526
+	}
527
+
528
+
529
+	/**
530
+	 * Like get_input(), gets the proper subsection of the form given the name,
531
+	 * otherwise throws an EE_Error
532
+	 *
533
+	 * @param string  $name
534
+	 * @param boolean $require_construction_to_be_finalized most client code should
535
+	 *                                                      leave this as TRUE so that the inputs will be properly
536
+	 *                                                      configured. However, some client code may be ok with
537
+	 *                                                      construction finalize being called later
538
+	 *                                                      (realizing that the subsections' html names might not be
539
+	 *                                                      set yet, etc.)
540
+	 * @return EE_Form_Section_Proper
541
+	 * @throws EE_Error
542
+	 */
543
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
+	{
545
+		$subsection = $this->get_subsection(
546
+			$name,
547
+			$require_construction_to_be_finalized
548
+		);
549
+		if (! $subsection instanceof EE_Form_Section_Proper) {
550
+			throw new EE_Error(
551
+				sprintf(
552
+					esc_html__(
553
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
+						'event_espresso'
555
+					),
556
+					$name,
557
+					get_class($this)
558
+				)
559
+			);
560
+		}
561
+		return $subsection;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
567
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
568
+	 *
569
+	 * @param string $name
570
+	 * @return mixed depending on the input's type and its normalization strategy
571
+	 * @throws EE_Error
572
+	 */
573
+	public function get_input_value($name)
574
+	{
575
+		$input = $this->get_input($name);
576
+		return $input->normalized_value();
577
+	}
578
+
579
+
580
+	/**
581
+	 * Checks if this form section itself is valid, and then checks its subsections
582
+	 *
583
+	 * @throws EE_Error
584
+	 * @return boolean
585
+	 */
586
+	public function is_valid()
587
+	{
588
+		if ($this->is_valid === null) {
589
+			if (! $this->has_received_submission()) {
590
+				throw new EE_Error(
591
+					sprintf(
592
+						esc_html__(
593
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
+							'event_espresso'
595
+						)
596
+					)
597
+				);
598
+			}
599
+			if (! parent::is_valid()) {
600
+				$this->is_valid = false;
601
+			} else {
602
+				// ok so no general errors to this entire form section.
603
+				// so let's check the subsections, but only set errors if that hasn't been done yet
604
+				$this->is_valid = true;
605
+				foreach ($this->get_validatable_subsections() as $subsection) {
606
+					if (! $subsection->is_valid()) {
607
+						$this->is_valid = false;
608
+					}
609
+				}
610
+			}
611
+		}
612
+		return $this->is_valid;
613
+	}
614
+
615
+
616
+	/**
617
+	 * gets the default name of this form section if none is specified
618
+	 *
619
+	 * @return void
620
+	 */
621
+	protected function _set_default_name_if_empty()
622
+	{
623
+		if (! $this->_name) {
624
+			$classname    = get_class($this);
625
+			$default_name = str_replace('EE_', '', $classname);
626
+			$this->_name  = $default_name;
627
+		}
628
+	}
629
+
630
+
631
+	/**
632
+	 * Returns the HTML for the form, except for the form opening and closing tags
633
+	 * (as the form section doesn't know where you necessarily want to send the information to),
634
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
637
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
+	 * any CSS.
639
+	 *
640
+	 * @throws InvalidArgumentException
641
+	 * @throws InvalidInterfaceException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws EE_Error
644
+	 */
645
+	public function get_html_and_js()
646
+	{
647
+		$this->enqueue_js();
648
+		return $this->get_html();
649
+	}
650
+
651
+
652
+	/**
653
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
+	 *
655
+	 * @param bool $display_previously_submitted_data
656
+	 * @return string
657
+	 * @throws InvalidArgumentException
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws EE_Error
662
+	 * @throws EE_Error
663
+	 */
664
+	public function get_html($display_previously_submitted_data = true)
665
+	{
666
+		$this->ensure_construct_finalized_called();
667
+		if ($display_previously_submitted_data) {
668
+			$this->populate_from_session();
669
+		}
670
+		return $this->_form_html_filter
671
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
+			: $this->_layout_strategy->layout_form();
673
+	}
674
+
675
+
676
+	/**
677
+	 * enqueues JS and CSS for the form.
678
+	 * It is preferred to call this before wp_enqueue_scripts so the
679
+	 * scripts and styles can be put in the header, but if called later
680
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
+	 * only be in the header; but in HTML5 its ok in the body.
682
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
+	 *
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 */
688
+	public function enqueue_js()
689
+	{
690
+		$this->_enqueue_and_localize_form_js();
691
+		foreach ($this->subsections() as $subsection) {
692
+			$subsection->enqueue_js();
693
+		}
694
+	}
695
+
696
+
697
+	/**
698
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
+	 * the wp_enqueue_scripts hook.
701
+	 * However, registering the form js and localizing it can happen when we
702
+	 * actually output the form (which is preferred, seeing how teh form's fields
703
+	 * could change until it's actually outputted)
704
+	 *
705
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
+	 *                                                    to be triggered automatically or not
707
+	 * @return void
708
+	 */
709
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
+	{
711
+		wp_register_script(
712
+			'ee_form_section_validation',
713
+			EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
714
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
+			EVENT_ESPRESSO_VERSION,
716
+			true
717
+		);
718
+		wp_localize_script(
719
+			'ee_form_section_validation',
720
+			'ee_form_section_validation_init',
721
+			array('init' => $init_form_validation_automatically ? '1' : '0')
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * gets the variables used by form_section_validation.js.
728
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
+	 * but before the wordpress hook wp_loaded
730
+	 *
731
+	 * @throws EE_Error
732
+	 */
733
+	public function _enqueue_and_localize_form_js()
734
+	{
735
+		$this->ensure_construct_finalized_called();
736
+		// actually, we don't want to localize just yet. There may be other forms on the page.
737
+		// so we need to add our form section data to a static variable accessible by all form sections
738
+		// and localize it just before the footer
739
+		$this->localize_validation_rules();
740
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
+	}
743
+
744
+
745
+	/**
746
+	 * add our form section data to a static variable accessible by all form sections
747
+	 *
748
+	 * @param bool $return_for_subsection
749
+	 * @return void
750
+	 * @throws EE_Error
751
+	 */
752
+	public function localize_validation_rules($return_for_subsection = false)
753
+	{
754
+		// we only want to localize vars ONCE for the entire form,
755
+		// so if the form section doesn't have a parent, then it must be the top dog
756
+		if ($return_for_subsection || ! $this->parent_section()) {
757
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
+				'form_section_id'  => $this->html_id(true),
759
+				'validation_rules' => $this->get_jquery_validation_rules(),
760
+				'other_data'       => $this->get_other_js_data(),
761
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
762
+			);
763
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
764
+		}
765
+	}
766
+
767
+
768
+	/**
769
+	 * Gets an array of extra data that will be useful for client-side javascript.
770
+	 * This is primarily data added by inputs and forms in addition to any
771
+	 * scripts they might enqueue
772
+	 *
773
+	 * @param array $form_other_js_data
774
+	 * @return array
775
+	 * @throws EE_Error
776
+	 */
777
+	public function get_other_js_data($form_other_js_data = array())
778
+	{
779
+		foreach ($this->subsections() as $subsection) {
780
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
+		}
782
+		return $form_other_js_data;
783
+	}
784
+
785
+
786
+	/**
787
+	 * Gets a flat array of inputs for this form section and its subsections.
788
+	 * Keys are their form names, and values are the inputs themselves
789
+	 *
790
+	 * @return EE_Form_Input_Base
791
+	 * @throws EE_Error
792
+	 */
793
+	public function inputs_in_subsections()
794
+	{
795
+		$inputs = array();
796
+		foreach ($this->subsections() as $subsection) {
797
+			if ($subsection instanceof EE_Form_Input_Base) {
798
+				$inputs[ $subsection->html_name() ] = $subsection;
799
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
800
+				$inputs += $subsection->inputs_in_subsections();
801
+			}
802
+		}
803
+		return $inputs;
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets a flat array of all the validation errors.
809
+	 * Keys are html names (because those should be unique)
810
+	 * and values are a string of all their validation errors
811
+	 *
812
+	 * @return string[]
813
+	 * @throws EE_Error
814
+	 */
815
+	public function subsection_validation_errors_by_html_name()
816
+	{
817
+		$inputs = $this->inputs();
818
+		$errors = array();
819
+		foreach ($inputs as $form_input) {
820
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
+			}
823
+		}
824
+		return $errors;
825
+	}
826
+
827
+
828
+	/**
829
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
831
+	 *
832
+	 * @throws InvalidArgumentException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws InvalidDataTypeException
835
+	 */
836
+	public static function localize_script_for_all_forms()
837
+	{
838
+		// allow inputs and stuff to hook in their JS and stuff here
839
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
+			? EE_Registry::instance()->CFG->registration->email_validation_level
843
+			: 'wp_default';
844
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
+		wp_enqueue_script('ee_form_section_validation');
846
+		wp_localize_script(
847
+			'ee_form_section_validation',
848
+			'ee_form_section_vars',
849
+			EE_Form_Section_Proper::$_js_localization
850
+		);
851
+	}
852
+
853
+
854
+	/**
855
+	 * ensure_scripts_localized
856
+	 *
857
+	 * @throws EE_Error
858
+	 */
859
+	public function ensure_scripts_localized()
860
+	{
861
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
862
+			$this->_enqueue_and_localize_form_js();
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
869
+	 * is that the key here should be the same as the custom validation rule put in the JS file
870
+	 *
871
+	 * @return array keys are custom validation rules, and values are internationalized strings
872
+	 */
873
+	private static function _get_localized_error_messages()
874
+	{
875
+		return array(
876
+			'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
+			'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
+		);
879
+	}
880
+
881
+
882
+	/**
883
+	 * @return array
884
+	 */
885
+	public static function js_localization()
886
+	{
887
+		return self::$_js_localization;
888
+	}
889
+
890
+
891
+	/**
892
+	 * @return void
893
+	 */
894
+	public static function reset_js_localization()
895
+	{
896
+		self::$_js_localization = array();
897
+	}
898
+
899
+
900
+	/**
901
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
+	 * See parent function for more...
903
+	 *
904
+	 * @return array
905
+	 * @throws EE_Error
906
+	 */
907
+	public function get_jquery_validation_rules()
908
+	{
909
+		$jquery_validation_rules = array();
910
+		foreach ($this->get_validatable_subsections() as $subsection) {
911
+			$jquery_validation_rules = array_merge(
912
+				$jquery_validation_rules,
913
+				$subsection->get_jquery_validation_rules()
914
+			);
915
+		}
916
+		return $jquery_validation_rules;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sanitizes all the data and sets the sanitized value of each field
922
+	 *
923
+	 * @param array $req_data like $_POST
924
+	 * @return void
925
+	 * @throws EE_Error
926
+	 */
927
+	protected function _normalize($req_data)
928
+	{
929
+		$this->_received_submission = true;
930
+		$this->_validation_errors   = array();
931
+		foreach ($this->get_validatable_subsections() as $subsection) {
932
+			try {
933
+				$subsection->_normalize($req_data);
934
+			} catch (EE_Validation_Error $e) {
935
+				$subsection->add_validation_error($e);
936
+			}
937
+		}
938
+	}
939
+
940
+
941
+	/**
942
+	 * Performs validation on this form section and its subsections.
943
+	 * For each subsection,
944
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
945
+	 * and passes it the subsection, then calls _validate on that subsection.
946
+	 * If you need to perform validation on the form as a whole (considering multiple)
947
+	 * you would be best to override this _validate method,
948
+	 * calling parent::_validate() first.
949
+	 *
950
+	 * @throws EE_Error
951
+	 */
952
+	protected function _validate()
953
+	{
954
+		// reset the cache of whether this form is valid or not- we're re-validating it now
955
+		$this->is_valid = null;
956
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
+			if (method_exists($this, '_validate_' . $subsection_name)) {
958
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
+			}
960
+			$subsection->_validate();
961
+		}
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets all the validated inputs for the form section
967
+	 *
968
+	 * @return array
969
+	 * @throws EE_Error
970
+	 */
971
+	public function valid_data()
972
+	{
973
+		$inputs = array();
974
+		foreach ($this->subsections() as $subsection_name => $subsection) {
975
+			if ($subsection instanceof EE_Form_Section_Proper) {
976
+				$inputs[ $subsection_name ] = $subsection->valid_data();
977
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
978
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
979
+			}
980
+		}
981
+		return $inputs;
982
+	}
983
+
984
+
985
+	/**
986
+	 * Gets all the inputs on this form section
987
+	 *
988
+	 * @return EE_Form_Input_Base[]
989
+	 * @throws EE_Error
990
+	 */
991
+	public function inputs()
992
+	{
993
+		$inputs = array();
994
+		foreach ($this->subsections() as $subsection_name => $subsection) {
995
+			if ($subsection instanceof EE_Form_Input_Base) {
996
+				$inputs[ $subsection_name ] = $subsection;
997
+			}
998
+		}
999
+		return $inputs;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * Gets all the subsections which are a proper form
1005
+	 *
1006
+	 * @return EE_Form_Section_Proper[]
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	public function subforms()
1010
+	{
1011
+		$form_sections = array();
1012
+		foreach ($this->subsections() as $name => $obj) {
1013
+			if ($obj instanceof EE_Form_Section_Proper) {
1014
+				$form_sections[ $name ] = $obj;
1015
+			}
1016
+		}
1017
+		return $form_sections;
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
+	 * Consider using inputs() or subforms()
1024
+	 * if you only want form inputs or proper form sections.
1025
+	 *
1026
+	 * @param boolean $require_construction_to_be_finalized most client code should
1027
+	 *                                                      leave this as TRUE so that the inputs will be properly
1028
+	 *                                                      configured. However, some client code may be ok with
1029
+	 *                                                      construction finalize being called later
1030
+	 *                                                      (realizing that the subsections' html names might not be
1031
+	 *                                                      set yet, etc.)
1032
+	 * @return EE_Form_Section_Proper[]
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	public function subsections($require_construction_to_be_finalized = true)
1036
+	{
1037
+		if ($require_construction_to_be_finalized) {
1038
+			$this->ensure_construct_finalized_called();
1039
+		}
1040
+		return $this->_subsections;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * Returns whether this form has any subforms or inputs
1046
+	 * @return bool
1047
+	 */
1048
+	public function hasSubsections()
1049
+	{
1050
+		return ! empty($this->_subsections);
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Returns a simple array where keys are input names, and values are their normalized
1056
+	 * values. (Similar to calling get_input_value on inputs)
1057
+	 *
1058
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
+	 *                                        or just this forms' direct children inputs
1060
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
+	 *                                        or allow multidimensional array
1062
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
+	 *                                        with array keys being input names
1064
+	 *                                        (regardless of whether they are from a subsection or not),
1065
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1066
+	 *                                        where keys are always subsection names and values are either
1067
+	 *                                        the input's normalized value, or an array like the top-level array
1068
+	 * @throws EE_Error
1069
+	 */
1070
+	public function input_values($include_subform_inputs = false, $flatten = false)
1071
+	{
1072
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
+	 * is not necessarily the value we want to display to users. This creates an array
1080
+	 * where keys are the input names, and values are their display values
1081
+	 *
1082
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
+	 *                                        or just this forms' direct children inputs
1084
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
+	 *                                        or allow multidimensional array
1086
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
+	 *                                        with array keys being input names
1088
+	 *                                        (regardless of whether they are from a subsection or not),
1089
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1090
+	 *                                        where keys are always subsection names and values are either
1091
+	 *                                        the input's normalized value, or an array like the top-level array
1092
+	 * @throws EE_Error
1093
+	 */
1094
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
+	{
1096
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * Gets the input values from the form
1102
+	 *
1103
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
+	 *                                        or just the normalized value
1105
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
+	 *                                        or just this forms' direct children inputs
1107
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
+	 *                                        or allow multidimensional array
1109
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
+	 *                                        input names (regardless of whether they are from a subsection or not),
1111
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1112
+	 *                                        where keys are always subsection names and values are either
1113
+	 *                                        the input's normalized value, or an array like the top-level array
1114
+	 * @throws EE_Error
1115
+	 */
1116
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
+	{
1118
+		$input_values = array();
1119
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1120
+			if ($subsection instanceof EE_Form_Input_Base) {
1121
+				$input_values[ $subsection_name ] = $pretty
1122
+					? $subsection->pretty_value()
1123
+					: $subsection->normalized_value();
1124
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
+				$subform_input_values = $subsection->_input_values(
1126
+					$pretty,
1127
+					$include_subform_inputs,
1128
+					$flatten
1129
+				);
1130
+				if ($flatten) {
1131
+					$input_values = array_merge($input_values, $subform_input_values);
1132
+				} else {
1133
+					$input_values[ $subsection_name ] = $subform_input_values;
1134
+				}
1135
+			}
1136
+		}
1137
+		return $input_values;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Gets the originally submitted input values from the form
1143
+	 *
1144
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
+	 *                                   or just this forms' direct children inputs
1146
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
+	 *                                   with array keys being input names
1148
+	 *                                   (regardless of whether they are from a subsection or not),
1149
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1150
+	 *                                   where keys are always subsection names and values are either
1151
+	 *                                   the input's normalized value, or an array like the top-level array
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function submitted_values($include_subforms = false)
1155
+	{
1156
+		$submitted_values = array();
1157
+		foreach ($this->subsections() as $subsection) {
1158
+			if ($subsection instanceof EE_Form_Input_Base) {
1159
+				// is this input part of an array of inputs?
1160
+				if (strpos($subsection->html_name(), '[') !== false) {
1161
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
+						explode(
1163
+							'[',
1164
+							str_replace(']', '', $subsection->html_name())
1165
+						),
1166
+						$subsection->raw_value()
1167
+					);
1168
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
+				} else {
1170
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
+				}
1172
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1174
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
+			}
1176
+		}
1177
+		return $submitted_values;
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * Indicates whether or not this form has received a submission yet
1183
+	 * (ie, had receive_form_submission called on it yet)
1184
+	 *
1185
+	 * @return boolean
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	public function has_received_submission()
1189
+	{
1190
+		$this->ensure_construct_finalized_called();
1191
+		return $this->_received_submission;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1197
+	 * Removes the listed inputs from the form
1198
+	 *
1199
+	 * @param array $inputs_to_exclude values are the input names
1200
+	 * @return void
1201
+	 */
1202
+	public function exclude(array $inputs_to_exclude = array())
1203
+	{
1204
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
+			unset($this->_subsections[ $input_to_exclude_name ]);
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
+	 * @param array $inputs_to_hide
1213
+	 * @throws EE_Error
1214
+	 */
1215
+	public function hide(array $inputs_to_hide = array())
1216
+	{
1217
+		foreach ($inputs_to_hide as $input_to_hide) {
1218
+			$input = $this->get_input($input_to_hide);
1219
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
+		}
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * add_subsections
1226
+	 * Adds the listed subsections to the form section.
1227
+	 * If $subsection_name_to_target is provided,
1228
+	 * then new subsections are added before or after that subsection,
1229
+	 * otherwise to the start or end of the entire subsections array.
1230
+	 *
1231
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
+	 *                                                          where keys are their names
1233
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
+	 *                                                          should be added before or after
1235
+	 *                                                          IF $subsection_name_to_target is null,
1236
+	 *                                                          then $new_subsections will be added to
1237
+	 *                                                          the beginning or end of the entire subsections array
1238
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
+	 *                                                          $subsection_name_to_target,
1240
+	 *                                                          or if $subsection_name_to_target is null,
1241
+	 *                                                          before or after entire subsections array
1242
+	 * @return void
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
+	{
1247
+		foreach ($new_subsections as $subsection_name => $subsection) {
1248
+			if (! $subsection instanceof EE_Form_Section_Base) {
1249
+				EE_Error::add_error(
1250
+					sprintf(
1251
+						esc_html__(
1252
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
+							'event_espresso'
1254
+						),
1255
+						get_class($subsection),
1256
+						$subsection_name,
1257
+						$this->name()
1258
+					)
1259
+				);
1260
+				unset($new_subsections[ $subsection_name ]);
1261
+			}
1262
+		}
1263
+		$this->_subsections = EEH_Array::insert_into_array(
1264
+			$this->_subsections,
1265
+			$new_subsections,
1266
+			$subsection_name_to_target,
1267
+			$add_before
1268
+		);
1269
+		if ($this->_construction_finalized) {
1270
+			foreach ($this->_subsections as $name => $subsection) {
1271
+				$subsection->_construct_finalize($this, $name);
1272
+			}
1273
+		}
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * @param string $subsection_name
1279
+	 * @param bool   $recursive
1280
+	 * @return bool
1281
+	 */
1282
+	public function has_subsection($subsection_name, $recursive = false)
1283
+	{
1284
+		foreach ($this->_subsections as $name => $subsection) {
1285
+			if ($name === $subsection_name
1286
+				|| (
1287
+					$recursive
1288
+					&& $subsection instanceof EE_Form_Section_Proper
1289
+					&& $subsection->has_subsection($subsection_name, $recursive)
1290
+				)
1291
+			) {
1292
+				return true;
1293
+			}
1294
+		}
1295
+		return false;
1296
+	}
1297
+
1298
+
1299
+
1300
+	/**
1301
+	 * Just gets all validatable subsections to clean their sensitive data
1302
+	 *
1303
+	 * @throws EE_Error
1304
+	 */
1305
+	public function clean_sensitive_data()
1306
+	{
1307
+		foreach ($this->get_validatable_subsections() as $subsection) {
1308
+			$subsection->clean_sensitive_data();
1309
+		}
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1315
+	 * @param string                           $form_submission_error_message
1316
+	 * @param EE_Form_Section_Validatable $form_section unused
1317
+	 * @throws EE_Error
1318
+	 */
1319
+	public function set_submission_error_message(
1320
+		$form_submission_error_message = ''
1321
+	) {
1322
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1323
+			? $form_submission_error_message
1324
+			: $this->getAllValidationErrorsString();
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Returns the cached error message. A default value is set for this during _validate(),
1330
+	 * (called during receive_form_submission) but it can be explicitly set using
1331
+	 * set_submission_error_message
1332
+	 *
1333
+	 * @return string
1334
+	 */
1335
+	public function submission_error_message()
1336
+	{
1337
+		return $this->_form_submission_error_message;
1338
+	}
1339
+
1340
+
1341
+	/**
1342
+	 * Sets a message to display if the data submitted to the form was valid.
1343
+	 * @param string $form_submission_success_message
1344
+	 */
1345
+	public function set_submission_success_message($form_submission_success_message = '')
1346
+	{
1347
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1348
+			? $form_submission_success_message
1349
+			: esc_html__('Form submitted successfully', 'event_espresso');
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Gets a message appropriate for display when the form is correctly submitted
1355
+	 * @return string
1356
+	 */
1357
+	public function submission_success_message()
1358
+	{
1359
+		return $this->_form_submission_success_message;
1360
+	}
1361
+
1362
+
1363
+	/**
1364
+	 * Returns the prefix that should be used on child of this form section for
1365
+	 * their html names. If this form section itself has a parent, prepends ITS
1366
+	 * prefix onto this form section's prefix. Used primarily by
1367
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1368
+	 *
1369
+	 * @return string
1370
+	 * @throws EE_Error
1371
+	 */
1372
+	public function html_name_prefix()
1373
+	{
1374
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1375
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1376
+		}
1377
+		return $this->name();
1378
+	}
1379
+
1380
+
1381
+	/**
1382
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1383
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1384
+	 * was set, which is probably nothing, or the classname)
1385
+	 *
1386
+	 * @return string
1387
+	 * @throws EE_Error
1388
+	 */
1389
+	public function name()
1390
+	{
1391
+		$this->ensure_construct_finalized_called();
1392
+		return parent::name();
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 * @return EE_Form_Section_Proper
1398
+	 * @throws EE_Error
1399
+	 */
1400
+	public function parent_section()
1401
+	{
1402
+		$this->ensure_construct_finalized_called();
1403
+		return parent::parent_section();
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * make sure construction finalized was called, otherwise children might not be ready
1409
+	 *
1410
+	 * @return void
1411
+	 * @throws EE_Error
1412
+	 */
1413
+	public function ensure_construct_finalized_called()
1414
+	{
1415
+		if (! $this->_construction_finalized) {
1416
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1417
+		}
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1423
+	 * are in teh form data. If any are found, returns true. Else false
1424
+	 *
1425
+	 * @param array $req_data
1426
+	 * @return boolean
1427
+	 * @throws EE_Error
1428
+	 */
1429
+	public function form_data_present_in($req_data = null)
1430
+	{
1431
+		$req_data = $this->getCachedRequest($req_data);
1432
+		foreach ($this->subsections() as $subsection) {
1433
+			if ($subsection instanceof EE_Form_Input_Base) {
1434
+				if ($subsection->form_data_present_in($req_data)) {
1435
+					return true;
1436
+				}
1437
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1438
+				if ($subsection->form_data_present_in($req_data)) {
1439
+					return true;
1440
+				}
1441
+			}
1442
+		}
1443
+		return false;
1444
+	}
1445
+
1446
+
1447
+	/**
1448
+	 * Gets validation errors for this form section and subsections
1449
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1450
+	 * gets the validation errors for ALL subsection
1451
+	 *
1452
+	 * @return EE_Validation_Error[]
1453
+	 * @throws EE_Error
1454
+	 */
1455
+	public function get_validation_errors_accumulated()
1456
+	{
1457
+		$validation_errors = $this->get_validation_errors();
1458
+		foreach ($this->get_validatable_subsections() as $subsection) {
1459
+			if ($subsection instanceof EE_Form_Section_Proper) {
1460
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1461
+			} else {
1462
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1463
+			}
1464
+			if ($validation_errors_on_this_subsection) {
1465
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1466
+			}
1467
+		}
1468
+		return $validation_errors;
1469
+	}
1470
+
1471
+	/**
1472
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1473
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1474
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1475
+	 *
1476
+	 * @return string
1477
+	 * @since 4.9.59.p
1478
+	 */
1479
+	protected function getAllValidationErrorsString()
1480
+	{
1481
+		$submission_error_messages = array();
1482
+		// bad, bad, bad registrant
1483
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1484
+			if ($validation_error instanceof EE_Validation_Error) {
1485
+				$form_section = $validation_error->get_form_section();
1486
+				if ($form_section instanceof EE_Form_Input_Base) {
1487
+					$label = $validation_error->get_form_section()->html_label_text();
1488
+				} elseif ($form_section instanceof EE_Form_Section_Validatable) {
1489
+					$label = $validation_error->get_form_section()->name();
1490
+				} else {
1491
+					$label = esc_html__('Unknown', 'event_espresso');
1492
+				}
1493
+				$submission_error_messages[] = sprintf(
1494
+					__('%s : %s', 'event_espresso'),
1495
+					$label,
1496
+					$validation_error->getMessage()
1497
+				);
1498
+			}
1499
+		}
1500
+		return implode('<br>', $submission_error_messages);
1501
+	}
1502
+
1503
+
1504
+	/**
1505
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1506
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1507
+	 * dot-dot-slash (../) means to ascend into the parent section.
1508
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1509
+	 * which will be returned.
1510
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1511
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1512
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1513
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1514
+	 * Etc
1515
+	 *
1516
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1517
+	 * @return EE_Form_Section_Base
1518
+	 * @throws EE_Error
1519
+	 */
1520
+	public function find_section_from_path($form_section_path)
1521
+	{
1522
+		// check if we can find the input from purely going straight up the tree
1523
+		$input = parent::find_section_from_path($form_section_path);
1524
+		if ($input instanceof EE_Form_Section_Base) {
1525
+			return $input;
1526
+		}
1527
+		$next_slash_pos = strpos($form_section_path, '/');
1528
+		if ($next_slash_pos !== false) {
1529
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1530
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1531
+		} else {
1532
+			$child_section_name = $form_section_path;
1533
+			$subpath            = '';
1534
+		}
1535
+		$child_section = $this->get_subsection($child_section_name);
1536
+		if ($child_section instanceof EE_Form_Section_Base) {
1537
+			return $child_section->find_section_from_path($subpath);
1538
+		}
1539
+		return null;
1540
+	}
1541 1541
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 1 patch
Indentation   +2102 added lines, -2102 removed lines patch added patch discarded remove patch
@@ -17,2106 +17,2106 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * Used to reference when a registration has never been checked in.
22
-     *
23
-     * @deprecated use \EE_Checkin::status_checked_never instead
24
-     * @type int
25
-     */
26
-    const checkin_status_never = 2;
27
-
28
-    /**
29
-     * Used to reference when a registration has been checked in.
30
-     *
31
-     * @deprecated use \EE_Checkin::status_checked_in instead
32
-     * @type int
33
-     */
34
-    const checkin_status_in = 1;
35
-
36
-
37
-    /**
38
-     * Used to reference when a registration has been checked out.
39
-     *
40
-     * @deprecated use \EE_Checkin::status_checked_out instead
41
-     * @type int
42
-     */
43
-    const checkin_status_out = 0;
44
-
45
-
46
-    /**
47
-     * extra meta key for tracking reg status os trashed registrations
48
-     *
49
-     * @type string
50
-     */
51
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
-
53
-
54
-    /**
55
-     * extra meta key for tracking if registration has reserved ticket
56
-     *
57
-     * @type string
58
-     */
59
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values          incoming values
64
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
-     *                                        used.)
66
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
-     *                                        date_format and the second value is the time format
68
-     * @return EE_Registration
69
-     * @throws EE_Error
70
-     */
71
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
-    {
73
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Registration
83
-     */
84
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
-    {
86
-        return new self($props_n_values, true, $timezone);
87
-    }
88
-
89
-
90
-    /**
91
-     *        Set Event ID
92
-     *
93
-     * @param        int $EVT_ID Event ID
94
-     * @throws EE_Error
95
-     * @throws RuntimeException
96
-     */
97
-    public function set_event($EVT_ID = 0)
98
-    {
99
-        $this->set('EVT_ID', $EVT_ID);
100
-    }
101
-
102
-
103
-    /**
104
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
-     * be routed to internal methods
106
-     *
107
-     * @param string $field_name
108
-     * @param mixed  $field_value
109
-     * @param bool   $use_default
110
-     * @throws EE_Error
111
-     * @throws EntityNotFoundException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     * @throws ReflectionException
116
-     * @throws RuntimeException
117
-     */
118
-    public function set($field_name, $field_value, $use_default = false)
119
-    {
120
-        switch ($field_name) {
121
-            case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
123
-                    $this->set_reg_code($field_value, $use_default);
124
-                }
125
-                break;
126
-            case 'STS_ID':
127
-                $this->set_status($field_value, $use_default);
128
-                break;
129
-            default:
130
-                parent::set($field_name, $field_value, $use_default);
131
-        }
132
-    }
133
-
134
-
135
-    /**
136
-     * Set Status ID
137
-     * updates the registration status and ALSO...
138
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
-     *
141
-     * @param string                $new_STS_ID
142
-     * @param boolean               $use_default
143
-     * @param ContextInterface|null $context
144
-     * @return bool
145
-     * @throws DomainException
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidInterfaceException
151
-     * @throws ReflectionException
152
-     * @throws RuntimeException
153
-     * @throws UnexpectedEntityException
154
-     */
155
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
-    {
157
-        // get current REG_Status
158
-        $old_STS_ID = $this->status_ID();
159
-        // if status has changed
160
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
-            && ! empty($old_STS_ID) // and that old status is actually set
162
-            && ! empty($new_STS_ID) // as well as the new status
163
-            && $this->ID() // ensure registration is in the db
164
-        ) {
165
-            // update internal status first
166
-            parent::set('STS_ID', $new_STS_ID, $use_default);
167
-            // THEN handle other changes that occur when reg status changes
168
-            // TO approved
169
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
-                // reserve a space by incrementing ticket and datetime sold values
171
-                $this->reserveRegistrationSpace();
172
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
-                // OR FROM  approved
174
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
-                // release a space by decrementing ticket and datetime sold values
176
-                $this->releaseRegistrationSpace();
177
-                do_action(
178
-                    'AHEE__EE_Registration__set_status__from_approved',
179
-                    $this,
180
-                    $old_STS_ID,
181
-                    $new_STS_ID,
182
-                    $context
183
-                );
184
-            }
185
-            // update status
186
-            parent::set('STS_ID', $new_STS_ID, $use_default);
187
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
-            if ($this->statusChangeUpdatesTransaction($context)) {
189
-                $this->updateTransactionAfterStatusChange();
190
-            }
191
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
-            return true;
193
-        }
194
-        // even though the old value matches the new value, it's still good to
195
-        // allow the parent set method to have a say
196
-        parent::set('STS_ID', $new_STS_ID, $use_default);
197
-        return true;
198
-    }
199
-
200
-
201
-    /**
202
-     * update REGs and TXN when cancelled or declined registrations involved
203
-     *
204
-     * @param string                $new_STS_ID
205
-     * @param string                $old_STS_ID
206
-     * @param ContextInterface|null $context
207
-     * @throws EE_Error
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     * @throws ReflectionException
212
-     * @throws RuntimeException
213
-     */
214
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
-    {
216
-        // these reg statuses should not be considered in any calculations involving monies owing
217
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
-        // true if registration has been cancelled or declined
219
-        $this->updateIfCanceled(
220
-            $closed_reg_statuses,
221
-            $new_STS_ID,
222
-            $old_STS_ID,
223
-            $context
224
-        );
225
-        $this->updateIfReinstated(
226
-            $closed_reg_statuses,
227
-            $new_STS_ID,
228
-            $old_STS_ID,
229
-            $context
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     * update REGs and TXN when cancelled or declined registrations involved
236
-     *
237
-     * @param array                 $closed_reg_statuses
238
-     * @param string                $new_STS_ID
239
-     * @param string                $old_STS_ID
240
-     * @param ContextInterface|null $context
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws InvalidDataTypeException
244
-     * @throws InvalidInterfaceException
245
-     * @throws ReflectionException
246
-     * @throws RuntimeException
247
-     */
248
-    private function updateIfCanceled(
249
-        array $closed_reg_statuses,
250
-        $new_STS_ID,
251
-        $old_STS_ID,
252
-        ContextInterface $context = null
253
-    ) {
254
-        // true if registration has been cancelled or declined
255
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
-        ) {
258
-            /** @type EE_Registration_Processor $registration_processor */
259
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
-            /** @type EE_Transaction_Processor $transaction_processor */
261
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
-            // cancelled or declined registration
263
-            $registration_processor->update_registration_after_being_canceled_or_declined(
264
-                $this,
265
-                $closed_reg_statuses
266
-            );
267
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
-                $this,
269
-                $closed_reg_statuses,
270
-                false
271
-            );
272
-            do_action(
273
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
274
-                $this,
275
-                $old_STS_ID,
276
-                $new_STS_ID,
277
-                $context
278
-            );
279
-            return;
280
-        }
281
-    }
282
-
283
-
284
-    /**
285
-     * update REGs and TXN when cancelled or declined registrations involved
286
-     *
287
-     * @param array                 $closed_reg_statuses
288
-     * @param string                $new_STS_ID
289
-     * @param string                $old_STS_ID
290
-     * @param ContextInterface|null $context
291
-     * @throws EE_Error
292
-     * @throws InvalidArgumentException
293
-     * @throws InvalidDataTypeException
294
-     * @throws InvalidInterfaceException
295
-     * @throws ReflectionException
296
-     */
297
-    private function updateIfReinstated(
298
-        array $closed_reg_statuses,
299
-        $new_STS_ID,
300
-        $old_STS_ID,
301
-        ContextInterface $context = null
302
-    ) {
303
-        // true if reinstating cancelled or declined registration
304
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
-        ) {
307
-            /** @type EE_Registration_Processor $registration_processor */
308
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
-            /** @type EE_Transaction_Processor $transaction_processor */
310
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
-            // reinstating cancelled or declined registration
312
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
-                $this,
314
-                $closed_reg_statuses
315
-            );
316
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
-                $this,
318
-                $closed_reg_statuses,
319
-                false
320
-            );
321
-            do_action(
322
-                'AHEE__EE_Registration__set_status__after_reinstated',
323
-                $this,
324
-                $old_STS_ID,
325
-                $new_STS_ID,
326
-                $context
327
-            );
328
-        }
329
-    }
330
-
331
-
332
-    /**
333
-     * @param ContextInterface|null $context
334
-     * @return bool
335
-     */
336
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
-    {
338
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
339
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
-            array('spco_reg_step_attendee_information_process_registrations'),
341
-            $context,
342
-            $this
343
-        );
344
-        return ! (
345
-            $context instanceof ContextInterface
346
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
-        );
348
-    }
349
-
350
-
351
-    /**
352
-     * @throws EE_Error
353
-     * @throws EntityNotFoundException
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidDataTypeException
356
-     * @throws InvalidInterfaceException
357
-     * @throws ReflectionException
358
-     * @throws RuntimeException
359
-     */
360
-    private function updateTransactionAfterStatusChange()
361
-    {
362
-        /** @type EE_Transaction_Payments $transaction_payments */
363
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
-        $this->transaction()->update_status_based_on_total_paid(true);
366
-    }
367
-
368
-
369
-    /**
370
-     *        get Status ID
371
-     */
372
-    public function status_ID()
373
-    {
374
-        return $this->get('STS_ID');
375
-    }
376
-
377
-
378
-    /**
379
-     * Gets the ticket this registration is for
380
-     *
381
-     * @param boolean $include_archived whether to include archived tickets or not.
382
-     *
383
-     * @return EE_Ticket|EE_Base_Class
384
-     * @throws EE_Error
385
-     */
386
-    public function ticket($include_archived = true)
387
-    {
388
-        $query_params = array();
389
-        if ($include_archived) {
390
-            $query_params['default_where_conditions'] = 'none';
391
-        }
392
-        return $this->get_first_related('Ticket', $query_params);
393
-    }
394
-
395
-
396
-    /**
397
-     * Gets the event this registration is for
398
-     *
399
-     * @return EE_Event
400
-     * @throws EE_Error
401
-     * @throws EntityNotFoundException
402
-     */
403
-    public function event()
404
-    {
405
-        $event = $this->get_first_related('Event');
406
-        if (! $event instanceof \EE_Event) {
407
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
408
-        }
409
-        return $event;
410
-    }
411
-
412
-
413
-    /**
414
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
-     * with the author of the event this registration is for.
416
-     *
417
-     * @since 4.5.0
418
-     * @return int
419
-     * @throws EE_Error
420
-     * @throws EntityNotFoundException
421
-     */
422
-    public function wp_user()
423
-    {
424
-        $event = $this->event();
425
-        if ($event instanceof EE_Event) {
426
-            return $event->wp_user();
427
-        }
428
-        return 0;
429
-    }
430
-
431
-
432
-    /**
433
-     * increments this registration's related ticket sold and corresponding datetime sold values
434
-     *
435
-     * @return void
436
-     * @throws DomainException
437
-     * @throws EE_Error
438
-     * @throws EntityNotFoundException
439
-     * @throws InvalidArgumentException
440
-     * @throws InvalidDataTypeException
441
-     * @throws InvalidInterfaceException
442
-     * @throws ReflectionException
443
-     * @throws UnexpectedEntityException
444
-     */
445
-    private function reserveRegistrationSpace()
446
-    {
447
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
448
-        // so stop tracking that this reg has a ticket reserved
449
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
-        $ticket = $this->ticket();
451
-        $ticket->increaseSold();
452
-        // possibly set event status to sold out
453
-        $this->event()->perform_sold_out_status_check();
454
-    }
455
-
456
-
457
-    /**
458
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
-     *
460
-     * @return void
461
-     * @throws DomainException
462
-     * @throws EE_Error
463
-     * @throws EntityNotFoundException
464
-     * @throws InvalidArgumentException
465
-     * @throws InvalidDataTypeException
466
-     * @throws InvalidInterfaceException
467
-     * @throws ReflectionException
468
-     * @throws UnexpectedEntityException
469
-     */
470
-    private function releaseRegistrationSpace()
471
-    {
472
-        $ticket = $this->ticket();
473
-        $ticket->decreaseSold();
474
-        // possibly change event status from sold out back to previous status
475
-        $this->event()->perform_sold_out_status_check();
476
-    }
477
-
478
-
479
-    /**
480
-     * tracks this registration's ticket reservation in extra meta
481
-     * and can increment related ticket reserved and corresponding datetime reserved values
482
-     *
483
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
-    {
493
-        // only reserve ticket if space is not currently reserved
494
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
-            // IMPORTANT !!!
497
-            // although checking $update_ticket first would be more efficient,
498
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
-                && $update_ticket
501
-            ) {
502
-                $ticket = $this->ticket();
503
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
-                $ticket->save();
505
-            }
506
-        }
507
-    }
508
-
509
-
510
-    /**
511
-     * stops tracking this registration's ticket reservation in extra meta
512
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
-     *
514
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
-     * @return void
516
-     * @throws EE_Error
517
-     * @throws InvalidArgumentException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     * @throws ReflectionException
521
-     */
522
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
-    {
524
-        // only release ticket if space is currently reserved
525
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
-            // IMPORTANT !!!
528
-            // although checking $update_ticket first would be more efficient,
529
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
-                && $update_ticket
532
-            ) {
533
-                $ticket = $this->ticket();
534
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
-            }
536
-        }
537
-    }
538
-
539
-
540
-    /**
541
-     * Set Attendee ID
542
-     *
543
-     * @param        int $ATT_ID Attendee ID
544
-     * @throws EE_Error
545
-     * @throws RuntimeException
546
-     */
547
-    public function set_attendee_id($ATT_ID = 0)
548
-    {
549
-        $this->set('ATT_ID', $ATT_ID);
550
-    }
551
-
552
-
553
-    /**
554
-     *        Set Transaction ID
555
-     *
556
-     * @param        int $TXN_ID Transaction ID
557
-     * @throws EE_Error
558
-     * @throws RuntimeException
559
-     */
560
-    public function set_transaction_id($TXN_ID = 0)
561
-    {
562
-        $this->set('TXN_ID', $TXN_ID);
563
-    }
564
-
565
-
566
-    /**
567
-     *        Set Session
568
-     *
569
-     * @param    string $REG_session PHP Session ID
570
-     * @throws EE_Error
571
-     * @throws RuntimeException
572
-     */
573
-    public function set_session($REG_session = '')
574
-    {
575
-        $this->set('REG_session', $REG_session);
576
-    }
577
-
578
-
579
-    /**
580
-     *        Set Registration URL Link
581
-     *
582
-     * @param    string $REG_url_link Registration URL Link
583
-     * @throws EE_Error
584
-     * @throws RuntimeException
585
-     */
586
-    public function set_reg_url_link($REG_url_link = '')
587
-    {
588
-        $this->set('REG_url_link', $REG_url_link);
589
-    }
590
-
591
-
592
-    /**
593
-     *        Set Attendee Counter
594
-     *
595
-     * @param        int $REG_count Primary Attendee
596
-     * @throws EE_Error
597
-     * @throws RuntimeException
598
-     */
599
-    public function set_count($REG_count = 1)
600
-    {
601
-        $this->set('REG_count', $REG_count);
602
-    }
603
-
604
-
605
-    /**
606
-     *        Set Group Size
607
-     *
608
-     * @param        boolean $REG_group_size Group Registration
609
-     * @throws EE_Error
610
-     * @throws RuntimeException
611
-     */
612
-    public function set_group_size($REG_group_size = false)
613
-    {
614
-        $this->set('REG_group_size', $REG_group_size);
615
-    }
616
-
617
-
618
-    /**
619
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
-     *    EEM_Registration::status_id_not_approved
621
-     *
622
-     * @return        boolean
623
-     */
624
-    public function is_not_approved()
625
-    {
626
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
-    }
628
-
629
-
630
-    /**
631
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
-     *    EEM_Registration::status_id_pending_payment
633
-     *
634
-     * @return        boolean
635
-     */
636
-    public function is_pending_payment()
637
-    {
638
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
-    }
640
-
641
-
642
-    /**
643
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
-     *
645
-     * @return        boolean
646
-     */
647
-    public function is_approved()
648
-    {
649
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
-    }
651
-
652
-
653
-    /**
654
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
-     *
656
-     * @return        boolean
657
-     */
658
-    public function is_cancelled()
659
-    {
660
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
-    }
662
-
663
-
664
-    /**
665
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
-     *
667
-     * @return        boolean
668
-     */
669
-    public function is_declined()
670
-    {
671
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
-    }
673
-
674
-
675
-    /**
676
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
-     *    EEM_Registration::status_id_incomplete
678
-     *
679
-     * @return        boolean
680
-     */
681
-    public function is_incomplete()
682
-    {
683
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
-    }
685
-
686
-
687
-    /**
688
-     *        Set Registration Date
689
-     *
690
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
-     *                                                 Date
692
-     * @throws EE_Error
693
-     * @throws RuntimeException
694
-     */
695
-    public function set_reg_date($REG_date = false)
696
-    {
697
-        $this->set('REG_date', $REG_date);
698
-    }
699
-
700
-
701
-    /**
702
-     *    Set final price owing for this registration after all ticket/price modifications
703
-     *
704
-     * @access    public
705
-     * @param    float $REG_final_price
706
-     * @throws EE_Error
707
-     * @throws RuntimeException
708
-     */
709
-    public function set_final_price($REG_final_price = 0.00)
710
-    {
711
-        $this->set('REG_final_price', $REG_final_price);
712
-    }
713
-
714
-
715
-    /**
716
-     *    Set amount paid towards this registration's final price
717
-     *
718
-     * @access    public
719
-     * @param    float $REG_paid
720
-     * @throws EE_Error
721
-     * @throws RuntimeException
722
-     */
723
-    public function set_paid($REG_paid = 0.00)
724
-    {
725
-        $this->set('REG_paid', $REG_paid);
726
-    }
727
-
728
-
729
-    /**
730
-     *        Attendee Is Going
731
-     *
732
-     * @param        boolean $REG_att_is_going Attendee Is Going
733
-     * @throws EE_Error
734
-     * @throws RuntimeException
735
-     */
736
-    public function set_att_is_going($REG_att_is_going = false)
737
-    {
738
-        $this->set('REG_att_is_going', $REG_att_is_going);
739
-    }
740
-
741
-
742
-    /**
743
-     * Gets the related attendee
744
-     *
745
-     * @return EE_Attendee
746
-     * @throws EE_Error
747
-     */
748
-    public function attendee()
749
-    {
750
-        return $this->get_first_related('Attendee');
751
-    }
752
-
753
-    /**
754
-     * Gets the name of the attendee.
755
-     * @since $VID:$
756
-     * @param bool $apply_html_entities set to true if you want to use HTML entities.
757
-     * @return string
758
-     * @throws EE_Error
759
-     * @throws InvalidArgumentException
760
-     * @throws InvalidDataTypeException
761
-     * @throws InvalidInterfaceException
762
-     * @throws ReflectionException
763
-     */
764
-    public function attendeeName($apply_html_entities = false)
765
-    {
766
-        $attendee = $this->get_first_related('Attendee');
767
-        if ($attendee instanceof EE_Attendee) {
768
-            $attendee_name = $attendee->full_name($apply_html_entities);
769
-        } else {
770
-            $attendee_name = esc_html__('Unknown', 'event_espresso');
771
-        }
772
-        return $attendee_name;
773
-    }
774
-
775
-
776
-    /**
777
-     *        get Event ID
778
-     */
779
-    public function event_ID()
780
-    {
781
-        return $this->get('EVT_ID');
782
-    }
783
-
784
-
785
-    /**
786
-     *        get Event ID
787
-     */
788
-    public function event_name()
789
-    {
790
-        $event = $this->event_obj();
791
-        if ($event) {
792
-            return $event->name();
793
-        } else {
794
-            return null;
795
-        }
796
-    }
797
-
798
-
799
-    /**
800
-     * Fetches the event this registration is for
801
-     *
802
-     * @return EE_Event
803
-     * @throws EE_Error
804
-     */
805
-    public function event_obj()
806
-    {
807
-        return $this->get_first_related('Event');
808
-    }
809
-
810
-
811
-    /**
812
-     *        get Attendee ID
813
-     */
814
-    public function attendee_ID()
815
-    {
816
-        return $this->get('ATT_ID');
817
-    }
818
-
819
-
820
-    /**
821
-     *        get PHP Session ID
822
-     */
823
-    public function session_ID()
824
-    {
825
-        return $this->get('REG_session');
826
-    }
827
-
828
-
829
-    /**
830
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
831
-     *
832
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
833
-     * @return string
834
-     */
835
-    public function receipt_url($messenger = 'html')
836
-    {
837
-
838
-        /**
839
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
840
-         * already in use on old system.  If there is then we just return the standard url for it.
841
-         *
842
-         * @since 4.5.0
843
-         */
844
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
845
-        $has_custom = EEH_Template::locate_template(
846
-            $template_relative_path,
847
-            array(),
848
-            true,
849
-            true,
850
-            true
851
-        );
852
-
853
-        if ($has_custom) {
854
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
855
-        }
856
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
857
-    }
858
-
859
-
860
-    /**
861
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
862
-     *
863
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
864
-     * @return string
865
-     * @throws EE_Error
866
-     */
867
-    public function invoice_url($messenger = 'html')
868
-    {
869
-        /**
870
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
871
-         * already in use on old system.  If there is then we just return the standard url for it.
872
-         *
873
-         * @since 4.5.0
874
-         */
875
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
876
-        $has_custom = EEH_Template::locate_template(
877
-            $template_relative_path,
878
-            array(),
879
-            true,
880
-            true,
881
-            true
882
-        );
883
-
884
-        if ($has_custom) {
885
-            if ($messenger == 'html') {
886
-                return $this->invoice_url('launch');
887
-            }
888
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
889
-
890
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
891
-            if ($messenger == 'html') {
892
-                $query_args['html'] = true;
893
-            }
894
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
895
-        }
896
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
897
-    }
898
-
899
-
900
-    /**
901
-     * get Registration URL Link
902
-     *
903
-     * @access public
904
-     * @return string
905
-     * @throws EE_Error
906
-     */
907
-    public function reg_url_link()
908
-    {
909
-        return (string) $this->get('REG_url_link');
910
-    }
911
-
912
-
913
-    /**
914
-     * Echoes out invoice_url()
915
-     *
916
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
917
-     * @return void
918
-     * @throws EE_Error
919
-     */
920
-    public function e_invoice_url($type = 'launch')
921
-    {
922
-        echo $this->invoice_url($type);
923
-    }
924
-
925
-
926
-    /**
927
-     * Echoes out payment_overview_url
928
-     */
929
-    public function e_payment_overview_url()
930
-    {
931
-        echo $this->payment_overview_url();
932
-    }
933
-
934
-
935
-    /**
936
-     * Gets the URL for the checkout payment options reg step
937
-     * with this registration's REG_url_link added as a query parameter
938
-     *
939
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
940
-     *                            payment overview url.
941
-     * @return string
942
-     * @throws InvalidInterfaceException
943
-     * @throws InvalidDataTypeException
944
-     * @throws EE_Error
945
-     * @throws InvalidArgumentException
946
-     */
947
-    public function payment_overview_url($clear_session = false)
948
-    {
949
-        return add_query_arg(
950
-            (array) apply_filters(
951
-                'FHEE__EE_Registration__payment_overview_url__query_args',
952
-                array(
953
-                    'e_reg_url_link' => $this->reg_url_link(),
954
-                    'step'           => 'payment_options',
955
-                    'revisit'        => true,
956
-                    'clear_session'  => (bool) $clear_session,
957
-                ),
958
-                $this
959
-            ),
960
-            EE_Registry::instance()->CFG->core->reg_page_url()
961
-        );
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets the URL for the checkout attendee information reg step
967
-     * with this registration's REG_url_link added as a query parameter
968
-     *
969
-     * @return string
970
-     * @throws InvalidInterfaceException
971
-     * @throws InvalidDataTypeException
972
-     * @throws EE_Error
973
-     * @throws InvalidArgumentException
974
-     */
975
-    public function edit_attendee_information_url()
976
-    {
977
-        return add_query_arg(
978
-            (array) apply_filters(
979
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
980
-                array(
981
-                    'e_reg_url_link' => $this->reg_url_link(),
982
-                    'step'           => 'attendee_information',
983
-                    'revisit'        => true,
984
-                ),
985
-                $this
986
-            ),
987
-            EE_Registry::instance()->CFG->core->reg_page_url()
988
-        );
989
-    }
990
-
991
-
992
-    /**
993
-     * Simply generates and returns the appropriate admin_url link to edit this registration
994
-     *
995
-     * @return string
996
-     * @throws EE_Error
997
-     */
998
-    public function get_admin_edit_url()
999
-    {
1000
-        return EEH_URL::add_query_args_and_nonce(
1001
-            array(
1002
-                'page'    => 'espresso_registrations',
1003
-                'action'  => 'view_registration',
1004
-                '_REG_ID' => $this->ID(),
1005
-            ),
1006
-            admin_url('admin.php')
1007
-        );
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     *    is_primary_registrant?
1013
-     */
1014
-    public function is_primary_registrant()
1015
-    {
1016
-        return $this->get('REG_count') === 1 ? true : false;
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * This returns the primary registration object for this registration group (which may be this object).
1022
-     *
1023
-     * @return EE_Registration
1024
-     * @throws EE_Error
1025
-     */
1026
-    public function get_primary_registration()
1027
-    {
1028
-        if ($this->is_primary_registrant()) {
1029
-            return $this;
1030
-        }
1031
-
1032
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1033
-        /** @var EE_Registration $primary_registrant */
1034
-        $primary_registrant = EEM_Registration::instance()->get_one(
1035
-            array(
1036
-                array(
1037
-                    'TXN_ID'    => $this->transaction_ID(),
1038
-                    'REG_count' => 1,
1039
-                ),
1040
-            )
1041
-        );
1042
-        return $primary_registrant;
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     *        get  Attendee Number
1048
-     *
1049
-     * @access        public
1050
-     */
1051
-    public function count()
1052
-    {
1053
-        return $this->get('REG_count');
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     *        get Group Size
1059
-     */
1060
-    public function group_size()
1061
-    {
1062
-        return $this->get('REG_group_size');
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     *        get Registration Date
1068
-     */
1069
-    public function date()
1070
-    {
1071
-        return $this->get('REG_date');
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * gets a pretty date
1077
-     *
1078
-     * @param string $date_format
1079
-     * @param string $time_format
1080
-     * @return string
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function pretty_date($date_format = null, $time_format = null)
1084
-    {
1085
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * final_price
1091
-     * the registration's share of the transaction total, so that the
1092
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1093
-     *
1094
-     * @return float
1095
-     * @throws EE_Error
1096
-     */
1097
-    public function final_price()
1098
-    {
1099
-        return $this->get('REG_final_price');
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * pretty_final_price
1105
-     *  final price as formatted string, with correct decimal places and currency symbol
1106
-     *
1107
-     * @return string
1108
-     * @throws EE_Error
1109
-     */
1110
-    public function pretty_final_price()
1111
-    {
1112
-        return $this->get_pretty('REG_final_price');
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * get paid (yeah)
1118
-     *
1119
-     * @return float
1120
-     * @throws EE_Error
1121
-     */
1122
-    public function paid()
1123
-    {
1124
-        return $this->get('REG_paid');
1125
-    }
1126
-
1127
-
1128
-    /**
1129
-     * pretty_paid
1130
-     *
1131
-     * @return float
1132
-     * @throws EE_Error
1133
-     */
1134
-    public function pretty_paid()
1135
-    {
1136
-        return $this->get_pretty('REG_paid');
1137
-    }
1138
-
1139
-
1140
-    /**
1141
-     * owes_monies_and_can_pay
1142
-     * whether or not this registration has monies owing and it's' status allows payment
1143
-     *
1144
-     * @param array $requires_payment
1145
-     * @return bool
1146
-     * @throws EE_Error
1147
-     */
1148
-    public function owes_monies_and_can_pay($requires_payment = array())
1149
-    {
1150
-        // these reg statuses require payment (if event is not free)
1151
-        $requires_payment = ! empty($requires_payment)
1152
-            ? $requires_payment
1153
-            : EEM_Registration::reg_statuses_that_allow_payment();
1154
-        if (in_array($this->status_ID(), $requires_payment) &&
1155
-            $this->final_price() != 0 &&
1156
-            $this->final_price() != $this->paid()
1157
-        ) {
1158
-            return true;
1159
-        } else {
1160
-            return false;
1161
-        }
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Prints out the return value of $this->pretty_status()
1167
-     *
1168
-     * @param bool $show_icons
1169
-     * @return void
1170
-     * @throws EE_Error
1171
-     */
1172
-    public function e_pretty_status($show_icons = false)
1173
-    {
1174
-        echo $this->pretty_status($show_icons);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Returns a nice version of the status for displaying to customers
1180
-     *
1181
-     * @param bool $show_icons
1182
-     * @return string
1183
-     * @throws EE_Error
1184
-     */
1185
-    public function pretty_status($show_icons = false)
1186
-    {
1187
-        $status = EEM_Status::instance()->localized_status(
1188
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1189
-            false,
1190
-            'sentence'
1191
-        );
1192
-        $icon = '';
1193
-        switch ($this->status_ID()) {
1194
-            case EEM_Registration::status_id_approved:
1195
-                $icon = $show_icons
1196
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1197
-                    : '';
1198
-                break;
1199
-            case EEM_Registration::status_id_pending_payment:
1200
-                $icon = $show_icons
1201
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1202
-                    : '';
1203
-                break;
1204
-            case EEM_Registration::status_id_not_approved:
1205
-                $icon = $show_icons
1206
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1207
-                    : '';
1208
-                break;
1209
-            case EEM_Registration::status_id_cancelled:
1210
-                $icon = $show_icons
1211
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1212
-                    : '';
1213
-                break;
1214
-            case EEM_Registration::status_id_incomplete:
1215
-                $icon = $show_icons
1216
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1217
-                    : '';
1218
-                break;
1219
-            case EEM_Registration::status_id_declined:
1220
-                $icon = $show_icons
1221
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1222
-                    : '';
1223
-                break;
1224
-            case EEM_Registration::status_id_wait_list:
1225
-                $icon = $show_icons
1226
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1227
-                    : '';
1228
-                break;
1229
-        }
1230
-        return $icon . $status[ $this->status_ID() ];
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     *        get Attendee Is Going
1236
-     */
1237
-    public function att_is_going()
1238
-    {
1239
-        return $this->get('REG_att_is_going');
1240
-    }
1241
-
1242
-
1243
-    /**
1244
-     * Gets related answers
1245
-     *
1246
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1247
-     * @return EE_Answer[]
1248
-     * @throws EE_Error
1249
-     */
1250
-    public function answers($query_params = null)
1251
-    {
1252
-        return $this->get_many_related('Answer', $query_params);
1253
-    }
1254
-
1255
-
1256
-    /**
1257
-     * Gets the registration's answer value to the specified question
1258
-     * (either the question's ID or a question object)
1259
-     *
1260
-     * @param EE_Question|int $question
1261
-     * @param bool            $pretty_value
1262
-     * @return array|string if pretty_value= true, the result will always be a string
1263
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1264
-     * will convert it into some kind of string)
1265
-     * @throws EE_Error
1266
-     */
1267
-    public function answer_value_to_question($question, $pretty_value = true)
1268
-    {
1269
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1270
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * question_groups
1276
-     * returns an array of EE_Question_Group objects for this registration
1277
-     *
1278
-     * @return EE_Question_Group[]
1279
-     * @throws EE_Error
1280
-     * @throws InvalidArgumentException
1281
-     * @throws InvalidDataTypeException
1282
-     * @throws InvalidInterfaceException
1283
-     * @throws ReflectionException
1284
-     */
1285
-    public function question_groups()
1286
-    {
1287
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * count_question_groups
1293
-     * returns a count of the number of EE_Question_Group objects for this registration
1294
-     *
1295
-     * @return int
1296
-     * @throws EE_Error
1297
-     * @throws EntityNotFoundException
1298
-     * @throws InvalidArgumentException
1299
-     * @throws InvalidDataTypeException
1300
-     * @throws InvalidInterfaceException
1301
-     * @throws ReflectionException
1302
-     */
1303
-    public function count_question_groups()
1304
-    {
1305
-        return EEM_Event::instance()->count_related(
1306
-            $this->event_ID(),
1307
-            'Question_Group',
1308
-            [
1309
-                [
1310
-                    'Event_Question_Group.'
1311
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1312
-                ]
1313
-            ]
1314
-        );
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * Returns the registration date in the 'standard' string format
1320
-     * (function may be improved in the future to allow for different formats and timezones)
1321
-     *
1322
-     * @return string
1323
-     * @throws EE_Error
1324
-     */
1325
-    public function reg_date()
1326
-    {
1327
-        return $this->get_datetime('REG_date');
1328
-    }
1329
-
1330
-
1331
-    /**
1332
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1333
-     * the ticket this registration purchased, or the datetime they have registered
1334
-     * to attend)
1335
-     *
1336
-     * @return EE_Datetime_Ticket
1337
-     * @throws EE_Error
1338
-     */
1339
-    public function datetime_ticket()
1340
-    {
1341
-        return $this->get_first_related('Datetime_Ticket');
1342
-    }
1343
-
1344
-
1345
-    /**
1346
-     * Sets the registration's datetime_ticket.
1347
-     *
1348
-     * @param EE_Datetime_Ticket $datetime_ticket
1349
-     * @return EE_Datetime_Ticket
1350
-     * @throws EE_Error
1351
-     */
1352
-    public function set_datetime_ticket($datetime_ticket)
1353
-    {
1354
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1355
-    }
1356
-
1357
-    /**
1358
-     * Gets deleted
1359
-     *
1360
-     * @return bool
1361
-     * @throws EE_Error
1362
-     */
1363
-    public function deleted()
1364
-    {
1365
-        return $this->get('REG_deleted');
1366
-    }
1367
-
1368
-    /**
1369
-     * Sets deleted
1370
-     *
1371
-     * @param boolean $deleted
1372
-     * @return bool
1373
-     * @throws EE_Error
1374
-     * @throws RuntimeException
1375
-     */
1376
-    public function set_deleted($deleted)
1377
-    {
1378
-        if ($deleted) {
1379
-            $this->delete();
1380
-        } else {
1381
-            $this->restore();
1382
-        }
1383
-    }
1384
-
1385
-
1386
-    /**
1387
-     * Get the status object of this object
1388
-     *
1389
-     * @return EE_Status
1390
-     * @throws EE_Error
1391
-     */
1392
-    public function status_obj()
1393
-    {
1394
-        return $this->get_first_related('Status');
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * Returns the number of times this registration has checked into any of the datetimes
1400
-     * its available for
1401
-     *
1402
-     * @return int
1403
-     * @throws EE_Error
1404
-     */
1405
-    public function count_checkins()
1406
-    {
1407
-        return $this->get_model()->count_related($this, 'Checkin');
1408
-    }
1409
-
1410
-
1411
-    /**
1412
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1413
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1414
-     *
1415
-     * @return int
1416
-     * @throws EE_Error
1417
-     */
1418
-    public function count_checkins_not_checkedout()
1419
-    {
1420
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1426
-     *
1427
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1428
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1429
-     *                                          consider registration status as well as datetime access.
1430
-     * @return bool
1431
-     * @throws EE_Error
1432
-     */
1433
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1434
-    {
1435
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1436
-
1437
-        // first check registration status
1438
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1439
-            return false;
1440
-        }
1441
-        // is there a datetime ticket that matches this dtt_ID?
1442
-        if (! (EEM_Datetime_Ticket::instance()->exists(
1443
-            array(
1444
-                array(
1445
-                    'TKT_ID' => $this->get('TKT_ID'),
1446
-                    'DTT_ID' => $DTT_ID,
1447
-                ),
1448
-            )
1449
-        ))
1450
-        ) {
1451
-            return false;
1452
-        }
1453
-
1454
-        // final check is against TKT_uses
1455
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1461
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1462
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1463
-     * then return false.  Otherwise return true.
1464
-     *
1465
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1466
-     * @return bool true means can checkin.  false means cannot checkin.
1467
-     * @throws EE_Error
1468
-     */
1469
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1470
-    {
1471
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1472
-
1473
-        if (! $DTT_ID) {
1474
-            return false;
1475
-        }
1476
-
1477
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1478
-
1479
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1480
-        // check-in or not.
1481
-        if (! $max_uses || $max_uses === EE_INF) {
1482
-            return true;
1483
-        }
1484
-
1485
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1486
-        // go ahead and toggle.
1487
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1488
-            return true;
1489
-        }
1490
-
1491
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1492
-        // disallows further check-ins.
1493
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1494
-            array(
1495
-                array(
1496
-                    'REG_ID' => $this->ID(),
1497
-                    'CHK_in' => true,
1498
-                ),
1499
-            ),
1500
-            'DTT_ID',
1501
-            true
1502
-        );
1503
-        // checkins have already reached their max number of uses
1504
-        // so registrant can NOT checkin
1505
-        if ($count_unique_dtt_checkins >= $max_uses) {
1506
-            EE_Error::add_error(
1507
-                esc_html__(
1508
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1509
-                    'event_espresso'
1510
-                ),
1511
-                __FILE__,
1512
-                __FUNCTION__,
1513
-                __LINE__
1514
-            );
1515
-            return false;
1516
-        }
1517
-        return true;
1518
-    }
1519
-
1520
-
1521
-    /**
1522
-     * toggle Check-in status for this registration
1523
-     * Check-ins are toggled in the following order:
1524
-     * never checked in -> checked in
1525
-     * checked in -> checked out
1526
-     * checked out -> checked in
1527
-     *
1528
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1529
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1530
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1531
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1532
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1533
-     * @throws EE_Error
1534
-     */
1535
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1536
-    {
1537
-        if (empty($DTT_ID)) {
1538
-            $datetime = $this->get_latest_related_datetime();
1539
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1540
-            // verify the registration can checkin for the given DTT_ID
1541
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1542
-            EE_Error::add_error(
1543
-                sprintf(
1544
-                    esc_html__(
1545
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1546
-                        'event_espresso'
1547
-                    ),
1548
-                    $this->ID(),
1549
-                    $DTT_ID
1550
-                ),
1551
-                __FILE__,
1552
-                __FUNCTION__,
1553
-                __LINE__
1554
-            );
1555
-            return false;
1556
-        }
1557
-        $status_paths = array(
1558
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1559
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1560
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1561
-        );
1562
-        // start by getting the current status so we know what status we'll be changing to.
1563
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1564
-        $status_to = $status_paths[ $cur_status ];
1565
-        // database only records true for checked IN or false for checked OUT
1566
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1567
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1568
-        // add relation - note Check-ins are always creating new rows
1569
-        // because we are keeping track of Check-ins over time.
1570
-        // Eventually we'll probably want to show a list table
1571
-        // for the individual Check-ins so that they can be managed.
1572
-        $checkin = EE_Checkin::new_instance(
1573
-            array(
1574
-                'REG_ID' => $this->ID(),
1575
-                'DTT_ID' => $DTT_ID,
1576
-                'CHK_in' => $new_status,
1577
-            )
1578
-        );
1579
-        // if the record could not be saved then return false
1580
-        if ($checkin->save() === 0) {
1581
-            if (WP_DEBUG) {
1582
-                global $wpdb;
1583
-                $error = sprintf(
1584
-                    esc_html__(
1585
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1586
-                        'event_espresso'
1587
-                    ),
1588
-                    '<br />',
1589
-                    $wpdb->last_error
1590
-                );
1591
-            } else {
1592
-                $error = esc_html__(
1593
-                    'Registration check in update failed because of an unknown database error',
1594
-                    'event_espresso'
1595
-                );
1596
-            }
1597
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1598
-            return false;
1599
-        }
1600
-        return $status_to;
1601
-    }
1602
-
1603
-
1604
-    /**
1605
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1606
-     * "Latest" is defined by the `DTT_EVT_start` column.
1607
-     *
1608
-     * @return EE_Datetime|null
1609
-     * @throws EE_Error
1610
-     */
1611
-    public function get_latest_related_datetime()
1612
-    {
1613
-        return EEM_Datetime::instance()->get_one(
1614
-            array(
1615
-                array(
1616
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1617
-                ),
1618
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1619
-            )
1620
-        );
1621
-    }
1622
-
1623
-
1624
-    /**
1625
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1626
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1627
-     *
1628
-     * @throws EE_Error
1629
-     */
1630
-    public function get_earliest_related_datetime()
1631
-    {
1632
-        return EEM_Datetime::instance()->get_one(
1633
-            array(
1634
-                array(
1635
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1636
-                ),
1637
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1638
-            )
1639
-        );
1640
-    }
1641
-
1642
-
1643
-    /**
1644
-     * This method simply returns the check-in status for this registration and the given datetime.
1645
-     * If neither the datetime nor the checkin values are provided as arguments,
1646
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1647
-     *
1648
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1649
-     *                            (if empty we'll get the primary datetime for
1650
-     *                            this registration (via event) and use it's ID);
1651
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1652
-     *
1653
-     * @return int                Integer representing Check-in status.
1654
-     * @throws EE_Error
1655
-     */
1656
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1657
-    {
1658
-        $checkin_query_params = array(
1659
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1660
-        );
1661
-
1662
-        if ($DTT_ID > 0) {
1663
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1664
-        }
1665
-
1666
-        // get checkin object (if exists)
1667
-        $checkin = $checkin instanceof EE_Checkin
1668
-            ? $checkin
1669
-            : $this->get_first_related('Checkin', $checkin_query_params);
1670
-        if ($checkin instanceof EE_Checkin) {
1671
-            if ($checkin->get('CHK_in')) {
1672
-                return EE_Checkin::status_checked_in; // checked in
1673
-            }
1674
-            return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1675
-        }
1676
-        return EE_Checkin::status_checked_never; // never been checked in
1677
-    }
1678
-
1679
-
1680
-    /**
1681
-     * This method returns a localized message for the toggled Check-in message.
1682
-     *
1683
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1684
-     *                     then it is assumed Check-in for primary datetime was toggled.
1685
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1686
-     *                     message can be customized with the attendee name.
1687
-     * @return string internationalized message
1688
-     * @throws EE_Error
1689
-     */
1690
-    public function get_checkin_msg($DTT_ID, $error = false)
1691
-    {
1692
-        // let's get the attendee first so we can include the name of the attendee
1693
-        $attendee = $this->get_first_related('Attendee');
1694
-        if ($attendee instanceof EE_Attendee) {
1695
-            if ($error) {
1696
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1697
-            }
1698
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1699
-            // what is the status message going to be?
1700
-            switch ($cur_status) {
1701
-                case EE_Checkin::status_checked_never:
1702
-                    return sprintf(
1703
-                        __("%s has been removed from Check-in records", "event_espresso"),
1704
-                        $attendee->full_name()
1705
-                    );
1706
-                    break;
1707
-                case EE_Checkin::status_checked_in:
1708
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1709
-                    break;
1710
-                case EE_Checkin::status_checked_out:
1711
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1712
-                    break;
1713
-            }
1714
-        }
1715
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1716
-    }
1717
-
1718
-
1719
-    /**
1720
-     * Returns the related EE_Transaction to this registration
1721
-     *
1722
-     * @return EE_Transaction
1723
-     * @throws EE_Error
1724
-     * @throws EntityNotFoundException
1725
-     */
1726
-    public function transaction()
1727
-    {
1728
-        $transaction = $this->get_first_related('Transaction');
1729
-        if (! $transaction instanceof \EE_Transaction) {
1730
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1731
-        }
1732
-        return $transaction;
1733
-    }
1734
-
1735
-
1736
-    /**
1737
-     *        get Registration Code
1738
-     */
1739
-    public function reg_code()
1740
-    {
1741
-        return $this->get('REG_code');
1742
-    }
1743
-
1744
-
1745
-    /**
1746
-     *        get Transaction ID
1747
-     */
1748
-    public function transaction_ID()
1749
-    {
1750
-        return $this->get('TXN_ID');
1751
-    }
1752
-
1753
-
1754
-    /**
1755
-     * @return int
1756
-     * @throws EE_Error
1757
-     */
1758
-    public function ticket_ID()
1759
-    {
1760
-        return $this->get('TKT_ID');
1761
-    }
1762
-
1763
-
1764
-    /**
1765
-     *        Set Registration Code
1766
-     *
1767
-     * @access    public
1768
-     * @param    string  $REG_code Registration Code
1769
-     * @param    boolean $use_default
1770
-     * @throws EE_Error
1771
-     */
1772
-    public function set_reg_code($REG_code, $use_default = false)
1773
-    {
1774
-        if (empty($REG_code)) {
1775
-            EE_Error::add_error(
1776
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1777
-                __FILE__,
1778
-                __FUNCTION__,
1779
-                __LINE__
1780
-            );
1781
-            return;
1782
-        }
1783
-        if (! $this->reg_code()) {
1784
-            parent::set('REG_code', $REG_code, $use_default);
1785
-        } else {
1786
-            EE_Error::doing_it_wrong(
1787
-                __CLASS__ . '::' . __FUNCTION__,
1788
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1789
-                '4.6.0'
1790
-            );
1791
-        }
1792
-    }
1793
-
1794
-
1795
-    /**
1796
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1797
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1798
-     *    $registration->transaction()->registrations();
1799
-     *
1800
-     * @since 4.5.0
1801
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1802
-     * @throws EE_Error
1803
-     */
1804
-    public function get_all_other_registrations_in_group()
1805
-    {
1806
-        if ($this->group_size() < 2) {
1807
-            return array();
1808
-        }
1809
-
1810
-        $query[0] = array(
1811
-            'TXN_ID' => $this->transaction_ID(),
1812
-            'REG_ID' => array('!=', $this->ID()),
1813
-            'TKT_ID' => $this->ticket_ID(),
1814
-        );
1815
-        /** @var EE_Registration[] $registrations */
1816
-        $registrations = $this->get_model()->get_all($query);
1817
-        return $registrations;
1818
-    }
1819
-
1820
-    /**
1821
-     * Return the link to the admin details for the object.
1822
-     *
1823
-     * @return string
1824
-     * @throws EE_Error
1825
-     */
1826
-    public function get_admin_details_link()
1827
-    {
1828
-        EE_Registry::instance()->load_helper('URL');
1829
-        return EEH_URL::add_query_args_and_nonce(
1830
-            array(
1831
-                'page'    => 'espresso_registrations',
1832
-                'action'  => 'view_registration',
1833
-                '_REG_ID' => $this->ID(),
1834
-            ),
1835
-            admin_url('admin.php')
1836
-        );
1837
-    }
1838
-
1839
-    /**
1840
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1841
-     *
1842
-     * @return string
1843
-     * @throws EE_Error
1844
-     */
1845
-    public function get_admin_edit_link()
1846
-    {
1847
-        return $this->get_admin_details_link();
1848
-    }
1849
-
1850
-    /**
1851
-     * Returns the link to a settings page for the object.
1852
-     *
1853
-     * @return string
1854
-     * @throws EE_Error
1855
-     */
1856
-    public function get_admin_settings_link()
1857
-    {
1858
-        return $this->get_admin_details_link();
1859
-    }
1860
-
1861
-    /**
1862
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1863
-     *
1864
-     * @return string
1865
-     */
1866
-    public function get_admin_overview_link()
1867
-    {
1868
-        EE_Registry::instance()->load_helper('URL');
1869
-        return EEH_URL::add_query_args_and_nonce(
1870
-            array(
1871
-                'page' => 'espresso_registrations',
1872
-            ),
1873
-            admin_url('admin.php')
1874
-        );
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     * @param array $query_params
1880
-     *
1881
-     * @return \EE_Registration[]
1882
-     * @throws EE_Error
1883
-     */
1884
-    public function payments($query_params = array())
1885
-    {
1886
-        return $this->get_many_related('Payment', $query_params);
1887
-    }
1888
-
1889
-
1890
-    /**
1891
-     * @param array $query_params
1892
-     *
1893
-     * @return \EE_Registration_Payment[]
1894
-     * @throws EE_Error
1895
-     */
1896
-    public function registration_payments($query_params = array())
1897
-    {
1898
-        return $this->get_many_related('Registration_Payment', $query_params);
1899
-    }
1900
-
1901
-
1902
-    /**
1903
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1904
-     * Note: if there are no payments on the registration there will be no payment method returned.
1905
-     *
1906
-     * @return EE_Payment_Method|null
1907
-     */
1908
-    public function payment_method()
1909
-    {
1910
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1911
-    }
1912
-
1913
-
1914
-    /**
1915
-     * @return \EE_Line_Item
1916
-     * @throws EntityNotFoundException
1917
-     * @throws EE_Error
1918
-     */
1919
-    public function ticket_line_item()
1920
-    {
1921
-        $ticket = $this->ticket();
1922
-        $transaction = $this->transaction();
1923
-        $line_item = null;
1924
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1925
-            $transaction->total_line_item(),
1926
-            'Ticket',
1927
-            array($ticket->ID())
1928
-        );
1929
-        foreach ($ticket_line_items as $ticket_line_item) {
1930
-            if ($ticket_line_item instanceof \EE_Line_Item
1931
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1932
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1933
-            ) {
1934
-                $line_item = $ticket_line_item;
1935
-                break;
1936
-            }
1937
-        }
1938
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1939
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1940
-        }
1941
-        return $line_item;
1942
-    }
1943
-
1944
-
1945
-    /**
1946
-     * Soft Deletes this model object.
1947
-     *
1948
-     * @return boolean | int
1949
-     * @throws RuntimeException
1950
-     * @throws EE_Error
1951
-     */
1952
-    public function delete()
1953
-    {
1954
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1955
-            $this->set_status(EEM_Registration::status_id_cancelled);
1956
-        }
1957
-        return parent::delete();
1958
-    }
1959
-
1960
-
1961
-    /**
1962
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1963
-     *
1964
-     * @throws EE_Error
1965
-     * @throws RuntimeException
1966
-     */
1967
-    public function restore()
1968
-    {
1969
-        $previous_status = $this->get_extra_meta(
1970
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1971
-            true,
1972
-            EEM_Registration::status_id_cancelled
1973
-        );
1974
-        if ($previous_status) {
1975
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1976
-            $this->set_status($previous_status);
1977
-        }
1978
-        return parent::restore();
1979
-    }
1980
-
1981
-
1982
-    /**
1983
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1984
-     *
1985
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1986
-     *                                           depending on whether the reg status changes to or from "Approved"
1987
-     * @return boolean whether the Registration status was updated
1988
-     * @throws EE_Error
1989
-     * @throws RuntimeException
1990
-     */
1991
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1992
-    {
1993
-        $paid = $this->paid();
1994
-        $price = $this->final_price();
1995
-        switch (true) {
1996
-            // overpaid or paid
1997
-            case EEH_Money::compare_floats($paid, $price, '>'):
1998
-            case EEH_Money::compare_floats($paid, $price):
1999
-                $new_status = EEM_Registration::status_id_approved;
2000
-                break;
2001
-            //  underpaid
2002
-            case EEH_Money::compare_floats($paid, $price, '<'):
2003
-                $new_status = EEM_Registration::status_id_pending_payment;
2004
-                break;
2005
-            // uhhh Houston...
2006
-            default:
2007
-                throw new RuntimeException(
2008
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2009
-                );
2010
-        }
2011
-        if ($new_status !== $this->status_ID()) {
2012
-            if ($trigger_set_status_logic) {
2013
-                return $this->set_status($new_status);
2014
-            }
2015
-            parent::set('STS_ID', $new_status);
2016
-            return true;
2017
-        }
2018
-        return false;
2019
-    }
2020
-
2021
-
2022
-    /*************************** DEPRECATED ***************************/
2023
-
2024
-
2025
-    /**
2026
-     * @deprecated
2027
-     * @since     4.7.0
2028
-     * @access    public
2029
-     */
2030
-    public function price_paid()
2031
-    {
2032
-        EE_Error::doing_it_wrong(
2033
-            'EE_Registration::price_paid()',
2034
-            esc_html__(
2035
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2036
-                'event_espresso'
2037
-            ),
2038
-            '4.7.0'
2039
-        );
2040
-        return $this->final_price();
2041
-    }
2042
-
2043
-
2044
-    /**
2045
-     * @deprecated
2046
-     * @since     4.7.0
2047
-     * @access    public
2048
-     * @param    float $REG_final_price
2049
-     * @throws EE_Error
2050
-     * @throws RuntimeException
2051
-     */
2052
-    public function set_price_paid($REG_final_price = 0.00)
2053
-    {
2054
-        EE_Error::doing_it_wrong(
2055
-            'EE_Registration::set_price_paid()',
2056
-            esc_html__(
2057
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2058
-                'event_espresso'
2059
-            ),
2060
-            '4.7.0'
2061
-        );
2062
-        $this->set_final_price($REG_final_price);
2063
-    }
2064
-
2065
-
2066
-    /**
2067
-     * @deprecated
2068
-     * @since 4.7.0
2069
-     * @return string
2070
-     * @throws EE_Error
2071
-     */
2072
-    public function pretty_price_paid()
2073
-    {
2074
-        EE_Error::doing_it_wrong(
2075
-            'EE_Registration::pretty_price_paid()',
2076
-            esc_html__(
2077
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2078
-                'event_espresso'
2079
-            ),
2080
-            '4.7.0'
2081
-        );
2082
-        return $this->pretty_final_price();
2083
-    }
2084
-
2085
-
2086
-    /**
2087
-     * Gets the primary datetime related to this registration via the related Event to this registration
2088
-     *
2089
-     * @deprecated 4.9.17
2090
-     * @return EE_Datetime
2091
-     * @throws EE_Error
2092
-     * @throws EntityNotFoundException
2093
-     */
2094
-    public function get_related_primary_datetime()
2095
-    {
2096
-        EE_Error::doing_it_wrong(
2097
-            __METHOD__,
2098
-            esc_html__(
2099
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2100
-                'event_espresso'
2101
-            ),
2102
-            '4.9.17',
2103
-            '5.0.0'
2104
-        );
2105
-        return $this->event()->primary_datetime();
2106
-    }
2107
-
2108
-    /**
2109
-     * Returns the contact's name (or "Unknown" if there is no contact.)
2110
-     * @since $VID:$
2111
-     * @return string
2112
-     * @throws EE_Error
2113
-     * @throws InvalidArgumentException
2114
-     * @throws InvalidDataTypeException
2115
-     * @throws InvalidInterfaceException
2116
-     * @throws ReflectionException
2117
-     */
2118
-    public function name()
2119
-    {
2120
-        return $this->attendeeName();
2121
-    }
20
+	/**
21
+	 * Used to reference when a registration has never been checked in.
22
+	 *
23
+	 * @deprecated use \EE_Checkin::status_checked_never instead
24
+	 * @type int
25
+	 */
26
+	const checkin_status_never = 2;
27
+
28
+	/**
29
+	 * Used to reference when a registration has been checked in.
30
+	 *
31
+	 * @deprecated use \EE_Checkin::status_checked_in instead
32
+	 * @type int
33
+	 */
34
+	const checkin_status_in = 1;
35
+
36
+
37
+	/**
38
+	 * Used to reference when a registration has been checked out.
39
+	 *
40
+	 * @deprecated use \EE_Checkin::status_checked_out instead
41
+	 * @type int
42
+	 */
43
+	const checkin_status_out = 0;
44
+
45
+
46
+	/**
47
+	 * extra meta key for tracking reg status os trashed registrations
48
+	 *
49
+	 * @type string
50
+	 */
51
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
+
53
+
54
+	/**
55
+	 * extra meta key for tracking if registration has reserved ticket
56
+	 *
57
+	 * @type string
58
+	 */
59
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values          incoming values
64
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
+	 *                                        used.)
66
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
+	 *                                        date_format and the second value is the time format
68
+	 * @return EE_Registration
69
+	 * @throws EE_Error
70
+	 */
71
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
+	{
73
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Registration
83
+	 */
84
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
+	{
86
+		return new self($props_n_values, true, $timezone);
87
+	}
88
+
89
+
90
+	/**
91
+	 *        Set Event ID
92
+	 *
93
+	 * @param        int $EVT_ID Event ID
94
+	 * @throws EE_Error
95
+	 * @throws RuntimeException
96
+	 */
97
+	public function set_event($EVT_ID = 0)
98
+	{
99
+		$this->set('EVT_ID', $EVT_ID);
100
+	}
101
+
102
+
103
+	/**
104
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
+	 * be routed to internal methods
106
+	 *
107
+	 * @param string $field_name
108
+	 * @param mixed  $field_value
109
+	 * @param bool   $use_default
110
+	 * @throws EE_Error
111
+	 * @throws EntityNotFoundException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws ReflectionException
116
+	 * @throws RuntimeException
117
+	 */
118
+	public function set($field_name, $field_value, $use_default = false)
119
+	{
120
+		switch ($field_name) {
121
+			case 'REG_code':
122
+				if (! empty($field_value) && $this->reg_code() === null) {
123
+					$this->set_reg_code($field_value, $use_default);
124
+				}
125
+				break;
126
+			case 'STS_ID':
127
+				$this->set_status($field_value, $use_default);
128
+				break;
129
+			default:
130
+				parent::set($field_name, $field_value, $use_default);
131
+		}
132
+	}
133
+
134
+
135
+	/**
136
+	 * Set Status ID
137
+	 * updates the registration status and ALSO...
138
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
+	 *
141
+	 * @param string                $new_STS_ID
142
+	 * @param boolean               $use_default
143
+	 * @param ContextInterface|null $context
144
+	 * @return bool
145
+	 * @throws DomainException
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidInterfaceException
151
+	 * @throws ReflectionException
152
+	 * @throws RuntimeException
153
+	 * @throws UnexpectedEntityException
154
+	 */
155
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
+	{
157
+		// get current REG_Status
158
+		$old_STS_ID = $this->status_ID();
159
+		// if status has changed
160
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
+			&& ! empty($old_STS_ID) // and that old status is actually set
162
+			&& ! empty($new_STS_ID) // as well as the new status
163
+			&& $this->ID() // ensure registration is in the db
164
+		) {
165
+			// update internal status first
166
+			parent::set('STS_ID', $new_STS_ID, $use_default);
167
+			// THEN handle other changes that occur when reg status changes
168
+			// TO approved
169
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
+				// reserve a space by incrementing ticket and datetime sold values
171
+				$this->reserveRegistrationSpace();
172
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
+				// OR FROM  approved
174
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
+				// release a space by decrementing ticket and datetime sold values
176
+				$this->releaseRegistrationSpace();
177
+				do_action(
178
+					'AHEE__EE_Registration__set_status__from_approved',
179
+					$this,
180
+					$old_STS_ID,
181
+					$new_STS_ID,
182
+					$context
183
+				);
184
+			}
185
+			// update status
186
+			parent::set('STS_ID', $new_STS_ID, $use_default);
187
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
+			if ($this->statusChangeUpdatesTransaction($context)) {
189
+				$this->updateTransactionAfterStatusChange();
190
+			}
191
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
+			return true;
193
+		}
194
+		// even though the old value matches the new value, it's still good to
195
+		// allow the parent set method to have a say
196
+		parent::set('STS_ID', $new_STS_ID, $use_default);
197
+		return true;
198
+	}
199
+
200
+
201
+	/**
202
+	 * update REGs and TXN when cancelled or declined registrations involved
203
+	 *
204
+	 * @param string                $new_STS_ID
205
+	 * @param string                $old_STS_ID
206
+	 * @param ContextInterface|null $context
207
+	 * @throws EE_Error
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 * @throws ReflectionException
212
+	 * @throws RuntimeException
213
+	 */
214
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
+	{
216
+		// these reg statuses should not be considered in any calculations involving monies owing
217
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
+		// true if registration has been cancelled or declined
219
+		$this->updateIfCanceled(
220
+			$closed_reg_statuses,
221
+			$new_STS_ID,
222
+			$old_STS_ID,
223
+			$context
224
+		);
225
+		$this->updateIfReinstated(
226
+			$closed_reg_statuses,
227
+			$new_STS_ID,
228
+			$old_STS_ID,
229
+			$context
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 * update REGs and TXN when cancelled or declined registrations involved
236
+	 *
237
+	 * @param array                 $closed_reg_statuses
238
+	 * @param string                $new_STS_ID
239
+	 * @param string                $old_STS_ID
240
+	 * @param ContextInterface|null $context
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws InvalidDataTypeException
244
+	 * @throws InvalidInterfaceException
245
+	 * @throws ReflectionException
246
+	 * @throws RuntimeException
247
+	 */
248
+	private function updateIfCanceled(
249
+		array $closed_reg_statuses,
250
+		$new_STS_ID,
251
+		$old_STS_ID,
252
+		ContextInterface $context = null
253
+	) {
254
+		// true if registration has been cancelled or declined
255
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
+		) {
258
+			/** @type EE_Registration_Processor $registration_processor */
259
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
+			/** @type EE_Transaction_Processor $transaction_processor */
261
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
+			// cancelled or declined registration
263
+			$registration_processor->update_registration_after_being_canceled_or_declined(
264
+				$this,
265
+				$closed_reg_statuses
266
+			);
267
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
+				$this,
269
+				$closed_reg_statuses,
270
+				false
271
+			);
272
+			do_action(
273
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
274
+				$this,
275
+				$old_STS_ID,
276
+				$new_STS_ID,
277
+				$context
278
+			);
279
+			return;
280
+		}
281
+	}
282
+
283
+
284
+	/**
285
+	 * update REGs and TXN when cancelled or declined registrations involved
286
+	 *
287
+	 * @param array                 $closed_reg_statuses
288
+	 * @param string                $new_STS_ID
289
+	 * @param string                $old_STS_ID
290
+	 * @param ContextInterface|null $context
291
+	 * @throws EE_Error
292
+	 * @throws InvalidArgumentException
293
+	 * @throws InvalidDataTypeException
294
+	 * @throws InvalidInterfaceException
295
+	 * @throws ReflectionException
296
+	 */
297
+	private function updateIfReinstated(
298
+		array $closed_reg_statuses,
299
+		$new_STS_ID,
300
+		$old_STS_ID,
301
+		ContextInterface $context = null
302
+	) {
303
+		// true if reinstating cancelled or declined registration
304
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
+		) {
307
+			/** @type EE_Registration_Processor $registration_processor */
308
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
+			/** @type EE_Transaction_Processor $transaction_processor */
310
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
+			// reinstating cancelled or declined registration
312
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
+				$this,
314
+				$closed_reg_statuses
315
+			);
316
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
+				$this,
318
+				$closed_reg_statuses,
319
+				false
320
+			);
321
+			do_action(
322
+				'AHEE__EE_Registration__set_status__after_reinstated',
323
+				$this,
324
+				$old_STS_ID,
325
+				$new_STS_ID,
326
+				$context
327
+			);
328
+		}
329
+	}
330
+
331
+
332
+	/**
333
+	 * @param ContextInterface|null $context
334
+	 * @return bool
335
+	 */
336
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
+	{
338
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
339
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
+			array('spco_reg_step_attendee_information_process_registrations'),
341
+			$context,
342
+			$this
343
+		);
344
+		return ! (
345
+			$context instanceof ContextInterface
346
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
+		);
348
+	}
349
+
350
+
351
+	/**
352
+	 * @throws EE_Error
353
+	 * @throws EntityNotFoundException
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws InvalidInterfaceException
357
+	 * @throws ReflectionException
358
+	 * @throws RuntimeException
359
+	 */
360
+	private function updateTransactionAfterStatusChange()
361
+	{
362
+		/** @type EE_Transaction_Payments $transaction_payments */
363
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
+		$this->transaction()->update_status_based_on_total_paid(true);
366
+	}
367
+
368
+
369
+	/**
370
+	 *        get Status ID
371
+	 */
372
+	public function status_ID()
373
+	{
374
+		return $this->get('STS_ID');
375
+	}
376
+
377
+
378
+	/**
379
+	 * Gets the ticket this registration is for
380
+	 *
381
+	 * @param boolean $include_archived whether to include archived tickets or not.
382
+	 *
383
+	 * @return EE_Ticket|EE_Base_Class
384
+	 * @throws EE_Error
385
+	 */
386
+	public function ticket($include_archived = true)
387
+	{
388
+		$query_params = array();
389
+		if ($include_archived) {
390
+			$query_params['default_where_conditions'] = 'none';
391
+		}
392
+		return $this->get_first_related('Ticket', $query_params);
393
+	}
394
+
395
+
396
+	/**
397
+	 * Gets the event this registration is for
398
+	 *
399
+	 * @return EE_Event
400
+	 * @throws EE_Error
401
+	 * @throws EntityNotFoundException
402
+	 */
403
+	public function event()
404
+	{
405
+		$event = $this->get_first_related('Event');
406
+		if (! $event instanceof \EE_Event) {
407
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
408
+		}
409
+		return $event;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
+	 * with the author of the event this registration is for.
416
+	 *
417
+	 * @since 4.5.0
418
+	 * @return int
419
+	 * @throws EE_Error
420
+	 * @throws EntityNotFoundException
421
+	 */
422
+	public function wp_user()
423
+	{
424
+		$event = $this->event();
425
+		if ($event instanceof EE_Event) {
426
+			return $event->wp_user();
427
+		}
428
+		return 0;
429
+	}
430
+
431
+
432
+	/**
433
+	 * increments this registration's related ticket sold and corresponding datetime sold values
434
+	 *
435
+	 * @return void
436
+	 * @throws DomainException
437
+	 * @throws EE_Error
438
+	 * @throws EntityNotFoundException
439
+	 * @throws InvalidArgumentException
440
+	 * @throws InvalidDataTypeException
441
+	 * @throws InvalidInterfaceException
442
+	 * @throws ReflectionException
443
+	 * @throws UnexpectedEntityException
444
+	 */
445
+	private function reserveRegistrationSpace()
446
+	{
447
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
448
+		// so stop tracking that this reg has a ticket reserved
449
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
+		$ticket = $this->ticket();
451
+		$ticket->increaseSold();
452
+		// possibly set event status to sold out
453
+		$this->event()->perform_sold_out_status_check();
454
+	}
455
+
456
+
457
+	/**
458
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
+	 *
460
+	 * @return void
461
+	 * @throws DomainException
462
+	 * @throws EE_Error
463
+	 * @throws EntityNotFoundException
464
+	 * @throws InvalidArgumentException
465
+	 * @throws InvalidDataTypeException
466
+	 * @throws InvalidInterfaceException
467
+	 * @throws ReflectionException
468
+	 * @throws UnexpectedEntityException
469
+	 */
470
+	private function releaseRegistrationSpace()
471
+	{
472
+		$ticket = $this->ticket();
473
+		$ticket->decreaseSold();
474
+		// possibly change event status from sold out back to previous status
475
+		$this->event()->perform_sold_out_status_check();
476
+	}
477
+
478
+
479
+	/**
480
+	 * tracks this registration's ticket reservation in extra meta
481
+	 * and can increment related ticket reserved and corresponding datetime reserved values
482
+	 *
483
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
+	{
493
+		// only reserve ticket if space is not currently reserved
494
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
+			// IMPORTANT !!!
497
+			// although checking $update_ticket first would be more efficient,
498
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
+				&& $update_ticket
501
+			) {
502
+				$ticket = $this->ticket();
503
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
+				$ticket->save();
505
+			}
506
+		}
507
+	}
508
+
509
+
510
+	/**
511
+	 * stops tracking this registration's ticket reservation in extra meta
512
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
+	 *
514
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
+	 * @return void
516
+	 * @throws EE_Error
517
+	 * @throws InvalidArgumentException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 * @throws ReflectionException
521
+	 */
522
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
+	{
524
+		// only release ticket if space is currently reserved
525
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
+			// IMPORTANT !!!
528
+			// although checking $update_ticket first would be more efficient,
529
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
+				&& $update_ticket
532
+			) {
533
+				$ticket = $this->ticket();
534
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
+			}
536
+		}
537
+	}
538
+
539
+
540
+	/**
541
+	 * Set Attendee ID
542
+	 *
543
+	 * @param        int $ATT_ID Attendee ID
544
+	 * @throws EE_Error
545
+	 * @throws RuntimeException
546
+	 */
547
+	public function set_attendee_id($ATT_ID = 0)
548
+	{
549
+		$this->set('ATT_ID', $ATT_ID);
550
+	}
551
+
552
+
553
+	/**
554
+	 *        Set Transaction ID
555
+	 *
556
+	 * @param        int $TXN_ID Transaction ID
557
+	 * @throws EE_Error
558
+	 * @throws RuntimeException
559
+	 */
560
+	public function set_transaction_id($TXN_ID = 0)
561
+	{
562
+		$this->set('TXN_ID', $TXN_ID);
563
+	}
564
+
565
+
566
+	/**
567
+	 *        Set Session
568
+	 *
569
+	 * @param    string $REG_session PHP Session ID
570
+	 * @throws EE_Error
571
+	 * @throws RuntimeException
572
+	 */
573
+	public function set_session($REG_session = '')
574
+	{
575
+		$this->set('REG_session', $REG_session);
576
+	}
577
+
578
+
579
+	/**
580
+	 *        Set Registration URL Link
581
+	 *
582
+	 * @param    string $REG_url_link Registration URL Link
583
+	 * @throws EE_Error
584
+	 * @throws RuntimeException
585
+	 */
586
+	public function set_reg_url_link($REG_url_link = '')
587
+	{
588
+		$this->set('REG_url_link', $REG_url_link);
589
+	}
590
+
591
+
592
+	/**
593
+	 *        Set Attendee Counter
594
+	 *
595
+	 * @param        int $REG_count Primary Attendee
596
+	 * @throws EE_Error
597
+	 * @throws RuntimeException
598
+	 */
599
+	public function set_count($REG_count = 1)
600
+	{
601
+		$this->set('REG_count', $REG_count);
602
+	}
603
+
604
+
605
+	/**
606
+	 *        Set Group Size
607
+	 *
608
+	 * @param        boolean $REG_group_size Group Registration
609
+	 * @throws EE_Error
610
+	 * @throws RuntimeException
611
+	 */
612
+	public function set_group_size($REG_group_size = false)
613
+	{
614
+		$this->set('REG_group_size', $REG_group_size);
615
+	}
616
+
617
+
618
+	/**
619
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
+	 *    EEM_Registration::status_id_not_approved
621
+	 *
622
+	 * @return        boolean
623
+	 */
624
+	public function is_not_approved()
625
+	{
626
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
+	}
628
+
629
+
630
+	/**
631
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
+	 *    EEM_Registration::status_id_pending_payment
633
+	 *
634
+	 * @return        boolean
635
+	 */
636
+	public function is_pending_payment()
637
+	{
638
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
+	}
640
+
641
+
642
+	/**
643
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
+	 *
645
+	 * @return        boolean
646
+	 */
647
+	public function is_approved()
648
+	{
649
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
+	}
651
+
652
+
653
+	/**
654
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
+	 *
656
+	 * @return        boolean
657
+	 */
658
+	public function is_cancelled()
659
+	{
660
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
+	}
662
+
663
+
664
+	/**
665
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
+	 *
667
+	 * @return        boolean
668
+	 */
669
+	public function is_declined()
670
+	{
671
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
+	}
673
+
674
+
675
+	/**
676
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
+	 *    EEM_Registration::status_id_incomplete
678
+	 *
679
+	 * @return        boolean
680
+	 */
681
+	public function is_incomplete()
682
+	{
683
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
+	}
685
+
686
+
687
+	/**
688
+	 *        Set Registration Date
689
+	 *
690
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
+	 *                                                 Date
692
+	 * @throws EE_Error
693
+	 * @throws RuntimeException
694
+	 */
695
+	public function set_reg_date($REG_date = false)
696
+	{
697
+		$this->set('REG_date', $REG_date);
698
+	}
699
+
700
+
701
+	/**
702
+	 *    Set final price owing for this registration after all ticket/price modifications
703
+	 *
704
+	 * @access    public
705
+	 * @param    float $REG_final_price
706
+	 * @throws EE_Error
707
+	 * @throws RuntimeException
708
+	 */
709
+	public function set_final_price($REG_final_price = 0.00)
710
+	{
711
+		$this->set('REG_final_price', $REG_final_price);
712
+	}
713
+
714
+
715
+	/**
716
+	 *    Set amount paid towards this registration's final price
717
+	 *
718
+	 * @access    public
719
+	 * @param    float $REG_paid
720
+	 * @throws EE_Error
721
+	 * @throws RuntimeException
722
+	 */
723
+	public function set_paid($REG_paid = 0.00)
724
+	{
725
+		$this->set('REG_paid', $REG_paid);
726
+	}
727
+
728
+
729
+	/**
730
+	 *        Attendee Is Going
731
+	 *
732
+	 * @param        boolean $REG_att_is_going Attendee Is Going
733
+	 * @throws EE_Error
734
+	 * @throws RuntimeException
735
+	 */
736
+	public function set_att_is_going($REG_att_is_going = false)
737
+	{
738
+		$this->set('REG_att_is_going', $REG_att_is_going);
739
+	}
740
+
741
+
742
+	/**
743
+	 * Gets the related attendee
744
+	 *
745
+	 * @return EE_Attendee
746
+	 * @throws EE_Error
747
+	 */
748
+	public function attendee()
749
+	{
750
+		return $this->get_first_related('Attendee');
751
+	}
752
+
753
+	/**
754
+	 * Gets the name of the attendee.
755
+	 * @since $VID:$
756
+	 * @param bool $apply_html_entities set to true if you want to use HTML entities.
757
+	 * @return string
758
+	 * @throws EE_Error
759
+	 * @throws InvalidArgumentException
760
+	 * @throws InvalidDataTypeException
761
+	 * @throws InvalidInterfaceException
762
+	 * @throws ReflectionException
763
+	 */
764
+	public function attendeeName($apply_html_entities = false)
765
+	{
766
+		$attendee = $this->get_first_related('Attendee');
767
+		if ($attendee instanceof EE_Attendee) {
768
+			$attendee_name = $attendee->full_name($apply_html_entities);
769
+		} else {
770
+			$attendee_name = esc_html__('Unknown', 'event_espresso');
771
+		}
772
+		return $attendee_name;
773
+	}
774
+
775
+
776
+	/**
777
+	 *        get Event ID
778
+	 */
779
+	public function event_ID()
780
+	{
781
+		return $this->get('EVT_ID');
782
+	}
783
+
784
+
785
+	/**
786
+	 *        get Event ID
787
+	 */
788
+	public function event_name()
789
+	{
790
+		$event = $this->event_obj();
791
+		if ($event) {
792
+			return $event->name();
793
+		} else {
794
+			return null;
795
+		}
796
+	}
797
+
798
+
799
+	/**
800
+	 * Fetches the event this registration is for
801
+	 *
802
+	 * @return EE_Event
803
+	 * @throws EE_Error
804
+	 */
805
+	public function event_obj()
806
+	{
807
+		return $this->get_first_related('Event');
808
+	}
809
+
810
+
811
+	/**
812
+	 *        get Attendee ID
813
+	 */
814
+	public function attendee_ID()
815
+	{
816
+		return $this->get('ATT_ID');
817
+	}
818
+
819
+
820
+	/**
821
+	 *        get PHP Session ID
822
+	 */
823
+	public function session_ID()
824
+	{
825
+		return $this->get('REG_session');
826
+	}
827
+
828
+
829
+	/**
830
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
831
+	 *
832
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
833
+	 * @return string
834
+	 */
835
+	public function receipt_url($messenger = 'html')
836
+	{
837
+
838
+		/**
839
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
840
+		 * already in use on old system.  If there is then we just return the standard url for it.
841
+		 *
842
+		 * @since 4.5.0
843
+		 */
844
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
845
+		$has_custom = EEH_Template::locate_template(
846
+			$template_relative_path,
847
+			array(),
848
+			true,
849
+			true,
850
+			true
851
+		);
852
+
853
+		if ($has_custom) {
854
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
855
+		}
856
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
857
+	}
858
+
859
+
860
+	/**
861
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
862
+	 *
863
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
864
+	 * @return string
865
+	 * @throws EE_Error
866
+	 */
867
+	public function invoice_url($messenger = 'html')
868
+	{
869
+		/**
870
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
871
+		 * already in use on old system.  If there is then we just return the standard url for it.
872
+		 *
873
+		 * @since 4.5.0
874
+		 */
875
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
876
+		$has_custom = EEH_Template::locate_template(
877
+			$template_relative_path,
878
+			array(),
879
+			true,
880
+			true,
881
+			true
882
+		);
883
+
884
+		if ($has_custom) {
885
+			if ($messenger == 'html') {
886
+				return $this->invoice_url('launch');
887
+			}
888
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
889
+
890
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
891
+			if ($messenger == 'html') {
892
+				$query_args['html'] = true;
893
+			}
894
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
895
+		}
896
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
897
+	}
898
+
899
+
900
+	/**
901
+	 * get Registration URL Link
902
+	 *
903
+	 * @access public
904
+	 * @return string
905
+	 * @throws EE_Error
906
+	 */
907
+	public function reg_url_link()
908
+	{
909
+		return (string) $this->get('REG_url_link');
910
+	}
911
+
912
+
913
+	/**
914
+	 * Echoes out invoice_url()
915
+	 *
916
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
917
+	 * @return void
918
+	 * @throws EE_Error
919
+	 */
920
+	public function e_invoice_url($type = 'launch')
921
+	{
922
+		echo $this->invoice_url($type);
923
+	}
924
+
925
+
926
+	/**
927
+	 * Echoes out payment_overview_url
928
+	 */
929
+	public function e_payment_overview_url()
930
+	{
931
+		echo $this->payment_overview_url();
932
+	}
933
+
934
+
935
+	/**
936
+	 * Gets the URL for the checkout payment options reg step
937
+	 * with this registration's REG_url_link added as a query parameter
938
+	 *
939
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
940
+	 *                            payment overview url.
941
+	 * @return string
942
+	 * @throws InvalidInterfaceException
943
+	 * @throws InvalidDataTypeException
944
+	 * @throws EE_Error
945
+	 * @throws InvalidArgumentException
946
+	 */
947
+	public function payment_overview_url($clear_session = false)
948
+	{
949
+		return add_query_arg(
950
+			(array) apply_filters(
951
+				'FHEE__EE_Registration__payment_overview_url__query_args',
952
+				array(
953
+					'e_reg_url_link' => $this->reg_url_link(),
954
+					'step'           => 'payment_options',
955
+					'revisit'        => true,
956
+					'clear_session'  => (bool) $clear_session,
957
+				),
958
+				$this
959
+			),
960
+			EE_Registry::instance()->CFG->core->reg_page_url()
961
+		);
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets the URL for the checkout attendee information reg step
967
+	 * with this registration's REG_url_link added as a query parameter
968
+	 *
969
+	 * @return string
970
+	 * @throws InvalidInterfaceException
971
+	 * @throws InvalidDataTypeException
972
+	 * @throws EE_Error
973
+	 * @throws InvalidArgumentException
974
+	 */
975
+	public function edit_attendee_information_url()
976
+	{
977
+		return add_query_arg(
978
+			(array) apply_filters(
979
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
980
+				array(
981
+					'e_reg_url_link' => $this->reg_url_link(),
982
+					'step'           => 'attendee_information',
983
+					'revisit'        => true,
984
+				),
985
+				$this
986
+			),
987
+			EE_Registry::instance()->CFG->core->reg_page_url()
988
+		);
989
+	}
990
+
991
+
992
+	/**
993
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
994
+	 *
995
+	 * @return string
996
+	 * @throws EE_Error
997
+	 */
998
+	public function get_admin_edit_url()
999
+	{
1000
+		return EEH_URL::add_query_args_and_nonce(
1001
+			array(
1002
+				'page'    => 'espresso_registrations',
1003
+				'action'  => 'view_registration',
1004
+				'_REG_ID' => $this->ID(),
1005
+			),
1006
+			admin_url('admin.php')
1007
+		);
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 *    is_primary_registrant?
1013
+	 */
1014
+	public function is_primary_registrant()
1015
+	{
1016
+		return $this->get('REG_count') === 1 ? true : false;
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * This returns the primary registration object for this registration group (which may be this object).
1022
+	 *
1023
+	 * @return EE_Registration
1024
+	 * @throws EE_Error
1025
+	 */
1026
+	public function get_primary_registration()
1027
+	{
1028
+		if ($this->is_primary_registrant()) {
1029
+			return $this;
1030
+		}
1031
+
1032
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1033
+		/** @var EE_Registration $primary_registrant */
1034
+		$primary_registrant = EEM_Registration::instance()->get_one(
1035
+			array(
1036
+				array(
1037
+					'TXN_ID'    => $this->transaction_ID(),
1038
+					'REG_count' => 1,
1039
+				),
1040
+			)
1041
+		);
1042
+		return $primary_registrant;
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 *        get  Attendee Number
1048
+	 *
1049
+	 * @access        public
1050
+	 */
1051
+	public function count()
1052
+	{
1053
+		return $this->get('REG_count');
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 *        get Group Size
1059
+	 */
1060
+	public function group_size()
1061
+	{
1062
+		return $this->get('REG_group_size');
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 *        get Registration Date
1068
+	 */
1069
+	public function date()
1070
+	{
1071
+		return $this->get('REG_date');
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * gets a pretty date
1077
+	 *
1078
+	 * @param string $date_format
1079
+	 * @param string $time_format
1080
+	 * @return string
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function pretty_date($date_format = null, $time_format = null)
1084
+	{
1085
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * final_price
1091
+	 * the registration's share of the transaction total, so that the
1092
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1093
+	 *
1094
+	 * @return float
1095
+	 * @throws EE_Error
1096
+	 */
1097
+	public function final_price()
1098
+	{
1099
+		return $this->get('REG_final_price');
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * pretty_final_price
1105
+	 *  final price as formatted string, with correct decimal places and currency symbol
1106
+	 *
1107
+	 * @return string
1108
+	 * @throws EE_Error
1109
+	 */
1110
+	public function pretty_final_price()
1111
+	{
1112
+		return $this->get_pretty('REG_final_price');
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * get paid (yeah)
1118
+	 *
1119
+	 * @return float
1120
+	 * @throws EE_Error
1121
+	 */
1122
+	public function paid()
1123
+	{
1124
+		return $this->get('REG_paid');
1125
+	}
1126
+
1127
+
1128
+	/**
1129
+	 * pretty_paid
1130
+	 *
1131
+	 * @return float
1132
+	 * @throws EE_Error
1133
+	 */
1134
+	public function pretty_paid()
1135
+	{
1136
+		return $this->get_pretty('REG_paid');
1137
+	}
1138
+
1139
+
1140
+	/**
1141
+	 * owes_monies_and_can_pay
1142
+	 * whether or not this registration has monies owing and it's' status allows payment
1143
+	 *
1144
+	 * @param array $requires_payment
1145
+	 * @return bool
1146
+	 * @throws EE_Error
1147
+	 */
1148
+	public function owes_monies_and_can_pay($requires_payment = array())
1149
+	{
1150
+		// these reg statuses require payment (if event is not free)
1151
+		$requires_payment = ! empty($requires_payment)
1152
+			? $requires_payment
1153
+			: EEM_Registration::reg_statuses_that_allow_payment();
1154
+		if (in_array($this->status_ID(), $requires_payment) &&
1155
+			$this->final_price() != 0 &&
1156
+			$this->final_price() != $this->paid()
1157
+		) {
1158
+			return true;
1159
+		} else {
1160
+			return false;
1161
+		}
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Prints out the return value of $this->pretty_status()
1167
+	 *
1168
+	 * @param bool $show_icons
1169
+	 * @return void
1170
+	 * @throws EE_Error
1171
+	 */
1172
+	public function e_pretty_status($show_icons = false)
1173
+	{
1174
+		echo $this->pretty_status($show_icons);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Returns a nice version of the status for displaying to customers
1180
+	 *
1181
+	 * @param bool $show_icons
1182
+	 * @return string
1183
+	 * @throws EE_Error
1184
+	 */
1185
+	public function pretty_status($show_icons = false)
1186
+	{
1187
+		$status = EEM_Status::instance()->localized_status(
1188
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1189
+			false,
1190
+			'sentence'
1191
+		);
1192
+		$icon = '';
1193
+		switch ($this->status_ID()) {
1194
+			case EEM_Registration::status_id_approved:
1195
+				$icon = $show_icons
1196
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1197
+					: '';
1198
+				break;
1199
+			case EEM_Registration::status_id_pending_payment:
1200
+				$icon = $show_icons
1201
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1202
+					: '';
1203
+				break;
1204
+			case EEM_Registration::status_id_not_approved:
1205
+				$icon = $show_icons
1206
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1207
+					: '';
1208
+				break;
1209
+			case EEM_Registration::status_id_cancelled:
1210
+				$icon = $show_icons
1211
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1212
+					: '';
1213
+				break;
1214
+			case EEM_Registration::status_id_incomplete:
1215
+				$icon = $show_icons
1216
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1217
+					: '';
1218
+				break;
1219
+			case EEM_Registration::status_id_declined:
1220
+				$icon = $show_icons
1221
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1222
+					: '';
1223
+				break;
1224
+			case EEM_Registration::status_id_wait_list:
1225
+				$icon = $show_icons
1226
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1227
+					: '';
1228
+				break;
1229
+		}
1230
+		return $icon . $status[ $this->status_ID() ];
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 *        get Attendee Is Going
1236
+	 */
1237
+	public function att_is_going()
1238
+	{
1239
+		return $this->get('REG_att_is_going');
1240
+	}
1241
+
1242
+
1243
+	/**
1244
+	 * Gets related answers
1245
+	 *
1246
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1247
+	 * @return EE_Answer[]
1248
+	 * @throws EE_Error
1249
+	 */
1250
+	public function answers($query_params = null)
1251
+	{
1252
+		return $this->get_many_related('Answer', $query_params);
1253
+	}
1254
+
1255
+
1256
+	/**
1257
+	 * Gets the registration's answer value to the specified question
1258
+	 * (either the question's ID or a question object)
1259
+	 *
1260
+	 * @param EE_Question|int $question
1261
+	 * @param bool            $pretty_value
1262
+	 * @return array|string if pretty_value= true, the result will always be a string
1263
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1264
+	 * will convert it into some kind of string)
1265
+	 * @throws EE_Error
1266
+	 */
1267
+	public function answer_value_to_question($question, $pretty_value = true)
1268
+	{
1269
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1270
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * question_groups
1276
+	 * returns an array of EE_Question_Group objects for this registration
1277
+	 *
1278
+	 * @return EE_Question_Group[]
1279
+	 * @throws EE_Error
1280
+	 * @throws InvalidArgumentException
1281
+	 * @throws InvalidDataTypeException
1282
+	 * @throws InvalidInterfaceException
1283
+	 * @throws ReflectionException
1284
+	 */
1285
+	public function question_groups()
1286
+	{
1287
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * count_question_groups
1293
+	 * returns a count of the number of EE_Question_Group objects for this registration
1294
+	 *
1295
+	 * @return int
1296
+	 * @throws EE_Error
1297
+	 * @throws EntityNotFoundException
1298
+	 * @throws InvalidArgumentException
1299
+	 * @throws InvalidDataTypeException
1300
+	 * @throws InvalidInterfaceException
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	public function count_question_groups()
1304
+	{
1305
+		return EEM_Event::instance()->count_related(
1306
+			$this->event_ID(),
1307
+			'Question_Group',
1308
+			[
1309
+				[
1310
+					'Event_Question_Group.'
1311
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1312
+				]
1313
+			]
1314
+		);
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * Returns the registration date in the 'standard' string format
1320
+	 * (function may be improved in the future to allow for different formats and timezones)
1321
+	 *
1322
+	 * @return string
1323
+	 * @throws EE_Error
1324
+	 */
1325
+	public function reg_date()
1326
+	{
1327
+		return $this->get_datetime('REG_date');
1328
+	}
1329
+
1330
+
1331
+	/**
1332
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1333
+	 * the ticket this registration purchased, or the datetime they have registered
1334
+	 * to attend)
1335
+	 *
1336
+	 * @return EE_Datetime_Ticket
1337
+	 * @throws EE_Error
1338
+	 */
1339
+	public function datetime_ticket()
1340
+	{
1341
+		return $this->get_first_related('Datetime_Ticket');
1342
+	}
1343
+
1344
+
1345
+	/**
1346
+	 * Sets the registration's datetime_ticket.
1347
+	 *
1348
+	 * @param EE_Datetime_Ticket $datetime_ticket
1349
+	 * @return EE_Datetime_Ticket
1350
+	 * @throws EE_Error
1351
+	 */
1352
+	public function set_datetime_ticket($datetime_ticket)
1353
+	{
1354
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1355
+	}
1356
+
1357
+	/**
1358
+	 * Gets deleted
1359
+	 *
1360
+	 * @return bool
1361
+	 * @throws EE_Error
1362
+	 */
1363
+	public function deleted()
1364
+	{
1365
+		return $this->get('REG_deleted');
1366
+	}
1367
+
1368
+	/**
1369
+	 * Sets deleted
1370
+	 *
1371
+	 * @param boolean $deleted
1372
+	 * @return bool
1373
+	 * @throws EE_Error
1374
+	 * @throws RuntimeException
1375
+	 */
1376
+	public function set_deleted($deleted)
1377
+	{
1378
+		if ($deleted) {
1379
+			$this->delete();
1380
+		} else {
1381
+			$this->restore();
1382
+		}
1383
+	}
1384
+
1385
+
1386
+	/**
1387
+	 * Get the status object of this object
1388
+	 *
1389
+	 * @return EE_Status
1390
+	 * @throws EE_Error
1391
+	 */
1392
+	public function status_obj()
1393
+	{
1394
+		return $this->get_first_related('Status');
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * Returns the number of times this registration has checked into any of the datetimes
1400
+	 * its available for
1401
+	 *
1402
+	 * @return int
1403
+	 * @throws EE_Error
1404
+	 */
1405
+	public function count_checkins()
1406
+	{
1407
+		return $this->get_model()->count_related($this, 'Checkin');
1408
+	}
1409
+
1410
+
1411
+	/**
1412
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1413
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1414
+	 *
1415
+	 * @return int
1416
+	 * @throws EE_Error
1417
+	 */
1418
+	public function count_checkins_not_checkedout()
1419
+	{
1420
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1426
+	 *
1427
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1428
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1429
+	 *                                          consider registration status as well as datetime access.
1430
+	 * @return bool
1431
+	 * @throws EE_Error
1432
+	 */
1433
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1434
+	{
1435
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1436
+
1437
+		// first check registration status
1438
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1439
+			return false;
1440
+		}
1441
+		// is there a datetime ticket that matches this dtt_ID?
1442
+		if (! (EEM_Datetime_Ticket::instance()->exists(
1443
+			array(
1444
+				array(
1445
+					'TKT_ID' => $this->get('TKT_ID'),
1446
+					'DTT_ID' => $DTT_ID,
1447
+				),
1448
+			)
1449
+		))
1450
+		) {
1451
+			return false;
1452
+		}
1453
+
1454
+		// final check is against TKT_uses
1455
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1461
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1462
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1463
+	 * then return false.  Otherwise return true.
1464
+	 *
1465
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1466
+	 * @return bool true means can checkin.  false means cannot checkin.
1467
+	 * @throws EE_Error
1468
+	 */
1469
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1470
+	{
1471
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1472
+
1473
+		if (! $DTT_ID) {
1474
+			return false;
1475
+		}
1476
+
1477
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1478
+
1479
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1480
+		// check-in or not.
1481
+		if (! $max_uses || $max_uses === EE_INF) {
1482
+			return true;
1483
+		}
1484
+
1485
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1486
+		// go ahead and toggle.
1487
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1488
+			return true;
1489
+		}
1490
+
1491
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1492
+		// disallows further check-ins.
1493
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1494
+			array(
1495
+				array(
1496
+					'REG_ID' => $this->ID(),
1497
+					'CHK_in' => true,
1498
+				),
1499
+			),
1500
+			'DTT_ID',
1501
+			true
1502
+		);
1503
+		// checkins have already reached their max number of uses
1504
+		// so registrant can NOT checkin
1505
+		if ($count_unique_dtt_checkins >= $max_uses) {
1506
+			EE_Error::add_error(
1507
+				esc_html__(
1508
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1509
+					'event_espresso'
1510
+				),
1511
+				__FILE__,
1512
+				__FUNCTION__,
1513
+				__LINE__
1514
+			);
1515
+			return false;
1516
+		}
1517
+		return true;
1518
+	}
1519
+
1520
+
1521
+	/**
1522
+	 * toggle Check-in status for this registration
1523
+	 * Check-ins are toggled in the following order:
1524
+	 * never checked in -> checked in
1525
+	 * checked in -> checked out
1526
+	 * checked out -> checked in
1527
+	 *
1528
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1529
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1530
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1531
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1532
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1533
+	 * @throws EE_Error
1534
+	 */
1535
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1536
+	{
1537
+		if (empty($DTT_ID)) {
1538
+			$datetime = $this->get_latest_related_datetime();
1539
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1540
+			// verify the registration can checkin for the given DTT_ID
1541
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1542
+			EE_Error::add_error(
1543
+				sprintf(
1544
+					esc_html__(
1545
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1546
+						'event_espresso'
1547
+					),
1548
+					$this->ID(),
1549
+					$DTT_ID
1550
+				),
1551
+				__FILE__,
1552
+				__FUNCTION__,
1553
+				__LINE__
1554
+			);
1555
+			return false;
1556
+		}
1557
+		$status_paths = array(
1558
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1559
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1560
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1561
+		);
1562
+		// start by getting the current status so we know what status we'll be changing to.
1563
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1564
+		$status_to = $status_paths[ $cur_status ];
1565
+		// database only records true for checked IN or false for checked OUT
1566
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1567
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1568
+		// add relation - note Check-ins are always creating new rows
1569
+		// because we are keeping track of Check-ins over time.
1570
+		// Eventually we'll probably want to show a list table
1571
+		// for the individual Check-ins so that they can be managed.
1572
+		$checkin = EE_Checkin::new_instance(
1573
+			array(
1574
+				'REG_ID' => $this->ID(),
1575
+				'DTT_ID' => $DTT_ID,
1576
+				'CHK_in' => $new_status,
1577
+			)
1578
+		);
1579
+		// if the record could not be saved then return false
1580
+		if ($checkin->save() === 0) {
1581
+			if (WP_DEBUG) {
1582
+				global $wpdb;
1583
+				$error = sprintf(
1584
+					esc_html__(
1585
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1586
+						'event_espresso'
1587
+					),
1588
+					'<br />',
1589
+					$wpdb->last_error
1590
+				);
1591
+			} else {
1592
+				$error = esc_html__(
1593
+					'Registration check in update failed because of an unknown database error',
1594
+					'event_espresso'
1595
+				);
1596
+			}
1597
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1598
+			return false;
1599
+		}
1600
+		return $status_to;
1601
+	}
1602
+
1603
+
1604
+	/**
1605
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1606
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1607
+	 *
1608
+	 * @return EE_Datetime|null
1609
+	 * @throws EE_Error
1610
+	 */
1611
+	public function get_latest_related_datetime()
1612
+	{
1613
+		return EEM_Datetime::instance()->get_one(
1614
+			array(
1615
+				array(
1616
+					'Ticket.Registration.REG_ID' => $this->ID(),
1617
+				),
1618
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1619
+			)
1620
+		);
1621
+	}
1622
+
1623
+
1624
+	/**
1625
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1626
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1627
+	 *
1628
+	 * @throws EE_Error
1629
+	 */
1630
+	public function get_earliest_related_datetime()
1631
+	{
1632
+		return EEM_Datetime::instance()->get_one(
1633
+			array(
1634
+				array(
1635
+					'Ticket.Registration.REG_ID' => $this->ID(),
1636
+				),
1637
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1638
+			)
1639
+		);
1640
+	}
1641
+
1642
+
1643
+	/**
1644
+	 * This method simply returns the check-in status for this registration and the given datetime.
1645
+	 * If neither the datetime nor the checkin values are provided as arguments,
1646
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1647
+	 *
1648
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1649
+	 *                            (if empty we'll get the primary datetime for
1650
+	 *                            this registration (via event) and use it's ID);
1651
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1652
+	 *
1653
+	 * @return int                Integer representing Check-in status.
1654
+	 * @throws EE_Error
1655
+	 */
1656
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1657
+	{
1658
+		$checkin_query_params = array(
1659
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1660
+		);
1661
+
1662
+		if ($DTT_ID > 0) {
1663
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1664
+		}
1665
+
1666
+		// get checkin object (if exists)
1667
+		$checkin = $checkin instanceof EE_Checkin
1668
+			? $checkin
1669
+			: $this->get_first_related('Checkin', $checkin_query_params);
1670
+		if ($checkin instanceof EE_Checkin) {
1671
+			if ($checkin->get('CHK_in')) {
1672
+				return EE_Checkin::status_checked_in; // checked in
1673
+			}
1674
+			return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1675
+		}
1676
+		return EE_Checkin::status_checked_never; // never been checked in
1677
+	}
1678
+
1679
+
1680
+	/**
1681
+	 * This method returns a localized message for the toggled Check-in message.
1682
+	 *
1683
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1684
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1685
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1686
+	 *                     message can be customized with the attendee name.
1687
+	 * @return string internationalized message
1688
+	 * @throws EE_Error
1689
+	 */
1690
+	public function get_checkin_msg($DTT_ID, $error = false)
1691
+	{
1692
+		// let's get the attendee first so we can include the name of the attendee
1693
+		$attendee = $this->get_first_related('Attendee');
1694
+		if ($attendee instanceof EE_Attendee) {
1695
+			if ($error) {
1696
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1697
+			}
1698
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1699
+			// what is the status message going to be?
1700
+			switch ($cur_status) {
1701
+				case EE_Checkin::status_checked_never:
1702
+					return sprintf(
1703
+						__("%s has been removed from Check-in records", "event_espresso"),
1704
+						$attendee->full_name()
1705
+					);
1706
+					break;
1707
+				case EE_Checkin::status_checked_in:
1708
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1709
+					break;
1710
+				case EE_Checkin::status_checked_out:
1711
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1712
+					break;
1713
+			}
1714
+		}
1715
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1716
+	}
1717
+
1718
+
1719
+	/**
1720
+	 * Returns the related EE_Transaction to this registration
1721
+	 *
1722
+	 * @return EE_Transaction
1723
+	 * @throws EE_Error
1724
+	 * @throws EntityNotFoundException
1725
+	 */
1726
+	public function transaction()
1727
+	{
1728
+		$transaction = $this->get_first_related('Transaction');
1729
+		if (! $transaction instanceof \EE_Transaction) {
1730
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1731
+		}
1732
+		return $transaction;
1733
+	}
1734
+
1735
+
1736
+	/**
1737
+	 *        get Registration Code
1738
+	 */
1739
+	public function reg_code()
1740
+	{
1741
+		return $this->get('REG_code');
1742
+	}
1743
+
1744
+
1745
+	/**
1746
+	 *        get Transaction ID
1747
+	 */
1748
+	public function transaction_ID()
1749
+	{
1750
+		return $this->get('TXN_ID');
1751
+	}
1752
+
1753
+
1754
+	/**
1755
+	 * @return int
1756
+	 * @throws EE_Error
1757
+	 */
1758
+	public function ticket_ID()
1759
+	{
1760
+		return $this->get('TKT_ID');
1761
+	}
1762
+
1763
+
1764
+	/**
1765
+	 *        Set Registration Code
1766
+	 *
1767
+	 * @access    public
1768
+	 * @param    string  $REG_code Registration Code
1769
+	 * @param    boolean $use_default
1770
+	 * @throws EE_Error
1771
+	 */
1772
+	public function set_reg_code($REG_code, $use_default = false)
1773
+	{
1774
+		if (empty($REG_code)) {
1775
+			EE_Error::add_error(
1776
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1777
+				__FILE__,
1778
+				__FUNCTION__,
1779
+				__LINE__
1780
+			);
1781
+			return;
1782
+		}
1783
+		if (! $this->reg_code()) {
1784
+			parent::set('REG_code', $REG_code, $use_default);
1785
+		} else {
1786
+			EE_Error::doing_it_wrong(
1787
+				__CLASS__ . '::' . __FUNCTION__,
1788
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1789
+				'4.6.0'
1790
+			);
1791
+		}
1792
+	}
1793
+
1794
+
1795
+	/**
1796
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1797
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1798
+	 *    $registration->transaction()->registrations();
1799
+	 *
1800
+	 * @since 4.5.0
1801
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1802
+	 * @throws EE_Error
1803
+	 */
1804
+	public function get_all_other_registrations_in_group()
1805
+	{
1806
+		if ($this->group_size() < 2) {
1807
+			return array();
1808
+		}
1809
+
1810
+		$query[0] = array(
1811
+			'TXN_ID' => $this->transaction_ID(),
1812
+			'REG_ID' => array('!=', $this->ID()),
1813
+			'TKT_ID' => $this->ticket_ID(),
1814
+		);
1815
+		/** @var EE_Registration[] $registrations */
1816
+		$registrations = $this->get_model()->get_all($query);
1817
+		return $registrations;
1818
+	}
1819
+
1820
+	/**
1821
+	 * Return the link to the admin details for the object.
1822
+	 *
1823
+	 * @return string
1824
+	 * @throws EE_Error
1825
+	 */
1826
+	public function get_admin_details_link()
1827
+	{
1828
+		EE_Registry::instance()->load_helper('URL');
1829
+		return EEH_URL::add_query_args_and_nonce(
1830
+			array(
1831
+				'page'    => 'espresso_registrations',
1832
+				'action'  => 'view_registration',
1833
+				'_REG_ID' => $this->ID(),
1834
+			),
1835
+			admin_url('admin.php')
1836
+		);
1837
+	}
1838
+
1839
+	/**
1840
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1841
+	 *
1842
+	 * @return string
1843
+	 * @throws EE_Error
1844
+	 */
1845
+	public function get_admin_edit_link()
1846
+	{
1847
+		return $this->get_admin_details_link();
1848
+	}
1849
+
1850
+	/**
1851
+	 * Returns the link to a settings page for the object.
1852
+	 *
1853
+	 * @return string
1854
+	 * @throws EE_Error
1855
+	 */
1856
+	public function get_admin_settings_link()
1857
+	{
1858
+		return $this->get_admin_details_link();
1859
+	}
1860
+
1861
+	/**
1862
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1863
+	 *
1864
+	 * @return string
1865
+	 */
1866
+	public function get_admin_overview_link()
1867
+	{
1868
+		EE_Registry::instance()->load_helper('URL');
1869
+		return EEH_URL::add_query_args_and_nonce(
1870
+			array(
1871
+				'page' => 'espresso_registrations',
1872
+			),
1873
+			admin_url('admin.php')
1874
+		);
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 * @param array $query_params
1880
+	 *
1881
+	 * @return \EE_Registration[]
1882
+	 * @throws EE_Error
1883
+	 */
1884
+	public function payments($query_params = array())
1885
+	{
1886
+		return $this->get_many_related('Payment', $query_params);
1887
+	}
1888
+
1889
+
1890
+	/**
1891
+	 * @param array $query_params
1892
+	 *
1893
+	 * @return \EE_Registration_Payment[]
1894
+	 * @throws EE_Error
1895
+	 */
1896
+	public function registration_payments($query_params = array())
1897
+	{
1898
+		return $this->get_many_related('Registration_Payment', $query_params);
1899
+	}
1900
+
1901
+
1902
+	/**
1903
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1904
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1905
+	 *
1906
+	 * @return EE_Payment_Method|null
1907
+	 */
1908
+	public function payment_method()
1909
+	{
1910
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1911
+	}
1912
+
1913
+
1914
+	/**
1915
+	 * @return \EE_Line_Item
1916
+	 * @throws EntityNotFoundException
1917
+	 * @throws EE_Error
1918
+	 */
1919
+	public function ticket_line_item()
1920
+	{
1921
+		$ticket = $this->ticket();
1922
+		$transaction = $this->transaction();
1923
+		$line_item = null;
1924
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1925
+			$transaction->total_line_item(),
1926
+			'Ticket',
1927
+			array($ticket->ID())
1928
+		);
1929
+		foreach ($ticket_line_items as $ticket_line_item) {
1930
+			if ($ticket_line_item instanceof \EE_Line_Item
1931
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1932
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1933
+			) {
1934
+				$line_item = $ticket_line_item;
1935
+				break;
1936
+			}
1937
+		}
1938
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1939
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1940
+		}
1941
+		return $line_item;
1942
+	}
1943
+
1944
+
1945
+	/**
1946
+	 * Soft Deletes this model object.
1947
+	 *
1948
+	 * @return boolean | int
1949
+	 * @throws RuntimeException
1950
+	 * @throws EE_Error
1951
+	 */
1952
+	public function delete()
1953
+	{
1954
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1955
+			$this->set_status(EEM_Registration::status_id_cancelled);
1956
+		}
1957
+		return parent::delete();
1958
+	}
1959
+
1960
+
1961
+	/**
1962
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1963
+	 *
1964
+	 * @throws EE_Error
1965
+	 * @throws RuntimeException
1966
+	 */
1967
+	public function restore()
1968
+	{
1969
+		$previous_status = $this->get_extra_meta(
1970
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1971
+			true,
1972
+			EEM_Registration::status_id_cancelled
1973
+		);
1974
+		if ($previous_status) {
1975
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1976
+			$this->set_status($previous_status);
1977
+		}
1978
+		return parent::restore();
1979
+	}
1980
+
1981
+
1982
+	/**
1983
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1984
+	 *
1985
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1986
+	 *                                           depending on whether the reg status changes to or from "Approved"
1987
+	 * @return boolean whether the Registration status was updated
1988
+	 * @throws EE_Error
1989
+	 * @throws RuntimeException
1990
+	 */
1991
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1992
+	{
1993
+		$paid = $this->paid();
1994
+		$price = $this->final_price();
1995
+		switch (true) {
1996
+			// overpaid or paid
1997
+			case EEH_Money::compare_floats($paid, $price, '>'):
1998
+			case EEH_Money::compare_floats($paid, $price):
1999
+				$new_status = EEM_Registration::status_id_approved;
2000
+				break;
2001
+			//  underpaid
2002
+			case EEH_Money::compare_floats($paid, $price, '<'):
2003
+				$new_status = EEM_Registration::status_id_pending_payment;
2004
+				break;
2005
+			// uhhh Houston...
2006
+			default:
2007
+				throw new RuntimeException(
2008
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2009
+				);
2010
+		}
2011
+		if ($new_status !== $this->status_ID()) {
2012
+			if ($trigger_set_status_logic) {
2013
+				return $this->set_status($new_status);
2014
+			}
2015
+			parent::set('STS_ID', $new_status);
2016
+			return true;
2017
+		}
2018
+		return false;
2019
+	}
2020
+
2021
+
2022
+	/*************************** DEPRECATED ***************************/
2023
+
2024
+
2025
+	/**
2026
+	 * @deprecated
2027
+	 * @since     4.7.0
2028
+	 * @access    public
2029
+	 */
2030
+	public function price_paid()
2031
+	{
2032
+		EE_Error::doing_it_wrong(
2033
+			'EE_Registration::price_paid()',
2034
+			esc_html__(
2035
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2036
+				'event_espresso'
2037
+			),
2038
+			'4.7.0'
2039
+		);
2040
+		return $this->final_price();
2041
+	}
2042
+
2043
+
2044
+	/**
2045
+	 * @deprecated
2046
+	 * @since     4.7.0
2047
+	 * @access    public
2048
+	 * @param    float $REG_final_price
2049
+	 * @throws EE_Error
2050
+	 * @throws RuntimeException
2051
+	 */
2052
+	public function set_price_paid($REG_final_price = 0.00)
2053
+	{
2054
+		EE_Error::doing_it_wrong(
2055
+			'EE_Registration::set_price_paid()',
2056
+			esc_html__(
2057
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2058
+				'event_espresso'
2059
+			),
2060
+			'4.7.0'
2061
+		);
2062
+		$this->set_final_price($REG_final_price);
2063
+	}
2064
+
2065
+
2066
+	/**
2067
+	 * @deprecated
2068
+	 * @since 4.7.0
2069
+	 * @return string
2070
+	 * @throws EE_Error
2071
+	 */
2072
+	public function pretty_price_paid()
2073
+	{
2074
+		EE_Error::doing_it_wrong(
2075
+			'EE_Registration::pretty_price_paid()',
2076
+			esc_html__(
2077
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2078
+				'event_espresso'
2079
+			),
2080
+			'4.7.0'
2081
+		);
2082
+		return $this->pretty_final_price();
2083
+	}
2084
+
2085
+
2086
+	/**
2087
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2088
+	 *
2089
+	 * @deprecated 4.9.17
2090
+	 * @return EE_Datetime
2091
+	 * @throws EE_Error
2092
+	 * @throws EntityNotFoundException
2093
+	 */
2094
+	public function get_related_primary_datetime()
2095
+	{
2096
+		EE_Error::doing_it_wrong(
2097
+			__METHOD__,
2098
+			esc_html__(
2099
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2100
+				'event_espresso'
2101
+			),
2102
+			'4.9.17',
2103
+			'5.0.0'
2104
+		);
2105
+		return $this->event()->primary_datetime();
2106
+	}
2107
+
2108
+	/**
2109
+	 * Returns the contact's name (or "Unknown" if there is no contact.)
2110
+	 * @since $VID:$
2111
+	 * @return string
2112
+	 * @throws EE_Error
2113
+	 * @throws InvalidArgumentException
2114
+	 * @throws InvalidDataTypeException
2115
+	 * @throws InvalidInterfaceException
2116
+	 * @throws ReflectionException
2117
+	 */
2118
+	public function name()
2119
+	{
2120
+		return $this->attendeeName();
2121
+	}
2122 2122
 }
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 2 patches
Indentation   +1210 added lines, -1210 removed lines patch added patch discarded remove patch
@@ -16,1267 +16,1267 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * This is used to hold the reports template data which is setup early in the request.
21
-     *
22
-     * @type array
23
-     */
24
-    protected $_reports_template_data = array();
19
+	/**
20
+	 * This is used to hold the reports template data which is setup early in the request.
21
+	 *
22
+	 * @type array
23
+	 */
24
+	protected $_reports_template_data = array();
25 25
 
26 26
 
27
-    /**
28
-     * Extend_Registrations_Admin_Page constructor.
29
-     *
30
-     * @param bool $routing
31
-     */
32
-    public function __construct($routing = true)
33
-    {
34
-        parent::__construct($routing);
35
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
39
-        }
40
-    }
27
+	/**
28
+	 * Extend_Registrations_Admin_Page constructor.
29
+	 *
30
+	 * @param bool $routing
31
+	 */
32
+	public function __construct($routing = true)
33
+	{
34
+		parent::__construct($routing);
35
+		if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
39
+		}
40
+	}
41 41
 
42 42
 
43
-    /**
44
-     * Extending page configuration.
45
-     */
46
-    protected function _extend_page_config()
47
-    {
48
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
-            ? $this->_req_data['_REG_ID']
51
-            : 0;
52
-        $new_page_routes = array(
53
-            'reports'                      => array(
54
-                'func'       => '_registration_reports',
55
-                'capability' => 'ee_read_registrations',
56
-            ),
57
-            'registration_checkins'        => array(
58
-                'func'       => '_registration_checkin_list_table',
59
-                'capability' => 'ee_read_checkins',
60
-            ),
61
-            'newsletter_selected_send'     => array(
62
-                'func'       => '_newsletter_selected_send',
63
-                'noheader'   => true,
64
-                'capability' => 'ee_send_message',
65
-            ),
66
-            'delete_checkin_rows'          => array(
67
-                'func'       => '_delete_checkin_rows',
68
-                'noheader'   => true,
69
-                'capability' => 'ee_delete_checkins',
70
-            ),
71
-            'delete_checkin_row'           => array(
72
-                'func'       => '_delete_checkin_row',
73
-                'noheader'   => true,
74
-                'capability' => 'ee_delete_checkin',
75
-                'obj_id'     => $reg_id,
76
-            ),
77
-            'toggle_checkin_status'        => array(
78
-                'func'       => '_toggle_checkin_status',
79
-                'noheader'   => true,
80
-                'capability' => 'ee_edit_checkin',
81
-                'obj_id'     => $reg_id,
82
-            ),
83
-            'toggle_checkin_status_bulk'   => array(
84
-                'func'       => '_toggle_checkin_status',
85
-                'noheader'   => true,
86
-                'capability' => 'ee_edit_checkins',
87
-            ),
88
-            'event_registrations'          => array(
89
-                'func'       => '_event_registrations_list_table',
90
-                'capability' => 'ee_read_checkins',
91
-            ),
92
-            'registrations_checkin_report' => array(
93
-                'func'       => '_registrations_checkin_report',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_read_registrations',
96
-            ),
97
-        );
98
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
99
-        $new_page_config = array(
100
-            'reports'               => array(
101
-                'nav'           => array(
102
-                    'label' => esc_html__('Reports', 'event_espresso'),
103
-                    'order' => 30,
104
-                ),
105
-                'help_tabs'     => array(
106
-                    'registrations_reports_help_tab' => array(
107
-                        'title'    => esc_html__('Registration Reports', 'event_espresso'),
108
-                        'filename' => 'registrations_reports',
109
-                    ),
110
-                ),
111
-                /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
112
-                'require_nonce' => false,
113
-            ),
114
-            'event_registrations'   => array(
115
-                'nav'           => array(
116
-                    'label'      => esc_html__('Event Check-In', 'event_espresso'),
117
-                    'order'      => 10,
118
-                    'persistent' => true,
119
-                ),
120
-                'help_tabs'     => array(
121
-                    'registrations_event_checkin_help_tab'                       => array(
122
-                        'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
123
-                        'filename' => 'registrations_event_checkin',
124
-                    ),
125
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
126
-                        'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
127
-                        'filename' => 'registrations_event_checkin_table_column_headings',
128
-                    ),
129
-                    'registrations_event_checkin_filters_help_tab'               => array(
130
-                        'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
131
-                        'filename' => 'registrations_event_checkin_filters',
132
-                    ),
133
-                    'registrations_event_checkin_views_help_tab'                 => array(
134
-                        'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
135
-                        'filename' => 'registrations_event_checkin_views',
136
-                    ),
137
-                    'registrations_event_checkin_other_help_tab'                 => array(
138
-                        'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
139
-                        'filename' => 'registrations_event_checkin_other',
140
-                    ),
141
-                ),
142
-                'help_tour'     => array('Event_Checkin_Help_Tour'),
143
-                'qtips'         => array('Registration_List_Table_Tips'),
144
-                'list_table'    => 'EE_Event_Registrations_List_Table',
145
-                'metaboxes'     => array(),
146
-                'require_nonce' => false,
147
-            ),
148
-            'registration_checkins' => array(
149
-                'nav'           => array(
150
-                    'label'      => esc_html__('Check-In Records', 'event_espresso'),
151
-                    'order'      => 15,
152
-                    'persistent' => false,
153
-                    'url'        => '',
154
-                ),
155
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
156
-                // 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
157
-                'metaboxes'     => array(),
158
-                'require_nonce' => false,
159
-            ),
160
-        );
161
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
162
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
163
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
164
-    }
43
+	/**
44
+	 * Extending page configuration.
45
+	 */
46
+	protected function _extend_page_config()
47
+	{
48
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
+			? $this->_req_data['_REG_ID']
51
+			: 0;
52
+		$new_page_routes = array(
53
+			'reports'                      => array(
54
+				'func'       => '_registration_reports',
55
+				'capability' => 'ee_read_registrations',
56
+			),
57
+			'registration_checkins'        => array(
58
+				'func'       => '_registration_checkin_list_table',
59
+				'capability' => 'ee_read_checkins',
60
+			),
61
+			'newsletter_selected_send'     => array(
62
+				'func'       => '_newsletter_selected_send',
63
+				'noheader'   => true,
64
+				'capability' => 'ee_send_message',
65
+			),
66
+			'delete_checkin_rows'          => array(
67
+				'func'       => '_delete_checkin_rows',
68
+				'noheader'   => true,
69
+				'capability' => 'ee_delete_checkins',
70
+			),
71
+			'delete_checkin_row'           => array(
72
+				'func'       => '_delete_checkin_row',
73
+				'noheader'   => true,
74
+				'capability' => 'ee_delete_checkin',
75
+				'obj_id'     => $reg_id,
76
+			),
77
+			'toggle_checkin_status'        => array(
78
+				'func'       => '_toggle_checkin_status',
79
+				'noheader'   => true,
80
+				'capability' => 'ee_edit_checkin',
81
+				'obj_id'     => $reg_id,
82
+			),
83
+			'toggle_checkin_status_bulk'   => array(
84
+				'func'       => '_toggle_checkin_status',
85
+				'noheader'   => true,
86
+				'capability' => 'ee_edit_checkins',
87
+			),
88
+			'event_registrations'          => array(
89
+				'func'       => '_event_registrations_list_table',
90
+				'capability' => 'ee_read_checkins',
91
+			),
92
+			'registrations_checkin_report' => array(
93
+				'func'       => '_registrations_checkin_report',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_read_registrations',
96
+			),
97
+		);
98
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
99
+		$new_page_config = array(
100
+			'reports'               => array(
101
+				'nav'           => array(
102
+					'label' => esc_html__('Reports', 'event_espresso'),
103
+					'order' => 30,
104
+				),
105
+				'help_tabs'     => array(
106
+					'registrations_reports_help_tab' => array(
107
+						'title'    => esc_html__('Registration Reports', 'event_espresso'),
108
+						'filename' => 'registrations_reports',
109
+					),
110
+				),
111
+				/*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
112
+				'require_nonce' => false,
113
+			),
114
+			'event_registrations'   => array(
115
+				'nav'           => array(
116
+					'label'      => esc_html__('Event Check-In', 'event_espresso'),
117
+					'order'      => 10,
118
+					'persistent' => true,
119
+				),
120
+				'help_tabs'     => array(
121
+					'registrations_event_checkin_help_tab'                       => array(
122
+						'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
123
+						'filename' => 'registrations_event_checkin',
124
+					),
125
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
126
+						'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
127
+						'filename' => 'registrations_event_checkin_table_column_headings',
128
+					),
129
+					'registrations_event_checkin_filters_help_tab'               => array(
130
+						'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
131
+						'filename' => 'registrations_event_checkin_filters',
132
+					),
133
+					'registrations_event_checkin_views_help_tab'                 => array(
134
+						'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
135
+						'filename' => 'registrations_event_checkin_views',
136
+					),
137
+					'registrations_event_checkin_other_help_tab'                 => array(
138
+						'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
139
+						'filename' => 'registrations_event_checkin_other',
140
+					),
141
+				),
142
+				'help_tour'     => array('Event_Checkin_Help_Tour'),
143
+				'qtips'         => array('Registration_List_Table_Tips'),
144
+				'list_table'    => 'EE_Event_Registrations_List_Table',
145
+				'metaboxes'     => array(),
146
+				'require_nonce' => false,
147
+			),
148
+			'registration_checkins' => array(
149
+				'nav'           => array(
150
+					'label'      => esc_html__('Check-In Records', 'event_espresso'),
151
+					'order'      => 15,
152
+					'persistent' => false,
153
+					'url'        => '',
154
+				),
155
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
156
+				// 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
157
+				'metaboxes'     => array(),
158
+				'require_nonce' => false,
159
+			),
160
+		);
161
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
162
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
163
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
164
+	}
165 165
 
166 166
 
167
-    /**
168
-     * Ajax hooks for all routes in this page.
169
-     */
170
-    protected function _ajax_hooks()
171
-    {
172
-        parent::_ajax_hooks();
173
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
-    }
167
+	/**
168
+	 * Ajax hooks for all routes in this page.
169
+	 */
170
+	protected function _ajax_hooks()
171
+	{
172
+		parent::_ajax_hooks();
173
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * Global scripts for all routes in this page.
179
-     */
180
-    public function load_scripts_styles()
181
-    {
182
-        parent::load_scripts_styles();
183
-        // if newsletter message type is active then let's add filter and load js for it.
184
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
185
-            // enqueue newsletter js
186
-            wp_enqueue_script(
187
-                'ee-newsletter-trigger',
188
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
189
-                array('ee-dialog'),
190
-                EVENT_ESPRESSO_VERSION,
191
-                true
192
-            );
193
-            wp_enqueue_style(
194
-                'ee-newsletter-trigger-css',
195
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
196
-                array(),
197
-                EVENT_ESPRESSO_VERSION
198
-            );
199
-            // hook in buttons for newsletter message type trigger.
200
-            add_action(
201
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
202
-                array($this, 'add_newsletter_action_buttons'),
203
-                10
204
-            );
205
-        }
206
-    }
177
+	/**
178
+	 * Global scripts for all routes in this page.
179
+	 */
180
+	public function load_scripts_styles()
181
+	{
182
+		parent::load_scripts_styles();
183
+		// if newsletter message type is active then let's add filter and load js for it.
184
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
185
+			// enqueue newsletter js
186
+			wp_enqueue_script(
187
+				'ee-newsletter-trigger',
188
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
189
+				array('ee-dialog'),
190
+				EVENT_ESPRESSO_VERSION,
191
+				true
192
+			);
193
+			wp_enqueue_style(
194
+				'ee-newsletter-trigger-css',
195
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
196
+				array(),
197
+				EVENT_ESPRESSO_VERSION
198
+			);
199
+			// hook in buttons for newsletter message type trigger.
200
+			add_action(
201
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
202
+				array($this, 'add_newsletter_action_buttons'),
203
+				10
204
+			);
205
+		}
206
+	}
207 207
 
208 208
 
209
-    /**
210
-     * Scripts and styles for just the reports route.
211
-     */
212
-    public function load_scripts_styles_reports()
213
-    {
214
-        wp_register_script(
215
-            'ee-reg-reports-js',
216
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
217
-            array('google-charts'),
218
-            EVENT_ESPRESSO_VERSION,
219
-            true
220
-        );
221
-        wp_enqueue_script('ee-reg-reports-js');
222
-        $this->_registration_reports_js_setup();
223
-    }
209
+	/**
210
+	 * Scripts and styles for just the reports route.
211
+	 */
212
+	public function load_scripts_styles_reports()
213
+	{
214
+		wp_register_script(
215
+			'ee-reg-reports-js',
216
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
217
+			array('google-charts'),
218
+			EVENT_ESPRESSO_VERSION,
219
+			true
220
+		);
221
+		wp_enqueue_script('ee-reg-reports-js');
222
+		$this->_registration_reports_js_setup();
223
+	}
224 224
 
225 225
 
226
-    /**
227
-     * Register screen options for event_registrations route.
228
-     */
229
-    protected function _add_screen_options_event_registrations()
230
-    {
231
-        $this->_per_page_screen_option();
232
-    }
226
+	/**
227
+	 * Register screen options for event_registrations route.
228
+	 */
229
+	protected function _add_screen_options_event_registrations()
230
+	{
231
+		$this->_per_page_screen_option();
232
+	}
233 233
 
234 234
 
235
-    /**
236
-     * Register screen options for registration_checkins route
237
-     */
238
-    protected function _add_screen_options_registration_checkins()
239
-    {
240
-        $page_title = $this->_admin_page_title;
241
-        $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
242
-        $this->_per_page_screen_option();
243
-        $this->_admin_page_title = $page_title;
244
-    }
235
+	/**
236
+	 * Register screen options for registration_checkins route
237
+	 */
238
+	protected function _add_screen_options_registration_checkins()
239
+	{
240
+		$page_title = $this->_admin_page_title;
241
+		$this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
242
+		$this->_per_page_screen_option();
243
+		$this->_admin_page_title = $page_title;
244
+	}
245 245
 
246 246
 
247
-    /**
248
-     * Set views property for event_registrations route.
249
-     */
250
-    protected function _set_list_table_views_event_registrations()
251
-    {
252
-        $this->_views = array(
253
-            'all' => array(
254
-                'slug'        => 'all',
255
-                'label'       => esc_html__('All', 'event_espresso'),
256
-                'count'       => 0,
257
-                'bulk_action' => ! isset($this->_req_data['event_id'])
258
-                    ? array()
259
-                    : array(
260
-                        'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
261
-                    ),
262
-            ),
263
-        );
264
-    }
247
+	/**
248
+	 * Set views property for event_registrations route.
249
+	 */
250
+	protected function _set_list_table_views_event_registrations()
251
+	{
252
+		$this->_views = array(
253
+			'all' => array(
254
+				'slug'        => 'all',
255
+				'label'       => esc_html__('All', 'event_espresso'),
256
+				'count'       => 0,
257
+				'bulk_action' => ! isset($this->_req_data['event_id'])
258
+					? array()
259
+					: array(
260
+						'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
261
+					),
262
+			),
263
+		);
264
+	}
265 265
 
266 266
 
267
-    /**
268
-     * Set views property for registration_checkins route.
269
-     */
270
-    protected function _set_list_table_views_registration_checkins()
271
-    {
272
-        $this->_views = array(
273
-            'all' => array(
274
-                'slug'        => 'all',
275
-                'label'       => esc_html__('All', 'event_espresso'),
276
-                'count'       => 0,
277
-                'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
278
-            ),
279
-        );
280
-    }
267
+	/**
268
+	 * Set views property for registration_checkins route.
269
+	 */
270
+	protected function _set_list_table_views_registration_checkins()
271
+	{
272
+		$this->_views = array(
273
+			'all' => array(
274
+				'slug'        => 'all',
275
+				'label'       => esc_html__('All', 'event_espresso'),
276
+				'count'       => 0,
277
+				'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
278
+			),
279
+		);
280
+	}
281 281
 
282 282
 
283
-    /**
284
-     * callback for ajax action.
285
-     *
286
-     * @since 4.3.0
287
-     * @return void (JSON)
288
-     * @throws EE_Error
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidDataTypeException
291
-     * @throws InvalidInterfaceException
292
-     */
293
-    public function get_newsletter_form_content()
294
-    {
295
-        // do a nonce check cause we're not coming in from an normal route here.
296
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
297
-            $this->_req_data['get_newsletter_form_content_nonce']
298
-        ) : '';
299
-        $nonce_ref = 'get_newsletter_form_content_nonce';
300
-        $this->_verify_nonce($nonce, $nonce_ref);
301
-        // let's get the mtp for the incoming MTP_ ID
302
-        if (! isset($this->_req_data['GRP_ID'])) {
303
-            EE_Error::add_error(
304
-                esc_html__(
305
-                    'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
306
-                    'event_espresso'
307
-                ),
308
-                __FILE__,
309
-                __FUNCTION__,
310
-                __LINE__
311
-            );
312
-            $this->_template_args['success'] = false;
313
-            $this->_template_args['error'] = true;
314
-            $this->_return_json();
315
-        }
316
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
-        if (! $MTPG instanceof EE_Message_Template_Group) {
318
-            EE_Error::add_error(
319
-                sprintf(
320
-                    esc_html__(
321
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
322
-                        'event_espresso'
323
-                    ),
324
-                    $this->_req_data['GRP_ID']
325
-                ),
326
-                __FILE__,
327
-                __FUNCTION__,
328
-                __LINE__
329
-            );
330
-            $this->_template_args['success'] = false;
331
-            $this->_template_args['error'] = true;
332
-            $this->_return_json();
333
-        }
334
-        $MTPs = $MTPG->context_templates();
335
-        $MTPs = $MTPs['attendee'];
336
-        $template_fields = array();
337
-        /** @var EE_Message_Template $MTP */
338
-        foreach ($MTPs as $MTP) {
339
-            $field = $MTP->get('MTP_template_field');
340
-            if ($field === 'content') {
341
-                $content = $MTP->get('MTP_content');
342
-                if (! empty($content['newsletter_content'])) {
343
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
344
-                }
345
-                continue;
346
-            }
347
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
348
-        }
349
-        $this->_template_args['success'] = true;
350
-        $this->_template_args['error'] = false;
351
-        $this->_template_args['data'] = array(
352
-            'batch_message_from'    => isset($template_fields['from'])
353
-                ? $template_fields['from']
354
-                : '',
355
-            'batch_message_subject' => isset($template_fields['subject'])
356
-                ? $template_fields['subject']
357
-                : '',
358
-            'batch_message_content' => isset($template_fields['newsletter_content'])
359
-                ? $template_fields['newsletter_content']
360
-                : '',
361
-        );
362
-        $this->_return_json();
363
-    }
283
+	/**
284
+	 * callback for ajax action.
285
+	 *
286
+	 * @since 4.3.0
287
+	 * @return void (JSON)
288
+	 * @throws EE_Error
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidDataTypeException
291
+	 * @throws InvalidInterfaceException
292
+	 */
293
+	public function get_newsletter_form_content()
294
+	{
295
+		// do a nonce check cause we're not coming in from an normal route here.
296
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
297
+			$this->_req_data['get_newsletter_form_content_nonce']
298
+		) : '';
299
+		$nonce_ref = 'get_newsletter_form_content_nonce';
300
+		$this->_verify_nonce($nonce, $nonce_ref);
301
+		// let's get the mtp for the incoming MTP_ ID
302
+		if (! isset($this->_req_data['GRP_ID'])) {
303
+			EE_Error::add_error(
304
+				esc_html__(
305
+					'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
306
+					'event_espresso'
307
+				),
308
+				__FILE__,
309
+				__FUNCTION__,
310
+				__LINE__
311
+			);
312
+			$this->_template_args['success'] = false;
313
+			$this->_template_args['error'] = true;
314
+			$this->_return_json();
315
+		}
316
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
+		if (! $MTPG instanceof EE_Message_Template_Group) {
318
+			EE_Error::add_error(
319
+				sprintf(
320
+					esc_html__(
321
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
322
+						'event_espresso'
323
+					),
324
+					$this->_req_data['GRP_ID']
325
+				),
326
+				__FILE__,
327
+				__FUNCTION__,
328
+				__LINE__
329
+			);
330
+			$this->_template_args['success'] = false;
331
+			$this->_template_args['error'] = true;
332
+			$this->_return_json();
333
+		}
334
+		$MTPs = $MTPG->context_templates();
335
+		$MTPs = $MTPs['attendee'];
336
+		$template_fields = array();
337
+		/** @var EE_Message_Template $MTP */
338
+		foreach ($MTPs as $MTP) {
339
+			$field = $MTP->get('MTP_template_field');
340
+			if ($field === 'content') {
341
+				$content = $MTP->get('MTP_content');
342
+				if (! empty($content['newsletter_content'])) {
343
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
344
+				}
345
+				continue;
346
+			}
347
+			$template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
348
+		}
349
+		$this->_template_args['success'] = true;
350
+		$this->_template_args['error'] = false;
351
+		$this->_template_args['data'] = array(
352
+			'batch_message_from'    => isset($template_fields['from'])
353
+				? $template_fields['from']
354
+				: '',
355
+			'batch_message_subject' => isset($template_fields['subject'])
356
+				? $template_fields['subject']
357
+				: '',
358
+			'batch_message_content' => isset($template_fields['newsletter_content'])
359
+				? $template_fields['newsletter_content']
360
+				: '',
361
+		);
362
+		$this->_return_json();
363
+	}
364 364
 
365 365
 
366
-    /**
367
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
368
-     *
369
-     * @since 4.3.0
370
-     * @param EE_Admin_List_Table $list_table
371
-     * @return void
372
-     * @throws InvalidArgumentException
373
-     * @throws InvalidDataTypeException
374
-     * @throws InvalidInterfaceException
375
-     */
376
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377
-    {
378
-        if (! EE_Registry::instance()->CAP->current_user_can(
379
-            'ee_send_message',
380
-            'espresso_registrations_newsletter_selected_send'
381
-        )
382
-        ) {
383
-            return;
384
-        }
385
-        $routes_to_add_to = array(
386
-            'contact_list',
387
-            'event_registrations',
388
-            'default',
389
-        );
390
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
391
-            if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
392
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
393
-            ) {
394
-                echo '';
395
-            } else {
396
-                $button_text = sprintf(
397
-                    esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
398
-                    '<span class="send-selected-newsletter-count">0</span>'
399
-                );
400
-                echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
401
-                     . '<span class="dashicons dashicons-email "></span>'
402
-                     . $button_text
403
-                     . '</button>';
404
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
405
-            }
406
-        }
407
-    }
366
+	/**
367
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
368
+	 *
369
+	 * @since 4.3.0
370
+	 * @param EE_Admin_List_Table $list_table
371
+	 * @return void
372
+	 * @throws InvalidArgumentException
373
+	 * @throws InvalidDataTypeException
374
+	 * @throws InvalidInterfaceException
375
+	 */
376
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377
+	{
378
+		if (! EE_Registry::instance()->CAP->current_user_can(
379
+			'ee_send_message',
380
+			'espresso_registrations_newsletter_selected_send'
381
+		)
382
+		) {
383
+			return;
384
+		}
385
+		$routes_to_add_to = array(
386
+			'contact_list',
387
+			'event_registrations',
388
+			'default',
389
+		);
390
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
391
+			if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
392
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
393
+			) {
394
+				echo '';
395
+			} else {
396
+				$button_text = sprintf(
397
+					esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
398
+					'<span class="send-selected-newsletter-count">0</span>'
399
+				);
400
+				echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
401
+					 . '<span class="dashicons dashicons-email "></span>'
402
+					 . $button_text
403
+					 . '</button>';
404
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
405
+			}
406
+		}
407
+	}
408 408
 
409 409
 
410
-    /**
411
-     * @throws DomainException
412
-     * @throws EE_Error
413
-     * @throws InvalidArgumentException
414
-     * @throws InvalidDataTypeException
415
-     * @throws InvalidInterfaceException
416
-     */
417
-    public function newsletter_send_form_skeleton()
418
-    {
419
-        $list_table = $this->_list_table_object;
420
-        $codes = array();
421
-        // need to templates for the newsletter message type for the template selector.
422
-        $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
423
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
424
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
425
-        );
426
-        foreach ($mtps as $mtp) {
427
-            $name = $mtp->name();
428
-            $values[] = array(
429
-                'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
430
-                'id'   => $mtp->ID(),
431
-            );
432
-        }
433
-        // need to get a list of shortcodes that are available for the newsletter message type.
434
-        $shortcodes = EEH_MSG_Template::get_shortcodes(
435
-            'newsletter',
436
-            'email',
437
-            array(),
438
-            'attendee',
439
-            false
440
-        );
441
-        foreach ($shortcodes as $field => $shortcode_array) {
442
-            $available_shortcodes = array();
443
-            foreach ($shortcode_array as $shortcode => $shortcode_details) {
444
-                $field_id = $field === '[NEWSLETTER_CONTENT]'
445
-                    ? 'content'
446
-                    : $field;
447
-                $field_id = 'batch-message-' . strtolower($field_id);
448
-                $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449
-                                          . $shortcode
450
-                                          . '" data-linked-input-id="' . $field_id . '">'
451
-                                          . $shortcode
452
-                                          . '</span>';
453
-            }
454
-            $codes[ $field ] = implode(', ', $available_shortcodes);
455
-        }
456
-        $shortcodes = $codes;
457
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
458
-        $form_template_args = array(
459
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460
-            'form_route'        => 'newsletter_selected_send',
461
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
462
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
463
-            'redirect_back_to'  => $this->_req_action,
464
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
465
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
466
-            'shortcodes'        => $shortcodes,
467
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
468
-        );
469
-        EEH_Template::display_template($form_template, $form_template_args);
470
-    }
410
+	/**
411
+	 * @throws DomainException
412
+	 * @throws EE_Error
413
+	 * @throws InvalidArgumentException
414
+	 * @throws InvalidDataTypeException
415
+	 * @throws InvalidInterfaceException
416
+	 */
417
+	public function newsletter_send_form_skeleton()
418
+	{
419
+		$list_table = $this->_list_table_object;
420
+		$codes = array();
421
+		// need to templates for the newsletter message type for the template selector.
422
+		$values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
423
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
424
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
425
+		);
426
+		foreach ($mtps as $mtp) {
427
+			$name = $mtp->name();
428
+			$values[] = array(
429
+				'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
430
+				'id'   => $mtp->ID(),
431
+			);
432
+		}
433
+		// need to get a list of shortcodes that are available for the newsletter message type.
434
+		$shortcodes = EEH_MSG_Template::get_shortcodes(
435
+			'newsletter',
436
+			'email',
437
+			array(),
438
+			'attendee',
439
+			false
440
+		);
441
+		foreach ($shortcodes as $field => $shortcode_array) {
442
+			$available_shortcodes = array();
443
+			foreach ($shortcode_array as $shortcode => $shortcode_details) {
444
+				$field_id = $field === '[NEWSLETTER_CONTENT]'
445
+					? 'content'
446
+					: $field;
447
+				$field_id = 'batch-message-' . strtolower($field_id);
448
+				$available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449
+										  . $shortcode
450
+										  . '" data-linked-input-id="' . $field_id . '">'
451
+										  . $shortcode
452
+										  . '</span>';
453
+			}
454
+			$codes[ $field ] = implode(', ', $available_shortcodes);
455
+		}
456
+		$shortcodes = $codes;
457
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
458
+		$form_template_args = array(
459
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460
+			'form_route'        => 'newsletter_selected_send',
461
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
462
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
463
+			'redirect_back_to'  => $this->_req_action,
464
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
465
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
466
+			'shortcodes'        => $shortcodes,
467
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
468
+		);
469
+		EEH_Template::display_template($form_template, $form_template_args);
470
+	}
471 471
 
472 472
 
473
-    /**
474
-     * Handles sending selected registrations/contacts a newsletter.
475
-     *
476
-     * @since  4.3.0
477
-     * @return void
478
-     * @throws EE_Error
479
-     * @throws InvalidArgumentException
480
-     * @throws InvalidDataTypeException
481
-     * @throws InvalidInterfaceException
482
-     */
483
-    protected function _newsletter_selected_send()
484
-    {
485
-        $success = true;
486
-        // first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
487
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
488
-            EE_Error::add_error(
489
-                esc_html__(
490
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
491
-                    'event_espresso'
492
-                ),
493
-                __FILE__,
494
-                __FUNCTION__,
495
-                __LINE__
496
-            );
497
-            $success = false;
498
-        }
499
-        if ($success) {
500
-            // update Message template in case there are any changes
501
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
502
-                $this->_req_data['newsletter_mtp_selected']
503
-            );
504
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
505
-                ? $Message_Template_Group->context_templates()
506
-                : array();
507
-            if (empty($Message_Templates)) {
508
-                EE_Error::add_error(
509
-                    esc_html__(
510
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
511
-                        'event_espresso'
512
-                    ),
513
-                    __FILE__,
514
-                    __FUNCTION__,
515
-                    __LINE__
516
-                );
517
-            }
518
-            // let's just update the specific fields
519
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
520
-                if ($Message_Template instanceof EE_Message_Template) {
521
-                    $field = $Message_Template->get('MTP_template_field');
522
-                    $content = $Message_Template->get('MTP_content');
523
-                    $new_content = $content;
524
-                    switch ($field) {
525
-                        case 'from':
526
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
527
-                                ? $this->_req_data['batch_message']['from']
528
-                                : $content;
529
-                            break;
530
-                        case 'subject':
531
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
532
-                                ? $this->_req_data['batch_message']['subject']
533
-                                : $content;
534
-                            break;
535
-                        case 'content':
536
-                            $new_content = $content;
537
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
538
-                                ? $this->_req_data['batch_message']['content']
539
-                                : $content['newsletter_content'];
540
-                            break;
541
-                        default:
542
-                            // continue the foreach loop, we don't want to set $new_content nor save.
543
-                            continue 2;
544
-                    }
545
-                    $Message_Template->set('MTP_content', $new_content);
546
-                    $Message_Template->save();
547
-                }
548
-            }
549
-            // great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
550
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
551
-                ? $this->_req_data['batch_message']['id_type']
552
-                : 'registration';
553
-            // id_type will affect how we assemble the ids.
554
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
555
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
556
-                : array();
557
-            $registrations_used_for_contact_data = array();
558
-            // using switch because eventually we'll have other contexts that will be used for generating messages.
559
-            switch ($id_type) {
560
-                case 'registration':
561
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
562
-                        array(
563
-                            array(
564
-                                'REG_ID' => array('IN', $ids),
565
-                            ),
566
-                        )
567
-                    );
568
-                    break;
569
-                case 'contact':
570
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
571
-                                                                           ->get_latest_registration_for_each_of_given_contacts(
572
-                                                                               $ids
573
-                                                                           );
574
-                    break;
575
-            }
576
-            do_action_ref_array(
577
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
578
-                array(
579
-                    $registrations_used_for_contact_data,
580
-                    $Message_Template_Group->ID(),
581
-                )
582
-            );
583
-            // kept for backward compat, internally we no longer use this action.
584
-            // @deprecated 4.8.36.rc.002
585
-            $contacts = $id_type === 'registration'
586
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
587
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
588
-            do_action_ref_array(
589
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
590
-                array(
591
-                    $contacts,
592
-                    $Message_Template_Group->ID(),
593
-                )
594
-            );
595
-        }
596
-        $query_args = array(
597
-            'action' => ! empty($this->_req_data['redirect_back_to'])
598
-                ? $this->_req_data['redirect_back_to']
599
-                : 'default',
600
-        );
601
-        $this->_redirect_after_action(false, '', '', $query_args, true);
602
-    }
473
+	/**
474
+	 * Handles sending selected registrations/contacts a newsletter.
475
+	 *
476
+	 * @since  4.3.0
477
+	 * @return void
478
+	 * @throws EE_Error
479
+	 * @throws InvalidArgumentException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws InvalidInterfaceException
482
+	 */
483
+	protected function _newsletter_selected_send()
484
+	{
485
+		$success = true;
486
+		// first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
487
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
488
+			EE_Error::add_error(
489
+				esc_html__(
490
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
491
+					'event_espresso'
492
+				),
493
+				__FILE__,
494
+				__FUNCTION__,
495
+				__LINE__
496
+			);
497
+			$success = false;
498
+		}
499
+		if ($success) {
500
+			// update Message template in case there are any changes
501
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
502
+				$this->_req_data['newsletter_mtp_selected']
503
+			);
504
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
505
+				? $Message_Template_Group->context_templates()
506
+				: array();
507
+			if (empty($Message_Templates)) {
508
+				EE_Error::add_error(
509
+					esc_html__(
510
+						'Unable to retrieve message template fields from the db. Messages not sent.',
511
+						'event_espresso'
512
+					),
513
+					__FILE__,
514
+					__FUNCTION__,
515
+					__LINE__
516
+				);
517
+			}
518
+			// let's just update the specific fields
519
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
520
+				if ($Message_Template instanceof EE_Message_Template) {
521
+					$field = $Message_Template->get('MTP_template_field');
522
+					$content = $Message_Template->get('MTP_content');
523
+					$new_content = $content;
524
+					switch ($field) {
525
+						case 'from':
526
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
527
+								? $this->_req_data['batch_message']['from']
528
+								: $content;
529
+							break;
530
+						case 'subject':
531
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
532
+								? $this->_req_data['batch_message']['subject']
533
+								: $content;
534
+							break;
535
+						case 'content':
536
+							$new_content = $content;
537
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
538
+								? $this->_req_data['batch_message']['content']
539
+								: $content['newsletter_content'];
540
+							break;
541
+						default:
542
+							// continue the foreach loop, we don't want to set $new_content nor save.
543
+							continue 2;
544
+					}
545
+					$Message_Template->set('MTP_content', $new_content);
546
+					$Message_Template->save();
547
+				}
548
+			}
549
+			// great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
550
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
551
+				? $this->_req_data['batch_message']['id_type']
552
+				: 'registration';
553
+			// id_type will affect how we assemble the ids.
554
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
555
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
556
+				: array();
557
+			$registrations_used_for_contact_data = array();
558
+			// using switch because eventually we'll have other contexts that will be used for generating messages.
559
+			switch ($id_type) {
560
+				case 'registration':
561
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
562
+						array(
563
+							array(
564
+								'REG_ID' => array('IN', $ids),
565
+							),
566
+						)
567
+					);
568
+					break;
569
+				case 'contact':
570
+					$registrations_used_for_contact_data = EEM_Registration::instance()
571
+																		   ->get_latest_registration_for_each_of_given_contacts(
572
+																			   $ids
573
+																		   );
574
+					break;
575
+			}
576
+			do_action_ref_array(
577
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
578
+				array(
579
+					$registrations_used_for_contact_data,
580
+					$Message_Template_Group->ID(),
581
+				)
582
+			);
583
+			// kept for backward compat, internally we no longer use this action.
584
+			// @deprecated 4.8.36.rc.002
585
+			$contacts = $id_type === 'registration'
586
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
587
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
588
+			do_action_ref_array(
589
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
590
+				array(
591
+					$contacts,
592
+					$Message_Template_Group->ID(),
593
+				)
594
+			);
595
+		}
596
+		$query_args = array(
597
+			'action' => ! empty($this->_req_data['redirect_back_to'])
598
+				? $this->_req_data['redirect_back_to']
599
+				: 'default',
600
+		);
601
+		$this->_redirect_after_action(false, '', '', $query_args, true);
602
+	}
603 603
 
604 604
 
605
-    /**
606
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
607
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
608
-     */
609
-    protected function _registration_reports_js_setup()
610
-    {
611
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
612
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
613
-    }
605
+	/**
606
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
607
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
608
+	 */
609
+	protected function _registration_reports_js_setup()
610
+	{
611
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
612
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
613
+	}
614 614
 
615 615
 
616
-    /**
617
-     *        generates Business Reports regarding Registrations
618
-     *
619
-     * @access protected
620
-     * @return void
621
-     * @throws DomainException
622
-     */
623
-    protected function _registration_reports()
624
-    {
625
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
626
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
627
-            $template_path,
628
-            $this->_reports_template_data,
629
-            true
630
-        );
631
-        // the final template wrapper
632
-        $this->display_admin_page_with_no_sidebar();
633
-    }
616
+	/**
617
+	 *        generates Business Reports regarding Registrations
618
+	 *
619
+	 * @access protected
620
+	 * @return void
621
+	 * @throws DomainException
622
+	 */
623
+	protected function _registration_reports()
624
+	{
625
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
626
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
627
+			$template_path,
628
+			$this->_reports_template_data,
629
+			true
630
+		);
631
+		// the final template wrapper
632
+		$this->display_admin_page_with_no_sidebar();
633
+	}
634 634
 
635 635
 
636
-    /**
637
-     * Generates Business Report showing total registrations per day.
638
-     *
639
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
640
-     * @return string
641
-     * @throws EE_Error
642
-     * @throws InvalidArgumentException
643
-     * @throws InvalidDataTypeException
644
-     * @throws InvalidInterfaceException
645
-     */
646
-    private function _registrations_per_day_report($period = '-1 month')
647
-    {
648
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
649
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
650
-        $results = (array) $results;
651
-        $regs = array();
652
-        $subtitle = '';
653
-        if ($results) {
654
-            $column_titles = array();
655
-            $tracker = 0;
656
-            foreach ($results as $result) {
657
-                $report_column_values = array();
658
-                foreach ($result as $property_name => $property_value) {
659
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
660
-                        : (int) $property_value;
661
-                    $report_column_values[] = $property_value;
662
-                    if ($tracker === 0) {
663
-                        if ($property_name === 'Registration_REG_date') {
664
-                            $column_titles[] = esc_html__(
665
-                                'Date (only days with registrations are shown)',
666
-                                'event_espresso'
667
-                            );
668
-                        } else {
669
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
670
-                        }
671
-                    }
672
-                }
673
-                $tracker++;
674
-                $regs[] = $report_column_values;
675
-            }
676
-            // make sure the column_titles is pushed to the beginning of the array
677
-            array_unshift($regs, $column_titles);
678
-            // setup the date range.
679
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
681
-            $ending_date = new DateTime("now", $DateTimeZone);
682
-            $subtitle = sprintf(
683
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
684
-                $beginning_date->format('Y-m-d'),
685
-                $ending_date->format('Y-m-d')
686
-            );
687
-        }
688
-        $report_title = esc_html__('Total Registrations per Day', 'event_espresso');
689
-        $report_params = array(
690
-            'title'     => $report_title,
691
-            'subtitle'  => $subtitle,
692
-            'id'        => $report_ID,
693
-            'regs'      => $regs,
694
-            'noResults' => empty($regs),
695
-            'noRegsMsg' => sprintf(
696
-                esc_html__(
697
-                    '%sThere are currently no registration records in the last month for this report.%s',
698
-                    'event_espresso'
699
-                ),
700
-                '<h2>' . $report_title . '</h2><p>',
701
-                '</p>'
702
-            ),
703
-        );
704
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
705
-        return $report_ID;
706
-    }
636
+	/**
637
+	 * Generates Business Report showing total registrations per day.
638
+	 *
639
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
640
+	 * @return string
641
+	 * @throws EE_Error
642
+	 * @throws InvalidArgumentException
643
+	 * @throws InvalidDataTypeException
644
+	 * @throws InvalidInterfaceException
645
+	 */
646
+	private function _registrations_per_day_report($period = '-1 month')
647
+	{
648
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
649
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
650
+		$results = (array) $results;
651
+		$regs = array();
652
+		$subtitle = '';
653
+		if ($results) {
654
+			$column_titles = array();
655
+			$tracker = 0;
656
+			foreach ($results as $result) {
657
+				$report_column_values = array();
658
+				foreach ($result as $property_name => $property_value) {
659
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
660
+						: (int) $property_value;
661
+					$report_column_values[] = $property_value;
662
+					if ($tracker === 0) {
663
+						if ($property_name === 'Registration_REG_date') {
664
+							$column_titles[] = esc_html__(
665
+								'Date (only days with registrations are shown)',
666
+								'event_espresso'
667
+							);
668
+						} else {
669
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
670
+						}
671
+					}
672
+				}
673
+				$tracker++;
674
+				$regs[] = $report_column_values;
675
+			}
676
+			// make sure the column_titles is pushed to the beginning of the array
677
+			array_unshift($regs, $column_titles);
678
+			// setup the date range.
679
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
681
+			$ending_date = new DateTime("now", $DateTimeZone);
682
+			$subtitle = sprintf(
683
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
684
+				$beginning_date->format('Y-m-d'),
685
+				$ending_date->format('Y-m-d')
686
+			);
687
+		}
688
+		$report_title = esc_html__('Total Registrations per Day', 'event_espresso');
689
+		$report_params = array(
690
+			'title'     => $report_title,
691
+			'subtitle'  => $subtitle,
692
+			'id'        => $report_ID,
693
+			'regs'      => $regs,
694
+			'noResults' => empty($regs),
695
+			'noRegsMsg' => sprintf(
696
+				esc_html__(
697
+					'%sThere are currently no registration records in the last month for this report.%s',
698
+					'event_espresso'
699
+				),
700
+				'<h2>' . $report_title . '</h2><p>',
701
+				'</p>'
702
+			),
703
+		);
704
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
705
+		return $report_ID;
706
+	}
707 707
 
708 708
 
709
-    /**
710
-     * Generates Business Report showing total registrations per event.
711
-     *
712
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
713
-     * @return string
714
-     * @throws EE_Error
715
-     * @throws InvalidArgumentException
716
-     * @throws InvalidDataTypeException
717
-     * @throws InvalidInterfaceException
718
-     */
719
-    private function _registrations_per_event_report($period = '-1 month')
720
-    {
721
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
722
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
723
-        $results = (array) $results;
724
-        $regs = array();
725
-        $subtitle = '';
726
-        if ($results) {
727
-            $column_titles = array();
728
-            $tracker = 0;
729
-            foreach ($results as $result) {
730
-                $report_column_values = array();
731
-                foreach ($result as $property_name => $property_value) {
732
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
733
-                        $property_value,
734
-                        4,
735
-                        '...'
736
-                    ) : (int) $property_value;
737
-                    $report_column_values[] = $property_value;
738
-                    if ($tracker === 0) {
739
-                        if ($property_name === 'Registration_Event') {
740
-                            $column_titles[] = esc_html__('Event', 'event_espresso');
741
-                        } else {
742
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
743
-                        }
744
-                    }
745
-                }
746
-                $tracker++;
747
-                $regs[] = $report_column_values;
748
-            }
749
-            // make sure the column_titles is pushed to the beginning of the array
750
-            array_unshift($regs, $column_titles);
751
-            // setup the date range.
752
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
754
-            $ending_date = new DateTime("now", $DateTimeZone);
755
-            $subtitle = sprintf(
756
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
757
-                $beginning_date->format('Y-m-d'),
758
-                $ending_date->format('Y-m-d')
759
-            );
760
-        }
761
-        $report_title = esc_html__('Total Registrations per Event', 'event_espresso');
762
-        $report_params = array(
763
-            'title'     => $report_title,
764
-            'subtitle'  => $subtitle,
765
-            'id'        => $report_ID,
766
-            'regs'      => $regs,
767
-            'noResults' => empty($regs),
768
-            'noRegsMsg' => sprintf(
769
-                esc_html__(
770
-                    '%sThere are currently no registration records in the last month for this report.%s',
771
-                    'event_espresso'
772
-                ),
773
-                '<h2>' . $report_title . '</h2><p>',
774
-                '</p>'
775
-            ),
776
-        );
777
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
778
-        return $report_ID;
779
-    }
709
+	/**
710
+	 * Generates Business Report showing total registrations per event.
711
+	 *
712
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
713
+	 * @return string
714
+	 * @throws EE_Error
715
+	 * @throws InvalidArgumentException
716
+	 * @throws InvalidDataTypeException
717
+	 * @throws InvalidInterfaceException
718
+	 */
719
+	private function _registrations_per_event_report($period = '-1 month')
720
+	{
721
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
722
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
723
+		$results = (array) $results;
724
+		$regs = array();
725
+		$subtitle = '';
726
+		if ($results) {
727
+			$column_titles = array();
728
+			$tracker = 0;
729
+			foreach ($results as $result) {
730
+				$report_column_values = array();
731
+				foreach ($result as $property_name => $property_value) {
732
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
733
+						$property_value,
734
+						4,
735
+						'...'
736
+					) : (int) $property_value;
737
+					$report_column_values[] = $property_value;
738
+					if ($tracker === 0) {
739
+						if ($property_name === 'Registration_Event') {
740
+							$column_titles[] = esc_html__('Event', 'event_espresso');
741
+						} else {
742
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
743
+						}
744
+					}
745
+				}
746
+				$tracker++;
747
+				$regs[] = $report_column_values;
748
+			}
749
+			// make sure the column_titles is pushed to the beginning of the array
750
+			array_unshift($regs, $column_titles);
751
+			// setup the date range.
752
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
754
+			$ending_date = new DateTime("now", $DateTimeZone);
755
+			$subtitle = sprintf(
756
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
757
+				$beginning_date->format('Y-m-d'),
758
+				$ending_date->format('Y-m-d')
759
+			);
760
+		}
761
+		$report_title = esc_html__('Total Registrations per Event', 'event_espresso');
762
+		$report_params = array(
763
+			'title'     => $report_title,
764
+			'subtitle'  => $subtitle,
765
+			'id'        => $report_ID,
766
+			'regs'      => $regs,
767
+			'noResults' => empty($regs),
768
+			'noRegsMsg' => sprintf(
769
+				esc_html__(
770
+					'%sThere are currently no registration records in the last month for this report.%s',
771
+					'event_espresso'
772
+				),
773
+				'<h2>' . $report_title . '</h2><p>',
774
+				'</p>'
775
+			),
776
+		);
777
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
778
+		return $report_ID;
779
+	}
780 780
 
781 781
 
782
-    /**
783
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
784
-     *
785
-     * @access protected
786
-     * @return void
787
-     * @throws EE_Error
788
-     * @throws InvalidArgumentException
789
-     * @throws InvalidDataTypeException
790
-     * @throws InvalidInterfaceException
791
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
792
-     */
793
-    protected function _registration_checkin_list_table()
794
-    {
795
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
796
-        $reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
797
-        /** @var EE_Registration $registration */
798
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
799
-        if (! $registration instanceof EE_Registration) {
800
-            throw new EE_Error(
801
-                sprintf(
802
-                    esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
803
-                    $reg_id
804
-                )
805
-            );
806
-        }
807
-        $attendee = $registration->attendee();
808
-        $this->_admin_page_title .= $this->get_action_link_or_button(
809
-            'new_registration',
810
-            'add-registrant',
811
-            array('event_id' => $registration->event_ID()),
812
-            'add-new-h2'
813
-        );
814
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
815
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
816
-        $legend_items = array(
817
-            'checkin'  => array(
818
-                'class' => $checked_in->cssClasses(),
819
-                'desc'  => $checked_in->legendLabel(),
820
-            ),
821
-            'checkout' => array(
822
-                'class' => $checked_out->cssClasses(),
823
-                'desc'  => $checked_out->legendLabel(),
824
-            ),
825
-        );
826
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
827
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
828
-        /** @var EE_Datetime $datetime */
829
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
830
-        $datetime_label = '';
831
-        if ($datetime instanceof EE_Datetime) {
832
-            $datetime_label = $datetime->get_dtt_display_name(true);
833
-            $datetime_label .= ! empty($datetime_label)
834
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
835
-                : $datetime->get_dtt_display_name();
836
-        }
837
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
838
-            ? EE_Admin_Page::add_query_args_and_nonce(
839
-                array(
840
-                    'action'   => 'event_registrations',
841
-                    'event_id' => $registration->event_ID(),
842
-                    'DTT_ID'   => $dtt_id,
843
-                ),
844
-                $this->_admin_base_url
845
-            )
846
-            : '';
847
-        $datetime_link = ! empty($datetime_link)
848
-            ? '<a href="' . $datetime_link . '">'
849
-              . '<span id="checkin-dtt">'
850
-              . $datetime_label
851
-              . '</span></a>'
852
-            : $datetime_label;
853
-        $attendee_name = $attendee instanceof EE_Attendee
854
-            ? $attendee->full_name()
855
-            : '';
856
-        $attendee_link = $attendee instanceof EE_Attendee
857
-            ? $attendee->get_admin_details_link()
858
-            : '';
859
-        $attendee_link = ! empty($attendee_link)
860
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
861
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
862
-              . '<span id="checkin-attendee-name">'
863
-              . $attendee_name
864
-              . '</span></a>'
865
-            : '';
866
-        $event_link = $registration->event() instanceof EE_Event
867
-            ? $registration->event()->get_admin_details_link()
868
-            : '';
869
-        $event_link = ! empty($event_link)
870
-            ? '<a href="' . $event_link . '"'
871
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
872
-              . '<span id="checkin-event-name">'
873
-              . $registration->event_name()
874
-              . '</span>'
875
-              . '</a>'
876
-            : '';
877
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
878
-            ? '<h2>' . sprintf(
879
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
880
-                $attendee_link,
881
-                $datetime_link,
882
-                $event_link
883
-            ) . '</h2>'
884
-            : '';
885
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
886
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
887
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
888
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
889
-        $this->display_admin_list_table_page_with_no_sidebar();
890
-    }
782
+	/**
783
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
784
+	 *
785
+	 * @access protected
786
+	 * @return void
787
+	 * @throws EE_Error
788
+	 * @throws InvalidArgumentException
789
+	 * @throws InvalidDataTypeException
790
+	 * @throws InvalidInterfaceException
791
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
792
+	 */
793
+	protected function _registration_checkin_list_table()
794
+	{
795
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
796
+		$reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
797
+		/** @var EE_Registration $registration */
798
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
799
+		if (! $registration instanceof EE_Registration) {
800
+			throw new EE_Error(
801
+				sprintf(
802
+					esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
803
+					$reg_id
804
+				)
805
+			);
806
+		}
807
+		$attendee = $registration->attendee();
808
+		$this->_admin_page_title .= $this->get_action_link_or_button(
809
+			'new_registration',
810
+			'add-registrant',
811
+			array('event_id' => $registration->event_ID()),
812
+			'add-new-h2'
813
+		);
814
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
815
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
816
+		$legend_items = array(
817
+			'checkin'  => array(
818
+				'class' => $checked_in->cssClasses(),
819
+				'desc'  => $checked_in->legendLabel(),
820
+			),
821
+			'checkout' => array(
822
+				'class' => $checked_out->cssClasses(),
823
+				'desc'  => $checked_out->legendLabel(),
824
+			),
825
+		);
826
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
827
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
828
+		/** @var EE_Datetime $datetime */
829
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
830
+		$datetime_label = '';
831
+		if ($datetime instanceof EE_Datetime) {
832
+			$datetime_label = $datetime->get_dtt_display_name(true);
833
+			$datetime_label .= ! empty($datetime_label)
834
+				? ' (' . $datetime->get_dtt_display_name() . ')'
835
+				: $datetime->get_dtt_display_name();
836
+		}
837
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
838
+			? EE_Admin_Page::add_query_args_and_nonce(
839
+				array(
840
+					'action'   => 'event_registrations',
841
+					'event_id' => $registration->event_ID(),
842
+					'DTT_ID'   => $dtt_id,
843
+				),
844
+				$this->_admin_base_url
845
+			)
846
+			: '';
847
+		$datetime_link = ! empty($datetime_link)
848
+			? '<a href="' . $datetime_link . '">'
849
+			  . '<span id="checkin-dtt">'
850
+			  . $datetime_label
851
+			  . '</span></a>'
852
+			: $datetime_label;
853
+		$attendee_name = $attendee instanceof EE_Attendee
854
+			? $attendee->full_name()
855
+			: '';
856
+		$attendee_link = $attendee instanceof EE_Attendee
857
+			? $attendee->get_admin_details_link()
858
+			: '';
859
+		$attendee_link = ! empty($attendee_link)
860
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
861
+			  . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
862
+			  . '<span id="checkin-attendee-name">'
863
+			  . $attendee_name
864
+			  . '</span></a>'
865
+			: '';
866
+		$event_link = $registration->event() instanceof EE_Event
867
+			? $registration->event()->get_admin_details_link()
868
+			: '';
869
+		$event_link = ! empty($event_link)
870
+			? '<a href="' . $event_link . '"'
871
+			  . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
872
+			  . '<span id="checkin-event-name">'
873
+			  . $registration->event_name()
874
+			  . '</span>'
875
+			  . '</a>'
876
+			: '';
877
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
878
+			? '<h2>' . sprintf(
879
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
880
+				$attendee_link,
881
+				$datetime_link,
882
+				$event_link
883
+			) . '</h2>'
884
+			: '';
885
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
886
+			? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
887
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
888
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
889
+		$this->display_admin_list_table_page_with_no_sidebar();
890
+	}
891 891
 
892 892
 
893
-    /**
894
-     * toggle the Check-in status for the given registration (coming from ajax)
895
-     *
896
-     * @return void (JSON)
897
-     * @throws EE_Error
898
-     * @throws InvalidArgumentException
899
-     * @throws InvalidDataTypeException
900
-     * @throws InvalidInterfaceException
901
-     */
902
-    public function toggle_checkin_status()
903
-    {
904
-        // first make sure we have the necessary data
905
-        if (! isset($this->_req_data['_regid'])) {
906
-            EE_Error::add_error(
907
-                esc_html__(
908
-                    'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
909
-                    'event_espresso'
910
-                ),
911
-                __FILE__,
912
-                __FUNCTION__,
913
-                __LINE__
914
-            );
915
-            $this->_template_args['success'] = false;
916
-            $this->_template_args['error'] = true;
917
-            $this->_return_json();
918
-        };
919
-        // do a nonce check cause we're not coming in from an normal route here.
920
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
921
-            : '';
922
-        $nonce_ref = 'checkin_nonce';
923
-        $this->_verify_nonce($nonce, $nonce_ref);
924
-        // beautiful! Made it this far so let's get the status.
925
-        $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
926
-        // setup new class to return via ajax
927
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
928
-        $this->_template_args['success'] = true;
929
-        $this->_return_json();
930
-    }
893
+	/**
894
+	 * toggle the Check-in status for the given registration (coming from ajax)
895
+	 *
896
+	 * @return void (JSON)
897
+	 * @throws EE_Error
898
+	 * @throws InvalidArgumentException
899
+	 * @throws InvalidDataTypeException
900
+	 * @throws InvalidInterfaceException
901
+	 */
902
+	public function toggle_checkin_status()
903
+	{
904
+		// first make sure we have the necessary data
905
+		if (! isset($this->_req_data['_regid'])) {
906
+			EE_Error::add_error(
907
+				esc_html__(
908
+					'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
909
+					'event_espresso'
910
+				),
911
+				__FILE__,
912
+				__FUNCTION__,
913
+				__LINE__
914
+			);
915
+			$this->_template_args['success'] = false;
916
+			$this->_template_args['error'] = true;
917
+			$this->_return_json();
918
+		};
919
+		// do a nonce check cause we're not coming in from an normal route here.
920
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
921
+			: '';
922
+		$nonce_ref = 'checkin_nonce';
923
+		$this->_verify_nonce($nonce, $nonce_ref);
924
+		// beautiful! Made it this far so let's get the status.
925
+		$new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
926
+		// setup new class to return via ajax
927
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
928
+		$this->_template_args['success'] = true;
929
+		$this->_return_json();
930
+	}
931 931
 
932 932
 
933
-    /**
934
-     * handles toggling the checkin status for the registration,
935
-     *
936
-     * @access protected
937
-     * @return int|void
938
-     * @throws EE_Error
939
-     * @throws InvalidArgumentException
940
-     * @throws InvalidDataTypeException
941
-     * @throws InvalidInterfaceException
942
-     */
943
-    protected function _toggle_checkin_status()
944
-    {
945
-        // first let's get the query args out of the way for the redirect
946
-        $query_args = array(
947
-            'action'   => 'event_registrations',
948
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
949
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
950
-        );
951
-        $new_status = false;
952
-        // bulk action check in toggle
953
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
954
-            // cycle thru checkboxes
955
-            while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
956
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
957
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
958
-            }
959
-        } elseif (isset($this->_req_data['_regid'])) {
960
-            // coming from ajax request
961
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
962
-            $query_args['DTT_ID'] = $DTT_ID;
963
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
964
-        } else {
965
-            EE_Error::add_error(
966
-                esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
967
-                __FILE__,
968
-                __FUNCTION__,
969
-                __LINE__
970
-            );
971
-        }
972
-        if (defined('DOING_AJAX')) {
973
-            return $new_status;
974
-        }
975
-        $this->_redirect_after_action(false, '', '', $query_args, true);
976
-    }
933
+	/**
934
+	 * handles toggling the checkin status for the registration,
935
+	 *
936
+	 * @access protected
937
+	 * @return int|void
938
+	 * @throws EE_Error
939
+	 * @throws InvalidArgumentException
940
+	 * @throws InvalidDataTypeException
941
+	 * @throws InvalidInterfaceException
942
+	 */
943
+	protected function _toggle_checkin_status()
944
+	{
945
+		// first let's get the query args out of the way for the redirect
946
+		$query_args = array(
947
+			'action'   => 'event_registrations',
948
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
949
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
950
+		);
951
+		$new_status = false;
952
+		// bulk action check in toggle
953
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
954
+			// cycle thru checkboxes
955
+			while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
956
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
957
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
958
+			}
959
+		} elseif (isset($this->_req_data['_regid'])) {
960
+			// coming from ajax request
961
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
962
+			$query_args['DTT_ID'] = $DTT_ID;
963
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
964
+		} else {
965
+			EE_Error::add_error(
966
+				esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
967
+				__FILE__,
968
+				__FUNCTION__,
969
+				__LINE__
970
+			);
971
+		}
972
+		if (defined('DOING_AJAX')) {
973
+			return $new_status;
974
+		}
975
+		$this->_redirect_after_action(false, '', '', $query_args, true);
976
+	}
977 977
 
978 978
 
979
-    /**
980
-     * This is toggles a single Check-in for the given registration and datetime.
981
-     *
982
-     * @param  int $REG_ID The registration we're toggling
983
-     * @param  int $DTT_ID The datetime we're toggling
984
-     * @return int The new status toggled to.
985
-     * @throws EE_Error
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidDataTypeException
988
-     * @throws InvalidInterfaceException
989
-     */
990
-    private function _toggle_checkin($REG_ID, $DTT_ID)
991
-    {
992
-        /** @var EE_Registration $REG */
993
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
994
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
995
-        if ($new_status !== false) {
996
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
997
-        } else {
998
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
999
-            $new_status = false;
1000
-        }
1001
-        return $new_status;
1002
-    }
979
+	/**
980
+	 * This is toggles a single Check-in for the given registration and datetime.
981
+	 *
982
+	 * @param  int $REG_ID The registration we're toggling
983
+	 * @param  int $DTT_ID The datetime we're toggling
984
+	 * @return int The new status toggled to.
985
+	 * @throws EE_Error
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidDataTypeException
988
+	 * @throws InvalidInterfaceException
989
+	 */
990
+	private function _toggle_checkin($REG_ID, $DTT_ID)
991
+	{
992
+		/** @var EE_Registration $REG */
993
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
994
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
995
+		if ($new_status !== false) {
996
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
997
+		} else {
998
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
999
+			$new_status = false;
1000
+		}
1001
+		return $new_status;
1002
+	}
1003 1003
 
1004 1004
 
1005
-    /**
1006
-     * Takes care of deleting multiple EE_Checkin table rows
1007
-     *
1008
-     * @access protected
1009
-     * @return void
1010
-     * @throws EE_Error
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     */
1015
-    protected function _delete_checkin_rows()
1016
-    {
1017
-        $query_args = array(
1018
-            'action'  => 'registration_checkins',
1019
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1020
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1021
-        );
1022
-        $errors = 0;
1023
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1024
-            while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1025
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1026
-                    $errors++;
1027
-                }
1028
-            }
1029
-        } else {
1030
-            EE_Error::add_error(
1031
-                esc_html__(
1032
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1033
-                    'event_espresso'
1034
-                ),
1035
-                __FILE__,
1036
-                __FUNCTION__,
1037
-                __LINE__
1038
-            );
1039
-            $this->_redirect_after_action(false, '', '', $query_args, true);
1040
-        }
1041
-        if ($errors > 0) {
1042
-            EE_Error::add_error(
1043
-                sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1044
-                __FILE__,
1045
-                __FUNCTION__,
1046
-                __LINE__
1047
-            );
1048
-        } else {
1049
-            EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
1050
-        }
1051
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1052
-    }
1005
+	/**
1006
+	 * Takes care of deleting multiple EE_Checkin table rows
1007
+	 *
1008
+	 * @access protected
1009
+	 * @return void
1010
+	 * @throws EE_Error
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 */
1015
+	protected function _delete_checkin_rows()
1016
+	{
1017
+		$query_args = array(
1018
+			'action'  => 'registration_checkins',
1019
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1020
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1021
+		);
1022
+		$errors = 0;
1023
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1024
+			while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1025
+				if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1026
+					$errors++;
1027
+				}
1028
+			}
1029
+		} else {
1030
+			EE_Error::add_error(
1031
+				esc_html__(
1032
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1033
+					'event_espresso'
1034
+				),
1035
+				__FILE__,
1036
+				__FUNCTION__,
1037
+				__LINE__
1038
+			);
1039
+			$this->_redirect_after_action(false, '', '', $query_args, true);
1040
+		}
1041
+		if ($errors > 0) {
1042
+			EE_Error::add_error(
1043
+				sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1044
+				__FILE__,
1045
+				__FUNCTION__,
1046
+				__LINE__
1047
+			);
1048
+		} else {
1049
+			EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
1050
+		}
1051
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1052
+	}
1053 1053
 
1054 1054
 
1055
-    /**
1056
-     * Deletes a single EE_Checkin row
1057
-     *
1058
-     * @return void
1059
-     * @throws EE_Error
1060
-     * @throws InvalidArgumentException
1061
-     * @throws InvalidDataTypeException
1062
-     * @throws InvalidInterfaceException
1063
-     */
1064
-    protected function _delete_checkin_row()
1065
-    {
1066
-        $query_args = array(
1067
-            'action'  => 'registration_checkins',
1068
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1069
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1070
-        );
1071
-        if (! empty($this->_req_data['CHK_ID'])) {
1072
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1073
-                EE_Error::add_error(
1074
-                    esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1075
-                    __FILE__,
1076
-                    __FUNCTION__,
1077
-                    __LINE__
1078
-                );
1079
-            } else {
1080
-                EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1081
-            }
1082
-        } else {
1083
-            EE_Error::add_error(
1084
-                esc_html__(
1085
-                    'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1086
-                    'event_espresso'
1087
-                ),
1088
-                __FILE__,
1089
-                __FUNCTION__,
1090
-                __LINE__
1091
-            );
1092
-        }
1093
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1094
-    }
1055
+	/**
1056
+	 * Deletes a single EE_Checkin row
1057
+	 *
1058
+	 * @return void
1059
+	 * @throws EE_Error
1060
+	 * @throws InvalidArgumentException
1061
+	 * @throws InvalidDataTypeException
1062
+	 * @throws InvalidInterfaceException
1063
+	 */
1064
+	protected function _delete_checkin_row()
1065
+	{
1066
+		$query_args = array(
1067
+			'action'  => 'registration_checkins',
1068
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1069
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1070
+		);
1071
+		if (! empty($this->_req_data['CHK_ID'])) {
1072
+			if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1073
+				EE_Error::add_error(
1074
+					esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1075
+					__FILE__,
1076
+					__FUNCTION__,
1077
+					__LINE__
1078
+				);
1079
+			} else {
1080
+				EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1081
+			}
1082
+		} else {
1083
+			EE_Error::add_error(
1084
+				esc_html__(
1085
+					'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1086
+					'event_espresso'
1087
+				),
1088
+				__FILE__,
1089
+				__FUNCTION__,
1090
+				__LINE__
1091
+			);
1092
+		}
1093
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1094
+	}
1095 1095
 
1096 1096
 
1097
-    /**
1098
-     *        generates HTML for the Event Registrations List Table
1099
-     *
1100
-     * @access protected
1101
-     * @return void
1102
-     * @throws EE_Error
1103
-     * @throws InvalidArgumentException
1104
-     * @throws InvalidDataTypeException
1105
-     * @throws InvalidInterfaceException
1106
-     */
1107
-    protected function _event_registrations_list_table()
1108
-    {
1109
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1110
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1111
-            ? $this->get_action_link_or_button(
1112
-                'new_registration',
1113
-                'add-registrant',
1114
-                array('event_id' => $this->_req_data['event_id']),
1115
-                'add-new-h2',
1116
-                '',
1117
-                false
1118
-            )
1119
-            : '';
1120
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1121
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1122
-        $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1123
-        $legend_items = array(
1124
-            'star-icon'        => array(
1125
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1126
-                'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1127
-            ),
1128
-            'checkin'          => array(
1129
-                'class' => $checked_in->cssClasses(),
1130
-                'desc'  => $checked_in->legendLabel(),
1131
-            ),
1132
-            'checkout'         => array(
1133
-                'class' => $checked_out->cssClasses(),
1134
-                'desc'  => $checked_out->legendLabel(),
1135
-            ),
1136
-            'nocheckinrecord'  => array(
1137
-                'class' => $checked_never->cssClasses(),
1138
-                'desc'  => $checked_never->legendLabel(),
1139
-            ),
1140
-            'approved_status'  => array(
1141
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1142
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1143
-            ),
1144
-            'cancelled_status' => array(
1145
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1146
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1147
-            ),
1148
-            'declined_status'  => array(
1149
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1150
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1151
-            ),
1152
-            'not_approved'     => array(
1153
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1154
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1155
-            ),
1156
-            'pending_status'   => array(
1157
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1158
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1159
-            ),
1160
-            'wait_list'        => array(
1161
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1162
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1163
-            ),
1164
-        );
1165
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1166
-        $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1167
-        /** @var EE_Event $event */
1168
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1169
-        $this->_template_args['before_list_table'] = $event instanceof EE_Event
1170
-            ? '<h2>' . sprintf(
1171
-                esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1172
-                EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1173
-            ) . '</h2>'
1174
-            : '';
1175
-        // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1176
-        // the event.
1177
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1178
-        $datetime = null;
1179
-        if ($event instanceof EE_Event) {
1180
-            $datetimes_on_event = $event->datetimes();
1181
-            if (count($datetimes_on_event) === 1) {
1182
-                $datetime = reset($datetimes_on_event);
1183
-            }
1184
-        }
1185
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1186
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1187
-            $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1188
-            $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1189
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1190
-            $this->_template_args['before_list_table'] .= $datetime->name();
1191
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1192
-            $this->_template_args['before_list_table'] .= '</span></h2>';
1193
-        }
1194
-        // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1195
-        // column represents
1196
-        if (! $datetime instanceof EE_Datetime) {
1197
-            $this->_template_args['before_list_table'] .= '<br><p class="description">'
1198
-                                                          . esc_html__(
1199
-                                                              'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1200
-                                                              'event_espresso'
1201
-                                                          )
1202
-                                                          . '</p>';
1203
-        }
1204
-        $this->display_admin_list_table_page_with_no_sidebar();
1205
-    }
1097
+	/**
1098
+	 *        generates HTML for the Event Registrations List Table
1099
+	 *
1100
+	 * @access protected
1101
+	 * @return void
1102
+	 * @throws EE_Error
1103
+	 * @throws InvalidArgumentException
1104
+	 * @throws InvalidDataTypeException
1105
+	 * @throws InvalidInterfaceException
1106
+	 */
1107
+	protected function _event_registrations_list_table()
1108
+	{
1109
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1110
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1111
+			? $this->get_action_link_or_button(
1112
+				'new_registration',
1113
+				'add-registrant',
1114
+				array('event_id' => $this->_req_data['event_id']),
1115
+				'add-new-h2',
1116
+				'',
1117
+				false
1118
+			)
1119
+			: '';
1120
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1121
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1122
+		$checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1123
+		$legend_items = array(
1124
+			'star-icon'        => array(
1125
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1126
+				'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1127
+			),
1128
+			'checkin'          => array(
1129
+				'class' => $checked_in->cssClasses(),
1130
+				'desc'  => $checked_in->legendLabel(),
1131
+			),
1132
+			'checkout'         => array(
1133
+				'class' => $checked_out->cssClasses(),
1134
+				'desc'  => $checked_out->legendLabel(),
1135
+			),
1136
+			'nocheckinrecord'  => array(
1137
+				'class' => $checked_never->cssClasses(),
1138
+				'desc'  => $checked_never->legendLabel(),
1139
+			),
1140
+			'approved_status'  => array(
1141
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1142
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1143
+			),
1144
+			'cancelled_status' => array(
1145
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1146
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1147
+			),
1148
+			'declined_status'  => array(
1149
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1150
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1151
+			),
1152
+			'not_approved'     => array(
1153
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1154
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1155
+			),
1156
+			'pending_status'   => array(
1157
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1158
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1159
+			),
1160
+			'wait_list'        => array(
1161
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1162
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1163
+			),
1164
+		);
1165
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1166
+		$event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1167
+		/** @var EE_Event $event */
1168
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1169
+		$this->_template_args['before_list_table'] = $event instanceof EE_Event
1170
+			? '<h2>' . sprintf(
1171
+				esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1172
+				EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1173
+			) . '</h2>'
1174
+			: '';
1175
+		// need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1176
+		// the event.
1177
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1178
+		$datetime = null;
1179
+		if ($event instanceof EE_Event) {
1180
+			$datetimes_on_event = $event->datetimes();
1181
+			if (count($datetimes_on_event) === 1) {
1182
+				$datetime = reset($datetimes_on_event);
1183
+			}
1184
+		}
1185
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1186
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1187
+			$this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1188
+			$this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1189
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1190
+			$this->_template_args['before_list_table'] .= $datetime->name();
1191
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1192
+			$this->_template_args['before_list_table'] .= '</span></h2>';
1193
+		}
1194
+		// if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1195
+		// column represents
1196
+		if (! $datetime instanceof EE_Datetime) {
1197
+			$this->_template_args['before_list_table'] .= '<br><p class="description">'
1198
+														  . esc_html__(
1199
+															  'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1200
+															  'event_espresso'
1201
+														  )
1202
+														  . '</p>';
1203
+		}
1204
+		$this->display_admin_list_table_page_with_no_sidebar();
1205
+	}
1206 1206
 
1207
-    /**
1208
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1209
-     * conditions)
1210
-     *
1211
-     * @return void ends the request by a redirect or download
1212
-     */
1213
-    public function _registrations_checkin_report()
1214
-    {
1215
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1216
-    }
1207
+	/**
1208
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1209
+	 * conditions)
1210
+	 *
1211
+	 * @return void ends the request by a redirect or download
1212
+	 */
1213
+	public function _registrations_checkin_report()
1214
+	{
1215
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1216
+	}
1217 1217
 
1218
-    /**
1219
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1220
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1221
-     *
1222
-     * @param array $request
1223
-     * @param int   $per_page
1224
-     * @param bool  $count
1225
-     * @return array
1226
-     * @throws EE_Error
1227
-     */
1228
-    protected function _get_checkin_query_params_from_request(
1229
-        $request,
1230
-        $per_page = 10,
1231
-        $count = false
1232
-    ) {
1233
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1234
-        // unlike the regular registrations list table,
1235
-        $status_ids_array = apply_filters(
1236
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1237
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1238
-        );
1239
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1240
-        return $query_params;
1241
-    }
1218
+	/**
1219
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1220
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1221
+	 *
1222
+	 * @param array $request
1223
+	 * @param int   $per_page
1224
+	 * @param bool  $count
1225
+	 * @return array
1226
+	 * @throws EE_Error
1227
+	 */
1228
+	protected function _get_checkin_query_params_from_request(
1229
+		$request,
1230
+		$per_page = 10,
1231
+		$count = false
1232
+	) {
1233
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1234
+		// unlike the regular registrations list table,
1235
+		$status_ids_array = apply_filters(
1236
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1237
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1238
+		);
1239
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1240
+		return $query_params;
1241
+	}
1242 1242
 
1243 1243
 
1244
-    /**
1245
-     * Gets registrations for an event
1246
-     *
1247
-     * @param int    $per_page
1248
-     * @param bool   $count whether to return count or data.
1249
-     * @param bool   $trash
1250
-     * @param string $orderby
1251
-     * @return EE_Registration[]|int
1252
-     * @throws EE_Error
1253
-     * @throws InvalidArgumentException
1254
-     * @throws InvalidDataTypeException
1255
-     * @throws InvalidInterfaceException
1256
-     */
1257
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1258
-    {
1259
-        // normalize some request params that get setup by the parent `get_registrations` method.
1260
-        $request = $this->_req_data;
1261
-        $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1262
-        $request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1263
-        if ($trash) {
1264
-            $request['status'] = 'trash';
1265
-        }
1266
-        $query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count);
1267
-        /**
1268
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1269
-         *
1270
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1271
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1272
-         *                             or if you have the development copy of EE you can view this at the path:
1273
-         *                             /docs/G--Model-System/model-query-params.md
1274
-         */
1275
-        $query_params['group_by'] = '';
1244
+	/**
1245
+	 * Gets registrations for an event
1246
+	 *
1247
+	 * @param int    $per_page
1248
+	 * @param bool   $count whether to return count or data.
1249
+	 * @param bool   $trash
1250
+	 * @param string $orderby
1251
+	 * @return EE_Registration[]|int
1252
+	 * @throws EE_Error
1253
+	 * @throws InvalidArgumentException
1254
+	 * @throws InvalidDataTypeException
1255
+	 * @throws InvalidInterfaceException
1256
+	 */
1257
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1258
+	{
1259
+		// normalize some request params that get setup by the parent `get_registrations` method.
1260
+		$request = $this->_req_data;
1261
+		$request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1262
+		$request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1263
+		if ($trash) {
1264
+			$request['status'] = 'trash';
1265
+		}
1266
+		$query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count);
1267
+		/**
1268
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1269
+		 *
1270
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1271
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1272
+		 *                             or if you have the development copy of EE you can view this at the path:
1273
+		 *                             /docs/G--Model-System/model-query-params.md
1274
+		 */
1275
+		$query_params['group_by'] = '';
1276 1276
 
1277
-        return $count
1278
-            ? EEM_Registration::instance()->count($query_params)
1279
-            /** @type EE_Registration[] */
1280
-            : EEM_Registration::instance()->get_all($query_params);
1281
-    }
1277
+		return $count
1278
+			? EEM_Registration::instance()->count($query_params)
1279
+			/** @type EE_Registration[] */
1280
+			: EEM_Registration::instance()->get_all($query_params);
1281
+	}
1282 1282
 }
Please login to merge, or discard this patch.
Spacing   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@  discard block
 block discarded – undo
32 32
     public function __construct($routing = true)
33 33
     {
34 34
         parent::__construct($routing);
35
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
35
+        if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
36
+            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'registrations/templates/');
37
+            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'registrations/assets/');
38
+            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registrations/assets/');
39 39
         }
40 40
     }
41 41
 
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
      */
46 46
     protected function _extend_page_config()
47 47
     {
48
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
48
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'registrations';
49 49
         $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50 50
             ? $this->_req_data['_REG_ID']
51 51
             : 0;
@@ -185,14 +185,14 @@  discard block
 block discarded – undo
185 185
             // enqueue newsletter js
186 186
             wp_enqueue_script(
187 187
                 'ee-newsletter-trigger',
188
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
188
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.js',
189 189
                 array('ee-dialog'),
190 190
                 EVENT_ESPRESSO_VERSION,
191 191
                 true
192 192
             );
193 193
             wp_enqueue_style(
194 194
                 'ee-newsletter-trigger-css',
195
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
195
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.css',
196 196
                 array(),
197 197
                 EVENT_ESPRESSO_VERSION
198 198
             );
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
     {
214 214
         wp_register_script(
215 215
             'ee-reg-reports-js',
216
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
216
+            REG_CAF_ASSETS_URL.'ee-registration-admin-reports.js',
217 217
             array('google-charts'),
218 218
             EVENT_ESPRESSO_VERSION,
219 219
             true
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
         $nonce_ref = 'get_newsletter_form_content_nonce';
300 300
         $this->_verify_nonce($nonce, $nonce_ref);
301 301
         // let's get the mtp for the incoming MTP_ ID
302
-        if (! isset($this->_req_data['GRP_ID'])) {
302
+        if ( ! isset($this->_req_data['GRP_ID'])) {
303 303
             EE_Error::add_error(
304 304
                 esc_html__(
305 305
                     'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
             $this->_return_json();
315 315
         }
316 316
         $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
-        if (! $MTPG instanceof EE_Message_Template_Group) {
317
+        if ( ! $MTPG instanceof EE_Message_Template_Group) {
318 318
             EE_Error::add_error(
319 319
                 sprintf(
320 320
                     esc_html__(
@@ -339,12 +339,12 @@  discard block
 block discarded – undo
339 339
             $field = $MTP->get('MTP_template_field');
340 340
             if ($field === 'content') {
341 341
                 $content = $MTP->get('MTP_content');
342
-                if (! empty($content['newsletter_content'])) {
342
+                if ( ! empty($content['newsletter_content'])) {
343 343
                     $template_fields['newsletter_content'] = $content['newsletter_content'];
344 344
                 }
345 345
                 continue;
346 346
             }
347
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
347
+            $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
348 348
         }
349 349
         $this->_template_args['success'] = true;
350 350
         $this->_template_args['error'] = false;
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
      */
376 376
     public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377 377
     {
378
-        if (! EE_Registry::instance()->CAP->current_user_can(
378
+        if ( ! EE_Registry::instance()->CAP->current_user_can(
379 379
             'ee_send_message',
380 380
             'espresso_registrations_newsletter_selected_send'
381 381
         )
@@ -444,17 +444,17 @@  discard block
 block discarded – undo
444 444
                 $field_id = $field === '[NEWSLETTER_CONTENT]'
445 445
                     ? 'content'
446 446
                     : $field;
447
-                $field_id = 'batch-message-' . strtolower($field_id);
447
+                $field_id = 'batch-message-'.strtolower($field_id);
448 448
                 $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449 449
                                           . $shortcode
450
-                                          . '" data-linked-input-id="' . $field_id . '">'
450
+                                          . '" data-linked-input-id="'.$field_id.'">'
451 451
                                           . $shortcode
452 452
                                           . '</span>';
453 453
             }
454
-            $codes[ $field ] = implode(', ', $available_shortcodes);
454
+            $codes[$field] = implode(', ', $available_shortcodes);
455 455
         }
456 456
         $shortcodes = $codes;
457
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
457
+        $form_template = REG_CAF_TEMPLATE_PATH.'newsletter-send-form.template.php';
458 458
         $form_template_args = array(
459 459
             'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460 460
             'form_route'        => 'newsletter_selected_send',
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
      */
623 623
     protected function _registration_reports()
624 624
     {
625
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
625
+        $template_path = EE_ADMIN_TEMPLATE.'admin_reports.template.php';
626 626
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
627 627
             $template_path,
628 628
             $this->_reports_template_data,
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
             array_unshift($regs, $column_titles);
678 678
             // setup the date range.
679 679
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
680
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
681 681
             $ending_date = new DateTime("now", $DateTimeZone);
682 682
             $subtitle = sprintf(
683 683
                 _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
                     '%sThere are currently no registration records in the last month for this report.%s',
698 698
                     'event_espresso'
699 699
                 ),
700
-                '<h2>' . $report_title . '</h2><p>',
700
+                '<h2>'.$report_title.'</h2><p>',
701 701
                 '</p>'
702 702
             ),
703 703
         );
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
             array_unshift($regs, $column_titles);
751 751
             // setup the date range.
752 752
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
753
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
754 754
             $ending_date = new DateTime("now", $DateTimeZone);
755 755
             $subtitle = sprintf(
756 756
                 _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
                     '%sThere are currently no registration records in the last month for this report.%s',
771 771
                     'event_espresso'
772 772
                 ),
773
-                '<h2>' . $report_title . '</h2><p>',
773
+                '<h2>'.$report_title.'</h2><p>',
774 774
                 '</p>'
775 775
             ),
776 776
         );
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
         $reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
797 797
         /** @var EE_Registration $registration */
798 798
         $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
799
-        if (! $registration instanceof EE_Registration) {
799
+        if ( ! $registration instanceof EE_Registration) {
800 800
             throw new EE_Error(
801 801
                 sprintf(
802 802
                     esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
@@ -831,7 +831,7 @@  discard block
 block discarded – undo
831 831
         if ($datetime instanceof EE_Datetime) {
832 832
             $datetime_label = $datetime->get_dtt_display_name(true);
833 833
             $datetime_label .= ! empty($datetime_label)
834
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
834
+                ? ' ('.$datetime->get_dtt_display_name().')'
835 835
                 : $datetime->get_dtt_display_name();
836 836
         }
837 837
         $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
             )
846 846
             : '';
847 847
         $datetime_link = ! empty($datetime_link)
848
-            ? '<a href="' . $datetime_link . '">'
848
+            ? '<a href="'.$datetime_link.'">'
849 849
               . '<span id="checkin-dtt">'
850 850
               . $datetime_label
851 851
               . '</span></a>'
@@ -857,8 +857,8 @@  discard block
 block discarded – undo
857 857
             ? $attendee->get_admin_details_link()
858 858
             : '';
859 859
         $attendee_link = ! empty($attendee_link)
860
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
861
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
860
+            ? '<a href="'.$attendee->get_admin_details_link().'"'
861
+              . ' title="'.esc_html__('Click for attendee details', 'event_espresso').'">'
862 862
               . '<span id="checkin-attendee-name">'
863 863
               . $attendee_name
864 864
               . '</span></a>'
@@ -867,25 +867,25 @@  discard block
 block discarded – undo
867 867
             ? $registration->event()->get_admin_details_link()
868 868
             : '';
869 869
         $event_link = ! empty($event_link)
870
-            ? '<a href="' . $event_link . '"'
871
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
870
+            ? '<a href="'.$event_link.'"'
871
+              . ' title="'.esc_html__('Click here to edit event.', 'event_espresso').'">'
872 872
               . '<span id="checkin-event-name">'
873 873
               . $registration->event_name()
874 874
               . '</span>'
875 875
               . '</a>'
876 876
             : '';
877 877
         $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
878
-            ? '<h2>' . sprintf(
878
+            ? '<h2>'.sprintf(
879 879
                 esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
880 880
                 $attendee_link,
881 881
                 $datetime_link,
882 882
                 $event_link
883
-            ) . '</h2>'
883
+            ).'</h2>'
884 884
             : '';
885 885
         $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
886
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
886
+            ? '<input type="hidden" name="_REG_ID" value="'.$reg_id.'">' : '';
887 887
         $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
888
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
888
+            ? '<input type="hidden" name="DTT_ID" value="'.$dtt_id.'">' : '';
889 889
         $this->display_admin_list_table_page_with_no_sidebar();
890 890
     }
891 891
 
@@ -902,7 +902,7 @@  discard block
 block discarded – undo
902 902
     public function toggle_checkin_status()
903 903
     {
904 904
         // first make sure we have the necessary data
905
-        if (! isset($this->_req_data['_regid'])) {
905
+        if ( ! isset($this->_req_data['_regid'])) {
906 906
             EE_Error::add_error(
907 907
                 esc_html__(
908 908
                     'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
@@ -924,7 +924,7 @@  discard block
 block discarded – undo
924 924
         // beautiful! Made it this far so let's get the status.
925 925
         $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
926 926
         // setup new class to return via ajax
927
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
927
+        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin '.$new_status->cssClasses();
928 928
         $this->_template_args['success'] = true;
929 929
         $this->_return_json();
930 930
     }
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         );
951 951
         $new_status = false;
952 952
         // bulk action check in toggle
953
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
953
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
954 954
             // cycle thru checkboxes
955 955
             while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
956 956
                 $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
@@ -1020,9 +1020,9 @@  discard block
 block discarded – undo
1020 1020
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1021 1021
         );
1022 1022
         $errors = 0;
1023
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1023
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1024 1024
             while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1025
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1025
+                if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1026 1026
                     $errors++;
1027 1027
                 }
1028 1028
             }
@@ -1068,8 +1068,8 @@  discard block
 block discarded – undo
1068 1068
             'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1069 1069
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1070 1070
         );
1071
-        if (! empty($this->_req_data['CHK_ID'])) {
1072
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1071
+        if ( ! empty($this->_req_data['CHK_ID'])) {
1072
+            if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1073 1073
                 EE_Error::add_error(
1074 1074
                     esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1075 1075
                     __FILE__,
@@ -1138,27 +1138,27 @@  discard block
 block discarded – undo
1138 1138
                 'desc'  => $checked_never->legendLabel(),
1139 1139
             ),
1140 1140
             'approved_status'  => array(
1141
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1141
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
1142 1142
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1143 1143
             ),
1144 1144
             'cancelled_status' => array(
1145
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1145
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1146 1146
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1147 1147
             ),
1148 1148
             'declined_status'  => array(
1149
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1149
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
1150 1150
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1151 1151
             ),
1152 1152
             'not_approved'     => array(
1153
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1153
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
1154 1154
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1155 1155
             ),
1156 1156
             'pending_status'   => array(
1157
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1157
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
1158 1158
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1159 1159
             ),
1160 1160
             'wait_list'        => array(
1161
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1161
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
1162 1162
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1163 1163
             ),
1164 1164
         );
@@ -1167,10 +1167,10 @@  discard block
 block discarded – undo
1167 1167
         /** @var EE_Event $event */
1168 1168
         $event = EEM_Event::instance()->get_one_by_ID($event_id);
1169 1169
         $this->_template_args['before_list_table'] = $event instanceof EE_Event
1170
-            ? '<h2>' . sprintf(
1170
+            ? '<h2>'.sprintf(
1171 1171
                 esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1172 1172
                 EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1173
-            ) . '</h2>'
1173
+            ).'</h2>'
1174 1174
             : '';
1175 1175
         // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1176 1176
         // the event.
@@ -1188,12 +1188,12 @@  discard block
 block discarded – undo
1188 1188
             $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1189 1189
             $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1190 1190
             $this->_template_args['before_list_table'] .= $datetime->name();
1191
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1191
+            $this->_template_args['before_list_table'] .= ' ( '.$datetime->date_and_time_range().' )';
1192 1192
             $this->_template_args['before_list_table'] .= '</span></h2>';
1193 1193
         }
1194 1194
         // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1195 1195
         // column represents
1196
-        if (! $datetime instanceof EE_Datetime) {
1196
+        if ( ! $datetime instanceof EE_Datetime) {
1197 1197
             $this->_template_args['before_list_table'] .= '<br><p class="description">'
1198 1198
                                                           . esc_html__(
1199 1199
                                                               'In this view, the check-in status represents the latest check-in record for the registration in that row.',
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/ExecuteBatchDeletion.php 3 patches
Unused Use Statements   -8 removed lines patch added patch discarded remove patch
@@ -4,21 +4,13 @@
 block discarded – undo
4 4
 
5 5
 use EE_Change_Log;
6 6
 use EE_Registry;
7
-use EEM_Event;
8
-use EEM_Price;
9
-use EEM_Ticket;
10
-use EventEspresso\core\exceptions\InvalidClassException;
11
-use EventEspresso\core\exceptions\InvalidDataTypeException;
12
-use EventEspresso\core\exceptions\InvalidInterfaceException;
13 7
 use EventEspresso\core\exceptions\UnexpectedEntityException;
14
-use EventEspresso\core\services\loaders\LoaderFactory;
15 8
 use EventEspresso\core\services\orm\tree_traversal\NodeGroupDao;
16 9
 use EventEspresso\core\services\orm\tree_traversal\ModelObjNode;
17 10
 use EventEspressoBatchRequest\Helpers\BatchRequestException;
18 11
 use EventEspressoBatchRequest\Helpers\JobParameters;
19 12
 use EventEspressoBatchRequest\Helpers\JobStepResponse;
20 13
 use EventEspressoBatchRequest\JobHandlerBaseClasses\JobHandler;
21
-use InvalidArgumentException;
22 14
 
23 15
 /**
24 16
  * Class EventDeletion
Please login to merge, or discard this patch.
Indentation   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -32,158 +32,158 @@
 block discarded – undo
32 32
  */
33 33
 class ExecuteBatchDeletion extends JobHandler
34 34
 {
35
-    /**
36
-     * @var NodeGroupDao
37
-     */
38
-    protected $model_obj_node_group_persister;
39
-    public function __construct(NodeGroupDao $model_obj_node_group_persister)
40
-    {
41
-        $this->model_obj_node_group_persister = $model_obj_node_group_persister;
42
-    }
35
+	/**
36
+	 * @var NodeGroupDao
37
+	 */
38
+	protected $model_obj_node_group_persister;
39
+	public function __construct(NodeGroupDao $model_obj_node_group_persister)
40
+	{
41
+		$this->model_obj_node_group_persister = $model_obj_node_group_persister;
42
+	}
43 43
 
44 44
 
45
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
-    /**
47
-     *
48
-     * @param JobParameters $job_parameters
49
-     * @throws BatchRequestException
50
-     * @return JobStepResponse
51
-     */
52
-    public function create_job(JobParameters $job_parameters)
53
-    {
54
-        $deletion_job_code = $job_parameters->request_datum('deletion_job_code', null);
55
-        $roots = $this->model_obj_node_group_persister->getModelObjNodesInGroup($deletion_job_code);
56
-        if ($roots === null) {
57
-            throw new UnexpectedEntityException($roots, 'array', esc_html__('The job seems to be stale. Please press the back button in your browser twice.', 'event_espresso'));
58
-        }
59
-        $models_and_ids_to_delete = [];
60
-        foreach ($roots as $root) {
61
-            if (! $root instanceof ModelObjNode) {
62
-                throw new UnexpectedEntityException($root, 'ModelObjNode');
63
-            }
64
-            $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
65
-        }
66
-        $job_parameters->set_extra_data(
67
-            [
68
-                'models_and_ids_to_delete' => $models_and_ids_to_delete
69
-            ]
70
-        );
71
-        // Find the job's actual size.
72
-        $job_size = 0;
73
-        foreach ($models_and_ids_to_delete as $model_name => $ids) {
74
-            $job_size += count($ids);
75
-        }
76
-        $job_parameters->set_job_size($job_size);
77
-        return new JobStepResponse(
78
-            $job_parameters,
79
-            esc_html__('Beginning to delete items...', 'event_espresso')
80
-        );
81
-    }
45
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
+	/**
47
+	 *
48
+	 * @param JobParameters $job_parameters
49
+	 * @throws BatchRequestException
50
+	 * @return JobStepResponse
51
+	 */
52
+	public function create_job(JobParameters $job_parameters)
53
+	{
54
+		$deletion_job_code = $job_parameters->request_datum('deletion_job_code', null);
55
+		$roots = $this->model_obj_node_group_persister->getModelObjNodesInGroup($deletion_job_code);
56
+		if ($roots === null) {
57
+			throw new UnexpectedEntityException($roots, 'array', esc_html__('The job seems to be stale. Please press the back button in your browser twice.', 'event_espresso'));
58
+		}
59
+		$models_and_ids_to_delete = [];
60
+		foreach ($roots as $root) {
61
+			if (! $root instanceof ModelObjNode) {
62
+				throw new UnexpectedEntityException($root, 'ModelObjNode');
63
+			}
64
+			$models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
65
+		}
66
+		$job_parameters->set_extra_data(
67
+			[
68
+				'models_and_ids_to_delete' => $models_and_ids_to_delete
69
+			]
70
+		);
71
+		// Find the job's actual size.
72
+		$job_size = 0;
73
+		foreach ($models_and_ids_to_delete as $model_name => $ids) {
74
+			$job_size += count($ids);
75
+		}
76
+		$job_parameters->set_job_size($job_size);
77
+		return new JobStepResponse(
78
+			$job_parameters,
79
+			esc_html__('Beginning to delete items...', 'event_espresso')
80
+		);
81
+	}
82 82
 
83
-    /**
84
-     * Performs another step of the job
85
-     * @param JobParameters $job_parameters
86
-     * @param int $batch_size
87
-     * @return JobStepResponse
88
-     * @throws BatchRequestException
89
-     */
90
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
91
-    {
92
-        // We already have the items IDs. So deleting is really fast. Let's speed it up.
93
-        $batch_size *= 10;
94
-        $units_processed = 0;
95
-        $models_and_ids_to_delete = $job_parameters->extra_datum('models_and_ids_to_delete', []);
96
-        // Build a new list of everything leftover after this request's of deletions.
97
-        $models_and_ids_remaining = [];
98
-        foreach ($models_and_ids_to_delete as $model_name => $ids_to_delete) {
99
-            if ($units_processed < $batch_size) {
100
-                $model = EE_Registry::instance()->load_model($model_name);
101
-                $ids_to_delete_this_query = array_slice($ids_to_delete, 0, $batch_size - $units_processed, true);
102
-                if ($model->has_primary_key_field()) {
103
-                    $where_conditions = [
104
-                        $model->primary_key_name() => [
105
-                            'IN',
106
-                            $ids_to_delete_this_query
107
-                        ]
108
-                    ];
109
-                } else {
110
-                    $where_conditions = [
111
-                        'OR' => []
112
-                    ];
113
-                    foreach ($ids_to_delete_this_query as $index_primary_key_string) {
114
-                        $keys_n_values = $model->parse_index_primary_key_string($index_primary_key_string);
115
-                        $where_conditions['OR'][ 'AND*' . $index_primary_key_string ] = $keys_n_values;
116
-                    }
117
-                }
118
-                // Deleting time!
119
-                // The model's deletion method reports every ROW deleted, and in the case of CPT models that will be
120
-                // two rows deleted for event CPT item. So don't rely on it for the count of items deleted.
121
-                $model->delete_permanently(
122
-                    [
123
-                        $where_conditions
124
-                    ],
125
-                    false
126
-                );
127
-                $units_processed += count($ids_to_delete_this_query);
128
-                $remaining_ids = array_diff_key($ids_to_delete, $ids_to_delete_this_query);
129
-                // If there's any more from this model, we'll do them next time.
130
-                if (count($remaining_ids) > 0) {
131
-                    $models_and_ids_remaining[ $model_name ] = $remaining_ids;
132
-                }
133
-            } else {
134
-                $models_and_ids_remaining[ $model_name ] = $models_and_ids_to_delete[ $model_name ];
135
-            }
136
-        }
137
-        $job_parameters->mark_processed($units_processed);
138
-        // All done deleting for this request. Is there anything to do next time?
139
-        if (empty($models_and_ids_remaining)) {
140
-            $job_parameters->set_status(JobParameters::status_complete);
141
-            return new JobStepResponse(
142
-                $job_parameters,
143
-                esc_html__('Deletion complete.', 'event_espresso')
144
-            );
145
-        }
146
-        $job_parameters->add_extra_data('models_and_ids_to_delete', $models_and_ids_remaining);
147
-        return new JobStepResponse(
148
-            $job_parameters,
149
-            sprintf(
150
-                esc_html__('Deleted %d items.', 'event_espresso'),
151
-                $units_processed
152
-            )
153
-        );
154
-    }
83
+	/**
84
+	 * Performs another step of the job
85
+	 * @param JobParameters $job_parameters
86
+	 * @param int $batch_size
87
+	 * @return JobStepResponse
88
+	 * @throws BatchRequestException
89
+	 */
90
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
91
+	{
92
+		// We already have the items IDs. So deleting is really fast. Let's speed it up.
93
+		$batch_size *= 10;
94
+		$units_processed = 0;
95
+		$models_and_ids_to_delete = $job_parameters->extra_datum('models_and_ids_to_delete', []);
96
+		// Build a new list of everything leftover after this request's of deletions.
97
+		$models_and_ids_remaining = [];
98
+		foreach ($models_and_ids_to_delete as $model_name => $ids_to_delete) {
99
+			if ($units_processed < $batch_size) {
100
+				$model = EE_Registry::instance()->load_model($model_name);
101
+				$ids_to_delete_this_query = array_slice($ids_to_delete, 0, $batch_size - $units_processed, true);
102
+				if ($model->has_primary_key_field()) {
103
+					$where_conditions = [
104
+						$model->primary_key_name() => [
105
+							'IN',
106
+							$ids_to_delete_this_query
107
+						]
108
+					];
109
+				} else {
110
+					$where_conditions = [
111
+						'OR' => []
112
+					];
113
+					foreach ($ids_to_delete_this_query as $index_primary_key_string) {
114
+						$keys_n_values = $model->parse_index_primary_key_string($index_primary_key_string);
115
+						$where_conditions['OR'][ 'AND*' . $index_primary_key_string ] = $keys_n_values;
116
+					}
117
+				}
118
+				// Deleting time!
119
+				// The model's deletion method reports every ROW deleted, and in the case of CPT models that will be
120
+				// two rows deleted for event CPT item. So don't rely on it for the count of items deleted.
121
+				$model->delete_permanently(
122
+					[
123
+						$where_conditions
124
+					],
125
+					false
126
+				);
127
+				$units_processed += count($ids_to_delete_this_query);
128
+				$remaining_ids = array_diff_key($ids_to_delete, $ids_to_delete_this_query);
129
+				// If there's any more from this model, we'll do them next time.
130
+				if (count($remaining_ids) > 0) {
131
+					$models_and_ids_remaining[ $model_name ] = $remaining_ids;
132
+				}
133
+			} else {
134
+				$models_and_ids_remaining[ $model_name ] = $models_and_ids_to_delete[ $model_name ];
135
+			}
136
+		}
137
+		$job_parameters->mark_processed($units_processed);
138
+		// All done deleting for this request. Is there anything to do next time?
139
+		if (empty($models_and_ids_remaining)) {
140
+			$job_parameters->set_status(JobParameters::status_complete);
141
+			return new JobStepResponse(
142
+				$job_parameters,
143
+				esc_html__('Deletion complete.', 'event_espresso')
144
+			);
145
+		}
146
+		$job_parameters->add_extra_data('models_and_ids_to_delete', $models_and_ids_remaining);
147
+		return new JobStepResponse(
148
+			$job_parameters,
149
+			sprintf(
150
+				esc_html__('Deleted %d items.', 'event_espresso'),
151
+				$units_processed
152
+			)
153
+		);
154
+	}
155 155
 
156
-    /**
157
-     * Performs any clean-up logic when we know the job is completed
158
-     * @param JobParameters $job_parameters
159
-     * @return JobStepResponse
160
-     */
161
-    public function cleanup_job(JobParameters $job_parameters)
162
-    {
163
-        $this->model_obj_node_group_persister->deleteModelObjNodesInGroup(
164
-            $job_parameters->request_datum('deletion_job_code')
165
-        );
166
-        // For backwards compatibility with how we used to delete events, make sure we still trigger the old action.
167
-        $models_and_ids_to_delete = $job_parameters->extra_datum('models_and_ids_to_delete', []);
168
-        foreach ($models_and_ids_to_delete['Event'] as $event_id) {
169
-            // Create a log entry so we know who and when this event was permanently deleted.
170
-            (EE_Change_Log::new_instance(
171
-                [
172
-                    'OBJ_ID' => $event_id,
173
-                    'OBJ_type' => 'Event',
174
-                    'LOG_message' => sprintf(
175
-                        esc_html__('Event %1$d permanently deleted using ExecuteBatchDeletion.', 'event_espresso'),
176
-                        $event_id
177
-                    )
178
-                ]
179
-            ))->save();
180
-            do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $event_id);
181
-        }
182
-        return new JobStepResponse(
183
-            $job_parameters,
184
-            esc_html__('All done', 'event_espresso')
185
-        );
186
-    }
156
+	/**
157
+	 * Performs any clean-up logic when we know the job is completed
158
+	 * @param JobParameters $job_parameters
159
+	 * @return JobStepResponse
160
+	 */
161
+	public function cleanup_job(JobParameters $job_parameters)
162
+	{
163
+		$this->model_obj_node_group_persister->deleteModelObjNodesInGroup(
164
+			$job_parameters->request_datum('deletion_job_code')
165
+		);
166
+		// For backwards compatibility with how we used to delete events, make sure we still trigger the old action.
167
+		$models_and_ids_to_delete = $job_parameters->extra_datum('models_and_ids_to_delete', []);
168
+		foreach ($models_and_ids_to_delete['Event'] as $event_id) {
169
+			// Create a log entry so we know who and when this event was permanently deleted.
170
+			(EE_Change_Log::new_instance(
171
+				[
172
+					'OBJ_ID' => $event_id,
173
+					'OBJ_type' => 'Event',
174
+					'LOG_message' => sprintf(
175
+						esc_html__('Event %1$d permanently deleted using ExecuteBatchDeletion.', 'event_espresso'),
176
+						$event_id
177
+					)
178
+				]
179
+			))->save();
180
+			do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $event_id);
181
+		}
182
+		return new JobStepResponse(
183
+			$job_parameters,
184
+			esc_html__('All done', 'event_espresso')
185
+		);
186
+	}
187 187
 }
188 188
 // End of file EventDeletion.php
189 189
 // Location: EventEspressoBatchRequest\JobHandlers/EventDeletion.php
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
         }
59 59
         $models_and_ids_to_delete = [];
60 60
         foreach ($roots as $root) {
61
-            if (! $root instanceof ModelObjNode) {
61
+            if ( ! $root instanceof ModelObjNode) {
62 62
                 throw new UnexpectedEntityException($root, 'ModelObjNode');
63 63
             }
64 64
             $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
@@ -112,7 +112,7 @@  discard block
 block discarded – undo
112 112
                     ];
113 113
                     foreach ($ids_to_delete_this_query as $index_primary_key_string) {
114 114
                         $keys_n_values = $model->parse_index_primary_key_string($index_primary_key_string);
115
-                        $where_conditions['OR'][ 'AND*' . $index_primary_key_string ] = $keys_n_values;
115
+                        $where_conditions['OR']['AND*'.$index_primary_key_string] = $keys_n_values;
116 116
                     }
117 117
                 }
118 118
                 // Deleting time!
@@ -128,10 +128,10 @@  discard block
 block discarded – undo
128 128
                 $remaining_ids = array_diff_key($ids_to_delete, $ids_to_delete_this_query);
129 129
                 // If there's any more from this model, we'll do them next time.
130 130
                 if (count($remaining_ids) > 0) {
131
-                    $models_and_ids_remaining[ $model_name ] = $remaining_ids;
131
+                    $models_and_ids_remaining[$model_name] = $remaining_ids;
132 132
                 }
133 133
             } else {
134
-                $models_and_ids_remaining[ $model_name ] = $models_and_ids_to_delete[ $model_name ];
134
+                $models_and_ids_remaining[$model_name] = $models_and_ids_to_delete[$model_name];
135 135
             }
136 136
         }
137 137
         $job_parameters->mark_processed($units_processed);
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/NodeGroupDao.php 2 patches
Indentation   +100 added lines, -100 removed lines patch added patch discarded remove patch
@@ -22,112 +22,112 @@
 block discarded – undo
22 22
  */
23 23
 class NodeGroupDao
24 24
 {
25
-    /**
26
-     * @since $VID:$
27
-     * @return mixed|void
28
-     */
29
-    public function generateGroupCode()
30
-    {
31
-        return wp_generate_password(6, false);
32
-    }
25
+	/**
26
+	 * @since $VID:$
27
+	 * @return mixed|void
28
+	 */
29
+	public function generateGroupCode()
30
+	{
31
+		return wp_generate_password(6, false);
32
+	}
33 33
 
34
-    /**
35
-     * Gets the string we put in front of the WP Option name used to store the jobs.
36
-     * @since $VID:$
37
-     * @return string
38
-     */
39
-    private function getOptionPrefix()
40
-    {
41
-        return 'ee_deletion_';
42
-    }
34
+	/**
35
+	 * Gets the string we put in front of the WP Option name used to store the jobs.
36
+	 * @since $VID:$
37
+	 * @return string
38
+	 */
39
+	private function getOptionPrefix()
40
+	{
41
+		return 'ee_deletion_';
42
+	}
43 43
 
44
-    /**
45
-     * @since $VID:$
46
-     * @param $code
47
-     * @return ModelObjNode[]
48
-     * @throws UnexpectedEntityException
49
-     */
50
-    public function getModelObjNodesInGroup($code)
51
-    {
52
-        if (! $code) {
53
-            throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
54
-        }
55
-        $deletion_data = get_option($this->getOptionPrefix() . $code, []);
56
-        foreach ($deletion_data as $root) {
57
-            if (! $root instanceof ModelObjNode) {
58
-                throw new UnexpectedEntityException($root, 'ModelObjNode');
59
-            }
60
-        }
61
-        return $deletion_data;
62
-    }
44
+	/**
45
+	 * @since $VID:$
46
+	 * @param $code
47
+	 * @return ModelObjNode[]
48
+	 * @throws UnexpectedEntityException
49
+	 */
50
+	public function getModelObjNodesInGroup($code)
51
+	{
52
+		if (! $code) {
53
+			throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
54
+		}
55
+		$deletion_data = get_option($this->getOptionPrefix() . $code, []);
56
+		foreach ($deletion_data as $root) {
57
+			if (! $root instanceof ModelObjNode) {
58
+				throw new UnexpectedEntityException($root, 'ModelObjNode');
59
+			}
60
+		}
61
+		return $deletion_data;
62
+	}
63 63
 
64
-    /**
65
-     * Gets an array indicating what database rows are contained in the job.
66
-     * Each top-level key is a model name, and its value is an array of IDs.
67
-     * @since $VID:$
68
-     * @param ModelObjNode[] $model_obj_nodes
69
-     * @return array
70
-     * @throws EE_Error
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws InvalidArgumentException
74
-     * @throws ReflectionException
75
-     */
76
-    public function getModelsAndIdsContainedIn($model_obj_nodes)
77
-    {
78
-        $models_and_ids_to_delete = [];
79
-        foreach ($model_obj_nodes as $root) {
80
-            $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
81
-        }
82
-        return $models_and_ids_to_delete;
83
-    }
64
+	/**
65
+	 * Gets an array indicating what database rows are contained in the job.
66
+	 * Each top-level key is a model name, and its value is an array of IDs.
67
+	 * @since $VID:$
68
+	 * @param ModelObjNode[] $model_obj_nodes
69
+	 * @return array
70
+	 * @throws EE_Error
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws InvalidArgumentException
74
+	 * @throws ReflectionException
75
+	 */
76
+	public function getModelsAndIdsContainedIn($model_obj_nodes)
77
+	{
78
+		$models_and_ids_to_delete = [];
79
+		foreach ($model_obj_nodes as $root) {
80
+			$models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
81
+		}
82
+		return $models_and_ids_to_delete;
83
+	}
84 84
 
85
-    /**
86
-     * Gets an array indicating what database rows are contained in the job.
87
-     * Each top-level key is a model name, and its value is an array of IDs.
88
-     * @since $VID:$
89
-     * @param string $code
90
-     * @return array
91
-     * @throws EE_Error
92
-     * @throws InvalidArgumentException
93
-     * @throws InvalidDataTypeException
94
-     * @throws InvalidInterfaceException
95
-     * @throws ReflectionException
96
-     * @throws UnexpectedEntityException
97
-     */
98
-    public function getModelsAndIdsFromGroup($code)
99
-    {
100
-        $model_obj_nodes = $this->getModelObjNodesInGroup($code);
101
-        return $this->getModelsAndIdsContainedIn($model_obj_nodes);
102
-    }
85
+	/**
86
+	 * Gets an array indicating what database rows are contained in the job.
87
+	 * Each top-level key is a model name, and its value is an array of IDs.
88
+	 * @since $VID:$
89
+	 * @param string $code
90
+	 * @return array
91
+	 * @throws EE_Error
92
+	 * @throws InvalidArgumentException
93
+	 * @throws InvalidDataTypeException
94
+	 * @throws InvalidInterfaceException
95
+	 * @throws ReflectionException
96
+	 * @throws UnexpectedEntityException
97
+	 */
98
+	public function getModelsAndIdsFromGroup($code)
99
+	{
100
+		$model_obj_nodes = $this->getModelObjNodesInGroup($code);
101
+		return $this->getModelsAndIdsContainedIn($model_obj_nodes);
102
+	}
103 103
 
104
-    /**
105
-     * Persists the ModelObjNodes for future requests, using the code for reference.
106
-     * @since $VID:$
107
-     * @param ModelObjNode[] $model_obj_nodes
108
-     * @param string $code
109
-     * @return bool
110
-     */
111
-    public function persistModelObjNodesGroup($model_obj_nodes, $code)
112
-    {
113
-        return add_option(
114
-            $this->getOptionPrefix() . $code,
115
-            $model_obj_nodes,
116
-            null,
117
-            'no'
118
-        );
119
-    }
104
+	/**
105
+	 * Persists the ModelObjNodes for future requests, using the code for reference.
106
+	 * @since $VID:$
107
+	 * @param ModelObjNode[] $model_obj_nodes
108
+	 * @param string $code
109
+	 * @return bool
110
+	 */
111
+	public function persistModelObjNodesGroup($model_obj_nodes, $code)
112
+	{
113
+		return add_option(
114
+			$this->getOptionPrefix() . $code,
115
+			$model_obj_nodes,
116
+			null,
117
+			'no'
118
+		);
119
+	}
120 120
 
121
-    /**
122
-     * Forgets about the group of ModelObjNodes. Doesn't delete the rows in the database they reference though.
123
-     * @since $VID:$
124
-     * @param $code
125
-     * @return bool
126
-     */
127
-    public function deleteModelObjNodesInGroup($code)
128
-    {
129
-        return delete_option($this->getOptionPrefix() . $code);
130
-    }
121
+	/**
122
+	 * Forgets about the group of ModelObjNodes. Doesn't delete the rows in the database they reference though.
123
+	 * @since $VID:$
124
+	 * @param $code
125
+	 * @return bool
126
+	 */
127
+	public function deleteModelObjNodesInGroup($code)
128
+	{
129
+		return delete_option($this->getOptionPrefix() . $code);
130
+	}
131 131
 }
132 132
 // End of file NodeGroupDao.php
133 133
 // Location: EventEspresso\core\services\orm\tree_traversal/NodeGroupDao.php
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -49,12 +49,12 @@  discard block
 block discarded – undo
49 49
      */
50 50
     public function getModelObjNodesInGroup($code)
51 51
     {
52
-        if (! $code) {
52
+        if ( ! $code) {
53 53
             throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
54 54
         }
55
-        $deletion_data = get_option($this->getOptionPrefix() . $code, []);
55
+        $deletion_data = get_option($this->getOptionPrefix().$code, []);
56 56
         foreach ($deletion_data as $root) {
57
-            if (! $root instanceof ModelObjNode) {
57
+            if ( ! $root instanceof ModelObjNode) {
58 58
                 throw new UnexpectedEntityException($root, 'ModelObjNode');
59 59
             }
60 60
         }
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
     public function persistModelObjNodesGroup($model_obj_nodes, $code)
112 112
     {
113 113
         return add_option(
114
-            $this->getOptionPrefix() . $code,
114
+            $this->getOptionPrefix().$code,
115 115
             $model_obj_nodes,
116 116
             null,
117 117
             'no'
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
      */
127 127
     public function deleteModelObjNodesInGroup($code)
128 128
     {
129
-        return delete_option($this->getOptionPrefix() . $code);
129
+        return delete_option($this->getOptionPrefix().$code);
130 130
     }
131 131
 }
132 132
 // End of file NodeGroupDao.php
Please login to merge, or discard this patch.