Completed
Branch update-venue-ui (a6984e)
by
unknown
09:20 queued 06:46
created
admin_pages/events/help_tours/Event_Edit_Help_Tour.class.php 1 patch
Indentation   +221 added lines, -221 removed lines patch added patch discarded remove patch
@@ -15,243 +15,243 @@
 block discarded – undo
15 15
 class Event_Edit_Help_Tour extends EE_Help_Tour
16 16
 {
17 17
 
18
-    protected function _set_tour_properties()
19
-    {
20
-        $this->_label = __('Event Editor Tour', 'event_espresso');
21
-        $this->_slug = $this->_is_caf ? 'event-edit-caf-joyride' : 'event-edit-joyride';
22
-    }
18
+	protected function _set_tour_properties()
19
+	{
20
+		$this->_label = __('Event Editor Tour', 'event_espresso');
21
+		$this->_slug = $this->_is_caf ? 'event-edit-caf-joyride' : 'event-edit-joyride';
22
+	}
23 23
 
24
-    protected function _set_tour_stops()
25
-    {
26
-        $this->_stops = array(
27
-            10 => array(
28
-                'content' => $this->_start(),
29
-            ),
30
-            20 => array(
31
-                'id'      => 'titlewrap',
32
-                'content' => $this->_event_title_stop(),
33
-                'options' => array(
34
-                    'tipLocation'    => 'bottom',
35
-                    'tipAdjustmentY' => -40,
36
-                ),
37
-            ),
38
-            30 => array(
39
-                'id'      => 'wp-content-editor-tools',
40
-                'content' => $this->_event_description_stop(),
41
-                'options' => array(
42
-                    'tipLocation' => 'right',
43
-                ),
44
-            ),
45
-            35 => array(
46
-                'id'      => 'espresso_event_editor_tickets',
47
-                'content' => $this->_event_pricing_stop(),
48
-                'options' => array(
49
-                    'tipLocation'    => 'top',
50
-                    'tipAdjustmentY' => -30,
51
-                ),
52
-            ),
53
-            40 => array(
54
-                'id'      => 'espresso_events_Venues_Hooks_venue_metabox_metabox',
55
-                'content' => $this->_event_venues_caf(),
56
-                'options' => array(
57
-                    'tipLocation'    => 'top',
58
-                    'tipAdjustmentY' => -30,
59
-                ),
60
-            ),
61
-            45 => array(
62
-                'id'      => 'espresso_event_editor_venue',
63
-                'content' => $this->_event_venues_stop(),
64
-                'options' => array(
65
-                    'tipLocation'    => 'top',
66
-                    'tipAdjustmentY' => -30,
67
-                ),
68
-            ),
69
-            50 => array(
70
-                'id'      => 'espresso_events_Pricing_Hooks_pricing_metabox_metabox',
71
-                'content' => $this->_event_pricing_caf(),
72
-                'options' => array(
73
-                    'tipLocation'    => 'top',
74
-                    'tipAdjustmentY' => -30,
75
-                ),
76
-            ),
77
-            60 => array(
78
-                'id'      => 'tagsdiv-post_tag',
79
-                'content' => $this->_event_post_tag_stop(),
80
-                'options' => array(
81
-                    'tipLocation' => 'left',
82
-                ),
83
-            ),
84
-            70 => array(
85
-                'id'      => 'espresso_event_categoriesdiv',
86
-                'content' => $this->_event_categories_stop(),
87
-                'options' => array(
88
-                    'tipLocation' => 'left',
89
-                ),
90
-            ),
24
+	protected function _set_tour_stops()
25
+	{
26
+		$this->_stops = array(
27
+			10 => array(
28
+				'content' => $this->_start(),
29
+			),
30
+			20 => array(
31
+				'id'      => 'titlewrap',
32
+				'content' => $this->_event_title_stop(),
33
+				'options' => array(
34
+					'tipLocation'    => 'bottom',
35
+					'tipAdjustmentY' => -40,
36
+				),
37
+			),
38
+			30 => array(
39
+				'id'      => 'wp-content-editor-tools',
40
+				'content' => $this->_event_description_stop(),
41
+				'options' => array(
42
+					'tipLocation' => 'right',
43
+				),
44
+			),
45
+			35 => array(
46
+				'id'      => 'espresso_event_editor_tickets',
47
+				'content' => $this->_event_pricing_stop(),
48
+				'options' => array(
49
+					'tipLocation'    => 'top',
50
+					'tipAdjustmentY' => -30,
51
+				),
52
+			),
53
+			40 => array(
54
+				'id'      => 'espresso_events_Venues_Hooks_venue_metabox_metabox',
55
+				'content' => $this->_event_venues_caf(),
56
+				'options' => array(
57
+					'tipLocation'    => 'top',
58
+					'tipAdjustmentY' => -30,
59
+				),
60
+			),
61
+			45 => array(
62
+				'id'      => 'espresso_event_editor_venue',
63
+				'content' => $this->_event_venues_stop(),
64
+				'options' => array(
65
+					'tipLocation'    => 'top',
66
+					'tipAdjustmentY' => -30,
67
+				),
68
+			),
69
+			50 => array(
70
+				'id'      => 'espresso_events_Pricing_Hooks_pricing_metabox_metabox',
71
+				'content' => $this->_event_pricing_caf(),
72
+				'options' => array(
73
+					'tipLocation'    => 'top',
74
+					'tipAdjustmentY' => -30,
75
+				),
76
+			),
77
+			60 => array(
78
+				'id'      => 'tagsdiv-post_tag',
79
+				'content' => $this->_event_post_tag_stop(),
80
+				'options' => array(
81
+					'tipLocation' => 'left',
82
+				),
83
+			),
84
+			70 => array(
85
+				'id'      => 'espresso_event_categoriesdiv',
86
+				'content' => $this->_event_categories_stop(),
87
+				'options' => array(
88
+					'tipLocation' => 'left',
89
+				),
90
+			),
91 91
 
92
-            80  => array(
93
-                'id'      => $this->_is_caf ? 'espresso_events_Registration_Form_Hooks_Extend_primary_questions_metabox'
94
-                    : 'espresso_events_Registration_Form_Hooks_primary_questions_metabox',
95
-                'content' => $this->_primary_question_stop_caf(),
96
-                'options' => array(
97
-                    'tipLocation' => 'left',
98
-                ),
99
-            ),
100
-            90  => array(
101
-                'id'      => 'espresso_events_Registration_Form_Hooks_Extend_additional_questions_metabox',
102
-                'content' => $this->_additional_questions_stop_caf(),
103
-                'options' => array(
104
-                    'tipLocation' => 'left',
105
-                ),
106
-            ),
107
-            100 => array(
108
-                'id'      => 'postimagediv',
109
-                'content' => $this->_featured_image_stop(),
110
-                'options' => array(
111
-                    'tipLocation' => 'left',
112
-                ),
113
-            ),
114
-            110 => array(
115
-                'id'      => 'espresso_event_editor_event_options',
116
-                'content' => $this->_event_registration_options_stop(),
117
-                'options' => array(
118
-                    'tipLocation' => 'left',
119
-                ),
120
-            ),
121
-            120 => array(
122
-                'id'      => 'submitpost',
123
-                'content' => $this->_publish_event_stop(),
124
-                'options' => array(
125
-                    'tipLocation' => 'left',
126
-                ),
127
-            ),
128
-        );
92
+			80  => array(
93
+				'id'      => $this->_is_caf ? 'espresso_events_Registration_Form_Hooks_Extend_primary_questions_metabox'
94
+					: 'espresso_events_Registration_Form_Hooks_primary_questions_metabox',
95
+				'content' => $this->_primary_question_stop_caf(),
96
+				'options' => array(
97
+					'tipLocation' => 'left',
98
+				),
99
+			),
100
+			90  => array(
101
+				'id'      => 'espresso_events_Registration_Form_Hooks_Extend_additional_questions_metabox',
102
+				'content' => $this->_additional_questions_stop_caf(),
103
+				'options' => array(
104
+					'tipLocation' => 'left',
105
+				),
106
+			),
107
+			100 => array(
108
+				'id'      => 'postimagediv',
109
+				'content' => $this->_featured_image_stop(),
110
+				'options' => array(
111
+					'tipLocation' => 'left',
112
+				),
113
+			),
114
+			110 => array(
115
+				'id'      => 'espresso_event_editor_event_options',
116
+				'content' => $this->_event_registration_options_stop(),
117
+				'options' => array(
118
+					'tipLocation' => 'left',
119
+				),
120
+			),
121
+			120 => array(
122
+				'id'      => 'submitpost',
123
+				'content' => $this->_publish_event_stop(),
124
+				'options' => array(
125
+					'tipLocation' => 'left',
126
+				),
127
+			),
128
+		);
129 129
 
130
-        if (EE_Config::instance()->admin->useAdvancedEditor()) {
131
-            unset(
132
-                // description
133
-                $this->_stops[30],
134
-                // tickets
135
-                $this->_stops[35],
136
-                // venues
137
-                $this->_stops[40],
138
-                $this->_stops[45],
139
-                // pricing
140
-                $this->_stops[50],
141
-                // questions
142
-                $this->_stops[90],
143
-                // reg options
144
-                $this->_stops[110]
145
-            );
146
-        }
147
-    }
130
+		if (EE_Config::instance()->admin->useAdvancedEditor()) {
131
+			unset(
132
+				// description
133
+				$this->_stops[30],
134
+				// tickets
135
+				$this->_stops[35],
136
+				// venues
137
+				$this->_stops[40],
138
+				$this->_stops[45],
139
+				// pricing
140
+				$this->_stops[50],
141
+				// questions
142
+				$this->_stops[90],
143
+				// reg options
144
+				$this->_stops[110]
145
+			);
146
+		}
147
+	}
148 148
 
149 149
 
150
-    protected function _start()
151
-    {
152
-        $content = '<h3>' . __('Event Editor', 'event_espresso') . '</h3>';
153
-        $content .= '<p>'
154
-                    . __(
155
-                        'This tour of the Event Editor will provide an overview of the different areas of the screen to help you understand what they are used for. Let\'s get started on setting up your first event with Event Espresso!',
156
-                        'event_espresso'
157
-                    ) . '</p>';
158
-        return $content;
159
-    }
150
+	protected function _start()
151
+	{
152
+		$content = '<h3>' . __('Event Editor', 'event_espresso') . '</h3>';
153
+		$content .= '<p>'
154
+					. __(
155
+						'This tour of the Event Editor will provide an overview of the different areas of the screen to help you understand what they are used for. Let\'s get started on setting up your first event with Event Espresso!',
156
+						'event_espresso'
157
+					) . '</p>';
158
+		return $content;
159
+	}
160 160
 
161
-    protected function _event_title_stop()
162
-    {
163
-        return '<p>Enter the title for your event in this field.</p>';
164
-    }
161
+	protected function _event_title_stop()
162
+	{
163
+		return '<p>Enter the title for your event in this field.</p>';
164
+	}
165 165
 
166
-    protected function _event_description_stop()
167
-    {
168
-        return '<p>'
169
-               . __(
170
-                   'The rich text editor can be used to add information about your event. Images and links can also be added along with your text.',
171
-                   'event_espresso'
172
-               ) . '</p>';
173
-    }
166
+	protected function _event_description_stop()
167
+	{
168
+		return '<p>'
169
+			   . __(
170
+				   'The rich text editor can be used to add information about your event. Images and links can also be added along with your text.',
171
+				   'event_espresso'
172
+			   ) . '</p>';
173
+	}
174 174
 
175
-    protected function _event_venues_caf()
176
-    {
177
-        return '<p>'
178
-               . __(
179
-                   'In this section, you can select the venue that is hosting your event.',
180
-                   'event_espresso'
181
-               ) . '</p>';
182
-    }
175
+	protected function _event_venues_caf()
176
+	{
177
+		return '<p>'
178
+			   . __(
179
+				   'In this section, you can select the venue that is hosting your event.',
180
+				   'event_espresso'
181
+			   ) . '</p>';
182
+	}
183 183
 
184
-    protected function _event_venues_stop()
185
-    {
186
-        return '<p>'
187
-               . __(
188
-                   'In this section, you can enter information about the venue that is hosting your event.',
189
-                   'event_espresso'
190
-               ) . '</p>';
191
-    }
184
+	protected function _event_venues_stop()
185
+	{
186
+		return '<p>'
187
+			   . __(
188
+				   'In this section, you can enter information about the venue that is hosting your event.',
189
+				   'event_espresso'
190
+			   ) . '</p>';
191
+	}
192 192
 
193
-    protected function _event_pricing_stop()
194
-    {
195
-        return '<p>'
196
-               . __(
197
-                   'Use the Event Datetime & Ticket section to enter details about when the event is happening and what tickets you want to offer for access to the event.',
198
-                   'event_espresso'
199
-               ) . '</p>';
200
-    }
193
+	protected function _event_pricing_stop()
194
+	{
195
+		return '<p>'
196
+			   . __(
197
+				   'Use the Event Datetime & Ticket section to enter details about when the event is happening and what tickets you want to offer for access to the event.',
198
+				   'event_espresso'
199
+			   ) . '</p>';
200
+	}
201 201
 
202
-    protected function _event_pricing_caf()
203
-    {
204
-        return '<p>'
205
-               . __(
206
-                   'Use the Event Datetimes & Ticket section to enter details about when the event is happening and what tickets you want to offer for access to the event.',
207
-                   'event_espresso'
208
-               ) . '</p>';
209
-    }
202
+	protected function _event_pricing_caf()
203
+	{
204
+		return '<p>'
205
+			   . __(
206
+				   'Use the Event Datetimes & Ticket section to enter details about when the event is happening and what tickets you want to offer for access to the event.',
207
+				   'event_espresso'
208
+			   ) . '</p>';
209
+	}
210 210
 
211
-    protected function _event_registration_options_stop()
212
-    {
213
-        return '<p>' . __('Setup custom options for your event registration.', 'event_espresso') . '</p>';
214
-    }
211
+	protected function _event_registration_options_stop()
212
+	{
213
+		return '<p>' . __('Setup custom options for your event registration.', 'event_espresso') . '</p>';
214
+	}
215 215
 
216
-    protected function _event_post_tag_stop()
217
-    {
218
-        return '<p>' . __('Quickly add tags to your event.', 'event_espresso') . '</p>';
219
-    }
216
+	protected function _event_post_tag_stop()
217
+	{
218
+		return '<p>' . __('Quickly add tags to your event.', 'event_espresso') . '</p>';
219
+	}
220 220
 
221
-    protected function _event_categories_stop()
222
-    {
223
-        return '<p>' . __('Events can also be categorized if you wish.', 'event_espresso') . '</p>';
224
-    }
221
+	protected function _event_categories_stop()
222
+	{
223
+		return '<p>' . __('Events can also be categorized if you wish.', 'event_espresso') . '</p>';
224
+	}
225 225
 
226
-    protected function _primary_question_stop_caf()
227
-    {
228
-        return '<p>'
229
-               . __(
230
-                   'Use the questions group to request information from your primary registrant.',
231
-                   'event_espresso'
232
-               ) . '</p>';
233
-    }
226
+	protected function _primary_question_stop_caf()
227
+	{
228
+		return '<p>'
229
+			   . __(
230
+				   'Use the questions group to request information from your primary registrant.',
231
+				   'event_espresso'
232
+			   ) . '</p>';
233
+	}
234 234
 
235
-    protected function _additional_questions_stop_caf()
236
-    {
237
-        return '<p>'
238
-               . __(
239
-                   'Use the questions group to request information from your additional registrant.',
240
-                   'event_espresso'
241
-               ) . '</p>';
242
-    }
235
+	protected function _additional_questions_stop_caf()
236
+	{
237
+		return '<p>'
238
+			   . __(
239
+				   'Use the questions group to request information from your additional registrant.',
240
+				   'event_espresso'
241
+			   ) . '</p>';
242
+	}
243 243
 
244
-    protected function _featured_image_stop()
245
-    {
246
-        return '<p>' . __('Set a feature image for your event here.', 'event_espresso') . '</p>';
247
-    }
244
+	protected function _featured_image_stop()
245
+	{
246
+		return '<p>' . __('Set a feature image for your event here.', 'event_espresso') . '</p>';
247
+	}
248 248
 
249
-    protected function _publish_event_stop()
250
-    {
251
-        return '<p>'
252
-               . __(
253
-                   'Easily control the state of your event. The main states are Published, Pending Review, and Draft. Additional states are Cancelled, Postponed, and Sold Out.',
254
-                   'event_espresso'
255
-               ) . '</p>';
256
-    }
249
+	protected function _publish_event_stop()
250
+	{
251
+		return '<p>'
252
+			   . __(
253
+				   'Easily control the state of your event. The main states are Published, Pending Review, and Draft. Additional states are Cancelled, Postponed, and Sold Out.',
254
+				   'event_espresso'
255
+			   ) . '</p>';
256
+	}
257 257
 }
Please login to merge, or discard this patch.
admin_pages/venues/espresso_events_Venues_Hooks.class.php 2 patches
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -15,216 +15,216 @@
 block discarded – undo
15 15
 class espresso_events_Venues_Hooks extends EE_Admin_Hooks
16 16
 {
17 17
 
18
-    /**
19
-     * @var EE_Event
20
-     */
21
-    protected $_event;
22
-
23
-
24
-    public function __construct(EE_Admin_Page $admin_page)
25
-    {
26
-        parent::__construct($admin_page);
27
-    }
28
-
29
-
30
-    protected function _set_hooks_properties()
31
-    {
32
-
33
-        $this->_name = 'venues';
34
-
35
-        if (EE_Config::instance()->admin->useAdvancedEditor()) {
36
-            $this->_metaboxes = [];
37
-            $this->_scripts_styles = [];
38
-            return;
39
-        }
40
-        $this->_metaboxes = array(
41
-            0 => array(
42
-                'page_route' => array('edit', 'create_new'),
43
-                'func'       => 'venue_metabox',
44
-                'label'      => __('Venue Details', 'event_espresso'),
45
-                'priority'   => 'high',
46
-                'context'    => 'normal',
47
-            ),
48
-        );
49
-
50
-        $this->_scripts_styles = array(
51
-            'registers' => array(
52
-                'ee_event_venues'     => array(
53
-                    'type'    => 'js',
54
-                    'url'     => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.js',
55
-                    'depends' => array('jquery'),
56
-                ),
57
-                'ee_event_venues_css' => array(
58
-                    'type' => 'css',
59
-                    'url'  => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.css',
60
-                ),
61
-            ),
62
-            'enqueues'  => array(
63
-                'ee_event_venues'     => array('edit', 'create_new'),
64
-                'ee_event_venues_css' => array('edit', 'create_new'),
65
-            ),
66
-        );
67
-
68
-        // hook into the handler for saving venue
69
-        add_filter(
70
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
71
-            array($this, 'modify_callbacks'),
72
-            10
73
-        );
74
-
75
-        // remove default ee_autosave returns for DECAF venues (not needed for CAF venues cause we have a dropdown selector)
76
-        add_filter('FHEE__Events_Admin_Page__ee_autosave_edit_do_decaf_venue_save', '__return_false');
77
-    }
78
-
79
-
80
-    public function modify_callbacks($callbacks)
81
-    {
82
-        // first remove default venue callback
83
-        foreach ($callbacks as $key => $callback) {
84
-            if ($callback[1] == '_default_venue_update') {
85
-                unset($callbacks[ $key ]);
86
-            }
87
-        }
88
-
89
-        // now let's add the caf version
90
-        $callbacks[] = array($this, 'caf_venue_update');
91
-        return $callbacks;
92
-    }
93
-
94
-
95
-    public function venue_metabox()
96
-    {
97
-        $evt_obj = $this->_adminpage_obj->get_event_object();
98
-        $evt_id = $evt_obj->ID();
99
-
100
-        // first let's see if we have a venue already
101
-        $evt_venues = ! empty($evt_id) ? $evt_obj->venues() : array();
102
-        $evt_venue = $evt_venues && is_array($evt_venues) ? reset($evt_venues) : null;
103
-        $evt_venue_id = $evt_venue instanceof EE_Venue ? $evt_venue->ID() : null;
104
-
105
-        // possibly private venues.
106
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
107
-            $vnu_where['status'] = array('IN', array('publish', 'private'));
108
-        } else {
109
-            $vnu_where['status'] = 'publish';
110
-        }
111
-
112
-        // cap checks
113
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
114
-            $vnu_where['VNU_wp_user'] = get_current_user_id();
115
-        }
116
-
117
-        $vnumdl = EE_Registry::instance()->load_model('Venue');
118
-        $venues = $vnumdl->get_all(array($vnu_where, 'order_by' => array('VNU_name' => 'ASC')));
119
-
120
-        $ven_select = array();
121
-        $ven_select[0] = __('Select a Venue', 'event_espresso');
122
-        // setup venues for selector
123
-        foreach ($venues as $venue) {
124
-            $ven_select[ $venue->ID() ] = $venue->name();
125
-        }
126
-
127
-        // if $ven_select does not have the existing venue attached to event then let's add that because we'll always
128
-        // show existing attached venues even if it's trashed (or some other restricted status).
129
-
130
-        if ($evt_venue_id && ! isset($ven_select[ $evt_venue_id ])) {
131
-            $ven_select[ $evt_venue_id ] = $evt_venue->name();
132
-            $venues = array_merge($venues, array($evt_venue));
133
-        }
134
-
135
-        $template_args['venues'] = $venues;
136
-        $template_args['evt_venue_id'] = $evt_venue_id;
137
-        $venue_selector = new EE_Select_Input(
138
-            $ven_select,
139
-            array(
140
-                'html_name'  => 'venue_id',
141
-                'html_id'    => 'venue_id',
142
-                'html_class' => 'wide',
143
-                'default'    => $evt_venue_id ? $evt_venue_id : '0'
144
-            )
145
-        );
146
-        $template_args['venue_selector'] = $venue_selector->get_html_for_input();
147
-        $enable_for_gmap = new EE_Yes_No_Input(
148
-            array(
149
-                'html_name'  => 'enable_for_gmap',
150
-                'html_id'    => 'enable_for_gmap',
151
-                'default'    => $evt_venue instanceof EE_Venue ? $evt_venue->enable_for_gmap() : false
152
-            )
153
-        );
154
-        $template_args['enable_for_gmap'] = $enable_for_gmap->get_html_for_input();
155
-        $template_args['new_venue_link'] = EEH_HTML::link(
156
-            EE_Admin_Page::add_query_args_and_nonce(
157
-                array('action' => 'create_new'),
158
-                EE_VENUES_ADMIN_URL
159
-            ),
160
-            esc_html_x('Add new Venue', 'a link to add a new venue', 'event_espresso'),
161
-            esc_html_x('Add new Venue', 'a link to add a new venue', 'event_espresso'),
162
-            'ev_new_venue_link',
163
-            'button',
164
-            'margin-left:10px;',
165
-            'target="_blank"'
166
-        );
167
-
168
-        // Decide on an info text when there are no venues to display.
169
-        $no_venues_info_txt = esc_html_x(
170
-            'You have not created any venues yet.',
171
-            'Information text displayed in the venues metabox when there are no venues to display',
172
-            'event_espresso'
173
-        );
174
-        if (empty($venues)) {
175
-            $unpublished_where = $vnu_where;
176
-            $unpublished_where['status'] = 'draft';
177
-            $unpublished_venues = $vnumdl->get_all(array($unpublished_where, 'order_by' => array('VNU_name' => 'ASC')));
178
-            if (count($unpublished_venues) > 0) {
179
-                $no_venues_info_txt = esc_html_x(
180
-                // @codingStandardsIgnoreStart
181
-                    'Use the link below to publish your venue through the venue editor so it appears here for selection.',
182
-                    // @codingStandardsIgnoreEnd
183
-                    'Information text displayed in the venues metabox when there are no venues to display',
184
-                    'event_espresso'
185
-                );
186
-            }
187
-        }
188
-        $template_args['no_venues_info'] = EEH_HTML::p(
189
-            EEH_HTML::strong($no_venues_info_txt),
190
-            'no_venues_info',
191
-            'info'
192
-        );
193
-
194
-        $template_path = empty($venues) ? EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content.template.php'
195
-            : EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content_from_manager.template.php';
196
-
197
-        // Allow events venue metabox template args filtering.
198
-        $template_args = apply_filters(
199
-            'FHEE__espresso_events_Venues_Hooks___venue_metabox__template_args',
200
-            $template_args,
201
-            $template_path
202
-        );
203
-
204
-        EEH_Template::display_template($template_path, $template_args);
205
-    }
206
-
207
-
208
-    public function caf_venue_update($evtobj, $data)
209
-    {
210
-        EE_Registry::instance()->load_model('Venue');
211
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
212
-
213
-
214
-        // first let's check if the selected venue matches any existing venue attached to the event
215
-        $evt_venue = $evtobj->venues();
216
-        $evt_venue = ! empty($evt_venue) ? array_shift($evt_venue) : null;
217
-
218
-        if (! empty($evt_venue) && $evt_venue->ID() != $venue_id) {
219
-            $evtobj->_remove_relation_to($evt_venue->ID(), 'Venue');
220
-        }
221
-
222
-        if (empty($venue_id)) {
223
-            return true;
224
-        } //no venue to attach
225
-
226
-        // this should take care of adding to revisions as well as main post object
227
-        $success = $evtobj->_add_relation_to($venue_id, 'Venue');
228
-        return ! empty($success) ? true : false;
229
-    }
18
+	/**
19
+	 * @var EE_Event
20
+	 */
21
+	protected $_event;
22
+
23
+
24
+	public function __construct(EE_Admin_Page $admin_page)
25
+	{
26
+		parent::__construct($admin_page);
27
+	}
28
+
29
+
30
+	protected function _set_hooks_properties()
31
+	{
32
+
33
+		$this->_name = 'venues';
34
+
35
+		if (EE_Config::instance()->admin->useAdvancedEditor()) {
36
+			$this->_metaboxes = [];
37
+			$this->_scripts_styles = [];
38
+			return;
39
+		}
40
+		$this->_metaboxes = array(
41
+			0 => array(
42
+				'page_route' => array('edit', 'create_new'),
43
+				'func'       => 'venue_metabox',
44
+				'label'      => __('Venue Details', 'event_espresso'),
45
+				'priority'   => 'high',
46
+				'context'    => 'normal',
47
+			),
48
+		);
49
+
50
+		$this->_scripts_styles = array(
51
+			'registers' => array(
52
+				'ee_event_venues'     => array(
53
+					'type'    => 'js',
54
+					'url'     => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.js',
55
+					'depends' => array('jquery'),
56
+				),
57
+				'ee_event_venues_css' => array(
58
+					'type' => 'css',
59
+					'url'  => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.css',
60
+				),
61
+			),
62
+			'enqueues'  => array(
63
+				'ee_event_venues'     => array('edit', 'create_new'),
64
+				'ee_event_venues_css' => array('edit', 'create_new'),
65
+			),
66
+		);
67
+
68
+		// hook into the handler for saving venue
69
+		add_filter(
70
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
71
+			array($this, 'modify_callbacks'),
72
+			10
73
+		);
74
+
75
+		// remove default ee_autosave returns for DECAF venues (not needed for CAF venues cause we have a dropdown selector)
76
+		add_filter('FHEE__Events_Admin_Page__ee_autosave_edit_do_decaf_venue_save', '__return_false');
77
+	}
78
+
79
+
80
+	public function modify_callbacks($callbacks)
81
+	{
82
+		// first remove default venue callback
83
+		foreach ($callbacks as $key => $callback) {
84
+			if ($callback[1] == '_default_venue_update') {
85
+				unset($callbacks[ $key ]);
86
+			}
87
+		}
88
+
89
+		// now let's add the caf version
90
+		$callbacks[] = array($this, 'caf_venue_update');
91
+		return $callbacks;
92
+	}
93
+
94
+
95
+	public function venue_metabox()
96
+	{
97
+		$evt_obj = $this->_adminpage_obj->get_event_object();
98
+		$evt_id = $evt_obj->ID();
99
+
100
+		// first let's see if we have a venue already
101
+		$evt_venues = ! empty($evt_id) ? $evt_obj->venues() : array();
102
+		$evt_venue = $evt_venues && is_array($evt_venues) ? reset($evt_venues) : null;
103
+		$evt_venue_id = $evt_venue instanceof EE_Venue ? $evt_venue->ID() : null;
104
+
105
+		// possibly private venues.
106
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
107
+			$vnu_where['status'] = array('IN', array('publish', 'private'));
108
+		} else {
109
+			$vnu_where['status'] = 'publish';
110
+		}
111
+
112
+		// cap checks
113
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
114
+			$vnu_where['VNU_wp_user'] = get_current_user_id();
115
+		}
116
+
117
+		$vnumdl = EE_Registry::instance()->load_model('Venue');
118
+		$venues = $vnumdl->get_all(array($vnu_where, 'order_by' => array('VNU_name' => 'ASC')));
119
+
120
+		$ven_select = array();
121
+		$ven_select[0] = __('Select a Venue', 'event_espresso');
122
+		// setup venues for selector
123
+		foreach ($venues as $venue) {
124
+			$ven_select[ $venue->ID() ] = $venue->name();
125
+		}
126
+
127
+		// if $ven_select does not have the existing venue attached to event then let's add that because we'll always
128
+		// show existing attached venues even if it's trashed (or some other restricted status).
129
+
130
+		if ($evt_venue_id && ! isset($ven_select[ $evt_venue_id ])) {
131
+			$ven_select[ $evt_venue_id ] = $evt_venue->name();
132
+			$venues = array_merge($venues, array($evt_venue));
133
+		}
134
+
135
+		$template_args['venues'] = $venues;
136
+		$template_args['evt_venue_id'] = $evt_venue_id;
137
+		$venue_selector = new EE_Select_Input(
138
+			$ven_select,
139
+			array(
140
+				'html_name'  => 'venue_id',
141
+				'html_id'    => 'venue_id',
142
+				'html_class' => 'wide',
143
+				'default'    => $evt_venue_id ? $evt_venue_id : '0'
144
+			)
145
+		);
146
+		$template_args['venue_selector'] = $venue_selector->get_html_for_input();
147
+		$enable_for_gmap = new EE_Yes_No_Input(
148
+			array(
149
+				'html_name'  => 'enable_for_gmap',
150
+				'html_id'    => 'enable_for_gmap',
151
+				'default'    => $evt_venue instanceof EE_Venue ? $evt_venue->enable_for_gmap() : false
152
+			)
153
+		);
154
+		$template_args['enable_for_gmap'] = $enable_for_gmap->get_html_for_input();
155
+		$template_args['new_venue_link'] = EEH_HTML::link(
156
+			EE_Admin_Page::add_query_args_and_nonce(
157
+				array('action' => 'create_new'),
158
+				EE_VENUES_ADMIN_URL
159
+			),
160
+			esc_html_x('Add new Venue', 'a link to add a new venue', 'event_espresso'),
161
+			esc_html_x('Add new Venue', 'a link to add a new venue', 'event_espresso'),
162
+			'ev_new_venue_link',
163
+			'button',
164
+			'margin-left:10px;',
165
+			'target="_blank"'
166
+		);
167
+
168
+		// Decide on an info text when there are no venues to display.
169
+		$no_venues_info_txt = esc_html_x(
170
+			'You have not created any venues yet.',
171
+			'Information text displayed in the venues metabox when there are no venues to display',
172
+			'event_espresso'
173
+		);
174
+		if (empty($venues)) {
175
+			$unpublished_where = $vnu_where;
176
+			$unpublished_where['status'] = 'draft';
177
+			$unpublished_venues = $vnumdl->get_all(array($unpublished_where, 'order_by' => array('VNU_name' => 'ASC')));
178
+			if (count($unpublished_venues) > 0) {
179
+				$no_venues_info_txt = esc_html_x(
180
+				// @codingStandardsIgnoreStart
181
+					'Use the link below to publish your venue through the venue editor so it appears here for selection.',
182
+					// @codingStandardsIgnoreEnd
183
+					'Information text displayed in the venues metabox when there are no venues to display',
184
+					'event_espresso'
185
+				);
186
+			}
187
+		}
188
+		$template_args['no_venues_info'] = EEH_HTML::p(
189
+			EEH_HTML::strong($no_venues_info_txt),
190
+			'no_venues_info',
191
+			'info'
192
+		);
193
+
194
+		$template_path = empty($venues) ? EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content.template.php'
195
+			: EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content_from_manager.template.php';
196
+
197
+		// Allow events venue metabox template args filtering.
198
+		$template_args = apply_filters(
199
+			'FHEE__espresso_events_Venues_Hooks___venue_metabox__template_args',
200
+			$template_args,
201
+			$template_path
202
+		);
203
+
204
+		EEH_Template::display_template($template_path, $template_args);
205
+	}
206
+
207
+
208
+	public function caf_venue_update($evtobj, $data)
209
+	{
210
+		EE_Registry::instance()->load_model('Venue');
211
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
212
+
213
+
214
+		// first let's check if the selected venue matches any existing venue attached to the event
215
+		$evt_venue = $evtobj->venues();
216
+		$evt_venue = ! empty($evt_venue) ? array_shift($evt_venue) : null;
217
+
218
+		if (! empty($evt_venue) && $evt_venue->ID() != $venue_id) {
219
+			$evtobj->_remove_relation_to($evt_venue->ID(), 'Venue');
220
+		}
221
+
222
+		if (empty($venue_id)) {
223
+			return true;
224
+		} //no venue to attach
225
+
226
+		// this should take care of adding to revisions as well as main post object
227
+		$success = $evtobj->_add_relation_to($venue_id, 'Venue');
228
+		return ! empty($success) ? true : false;
229
+	}
230 230
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -51,12 +51,12 @@  discard block
 block discarded – undo
51 51
             'registers' => array(
52 52
                 'ee_event_venues'     => array(
53 53
                     'type'    => 'js',
54
-                    'url'     => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.js',
54
+                    'url'     => EE_VENUES_ASSETS_URL.'ee-event-venues-admin.js',
55 55
                     'depends' => array('jquery'),
56 56
                 ),
57 57
                 'ee_event_venues_css' => array(
58 58
                     'type' => 'css',
59
-                    'url'  => EE_VENUES_ASSETS_URL . 'ee-event-venues-admin.css',
59
+                    'url'  => EE_VENUES_ASSETS_URL.'ee-event-venues-admin.css',
60 60
                 ),
61 61
             ),
62 62
             'enqueues'  => array(
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
         // first remove default venue callback
83 83
         foreach ($callbacks as $key => $callback) {
84 84
             if ($callback[1] == '_default_venue_update') {
85
-                unset($callbacks[ $key ]);
85
+                unset($callbacks[$key]);
86 86
             }
87 87
         }
88 88
 
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
         }
111 111
 
112 112
         // cap checks
113
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
113
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
114 114
             $vnu_where['VNU_wp_user'] = get_current_user_id();
115 115
         }
116 116
 
@@ -121,14 +121,14 @@  discard block
 block discarded – undo
121 121
         $ven_select[0] = __('Select a Venue', 'event_espresso');
122 122
         // setup venues for selector
123 123
         foreach ($venues as $venue) {
124
-            $ven_select[ $venue->ID() ] = $venue->name();
124
+            $ven_select[$venue->ID()] = $venue->name();
125 125
         }
126 126
 
127 127
         // if $ven_select does not have the existing venue attached to event then let's add that because we'll always
128 128
         // show existing attached venues even if it's trashed (or some other restricted status).
129 129
 
130
-        if ($evt_venue_id && ! isset($ven_select[ $evt_venue_id ])) {
131
-            $ven_select[ $evt_venue_id ] = $evt_venue->name();
130
+        if ($evt_venue_id && ! isset($ven_select[$evt_venue_id])) {
131
+            $ven_select[$evt_venue_id] = $evt_venue->name();
132 132
             $venues = array_merge($venues, array($evt_venue));
133 133
         }
134 134
 
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
         );
193 193
 
194 194
         $template_path = empty($venues) ? EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content.template.php'
195
-            : EE_VENUES_TEMPLATE_PATH . 'event_venues_metabox_content_from_manager.template.php';
195
+            : EE_VENUES_TEMPLATE_PATH.'event_venues_metabox_content_from_manager.template.php';
196 196
 
197 197
         // Allow events venue metabox template args filtering.
198 198
         $template_args = apply_filters(
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
         $evt_venue = $evtobj->venues();
216 216
         $evt_venue = ! empty($evt_venue) ? array_shift($evt_venue) : null;
217 217
 
218
-        if (! empty($evt_venue) && $evt_venue->ID() != $venue_id) {
218
+        if ( ! empty($evt_venue) && $evt_venue->ID() != $venue_id) {
219 219
             $evtobj->_remove_relation_to($evt_venue->ID(), 'Venue');
220 220
         }
221 221
 
Please login to merge, or discard this patch.
core/data_migration_scripts/EE_DMS_Core_4_12_0.dms.php 2 patches
Indentation   +180 added lines, -180 removed lines patch added patch discarded remove patch
@@ -10,9 +10,9 @@  discard block
 block discarded – undo
10 10
 $stages            = glob(EE_CORE . 'data_migration_scripts/4_12_0_stages/*');
11 11
 $class_to_filepath = [];
12 12
 foreach ($stages as $filepath) {
13
-    $matches = [];
14
-    preg_match('~4_12_0_stages/(.*).dmsstage.php~', $filepath, $matches);
15
-    $class_to_filepath[ $matches[1] ] = $filepath;
13
+	$matches = [];
14
+	preg_match('~4_12_0_stages/(.*).dmsstage.php~', $filepath, $matches);
15
+	$class_to_filepath[ $matches[1] ] = $filepath;
16 16
 }
17 17
 // give addons a chance to autoload their stages too
18 18
 $class_to_filepath = apply_filters('FHEE__EE_DMS_4_12_0__autoloaded_stages', $class_to_filepath);
@@ -28,63 +28,63 @@  discard block
 block discarded – undo
28 28
  */
29 29
 class EE_DMS_Core_4_12_0 extends EE_Data_Migration_Script_Base
30 30
 {
31
-    /**
32
-     *
33
-     * @param EE_DMS_Core_4_11_0 $dms_4_11
34
-     * @param TableManager|null  $table_manager
35
-     * @param TableAnalysis|null $table_analysis
36
-     */
37
-    public function __construct(
38
-        EE_DMS_Core_4_11_0 $dms_4_11,
39
-        TableManager $table_manager = null,
40
-        TableAnalysis $table_analysis = null
41
-    ) {
42
-        $this->previous_dms      = $dms_4_11;
43
-        $this->_pretty_name      = esc_html__("Data Update to Event Espresso 4.12.0", "event_espresso");
44
-        $this->_priority         = 10;
45
-        $this->_migration_stages = [
46
-            new EE_DMS_4_12_0_Event_Venues(),
47
-        ];
48
-        parent::__construct($table_manager, $table_analysis);
49
-    }
50
-
51
-
52
-    /**
53
-     * Whether to migrate or not.
54
-     *
55
-     * @param array $version_array
56
-     * @return bool
57
-     */
58
-    public function can_migrate_from_version($version_array): bool
59
-    {
60
-        $version_string = $version_array['Core'];
61
-        return $version_string
62
-               && version_compare($version_string, '4.12.0.decaf', '<')
63
-               && version_compare($version_string, '4.11.0.decaf', '>=');
64
-    }
65
-
66
-
67
-    /**
68
-     * @return bool
69
-     * @throws EE_Error
70
-     * @throws ReflectionException
71
-     */
72
-    public function schema_changes_before_migration(): bool
73
-    {
74
-        require_once EE_HELPERS . 'EEH_Activation.helper.php';
75
-
76
-        $table_name = 'esp_answer';
77
-        $sql        = " ANS_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
31
+	/**
32
+	 *
33
+	 * @param EE_DMS_Core_4_11_0 $dms_4_11
34
+	 * @param TableManager|null  $table_manager
35
+	 * @param TableAnalysis|null $table_analysis
36
+	 */
37
+	public function __construct(
38
+		EE_DMS_Core_4_11_0 $dms_4_11,
39
+		TableManager $table_manager = null,
40
+		TableAnalysis $table_analysis = null
41
+	) {
42
+		$this->previous_dms      = $dms_4_11;
43
+		$this->_pretty_name      = esc_html__("Data Update to Event Espresso 4.12.0", "event_espresso");
44
+		$this->_priority         = 10;
45
+		$this->_migration_stages = [
46
+			new EE_DMS_4_12_0_Event_Venues(),
47
+		];
48
+		parent::__construct($table_manager, $table_analysis);
49
+	}
50
+
51
+
52
+	/**
53
+	 * Whether to migrate or not.
54
+	 *
55
+	 * @param array $version_array
56
+	 * @return bool
57
+	 */
58
+	public function can_migrate_from_version($version_array): bool
59
+	{
60
+		$version_string = $version_array['Core'];
61
+		return $version_string
62
+			   && version_compare($version_string, '4.12.0.decaf', '<')
63
+			   && version_compare($version_string, '4.11.0.decaf', '>=');
64
+	}
65
+
66
+
67
+	/**
68
+	 * @return bool
69
+	 * @throws EE_Error
70
+	 * @throws ReflectionException
71
+	 */
72
+	public function schema_changes_before_migration(): bool
73
+	{
74
+		require_once EE_HELPERS . 'EEH_Activation.helper.php';
75
+
76
+		$table_name = 'esp_answer';
77
+		$sql        = " ANS_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
78 78
 					REG_ID int(10) unsigned NOT NULL,
79 79
 					QST_ID int(10) unsigned NOT NULL,
80 80
 					ANS_value text NOT NULL,
81 81
 					PRIMARY KEY  (ANS_ID),
82 82
 					KEY REG_ID (REG_ID),
83 83
 					KEY QST_ID (QST_ID)";
84
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
84
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
85 85
 
86
-        $table_name = 'esp_attendee_meta';
87
-        $sql        = "ATTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
86
+		$table_name = 'esp_attendee_meta';
87
+		$sql        = "ATTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
88 88
 				ATT_ID bigint(20) unsigned NOT NULL,
89 89
 				ATT_fname varchar(45) NOT NULL,
90 90
 				ATT_lname varchar(45) NOT NULL,
@@ -101,10 +101,10 @@  discard block
 block discarded – undo
101 101
 				KEY ATT_email (ATT_email(191)),
102 102
 				KEY ATT_lname (ATT_lname),
103 103
 				KEY ATT_fname (ATT_fname)";
104
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
104
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
105 105
 
106
-        $table_name = 'esp_checkin';
107
-        $sql        = "CHK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
106
+		$table_name = 'esp_checkin';
107
+		$sql        = "CHK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
108 108
 				REG_ID int(10) unsigned NOT NULL,
109 109
 				DTT_ID int(10) unsigned NOT NULL,
110 110
 				CHK_in tinyint(1) unsigned NOT NULL DEFAULT 1,
@@ -112,10 +112,10 @@  discard block
 block discarded – undo
112 112
 				PRIMARY KEY  (CHK_ID),
113 113
 				KEY REG_ID (REG_ID),
114 114
 				KEY DTT_ID (DTT_ID)";
115
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
115
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
116 116
 
117
-        $table_name = 'esp_country';
118
-        $sql        = "CNT_ISO varchar(2) NOT NULL,
117
+		$table_name = 'esp_country';
118
+		$sql        = "CNT_ISO varchar(2) NOT NULL,
119 119
 				CNT_ISO3 varchar(3) NOT NULL,
120 120
 				RGN_ID tinyint(3) unsigned DEFAULT NULL,
121 121
 				CNT_name varchar(45) NOT NULL,
@@ -131,32 +131,32 @@  discard block
 block discarded – undo
131 131
 				CNT_is_EU tinyint(1) DEFAULT '0',
132 132
 				CNT_active tinyint(1) DEFAULT '0',
133 133
 				PRIMARY KEY  (CNT_ISO)";
134
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
134
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
135 135
 
136
-        $table_name = 'esp_currency';
137
-        $sql        = "CUR_code varchar(6) NOT NULL,
136
+		$table_name = 'esp_currency';
137
+		$sql        = "CUR_code varchar(6) NOT NULL,
138 138
 				CUR_single varchar(45) DEFAULT 'dollar',
139 139
 				CUR_plural varchar(45) DEFAULT 'dollars',
140 140
 				CUR_sign varchar(45) DEFAULT '$',
141 141
 				CUR_dec_plc varchar(1) NOT NULL DEFAULT '2',
142 142
 				CUR_active tinyint(1) DEFAULT '0',
143 143
 				PRIMARY KEY  (CUR_code)";
144
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
145
-
146
-        // note: although this table is no longer in use,
147
-        // it hasn't been removed because then queries to the model will have errors.
148
-        // but you should expect this table and its corresponding model to be removed in
149
-        // the next few months
150
-        $table_name = 'esp_currency_payment_method';
151
-        $sql        = "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
144
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
145
+
146
+		// note: although this table is no longer in use,
147
+		// it hasn't been removed because then queries to the model will have errors.
148
+		// but you should expect this table and its corresponding model to be removed in
149
+		// the next few months
150
+		$table_name = 'esp_currency_payment_method';
151
+		$sql        = "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
152 152
 				CUR_code varchar(6) NOT NULL,
153 153
 				PMD_ID int(11) NOT NULL,
154 154
 				PRIMARY KEY  (CPM_ID),
155 155
 				KEY PMD_ID (PMD_ID)";
156
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
156
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
157 157
 
158
-        $table_name = 'esp_datetime';
159
-        $sql        = "DTT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
158
+		$table_name = 'esp_datetime';
159
+		$sql        = "DTT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
160 160
 				EVT_ID bigint(20) unsigned NOT NULL,
161 161
 			    VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
162 162
 				DTT_name varchar(255) NOT NULL DEFAULT '',
@@ -174,28 +174,28 @@  discard block
 block discarded – undo
174 174
 				KEY DTT_EVT_start (DTT_EVT_start),
175 175
 				KEY EVT_ID (EVT_ID),
176 176
 				KEY DTT_is_primary (DTT_is_primary)";
177
-        $this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
177
+		$this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
178 178
 
179
-        $table_name = "esp_datetime_ticket";
180
-        $sql        = "DTK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
179
+		$table_name = "esp_datetime_ticket";
180
+		$sql        = "DTK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
181 181
 				DTT_ID int(10) unsigned NOT NULL,
182 182
 				TKT_ID int(10) unsigned NOT NULL,
183 183
 				PRIMARY KEY  (DTK_ID),
184 184
 				KEY DTT_ID (DTT_ID),
185 185
 				KEY TKT_ID (TKT_ID)";
186
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
186
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
187 187
 
188
-        $table_name = 'esp_event_message_template';
189
-        $sql        = "EMT_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
188
+		$table_name = 'esp_event_message_template';
189
+		$sql        = "EMT_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
190 190
 				EVT_ID bigint(20) unsigned NOT NULL DEFAULT 0,
191 191
 				GRP_ID int(10) unsigned NOT NULL DEFAULT 0,
192 192
 				PRIMARY KEY  (EMT_ID),
193 193
 				KEY EVT_ID (EVT_ID),
194 194
 				KEY GRP_ID (GRP_ID)";
195
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
195
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
196 196
 
197
-        $table_name = 'esp_event_meta';
198
-        $sql        = "EVTM_ID int(10) NOT NULL AUTO_INCREMENT,
197
+		$table_name = 'esp_event_meta';
198
+		$sql        = "EVTM_ID int(10) NOT NULL AUTO_INCREMENT,
199 199
 				EVT_ID bigint(20) unsigned NOT NULL,
200 200
 			    VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
201 201
 				EVT_display_desc tinyint(1) unsigned NOT NULL DEFAULT 1,
@@ -212,10 +212,10 @@  discard block
 block discarded – undo
212 212
 				FSC_UUID varchar(25) DEFAULT NULL,
213 213
 				PRIMARY KEY  (EVTM_ID),
214 214
 				KEY EVT_ID (EVT_ID)";
215
-        $this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
215
+		$this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
216 216
 
217
-        $table_name = 'esp_event_question_group';
218
-        $sql        = "EQG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
217
+		$table_name = 'esp_event_question_group';
218
+		$sql        = "EQG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
219 219
 				EVT_ID bigint(20) unsigned NOT NULL,
220 220
 				QSG_ID int(10) unsigned NOT NULL,
221 221
 				EQG_primary tinyint(1) unsigned NOT NULL DEFAULT 0,
@@ -223,28 +223,28 @@  discard block
 block discarded – undo
223 223
 				PRIMARY KEY  (EQG_ID),
224 224
 				KEY EVT_ID (EVT_ID),
225 225
 				KEY QSG_ID (QSG_ID)";
226
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
226
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
227 227
 
228
-        $table_name = 'esp_event_venue';
229
-        $sql        = "EVV_ID int(11) NOT NULL AUTO_INCREMENT,
228
+		$table_name = 'esp_event_venue';
229
+		$sql        = "EVV_ID int(11) NOT NULL AUTO_INCREMENT,
230 230
 				EVT_ID bigint(20) unsigned NOT NULL,
231 231
 				VNU_ID bigint(20) unsigned NOT NULL,
232 232
 				EVV_primary tinyint(1) unsigned NOT NULL DEFAULT 0,
233 233
 				PRIMARY KEY  (EVV_ID)";
234
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
234
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
235 235
 
236
-        $table_name = 'esp_extra_meta';
237
-        $sql        = "EXM_ID int(11) NOT NULL AUTO_INCREMENT,
236
+		$table_name = 'esp_extra_meta';
237
+		$sql        = "EXM_ID int(11) NOT NULL AUTO_INCREMENT,
238 238
 				OBJ_ID int(11) DEFAULT NULL,
239 239
 				EXM_type varchar(45) DEFAULT NULL,
240 240
 				EXM_key varchar(45) DEFAULT NULL,
241 241
 				EXM_value text,
242 242
 				PRIMARY KEY  (EXM_ID),
243 243
 				KEY EXM_type (EXM_type,OBJ_ID,EXM_key)";
244
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
244
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
245 245
 
246
-        $table_name = 'esp_extra_join';
247
-        $sql        = "EXJ_ID int(11) NOT NULL AUTO_INCREMENT,
246
+		$table_name = 'esp_extra_join';
247
+		$sql        = "EXJ_ID int(11) NOT NULL AUTO_INCREMENT,
248 248
 				EXJ_first_model_id varchar(6) NOT NULL,
249 249
 				EXJ_first_model_name varchar(20) NOT NULL,
250 250
 				EXJ_second_model_id varchar(6) NOT NULL,
@@ -252,10 +252,10 @@  discard block
 block discarded – undo
252 252
 				PRIMARY KEY  (EXJ_ID),
253 253
 				KEY first_model (EXJ_first_model_name,EXJ_first_model_id),
254 254
 				KEY second_model (EXJ_second_model_name,EXJ_second_model_id)";
255
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
255
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
256 256
 
257
-        $table_name = 'esp_form_element';
258
-        $sql        = "FIN_UUID varchar(25) NOT NULL,
257
+		$table_name = 'esp_form_element';
258
+		$sql        = "FIN_UUID varchar(25) NOT NULL,
259 259
 				FSC_UUID varchar(25) NOT NULL,
260 260
 				FIN_adminOnly tinyint(1) unsigned NOT NULL DEFAULT 0,
261 261
 				FIN_attributes text DEFAULT NULL,
@@ -272,10 +272,10 @@  discard block
 block discarded – undo
272 272
 				KEY FSC_UUID (FSC_UUID),
273 273
 				KEY FIN_order (FIN_order),
274 274
 				KEY FIN_status (FIN_status)";
275
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
275
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
276 276
 
277
-        $table_name = 'esp_form_section';
278
-        $sql        = "FSC_UUID varchar(25) NOT NULL,
277
+		$table_name = 'esp_form_section';
278
+		$sql        = "FSC_UUID varchar(25) NOT NULL,
279 279
 				FSC_appliesTo tinytext NOT NULL,
280 280
 				FSC_attributes text DEFAULT NULL,
281 281
 				FSC_belongsTo varchar(25) DEFAULT NULL,
@@ -287,10 +287,10 @@  discard block
 block discarded – undo
287 287
 				KEY FSC_belongsTo (FSC_belongsTo),
288 288
 				KEY FSC_order (FSC_order),
289 289
 				KEY FSC_status (FSC_status)";
290
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
290
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
291 291
 
292
-        $table_name = 'esp_form_submission';
293
-        $sql        = "FSB_UUID varchar(25) NOT NULL,
292
+		$table_name = 'esp_form_submission';
293
+		$sql        = "FSB_UUID varchar(25) NOT NULL,
294 294
                 FSC_UUID varchar(25) NOT NULL,
295 295
 				TXN_ID int(10) DEFAULT NULL,
296 296
 				FSB_data mediumtext DEFAULT NULL,
@@ -298,10 +298,10 @@  discard block
 block discarded – undo
298 298
 				PRIMARY KEY  (FSB_UUID),
299 299
 				KEY FSC_UUID (FSC_UUID),
300 300
 				KEY TXN_ID (TXN_ID)";
301
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
301
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
302 302
 
303
-        $table_name   = 'esp_line_item';
304
-        $sql          = "LIN_ID int(11) NOT NULL AUTO_INCREMENT,
303
+		$table_name   = 'esp_line_item';
304
+		$sql          = "LIN_ID int(11) NOT NULL AUTO_INCREMENT,
305 305
 				LIN_code varchar(245) NOT NULL DEFAULT '',
306 306
 				TXN_ID int(10) DEFAULT NULL,
307 307
 				LIN_name varchar(245) NOT NULL DEFAULT '',
@@ -322,10 +322,10 @@  discard block
 block discarded – undo
322 322
 				KEY txn_type_timestamp (TXN_ID,LIN_type,LIN_timestamp),
323 323
 				KEY txn_obj_id_obj_type (TXN_ID,OBJ_ID,OBJ_type),
324 324
 				KEY obj_id_obj_type (OBJ_ID,OBJ_type)";
325
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
325
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
326 326
 
327
-        $table_name = 'esp_log';
328
-        $sql        = "LOG_ID int(11) NOT NULL AUTO_INCREMENT,
327
+		$table_name = 'esp_log';
328
+		$sql        = "LOG_ID int(11) NOT NULL AUTO_INCREMENT,
329 329
 				LOG_time datetime DEFAULT NULL,
330 330
 				OBJ_ID varchar(45) DEFAULT NULL,
331 331
 				OBJ_type varchar(45) DEFAULT NULL,
@@ -336,10 +336,10 @@  discard block
 block discarded – undo
336 336
 				KEY LOG_time (LOG_time),
337 337
 				KEY OBJ (OBJ_type,OBJ_ID),
338 338
 				KEY LOG_type (LOG_type)";
339
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
339
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
340 340
 
341
-        $table_name = 'esp_message';
342
-        $sql        = "MSG_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
341
+		$table_name = 'esp_message';
342
+		$sql        = "MSG_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
343 343
 				GRP_ID int(10) unsigned NULL,
344 344
 				MSG_token varchar(255) NULL,
345 345
 				TXN_ID int(10) unsigned NULL,
@@ -371,20 +371,20 @@  discard block
 block discarded – undo
371 371
 				KEY STS_ID (STS_ID),
372 372
 				KEY MSG_created (MSG_created),
373 373
 				KEY MSG_modified (MSG_modified)";
374
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
374
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
375 375
 
376
-        $table_name = 'esp_message_template';
377
-        $sql        = "MTP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
376
+		$table_name = 'esp_message_template';
377
+		$sql        = "MTP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
378 378
 				GRP_ID int(10) unsigned NOT NULL,
379 379
 				MTP_context varchar(50) NOT NULL,
380 380
 				MTP_template_field varchar(30) NOT NULL,
381 381
 				MTP_content text NOT NULL,
382 382
 				PRIMARY KEY  (MTP_ID),
383 383
 				KEY GRP_ID (GRP_ID)";
384
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
384
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
385 385
 
386
-        $table_name = 'esp_message_template_group';
387
-        $sql        = "GRP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
386
+		$table_name = 'esp_message_template_group';
387
+		$sql        = "GRP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
388 388
 				MTP_user_id int(10) NOT NULL DEFAULT '1',
389 389
 				MTP_name varchar(245) NOT NULL DEFAULT '',
390 390
 				MTP_description varchar(245) NOT NULL DEFAULT '',
@@ -396,10 +396,10 @@  discard block
 block discarded – undo
396 396
 				MTP_is_active tinyint(1) NOT NULL DEFAULT '1',
397 397
 				PRIMARY KEY  (GRP_ID),
398 398
 				KEY MTP_user_id (MTP_user_id)";
399
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
399
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
400 400
 
401
-        $table_name = 'esp_payment';
402
-        $sql        = "PAY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
401
+		$table_name = 'esp_payment';
402
+		$sql        = "PAY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
403 403
 				TXN_ID int(10) unsigned DEFAULT NULL,
404 404
 				STS_ID varchar(3) DEFAULT NULL,
405 405
 				PAY_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -416,10 +416,10 @@  discard block
 block discarded – undo
416 416
 				PRIMARY KEY  (PAY_ID),
417 417
 				KEY PAY_timestamp (PAY_timestamp),
418 418
 				KEY TXN_ID (TXN_ID)";
419
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
419
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
420 420
 
421
-        $table_name = 'esp_payment_method';
422
-        $sql        = "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
421
+		$table_name = 'esp_payment_method';
422
+		$sql        = "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
423 423
 				PMD_type varchar(124) DEFAULT NULL,
424 424
 				PMD_name varchar(255) DEFAULT NULL,
425 425
 				PMD_desc text,
@@ -435,10 +435,10 @@  discard block
 block discarded – undo
435 435
 				PRIMARY KEY  (PMD_ID),
436 436
 				UNIQUE KEY PMD_slug_UNIQUE (PMD_slug),
437 437
 				KEY PMD_type (PMD_type)";
438
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
438
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
439 439
 
440
-        $table_name = "esp_price";
441
-        $sql        = "PRC_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
440
+		$table_name = "esp_price";
441
+		$sql        = "PRC_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
442 442
 				PRT_ID tinyint(3) unsigned NOT NULL,
443 443
 				PRC_amount decimal(12,3) NOT NULL DEFAULT '0.00',
444 444
 				PRC_name varchar(245) NOT NULL,
@@ -451,10 +451,10 @@  discard block
 block discarded – undo
451 451
 				PRC_parent int(10) unsigned DEFAULT 0,
452 452
 				PRIMARY KEY  (PRC_ID),
453 453
 				KEY PRT_ID (PRT_ID)";
454
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
454
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
455 455
 
456
-        $table_name = "esp_price_type";
457
-        $sql        = "PRT_ID tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
456
+		$table_name = "esp_price_type";
457
+		$sql        = "PRT_ID tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
458 458
 				PRT_name varchar(45) NOT NULL,
459 459
 				PBT_ID tinyint(3) unsigned NOT NULL DEFAULT '1',
460 460
 				PRT_is_percent tinyint(1) NOT NULL DEFAULT '0',
@@ -463,27 +463,27 @@  discard block
 block discarded – undo
463 463
 				PRT_deleted tinyint(1) NOT NULL DEFAULT '0',
464 464
 				UNIQUE KEY PRT_name_UNIQUE (PRT_name),
465 465
 				PRIMARY KEY  (PRT_ID)";
466
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
466
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
467 467
 
468
-        $table_name = "esp_ticket_price";
469
-        $sql        = "TKP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
468
+		$table_name = "esp_ticket_price";
469
+		$sql        = "TKP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
470 470
 				TKT_ID int(10) unsigned NOT NULL,
471 471
 				PRC_ID int(10) unsigned NOT NULL,
472 472
 				PRIMARY KEY  (TKP_ID),
473 473
 				KEY TKT_ID (TKT_ID),
474 474
 				KEY PRC_ID (PRC_ID)";
475
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
475
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
476 476
 
477
-        $table_name = "esp_ticket_template";
478
-        $sql        = "TTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
477
+		$table_name = "esp_ticket_template";
478
+		$sql        = "TTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
479 479
 				TTM_name varchar(45) NOT NULL,
480 480
 				TTM_description text,
481 481
 				TTM_file varchar(45),
482 482
 				PRIMARY KEY  (TTM_ID)";
483
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
483
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
484 484
 
485
-        $table_name = 'esp_question';
486
-        $sql        = 'QST_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
485
+		$table_name = 'esp_question';
486
+		$sql        = 'QST_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
487 487
 				QST_display_text text NOT NULL,
488 488
 				QST_admin_label varchar(255) NOT NULL,
489 489
 				QST_system varchar(25) DEFAULT NULL,
@@ -497,10 +497,10 @@  discard block
 block discarded – undo
497 497
 				QST_deleted tinyint(2) unsigned NOT NULL DEFAULT 0,
498 498
 				PRIMARY KEY  (QST_ID),
499 499
 				KEY QST_order (QST_order)';
500
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
500
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
501 501
 
502
-        $table_name = 'esp_question_group';
503
-        $sql        = 'QSG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
502
+		$table_name = 'esp_question_group';
503
+		$sql        = 'QSG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
504 504
 				QSG_name varchar(255) NOT NULL,
505 505
 				QSG_identifier varchar(100) NOT NULL,
506 506
 				QSG_desc text NULL,
@@ -513,20 +513,20 @@  discard block
 block discarded – undo
513 513
 				PRIMARY KEY  (QSG_ID),
514 514
 				UNIQUE KEY QSG_identifier_UNIQUE (QSG_identifier),
515 515
 				KEY QSG_order (QSG_order)';
516
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
516
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
517 517
 
518
-        $table_name = 'esp_question_group_question';
519
-        $sql        = "QGQ_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
518
+		$table_name = 'esp_question_group_question';
519
+		$sql        = "QGQ_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
520 520
 				QSG_ID int(10) unsigned NOT NULL,
521 521
 				QST_ID int(10) unsigned NOT NULL,
522 522
 				QGQ_order int(10) unsigned NOT NULL DEFAULT 0,
523 523
 				PRIMARY KEY  (QGQ_ID),
524 524
 				KEY QST_ID (QST_ID),
525 525
 				KEY QSG_ID_order (QSG_ID,QGQ_order)";
526
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
526
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
527 527
 
528
-        $table_name = 'esp_question_option';
529
-        $sql        = "QSO_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
528
+		$table_name = 'esp_question_option';
529
+		$sql        = "QSO_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
530 530
 				QSO_value varchar(255) NOT NULL,
531 531
 				QSO_desc text NOT NULL,
532 532
 				QST_ID int(10) unsigned NOT NULL,
@@ -536,10 +536,10 @@  discard block
 block discarded – undo
536 536
 				PRIMARY KEY  (QSO_ID),
537 537
 				KEY QST_ID (QST_ID),
538 538
 				KEY QSO_order (QSO_order)";
539
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
539
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
540 540
 
541
-        $table_name = 'esp_registration';
542
-        $sql        = "REG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
541
+		$table_name = 'esp_registration';
542
+		$sql        = "REG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
543 543
 				EVT_ID bigint(20) unsigned NOT NULL,
544 544
 				ATT_ID bigint(20) unsigned NOT NULL,
545 545
 				TXN_ID int(10) unsigned NOT NULL,
@@ -563,20 +563,20 @@  discard block
 block discarded – undo
563 563
 				KEY TKT_ID (TKT_ID),
564 564
 				KEY EVT_ID (EVT_ID),
565 565
 				KEY STS_ID (STS_ID)";
566
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
566
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
567 567
 
568
-        $table_name = 'esp_registration_payment';
569
-        $sql        = "RPY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
568
+		$table_name = 'esp_registration_payment';
569
+		$sql        = "RPY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
570 570
 					  REG_ID int(10) unsigned NOT NULL,
571 571
 					  PAY_ID int(10) unsigned NULL,
572 572
 					  RPY_amount decimal(12,3) NOT NULL DEFAULT '0.00',
573 573
 					  PRIMARY KEY  (RPY_ID),
574 574
 					  KEY REG_ID (REG_ID),
575 575
 					  KEY PAY_ID (PAY_ID)";
576
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
576
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB ');
577 577
 
578
-        $table_name = 'esp_state';
579
-        $sql        = "STA_ID smallint(5) unsigned NOT NULL AUTO_INCREMENT,
578
+		$table_name = 'esp_state';
579
+		$sql        = "STA_ID smallint(5) unsigned NOT NULL AUTO_INCREMENT,
580 580
 				CNT_ISO varchar(2) NOT NULL,
581 581
 				STA_abbrev varchar(24) NOT NULL,
582 582
 				STA_name varchar(100) NOT NULL,
@@ -584,10 +584,10 @@  discard block
 block discarded – undo
584 584
 				PRIMARY KEY  (STA_ID),
585 585
 				KEY STA_abbrev (STA_abbrev),
586 586
 				KEY CNT_ISO (CNT_ISO)";
587
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
587
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
588 588
 
589
-        $table_name = 'esp_status';
590
-        $sql        = "STS_ID varchar(3) NOT NULL,
589
+		$table_name = 'esp_status';
590
+		$sql        = "STS_ID varchar(3) NOT NULL,
591 591
 				STS_code varchar(45) NOT NULL,
592 592
 				STS_type varchar(45) NOT NULL,
593 593
 				STS_can_edit tinyint(1) NOT NULL DEFAULT 0,
@@ -595,10 +595,10 @@  discard block
 block discarded – undo
595 595
 				STS_open tinyint(1) NOT NULL DEFAULT 1,
596 596
 				UNIQUE KEY STS_ID_UNIQUE (STS_ID),
597 597
 				KEY STS_type (STS_type)";
598
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
598
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
599 599
 
600
-        $table_name = "esp_ticket";
601
-        $sql        = "TKT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
600
+		$table_name = "esp_ticket";
601
+		$sql        = "TKT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
602 602
 				TTM_ID int(10) unsigned NOT NULL,
603 603
 				TKT_name varchar(245) NOT NULL DEFAULT '',
604 604
 				TKT_description text NOT NULL,
@@ -623,10 +623,10 @@  discard block
 block discarded – undo
623 623
 				TKT_visibility smallint(6) unsigned NOT NULL DEFAULT 100,
624 624
 				PRIMARY KEY  (TKT_ID),
625 625
 				KEY TKT_start_date (TKT_start_date)";
626
-        $this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
626
+		$this->_table_is_changed_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
627 627
 
628
-        $table_name = 'esp_transaction';
629
-        $sql        = "TXN_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
628
+		$table_name = 'esp_transaction';
629
+		$sql        = "TXN_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
630 630
 				TXN_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
631 631
 				TXN_total decimal(12,3) DEFAULT '0.00',
632 632
 				TXN_paid decimal(12,3) NOT NULL DEFAULT '0.00',
@@ -638,10 +638,10 @@  discard block
 block discarded – undo
638 638
 				PRIMARY KEY  (TXN_ID),
639 639
 				KEY TXN_timestamp (TXN_timestamp),
640 640
 				KEY STS_ID (STS_ID)";
641
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
641
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
642 642
 
643
-        $table_name = 'esp_venue_meta';
644
-        $sql        = "VNUM_ID int(11) NOT NULL AUTO_INCREMENT,
643
+		$table_name = 'esp_venue_meta';
644
+		$sql        = "VNUM_ID int(11) NOT NULL AUTO_INCREMENT,
645 645
 			VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
646 646
 			VNU_address varchar(255) DEFAULT NULL,
647 647
 			VNU_address2 varchar(255) DEFAULT NULL,
@@ -660,18 +660,18 @@  discard block
 block discarded – undo
660 660
 			KEY VNU_ID (VNU_ID),
661 661
 			KEY STA_ID (STA_ID),
662 662
 			KEY CNT_ISO (CNT_ISO)";
663
-        $this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
663
+		$this->_table_has_not_changed_since_previous($table_name, $sql, 'ENGINE=InnoDB');
664 664
 
665
-        $this->previous_dms->insert_default_data();
666
-        return true;
667
-    }
665
+		$this->previous_dms->insert_default_data();
666
+		return true;
667
+	}
668 668
 
669 669
 
670
-    /**
671
-     * @return boolean
672
-     */
673
-    public function schema_changes_after_migration(): bool
674
-    {
675
-        return true;
676
-    }
670
+	/**
671
+	 * @return boolean
672
+	 */
673
+	public function schema_changes_after_migration(): bool
674
+	{
675
+		return true;
676
+	}
677 677
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -7,12 +7,12 @@  discard block
 block discarded – undo
7 7
 // unfortunately, this needs to be done upon INCLUSION of this file,
8 8
 // instead of construction, because it only gets constructed on first page load
9 9
 // (all other times it gets resurrected from a wordpress option)
10
-$stages            = glob(EE_CORE . 'data_migration_scripts/4_12_0_stages/*');
10
+$stages            = glob(EE_CORE.'data_migration_scripts/4_12_0_stages/*');
11 11
 $class_to_filepath = [];
12 12
 foreach ($stages as $filepath) {
13 13
     $matches = [];
14 14
     preg_match('~4_12_0_stages/(.*).dmsstage.php~', $filepath, $matches);
15
-    $class_to_filepath[ $matches[1] ] = $filepath;
15
+    $class_to_filepath[$matches[1]] = $filepath;
16 16
 }
17 17
 // give addons a chance to autoload their stages too
18 18
 $class_to_filepath = apply_filters('FHEE__EE_DMS_4_12_0__autoloaded_stages', $class_to_filepath);
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
      */
72 72
     public function schema_changes_before_migration(): bool
73 73
     {
74
-        require_once EE_HELPERS . 'EEH_Activation.helper.php';
74
+        require_once EE_HELPERS.'EEH_Activation.helper.php';
75 75
 
76 76
         $table_name = 'esp_answer';
77 77
         $sql        = " ANS_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
Please login to merge, or discard this patch.
4_12_0_stages/EE_DMS_4_12_0_Event_Venues.dmsstage.php 2 patches
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -12,54 +12,54 @@
 block discarded – undo
12 12
  */
13 13
 class EE_DMS_4_12_0_Event_Venues extends EE_Data_Migration_Script_Stage_Table
14 14
 {
15
-    /**
16
-     * @var string
17
-     */
18
-    private $_event_meta;
15
+	/**
16
+	 * @var string
17
+	 */
18
+	private $_event_meta;
19 19
 
20 20
 
21
-    /**
22
-     * Just initializes the status of the migration
23
-     */
24
-    public function __construct()
25
-    {
26
-        global $wpdb;
27
-        $this->_pretty_name = esc_html__('Event Venue Relations', 'event_espresso');
28
-        $this->_old_table   = $wpdb->prefix . 'esp_event_venue';
29
-        $this->_event_meta  = $wpdb->prefix . 'esp_event_meta';
30
-        parent::__construct();
31
-    }
21
+	/**
22
+	 * Just initializes the status of the migration
23
+	 */
24
+	public function __construct()
25
+	{
26
+		global $wpdb;
27
+		$this->_pretty_name = esc_html__('Event Venue Relations', 'event_espresso');
28
+		$this->_old_table   = $wpdb->prefix . 'esp_event_venue';
29
+		$this->_event_meta  = $wpdb->prefix . 'esp_event_meta';
30
+		parent::__construct();
31
+	}
32 32
 
33 33
 
34
-    /**
35
-     * Copies Venue IDs from `wp_esp_event_venue` to `wp_esp_event_meta` for each Event
36
-     *
37
-     * @param array $old_row an associative array where keys are column names and values are their values.
38
-     * @return null
39
-     */
40
-    protected function _migrate_old_row($old_row): ?bool
41
-    {
42
-        $EVT_ID =
43
-            isset($old_row['EVT_ID'])
44
-                ? absint($old_row['EVT_ID'])
45
-                : 0;
46
-        $VNU_ID =
47
-            isset($old_row['VNU_ID'])
48
-                ? absint($old_row['VNU_ID'])
49
-                : 0;
50
-        if ($EVT_ID && $VNU_ID) {
51
-            global $wpdb;
52
-            // If the question group was also for primary attendees, we should just update that row.
53
-            // And we delete this row.
54
-            $result = $wpdb->update(
55
-                $this->_event_meta,
56
-                ['VNU_ID' => $VNU_ID],  // data
57
-                ['EVT_ID' => $EVT_ID],  // where
58
-                ['%d'],                 // data format
59
-                ['%d']                  // where format
60
-            );
61
-            return filter_var($result, FILTER_VALIDATE_BOOLEAN);
62
-        }
63
-        return false;
64
-    }
34
+	/**
35
+	 * Copies Venue IDs from `wp_esp_event_venue` to `wp_esp_event_meta` for each Event
36
+	 *
37
+	 * @param array $old_row an associative array where keys are column names and values are their values.
38
+	 * @return null
39
+	 */
40
+	protected function _migrate_old_row($old_row): ?bool
41
+	{
42
+		$EVT_ID =
43
+			isset($old_row['EVT_ID'])
44
+				? absint($old_row['EVT_ID'])
45
+				: 0;
46
+		$VNU_ID =
47
+			isset($old_row['VNU_ID'])
48
+				? absint($old_row['VNU_ID'])
49
+				: 0;
50
+		if ($EVT_ID && $VNU_ID) {
51
+			global $wpdb;
52
+			// If the question group was also for primary attendees, we should just update that row.
53
+			// And we delete this row.
54
+			$result = $wpdb->update(
55
+				$this->_event_meta,
56
+				['VNU_ID' => $VNU_ID],  // data
57
+				['EVT_ID' => $EVT_ID],  // where
58
+				['%d'],                 // data format
59
+				['%d']                  // where format
60
+			);
61
+			return filter_var($result, FILTER_VALIDATE_BOOLEAN);
62
+		}
63
+		return false;
64
+	}
65 65
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -25,8 +25,8 @@  discard block
 block discarded – undo
25 25
     {
26 26
         global $wpdb;
27 27
         $this->_pretty_name = esc_html__('Event Venue Relations', 'event_espresso');
28
-        $this->_old_table   = $wpdb->prefix . 'esp_event_venue';
29
-        $this->_event_meta  = $wpdb->prefix . 'esp_event_meta';
28
+        $this->_old_table   = $wpdb->prefix.'esp_event_venue';
29
+        $this->_event_meta  = $wpdb->prefix.'esp_event_meta';
30 30
         parent::__construct();
31 31
     }
32 32
 
@@ -53,9 +53,9 @@  discard block
 block discarded – undo
53 53
             // And we delete this row.
54 54
             $result = $wpdb->update(
55 55
                 $this->_event_meta,
56
-                ['VNU_ID' => $VNU_ID],  // data
57
-                ['EVT_ID' => $EVT_ID],  // where
58
-                ['%d'],                 // data format
56
+                ['VNU_ID' => $VNU_ID], // data
57
+                ['EVT_ID' => $EVT_ID], // where
58
+                ['%d'], // data format
59 59
                 ['%d']                  // where format
60 60
             );
61 61
             return filter_var($result, FILTER_VALIDATE_BOOLEAN);
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +838 added lines, -838 removed lines patch added patch discarded remove patch
@@ -13,842 +13,842 @@
 block discarded – undo
13 13
 class EEM_Datetime extends EEM_Soft_Delete_Base
14 14
 {
15 15
 
16
-    /**
17
-     * @var EEM_Datetime $_instance
18
-     */
19
-    protected static $_instance;
20
-
21
-
22
-    /**
23
-     * private constructor to prevent direct creation
24
-     *
25
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
-     *                         (and any incoming timezone data that gets saved).
27
-     *                         Note this just sends the timezone info to the date time model field objects.
28
-     *                         Default is NULL
29
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
-     * @throws EE_Error
31
-     * @throws InvalidArgumentException
32
-     * @throws InvalidArgumentException
33
-     */
34
-    protected function __construct($timezone)
35
-    {
36
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
-        $this->_tables                 = [
39
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
-        ];
41
-        $this->_fields                 = [
42
-            'Datetime' => [
43
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
-                    'DTT_ID',
45
-                    esc_html__('Datetime ID', 'event_espresso')
46
-                ),
47
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
-                    'EVT_ID',
49
-                    esc_html__('Event ID', 'event_espresso'),
50
-                    false,
51
-                    0,
52
-                    'Event'
53
-                ),
54
-                'VNU_ID' => new EE_Foreign_Key_Int_Field(
55
-                    'VNU_ID',
56
-                    __('Venue ID', 'event_espresso'),
57
-                    false,
58
-                    0,
59
-                    'Venue'
60
-                ),
61
-                'DTT_name'        => new EE_Plain_Text_Field(
62
-                    'DTT_name',
63
-                    esc_html__('Datetime Name', 'event_espresso'),
64
-                    false,
65
-                    ''
66
-                ),
67
-                'DTT_description' => new EE_Post_Content_Field(
68
-                    'DTT_description',
69
-                    esc_html__('Description for Datetime', 'event_espresso'),
70
-                    false,
71
-                    ''
72
-                ),
73
-                'DTT_EVT_start'   => new EE_Datetime_Field(
74
-                    'DTT_EVT_start',
75
-                    esc_html__('Start time/date of Event', 'event_espresso'),
76
-                    false,
77
-                    EE_Datetime_Field::now,
78
-                    $timezone
79
-                ),
80
-                'DTT_EVT_end'     => new EE_Datetime_Field(
81
-                    'DTT_EVT_end',
82
-                    esc_html__('End time/date of Event', 'event_espresso'),
83
-                    false,
84
-                    EE_Datetime_Field::now,
85
-                    $timezone
86
-                ),
87
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
88
-                    'DTT_reg_limit',
89
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
90
-                    true,
91
-                    EE_INF
92
-                ),
93
-                'DTT_sold'        => new EE_Integer_Field(
94
-                    'DTT_sold',
95
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
96
-                    true,
97
-                    0
98
-                ),
99
-                'DTT_reserved'    => new EE_Integer_Field(
100
-                    'DTT_reserved',
101
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
102
-                    false,
103
-                    0
104
-                ),
105
-                'DTT_is_primary'  => new EE_Boolean_Field(
106
-                    'DTT_is_primary',
107
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
108
-                    false,
109
-                    false
110
-                ),
111
-                'DTT_order'       => new EE_Integer_Field(
112
-                    'DTT_order',
113
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
114
-                    false,
115
-                    0
116
-                ),
117
-                'DTT_parent'      => new EE_Integer_Field(
118
-                    'DTT_parent',
119
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
120
-                    true,
121
-                    0
122
-                ),
123
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
124
-                    'DTT_deleted',
125
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
126
-                    false,
127
-                    false
128
-                ),
129
-            ],
130
-        ];
131
-        $this->_model_relations        = [
132
-            'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
133
-            'Event'           => new EE_Belongs_To_Relation(),
134
-            'Checkin'         => new EE_Has_Many_Relation(),
135
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
136
-            'Venue'           => new EE_Belongs_To_Relation(),
137
-        ];
138
-        $path_to_event_model           = 'Event';
139
-        $this->model_chain_to_password = $path_to_event_model;
140
-        $this->_model_chain_to_wp_user = $path_to_event_model;
141
-        // this model is generally available for reading
142
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
143
-            new EE_Restriction_Generator_Event_Related_Public(
144
-                $path_to_event_model
145
-            );
146
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
147
-            new EE_Restriction_Generator_Event_Related_Protected(
148
-                $path_to_event_model
149
-            );
150
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
151
-            new EE_Restriction_Generator_Event_Related_Protected(
152
-                $path_to_event_model
153
-            );
154
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
155
-            new EE_Restriction_Generator_Event_Related_Protected(
156
-                $path_to_event_model,
157
-                EEM_Base::caps_edit
158
-            );
159
-        parent::__construct($timezone);
160
-    }
161
-
162
-
163
-    /**
164
-     * create new blank datetime
165
-     *
166
-     * @access public
167
-     * @return EE_Datetime[] array on success, FALSE on fail
168
-     * @throws EE_Error
169
-     * @throws InvalidArgumentException
170
-     * @throws InvalidDataTypeException
171
-     * @throws ReflectionException
172
-     * @throws InvalidInterfaceException
173
-     */
174
-    public function create_new_blank_datetime()
175
-    {
176
-        // makes sure timezone is always set.
177
-        $timezone_string = $this->get_timezone();
178
-        /**
179
-         * Filters the initial start date for the new datetime.
180
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
181
-         *
182
-         * @param int $start_date Unix timestamp representing now + 30 days in seconds.
183
-         * @return int Unix timestamp
184
-         */
185
-        $start_date = apply_filters(
186
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
187
-            $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
188
-        );
189
-        /**
190
-         * Filters the initial end date for the new datetime.
191
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
192
-         *
193
-         * @param int $end_data Unix timestamp representing now + 30 days in seconds.
194
-         * @return int Unix timestamp
195
-         */
196
-        $end_date       = apply_filters(
197
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
198
-            $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
199
-        );
200
-        $blank_datetime = EE_Datetime::new_instance(
201
-            [
202
-                'DTT_EVT_start' => $start_date,
203
-                'DTT_EVT_end'   => $end_date,
204
-                'DTT_order'     => 1,
205
-                'DTT_reg_limit' => EE_INF,
206
-            ],
207
-            $timezone_string
208
-        );
209
-        /**
210
-         * Filters the initial start time and format for the new EE_Datetime instance.
211
-         *
212
-         * @param array $start_time An array having size 2.  First element is the time, second element is the time
213
-         *                          format.
214
-         * @return array
215
-         */
216
-        $start_time = apply_filters(
217
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
218
-            ['8am', 'ga']
219
-        );
220
-        /**
221
-         * Filters the initial end time and format for the new EE_Datetime instance.
222
-         *
223
-         * @param array $end_time An array having size 2.  First element is the time, second element is the time
224
-         *                        format
225
-         * @return array
226
-         */
227
-        $end_time = apply_filters(
228
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
229
-            ['5pm', 'ga']
230
-        );
231
-        $this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
232
-        $blank_datetime->set_start_time(
233
-            $this->convert_datetime_for_query(
234
-                'DTT_EVT_start',
235
-                $start_time[0],
236
-                $start_time[1],
237
-                $timezone_string
238
-            )
239
-        );
240
-        $blank_datetime->set_end_time(
241
-            $this->convert_datetime_for_query(
242
-                'DTT_EVT_end',
243
-                $end_time[0],
244
-                $end_time[1],
245
-                $timezone_string
246
-            )
247
-        );
248
-        return [$blank_datetime];
249
-    }
250
-
251
-
252
-    /**
253
-     * Validates whether the start_time and end_time are in the expected format.
254
-     *
255
-     * @param array $start_time
256
-     * @param array $end_time
257
-     * @throws InvalidArgumentException
258
-     * @throws InvalidDataTypeException
259
-     */
260
-    private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
261
-    {
262
-        if (! is_array($start_time)) {
263
-            throw new InvalidDataTypeException('start_time', $start_time, 'array');
264
-        }
265
-        if (! is_array($end_time)) {
266
-            throw new InvalidDataTypeException('end_time', $end_time, 'array');
267
-        }
268
-        if (count($start_time) !== 2) {
269
-            throw new InvalidArgumentException(
270
-                sprintf(
271
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
273
-                    '$start_time'
274
-                )
275
-            );
276
-        }
277
-        if (count($end_time) !== 2) {
278
-            throw new InvalidArgumentException(
279
-                sprintf(
280
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
281
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
282
-                    '$end_time'
283
-                )
284
-            );
285
-        }
286
-    }
287
-
288
-
289
-    /**
290
-     * get event start date from db
291
-     *
292
-     * @access public
293
-     * @param int $EVT_ID
294
-     * @return EE_Datetime[] array on success, FALSE on fail
295
-     * @throws EE_Error
296
-     * @throws ReflectionException
297
-     */
298
-    public function get_all_event_dates($EVT_ID = 0)
299
-    {
300
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
301
-            return $this->create_new_blank_datetime();
302
-        }
303
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
304
-        if (empty($results)) {
305
-            return $this->create_new_blank_datetime();
306
-        }
307
-        return $results;
308
-    }
309
-
310
-
311
-    /**
312
-     * get all datetimes attached to an event ordered by the DTT_order field
313
-     *
314
-     * @public
315
-     * @param int     $EVT_ID     event id
316
-     * @param boolean $include_expired
317
-     * @param boolean $include_deleted
318
-     * @param int     $limit      If included then limit the count of results by
319
-     *                            the given number
320
-     * @return EE_Datetime[]
321
-     * @throws EE_Error
322
-     */
323
-    public function get_datetimes_for_event_ordered_by_DTT_order(
324
-        int $EVT_ID,
325
-        bool $include_expired = true,
326
-        bool $include_deleted = true,
327
-        $limit = 0
328
-    ) {
329
-        $prev_data_prep_value = $this->prepModelForQuery();
330
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
331
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
332
-        $query_params         = $this->addDefaultWhereConditions($query_params);
333
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
334
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
335
-    }
336
-
337
-
338
-    /**
339
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
340
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
341
-     * and then the earlier datetimes are the most important.
342
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
343
-     *
344
-     * @param int $EVT_ID
345
-     * @param int $limit
346
-     * @return EE_Datetime[]|EE_Base_Class[]
347
-     * @throws EE_Error
348
-     */
349
-    public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, $limit = 0)
350
-    {
351
-        $query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
352
-        $query_params    = $this->addDefaultWhereConditions($query_params);
353
-        $query_params    = $this->addDefaultQueryParams($query_params, $limit);
354
-        return $this->get_all($query_params);
355
-    }
356
-
357
-
358
-    /**
359
-     * @param int     $EVT_ID
360
-     * @param boolean $include_expired
361
-     * @param boolean $include_deleted
362
-     * @return EE_Datetime
363
-     * @throws EE_Error
364
-     */
365
-    public function get_oldest_datetime_for_event(
366
-        int $EVT_ID,
367
-        bool $include_expired = false,
368
-        bool $include_deleted = false
369
-    ) {
370
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
371
-            $EVT_ID,
372
-            $include_expired,
373
-            $include_deleted,
374
-            1
375
-        );
376
-        if ($results) {
377
-            return array_shift($results);
378
-        }
379
-        return null;
380
-    }
381
-
382
-
383
-    /**
384
-     * Gets the 'primary' datetime for an event.
385
-     *
386
-     * @param int  $EVT_ID
387
-     * @param bool $try_to_exclude_expired
388
-     * @param bool $try_to_exclude_deleted
389
-     * @return EE_Datetime
390
-     * @throws EE_Error
391
-     */
392
-    public function get_primary_datetime_for_event(
393
-        int $EVT_ID,
394
-        bool $try_to_exclude_expired = true,
395
-        bool $try_to_exclude_deleted = true
396
-    ) {
397
-        if ($try_to_exclude_expired) {
398
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
399
-            if ($non_expired) {
400
-                return $non_expired;
401
-            }
402
-        }
403
-        if ($try_to_exclude_deleted) {
404
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
405
-            if ($expired_even) {
406
-                return $expired_even;
407
-            }
408
-        }
409
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
410
-    }
411
-
412
-
413
-    /**
414
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
415
-     * only by start date
416
-     *
417
-     * @param int     $EVT_ID
418
-     * @param boolean $include_expired
419
-     * @param boolean $include_deleted
420
-     * @param int     $limit
421
-     * @return EE_Datetime[]
422
-     * @throws EE_Error
423
-     */
424
-    public function get_datetimes_for_event_ordered_by_start_time(
425
-        int $EVT_ID,
426
-        bool $include_expired = true,
427
-        bool $include_deleted = true,
428
-        $limit = 0
429
-    ) {
430
-        $prev_data_prep_value = $this->prepModelForQuery();
431
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
432
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
433
-        $query_params         = $this->addDefaultWhereConditions(
434
-            $query_params,
435
-            EEM_Base::default_where_conditions_this_only
436
-        );
437
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
438
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
439
-    }
440
-
441
-
442
-    /**
443
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
444
-     * only by start date
445
-     *
446
-     * @param int     $TKT_ID
447
-     * @param boolean $include_expired
448
-     * @param boolean $include_deleted
449
-     * @param int     $limit
450
-     * @return EE_Datetime[]
451
-     * @throws EE_Error
452
-     */
453
-    public function get_datetimes_for_ticket_ordered_by_start_time(
454
-        int $TKT_ID,
455
-        bool $include_expired = true,
456
-        bool $include_deleted = true,
457
-        $limit = 0
458
-    ) {
459
-        $prev_data_prep_value = $this->prepModelForQuery();
460
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
461
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
462
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit);
463
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
464
-    }
465
-
466
-
467
-    /**
468
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
469
-     * datetimes.
470
-     *
471
-     * @param int      $TKT_ID           ID of ticket to retrieve the datetimes for
472
-     * @param boolean  $include_expired  whether to include expired datetimes or not
473
-     * @param boolean  $include_deleted  whether to include trashed datetimes or not.
474
-     * @param int|null $limit            if null, no limit, if int then limit results by
475
-     *                                   that number
476
-     * @return EE_Datetime[]
477
-     * @throws EE_Error
478
-     */
479
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
480
-        int $TKT_ID,
481
-        bool $include_expired = true,
482
-        bool $include_deleted = true,
483
-        $limit = 0
484
-    ) {
485
-        $prev_data_prep_value = $this->prepModelForQuery();
486
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
487
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
488
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
489
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
490
-    }
491
-
492
-
493
-    /**
494
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
495
-     * reason it doesn't exist, we consider the earliest event the most important)
496
-     *
497
-     * @param int $EVT_ID
498
-     * @return EE_Datetime
499
-     * @throws EE_Error
500
-     */
501
-    public function get_most_important_datetime_for_event(int $EVT_ID)
502
-    {
503
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
504
-        if ($results) {
505
-            return array_shift($results);
506
-        }
507
-        return null;
508
-    }
509
-
510
-
511
-    /**
512
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
513
-     * grouped by month and year.
514
-     *
515
-     * @param array  $where_params       @see
516
-     *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
517
-     * @param string $evt_active_status  A string representing the evt active status to filter the months by.
518
-     *                                   Can be:
519
-     *                                   - '' = no filter
520
-     *                                   - upcoming = Published events with at least one upcoming datetime.
521
-     *                                   - expired = Events with all datetimes expired.
522
-     *                                   - active = Events that are published and have at least one datetime that
523
-     *                                   starts before now and ends after now.
524
-     *                                   - inactive = Events that are either not published.
525
-     * @return EE_Base_Class[]
526
-     * @throws EE_Error
527
-     * @throws InvalidArgumentException
528
-     * @throws InvalidArgumentException
529
-     */
530
-    public function get_dtt_months_and_years(array $where_params, $evt_active_status = '')
531
-    {
532
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
-        switch ($evt_active_status) {
535
-            case 'upcoming':
536
-                $where_params['Event.status'] = 'publish';
537
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
-                if (isset($where_params['DTT_EVT_start'])) {
539
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
-                }
541
-                $where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
-                break;
543
-            case 'expired':
544
-                if (isset($where_params['Event.status'])) {
545
-                    unset($where_params['Event.status']);
546
-                }
547
-                // get events to exclude
548
-                $exclude_query[0] = array_merge(
549
-                    $where_params,
550
-                    ['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
-                );
552
-                // first get all events that have datetimes where its not expired.
553
-                $event_ids = $this->_get_all_wpdb_results(
554
-                    $exclude_query,
555
-                    OBJECT_K,
556
-                    'Datetime.EVT_ID'
557
-                );
558
-                $event_ids = array_keys($event_ids);
559
-                if (isset($where_params['DTT_EVT_end'])) {
560
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
-                }
562
-                $where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
-                $where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
-                break;
565
-            case 'active':
566
-                $where_params['Event.status'] = 'publish';
567
-                if (isset($where_params['DTT_EVT_start'])) {
568
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
-                }
570
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
-                }
573
-                $where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
-                $where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
-                break;
576
-            case 'inactive':
577
-                if (isset($where_params['Event.status'])) {
578
-                    unset($where_params['Event.status']);
579
-                }
580
-                if (isset($where_params['OR'])) {
581
-                    $where_params['AND']['OR'] = $where_params['OR'];
582
-                }
583
-                if (isset($where_params['DTT_EVT_end'])) {
584
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
-                    unset($where_params['DTT_EVT_end']);
586
-                }
587
-                if (isset($where_params['DTT_EVT_start'])) {
588
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
-                    unset($where_params['DTT_EVT_start']);
590
-                }
591
-                $where_params['AND']['Event.status'] = ['!=', 'publish'];
592
-                break;
593
-        }
594
-        $query_params[0]          = $where_params;
595
-        $query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
-        $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
-
598
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
-            $this->get_timezone(),
600
-            'DTT_EVT_start'
601
-        );
602
-        $columns_to_select = [
603
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
-        ];
607
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
-    }
609
-
610
-
611
-    /**
612
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
613
-     * for the tickets for each datetime)
614
-     *
615
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
-     * @throws EE_Error
617
-     * @throws ReflectionException
618
-     */
619
-    public function update_sold(array $datetimes)
620
-    {
621
-        EE_Error::doing_it_wrong(
622
-            __FUNCTION__,
623
-            esc_html__(
624
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
-                'event_espresso'
626
-            ),
627
-            '4.9.32.rc.005'
628
-        );
629
-        foreach ($datetimes as $datetime) {
630
-            $datetime->update_sold();
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     *    Gets the total number of tickets available at a particular datetime
637
-     *    (does NOT take into account the datetime's spaces available)
638
-     *
639
-     * @param int   $DTT_ID
640
-     * @param array $query_params
641
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
-     *             tickets attached to datetime then FALSE is returned.
643
-     * @throws EE_Error
644
-     * @throws ReflectionException
645
-     */
646
-    public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = [])
647
-    {
648
-        $datetime = $this->get_one_by_ID($DTT_ID);
649
-        if ($datetime instanceof EE_Datetime) {
650
-            return $datetime->tickets_remaining($query_params);
651
-        }
652
-        return 0;
653
-    }
654
-
655
-
656
-    /**
657
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
-     *
659
-     * @param array $stati_to_include  If included you can restrict the statuses we return counts for by including the
660
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
661
-     *                                 for all valid stati.
662
-     * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
664
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
-     * @throws EE_Error
666
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
667
-     *                                 EE_Datetime::expired
668
-     */
669
-    public function get_datetime_counts_by_status(array $stati_to_include = [], array $query_params = [])
670
-    {
671
-        // only accept where conditions for this query.
672
-        $_where            = isset($query_params[0]) ? $query_params[0] : [];
673
-        $status_query_args = [
674
-            EE_Datetime::active   => array_merge(
675
-                $_where,
676
-                ['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
677
-            ),
678
-            EE_Datetime::upcoming => array_merge(
679
-                $_where,
680
-                ['DTT_EVT_start' => ['>', time()]]
681
-            ),
682
-            EE_Datetime::expired  => array_merge(
683
-                $_where,
684
-                ['DTT_EVT_end' => ['<', time()]]
685
-            ),
686
-        ];
687
-        if (! empty($stati_to_include)) {
688
-            foreach (array_keys($status_query_args) as $status) {
689
-                if (! in_array($status, $stati_to_include, true)) {
690
-                    unset($status_query_args[ $status ]);
691
-                }
692
-            }
693
-        }
694
-        // loop through and query counts for each stati.
695
-        $status_query_results = [];
696
-        foreach ($status_query_args as $status => $status_where_conditions) {
697
-            $status_query_results[ $status ] = EEM_Datetime::count(
698
-                [$status_where_conditions],
699
-                'DTT_ID',
700
-                true
701
-            );
702
-        }
703
-        return $status_query_results;
704
-    }
705
-
706
-
707
-    /**
708
-     * Returns the specific count for a given Datetime status matching any given query_params.
709
-     *
710
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
711
-     * @param array  $query_params
712
-     * @return int
713
-     * @throws EE_Error
714
-     */
715
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = [])
716
-    {
717
-        $count = $this->get_datetime_counts_by_status([$status], $query_params);
718
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
719
-    }
720
-
721
-
722
-    /**
723
-     * @return bool|int
724
-     * @since   $VID:$
725
-     */
726
-    private function prepModelForQuery()
727
-    {
728
-        $prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
729
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
730
-        return $prev_data_prep_value;
731
-    }
732
-
733
-
734
-    /**
735
-     * @param array    $query_params
736
-     * @param bool|int $prev_data_prep_value
737
-     * @return EE_Base_Class[]|EE_Datetime[]
738
-     * @throws EE_Error
739
-     * @since   $VID:$
740
-     */
741
-    private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value)
742
-    {
743
-        $result = $this->get_all($query_params);
744
-        $this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
745
-        return $result;
746
-    }
747
-
748
-
749
-    /**
750
-     * @param array  $query_params
751
-     * @param int    $limit
752
-     * @param string $order_by
753
-     * @param string $order
754
-     * @return array
755
-     * @since   $VID:$
756
-     */
757
-    private function addDefaultQueryParams(array $query_params, $limit = 0, $order_by = 'DTT_EVT_start', $order = 'ASC')
758
-    {
759
-        $query_params = $this->addOrderByQueryParams($query_params, $order_by, $order);
760
-        $query_params = $this->addLimitQueryParams($query_params, $limit);
761
-        return $query_params;
762
-    }
763
-
764
-
765
-    /**
766
-     * @param array  $query_params
767
-     * @param string $default_where_conditions
768
-     * @return array
769
-     * @since   $VID:$
770
-     */
771
-    private function addDefaultWhereConditions(
772
-        array $query_params,
773
-        $default_where_conditions = EEM_Base::default_where_conditions_none
774
-    ) {
775
-        $query_params['default_where_conditions'] = $default_where_conditions;
776
-        return $query_params;
777
-    }
778
-
779
-
780
-    /**
781
-     * @param array $where_params
782
-     * @param bool  $include_deleted
783
-     * @param bool  $include_expired
784
-     * @return array
785
-     * @since   $VID:$
786
-     */
787
-    private function addDefaultWhereParams(array $where_params, bool $include_deleted = true, bool $include_expired = true)
788
-    {
789
-        $where_params = $this->addExpiredWhereParams($where_params, $include_expired);
790
-        $where_params = $this->addDeletedWhereParams($where_params, $include_deleted);
791
-        return $where_params;
792
-    }
793
-
794
-
795
-    /**
796
-     * @param array $where_params
797
-     * @param bool  $include_deleted
798
-     * @return array
799
-     * @since   $VID:$
800
-     */
801
-    private function addDeletedWhereParams(array $where_params, bool $include_deleted = true)
802
-    {
803
-        $deleted                     = $include_deleted ? [true, false] : [false];
804
-        $where_params['DTT_deleted'] = ['IN', $deleted];
805
-        return $where_params;
806
-    }
807
-
808
-
809
-    /**
810
-     * @param array $where_params
811
-     * @param bool  $include_expired
812
-     * @return array
813
-     * @since   $VID:$
814
-     */
815
-    private function addExpiredWhereParams(array $where_params, bool $include_expired = true)
816
-    {
817
-        if (! $include_expired) {
818
-            $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
819
-        }
820
-        return $where_params;
821
-    }
822
-
823
-
824
-    /**
825
-     * @param array $query_params
826
-     * @param int   $limit
827
-     * @return array
828
-     * @since   $VID:$
829
-     */
830
-    private function addLimitQueryParams(array $query_params, $limit = 0)
831
-    {
832
-        if ($limit) {
833
-            $query_params['limit'] = $limit;
834
-        }
835
-        return $query_params;
836
-    }
837
-
838
-
839
-    /**
840
-     * @param array  $query_params
841
-     * @param string $order_by
842
-     * @param string $order
843
-     * @return array
844
-     * @since   $VID:$
845
-     */
846
-    private function addOrderByQueryParams(array $query_params, $order_by = 'DTT_EVT_start', $order = 'ASC')
847
-    {
848
-        $order                    = $order === 'ASC' ? 'ASC' : 'DESC';
849
-        $valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
850
-        $order_by                 = in_array($order_by, $valid_order_columns, true) ? $order_by : 'DTT_EVT_start';
851
-        $query_params['order_by'] = [$order_by => $order];
852
-        return $query_params;
853
-    }
16
+	/**
17
+	 * @var EEM_Datetime $_instance
18
+	 */
19
+	protected static $_instance;
20
+
21
+
22
+	/**
23
+	 * private constructor to prevent direct creation
24
+	 *
25
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
+	 *                         (and any incoming timezone data that gets saved).
27
+	 *                         Note this just sends the timezone info to the date time model field objects.
28
+	 *                         Default is NULL
29
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
+	 * @throws EE_Error
31
+	 * @throws InvalidArgumentException
32
+	 * @throws InvalidArgumentException
33
+	 */
34
+	protected function __construct($timezone)
35
+	{
36
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
+		$this->_tables                 = [
39
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
+		];
41
+		$this->_fields                 = [
42
+			'Datetime' => [
43
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
+					'DTT_ID',
45
+					esc_html__('Datetime ID', 'event_espresso')
46
+				),
47
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
+					'EVT_ID',
49
+					esc_html__('Event ID', 'event_espresso'),
50
+					false,
51
+					0,
52
+					'Event'
53
+				),
54
+				'VNU_ID' => new EE_Foreign_Key_Int_Field(
55
+					'VNU_ID',
56
+					__('Venue ID', 'event_espresso'),
57
+					false,
58
+					0,
59
+					'Venue'
60
+				),
61
+				'DTT_name'        => new EE_Plain_Text_Field(
62
+					'DTT_name',
63
+					esc_html__('Datetime Name', 'event_espresso'),
64
+					false,
65
+					''
66
+				),
67
+				'DTT_description' => new EE_Post_Content_Field(
68
+					'DTT_description',
69
+					esc_html__('Description for Datetime', 'event_espresso'),
70
+					false,
71
+					''
72
+				),
73
+				'DTT_EVT_start'   => new EE_Datetime_Field(
74
+					'DTT_EVT_start',
75
+					esc_html__('Start time/date of Event', 'event_espresso'),
76
+					false,
77
+					EE_Datetime_Field::now,
78
+					$timezone
79
+				),
80
+				'DTT_EVT_end'     => new EE_Datetime_Field(
81
+					'DTT_EVT_end',
82
+					esc_html__('End time/date of Event', 'event_espresso'),
83
+					false,
84
+					EE_Datetime_Field::now,
85
+					$timezone
86
+				),
87
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
88
+					'DTT_reg_limit',
89
+					esc_html__('Registration Limit for this time', 'event_espresso'),
90
+					true,
91
+					EE_INF
92
+				),
93
+				'DTT_sold'        => new EE_Integer_Field(
94
+					'DTT_sold',
95
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
96
+					true,
97
+					0
98
+				),
99
+				'DTT_reserved'    => new EE_Integer_Field(
100
+					'DTT_reserved',
101
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
102
+					false,
103
+					0
104
+				),
105
+				'DTT_is_primary'  => new EE_Boolean_Field(
106
+					'DTT_is_primary',
107
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
108
+					false,
109
+					false
110
+				),
111
+				'DTT_order'       => new EE_Integer_Field(
112
+					'DTT_order',
113
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
114
+					false,
115
+					0
116
+				),
117
+				'DTT_parent'      => new EE_Integer_Field(
118
+					'DTT_parent',
119
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
120
+					true,
121
+					0
122
+				),
123
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
124
+					'DTT_deleted',
125
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
126
+					false,
127
+					false
128
+				),
129
+			],
130
+		];
131
+		$this->_model_relations        = [
132
+			'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
133
+			'Event'           => new EE_Belongs_To_Relation(),
134
+			'Checkin'         => new EE_Has_Many_Relation(),
135
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
136
+			'Venue'           => new EE_Belongs_To_Relation(),
137
+		];
138
+		$path_to_event_model           = 'Event';
139
+		$this->model_chain_to_password = $path_to_event_model;
140
+		$this->_model_chain_to_wp_user = $path_to_event_model;
141
+		// this model is generally available for reading
142
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
143
+			new EE_Restriction_Generator_Event_Related_Public(
144
+				$path_to_event_model
145
+			);
146
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
147
+			new EE_Restriction_Generator_Event_Related_Protected(
148
+				$path_to_event_model
149
+			);
150
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
151
+			new EE_Restriction_Generator_Event_Related_Protected(
152
+				$path_to_event_model
153
+			);
154
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
155
+			new EE_Restriction_Generator_Event_Related_Protected(
156
+				$path_to_event_model,
157
+				EEM_Base::caps_edit
158
+			);
159
+		parent::__construct($timezone);
160
+	}
161
+
162
+
163
+	/**
164
+	 * create new blank datetime
165
+	 *
166
+	 * @access public
167
+	 * @return EE_Datetime[] array on success, FALSE on fail
168
+	 * @throws EE_Error
169
+	 * @throws InvalidArgumentException
170
+	 * @throws InvalidDataTypeException
171
+	 * @throws ReflectionException
172
+	 * @throws InvalidInterfaceException
173
+	 */
174
+	public function create_new_blank_datetime()
175
+	{
176
+		// makes sure timezone is always set.
177
+		$timezone_string = $this->get_timezone();
178
+		/**
179
+		 * Filters the initial start date for the new datetime.
180
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
181
+		 *
182
+		 * @param int $start_date Unix timestamp representing now + 30 days in seconds.
183
+		 * @return int Unix timestamp
184
+		 */
185
+		$start_date = apply_filters(
186
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
187
+			$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
188
+		);
189
+		/**
190
+		 * Filters the initial end date for the new datetime.
191
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
192
+		 *
193
+		 * @param int $end_data Unix timestamp representing now + 30 days in seconds.
194
+		 * @return int Unix timestamp
195
+		 */
196
+		$end_date       = apply_filters(
197
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
198
+			$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
199
+		);
200
+		$blank_datetime = EE_Datetime::new_instance(
201
+			[
202
+				'DTT_EVT_start' => $start_date,
203
+				'DTT_EVT_end'   => $end_date,
204
+				'DTT_order'     => 1,
205
+				'DTT_reg_limit' => EE_INF,
206
+			],
207
+			$timezone_string
208
+		);
209
+		/**
210
+		 * Filters the initial start time and format for the new EE_Datetime instance.
211
+		 *
212
+		 * @param array $start_time An array having size 2.  First element is the time, second element is the time
213
+		 *                          format.
214
+		 * @return array
215
+		 */
216
+		$start_time = apply_filters(
217
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
218
+			['8am', 'ga']
219
+		);
220
+		/**
221
+		 * Filters the initial end time and format for the new EE_Datetime instance.
222
+		 *
223
+		 * @param array $end_time An array having size 2.  First element is the time, second element is the time
224
+		 *                        format
225
+		 * @return array
226
+		 */
227
+		$end_time = apply_filters(
228
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
229
+			['5pm', 'ga']
230
+		);
231
+		$this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
232
+		$blank_datetime->set_start_time(
233
+			$this->convert_datetime_for_query(
234
+				'DTT_EVT_start',
235
+				$start_time[0],
236
+				$start_time[1],
237
+				$timezone_string
238
+			)
239
+		);
240
+		$blank_datetime->set_end_time(
241
+			$this->convert_datetime_for_query(
242
+				'DTT_EVT_end',
243
+				$end_time[0],
244
+				$end_time[1],
245
+				$timezone_string
246
+			)
247
+		);
248
+		return [$blank_datetime];
249
+	}
250
+
251
+
252
+	/**
253
+	 * Validates whether the start_time and end_time are in the expected format.
254
+	 *
255
+	 * @param array $start_time
256
+	 * @param array $end_time
257
+	 * @throws InvalidArgumentException
258
+	 * @throws InvalidDataTypeException
259
+	 */
260
+	private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
261
+	{
262
+		if (! is_array($start_time)) {
263
+			throw new InvalidDataTypeException('start_time', $start_time, 'array');
264
+		}
265
+		if (! is_array($end_time)) {
266
+			throw new InvalidDataTypeException('end_time', $end_time, 'array');
267
+		}
268
+		if (count($start_time) !== 2) {
269
+			throw new InvalidArgumentException(
270
+				sprintf(
271
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
273
+					'$start_time'
274
+				)
275
+			);
276
+		}
277
+		if (count($end_time) !== 2) {
278
+			throw new InvalidArgumentException(
279
+				sprintf(
280
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
281
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
282
+					'$end_time'
283
+				)
284
+			);
285
+		}
286
+	}
287
+
288
+
289
+	/**
290
+	 * get event start date from db
291
+	 *
292
+	 * @access public
293
+	 * @param int $EVT_ID
294
+	 * @return EE_Datetime[] array on success, FALSE on fail
295
+	 * @throws EE_Error
296
+	 * @throws ReflectionException
297
+	 */
298
+	public function get_all_event_dates($EVT_ID = 0)
299
+	{
300
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
301
+			return $this->create_new_blank_datetime();
302
+		}
303
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
304
+		if (empty($results)) {
305
+			return $this->create_new_blank_datetime();
306
+		}
307
+		return $results;
308
+	}
309
+
310
+
311
+	/**
312
+	 * get all datetimes attached to an event ordered by the DTT_order field
313
+	 *
314
+	 * @public
315
+	 * @param int     $EVT_ID     event id
316
+	 * @param boolean $include_expired
317
+	 * @param boolean $include_deleted
318
+	 * @param int     $limit      If included then limit the count of results by
319
+	 *                            the given number
320
+	 * @return EE_Datetime[]
321
+	 * @throws EE_Error
322
+	 */
323
+	public function get_datetimes_for_event_ordered_by_DTT_order(
324
+		int $EVT_ID,
325
+		bool $include_expired = true,
326
+		bool $include_deleted = true,
327
+		$limit = 0
328
+	) {
329
+		$prev_data_prep_value = $this->prepModelForQuery();
330
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
331
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
332
+		$query_params         = $this->addDefaultWhereConditions($query_params);
333
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
334
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
335
+	}
336
+
337
+
338
+	/**
339
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
340
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
341
+	 * and then the earlier datetimes are the most important.
342
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
343
+	 *
344
+	 * @param int $EVT_ID
345
+	 * @param int $limit
346
+	 * @return EE_Datetime[]|EE_Base_Class[]
347
+	 * @throws EE_Error
348
+	 */
349
+	public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, $limit = 0)
350
+	{
351
+		$query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
352
+		$query_params    = $this->addDefaultWhereConditions($query_params);
353
+		$query_params    = $this->addDefaultQueryParams($query_params, $limit);
354
+		return $this->get_all($query_params);
355
+	}
356
+
357
+
358
+	/**
359
+	 * @param int     $EVT_ID
360
+	 * @param boolean $include_expired
361
+	 * @param boolean $include_deleted
362
+	 * @return EE_Datetime
363
+	 * @throws EE_Error
364
+	 */
365
+	public function get_oldest_datetime_for_event(
366
+		int $EVT_ID,
367
+		bool $include_expired = false,
368
+		bool $include_deleted = false
369
+	) {
370
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
371
+			$EVT_ID,
372
+			$include_expired,
373
+			$include_deleted,
374
+			1
375
+		);
376
+		if ($results) {
377
+			return array_shift($results);
378
+		}
379
+		return null;
380
+	}
381
+
382
+
383
+	/**
384
+	 * Gets the 'primary' datetime for an event.
385
+	 *
386
+	 * @param int  $EVT_ID
387
+	 * @param bool $try_to_exclude_expired
388
+	 * @param bool $try_to_exclude_deleted
389
+	 * @return EE_Datetime
390
+	 * @throws EE_Error
391
+	 */
392
+	public function get_primary_datetime_for_event(
393
+		int $EVT_ID,
394
+		bool $try_to_exclude_expired = true,
395
+		bool $try_to_exclude_deleted = true
396
+	) {
397
+		if ($try_to_exclude_expired) {
398
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
399
+			if ($non_expired) {
400
+				return $non_expired;
401
+			}
402
+		}
403
+		if ($try_to_exclude_deleted) {
404
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
405
+			if ($expired_even) {
406
+				return $expired_even;
407
+			}
408
+		}
409
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
410
+	}
411
+
412
+
413
+	/**
414
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
415
+	 * only by start date
416
+	 *
417
+	 * @param int     $EVT_ID
418
+	 * @param boolean $include_expired
419
+	 * @param boolean $include_deleted
420
+	 * @param int     $limit
421
+	 * @return EE_Datetime[]
422
+	 * @throws EE_Error
423
+	 */
424
+	public function get_datetimes_for_event_ordered_by_start_time(
425
+		int $EVT_ID,
426
+		bool $include_expired = true,
427
+		bool $include_deleted = true,
428
+		$limit = 0
429
+	) {
430
+		$prev_data_prep_value = $this->prepModelForQuery();
431
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
432
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
433
+		$query_params         = $this->addDefaultWhereConditions(
434
+			$query_params,
435
+			EEM_Base::default_where_conditions_this_only
436
+		);
437
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
438
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
439
+	}
440
+
441
+
442
+	/**
443
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
444
+	 * only by start date
445
+	 *
446
+	 * @param int     $TKT_ID
447
+	 * @param boolean $include_expired
448
+	 * @param boolean $include_deleted
449
+	 * @param int     $limit
450
+	 * @return EE_Datetime[]
451
+	 * @throws EE_Error
452
+	 */
453
+	public function get_datetimes_for_ticket_ordered_by_start_time(
454
+		int $TKT_ID,
455
+		bool $include_expired = true,
456
+		bool $include_deleted = true,
457
+		$limit = 0
458
+	) {
459
+		$prev_data_prep_value = $this->prepModelForQuery();
460
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
461
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
462
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit);
463
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
464
+	}
465
+
466
+
467
+	/**
468
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
469
+	 * datetimes.
470
+	 *
471
+	 * @param int      $TKT_ID           ID of ticket to retrieve the datetimes for
472
+	 * @param boolean  $include_expired  whether to include expired datetimes or not
473
+	 * @param boolean  $include_deleted  whether to include trashed datetimes or not.
474
+	 * @param int|null $limit            if null, no limit, if int then limit results by
475
+	 *                                   that number
476
+	 * @return EE_Datetime[]
477
+	 * @throws EE_Error
478
+	 */
479
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
480
+		int $TKT_ID,
481
+		bool $include_expired = true,
482
+		bool $include_deleted = true,
483
+		$limit = 0
484
+	) {
485
+		$prev_data_prep_value = $this->prepModelForQuery();
486
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
487
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
488
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
489
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
490
+	}
491
+
492
+
493
+	/**
494
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
495
+	 * reason it doesn't exist, we consider the earliest event the most important)
496
+	 *
497
+	 * @param int $EVT_ID
498
+	 * @return EE_Datetime
499
+	 * @throws EE_Error
500
+	 */
501
+	public function get_most_important_datetime_for_event(int $EVT_ID)
502
+	{
503
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
504
+		if ($results) {
505
+			return array_shift($results);
506
+		}
507
+		return null;
508
+	}
509
+
510
+
511
+	/**
512
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
513
+	 * grouped by month and year.
514
+	 *
515
+	 * @param array  $where_params       @see
516
+	 *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
517
+	 * @param string $evt_active_status  A string representing the evt active status to filter the months by.
518
+	 *                                   Can be:
519
+	 *                                   - '' = no filter
520
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
521
+	 *                                   - expired = Events with all datetimes expired.
522
+	 *                                   - active = Events that are published and have at least one datetime that
523
+	 *                                   starts before now and ends after now.
524
+	 *                                   - inactive = Events that are either not published.
525
+	 * @return EE_Base_Class[]
526
+	 * @throws EE_Error
527
+	 * @throws InvalidArgumentException
528
+	 * @throws InvalidArgumentException
529
+	 */
530
+	public function get_dtt_months_and_years(array $where_params, $evt_active_status = '')
531
+	{
532
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
+		switch ($evt_active_status) {
535
+			case 'upcoming':
536
+				$where_params['Event.status'] = 'publish';
537
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
+				if (isset($where_params['DTT_EVT_start'])) {
539
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
+				}
541
+				$where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
+				break;
543
+			case 'expired':
544
+				if (isset($where_params['Event.status'])) {
545
+					unset($where_params['Event.status']);
546
+				}
547
+				// get events to exclude
548
+				$exclude_query[0] = array_merge(
549
+					$where_params,
550
+					['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
+				);
552
+				// first get all events that have datetimes where its not expired.
553
+				$event_ids = $this->_get_all_wpdb_results(
554
+					$exclude_query,
555
+					OBJECT_K,
556
+					'Datetime.EVT_ID'
557
+				);
558
+				$event_ids = array_keys($event_ids);
559
+				if (isset($where_params['DTT_EVT_end'])) {
560
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
+				}
562
+				$where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
+				$where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
+				break;
565
+			case 'active':
566
+				$where_params['Event.status'] = 'publish';
567
+				if (isset($where_params['DTT_EVT_start'])) {
568
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
+				}
570
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
+				}
573
+				$where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
+				$where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
+				break;
576
+			case 'inactive':
577
+				if (isset($where_params['Event.status'])) {
578
+					unset($where_params['Event.status']);
579
+				}
580
+				if (isset($where_params['OR'])) {
581
+					$where_params['AND']['OR'] = $where_params['OR'];
582
+				}
583
+				if (isset($where_params['DTT_EVT_end'])) {
584
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
+					unset($where_params['DTT_EVT_end']);
586
+				}
587
+				if (isset($where_params['DTT_EVT_start'])) {
588
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
+					unset($where_params['DTT_EVT_start']);
590
+				}
591
+				$where_params['AND']['Event.status'] = ['!=', 'publish'];
592
+				break;
593
+		}
594
+		$query_params[0]          = $where_params;
595
+		$query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
+		$query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
+
598
+		$query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
+			$this->get_timezone(),
600
+			'DTT_EVT_start'
601
+		);
602
+		$columns_to_select = [
603
+			'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
+			'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
+			'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
+		];
607
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
+	}
609
+
610
+
611
+	/**
612
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
613
+	 * for the tickets for each datetime)
614
+	 *
615
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
+	 * @throws EE_Error
617
+	 * @throws ReflectionException
618
+	 */
619
+	public function update_sold(array $datetimes)
620
+	{
621
+		EE_Error::doing_it_wrong(
622
+			__FUNCTION__,
623
+			esc_html__(
624
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
+				'event_espresso'
626
+			),
627
+			'4.9.32.rc.005'
628
+		);
629
+		foreach ($datetimes as $datetime) {
630
+			$datetime->update_sold();
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 *    Gets the total number of tickets available at a particular datetime
637
+	 *    (does NOT take into account the datetime's spaces available)
638
+	 *
639
+	 * @param int   $DTT_ID
640
+	 * @param array $query_params
641
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
+	 *             tickets attached to datetime then FALSE is returned.
643
+	 * @throws EE_Error
644
+	 * @throws ReflectionException
645
+	 */
646
+	public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = [])
647
+	{
648
+		$datetime = $this->get_one_by_ID($DTT_ID);
649
+		if ($datetime instanceof EE_Datetime) {
650
+			return $datetime->tickets_remaining($query_params);
651
+		}
652
+		return 0;
653
+	}
654
+
655
+
656
+	/**
657
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
+	 *
659
+	 * @param array $stati_to_include  If included you can restrict the statuses we return counts for by including the
660
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
661
+	 *                                 for all valid stati.
662
+	 * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
664
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
+	 * @throws EE_Error
666
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
667
+	 *                                 EE_Datetime::expired
668
+	 */
669
+	public function get_datetime_counts_by_status(array $stati_to_include = [], array $query_params = [])
670
+	{
671
+		// only accept where conditions for this query.
672
+		$_where            = isset($query_params[0]) ? $query_params[0] : [];
673
+		$status_query_args = [
674
+			EE_Datetime::active   => array_merge(
675
+				$_where,
676
+				['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
677
+			),
678
+			EE_Datetime::upcoming => array_merge(
679
+				$_where,
680
+				['DTT_EVT_start' => ['>', time()]]
681
+			),
682
+			EE_Datetime::expired  => array_merge(
683
+				$_where,
684
+				['DTT_EVT_end' => ['<', time()]]
685
+			),
686
+		];
687
+		if (! empty($stati_to_include)) {
688
+			foreach (array_keys($status_query_args) as $status) {
689
+				if (! in_array($status, $stati_to_include, true)) {
690
+					unset($status_query_args[ $status ]);
691
+				}
692
+			}
693
+		}
694
+		// loop through and query counts for each stati.
695
+		$status_query_results = [];
696
+		foreach ($status_query_args as $status => $status_where_conditions) {
697
+			$status_query_results[ $status ] = EEM_Datetime::count(
698
+				[$status_where_conditions],
699
+				'DTT_ID',
700
+				true
701
+			);
702
+		}
703
+		return $status_query_results;
704
+	}
705
+
706
+
707
+	/**
708
+	 * Returns the specific count for a given Datetime status matching any given query_params.
709
+	 *
710
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
711
+	 * @param array  $query_params
712
+	 * @return int
713
+	 * @throws EE_Error
714
+	 */
715
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = [])
716
+	{
717
+		$count = $this->get_datetime_counts_by_status([$status], $query_params);
718
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
719
+	}
720
+
721
+
722
+	/**
723
+	 * @return bool|int
724
+	 * @since   $VID:$
725
+	 */
726
+	private function prepModelForQuery()
727
+	{
728
+		$prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
729
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
730
+		return $prev_data_prep_value;
731
+	}
732
+
733
+
734
+	/**
735
+	 * @param array    $query_params
736
+	 * @param bool|int $prev_data_prep_value
737
+	 * @return EE_Base_Class[]|EE_Datetime[]
738
+	 * @throws EE_Error
739
+	 * @since   $VID:$
740
+	 */
741
+	private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value)
742
+	{
743
+		$result = $this->get_all($query_params);
744
+		$this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
745
+		return $result;
746
+	}
747
+
748
+
749
+	/**
750
+	 * @param array  $query_params
751
+	 * @param int    $limit
752
+	 * @param string $order_by
753
+	 * @param string $order
754
+	 * @return array
755
+	 * @since   $VID:$
756
+	 */
757
+	private function addDefaultQueryParams(array $query_params, $limit = 0, $order_by = 'DTT_EVT_start', $order = 'ASC')
758
+	{
759
+		$query_params = $this->addOrderByQueryParams($query_params, $order_by, $order);
760
+		$query_params = $this->addLimitQueryParams($query_params, $limit);
761
+		return $query_params;
762
+	}
763
+
764
+
765
+	/**
766
+	 * @param array  $query_params
767
+	 * @param string $default_where_conditions
768
+	 * @return array
769
+	 * @since   $VID:$
770
+	 */
771
+	private function addDefaultWhereConditions(
772
+		array $query_params,
773
+		$default_where_conditions = EEM_Base::default_where_conditions_none
774
+	) {
775
+		$query_params['default_where_conditions'] = $default_where_conditions;
776
+		return $query_params;
777
+	}
778
+
779
+
780
+	/**
781
+	 * @param array $where_params
782
+	 * @param bool  $include_deleted
783
+	 * @param bool  $include_expired
784
+	 * @return array
785
+	 * @since   $VID:$
786
+	 */
787
+	private function addDefaultWhereParams(array $where_params, bool $include_deleted = true, bool $include_expired = true)
788
+	{
789
+		$where_params = $this->addExpiredWhereParams($where_params, $include_expired);
790
+		$where_params = $this->addDeletedWhereParams($where_params, $include_deleted);
791
+		return $where_params;
792
+	}
793
+
794
+
795
+	/**
796
+	 * @param array $where_params
797
+	 * @param bool  $include_deleted
798
+	 * @return array
799
+	 * @since   $VID:$
800
+	 */
801
+	private function addDeletedWhereParams(array $where_params, bool $include_deleted = true)
802
+	{
803
+		$deleted                     = $include_deleted ? [true, false] : [false];
804
+		$where_params['DTT_deleted'] = ['IN', $deleted];
805
+		return $where_params;
806
+	}
807
+
808
+
809
+	/**
810
+	 * @param array $where_params
811
+	 * @param bool  $include_expired
812
+	 * @return array
813
+	 * @since   $VID:$
814
+	 */
815
+	private function addExpiredWhereParams(array $where_params, bool $include_expired = true)
816
+	{
817
+		if (! $include_expired) {
818
+			$where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
819
+		}
820
+		return $where_params;
821
+	}
822
+
823
+
824
+	/**
825
+	 * @param array $query_params
826
+	 * @param int   $limit
827
+	 * @return array
828
+	 * @since   $VID:$
829
+	 */
830
+	private function addLimitQueryParams(array $query_params, $limit = 0)
831
+	{
832
+		if ($limit) {
833
+			$query_params['limit'] = $limit;
834
+		}
835
+		return $query_params;
836
+	}
837
+
838
+
839
+	/**
840
+	 * @param array  $query_params
841
+	 * @param string $order_by
842
+	 * @param string $order
843
+	 * @return array
844
+	 * @since   $VID:$
845
+	 */
846
+	private function addOrderByQueryParams(array $query_params, $order_by = 'DTT_EVT_start', $order = 'ASC')
847
+	{
848
+		$order                    = $order === 'ASC' ? 'ASC' : 'DESC';
849
+		$valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
850
+		$order_by                 = in_array($order_by, $valid_order_columns, true) ? $order_by : 'DTT_EVT_start';
851
+		$query_params['order_by'] = [$order_by => $order];
852
+		return $query_params;
853
+	}
854 854
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 1 patch
Indentation   +927 added lines, -927 removed lines patch added patch discarded remove patch
@@ -14,931 +14,931 @@
 block discarded – undo
14 14
 class EEM_Event extends EEM_CPT_Base
15 15
 {
16 16
 
17
-    /**
18
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
-     * event
20
-     */
21
-    const sold_out = 'sold_out';
22
-
23
-    /**
24
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
-     * date)
26
-     */
27
-    const postponed = 'postponed';
28
-
29
-    /**
30
-     * constant used by status(), indicating that the event will no longer occur
31
-     */
32
-    const cancelled = 'cancelled';
33
-
34
-
35
-    /**
36
-     * @var string
37
-     */
38
-    protected static $_default_reg_status;
39
-
40
-
41
-    /**
42
-     * This is the default for the additional limit field.
43
-     * @var int
44
-     */
45
-    protected static $_default_additional_limit = 10;
46
-
47
-
48
-    /**
49
-     * private instance of the Event object
50
-     *
51
-     * @var EEM_Event
52
-     */
53
-    protected static $_instance;
54
-
55
-
56
-    /**
57
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
58
-     *
59
-     * @param string $timezone
60
-     * @throws EE_Error
61
-     * @throws ReflectionException
62
-     */
63
-    protected function __construct($timezone = null)
64
-    {
65
-        EE_Registry::instance()->load_model('Registration');
66
-        $this->singular_item = esc_html__('Event', 'event_espresso');
67
-        $this->plural_item = esc_html__('Events', 'event_espresso');
68
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
69
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
70
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
71
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
72
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
73
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
74
-        $this->_custom_stati = apply_filters(
75
-            'AFEE__EEM_Event__construct___custom_stati',
76
-            array(
77
-                EEM_Event::cancelled => array(
78
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
79
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
80
-                ),
81
-                EEM_Event::postponed => array(
82
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
83
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
84
-                ),
85
-                EEM_Event::sold_out  => array(
86
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
87
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
88
-                ),
89
-            )
90
-        );
91
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
92
-            : self::$_default_reg_status;
93
-        $this->_tables = array(
94
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
95
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
96
-        );
97
-        $this->_fields = array(
98
-            'Event_CPT'  => array(
99
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
100
-                    'ID',
101
-                    esc_html__('Post ID for Event', 'event_espresso')
102
-                ),
103
-                'EVT_name'       => new EE_Plain_Text_Field(
104
-                    'post_title',
105
-                    esc_html__('Event Name', 'event_espresso'),
106
-                    false,
107
-                    ''
108
-                ),
109
-                'EVT_desc'       => new EE_Post_Content_Field(
110
-                    'post_content',
111
-                    esc_html__('Event Description', 'event_espresso'),
112
-                    false,
113
-                    ''
114
-                ),
115
-                'EVT_slug'       => new EE_Slug_Field(
116
-                    'post_name',
117
-                    esc_html__('Event Slug', 'event_espresso'),
118
-                    false,
119
-                    ''
120
-                ),
121
-                'EVT_created'    => new EE_Datetime_Field(
122
-                    'post_date',
123
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
124
-                    false,
125
-                    EE_Datetime_Field::now
126
-                ),
127
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
128
-                    'post_excerpt',
129
-                    esc_html__('Event Short Description', 'event_espresso'),
130
-                    false,
131
-                    ''
132
-                ),
133
-                'EVT_modified'   => new EE_Datetime_Field(
134
-                    'post_modified',
135
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
136
-                    false,
137
-                    EE_Datetime_Field::now
138
-                ),
139
-                'EVT_wp_user'    => new EE_WP_User_Field(
140
-                    'post_author',
141
-                    esc_html__('Event Creator ID', 'event_espresso'),
142
-                    false
143
-                ),
144
-                'parent'         => new EE_Integer_Field(
145
-                    'post_parent',
146
-                    esc_html__('Event Parent ID', 'event_espresso'),
147
-                    false,
148
-                    0
149
-                ),
150
-                'EVT_order'      => new EE_Integer_Field(
151
-                    'menu_order',
152
-                    esc_html__('Event Menu Order', 'event_espresso'),
153
-                    false,
154
-                    1
155
-                ),
156
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
157
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
158
-                'status'         => new EE_WP_Post_Status_Field(
159
-                    'post_status',
160
-                    esc_html__('Event Status', 'event_espresso'),
161
-                    false,
162
-                    'draft',
163
-                    $this->_custom_stati
164
-                ),
165
-                'password' => new EE_Password_Field(
166
-                    'post_password',
167
-                    __('Password', 'event_espresso'),
168
-                    false,
169
-                    '',
170
-                    array(
171
-                        'EVT_desc',
172
-                        'EVT_short_desc',
173
-                        'EVT_display_desc',
174
-                        'EVT_display_ticket_selector',
175
-                        'EVT_visible_on',
176
-                        'EVT_additional_limit',
177
-                        'EVT_default_registration_status',
178
-                        'EVT_member_only',
179
-                        'EVT_phone',
180
-                        'EVT_allow_overflow',
181
-                        'EVT_timezone_string',
182
-                        'EVT_external_URL',
183
-                        'EVT_donations'
184
-                    )
185
-                )
186
-            ),
187
-            'Event_Meta' => array(
188
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
189
-                    'EVTM_ID',
190
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
191
-                    false
192
-                ),
193
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
194
-                    'EVT_ID',
195
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
196
-                    false
197
-                ),
198
-                'VNU_ID' => new EE_Foreign_Key_Int_Field(
199
-                    'VNU_ID',
200
-                    __('Venue ID', 'event_espresso'),
201
-                    false,
202
-                    0,
203
-                    'Venue'
204
-                ),
205
-                'EVT_display_desc'                => new EE_Boolean_Field(
206
-                    'EVT_display_desc',
207
-                    esc_html__('Display Description Flag', 'event_espresso'),
208
-                    false,
209
-                    true
210
-                ),
211
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
212
-                    'EVT_display_ticket_selector',
213
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
214
-                    false,
215
-                    true
216
-                ),
217
-                'EVT_visible_on'                  => new EE_Datetime_Field(
218
-                    'EVT_visible_on',
219
-                    esc_html__('Event Visible Date', 'event_espresso'),
220
-                    true,
221
-                    EE_Datetime_Field::now
222
-                ),
223
-                'EVT_additional_limit'            => new EE_Integer_Field(
224
-                    'EVT_additional_limit',
225
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
226
-                    true,
227
-                    self::$_default_additional_limit
228
-                ),
229
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
230
-                    'EVT_default_registration_status',
231
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
232
-                    false,
233
-                    EEM_Event::$_default_reg_status,
234
-                    EEM_Registration::reg_status_array()
235
-                ),
236
-                'EVT_member_only'                 => new EE_Boolean_Field(
237
-                    'EVT_member_only',
238
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
239
-                    false,
240
-                    false
241
-                ),
242
-                'EVT_phone'                       => new EE_Plain_Text_Field(
243
-                    'EVT_phone',
244
-                    esc_html__('Event Phone Number', 'event_espresso'),
245
-                    false,
246
-                    ''
247
-                ),
248
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
249
-                    'EVT_allow_overflow',
250
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
251
-                    false,
252
-                    false
253
-                ),
254
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
255
-                    'EVT_timezone_string',
256
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
257
-                    false,
258
-                    ''
259
-                ),
260
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
261
-                    'EVT_external_URL',
262
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
263
-                    true
264
-                ),
265
-                'EVT_donations'                   => new EE_Boolean_Field(
266
-                    'EVT_donations',
267
-                    esc_html__('Accept Donations?', 'event_espresso'),
268
-                    false,
269
-                    false
270
-                ),
271
-                'FSC_UUID'                        => new EE_Foreign_Key_String_Field(
272
-                    'FSC_UUID',
273
-                    esc_html__('Registration Form UUID (universally unique identifier)', 'event_espresso'),
274
-                    true,
275
-                    null,
276
-                    'Form_Section',
277
-                    false
278
-                ),
279
-            ),
280
-        );
281
-        $this->_model_relations = array(
282
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
283
-            'Datetime'               => new EE_Has_Many_Relation(),
284
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
285
-            'Form_Section'           => new EE_Belongs_To_Relation(),
286
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
287
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
288
-            'Registration'           => new EE_Has_Many_Relation(),
289
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
290
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
291
-            'Venue'                  => new EE_Belongs_To_Relation(),
292
-            'WP_User'                => new EE_Belongs_To_Relation(),
293
-        );
294
-        // this model is generally available for reading
295
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
296
-        $this->model_chain_to_password = '';
297
-        parent::__construct($timezone);
298
-    }
299
-
300
-
301
-    /**
302
-     * @param string $default_reg_status
303
-     * @throws EE_Error
304
-     * @throws EE_Error
305
-     */
306
-    public static function set_default_reg_status($default_reg_status)
307
-    {
308
-        self::$_default_reg_status = $default_reg_status;
309
-        // if EEM_Event has already been instantiated,
310
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
311
-        if (self::$_instance instanceof EEM_Event) {
312
-            $default_reg_status = new EE_Enum_Text_Field(
313
-                'EVT_default_registration_status',
314
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
315
-                false,
316
-                $default_reg_status,
317
-                EEM_Registration::reg_status_array()
318
-            );
319
-            $default_reg_status->_construct_finalize(
320
-                'Event_Meta',
321
-                'EVT_default_registration_status',
322
-                'EEM_Event'
323
-            );
324
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
325
-        }
326
-    }
327
-
328
-
329
-    /**
330
-     * Used to override the default for the additional limit field.
331
-     * @param $additional_limit
332
-     */
333
-    public static function set_default_additional_limit($additional_limit)
334
-    {
335
-        self::$_default_additional_limit = (int) $additional_limit;
336
-        if (self::$_instance instanceof EEM_Event) {
337
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
338
-                'EVT_additional_limit',
339
-                __('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
340
-                true,
341
-                self::$_default_additional_limit
342
-            );
343
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
344
-                'Event_Meta',
345
-                'EVT_additional_limit',
346
-                'EEM_Event'
347
-            );
348
-        }
349
-    }
350
-
351
-
352
-    /**
353
-     * Return what is currently set as the default additional limit for the event.
354
-     * @return int
355
-     */
356
-    public static function get_default_additional_limit()
357
-    {
358
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
359
-    }
360
-
361
-
362
-    /**
363
-     * get_question_groups
364
-     *
365
-     * @return array
366
-     * @throws EE_Error
367
-     * @throws ReflectionException
368
-     */
369
-    public function get_all_question_groups()
370
-    {
371
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
372
-            array(
373
-                array('QSG_deleted' => false),
374
-                'order_by' => array('QSG_order' => 'ASC'),
375
-            )
376
-        );
377
-    }
378
-
379
-
380
-    /**
381
-     * get_question_groups
382
-     *
383
-     * @param int $EVT_ID
384
-     * @return array|bool
385
-     * @throws EE_Error
386
-     * @throws ReflectionException
387
-     */
388
-    public function get_all_event_question_groups($EVT_ID = 0)
389
-    {
390
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
391
-            EE_Error::add_error(
392
-                esc_html__(
393
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
394
-                    'event_espresso'
395
-                ),
396
-                __FILE__,
397
-                __FUNCTION__,
398
-                __LINE__
399
-            );
400
-            return false;
401
-        }
402
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
403
-            array(
404
-                array('EVT_ID' => $EVT_ID),
405
-            )
406
-        );
407
-    }
408
-
409
-
410
-    /**
411
-     * get_question_groups
412
-     *
413
-     * @param int $EVT_ID
414
-     * @param boolean $for_primary_attendee
415
-     * @return array|bool
416
-     * @throws EE_Error
417
-     * @throws InvalidArgumentException
418
-     * @throws ReflectionException
419
-     * @throws InvalidDataTypeException
420
-     * @throws InvalidInterfaceException
421
-     */
422
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
423
-    {
424
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
425
-            EE_Error::add_error(
426
-                esc_html__(
427
-                    // @codingStandardsIgnoreStart
428
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
429
-                    // @codingStandardsIgnoreEnd
430
-                    'event_espresso'
431
-                ),
432
-                __FILE__,
433
-                __FUNCTION__,
434
-                __LINE__
435
-            );
436
-            return false;
437
-        }
438
-        $query_params = [
439
-            [
440
-                'EVT_ID' => $EVT_ID,
441
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
442
-            ]
443
-        ];
444
-        if ($for_primary_attendee) {
445
-            $query_params[0]['EQG_primary'] = true;
446
-        } else {
447
-            $query_params[0]['EQG_additional'] = true;
448
-        }
449
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
450
-    }
451
-
452
-
453
-    /**
454
-     * get_question_groups
455
-     *
456
-     * @param int $EVT_ID
457
-     * @param EE_Registration $registration
458
-     * @return array|bool
459
-     * @throws EE_Error
460
-     * @throws InvalidArgumentException
461
-     * @throws InvalidDataTypeException
462
-     * @throws InvalidInterfaceException
463
-     * @throws ReflectionException
464
-     */
465
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
466
-    {
467
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
468
-            EE_Error::add_error(
469
-                esc_html__(
470
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
471
-                    'event_espresso'
472
-                ),
473
-                __FILE__,
474
-                __FUNCTION__,
475
-                __LINE__
476
-            );
477
-            return false;
478
-        }
479
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
480
-            [
481
-                [
482
-                    'Event_Question_Group.EVT_ID'      => $EVT_ID,
483
-                    'Event_Question_Group.'
484
-                        . EEM_Event_Question_Group::instance()->fieldNameForContext(
485
-                            $registration->is_primary_registrant()
486
-                        ) => true
487
-                ],
488
-                'order_by' => ['QSG_order' => 'ASC'],
489
-            ]
490
-        );
491
-    }
492
-
493
-
494
-    /**
495
-     * get_question_target_db_column
496
-     *
497
-     * @param string $QSG_IDs csv list of $QSG IDs
498
-     * @return array|bool
499
-     * @throws EE_Error
500
-     * @throws ReflectionException
501
-     */
502
-    public function get_questions_in_groups($QSG_IDs = '')
503
-    {
504
-        if (empty($QSG_IDs)) {
505
-            EE_Error::add_error(
506
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
507
-                __FILE__,
508
-                __FUNCTION__,
509
-                __LINE__
510
-            );
511
-            return false;
512
-        }
513
-        return EE_Registry::instance()->load_model('Question')->get_all(
514
-            array(
515
-                array(
516
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
517
-                    'QST_deleted'           => false,
518
-                    'QST_admin_only'        => is_admin(),
519
-                ),
520
-                'order_by' => 'QST_order',
521
-            )
522
-        );
523
-    }
524
-
525
-
526
-    /**
527
-     * get_options_for_question
528
-     *
529
-     * @param string $QST_IDs csv list of $QST IDs
530
-     * @return array|bool
531
-     * @throws EE_Error
532
-     * @throws ReflectionException
533
-     */
534
-    public function get_options_for_question($QST_IDs)
535
-    {
536
-        if (empty($QST_IDs)) {
537
-            EE_Error::add_error(
538
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
539
-                __FILE__,
540
-                __FUNCTION__,
541
-                __LINE__
542
-            );
543
-            return false;
544
-        }
545
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
546
-            array(
547
-                array(
548
-                    'Question.QST_ID' => array('IN', $QST_IDs),
549
-                    'QSO_deleted'     => false,
550
-                ),
551
-                'order_by' => 'QSO_ID',
552
-            )
553
-        );
554
-    }
555
-
556
-
557
-    /**
558
-     * Gets all events that are published
559
-     * and have event start time earlier than now and an event end time later than now
560
-     *
561
-     * @param array $query_params  An array of query params to further filter on
562
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
563
-     * @param bool  $count         whether to return the count or not (default FALSE)
564
-     * @return EE_Event[]|int
565
-     * @throws EE_Error
566
-     * @throws ReflectionException
567
-     */
568
-    public function get_active_events($query_params, $count = false)
569
-    {
570
-        if (array_key_exists(0, $query_params)) {
571
-            $where_params = $query_params[0];
572
-            unset($query_params[0]);
573
-        } else {
574
-            $where_params = array();
575
-        }
576
-        // if we have count make sure we don't include group by
577
-        if ($count && isset($query_params['group_by'])) {
578
-            unset($query_params['group_by']);
579
-        }
580
-        // let's add specific query_params for active_events
581
-        // keep in mind this will override any sent status in the query AND any date queries.
582
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
583
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
584
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
585
-            $where_params['Datetime.DTT_EVT_start******'] = array(
586
-                '<',
587
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
588
-            );
589
-        } else {
590
-            $where_params['Datetime.DTT_EVT_start'] = array(
591
-                '<',
592
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
593
-            );
594
-        }
595
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
596
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
597
-                '>',
598
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
599
-            );
600
-        } else {
601
-            $where_params['Datetime.DTT_EVT_end'] = array(
602
-                '>',
603
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
604
-            );
605
-        }
606
-        $query_params[0] = $where_params;
607
-        // don't use $query_params with count()
608
-        // because we don't want to include additional query clauses like "GROUP BY"
609
-        return $count
610
-            ? $this->count(array($where_params), 'EVT_ID', true)
611
-            : $this->get_all($query_params);
612
-    }
613
-
614
-
615
-    /**
616
-     * get all events that are published and have an event start time later than now
617
-     *
618
-     * @param array $query_params  An array of query params to further filter on
619
-     *                             (Note that status and DTT_EVT_start will be overridden)
620
-     * @param bool  $count         whether to return the count or not (default FALSE)
621
-     * @return EE_Event[]|int
622
-     * @throws EE_Error
623
-     * @throws ReflectionException
624
-     */
625
-    public function get_upcoming_events($query_params, $count = false)
626
-    {
627
-        if (array_key_exists(0, $query_params)) {
628
-            $where_params = $query_params[0];
629
-            unset($query_params[0]);
630
-        } else {
631
-            $where_params = array();
632
-        }
633
-        // if we have count make sure we don't include group by
634
-        if ($count && isset($query_params['group_by'])) {
635
-            unset($query_params['group_by']);
636
-        }
637
-        // let's add specific query_params for active_events
638
-        // keep in mind this will override any sent status in the query AND any date queries.
639
-        // we need to pull events with a status of publish and sold_out
640
-        $event_status = array('publish', EEM_Event::sold_out);
641
-        // check if the user can read private events and if so add the 'private status to the were params'
642
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
643
-            $event_status[] = 'private';
644
-        }
645
-        $where_params['status'] = array('IN', $event_status);
646
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
647
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
648
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
649
-                '>',
650
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
651
-            );
652
-        } else {
653
-            $where_params['Datetime.DTT_EVT_start'] = array(
654
-                '>',
655
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
656
-            );
657
-        }
658
-        $query_params[0] = $where_params;
659
-        // don't use $query_params with count()
660
-        // because we don't want to include additional query clauses like "GROUP BY"
661
-        return $count
662
-            ? $this->count(array($where_params), 'EVT_ID', true)
663
-            : $this->get_all($query_params);
664
-    }
665
-
666
-
667
-    /**
668
-     * Gets all events that are published
669
-     * and have an event end time later than now
670
-     *
671
-     * @param array $query_params  An array of query params to further filter on
672
-     *                             (note that status and DTT_EVT_end will be overridden)
673
-     * @param bool  $count         whether to return the count or not (default FALSE)
674
-     * @return EE_Event[]|int
675
-     * @throws EE_Error
676
-     * @throws ReflectionException
677
-     */
678
-    public function get_active_and_upcoming_events($query_params, $count = false)
679
-    {
680
-        if (array_key_exists(0, $query_params)) {
681
-            $where_params = $query_params[0];
682
-            unset($query_params[0]);
683
-        } else {
684
-            $where_params = array();
685
-        }
686
-        // if we have count make sure we don't include group by
687
-        if ($count && isset($query_params['group_by'])) {
688
-            unset($query_params['group_by']);
689
-        }
690
-        // let's add specific query_params for active_events
691
-        // keep in mind this will override any sent status in the query AND any date queries.
692
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
693
-        // add where params for DTT_EVT_end
694
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
695
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
696
-                '>',
697
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
698
-            );
699
-        } else {
700
-            $where_params['Datetime.DTT_EVT_end'] = array(
701
-                '>',
702
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
703
-            );
704
-        }
705
-        $query_params[0] = $where_params;
706
-        // don't use $query_params with count()
707
-        // because we don't want to include additional query clauses like "GROUP BY"
708
-        return $count
709
-            ? $this->count(array($where_params), 'EVT_ID', true)
710
-            : $this->get_all($query_params);
711
-    }
712
-
713
-
714
-    /**
715
-     * This only returns events that are expired.
716
-     * They may still be published but all their datetimes have expired.
717
-     *
718
-     * @param array $query_params  An array of query params to further filter on
719
-     *                             (note that status and DTT_EVT_end will be overridden)
720
-     * @param bool  $count         whether to return the count or not (default FALSE)
721
-     * @return EE_Event[]|int
722
-     * @throws EE_Error
723
-     * @throws ReflectionException
724
-     */
725
-    public function get_expired_events($query_params, $count = false)
726
-    {
727
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
728
-        // if we have count make sure we don't include group by
729
-        if ($count && isset($query_params['group_by'])) {
730
-            unset($query_params['group_by']);
731
-        }
732
-        // let's add specific query_params for active_events
733
-        // keep in mind this will override any sent status in the query AND any date queries.
734
-        if (isset($where_params['status'])) {
735
-            unset($where_params['status']);
736
-        }
737
-        $exclude_query = $query_params;
738
-        if (isset($exclude_query[0])) {
739
-            unset($exclude_query[0]);
740
-        }
741
-        $exclude_query[0] = array(
742
-            'Datetime.DTT_EVT_end' => array(
743
-                '>',
744
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
745
-            ),
746
-        );
747
-        // first get all events that have datetimes where its not expired.
748
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
749
-        $event_ids = array_keys($event_ids);
750
-        // if we have any additional query_params, let's add them to the 'AND' condition
751
-        $and_condition = array(
752
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
753
-            'EVT_ID'               => array('NOT IN', $event_ids),
754
-        );
755
-        if (isset($where_params['OR'])) {
756
-            $and_condition['OR'] = $where_params['OR'];
757
-            unset($where_params['OR']);
758
-        }
759
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
760
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
761
-            unset($where_params['Datetime.DTT_EVT_end']);
762
-        }
763
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
764
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
765
-            unset($where_params['Datetime.DTT_EVT_start']);
766
-        }
767
-        // merge remaining $where params with the and conditions.
768
-        $where_params['AND'] = array_merge($and_condition, $where_params);
769
-        $query_params[0] = $where_params;
770
-        // don't use $query_params with count()
771
-        // because we don't want to include additional query clauses like "GROUP BY"
772
-        return $count
773
-            ? $this->count(array($where_params), 'EVT_ID', true)
774
-            : $this->get_all($query_params);
775
-    }
776
-
777
-
778
-
779
-    /**
780
-     * This basically just returns the events that do not have the publish status.
781
-     *
782
-     * @param  array   $query_params An array of query params to further filter on
783
-     *                               (note that status will be overwritten)
784
-     * @param  boolean $count        whether to return the count or not (default FALSE)
785
-     * @return EE_Event[]|int
786
-     * @throws EE_Error
787
-     */
788
-    public function get_inactive_events($query_params, $count = false)
789
-    {
790
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
791
-        // let's add in specific query_params for inactive events.
792
-        if (isset($where_params['status'])) {
793
-            unset($where_params['status']);
794
-        }
795
-        // if we have count make sure we don't include group by
796
-        if ($count && isset($query_params['group_by'])) {
797
-            unset($query_params['group_by']);
798
-        }
799
-        // if we have any additional query_params, let's add them to the 'AND' condition
800
-        $where_params['AND']['status'] = array('!=', 'publish');
801
-        if (isset($where_params['OR'])) {
802
-            $where_params['AND']['OR'] = $where_params['OR'];
803
-            unset($where_params['OR']);
804
-        }
805
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
806
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
807
-            unset($where_params['Datetime.DTT_EVT_end']);
808
-        }
809
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
810
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
811
-            unset($where_params['Datetime.DTT_EVT_start']);
812
-        }
813
-        $query_params[0] = $where_params;
814
-        // don't use $query_params with count()
815
-        // because we don't want to include additional query clauses like "GROUP BY"
816
-        return $count
817
-            ? $this->count(array($where_params), 'EVT_ID', true)
818
-            : $this->get_all($query_params);
819
-    }
820
-
821
-
822
-    /**
823
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
824
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
825
-     * attached to the event. See parent for param descriptions
826
-     *
827
-     * @param        $id_or_obj
828
-     * @param        $other_model_id_or_obj
829
-     * @param string $relationName
830
-     * @param array  $where_query
831
-     * @return EE_Base_Class
832
-     * @throws EE_Error
833
-     * @throws ReflectionException
834
-     */
835
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
836
-    {
837
-        if ($relationName === 'Price') {
838
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
839
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
840
-            // if EVT_ID = 0, then this is a default
841
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
842
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
843
-                $prc_chk->set('PRC_ID', 0);
844
-            }
845
-            // run parent
846
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
847
-        }
848
-        // otherwise carry on as normal
849
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
850
-    }
851
-
852
-
853
-
854
-    /******************** DEPRECATED METHODS ********************/
855
-
856
-
857
-    /**
858
-     * _get_question_target_db_column
859
-     *
860
-     * @param EE_Registration $registration    (so existing answers for registration are included)
861
-     * @param int             $EVT_ID          so all question groups are included for event (not just answers from
862
-     *                                         registration).
863
-     * @return    array
864
-     * @throws ReflectionException
865
-     * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
866
-     *                                         EE_Registration_Custom_Questions_Form located in
867
-     *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
868
-     * @access     public
869
-     */
870
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
871
-    {
872
-        if (empty($EVT_ID)) {
873
-            throw new EE_Error(__(
874
-                'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
875
-                'event_espresso'
876
-            ));
877
-        }
878
-        $questions = array();
879
-        // get all question groups for event
880
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
881
-        if (! empty($qgs)) {
882
-            foreach ($qgs as $qg) {
883
-                $qsts = $qg->questions();
884
-                $questions[ $qg->ID() ] = $qg->model_field_array();
885
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
886
-                foreach ($qsts as $qst) {
887
-                    if ($qst->is_system_question()) {
888
-                        continue;
889
-                    }
890
-                    $answer = EEM_Answer::instance()->get_one(array(
891
-                        array(
892
-                            'QST_ID' => $qst->ID(),
893
-                            'REG_ID' => $registration->ID(),
894
-                        ),
895
-                    ));
896
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
897
-                    $qst_name = $qstn_id = $qst->ID();
898
-                    $ans_id = $answer->ID();
899
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
900
-                    $input_name = '';
901
-                    $input_id = sanitize_key($qst->display_text());
902
-                    $input_class = '';
903
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
904
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
905
-                                                                                           . $input_name
906
-                                                                                           . $qst_name;
907
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
908
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
909
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
910
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
911
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
912
-                    // leave responses as-is, don't convert stuff into html entities please!
913
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
914
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
915
-                        $QSOs = $qst->options(true, $answer->value());
916
-                        if (is_array($QSOs)) {
917
-                            foreach ($QSOs as $QSO_ID => $QSO) {
918
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
919
-                            }
920
-                        }
921
-                    }
922
-                }
923
-            }
924
-        }
925
-        return $questions;
926
-    }
927
-
928
-
929
-    /**
930
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
931
-     *                             or an stdClass where each property is the name of a column,
932
-     * @return EE_Base_Class
933
-     * @throws EE_Error
934
-     */
935
-    public function instantiate_class_from_array_or_object($cols_n_values)
936
-    {
937
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
938
-        if ($classInstance instanceof EE_Event) {
939
-            // events have their timezone defined in the DB, so use it immediately
940
-            $this->set_timezone($classInstance->get_timezone());
941
-        }
942
-        return $classInstance;
943
-    }
17
+	/**
18
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
+	 * event
20
+	 */
21
+	const sold_out = 'sold_out';
22
+
23
+	/**
24
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
+	 * date)
26
+	 */
27
+	const postponed = 'postponed';
28
+
29
+	/**
30
+	 * constant used by status(), indicating that the event will no longer occur
31
+	 */
32
+	const cancelled = 'cancelled';
33
+
34
+
35
+	/**
36
+	 * @var string
37
+	 */
38
+	protected static $_default_reg_status;
39
+
40
+
41
+	/**
42
+	 * This is the default for the additional limit field.
43
+	 * @var int
44
+	 */
45
+	protected static $_default_additional_limit = 10;
46
+
47
+
48
+	/**
49
+	 * private instance of the Event object
50
+	 *
51
+	 * @var EEM_Event
52
+	 */
53
+	protected static $_instance;
54
+
55
+
56
+	/**
57
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
58
+	 *
59
+	 * @param string $timezone
60
+	 * @throws EE_Error
61
+	 * @throws ReflectionException
62
+	 */
63
+	protected function __construct($timezone = null)
64
+	{
65
+		EE_Registry::instance()->load_model('Registration');
66
+		$this->singular_item = esc_html__('Event', 'event_espresso');
67
+		$this->plural_item = esc_html__('Events', 'event_espresso');
68
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
69
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
70
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
71
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
72
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
73
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
74
+		$this->_custom_stati = apply_filters(
75
+			'AFEE__EEM_Event__construct___custom_stati',
76
+			array(
77
+				EEM_Event::cancelled => array(
78
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
79
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
80
+				),
81
+				EEM_Event::postponed => array(
82
+					'label'  => esc_html__('Postponed', 'event_espresso'),
83
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
84
+				),
85
+				EEM_Event::sold_out  => array(
86
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
87
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
88
+				),
89
+			)
90
+		);
91
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
92
+			: self::$_default_reg_status;
93
+		$this->_tables = array(
94
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
95
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
96
+		);
97
+		$this->_fields = array(
98
+			'Event_CPT'  => array(
99
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
100
+					'ID',
101
+					esc_html__('Post ID for Event', 'event_espresso')
102
+				),
103
+				'EVT_name'       => new EE_Plain_Text_Field(
104
+					'post_title',
105
+					esc_html__('Event Name', 'event_espresso'),
106
+					false,
107
+					''
108
+				),
109
+				'EVT_desc'       => new EE_Post_Content_Field(
110
+					'post_content',
111
+					esc_html__('Event Description', 'event_espresso'),
112
+					false,
113
+					''
114
+				),
115
+				'EVT_slug'       => new EE_Slug_Field(
116
+					'post_name',
117
+					esc_html__('Event Slug', 'event_espresso'),
118
+					false,
119
+					''
120
+				),
121
+				'EVT_created'    => new EE_Datetime_Field(
122
+					'post_date',
123
+					esc_html__('Date/Time Event Created', 'event_espresso'),
124
+					false,
125
+					EE_Datetime_Field::now
126
+				),
127
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
128
+					'post_excerpt',
129
+					esc_html__('Event Short Description', 'event_espresso'),
130
+					false,
131
+					''
132
+				),
133
+				'EVT_modified'   => new EE_Datetime_Field(
134
+					'post_modified',
135
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
136
+					false,
137
+					EE_Datetime_Field::now
138
+				),
139
+				'EVT_wp_user'    => new EE_WP_User_Field(
140
+					'post_author',
141
+					esc_html__('Event Creator ID', 'event_espresso'),
142
+					false
143
+				),
144
+				'parent'         => new EE_Integer_Field(
145
+					'post_parent',
146
+					esc_html__('Event Parent ID', 'event_espresso'),
147
+					false,
148
+					0
149
+				),
150
+				'EVT_order'      => new EE_Integer_Field(
151
+					'menu_order',
152
+					esc_html__('Event Menu Order', 'event_espresso'),
153
+					false,
154
+					1
155
+				),
156
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
157
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
158
+				'status'         => new EE_WP_Post_Status_Field(
159
+					'post_status',
160
+					esc_html__('Event Status', 'event_espresso'),
161
+					false,
162
+					'draft',
163
+					$this->_custom_stati
164
+				),
165
+				'password' => new EE_Password_Field(
166
+					'post_password',
167
+					__('Password', 'event_espresso'),
168
+					false,
169
+					'',
170
+					array(
171
+						'EVT_desc',
172
+						'EVT_short_desc',
173
+						'EVT_display_desc',
174
+						'EVT_display_ticket_selector',
175
+						'EVT_visible_on',
176
+						'EVT_additional_limit',
177
+						'EVT_default_registration_status',
178
+						'EVT_member_only',
179
+						'EVT_phone',
180
+						'EVT_allow_overflow',
181
+						'EVT_timezone_string',
182
+						'EVT_external_URL',
183
+						'EVT_donations'
184
+					)
185
+				)
186
+			),
187
+			'Event_Meta' => array(
188
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
189
+					'EVTM_ID',
190
+					esc_html__('Event Meta Row ID', 'event_espresso'),
191
+					false
192
+				),
193
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
194
+					'EVT_ID',
195
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
196
+					false
197
+				),
198
+				'VNU_ID' => new EE_Foreign_Key_Int_Field(
199
+					'VNU_ID',
200
+					__('Venue ID', 'event_espresso'),
201
+					false,
202
+					0,
203
+					'Venue'
204
+				),
205
+				'EVT_display_desc'                => new EE_Boolean_Field(
206
+					'EVT_display_desc',
207
+					esc_html__('Display Description Flag', 'event_espresso'),
208
+					false,
209
+					true
210
+				),
211
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
212
+					'EVT_display_ticket_selector',
213
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
214
+					false,
215
+					true
216
+				),
217
+				'EVT_visible_on'                  => new EE_Datetime_Field(
218
+					'EVT_visible_on',
219
+					esc_html__('Event Visible Date', 'event_espresso'),
220
+					true,
221
+					EE_Datetime_Field::now
222
+				),
223
+				'EVT_additional_limit'            => new EE_Integer_Field(
224
+					'EVT_additional_limit',
225
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
226
+					true,
227
+					self::$_default_additional_limit
228
+				),
229
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
230
+					'EVT_default_registration_status',
231
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
232
+					false,
233
+					EEM_Event::$_default_reg_status,
234
+					EEM_Registration::reg_status_array()
235
+				),
236
+				'EVT_member_only'                 => new EE_Boolean_Field(
237
+					'EVT_member_only',
238
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
239
+					false,
240
+					false
241
+				),
242
+				'EVT_phone'                       => new EE_Plain_Text_Field(
243
+					'EVT_phone',
244
+					esc_html__('Event Phone Number', 'event_espresso'),
245
+					false,
246
+					''
247
+				),
248
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
249
+					'EVT_allow_overflow',
250
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
251
+					false,
252
+					false
253
+				),
254
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
255
+					'EVT_timezone_string',
256
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
257
+					false,
258
+					''
259
+				),
260
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
261
+					'EVT_external_URL',
262
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
263
+					true
264
+				),
265
+				'EVT_donations'                   => new EE_Boolean_Field(
266
+					'EVT_donations',
267
+					esc_html__('Accept Donations?', 'event_espresso'),
268
+					false,
269
+					false
270
+				),
271
+				'FSC_UUID'                        => new EE_Foreign_Key_String_Field(
272
+					'FSC_UUID',
273
+					esc_html__('Registration Form UUID (universally unique identifier)', 'event_espresso'),
274
+					true,
275
+					null,
276
+					'Form_Section',
277
+					false
278
+				),
279
+			),
280
+		);
281
+		$this->_model_relations = array(
282
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
283
+			'Datetime'               => new EE_Has_Many_Relation(),
284
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
285
+			'Form_Section'           => new EE_Belongs_To_Relation(),
286
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
287
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
288
+			'Registration'           => new EE_Has_Many_Relation(),
289
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
290
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
291
+			'Venue'                  => new EE_Belongs_To_Relation(),
292
+			'WP_User'                => new EE_Belongs_To_Relation(),
293
+		);
294
+		// this model is generally available for reading
295
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
296
+		$this->model_chain_to_password = '';
297
+		parent::__construct($timezone);
298
+	}
299
+
300
+
301
+	/**
302
+	 * @param string $default_reg_status
303
+	 * @throws EE_Error
304
+	 * @throws EE_Error
305
+	 */
306
+	public static function set_default_reg_status($default_reg_status)
307
+	{
308
+		self::$_default_reg_status = $default_reg_status;
309
+		// if EEM_Event has already been instantiated,
310
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
311
+		if (self::$_instance instanceof EEM_Event) {
312
+			$default_reg_status = new EE_Enum_Text_Field(
313
+				'EVT_default_registration_status',
314
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
315
+				false,
316
+				$default_reg_status,
317
+				EEM_Registration::reg_status_array()
318
+			);
319
+			$default_reg_status->_construct_finalize(
320
+				'Event_Meta',
321
+				'EVT_default_registration_status',
322
+				'EEM_Event'
323
+			);
324
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
325
+		}
326
+	}
327
+
328
+
329
+	/**
330
+	 * Used to override the default for the additional limit field.
331
+	 * @param $additional_limit
332
+	 */
333
+	public static function set_default_additional_limit($additional_limit)
334
+	{
335
+		self::$_default_additional_limit = (int) $additional_limit;
336
+		if (self::$_instance instanceof EEM_Event) {
337
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
338
+				'EVT_additional_limit',
339
+				__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
340
+				true,
341
+				self::$_default_additional_limit
342
+			);
343
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
344
+				'Event_Meta',
345
+				'EVT_additional_limit',
346
+				'EEM_Event'
347
+			);
348
+		}
349
+	}
350
+
351
+
352
+	/**
353
+	 * Return what is currently set as the default additional limit for the event.
354
+	 * @return int
355
+	 */
356
+	public static function get_default_additional_limit()
357
+	{
358
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
359
+	}
360
+
361
+
362
+	/**
363
+	 * get_question_groups
364
+	 *
365
+	 * @return array
366
+	 * @throws EE_Error
367
+	 * @throws ReflectionException
368
+	 */
369
+	public function get_all_question_groups()
370
+	{
371
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
372
+			array(
373
+				array('QSG_deleted' => false),
374
+				'order_by' => array('QSG_order' => 'ASC'),
375
+			)
376
+		);
377
+	}
378
+
379
+
380
+	/**
381
+	 * get_question_groups
382
+	 *
383
+	 * @param int $EVT_ID
384
+	 * @return array|bool
385
+	 * @throws EE_Error
386
+	 * @throws ReflectionException
387
+	 */
388
+	public function get_all_event_question_groups($EVT_ID = 0)
389
+	{
390
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
391
+			EE_Error::add_error(
392
+				esc_html__(
393
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
394
+					'event_espresso'
395
+				),
396
+				__FILE__,
397
+				__FUNCTION__,
398
+				__LINE__
399
+			);
400
+			return false;
401
+		}
402
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
403
+			array(
404
+				array('EVT_ID' => $EVT_ID),
405
+			)
406
+		);
407
+	}
408
+
409
+
410
+	/**
411
+	 * get_question_groups
412
+	 *
413
+	 * @param int $EVT_ID
414
+	 * @param boolean $for_primary_attendee
415
+	 * @return array|bool
416
+	 * @throws EE_Error
417
+	 * @throws InvalidArgumentException
418
+	 * @throws ReflectionException
419
+	 * @throws InvalidDataTypeException
420
+	 * @throws InvalidInterfaceException
421
+	 */
422
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
423
+	{
424
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
425
+			EE_Error::add_error(
426
+				esc_html__(
427
+					// @codingStandardsIgnoreStart
428
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
429
+					// @codingStandardsIgnoreEnd
430
+					'event_espresso'
431
+				),
432
+				__FILE__,
433
+				__FUNCTION__,
434
+				__LINE__
435
+			);
436
+			return false;
437
+		}
438
+		$query_params = [
439
+			[
440
+				'EVT_ID' => $EVT_ID,
441
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
442
+			]
443
+		];
444
+		if ($for_primary_attendee) {
445
+			$query_params[0]['EQG_primary'] = true;
446
+		} else {
447
+			$query_params[0]['EQG_additional'] = true;
448
+		}
449
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
450
+	}
451
+
452
+
453
+	/**
454
+	 * get_question_groups
455
+	 *
456
+	 * @param int $EVT_ID
457
+	 * @param EE_Registration $registration
458
+	 * @return array|bool
459
+	 * @throws EE_Error
460
+	 * @throws InvalidArgumentException
461
+	 * @throws InvalidDataTypeException
462
+	 * @throws InvalidInterfaceException
463
+	 * @throws ReflectionException
464
+	 */
465
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
466
+	{
467
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
468
+			EE_Error::add_error(
469
+				esc_html__(
470
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
471
+					'event_espresso'
472
+				),
473
+				__FILE__,
474
+				__FUNCTION__,
475
+				__LINE__
476
+			);
477
+			return false;
478
+		}
479
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
480
+			[
481
+				[
482
+					'Event_Question_Group.EVT_ID'      => $EVT_ID,
483
+					'Event_Question_Group.'
484
+						. EEM_Event_Question_Group::instance()->fieldNameForContext(
485
+							$registration->is_primary_registrant()
486
+						) => true
487
+				],
488
+				'order_by' => ['QSG_order' => 'ASC'],
489
+			]
490
+		);
491
+	}
492
+
493
+
494
+	/**
495
+	 * get_question_target_db_column
496
+	 *
497
+	 * @param string $QSG_IDs csv list of $QSG IDs
498
+	 * @return array|bool
499
+	 * @throws EE_Error
500
+	 * @throws ReflectionException
501
+	 */
502
+	public function get_questions_in_groups($QSG_IDs = '')
503
+	{
504
+		if (empty($QSG_IDs)) {
505
+			EE_Error::add_error(
506
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
507
+				__FILE__,
508
+				__FUNCTION__,
509
+				__LINE__
510
+			);
511
+			return false;
512
+		}
513
+		return EE_Registry::instance()->load_model('Question')->get_all(
514
+			array(
515
+				array(
516
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
517
+					'QST_deleted'           => false,
518
+					'QST_admin_only'        => is_admin(),
519
+				),
520
+				'order_by' => 'QST_order',
521
+			)
522
+		);
523
+	}
524
+
525
+
526
+	/**
527
+	 * get_options_for_question
528
+	 *
529
+	 * @param string $QST_IDs csv list of $QST IDs
530
+	 * @return array|bool
531
+	 * @throws EE_Error
532
+	 * @throws ReflectionException
533
+	 */
534
+	public function get_options_for_question($QST_IDs)
535
+	{
536
+		if (empty($QST_IDs)) {
537
+			EE_Error::add_error(
538
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
539
+				__FILE__,
540
+				__FUNCTION__,
541
+				__LINE__
542
+			);
543
+			return false;
544
+		}
545
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
546
+			array(
547
+				array(
548
+					'Question.QST_ID' => array('IN', $QST_IDs),
549
+					'QSO_deleted'     => false,
550
+				),
551
+				'order_by' => 'QSO_ID',
552
+			)
553
+		);
554
+	}
555
+
556
+
557
+	/**
558
+	 * Gets all events that are published
559
+	 * and have event start time earlier than now and an event end time later than now
560
+	 *
561
+	 * @param array $query_params  An array of query params to further filter on
562
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
563
+	 * @param bool  $count         whether to return the count or not (default FALSE)
564
+	 * @return EE_Event[]|int
565
+	 * @throws EE_Error
566
+	 * @throws ReflectionException
567
+	 */
568
+	public function get_active_events($query_params, $count = false)
569
+	{
570
+		if (array_key_exists(0, $query_params)) {
571
+			$where_params = $query_params[0];
572
+			unset($query_params[0]);
573
+		} else {
574
+			$where_params = array();
575
+		}
576
+		// if we have count make sure we don't include group by
577
+		if ($count && isset($query_params['group_by'])) {
578
+			unset($query_params['group_by']);
579
+		}
580
+		// let's add specific query_params for active_events
581
+		// keep in mind this will override any sent status in the query AND any date queries.
582
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
583
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
584
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
585
+			$where_params['Datetime.DTT_EVT_start******'] = array(
586
+				'<',
587
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
588
+			);
589
+		} else {
590
+			$where_params['Datetime.DTT_EVT_start'] = array(
591
+				'<',
592
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
593
+			);
594
+		}
595
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
596
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
597
+				'>',
598
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
599
+			);
600
+		} else {
601
+			$where_params['Datetime.DTT_EVT_end'] = array(
602
+				'>',
603
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
604
+			);
605
+		}
606
+		$query_params[0] = $where_params;
607
+		// don't use $query_params with count()
608
+		// because we don't want to include additional query clauses like "GROUP BY"
609
+		return $count
610
+			? $this->count(array($where_params), 'EVT_ID', true)
611
+			: $this->get_all($query_params);
612
+	}
613
+
614
+
615
+	/**
616
+	 * get all events that are published and have an event start time later than now
617
+	 *
618
+	 * @param array $query_params  An array of query params to further filter on
619
+	 *                             (Note that status and DTT_EVT_start will be overridden)
620
+	 * @param bool  $count         whether to return the count or not (default FALSE)
621
+	 * @return EE_Event[]|int
622
+	 * @throws EE_Error
623
+	 * @throws ReflectionException
624
+	 */
625
+	public function get_upcoming_events($query_params, $count = false)
626
+	{
627
+		if (array_key_exists(0, $query_params)) {
628
+			$where_params = $query_params[0];
629
+			unset($query_params[0]);
630
+		} else {
631
+			$where_params = array();
632
+		}
633
+		// if we have count make sure we don't include group by
634
+		if ($count && isset($query_params['group_by'])) {
635
+			unset($query_params['group_by']);
636
+		}
637
+		// let's add specific query_params for active_events
638
+		// keep in mind this will override any sent status in the query AND any date queries.
639
+		// we need to pull events with a status of publish and sold_out
640
+		$event_status = array('publish', EEM_Event::sold_out);
641
+		// check if the user can read private events and if so add the 'private status to the were params'
642
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
643
+			$event_status[] = 'private';
644
+		}
645
+		$where_params['status'] = array('IN', $event_status);
646
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
647
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
648
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
649
+				'>',
650
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
651
+			);
652
+		} else {
653
+			$where_params['Datetime.DTT_EVT_start'] = array(
654
+				'>',
655
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
656
+			);
657
+		}
658
+		$query_params[0] = $where_params;
659
+		// don't use $query_params with count()
660
+		// because we don't want to include additional query clauses like "GROUP BY"
661
+		return $count
662
+			? $this->count(array($where_params), 'EVT_ID', true)
663
+			: $this->get_all($query_params);
664
+	}
665
+
666
+
667
+	/**
668
+	 * Gets all events that are published
669
+	 * and have an event end time later than now
670
+	 *
671
+	 * @param array $query_params  An array of query params to further filter on
672
+	 *                             (note that status and DTT_EVT_end will be overridden)
673
+	 * @param bool  $count         whether to return the count or not (default FALSE)
674
+	 * @return EE_Event[]|int
675
+	 * @throws EE_Error
676
+	 * @throws ReflectionException
677
+	 */
678
+	public function get_active_and_upcoming_events($query_params, $count = false)
679
+	{
680
+		if (array_key_exists(0, $query_params)) {
681
+			$where_params = $query_params[0];
682
+			unset($query_params[0]);
683
+		} else {
684
+			$where_params = array();
685
+		}
686
+		// if we have count make sure we don't include group by
687
+		if ($count && isset($query_params['group_by'])) {
688
+			unset($query_params['group_by']);
689
+		}
690
+		// let's add specific query_params for active_events
691
+		// keep in mind this will override any sent status in the query AND any date queries.
692
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
693
+		// add where params for DTT_EVT_end
694
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
695
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
696
+				'>',
697
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
698
+			);
699
+		} else {
700
+			$where_params['Datetime.DTT_EVT_end'] = array(
701
+				'>',
702
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
703
+			);
704
+		}
705
+		$query_params[0] = $where_params;
706
+		// don't use $query_params with count()
707
+		// because we don't want to include additional query clauses like "GROUP BY"
708
+		return $count
709
+			? $this->count(array($where_params), 'EVT_ID', true)
710
+			: $this->get_all($query_params);
711
+	}
712
+
713
+
714
+	/**
715
+	 * This only returns events that are expired.
716
+	 * They may still be published but all their datetimes have expired.
717
+	 *
718
+	 * @param array $query_params  An array of query params to further filter on
719
+	 *                             (note that status and DTT_EVT_end will be overridden)
720
+	 * @param bool  $count         whether to return the count or not (default FALSE)
721
+	 * @return EE_Event[]|int
722
+	 * @throws EE_Error
723
+	 * @throws ReflectionException
724
+	 */
725
+	public function get_expired_events($query_params, $count = false)
726
+	{
727
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
728
+		// if we have count make sure we don't include group by
729
+		if ($count && isset($query_params['group_by'])) {
730
+			unset($query_params['group_by']);
731
+		}
732
+		// let's add specific query_params for active_events
733
+		// keep in mind this will override any sent status in the query AND any date queries.
734
+		if (isset($where_params['status'])) {
735
+			unset($where_params['status']);
736
+		}
737
+		$exclude_query = $query_params;
738
+		if (isset($exclude_query[0])) {
739
+			unset($exclude_query[0]);
740
+		}
741
+		$exclude_query[0] = array(
742
+			'Datetime.DTT_EVT_end' => array(
743
+				'>',
744
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
745
+			),
746
+		);
747
+		// first get all events that have datetimes where its not expired.
748
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
749
+		$event_ids = array_keys($event_ids);
750
+		// if we have any additional query_params, let's add them to the 'AND' condition
751
+		$and_condition = array(
752
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
753
+			'EVT_ID'               => array('NOT IN', $event_ids),
754
+		);
755
+		if (isset($where_params['OR'])) {
756
+			$and_condition['OR'] = $where_params['OR'];
757
+			unset($where_params['OR']);
758
+		}
759
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
760
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
761
+			unset($where_params['Datetime.DTT_EVT_end']);
762
+		}
763
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
764
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
765
+			unset($where_params['Datetime.DTT_EVT_start']);
766
+		}
767
+		// merge remaining $where params with the and conditions.
768
+		$where_params['AND'] = array_merge($and_condition, $where_params);
769
+		$query_params[0] = $where_params;
770
+		// don't use $query_params with count()
771
+		// because we don't want to include additional query clauses like "GROUP BY"
772
+		return $count
773
+			? $this->count(array($where_params), 'EVT_ID', true)
774
+			: $this->get_all($query_params);
775
+	}
776
+
777
+
778
+
779
+	/**
780
+	 * This basically just returns the events that do not have the publish status.
781
+	 *
782
+	 * @param  array   $query_params An array of query params to further filter on
783
+	 *                               (note that status will be overwritten)
784
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
785
+	 * @return EE_Event[]|int
786
+	 * @throws EE_Error
787
+	 */
788
+	public function get_inactive_events($query_params, $count = false)
789
+	{
790
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
791
+		// let's add in specific query_params for inactive events.
792
+		if (isset($where_params['status'])) {
793
+			unset($where_params['status']);
794
+		}
795
+		// if we have count make sure we don't include group by
796
+		if ($count && isset($query_params['group_by'])) {
797
+			unset($query_params['group_by']);
798
+		}
799
+		// if we have any additional query_params, let's add them to the 'AND' condition
800
+		$where_params['AND']['status'] = array('!=', 'publish');
801
+		if (isset($where_params['OR'])) {
802
+			$where_params['AND']['OR'] = $where_params['OR'];
803
+			unset($where_params['OR']);
804
+		}
805
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
806
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
807
+			unset($where_params['Datetime.DTT_EVT_end']);
808
+		}
809
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
810
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
811
+			unset($where_params['Datetime.DTT_EVT_start']);
812
+		}
813
+		$query_params[0] = $where_params;
814
+		// don't use $query_params with count()
815
+		// because we don't want to include additional query clauses like "GROUP BY"
816
+		return $count
817
+			? $this->count(array($where_params), 'EVT_ID', true)
818
+			: $this->get_all($query_params);
819
+	}
820
+
821
+
822
+	/**
823
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
824
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
825
+	 * attached to the event. See parent for param descriptions
826
+	 *
827
+	 * @param        $id_or_obj
828
+	 * @param        $other_model_id_or_obj
829
+	 * @param string $relationName
830
+	 * @param array  $where_query
831
+	 * @return EE_Base_Class
832
+	 * @throws EE_Error
833
+	 * @throws ReflectionException
834
+	 */
835
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
836
+	{
837
+		if ($relationName === 'Price') {
838
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
839
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
840
+			// if EVT_ID = 0, then this is a default
841
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
842
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
843
+				$prc_chk->set('PRC_ID', 0);
844
+			}
845
+			// run parent
846
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
847
+		}
848
+		// otherwise carry on as normal
849
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
850
+	}
851
+
852
+
853
+
854
+	/******************** DEPRECATED METHODS ********************/
855
+
856
+
857
+	/**
858
+	 * _get_question_target_db_column
859
+	 *
860
+	 * @param EE_Registration $registration    (so existing answers for registration are included)
861
+	 * @param int             $EVT_ID          so all question groups are included for event (not just answers from
862
+	 *                                         registration).
863
+	 * @return    array
864
+	 * @throws ReflectionException
865
+	 * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
866
+	 *                                         EE_Registration_Custom_Questions_Form located in
867
+	 *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
868
+	 * @access     public
869
+	 */
870
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
871
+	{
872
+		if (empty($EVT_ID)) {
873
+			throw new EE_Error(__(
874
+				'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
875
+				'event_espresso'
876
+			));
877
+		}
878
+		$questions = array();
879
+		// get all question groups for event
880
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
881
+		if (! empty($qgs)) {
882
+			foreach ($qgs as $qg) {
883
+				$qsts = $qg->questions();
884
+				$questions[ $qg->ID() ] = $qg->model_field_array();
885
+				$questions[ $qg->ID() ]['QSG_questions'] = array();
886
+				foreach ($qsts as $qst) {
887
+					if ($qst->is_system_question()) {
888
+						continue;
889
+					}
890
+					$answer = EEM_Answer::instance()->get_one(array(
891
+						array(
892
+							'QST_ID' => $qst->ID(),
893
+							'REG_ID' => $registration->ID(),
894
+						),
895
+					));
896
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
897
+					$qst_name = $qstn_id = $qst->ID();
898
+					$ans_id = $answer->ID();
899
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
900
+					$input_name = '';
901
+					$input_id = sanitize_key($qst->display_text());
902
+					$input_class = '';
903
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
904
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
905
+																						   . $input_name
906
+																						   . $qst_name;
907
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
908
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
909
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
910
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
911
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
912
+					// leave responses as-is, don't convert stuff into html entities please!
913
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
914
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
915
+						$QSOs = $qst->options(true, $answer->value());
916
+						if (is_array($QSOs)) {
917
+							foreach ($QSOs as $QSO_ID => $QSO) {
918
+								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
919
+							}
920
+						}
921
+					}
922
+				}
923
+			}
924
+		}
925
+		return $questions;
926
+	}
927
+
928
+
929
+	/**
930
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
931
+	 *                             or an stdClass where each property is the name of a column,
932
+	 * @return EE_Base_Class
933
+	 * @throws EE_Error
934
+	 */
935
+	public function instantiate_class_from_array_or_object($cols_n_values)
936
+	{
937
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
938
+		if ($classInstance instanceof EE_Event) {
939
+			// events have their timezone defined in the DB, so use it immediately
940
+			$this->set_timezone($classInstance->get_timezone());
941
+		}
942
+		return $classInstance;
943
+	}
944 944
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Event_Query.helper.php 2 patches
Indentation   +671 added lines, -671 removed lines patch added patch discarded remove patch
@@ -15,675 +15,675 @@
 block discarded – undo
15 15
 class EEH_Event_Query
16 16
 {
17 17
 
18
-    /**
19
-     * Start Date
20
-     *
21
-     * @var $_event_query_month
22
-     */
23
-    protected static $_event_query_month;
24
-
25
-    /**
26
-     * Category
27
-     *
28
-     * @var $_event_query_category
29
-     */
30
-    protected static $_event_query_category;
31
-
32
-    /**
33
-     * whether to display expired events in the event list
34
-     *
35
-     * @var bool $_show_expired
36
-     */
37
-    protected static $_event_query_show_expired = false;
38
-
39
-    /**
40
-     * list of params for controlling how the query results are ordered
41
-     *
42
-     * @var array $_event_query_orderby
43
-     */
44
-    protected static $_event_query_orderby = array();
45
-
46
-    /**
47
-     * direction list is sorted
48
-     *
49
-     * @var string $_event_query_sort
50
-     */
51
-    protected static $_event_query_sort;
52
-
53
-    /**
54
-     * list of params used to build the query's various clauses
55
-     *
56
-     * @var $_query_params
57
-     */
58
-    protected static $_query_params = array();
59
-
60
-
61
-
62
-    /**
63
-     * @return void
64
-     */
65
-    public static function add_query_filters()
66
-    {
67
-        // add query filters
68
-        add_action('pre_get_posts', array('EEH_Event_Query', 'filter_query_parts'), 10, 1);
69
-    }
70
-
71
-
72
-
73
-    /**
74
-     * @param WP_Query $WP_Query
75
-     * @return bool
76
-     */
77
-    public static function apply_query_filters(WP_Query $WP_Query)
78
-    {
79
-        return (
80
-                   isset($WP_Query->query['post_type'])
81
-                   && $WP_Query->query['post_type'] === 'espresso_events'
82
-               )
83
-               || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
84
-    }
85
-
86
-
87
-    /**
88
-     * @param WP_Query $WP_Query
89
-     */
90
-    public static function filter_query_parts(WP_Query $WP_Query)
91
-    {
92
-        // ONLY add our filters if this isn't the main wp_query,
93
-        // because if this is the main wp_query we already have
94
-        // our cpt strategies take care of adding things in.
95
-        if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
96
-            // build event list query
97
-            add_filter('posts_fields', array('EEH_Event_Query', 'posts_fields'), 10, 2);
98
-            add_filter('posts_join', array('EEH_Event_Query', 'posts_join'), 10, 2);
99
-            add_filter('posts_where', array('EEH_Event_Query', 'posts_where'), 10, 2);
100
-            add_filter('posts_orderby', array('EEH_Event_Query', 'posts_orderby'), 10, 2);
101
-            add_filter('posts_clauses_request', array('EEH_Event_Query', 'posts_clauses'), 10, 2);
102
-        }
103
-    }
104
-
105
-
106
-
107
-    /**
108
-     * @param string $month
109
-     * @param string $category
110
-     * @param bool   $show_expired
111
-     * @param string $orderby
112
-     * @param string $sort
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     */
117
-    public static function set_query_params(
118
-        $month = '',
119
-        $category = '',
120
-        $show_expired = false,
121
-        $orderby = 'start_date',
122
-        $sort = 'ASC'
123
-    ) {
124
-        self::$_query_params                        = array();
125
-        EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
126
-        EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
127
-        EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
128
-        EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
129
-        EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
130
-    }
131
-
132
-
133
-
134
-    /**
135
-     * what month should the event list display events for?
136
-     *
137
-     * @param string $month
138
-     * @return string
139
-     * @throws InvalidArgumentException
140
-     * @throws InvalidDataTypeException
141
-     * @throws InvalidInterfaceException
142
-     */
143
-    private static function _display_month($month = '')
144
-    {
145
-        return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_month', $month));
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     * @param string $category
152
-     * @return string
153
-     * @throws InvalidArgumentException
154
-     * @throws InvalidDataTypeException
155
-     * @throws InvalidInterfaceException
156
-     */
157
-    private static function _event_category_slug($category = '')
158
-    {
159
-        return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_category', $category));
160
-    }
161
-
162
-
163
-
164
-    /**
165
-     * @param bool $show_expired
166
-     * @return bool
167
-     * @throws InvalidArgumentException
168
-     * @throws InvalidDataTypeException
169
-     * @throws InvalidInterfaceException
170
-     */
171
-    private static function _show_expired($show_expired = false)
172
-    {
173
-        // override default expired option if set via filter
174
-        return filter_var(
175
-            EE_Registry::instance()->REQ->get('event_query_show_expired', $show_expired),
176
-            FILTER_VALIDATE_BOOLEAN
177
-        );
178
-    }
179
-
180
-
181
-
182
-    /**
183
-     * @param    string $orderby
184
-     * @return array
185
-     * @throws InvalidArgumentException
186
-     * @throws InvalidDataTypeException
187
-     * @throws InvalidInterfaceException
188
-     */
189
-    private static function _orderby($orderby = 'start_date')
190
-    {
191
-        $event_query_orderby = EE_Registry::instance()->REQ->get('event_query_orderby', $orderby);
192
-        $event_query_orderby = is_array($event_query_orderby)
193
-            ? $event_query_orderby
194
-            : explode(',', $event_query_orderby);
195
-        $event_query_orderby = array_map('trim', $event_query_orderby);
196
-        $event_query_orderby = array_map('sanitize_text_field', $event_query_orderby);
197
-        return $event_query_orderby;
198
-    }
199
-
200
-
201
-
202
-    /**
203
-     * @param string $sort
204
-     * @return string
205
-     * @throws InvalidArgumentException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     */
209
-    private static function _sort($sort = 'ASC')
210
-    {
211
-        $sort = EE_Registry::instance()->REQ->get('event_query_sort', $sort);
212
-        return in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
213
-            ? strtoupper($sort)
214
-            : 'ASC';
215
-    }
216
-
217
-
218
-
219
-    /**
220
-     * Filters the clauses for the WP_Query object
221
-     *
222
-     * @param array    $clauses array of clauses
223
-     * @param WP_Query $wp_query
224
-     * @return array   array of clauses
225
-     */
226
-    public static function posts_clauses($clauses, WP_Query $wp_query)
227
-    {
228
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
229
-            global $wpdb;
230
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
231
-        }
232
-        return $clauses;
233
-    }
234
-
235
-
236
-
237
-    /**
238
-     * @param string   $SQL
239
-     * @param WP_Query $wp_query
240
-     * @return string
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws InvalidDataTypeException
244
-     * @throws InvalidInterfaceException
245
-     */
246
-    public static function posts_fields($SQL, WP_Query $wp_query)
247
-    {
248
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
249
-            // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
250
-            $SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
251
-        }
252
-        return $SQL;
253
-    }
254
-
255
-
256
-
257
-    /**
258
-     * @param array $orderby_params
259
-     * @return string
260
-     * @throws EE_Error
261
-     * @throws InvalidArgumentException
262
-     * @throws InvalidDataTypeException
263
-     * @throws InvalidInterfaceException
264
-     */
265
-    public static function posts_fields_sql_for_orderby(array $orderby_params = array())
266
-    {
267
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
268
-        foreach ($orderby_params as $orderby) {
269
-            switch ($orderby) {
270
-                case 'ticket_start':
271
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
272
-                    break;
273
-                case 'ticket_end':
274
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
275
-                    break;
276
-                case 'venue_title':
277
-                    $SQL .= ', Venue.post_title AS venue_title';
278
-                    break;
279
-                case 'city':
280
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
281
-                    break;
282
-                case 'state':
283
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
284
-                    break;
285
-            }
286
-        }
287
-        return $SQL;
288
-    }
289
-
290
-
291
-
292
-    /**
293
-     * @param string   $SQL
294
-     * @param WP_Query $wp_query
295
-     * @return string
296
-     * @throws EE_Error
297
-     * @throws InvalidArgumentException
298
-     * @throws InvalidDataTypeException
299
-     * @throws InvalidInterfaceException
300
-     */
301
-    public static function posts_join($SQL = '', WP_Query $wp_query)
302
-    {
303
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
304
-            // Category
305
-            $SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
306
-            $SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
307
-            $SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
308
-        }
309
-        return $SQL;
310
-    }
311
-
312
-
313
-
314
-    /**
315
-     * @param string  $SQL
316
-     * @param boolean $show_expired if TRUE, then displayed past events
317
-     * @return string
318
-     * @throws EE_Error
319
-     * @throws InvalidArgumentException
320
-     * @throws InvalidDataTypeException
321
-     * @throws InvalidInterfaceException
322
-     */
323
-    public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
324
-    {
325
-        if (! $show_expired) {
326
-            $join = EEM_Event::instance()->table() . '.ID = ';
327
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
328
-            // don't add if this is already in the SQL
329
-            if (strpos($SQL, $join) === false) {
330
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
331
-            }
332
-        }
333
-        return $SQL;
334
-    }
335
-
336
-
337
-
338
-    /**
339
-     * @param string $SQL
340
-     * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
341
-     *                              used for anything yet
342
-     * @return string
343
-     */
344
-    public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
345
-    {
346
-        if (! empty($join_terms)) {
347
-            global $wpdb;
348
-            $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
349
-            $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
350
-            $SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
351
-        }
352
-        return $SQL;
353
-    }
354
-
355
-
356
-
357
-    /**
358
-     * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
359
-     *
360
-     * @param    string $SQL
361
-     * @param    array  $orderby_params
362
-     * @return string
363
-     * @throws EE_Error
364
-     * @throws InvalidArgumentException
365
-     * @throws InvalidDataTypeException
366
-     * @throws InvalidInterfaceException
367
-     */
368
-    public static function posts_join_for_orderby($SQL = '', array $orderby_params = array())
369
-    {
370
-        foreach ($orderby_params as $orderby) {
371
-            switch ($orderby) {
372
-                case 'ticket_start':
373
-                case 'ticket_end':
374
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime(
375
-                        $SQL,
376
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
377
-                    );
378
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
379
-                    $SQL .= ' ON (';
380
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
381
-                    $SQL .= ' = ';
382
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
383
-                    $SQL .= ' )';
384
-                    break;
385
-                case 'venue_title':
386
-                case 'city':
387
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
388
-                    break;
389
-                case 'state':
390
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
391
-                    $SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
392
-                    break;
393
-                case 'start_date':
394
-                default:
395
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
396
-                    break;
397
-            }
398
-        }
399
-        return $SQL;
400
-    }
401
-
402
-
403
-
404
-    /**
405
-     * @param string $SQL
406
-     * @param string $join
407
-     * @return string
408
-     * @throws EE_Error
409
-     * @throws InvalidArgumentException
410
-     * @throws InvalidDataTypeException
411
-     * @throws InvalidInterfaceException
412
-     */
413
-    protected static function _posts_join_for_datetime($SQL = '', $join = '')
414
-    {
415
-        if (! empty($join)) {
416
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
417
-            if (strpos($SQL, $join) === false) {
418
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
419
-            }
420
-        }
421
-        return '';
422
-    }
423
-
424
-
425
-    /**
426
-     * @param string $SQL
427
-     * @return string
428
-     * @throws EE_Error
429
-     * @throws InvalidArgumentException
430
-     * @throws InvalidDataTypeException
431
-     * @throws InvalidInterfaceException
432
-     * @throws ReflectionException
433
-     */
434
-    protected static function _posts_join_for_event_venue(string $SQL = ''): string
435
-    {
436
-        // grab venue table PK name & event_meta table name
437
-        $VNU_ID = EEM_Venue::instance()->primary_key_name();
438
-        $event_meta = EEM_Event::instance()->second_table();
439
-        // generate conditions for:  Event <=> Venue  JOIN clause
440
-        $event_venue_join = "Venue.ID = $event_meta.$VNU_ID";
441
-        // don't add joins if they have already been added
442
-        if (strpos($SQL, $event_venue_join) === false) {
443
-            global $wpdb;
444
-            // grab wp_posts (event), venue, and venue_meta table names
445
-            $wp_posts = $wpdb->posts;
446
-            $venue = EEM_Venue::instance()->table();
447
-            $venue_meta = EEM_Venue::instance()->second_table();
448
-            // generate JOIN clause for: Event <=> Event Meta
449
-            $venue_SQL = " LEFT JOIN $event_meta ON ( $wp_posts.ID = $event_meta.EVT_ID )";
450
-            // generate JOIN clause for: Event Meta <=> Venue
451
-            $venue_SQL .= " LEFT JOIN $venue AS Venue ON ( $event_venue_join )";
452
-            // generate JOIN clause for: Venue <=> Venue Meta
453
-            $venue_SQL .= " LEFT JOIN $venue_meta ON ( Venue.ID = $venue_meta.$VNU_ID )";
454
-            unset($venue, $VNU_ID, $event_meta, $venue_meta, $event_venue_join);
455
-            return $venue_SQL;
456
-        }
457
-        unset($VNU_ID, $event_meta, $event_venue_join);
458
-        return '';
459
-    }
460
-
461
-
462
-
463
-    /**
464
-     * @param string $SQL
465
-     * @return string
466
-     * @throws EE_Error
467
-     * @throws InvalidArgumentException
468
-     * @throws InvalidDataTypeException
469
-     * @throws InvalidInterfaceException
470
-     */
471
-    protected static function _posts_join_for_venue_state($SQL = '')
472
-    {
473
-        // Venue Meta table name
474
-        $venue_meta_table = EEM_Venue::instance()->second_table();
475
-        // State table name
476
-        $state_table = EEM_State::instance()->table();
477
-        // State table pk
478
-        $state_table_pk = EEM_State::instance()->primary_key_name();
479
-        // verify vars
480
-        if ($venue_meta_table && $state_table && $state_table_pk) {
481
-            // like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
482
-            $join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
483
-            // don't add join if it has already been added
484
-            if (strpos($SQL, $join) === false) {
485
-                unset($state_table_pk, $venue_meta_table, $venue_table_pk);
486
-                return " LEFT JOIN $state_table ON ( $join )";
487
-            }
488
-        }
489
-        unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
490
-        return '';
491
-    }
492
-
493
-
494
-
495
-    /**
496
-     * @param string   $SQL
497
-     * @param WP_Query $wp_query
498
-     * @return string
499
-     * @throws EE_Error
500
-     * @throws InvalidArgumentException
501
-     * @throws InvalidDataTypeException
502
-     * @throws InvalidInterfaceException
503
-     */
504
-    public static function posts_where($SQL = '', WP_Query $wp_query)
505
-    {
506
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
507
-            // Show Expired ?
508
-            $SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
509
-            // Category
510
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
511
-            // Start Date
512
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
513
-        }
514
-        return $SQL;
515
-    }
516
-
517
-
518
-
519
-    /**
520
-     * @param    boolean $show_expired if TRUE, then displayed past events
521
-     * @return string
522
-     * @throws EE_Error
523
-     * @throws InvalidArgumentException
524
-     * @throws InvalidDataTypeException
525
-     * @throws InvalidInterfaceException
526
-     */
527
-    public static function posts_where_sql_for_show_expired($show_expired = false)
528
-    {
529
-        return ! $show_expired
530
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
531
-            : '';
532
-    }
533
-
534
-
535
-
536
-    /**
537
-     * @param boolean $event_category_slug
538
-     * @return string
539
-     */
540
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
541
-    {
542
-        global $wpdb;
543
-        if (! empty($event_category_slug)) {
544
-            $event_category_slugs_array = array_map('trim', explode(',', $event_category_slug));
545
-            $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
546
-            return $wpdb->prepare(" AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ", $event_category_slugs_array);
547
-        }
548
-        return '';
549
-    }
550
-
551
-
552
-
553
-    /**
554
-     * @param boolean $month
555
-     * @return string
556
-     * @throws EE_Error
557
-     * @throws InvalidArgumentException
558
-     * @throws InvalidDataTypeException
559
-     * @throws InvalidInterfaceException
560
-     */
561
-    public static function posts_where_sql_for_event_list_month($month = null)
562
-    {
563
-        $SQL = '';
564
-        if (! empty($month)) {
565
-            $datetime_table = EEM_Datetime::instance()->table();
566
-            // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
567
-            $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
568
-            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
569
-            // event end date is GREATER than the start of the month ( so nothing that ended before this month )
570
-            $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
571
-            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
572
-        }
573
-        return $SQL;
574
-    }
575
-
576
-
577
-
578
-    /**
579
-     * @param string $SQL
580
-     * @param WP_Query $wp_query
581
-     * @return string
582
-     * @throws EE_Error
583
-     * @throws InvalidArgumentException
584
-     * @throws InvalidDataTypeException
585
-     * @throws InvalidInterfaceException
586
-     */
587
-    public static function posts_orderby($SQL = '', WP_Query $wp_query)
588
-    {
589
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
590
-            $SQL = EEH_Event_Query::posts_orderby_sql(
591
-                EEH_Event_Query::$_event_query_orderby,
592
-                EEH_Event_Query::$_event_query_sort
593
-            );
594
-        }
595
-        return $SQL;
596
-    }
597
-
598
-
599
-
600
-    /**
601
-     *    posts_orderby_sql
602
-     *    possible parameters:
603
-     *    ID
604
-     *    start_date
605
-     *    end_date
606
-     *    event_name
607
-     *    category_slug
608
-     *    ticket_start
609
-     *    ticket_end
610
-     *    venue_title
611
-     *    city
612
-     *    state
613
-     *    **IMPORTANT**
614
-     *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
615
-     *    or else some of the table references below will result in MySQL errors
616
-     *
617
-     * @param array  $orderby_params
618
-     * @param string $sort
619
-     * @return string
620
-     * @throws EE_Error
621
-     * @throws InvalidArgumentException
622
-     * @throws InvalidDataTypeException
623
-     * @throws InvalidInterfaceException
624
-     */
625
-    public static function posts_orderby_sql(array $orderby_params = array(), $sort = 'ASC')
626
-    {
627
-        global $wpdb;
628
-        $SQL     = '';
629
-        $counter = 0;
630
-        $sort    = in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
631
-            ? strtoupper($sort)
632
-            : 'ASC';
633
-        // make sure 'orderby' is set in query params
634
-        if (! isset(self::$_query_params['orderby'])) {
635
-            self::$_query_params['orderby'] = array();
636
-        }
637
-        // loop thru $orderby_params (type cast as array)
638
-        foreach ($orderby_params as $orderby) {
639
-            // check if we have already added this param
640
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
641
-                // if so then remove from the $orderby_params so that the count() method below is accurate
642
-                unset($orderby_params[ $orderby ]);
643
-                // then bump ahead to the next param
644
-                continue;
645
-            }
646
-            // this will ad a comma depending on whether this is the first or last param
647
-            $glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
648
-            // ok what's we dealing with?
649
-            switch ($orderby) {
650
-                case 'id':
651
-                case 'ID':
652
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
653
-                    break;
654
-                case 'end_date':
655
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
656
-                    break;
657
-                case 'event_name':
658
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
659
-                    break;
660
-                case 'category_slug':
661
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
662
-                    break;
663
-                case 'ticket_start':
664
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
665
-                    break;
666
-                case 'ticket_end':
667
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
668
-                    break;
669
-                case 'venue_title':
670
-                    $SQL .= $glue . 'venue_title ' . $sort;
671
-                    break;
672
-                case 'city':
673
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
674
-                    break;
675
-                case 'state':
676
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
677
-                    break;
678
-                case 'start_date':
679
-                default:
680
-                    $SQL .= $glue . ' event_start_date ' . $sort;
681
-                    break;
682
-            }
683
-            // add to array of orderby params that have been added
684
-            self::$_query_params['orderby'][ $orderby ] = true;
685
-            $counter++;
686
-        }
687
-        return $SQL;
688
-    }
18
+	/**
19
+	 * Start Date
20
+	 *
21
+	 * @var $_event_query_month
22
+	 */
23
+	protected static $_event_query_month;
24
+
25
+	/**
26
+	 * Category
27
+	 *
28
+	 * @var $_event_query_category
29
+	 */
30
+	protected static $_event_query_category;
31
+
32
+	/**
33
+	 * whether to display expired events in the event list
34
+	 *
35
+	 * @var bool $_show_expired
36
+	 */
37
+	protected static $_event_query_show_expired = false;
38
+
39
+	/**
40
+	 * list of params for controlling how the query results are ordered
41
+	 *
42
+	 * @var array $_event_query_orderby
43
+	 */
44
+	protected static $_event_query_orderby = array();
45
+
46
+	/**
47
+	 * direction list is sorted
48
+	 *
49
+	 * @var string $_event_query_sort
50
+	 */
51
+	protected static $_event_query_sort;
52
+
53
+	/**
54
+	 * list of params used to build the query's various clauses
55
+	 *
56
+	 * @var $_query_params
57
+	 */
58
+	protected static $_query_params = array();
59
+
60
+
61
+
62
+	/**
63
+	 * @return void
64
+	 */
65
+	public static function add_query_filters()
66
+	{
67
+		// add query filters
68
+		add_action('pre_get_posts', array('EEH_Event_Query', 'filter_query_parts'), 10, 1);
69
+	}
70
+
71
+
72
+
73
+	/**
74
+	 * @param WP_Query $WP_Query
75
+	 * @return bool
76
+	 */
77
+	public static function apply_query_filters(WP_Query $WP_Query)
78
+	{
79
+		return (
80
+				   isset($WP_Query->query['post_type'])
81
+				   && $WP_Query->query['post_type'] === 'espresso_events'
82
+			   )
83
+			   || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param WP_Query $WP_Query
89
+	 */
90
+	public static function filter_query_parts(WP_Query $WP_Query)
91
+	{
92
+		// ONLY add our filters if this isn't the main wp_query,
93
+		// because if this is the main wp_query we already have
94
+		// our cpt strategies take care of adding things in.
95
+		if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
96
+			// build event list query
97
+			add_filter('posts_fields', array('EEH_Event_Query', 'posts_fields'), 10, 2);
98
+			add_filter('posts_join', array('EEH_Event_Query', 'posts_join'), 10, 2);
99
+			add_filter('posts_where', array('EEH_Event_Query', 'posts_where'), 10, 2);
100
+			add_filter('posts_orderby', array('EEH_Event_Query', 'posts_orderby'), 10, 2);
101
+			add_filter('posts_clauses_request', array('EEH_Event_Query', 'posts_clauses'), 10, 2);
102
+		}
103
+	}
104
+
105
+
106
+
107
+	/**
108
+	 * @param string $month
109
+	 * @param string $category
110
+	 * @param bool   $show_expired
111
+	 * @param string $orderby
112
+	 * @param string $sort
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 */
117
+	public static function set_query_params(
118
+		$month = '',
119
+		$category = '',
120
+		$show_expired = false,
121
+		$orderby = 'start_date',
122
+		$sort = 'ASC'
123
+	) {
124
+		self::$_query_params                        = array();
125
+		EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
126
+		EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
127
+		EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
128
+		EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
129
+		EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
130
+	}
131
+
132
+
133
+
134
+	/**
135
+	 * what month should the event list display events for?
136
+	 *
137
+	 * @param string $month
138
+	 * @return string
139
+	 * @throws InvalidArgumentException
140
+	 * @throws InvalidDataTypeException
141
+	 * @throws InvalidInterfaceException
142
+	 */
143
+	private static function _display_month($month = '')
144
+	{
145
+		return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_month', $month));
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 * @param string $category
152
+	 * @return string
153
+	 * @throws InvalidArgumentException
154
+	 * @throws InvalidDataTypeException
155
+	 * @throws InvalidInterfaceException
156
+	 */
157
+	private static function _event_category_slug($category = '')
158
+	{
159
+		return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_category', $category));
160
+	}
161
+
162
+
163
+
164
+	/**
165
+	 * @param bool $show_expired
166
+	 * @return bool
167
+	 * @throws InvalidArgumentException
168
+	 * @throws InvalidDataTypeException
169
+	 * @throws InvalidInterfaceException
170
+	 */
171
+	private static function _show_expired($show_expired = false)
172
+	{
173
+		// override default expired option if set via filter
174
+		return filter_var(
175
+			EE_Registry::instance()->REQ->get('event_query_show_expired', $show_expired),
176
+			FILTER_VALIDATE_BOOLEAN
177
+		);
178
+	}
179
+
180
+
181
+
182
+	/**
183
+	 * @param    string $orderby
184
+	 * @return array
185
+	 * @throws InvalidArgumentException
186
+	 * @throws InvalidDataTypeException
187
+	 * @throws InvalidInterfaceException
188
+	 */
189
+	private static function _orderby($orderby = 'start_date')
190
+	{
191
+		$event_query_orderby = EE_Registry::instance()->REQ->get('event_query_orderby', $orderby);
192
+		$event_query_orderby = is_array($event_query_orderby)
193
+			? $event_query_orderby
194
+			: explode(',', $event_query_orderby);
195
+		$event_query_orderby = array_map('trim', $event_query_orderby);
196
+		$event_query_orderby = array_map('sanitize_text_field', $event_query_orderby);
197
+		return $event_query_orderby;
198
+	}
199
+
200
+
201
+
202
+	/**
203
+	 * @param string $sort
204
+	 * @return string
205
+	 * @throws InvalidArgumentException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 */
209
+	private static function _sort($sort = 'ASC')
210
+	{
211
+		$sort = EE_Registry::instance()->REQ->get('event_query_sort', $sort);
212
+		return in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
213
+			? strtoupper($sort)
214
+			: 'ASC';
215
+	}
216
+
217
+
218
+
219
+	/**
220
+	 * Filters the clauses for the WP_Query object
221
+	 *
222
+	 * @param array    $clauses array of clauses
223
+	 * @param WP_Query $wp_query
224
+	 * @return array   array of clauses
225
+	 */
226
+	public static function posts_clauses($clauses, WP_Query $wp_query)
227
+	{
228
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
229
+			global $wpdb;
230
+			$clauses['groupby'] = $wpdb->posts . '.ID ';
231
+		}
232
+		return $clauses;
233
+	}
234
+
235
+
236
+
237
+	/**
238
+	 * @param string   $SQL
239
+	 * @param WP_Query $wp_query
240
+	 * @return string
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws InvalidDataTypeException
244
+	 * @throws InvalidInterfaceException
245
+	 */
246
+	public static function posts_fields($SQL, WP_Query $wp_query)
247
+	{
248
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
249
+			// adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
250
+			$SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
251
+		}
252
+		return $SQL;
253
+	}
254
+
255
+
256
+
257
+	/**
258
+	 * @param array $orderby_params
259
+	 * @return string
260
+	 * @throws EE_Error
261
+	 * @throws InvalidArgumentException
262
+	 * @throws InvalidDataTypeException
263
+	 * @throws InvalidInterfaceException
264
+	 */
265
+	public static function posts_fields_sql_for_orderby(array $orderby_params = array())
266
+	{
267
+		$SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
268
+		foreach ($orderby_params as $orderby) {
269
+			switch ($orderby) {
270
+				case 'ticket_start':
271
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
272
+					break;
273
+				case 'ticket_end':
274
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
275
+					break;
276
+				case 'venue_title':
277
+					$SQL .= ', Venue.post_title AS venue_title';
278
+					break;
279
+				case 'city':
280
+					$SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
281
+					break;
282
+				case 'state':
283
+					$SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
284
+					break;
285
+			}
286
+		}
287
+		return $SQL;
288
+	}
289
+
290
+
291
+
292
+	/**
293
+	 * @param string   $SQL
294
+	 * @param WP_Query $wp_query
295
+	 * @return string
296
+	 * @throws EE_Error
297
+	 * @throws InvalidArgumentException
298
+	 * @throws InvalidDataTypeException
299
+	 * @throws InvalidInterfaceException
300
+	 */
301
+	public static function posts_join($SQL = '', WP_Query $wp_query)
302
+	{
303
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
304
+			// Category
305
+			$SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
306
+			$SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
307
+			$SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
308
+		}
309
+		return $SQL;
310
+	}
311
+
312
+
313
+
314
+	/**
315
+	 * @param string  $SQL
316
+	 * @param boolean $show_expired if TRUE, then displayed past events
317
+	 * @return string
318
+	 * @throws EE_Error
319
+	 * @throws InvalidArgumentException
320
+	 * @throws InvalidDataTypeException
321
+	 * @throws InvalidInterfaceException
322
+	 */
323
+	public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
324
+	{
325
+		if (! $show_expired) {
326
+			$join = EEM_Event::instance()->table() . '.ID = ';
327
+			$join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
328
+			// don't add if this is already in the SQL
329
+			if (strpos($SQL, $join) === false) {
330
+				$SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
331
+			}
332
+		}
333
+		return $SQL;
334
+	}
335
+
336
+
337
+
338
+	/**
339
+	 * @param string $SQL
340
+	 * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
341
+	 *                              used for anything yet
342
+	 * @return string
343
+	 */
344
+	public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
345
+	{
346
+		if (! empty($join_terms)) {
347
+			global $wpdb;
348
+			$SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
349
+			$SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
350
+			$SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
351
+		}
352
+		return $SQL;
353
+	}
354
+
355
+
356
+
357
+	/**
358
+	 * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
359
+	 *
360
+	 * @param    string $SQL
361
+	 * @param    array  $orderby_params
362
+	 * @return string
363
+	 * @throws EE_Error
364
+	 * @throws InvalidArgumentException
365
+	 * @throws InvalidDataTypeException
366
+	 * @throws InvalidInterfaceException
367
+	 */
368
+	public static function posts_join_for_orderby($SQL = '', array $orderby_params = array())
369
+	{
370
+		foreach ($orderby_params as $orderby) {
371
+			switch ($orderby) {
372
+				case 'ticket_start':
373
+				case 'ticket_end':
374
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime(
375
+						$SQL,
376
+						EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
377
+					);
378
+					$SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
379
+					$SQL .= ' ON (';
380
+					$SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
381
+					$SQL .= ' = ';
382
+					$SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
383
+					$SQL .= ' )';
384
+					break;
385
+				case 'venue_title':
386
+				case 'city':
387
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
388
+					break;
389
+				case 'state':
390
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
391
+					$SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
392
+					break;
393
+				case 'start_date':
394
+				default:
395
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
396
+					break;
397
+			}
398
+		}
399
+		return $SQL;
400
+	}
401
+
402
+
403
+
404
+	/**
405
+	 * @param string $SQL
406
+	 * @param string $join
407
+	 * @return string
408
+	 * @throws EE_Error
409
+	 * @throws InvalidArgumentException
410
+	 * @throws InvalidDataTypeException
411
+	 * @throws InvalidInterfaceException
412
+	 */
413
+	protected static function _posts_join_for_datetime($SQL = '', $join = '')
414
+	{
415
+		if (! empty($join)) {
416
+			$join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
417
+			if (strpos($SQL, $join) === false) {
418
+				return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
419
+			}
420
+		}
421
+		return '';
422
+	}
423
+
424
+
425
+	/**
426
+	 * @param string $SQL
427
+	 * @return string
428
+	 * @throws EE_Error
429
+	 * @throws InvalidArgumentException
430
+	 * @throws InvalidDataTypeException
431
+	 * @throws InvalidInterfaceException
432
+	 * @throws ReflectionException
433
+	 */
434
+	protected static function _posts_join_for_event_venue(string $SQL = ''): string
435
+	{
436
+		// grab venue table PK name & event_meta table name
437
+		$VNU_ID = EEM_Venue::instance()->primary_key_name();
438
+		$event_meta = EEM_Event::instance()->second_table();
439
+		// generate conditions for:  Event <=> Venue  JOIN clause
440
+		$event_venue_join = "Venue.ID = $event_meta.$VNU_ID";
441
+		// don't add joins if they have already been added
442
+		if (strpos($SQL, $event_venue_join) === false) {
443
+			global $wpdb;
444
+			// grab wp_posts (event), venue, and venue_meta table names
445
+			$wp_posts = $wpdb->posts;
446
+			$venue = EEM_Venue::instance()->table();
447
+			$venue_meta = EEM_Venue::instance()->second_table();
448
+			// generate JOIN clause for: Event <=> Event Meta
449
+			$venue_SQL = " LEFT JOIN $event_meta ON ( $wp_posts.ID = $event_meta.EVT_ID )";
450
+			// generate JOIN clause for: Event Meta <=> Venue
451
+			$venue_SQL .= " LEFT JOIN $venue AS Venue ON ( $event_venue_join )";
452
+			// generate JOIN clause for: Venue <=> Venue Meta
453
+			$venue_SQL .= " LEFT JOIN $venue_meta ON ( Venue.ID = $venue_meta.$VNU_ID )";
454
+			unset($venue, $VNU_ID, $event_meta, $venue_meta, $event_venue_join);
455
+			return $venue_SQL;
456
+		}
457
+		unset($VNU_ID, $event_meta, $event_venue_join);
458
+		return '';
459
+	}
460
+
461
+
462
+
463
+	/**
464
+	 * @param string $SQL
465
+	 * @return string
466
+	 * @throws EE_Error
467
+	 * @throws InvalidArgumentException
468
+	 * @throws InvalidDataTypeException
469
+	 * @throws InvalidInterfaceException
470
+	 */
471
+	protected static function _posts_join_for_venue_state($SQL = '')
472
+	{
473
+		// Venue Meta table name
474
+		$venue_meta_table = EEM_Venue::instance()->second_table();
475
+		// State table name
476
+		$state_table = EEM_State::instance()->table();
477
+		// State table pk
478
+		$state_table_pk = EEM_State::instance()->primary_key_name();
479
+		// verify vars
480
+		if ($venue_meta_table && $state_table && $state_table_pk) {
481
+			// like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
482
+			$join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
483
+			// don't add join if it has already been added
484
+			if (strpos($SQL, $join) === false) {
485
+				unset($state_table_pk, $venue_meta_table, $venue_table_pk);
486
+				return " LEFT JOIN $state_table ON ( $join )";
487
+			}
488
+		}
489
+		unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
490
+		return '';
491
+	}
492
+
493
+
494
+
495
+	/**
496
+	 * @param string   $SQL
497
+	 * @param WP_Query $wp_query
498
+	 * @return string
499
+	 * @throws EE_Error
500
+	 * @throws InvalidArgumentException
501
+	 * @throws InvalidDataTypeException
502
+	 * @throws InvalidInterfaceException
503
+	 */
504
+	public static function posts_where($SQL = '', WP_Query $wp_query)
505
+	{
506
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
507
+			// Show Expired ?
508
+			$SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
509
+			// Category
510
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
511
+			// Start Date
512
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
513
+		}
514
+		return $SQL;
515
+	}
516
+
517
+
518
+
519
+	/**
520
+	 * @param    boolean $show_expired if TRUE, then displayed past events
521
+	 * @return string
522
+	 * @throws EE_Error
523
+	 * @throws InvalidArgumentException
524
+	 * @throws InvalidDataTypeException
525
+	 * @throws InvalidInterfaceException
526
+	 */
527
+	public static function posts_where_sql_for_show_expired($show_expired = false)
528
+	{
529
+		return ! $show_expired
530
+			? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
531
+			: '';
532
+	}
533
+
534
+
535
+
536
+	/**
537
+	 * @param boolean $event_category_slug
538
+	 * @return string
539
+	 */
540
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
541
+	{
542
+		global $wpdb;
543
+		if (! empty($event_category_slug)) {
544
+			$event_category_slugs_array = array_map('trim', explode(',', $event_category_slug));
545
+			$event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
546
+			return $wpdb->prepare(" AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ", $event_category_slugs_array);
547
+		}
548
+		return '';
549
+	}
550
+
551
+
552
+
553
+	/**
554
+	 * @param boolean $month
555
+	 * @return string
556
+	 * @throws EE_Error
557
+	 * @throws InvalidArgumentException
558
+	 * @throws InvalidDataTypeException
559
+	 * @throws InvalidInterfaceException
560
+	 */
561
+	public static function posts_where_sql_for_event_list_month($month = null)
562
+	{
563
+		$SQL = '';
564
+		if (! empty($month)) {
565
+			$datetime_table = EEM_Datetime::instance()->table();
566
+			// event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
567
+			$SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
568
+			$SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
569
+			// event end date is GREATER than the start of the month ( so nothing that ended before this month )
570
+			$SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
571
+			$SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
572
+		}
573
+		return $SQL;
574
+	}
575
+
576
+
577
+
578
+	/**
579
+	 * @param string $SQL
580
+	 * @param WP_Query $wp_query
581
+	 * @return string
582
+	 * @throws EE_Error
583
+	 * @throws InvalidArgumentException
584
+	 * @throws InvalidDataTypeException
585
+	 * @throws InvalidInterfaceException
586
+	 */
587
+	public static function posts_orderby($SQL = '', WP_Query $wp_query)
588
+	{
589
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
590
+			$SQL = EEH_Event_Query::posts_orderby_sql(
591
+				EEH_Event_Query::$_event_query_orderby,
592
+				EEH_Event_Query::$_event_query_sort
593
+			);
594
+		}
595
+		return $SQL;
596
+	}
597
+
598
+
599
+
600
+	/**
601
+	 *    posts_orderby_sql
602
+	 *    possible parameters:
603
+	 *    ID
604
+	 *    start_date
605
+	 *    end_date
606
+	 *    event_name
607
+	 *    category_slug
608
+	 *    ticket_start
609
+	 *    ticket_end
610
+	 *    venue_title
611
+	 *    city
612
+	 *    state
613
+	 *    **IMPORTANT**
614
+	 *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
615
+	 *    or else some of the table references below will result in MySQL errors
616
+	 *
617
+	 * @param array  $orderby_params
618
+	 * @param string $sort
619
+	 * @return string
620
+	 * @throws EE_Error
621
+	 * @throws InvalidArgumentException
622
+	 * @throws InvalidDataTypeException
623
+	 * @throws InvalidInterfaceException
624
+	 */
625
+	public static function posts_orderby_sql(array $orderby_params = array(), $sort = 'ASC')
626
+	{
627
+		global $wpdb;
628
+		$SQL     = '';
629
+		$counter = 0;
630
+		$sort    = in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
631
+			? strtoupper($sort)
632
+			: 'ASC';
633
+		// make sure 'orderby' is set in query params
634
+		if (! isset(self::$_query_params['orderby'])) {
635
+			self::$_query_params['orderby'] = array();
636
+		}
637
+		// loop thru $orderby_params (type cast as array)
638
+		foreach ($orderby_params as $orderby) {
639
+			// check if we have already added this param
640
+			if (isset(self::$_query_params['orderby'][ $orderby ])) {
641
+				// if so then remove from the $orderby_params so that the count() method below is accurate
642
+				unset($orderby_params[ $orderby ]);
643
+				// then bump ahead to the next param
644
+				continue;
645
+			}
646
+			// this will ad a comma depending on whether this is the first or last param
647
+			$glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
648
+			// ok what's we dealing with?
649
+			switch ($orderby) {
650
+				case 'id':
651
+				case 'ID':
652
+					$SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
653
+					break;
654
+				case 'end_date':
655
+					$SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
656
+					break;
657
+				case 'event_name':
658
+					$SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
659
+					break;
660
+				case 'category_slug':
661
+					$SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
662
+					break;
663
+				case 'ticket_start':
664
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
665
+					break;
666
+				case 'ticket_end':
667
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
668
+					break;
669
+				case 'venue_title':
670
+					$SQL .= $glue . 'venue_title ' . $sort;
671
+					break;
672
+				case 'city':
673
+					$SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
674
+					break;
675
+				case 'state':
676
+					$SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
677
+					break;
678
+				case 'start_date':
679
+				default:
680
+					$SQL .= $glue . ' event_start_date ' . $sort;
681
+					break;
682
+			}
683
+			// add to array of orderby params that have been added
684
+			self::$_query_params['orderby'][ $orderby ] = true;
685
+			$counter++;
686
+		}
687
+		return $SQL;
688
+	}
689 689
 }
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
     {
228 228
         if (EEH_Event_Query::apply_query_filters($wp_query)) {
229 229
             global $wpdb;
230
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
230
+            $clauses['groupby'] = $wpdb->posts.'.ID ';
231 231
         }
232 232
         return $clauses;
233 233
     }
@@ -264,23 +264,23 @@  discard block
 block discarded – undo
264 264
      */
265 265
     public static function posts_fields_sql_for_orderby(array $orderby_params = array())
266 266
     {
267
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
267
+        $SQL = ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date ';
268 268
         foreach ($orderby_params as $orderby) {
269 269
             switch ($orderby) {
270 270
                 case 'ticket_start':
271
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
271
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_start_date';
272 272
                     break;
273 273
                 case 'ticket_end':
274
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
274
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_end_date';
275 275
                     break;
276 276
                 case 'venue_title':
277 277
                     $SQL .= ', Venue.post_title AS venue_title';
278 278
                     break;
279 279
                 case 'city':
280
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
280
+                    $SQL .= ', '.EEM_Venue::instance()->second_table().'.VNU_city';
281 281
                     break;
282 282
                 case 'state':
283
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
283
+                    $SQL .= ', '.EEM_State::instance()->table().'.STA_name';
284 284
                     break;
285 285
             }
286 286
         }
@@ -322,12 +322,12 @@  discard block
 block discarded – undo
322 322
      */
323 323
     public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
324 324
     {
325
-        if (! $show_expired) {
326
-            $join = EEM_Event::instance()->table() . '.ID = ';
327
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
325
+        if ( ! $show_expired) {
326
+            $join = EEM_Event::instance()->table().'.ID = ';
327
+            $join .= EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
328 328
             // don't add if this is already in the SQL
329 329
             if (strpos($SQL, $join) === false) {
330
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
330
+                $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' ) ';
331 331
             }
332 332
         }
333 333
         return $SQL;
@@ -343,7 +343,7 @@  discard block
 block discarded – undo
343 343
      */
344 344
     public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
345 345
     {
346
-        if (! empty($join_terms)) {
346
+        if ( ! empty($join_terms)) {
347 347
             global $wpdb;
348 348
             $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
349 349
             $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
@@ -373,13 +373,13 @@  discard block
 block discarded – undo
373 373
                 case 'ticket_end':
374 374
                     $SQL .= EEH_Event_Query::_posts_join_for_datetime(
375 375
                         $SQL,
376
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
376
+                        EEM_Datetime_Ticket::instance()->table().'.'.EEM_Datetime::instance()->primary_key_name()
377 377
                     );
378
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
378
+                    $SQL .= ' LEFT JOIN '.EEM_Ticket::instance()->table();
379 379
                     $SQL .= ' ON (';
380
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
380
+                    $SQL .= EEM_Datetime_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
381 381
                     $SQL .= ' = ';
382
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
382
+                    $SQL .= EEM_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
383 383
                     $SQL .= ' )';
384 384
                     break;
385 385
                 case 'venue_title':
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
                     break;
393 393
                 case 'start_date':
394 394
                 default:
395
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
395
+                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table().'.ID');
396 396
                     break;
397 397
             }
398 398
         }
@@ -412,10 +412,10 @@  discard block
 block discarded – undo
412 412
      */
413 413
     protected static function _posts_join_for_datetime($SQL = '', $join = '')
414 414
     {
415
-        if (! empty($join)) {
416
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
415
+        if ( ! empty($join)) {
416
+            $join .= ' = '.EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
417 417
             if (strpos($SQL, $join) === false) {
418
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
418
+                return ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' )';
419 419
             }
420 420
         }
421 421
         return '';
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
     public static function posts_where_sql_for_show_expired($show_expired = false)
528 528
     {
529 529
         return ! $show_expired
530
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
530
+            ? ' AND '.EEM_Datetime::instance()->table().'.DTT_EVT_end > \''.current_time('mysql', true).'\' '
531 531
             : '';
532 532
     }
533 533
 
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
     public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
541 541
     {
542 542
         global $wpdb;
543
-        if (! empty($event_category_slug)) {
543
+        if ( ! empty($event_category_slug)) {
544 544
             $event_category_slugs_array = array_map('trim', explode(',', $event_category_slug));
545 545
             $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
546 546
             return $wpdb->prepare(" AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ", $event_category_slugs_array);
@@ -561,14 +561,14 @@  discard block
 block discarded – undo
561 561
     public static function posts_where_sql_for_event_list_month($month = null)
562 562
     {
563 563
         $SQL = '';
564
-        if (! empty($month)) {
564
+        if ( ! empty($month)) {
565 565
             $datetime_table = EEM_Datetime::instance()->table();
566 566
             // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
567 567
             $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
568
-            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
568
+            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month))."'";
569 569
             // event end date is GREATER than the start of the month ( so nothing that ended before this month )
570 570
             $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
571
-            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
571
+            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month))."' ";
572 572
         }
573 573
         return $SQL;
574 574
     }
@@ -631,15 +631,15 @@  discard block
 block discarded – undo
631 631
             ? strtoupper($sort)
632 632
             : 'ASC';
633 633
         // make sure 'orderby' is set in query params
634
-        if (! isset(self::$_query_params['orderby'])) {
634
+        if ( ! isset(self::$_query_params['orderby'])) {
635 635
             self::$_query_params['orderby'] = array();
636 636
         }
637 637
         // loop thru $orderby_params (type cast as array)
638 638
         foreach ($orderby_params as $orderby) {
639 639
             // check if we have already added this param
640
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
640
+            if (isset(self::$_query_params['orderby'][$orderby])) {
641 641
                 // if so then remove from the $orderby_params so that the count() method below is accurate
642
-                unset($orderby_params[ $orderby ]);
642
+                unset($orderby_params[$orderby]);
643 643
                 // then bump ahead to the next param
644 644
                 continue;
645 645
             }
@@ -649,39 +649,39 @@  discard block
 block discarded – undo
649 649
             switch ($orderby) {
650 650
                 case 'id':
651 651
                 case 'ID':
652
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
652
+                    $SQL .= $glue.$wpdb->posts.'.ID '.$sort;
653 653
                     break;
654 654
                 case 'end_date':
655
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
655
+                    $SQL .= $glue.EEM_Datetime::instance()->table().'.DTT_EVT_end '.$sort;
656 656
                     break;
657 657
                 case 'event_name':
658
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
658
+                    $SQL .= $glue.$wpdb->posts.'.post_title '.$sort;
659 659
                     break;
660 660
                 case 'category_slug':
661
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
661
+                    $SQL .= $glue.$wpdb->terms.'.slug '.$sort;
662 662
                     break;
663 663
                 case 'ticket_start':
664
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
664
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_start_date '.$sort;
665 665
                     break;
666 666
                 case 'ticket_end':
667
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
667
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_end_date '.$sort;
668 668
                     break;
669 669
                 case 'venue_title':
670
-                    $SQL .= $glue . 'venue_title ' . $sort;
670
+                    $SQL .= $glue.'venue_title '.$sort;
671 671
                     break;
672 672
                 case 'city':
673
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
673
+                    $SQL .= $glue.EEM_Venue::instance()->second_table().'.VNU_city '.$sort;
674 674
                     break;
675 675
                 case 'state':
676
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
676
+                    $SQL .= $glue.EEM_State::instance()->table().'.STA_name '.$sort;
677 677
                     break;
678 678
                 case 'start_date':
679 679
                 default:
680
-                    $SQL .= $glue . ' event_start_date ' . $sort;
680
+                    $SQL .= $glue.' event_start_date '.$sort;
681 681
                     break;
682 682
             }
683 683
             // add to array of orderby params that have been added
684
-            self::$_query_params['orderby'][ $orderby ] = true;
684
+            self::$_query_params['orderby'][$orderby] = true;
685 685
             $counter++;
686 686
         }
687 687
         return $SQL;
Please login to merge, or discard this patch.
core/db_models/EEM_Venue.model.php 2 patches
Indentation   +182 added lines, -182 removed lines patch added patch discarded remove patch
@@ -11,189 +11,189 @@
 block discarded – undo
11 11
 class EEM_Venue extends EEM_CPT_Base
12 12
 {
13 13
 
14
-    // private instance of the Attendee object
15
-    protected static $_instance = null;
14
+	// private instance of the Attendee object
15
+	protected static $_instance = null;
16 16
 
17 17
 
18 18
 
19
-    protected function __construct($timezone = null)
20
-    {
21
-        $this->singular_item = __('Venue', 'event_espresso');
22
-        $this->plural_item = __('Venues', 'event_espresso');
23
-        $this->_tables = array(
24
-            'Venue_CPT'  => new EE_Primary_Table('posts', 'ID'),
25
-            'Venue_Meta' => new EE_Secondary_Table('esp_venue_meta', 'VNUM_ID', 'VNU_ID'),
26
-        );
27
-        $this->_fields = array(
28
-            'Venue_CPT'  => array(
29
-                'VNU_ID'         => new EE_Primary_Key_Int_Field('ID', __("Venue ID", "event_espresso")),
30
-                'VNU_name'       => new EE_Plain_Text_Field(
31
-                    'post_title',
32
-                    __("Venue Name", "event_espresso"),
33
-                    false,
34
-                    ''
35
-                ),
36
-                'VNU_desc'       => new EE_Post_Content_Field(
37
-                    'post_content',
38
-                    __("Venue Description", "event_espresso"),
39
-                    false,
40
-                    ''
41
-                ),
42
-                'VNU_identifier' => new EE_Slug_Field('post_name', __("Venue Identifier", "event_espresso"), false, ''),
43
-                'VNU_created'    => new EE_Datetime_Field(
44
-                    'post_date',
45
-                    __("Date Venue Created", "event_espresso"),
46
-                    false,
47
-                    EE_Datetime_Field::now
48
-                ),
49
-                'VNU_short_desc' => new EE_Plain_Text_Field(
50
-                    'post_excerpt',
51
-                    __("Short Description of Venue", "event_espresso"),
52
-                    true,
53
-                    ''
54
-                ),
55
-                'VNU_modified'   => new EE_Datetime_Field(
56
-                    'post_modified',
57
-                    __("Venue Modified Date", "event_espresso"),
58
-                    false,
59
-                    EE_Datetime_Field::now
60
-                ),
61
-                'VNU_wp_user'    => new EE_WP_User_Field(
62
-                    'post_author',
63
-                    __("Venue Creator ID", "event_espresso"),
64
-                    false
65
-                ),
66
-                'parent'         => new EE_Integer_Field(
67
-                    'post_parent',
68
-                    __("Venue Parent ID", "event_espresso"),
69
-                    false,
70
-                    0
71
-                ),
72
-                'VNU_order'      => new EE_Integer_Field('menu_order', __("Venue order", "event_espresso"), false, 1),
73
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_venues'),
74
-                'password' => new EE_Password_Field(
75
-                    'post_password',
76
-                    __('Password', 'event_espresso'),
77
-                    false,
78
-                    '',
79
-                    array(
80
-                        'VNU_desc',
81
-                        'VNU_short_desc',
82
-                        'VNU_address',
83
-                        'VNU_address2',
84
-                        'VNU_city',
85
-                        'STA_ID',
86
-                        'CNT_ISO',
87
-                        'VNU_zip',
88
-                        'VNU_phone',
89
-                        'VNU_capacity',
90
-                        'VNU_url',
91
-                        'VNU_virtual_phone',
92
-                        'VNU_virtual_url',
93
-                        'VNU_google_map_link',
94
-                        'VNU_enable_for_gmap',
95
-                    )
96
-                )
97
-            ),
98
-            'Venue_Meta' => array(
99
-                'VNUM_ID'             => new EE_DB_Only_Int_Field(
100
-                    'VNUM_ID',
101
-                    __("ID of Venue Meta Row", "event_espresso"),
102
-                    false
103
-                ),
104
-                'VNU_ID_fk'           => new EE_DB_Only_Int_Field(
105
-                    'VNU_ID',
106
-                    __("Foreign Key to Venue Post ", "event_espresso"),
107
-                    false
108
-                ),
109
-                'VNU_address'         => new EE_Plain_Text_Field(
110
-                    'VNU_address',
111
-                    __("Venue Address line 1", "event_espresso"),
112
-                    true,
113
-                    ''
114
-                ),
115
-                'VNU_address2'        => new EE_Plain_Text_Field(
116
-                    'VNU_address2',
117
-                    __("Venue Address line 2", "event_espresso"),
118
-                    true,
119
-                    ''
120
-                ),
121
-                'VNU_city'            => new EE_Plain_Text_Field(
122
-                    'VNU_city',
123
-                    __("Venue City", "event_espresso"),
124
-                    true,
125
-                    ''
126
-                ),
127
-                'STA_ID'              => new EE_Foreign_Key_Int_Field(
128
-                    'STA_ID',
129
-                    __("State ID", "event_espresso"),
130
-                    true,
131
-                    null,
132
-                    'State'
133
-                ),
134
-                'CNT_ISO'             => new EE_Foreign_Key_String_Field(
135
-                    'CNT_ISO',
136
-                    __("Country Code", "event_espresso"),
137
-                    true,
138
-                    null,
139
-                    'Country'
140
-                ),
141
-                'VNU_zip'             => new EE_Plain_Text_Field(
142
-                    'VNU_zip',
143
-                    __("Venue Zip/Postal Code", "event_espresso"),
144
-                    true
145
-                ),
146
-                'VNU_phone'           => new EE_Plain_Text_Field(
147
-                    'VNU_phone',
148
-                    __("Venue Phone", "event_espresso"),
149
-                    true
150
-                ),
151
-                'VNU_capacity'        => new EE_Infinite_Integer_Field(
152
-                    'VNU_capacity',
153
-                    __("Venue Capacity", "event_espresso"),
154
-                    true,
155
-                    EE_INF
156
-                ),
157
-                'VNU_url'             => new EE_Plain_Text_Field(
158
-                    'VNU_url',
159
-                    __('Venue Website', 'event_espresso'),
160
-                    true
161
-                ),
162
-                'VNU_virtual_phone'   => new EE_Plain_Text_Field(
163
-                    'VNU_virtual_phone',
164
-                    __('Call in Number', 'event_espresso'),
165
-                    true
166
-                ),
167
-                'VNU_virtual_url'     => new EE_Plain_Text_Field(
168
-                    'VNU_virtual_url',
169
-                    __('Virtual URL', 'event_espresso'),
170
-                    true
171
-                ),
172
-                'VNU_google_map_link' => new EE_Plain_Text_Field(
173
-                    'VNU_google_map_link',
174
-                    __('Google Map Link', 'event_espresso'),
175
-                    true
176
-                ),
177
-                'VNU_enable_for_gmap' => new EE_Boolean_Field(
178
-                    'VNU_enable_for_gmap',
179
-                    __('Show Google Map?', 'event_espresso'),
180
-                    false,
181
-                    false
182
-                ),
183
-            ),
184
-        );
185
-        $this->_model_relations = array(
186
-            'Country'           => new EE_Belongs_To_Relation(),
187
-            'Event'             => new EE_Has_Many_Relation(),
188
-            'Datetime'          => new EE_Has_Many_Relation(),
189
-            'State'             => new EE_Belongs_To_Relation(),
190
-            'Term_Relationship' => new EE_Has_Many_Relation(),
191
-            'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
192
-            'WP_User'           => new EE_Belongs_To_Relation(),
193
-        );
194
-        // this model is generally available for reading
195
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
196
-        $this->model_chain_to_password = '';
197
-        parent::__construct($timezone);
198
-    }
19
+	protected function __construct($timezone = null)
20
+	{
21
+		$this->singular_item = __('Venue', 'event_espresso');
22
+		$this->plural_item = __('Venues', 'event_espresso');
23
+		$this->_tables = array(
24
+			'Venue_CPT'  => new EE_Primary_Table('posts', 'ID'),
25
+			'Venue_Meta' => new EE_Secondary_Table('esp_venue_meta', 'VNUM_ID', 'VNU_ID'),
26
+		);
27
+		$this->_fields = array(
28
+			'Venue_CPT'  => array(
29
+				'VNU_ID'         => new EE_Primary_Key_Int_Field('ID', __("Venue ID", "event_espresso")),
30
+				'VNU_name'       => new EE_Plain_Text_Field(
31
+					'post_title',
32
+					__("Venue Name", "event_espresso"),
33
+					false,
34
+					''
35
+				),
36
+				'VNU_desc'       => new EE_Post_Content_Field(
37
+					'post_content',
38
+					__("Venue Description", "event_espresso"),
39
+					false,
40
+					''
41
+				),
42
+				'VNU_identifier' => new EE_Slug_Field('post_name', __("Venue Identifier", "event_espresso"), false, ''),
43
+				'VNU_created'    => new EE_Datetime_Field(
44
+					'post_date',
45
+					__("Date Venue Created", "event_espresso"),
46
+					false,
47
+					EE_Datetime_Field::now
48
+				),
49
+				'VNU_short_desc' => new EE_Plain_Text_Field(
50
+					'post_excerpt',
51
+					__("Short Description of Venue", "event_espresso"),
52
+					true,
53
+					''
54
+				),
55
+				'VNU_modified'   => new EE_Datetime_Field(
56
+					'post_modified',
57
+					__("Venue Modified Date", "event_espresso"),
58
+					false,
59
+					EE_Datetime_Field::now
60
+				),
61
+				'VNU_wp_user'    => new EE_WP_User_Field(
62
+					'post_author',
63
+					__("Venue Creator ID", "event_espresso"),
64
+					false
65
+				),
66
+				'parent'         => new EE_Integer_Field(
67
+					'post_parent',
68
+					__("Venue Parent ID", "event_espresso"),
69
+					false,
70
+					0
71
+				),
72
+				'VNU_order'      => new EE_Integer_Field('menu_order', __("Venue order", "event_espresso"), false, 1),
73
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_venues'),
74
+				'password' => new EE_Password_Field(
75
+					'post_password',
76
+					__('Password', 'event_espresso'),
77
+					false,
78
+					'',
79
+					array(
80
+						'VNU_desc',
81
+						'VNU_short_desc',
82
+						'VNU_address',
83
+						'VNU_address2',
84
+						'VNU_city',
85
+						'STA_ID',
86
+						'CNT_ISO',
87
+						'VNU_zip',
88
+						'VNU_phone',
89
+						'VNU_capacity',
90
+						'VNU_url',
91
+						'VNU_virtual_phone',
92
+						'VNU_virtual_url',
93
+						'VNU_google_map_link',
94
+						'VNU_enable_for_gmap',
95
+					)
96
+				)
97
+			),
98
+			'Venue_Meta' => array(
99
+				'VNUM_ID'             => new EE_DB_Only_Int_Field(
100
+					'VNUM_ID',
101
+					__("ID of Venue Meta Row", "event_espresso"),
102
+					false
103
+				),
104
+				'VNU_ID_fk'           => new EE_DB_Only_Int_Field(
105
+					'VNU_ID',
106
+					__("Foreign Key to Venue Post ", "event_espresso"),
107
+					false
108
+				),
109
+				'VNU_address'         => new EE_Plain_Text_Field(
110
+					'VNU_address',
111
+					__("Venue Address line 1", "event_espresso"),
112
+					true,
113
+					''
114
+				),
115
+				'VNU_address2'        => new EE_Plain_Text_Field(
116
+					'VNU_address2',
117
+					__("Venue Address line 2", "event_espresso"),
118
+					true,
119
+					''
120
+				),
121
+				'VNU_city'            => new EE_Plain_Text_Field(
122
+					'VNU_city',
123
+					__("Venue City", "event_espresso"),
124
+					true,
125
+					''
126
+				),
127
+				'STA_ID'              => new EE_Foreign_Key_Int_Field(
128
+					'STA_ID',
129
+					__("State ID", "event_espresso"),
130
+					true,
131
+					null,
132
+					'State'
133
+				),
134
+				'CNT_ISO'             => new EE_Foreign_Key_String_Field(
135
+					'CNT_ISO',
136
+					__("Country Code", "event_espresso"),
137
+					true,
138
+					null,
139
+					'Country'
140
+				),
141
+				'VNU_zip'             => new EE_Plain_Text_Field(
142
+					'VNU_zip',
143
+					__("Venue Zip/Postal Code", "event_espresso"),
144
+					true
145
+				),
146
+				'VNU_phone'           => new EE_Plain_Text_Field(
147
+					'VNU_phone',
148
+					__("Venue Phone", "event_espresso"),
149
+					true
150
+				),
151
+				'VNU_capacity'        => new EE_Infinite_Integer_Field(
152
+					'VNU_capacity',
153
+					__("Venue Capacity", "event_espresso"),
154
+					true,
155
+					EE_INF
156
+				),
157
+				'VNU_url'             => new EE_Plain_Text_Field(
158
+					'VNU_url',
159
+					__('Venue Website', 'event_espresso'),
160
+					true
161
+				),
162
+				'VNU_virtual_phone'   => new EE_Plain_Text_Field(
163
+					'VNU_virtual_phone',
164
+					__('Call in Number', 'event_espresso'),
165
+					true
166
+				),
167
+				'VNU_virtual_url'     => new EE_Plain_Text_Field(
168
+					'VNU_virtual_url',
169
+					__('Virtual URL', 'event_espresso'),
170
+					true
171
+				),
172
+				'VNU_google_map_link' => new EE_Plain_Text_Field(
173
+					'VNU_google_map_link',
174
+					__('Google Map Link', 'event_espresso'),
175
+					true
176
+				),
177
+				'VNU_enable_for_gmap' => new EE_Boolean_Field(
178
+					'VNU_enable_for_gmap',
179
+					__('Show Google Map?', 'event_espresso'),
180
+					false,
181
+					false
182
+				),
183
+			),
184
+		);
185
+		$this->_model_relations = array(
186
+			'Country'           => new EE_Belongs_To_Relation(),
187
+			'Event'             => new EE_Has_Many_Relation(),
188
+			'Datetime'          => new EE_Has_Many_Relation(),
189
+			'State'             => new EE_Belongs_To_Relation(),
190
+			'Term_Relationship' => new EE_Has_Many_Relation(),
191
+			'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
192
+			'WP_User'           => new EE_Belongs_To_Relation(),
193
+		);
194
+		// this model is generally available for reading
195
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
196
+		$this->model_chain_to_password = '';
197
+		parent::__construct($timezone);
198
+	}
199 199
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -192,7 +192,7 @@
 block discarded – undo
192 192
             'WP_User'           => new EE_Belongs_To_Relation(),
193 193
         );
194 194
         // this model is generally available for reading
195
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
195
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
196 196
         $this->model_chain_to_password = '';
197 197
         parent::__construct($timezone);
198 198
     }
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 1 patch
Indentation   +1481 added lines, -1481 removed lines patch added patch discarded remove patch
@@ -16,1485 +16,1485 @@
 block discarded – undo
16 16
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
17 17
 {
18 18
 
19
-    /**
20
-     * cached value for the the logical active status for the event
21
-     *
22
-     * @see get_active_status()
23
-     * @var string
24
-     */
25
-    protected $_active_status = '';
26
-
27
-    /**
28
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
-     *
30
-     * @var EE_Datetime
31
-     */
32
-    protected $_Primary_Datetime;
33
-
34
-    /**
35
-     * @var EventSpacesCalculator $available_spaces_calculator
36
-     */
37
-    protected $available_spaces_calculator;
38
-
39
-
40
-    /**
41
-     * @param array  $props_n_values          incoming values
42
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
-     *                                        used.)
44
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
-     *                                        date_format and the second value is the time format
46
-     * @return EE_Event
47
-     * @throws EE_Error
48
-     */
49
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
-    {
51
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
-    }
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values  incoming values from the database
58
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
-     *                                the website will be used.
60
-     * @return EE_Event
61
-     * @throws EE_Error
62
-     */
63
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
-    {
65
-        return new self($props_n_values, true, $timezone);
66
-    }
67
-
68
-
69
-    /**
70
-     * @return EventSpacesCalculator
71
-     * @throws \EE_Error
72
-     */
73
-    public function getAvailableSpacesCalculator()
74
-    {
75
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
77
-        }
78
-        return $this->available_spaces_calculator;
79
-    }
80
-
81
-
82
-    /**
83
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
-     *
85
-     * @param string $field_name
86
-     * @param mixed  $field_value
87
-     * @param bool   $use_default
88
-     * @throws EE_Error
89
-     */
90
-    public function set($field_name, $field_value, $use_default = false)
91
-    {
92
-        switch ($field_name) {
93
-            case 'status':
94
-                $this->set_status($field_value, $use_default);
95
-                break;
96
-            default:
97
-                parent::set($field_name, $field_value, $use_default);
98
-        }
99
-    }
100
-
101
-
102
-    /**
103
-     *    set_status
104
-     * Checks if event status is being changed to SOLD OUT
105
-     * and updates event meta data with previous event status
106
-     * so that we can revert things if/when the event is no longer sold out
107
-     *
108
-     * @access public
109
-     * @param string $new_status
110
-     * @param bool   $use_default
111
-     * @return void
112
-     * @throws EE_Error
113
-     */
114
-    public function set_status($new_status = null, $use_default = false)
115
-    {
116
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
-        if (empty($new_status) && ! $use_default) {
118
-            return;
119
-        }
120
-        // get current Event status
121
-        $old_status = $this->status();
122
-        // if status has changed
123
-        if ($old_status !== $new_status) {
124
-            // TO sold_out
125
-            if ($new_status === EEM_Event::sold_out) {
126
-                // save the previous event status so that we can revert if the event is no longer sold out
127
-                $this->add_post_meta('_previous_event_status', $old_status);
128
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
-            // OR FROM  sold_out
130
-            } elseif ($old_status === EEM_Event::sold_out) {
131
-                $this->delete_post_meta('_previous_event_status');
132
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
-            }
134
-            // clear out the active status so that it gets reset the next time it is requested
135
-            $this->_active_status = null;
136
-            // update status
137
-            parent::set('status', $new_status, $use_default);
138
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
139
-            return;
140
-        }
141
-        // even though the old value matches the new value, it's still good to
142
-        // allow the parent set method to have a say
143
-        parent::set('status', $new_status, $use_default);
144
-    }
145
-
146
-
147
-    /**
148
-     * Gets all the datetimes for this event
149
-     *
150
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
-     * @return EE_Base_Class[]|EE_Datetime[]
152
-     * @throws EE_Error
153
-     */
154
-    public function datetimes($query_params = array())
155
-    {
156
-        return $this->get_many_related('Datetime', $query_params);
157
-    }
158
-
159
-
160
-    /**
161
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
-     *
163
-     * @return EE_Base_Class[]|EE_Datetime[]
164
-     * @throws EE_Error
165
-     */
166
-    public function datetimes_in_chronological_order()
167
-    {
168
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
-    }
170
-
171
-
172
-    /**
173
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
-     * after running our query, so that this timezone isn't set for EVERY query
176
-     * on EEM_Datetime for the rest of the request, no?
177
-     *
178
-     * @param boolean $show_expired whether or not to include expired events
179
-     * @param boolean $show_deleted whether or not to include deleted events
180
-     * @param null    $limit
181
-     * @return EE_Datetime[]
182
-     * @throws EE_Error
183
-     */
184
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
-    {
186
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
-            $this->ID(),
188
-            $show_expired,
189
-            $show_deleted,
190
-            $limit
191
-        );
192
-    }
193
-
194
-
195
-    /**
196
-     * Returns one related datetime. Mostly only used by some legacy code.
197
-     *
198
-     * @return EE_Base_Class|EE_Datetime
199
-     * @throws EE_Error
200
-     */
201
-    public function first_datetime()
202
-    {
203
-        return $this->get_first_related('Datetime');
204
-    }
205
-
206
-
207
-    /**
208
-     * Returns the 'primary' datetime for the event
209
-     *
210
-     * @param bool $try_to_exclude_expired
211
-     * @param bool $try_to_exclude_deleted
212
-     * @return EE_Datetime
213
-     * @throws EE_Error
214
-     */
215
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
-    {
217
-        if (! empty($this->_Primary_Datetime)) {
218
-            return $this->_Primary_Datetime;
219
-        }
220
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
-            $this->ID(),
222
-            $try_to_exclude_expired,
223
-            $try_to_exclude_deleted
224
-        );
225
-        return $this->_Primary_Datetime;
226
-    }
227
-
228
-
229
-    /**
230
-     * Gets all the tickets available for purchase of this event
231
-     *
232
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
-     * @return EE_Base_Class[]|EE_Ticket[]
234
-     * @throws EE_Error
235
-     */
236
-    public function tickets($query_params = array())
237
-    {
238
-        // first get all datetimes
239
-        $datetimes = $this->datetimes_ordered();
240
-        if (! $datetimes) {
241
-            return array();
242
-        }
243
-        $datetime_ids = array();
244
-        foreach ($datetimes as $datetime) {
245
-            $datetime_ids[] = $datetime->ID();
246
-        }
247
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
-        // if incoming $query_params has where conditions let's merge but not override existing.
249
-        if (is_array($query_params) && isset($query_params[0])) {
250
-            $where_params = array_merge($query_params[0], $where_params);
251
-            unset($query_params[0]);
252
-        }
253
-        // now add $where_params to $query_params
254
-        $query_params[0] = $where_params;
255
-        return EEM_Ticket::instance()->get_all($query_params);
256
-    }
257
-
258
-
259
-    /**
260
-     * get all unexpired untrashed tickets
261
-     *
262
-     * @return EE_Ticket[]
263
-     * @throws EE_Error
264
-     */
265
-    public function active_tickets()
266
-    {
267
-        return $this->tickets(
268
-            array(
269
-                array(
270
-                    'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
-                    'TKT_deleted'  => false,
272
-                ),
273
-            )
274
-        );
275
-    }
276
-
277
-
278
-    /**
279
-     * @return bool
280
-     * @throws EE_Error
281
-     */
282
-    public function additional_limit()
283
-    {
284
-        return $this->get('EVT_additional_limit');
285
-    }
286
-
287
-
288
-    /**
289
-     * @return bool
290
-     * @throws EE_Error
291
-     */
292
-    public function allow_overflow()
293
-    {
294
-        return $this->get('EVT_allow_overflow');
295
-    }
296
-
297
-
298
-    /**
299
-     * @return bool
300
-     * @throws EE_Error
301
-     */
302
-    public function created()
303
-    {
304
-        return $this->get('EVT_created');
305
-    }
306
-
307
-
308
-    /**
309
-     * @return bool
310
-     * @throws EE_Error
311
-     */
312
-    public function description()
313
-    {
314
-        return $this->get('EVT_desc');
315
-    }
316
-
317
-
318
-    /**
319
-     * Runs do_shortcode and wpautop on the description
320
-     *
321
-     * @return string of html
322
-     * @throws EE_Error
323
-     */
324
-    public function description_filtered()
325
-    {
326
-        return $this->get_pretty('EVT_desc');
327
-    }
328
-
329
-
330
-    /**
331
-     * @return bool
332
-     * @throws EE_Error
333
-     */
334
-    public function display_description()
335
-    {
336
-        return $this->get('EVT_display_desc');
337
-    }
338
-
339
-
340
-    /**
341
-     * @return bool
342
-     * @throws EE_Error
343
-     */
344
-    public function display_ticket_selector()
345
-    {
346
-        return (bool) $this->get('EVT_display_ticket_selector');
347
-    }
348
-
349
-
350
-    /**
351
-     * @return bool
352
-     * @throws EE_Error
353
-     */
354
-    public function external_url()
355
-    {
356
-        return $this->get('EVT_external_URL');
357
-    }
358
-
359
-
360
-    /**
361
-     * @return bool
362
-     * @throws EE_Error
363
-     */
364
-    public function member_only()
365
-    {
366
-        return $this->get('EVT_member_only');
367
-    }
368
-
369
-
370
-    /**
371
-     * @return bool
372
-     * @throws EE_Error
373
-     */
374
-    public function phone()
375
-    {
376
-        return $this->get('EVT_phone');
377
-    }
378
-
379
-
380
-    /**
381
-     * @return bool
382
-     * @throws EE_Error
383
-     */
384
-    public function modified()
385
-    {
386
-        return $this->get('EVT_modified');
387
-    }
388
-
389
-
390
-    /**
391
-     * @return bool
392
-     * @throws EE_Error
393
-     */
394
-    public function name()
395
-    {
396
-        return $this->get('EVT_name');
397
-    }
398
-
399
-
400
-    /**
401
-     * @return bool
402
-     * @throws EE_Error
403
-     */
404
-    public function order()
405
-    {
406
-        return $this->get('EVT_order');
407
-    }
408
-
409
-
410
-    /**
411
-     * @return bool|string
412
-     * @throws EE_Error
413
-     */
414
-    public function default_registration_status()
415
-    {
416
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
417
-        return ! empty($event_default_registration_status)
418
-            ? $event_default_registration_status
419
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
420
-    }
421
-
422
-
423
-    /**
424
-     * @param int  $num_words
425
-     * @param null $more
426
-     * @param bool $not_full_desc
427
-     * @return bool|string
428
-     * @throws EE_Error
429
-     */
430
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
-    {
432
-        $short_desc = $this->get('EVT_short_desc');
433
-        if (! empty($short_desc) || $not_full_desc) {
434
-            return $short_desc;
435
-        }
436
-        $full_desc = $this->get('EVT_desc');
437
-        return wp_trim_words($full_desc, $num_words, $more);
438
-    }
439
-
440
-
441
-    /**
442
-     * @return bool
443
-     * @throws EE_Error
444
-     */
445
-    public function slug()
446
-    {
447
-        return $this->get('EVT_slug');
448
-    }
449
-
450
-
451
-    /**
452
-     * @return bool
453
-     * @throws EE_Error
454
-     */
455
-    public function timezone_string()
456
-    {
457
-        return $this->get('EVT_timezone_string');
458
-    }
459
-
460
-
461
-    /**
462
-     * @return bool
463
-     * @throws EE_Error
464
-     */
465
-    public function visible_on()
466
-    {
467
-        return $this->get('EVT_visible_on');
468
-    }
469
-
470
-
471
-    /**
472
-     * @return int
473
-     * @throws EE_Error
474
-     */
475
-    public function wp_user()
476
-    {
477
-        return $this->get('EVT_wp_user');
478
-    }
479
-
480
-
481
-    /**
482
-     * @return bool
483
-     * @throws EE_Error
484
-     */
485
-    public function donations()
486
-    {
487
-        return $this->get('EVT_donations');
488
-    }
489
-
490
-
491
-    /**
492
-     * @param $limit
493
-     * @throws EE_Error
494
-     */
495
-    public function set_additional_limit($limit)
496
-    {
497
-        $this->set('EVT_additional_limit', $limit);
498
-    }
499
-
500
-
501
-    /**
502
-     * @param $created
503
-     * @throws EE_Error
504
-     */
505
-    public function set_created($created)
506
-    {
507
-        $this->set('EVT_created', $created);
508
-    }
509
-
510
-
511
-    /**
512
-     * @param $desc
513
-     * @throws EE_Error
514
-     */
515
-    public function set_description($desc)
516
-    {
517
-        $this->set('EVT_desc', $desc);
518
-    }
519
-
520
-
521
-    /**
522
-     * @param $display_desc
523
-     * @throws EE_Error
524
-     */
525
-    public function set_display_description($display_desc)
526
-    {
527
-        $this->set('EVT_display_desc', $display_desc);
528
-    }
529
-
530
-
531
-    /**
532
-     * @param $display_ticket_selector
533
-     * @throws EE_Error
534
-     */
535
-    public function set_display_ticket_selector($display_ticket_selector)
536
-    {
537
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
-    }
539
-
540
-
541
-    /**
542
-     * @param $external_url
543
-     * @throws EE_Error
544
-     */
545
-    public function set_external_url($external_url)
546
-    {
547
-        $this->set('EVT_external_URL', $external_url);
548
-    }
549
-
550
-
551
-    /**
552
-     * @param $member_only
553
-     * @throws EE_Error
554
-     */
555
-    public function set_member_only($member_only)
556
-    {
557
-        $this->set('EVT_member_only', $member_only);
558
-    }
559
-
560
-
561
-    /**
562
-     * @param $event_phone
563
-     * @throws EE_Error
564
-     */
565
-    public function set_event_phone($event_phone)
566
-    {
567
-        $this->set('EVT_phone', $event_phone);
568
-    }
569
-
570
-
571
-    /**
572
-     * @param $modified
573
-     * @throws EE_Error
574
-     */
575
-    public function set_modified($modified)
576
-    {
577
-        $this->set('EVT_modified', $modified);
578
-    }
579
-
580
-
581
-    /**
582
-     * @param $name
583
-     * @throws EE_Error
584
-     */
585
-    public function set_name($name)
586
-    {
587
-        $this->set('EVT_name', $name);
588
-    }
589
-
590
-
591
-    /**
592
-     * @param $order
593
-     * @throws EE_Error
594
-     */
595
-    public function set_order($order)
596
-    {
597
-        $this->set('EVT_order', $order);
598
-    }
599
-
600
-
601
-    /**
602
-     * @param $short_desc
603
-     * @throws EE_Error
604
-     */
605
-    public function set_short_description($short_desc)
606
-    {
607
-        $this->set('EVT_short_desc', $short_desc);
608
-    }
609
-
610
-
611
-    /**
612
-     * @param $slug
613
-     * @throws EE_Error
614
-     */
615
-    public function set_slug($slug)
616
-    {
617
-        $this->set('EVT_slug', $slug);
618
-    }
619
-
620
-
621
-    /**
622
-     * @param $timezone_string
623
-     * @throws EE_Error
624
-     */
625
-    public function set_timezone_string($timezone_string)
626
-    {
627
-        $this->set('EVT_timezone_string', $timezone_string);
628
-    }
629
-
630
-
631
-    /**
632
-     * @param $visible_on
633
-     * @throws EE_Error
634
-     */
635
-    public function set_visible_on($visible_on)
636
-    {
637
-        $this->set('EVT_visible_on', $visible_on);
638
-    }
639
-
640
-
641
-    /**
642
-     * @param $wp_user
643
-     * @throws EE_Error
644
-     */
645
-    public function set_wp_user($wp_user)
646
-    {
647
-        $this->set('EVT_wp_user', $wp_user);
648
-    }
649
-
650
-
651
-    /**
652
-     * @param $default_registration_status
653
-     * @throws EE_Error
654
-     */
655
-    public function set_default_registration_status($default_registration_status)
656
-    {
657
-        $this->set('EVT_default_registration_status', $default_registration_status);
658
-    }
659
-
660
-
661
-    /**
662
-     * @param $donations
663
-     * @throws EE_Error
664
-     */
665
-    public function set_donations($donations)
666
-    {
667
-        $this->set('EVT_donations', $donations);
668
-    }
669
-
670
-
671
-    /**
672
-     * Adds a venue to this event
673
-     *
674
-     * @param int|EE_Venue /int $venue_id_or_obj
675
-     * @return EE_Base_Class|EE_Venue
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     */
679
-    public function add_venue($venue_id_or_obj): EE_Venue
680
-    {
681
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
682
-    }
683
-
684
-
685
-    /**
686
-     * Removes a venue from the event
687
-     *
688
-     * @param EE_Venue /int $venue_id_or_obj
689
-     * @return EE_Base_Class|EE_Venue
690
-     * @throws EE_Error
691
-     * @throws ReflectionException
692
-     */
693
-    public function remove_venue($venue_id_or_obj): EE_Venue
694
-    {
695
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
696
-    }
697
-
698
-
699
-    /**
700
-     * Gets the venue related to the event. May provide additional $query_params if desired
701
-     *
702
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
703
-     * @return int
704
-     * @throws EE_Error
705
-     * @throws ReflectionException
706
-     */
707
-    public function venue_ID(array $query_params = array()): int
708
-    {
709
-        $venue = $this->get_first_related('Venue', $query_params);
710
-        return $venue instanceof EE_Venue ? $venue->ID() : 0;
711
-    }
712
-
713
-
714
-    /**
715
-     * Gets the venue related to the event. May provide additional $query_params if desired
716
-     *
717
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
718
-     * @return EE_Base_Class|EE_Venue
719
-     * @throws EE_Error
720
-     * @throws ReflectionException
721
-     */
722
-    public function venue(array $query_params = array())
723
-    {
724
-        return $this->get_first_related('Venue', $query_params);
725
-    }
726
-
727
-
728
-    /**
729
-     * @param array $query_params
730
-     * @return EE_Base_Class[]|EE_Venue[]
731
-     * @throws EE_Error
732
-     * @throws ReflectionException
733
-     * @deprecated $VID:$
734
-     */
735
-    public function venues(array $query_params = array()): array
736
-    {
737
-        return (array) $this->venue($query_params);
738
-    }
739
-
740
-
741
-    /**
742
-     * check if event id is present and if event is published
743
-     *
744
-     * @access public
745
-     * @return boolean true yes, false no
746
-     * @throws EE_Error
747
-     */
748
-    private function _has_ID_and_is_published()
749
-    {
750
-        // first check if event id is present and not NULL,
751
-        // then check if this event is published (or any of the equivalent "published" statuses)
752
-        return
753
-            $this->ID() && $this->ID() !== null
754
-            && (
755
-                $this->status() === 'publish'
756
-                || $this->status() === EEM_Event::sold_out
757
-                || $this->status() === EEM_Event::postponed
758
-                || $this->status() === EEM_Event::cancelled
759
-            );
760
-    }
761
-
762
-
763
-    /**
764
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
765
-     *
766
-     * @access public
767
-     * @return boolean true yes, false no
768
-     * @throws EE_Error
769
-     */
770
-    public function is_upcoming()
771
-    {
772
-        // check if event id is present and if this event is published
773
-        if ($this->is_inactive()) {
774
-            return false;
775
-        }
776
-        // set initial value
777
-        $upcoming = false;
778
-        // next let's get all datetimes and loop through them
779
-        $datetimes = $this->datetimes_in_chronological_order();
780
-        foreach ($datetimes as $datetime) {
781
-            if ($datetime instanceof EE_Datetime) {
782
-                // if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
783
-                if ($datetime->is_expired()) {
784
-                    continue;
785
-                }
786
-                // if this dtt is active then we return false.
787
-                if ($datetime->is_active()) {
788
-                    return false;
789
-                }
790
-                // otherwise let's check upcoming status
791
-                $upcoming = $datetime->is_upcoming();
792
-            }
793
-        }
794
-        return $upcoming;
795
-    }
796
-
797
-
798
-    /**
799
-     * @return bool
800
-     * @throws EE_Error
801
-     */
802
-    public function is_active()
803
-    {
804
-        // check if event id is present and if this event is published
805
-        if ($this->is_inactive()) {
806
-            return false;
807
-        }
808
-        // set initial value
809
-        $active = false;
810
-        // next let's get all datetimes and loop through them
811
-        $datetimes = $this->datetimes_in_chronological_order();
812
-        foreach ($datetimes as $datetime) {
813
-            if ($datetime instanceof EE_Datetime) {
814
-                // if this dtt is expired then we continue cause one of the other datetimes might be active.
815
-                if ($datetime->is_expired()) {
816
-                    continue;
817
-                }
818
-                // if this dtt is upcoming then we return false.
819
-                if ($datetime->is_upcoming()) {
820
-                    return false;
821
-                }
822
-                // otherwise let's check active status
823
-                $active = $datetime->is_active();
824
-            }
825
-        }
826
-        return $active;
827
-    }
828
-
829
-
830
-    /**
831
-     * @return bool
832
-     * @throws EE_Error
833
-     */
834
-    public function is_expired()
835
-    {
836
-        // check if event id is present and if this event is published
837
-        if ($this->is_inactive()) {
838
-            return false;
839
-        }
840
-        // set initial value
841
-        $expired = false;
842
-        // first let's get all datetimes and loop through them
843
-        $datetimes = $this->datetimes_in_chronological_order();
844
-        foreach ($datetimes as $datetime) {
845
-            if ($datetime instanceof EE_Datetime) {
846
-                // if this dtt is upcoming or active then we return false.
847
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
848
-                    return false;
849
-                }
850
-                // otherwise let's check active status
851
-                $expired = $datetime->is_expired();
852
-            }
853
-        }
854
-        return $expired;
855
-    }
856
-
857
-
858
-    /**
859
-     * @return bool
860
-     * @throws EE_Error
861
-     */
862
-    public function is_inactive()
863
-    {
864
-        // check if event id is present and if this event is published
865
-        if ($this->_has_ID_and_is_published()) {
866
-            return false;
867
-        }
868
-        return true;
869
-    }
870
-
871
-
872
-    /**
873
-     * calculate spaces remaining based on "saleable" tickets
874
-     *
875
-     * @param array $tickets
876
-     * @param bool  $filtered
877
-     * @return int|float
878
-     * @throws EE_Error
879
-     * @throws DomainException
880
-     * @throws UnexpectedEntityException
881
-     */
882
-    public function spaces_remaining($tickets = array(), $filtered = true)
883
-    {
884
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
885
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
886
-        return $filtered
887
-            ? apply_filters(
888
-                'FHEE_EE_Event__spaces_remaining',
889
-                $spaces_remaining,
890
-                $this,
891
-                $tickets
892
-            )
893
-            : $spaces_remaining;
894
-    }
895
-
896
-
897
-    /**
898
-     *    perform_sold_out_status_check
899
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
900
-     *    available... if NOT, then the event status will get toggled to 'sold_out'
901
-     *
902
-     * @return bool    return the ACTUAL sold out state.
903
-     * @throws EE_Error
904
-     * @throws DomainException
905
-     * @throws UnexpectedEntityException
906
-     */
907
-    public function perform_sold_out_status_check()
908
-    {
909
-        // get all tickets
910
-        $tickets = $this->tickets(
911
-            array(
912
-                'default_where_conditions' => 'none',
913
-                'order_by' => array('TKT_qty' => 'ASC'),
914
-            )
915
-        );
916
-        $all_expired = true;
917
-        foreach ($tickets as $ticket) {
918
-            if (! $ticket->is_expired()) {
919
-                $all_expired = false;
920
-                break;
921
-            }
922
-        }
923
-        // if all the tickets are just expired, then don't update the event status to sold out
924
-        if ($all_expired) {
925
-            return true;
926
-        }
927
-        $spaces_remaining = $this->spaces_remaining($tickets);
928
-        if ($spaces_remaining < 1) {
929
-            if ($this->status() !== EEM_Event::post_status_private) {
930
-                $this->set_status(EEM_Event::sold_out);
931
-                $this->save();
932
-            }
933
-            $sold_out = true;
934
-        } else {
935
-            $sold_out = false;
936
-            // was event previously marked as sold out ?
937
-            if ($this->status() === EEM_Event::sold_out) {
938
-                // revert status to previous value, if it was set
939
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
940
-                if ($previous_event_status) {
941
-                    $this->set_status($previous_event_status);
942
-                    $this->save();
943
-                }
944
-            }
945
-        }
946
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
947
-        return $sold_out;
948
-    }
949
-
950
-
951
-    /**
952
-     * This returns the total remaining spaces for sale on this event.
953
-     *
954
-     * @uses EE_Event::total_available_spaces()
955
-     * @return float|int
956
-     * @throws EE_Error
957
-     * @throws DomainException
958
-     * @throws UnexpectedEntityException
959
-     */
960
-    public function spaces_remaining_for_sale()
961
-    {
962
-        return $this->total_available_spaces(true);
963
-    }
964
-
965
-
966
-    /**
967
-     * This returns the total spaces available for an event
968
-     * while considering all the qtys on the tickets and the reg limits
969
-     * on the datetimes attached to this event.
970
-     *
971
-     * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
972
-     *                              If this is false, then we return the most tickets that could ever be sold
973
-     *                              for this event with the datetime and tickets setup on the event under optimal
974
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
975
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
976
-     *                              may appear to equal remaining tickets.  However, the more tickets are
977
-     *                              sold out, the more accurate the "live" total is.
978
-     * @return float|int
979
-     * @throws EE_Error
980
-     * @throws DomainException
981
-     * @throws UnexpectedEntityException
982
-     */
983
-    public function total_available_spaces($consider_sold = false)
984
-    {
985
-        $spaces_available = $consider_sold
986
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
987
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
988
-        return apply_filters(
989
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
990
-            $spaces_available,
991
-            $this,
992
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
993
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
994
-        );
995
-    }
996
-
997
-
998
-    /**
999
-     * Checks if the event is set to sold out
1000
-     *
1001
-     * @param  bool $actual whether or not to perform calculations to not only figure the
1002
-     *                      actual status but also to flip the status if necessary to sold
1003
-     *                      out If false, we just check the existing status of the event
1004
-     * @return boolean
1005
-     * @throws EE_Error
1006
-     */
1007
-    public function is_sold_out($actual = false)
1008
-    {
1009
-        if (! $actual) {
1010
-            return $this->status() === EEM_Event::sold_out;
1011
-        }
1012
-        return $this->perform_sold_out_status_check();
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * Checks if the event is marked as postponed
1018
-     *
1019
-     * @return boolean
1020
-     */
1021
-    public function is_postponed()
1022
-    {
1023
-        return $this->status() === EEM_Event::postponed;
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * Checks if the event is marked as cancelled
1029
-     *
1030
-     * @return boolean
1031
-     */
1032
-    public function is_cancelled()
1033
-    {
1034
-        return $this->status() === EEM_Event::cancelled;
1035
-    }
1036
-
1037
-
1038
-    /**
1039
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1040
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1041
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1042
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1043
-     * the event is considered expired.
1044
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1045
-     * status set on the EVENT when it is not published and thus is done
1046
-     *
1047
-     * @param bool $reset
1048
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1049
-     * @throws EE_Error
1050
-     */
1051
-    public function get_active_status($reset = false)
1052
-    {
1053
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1054
-        if (! empty($this->_active_status) && ! $reset) {
1055
-            return $this->_active_status;
1056
-        }
1057
-        // first check if event id is present on this object
1058
-        if (! $this->ID()) {
1059
-            return false;
1060
-        }
1061
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1062
-        // if event is published:
1063
-        if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1064
-            // active?
1065
-            if (
1066
-                EEM_Datetime::instance()->get_datetime_count_for_status(
1067
-                    EE_Datetime::active,
1068
-                    $where_params_for_event
1069
-                ) > 0
1070
-            ) {
1071
-                $this->_active_status = EE_Datetime::active;
1072
-            } else {
1073
-                // upcoming?
1074
-                if (
1075
-                    EEM_Datetime::instance()->get_datetime_count_for_status(
1076
-                        EE_Datetime::upcoming,
1077
-                        $where_params_for_event
1078
-                    ) > 0
1079
-                ) {
1080
-                    $this->_active_status = EE_Datetime::upcoming;
1081
-                } else {
1082
-                    // expired?
1083
-                    if (
1084
-                        EEM_Datetime::instance()->get_datetime_count_for_status(
1085
-                            EE_Datetime::expired,
1086
-                            $where_params_for_event
1087
-                        ) > 0
1088
-                    ) {
1089
-                        $this->_active_status = EE_Datetime::expired;
1090
-                    } else {
1091
-                        // it would be odd if things make it this far because it basically means there are no datetime's
1092
-                        // attached to the event.  So in this case it will just be considered inactive.
1093
-                        $this->_active_status = EE_Datetime::inactive;
1094
-                    }
1095
-                }
1096
-            }
1097
-        } else {
1098
-            // the event is not published, so let's just set it's active status according to its' post status
1099
-            switch ($this->status()) {
1100
-                case EEM_Event::sold_out:
1101
-                    $this->_active_status = EE_Datetime::sold_out;
1102
-                    break;
1103
-                case EEM_Event::cancelled:
1104
-                    $this->_active_status = EE_Datetime::cancelled;
1105
-                    break;
1106
-                case EEM_Event::postponed:
1107
-                    $this->_active_status = EE_Datetime::postponed;
1108
-                    break;
1109
-                default:
1110
-                    $this->_active_status = EE_Datetime::inactive;
1111
-            }
1112
-        }
1113
-        return $this->_active_status;
1114
-    }
1115
-
1116
-
1117
-    /**
1118
-     *    pretty_active_status
1119
-     *
1120
-     * @access public
1121
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1122
-     * @return mixed void|string
1123
-     * @throws EE_Error
1124
-     */
1125
-    public function pretty_active_status($echo = true)
1126
-    {
1127
-        $active_status = $this->get_active_status();
1128
-        $status = '<span class="ee-status event-active-status-'
1129
-                  . $active_status
1130
-                  . '">'
1131
-                  . EEH_Template::pretty_status($active_status, false, 'sentence')
1132
-                  . '</span>';
1133
-        if ($echo) {
1134
-            echo $status;
1135
-            return '';
1136
-        }
1137
-        return $status;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * @return bool|int
1143
-     * @throws EE_Error
1144
-     */
1145
-    public function get_number_of_tickets_sold()
1146
-    {
1147
-        $tkt_sold = 0;
1148
-        if (! $this->ID()) {
1149
-            return 0;
1150
-        }
1151
-        $datetimes = $this->datetimes();
1152
-        foreach ($datetimes as $datetime) {
1153
-            if ($datetime instanceof EE_Datetime) {
1154
-                $tkt_sold += $datetime->sold();
1155
-            }
1156
-        }
1157
-        return $tkt_sold;
1158
-    }
1159
-
1160
-
1161
-    /**
1162
-     * This just returns a count of all the registrations for this event
1163
-     *
1164
-     * @access  public
1165
-     * @return int
1166
-     * @throws EE_Error
1167
-     */
1168
-    public function get_count_of_all_registrations()
1169
-    {
1170
-        return EEM_Event::instance()->count_related($this, 'Registration');
1171
-    }
1172
-
1173
-
1174
-    /**
1175
-     * This returns the ticket with the earliest start time that is
1176
-     * available for this event (across all datetimes attached to the event)
1177
-     *
1178
-     * @return EE_Base_Class|EE_Ticket|null
1179
-     * @throws EE_Error
1180
-     */
1181
-    public function get_ticket_with_earliest_start_time()
1182
-    {
1183
-        $where['Datetime.EVT_ID'] = $this->ID();
1184
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1185
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1186
-    }
1187
-
1188
-
1189
-    /**
1190
-     * This returns the ticket with the latest end time that is available
1191
-     * for this event (across all datetimes attached to the event)
1192
-     *
1193
-     * @return EE_Base_Class|EE_Ticket|null
1194
-     * @throws EE_Error
1195
-     */
1196
-    public function get_ticket_with_latest_end_time()
1197
-    {
1198
-        $where['Datetime.EVT_ID'] = $this->ID();
1199
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1200
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * This returns the number of different ticket types currently on sale for this event.
1206
-     *
1207
-     * @return int
1208
-     * @throws EE_Error
1209
-     */
1210
-    public function countTicketsOnSale()
1211
-    {
1212
-        $where = array(
1213
-            'Datetime.EVT_ID' => $this->ID(),
1214
-            'TKT_start_date'  => array('<', time()),
1215
-            'TKT_end_date'    => array('>', time()),
1216
-        );
1217
-        return EEM_Ticket::instance()->count(array($where));
1218
-    }
1219
-
1220
-
1221
-    /**
1222
-     * This returns whether there are any tickets on sale for this event.
1223
-     *
1224
-     * @return bool true = YES tickets on sale.
1225
-     * @throws EE_Error
1226
-     */
1227
-    public function tickets_on_sale()
1228
-    {
1229
-        return $this->countTicketsOnSale() > 0;
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1235
-     * to check for an external URL first
1236
-     *
1237
-     * @return string
1238
-     * @throws EE_Error
1239
-     */
1240
-    public function get_permalink()
1241
-    {
1242
-        if ($this->external_url()) {
1243
-            return $this->external_url();
1244
-        }
1245
-        return parent::get_permalink();
1246
-    }
1247
-
1248
-
1249
-    /**
1250
-     * Gets the first term for 'espresso_event_categories' we can find
1251
-     *
1252
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1253
-     * @return EE_Base_Class|EE_Term|null
1254
-     * @throws EE_Error
1255
-     */
1256
-    public function first_event_category($query_params = array())
1257
-    {
1258
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1259
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1260
-        return EEM_Term::instance()->get_one($query_params);
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     * Gets all terms for 'espresso_event_categories' we can find
1266
-     *
1267
-     * @param array $query_params
1268
-     * @return EE_Base_Class[]|EE_Term[]
1269
-     * @throws EE_Error
1270
-     */
1271
-    public function get_all_event_categories($query_params = array())
1272
-    {
1273
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1274
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1275
-        return EEM_Term::instance()->get_all($query_params);
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * Adds a question group to this event
1281
-     *
1282
-     * @param EE_Question_Group|int $question_group_id_or_obj
1283
-     * @param bool $for_primary if true, the question group will be added for the primary
1284
-     *                                           registrant, if false will be added for others. default: false
1285
-     * @return EE_Base_Class|EE_Question_Group
1286
-     * @throws EE_Error
1287
-     * @throws InvalidArgumentException
1288
-     * @throws InvalidDataTypeException
1289
-     * @throws InvalidInterfaceException
1290
-     * @throws ReflectionException
1291
-     */
1292
-    public function add_question_group($question_group_id_or_obj, $for_primary = false)
1293
-    {
1294
-        // If the row already exists, it will be updated. If it doesn't, it will be inserted.
1295
-        // That's in EE_HABTM_Relation::add_relation_to().
1296
-        return $this->_add_relation_to(
1297
-            $question_group_id_or_obj,
1298
-            'Question_Group',
1299
-            [
1300
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1301
-            ]
1302
-        );
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     * Removes a question group from the event
1308
-     *
1309
-     * @param EE_Question_Group|int $question_group_id_or_obj
1310
-     * @param bool $for_primary if true, the question group will be removed from the primary
1311
-     *                                           registrant, if false will be removed from others. default: false
1312
-     * @return EE_Base_Class|EE_Question_Group
1313
-     * @throws EE_Error
1314
-     * @throws InvalidArgumentException
1315
-     * @throws ReflectionException
1316
-     * @throws InvalidDataTypeException
1317
-     * @throws InvalidInterfaceException
1318
-     */
1319
-    public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1320
-    {
1321
-        // If the question group is used for the other type (primary or additional)
1322
-        // then just update it. If not, delete it outright.
1323
-        $existing_relation = $this->get_first_related(
1324
-            'Event_Question_Group',
1325
-            [
1326
-                [
1327
-                    'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1328
-                ]
1329
-            ]
1330
-        );
1331
-        $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1332
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1333
-        if ($existing_relation->get($other_field) === false) {
1334
-            // Delete it. It's now no longer for primary or additional question groups.
1335
-            return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1336
-        }
1337
-        // Just update it. They'll still use this question group for the other category
1338
-        $existing_relation->save(
1339
-            [
1340
-                $field_to_update => false
1341
-            ]
1342
-        );
1343
-    }
1344
-
1345
-
1346
-    /**
1347
-     * Gets all the question groups, ordering them by QSG_order ascending
1348
-     *
1349
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1350
-     * @return EE_Base_Class[]|EE_Question_Group[]
1351
-     * @throws EE_Error
1352
-     */
1353
-    public function question_groups($query_params = array())
1354
-    {
1355
-        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1356
-        return $this->get_many_related('Question_Group', $query_params);
1357
-    }
1358
-
1359
-
1360
-    /**
1361
-     * Implementation for EEI_Has_Icon interface method.
1362
-     *
1363
-     * @see EEI_Visual_Representation for comments
1364
-     * @return string
1365
-     */
1366
-    public function get_icon()
1367
-    {
1368
-        return '<span class="dashicons dashicons-flag"></span>';
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     * Implementation for EEI_Admin_Links interface method.
1374
-     *
1375
-     * @see EEI_Admin_Links for comments
1376
-     * @return string
1377
-     * @throws EE_Error
1378
-     */
1379
-    public function get_admin_details_link()
1380
-    {
1381
-        return $this->get_admin_edit_link();
1382
-    }
1383
-
1384
-
1385
-    /**
1386
-     * Implementation for EEI_Admin_Links interface method.
1387
-     *
1388
-     * @see EEI_Admin_Links for comments
1389
-     * @return string
1390
-     * @throws EE_Error
1391
-     */
1392
-    public function get_admin_edit_link()
1393
-    {
1394
-        return EEH_URL::add_query_args_and_nonce(
1395
-            array(
1396
-                'page'   => 'espresso_events',
1397
-                'action' => 'edit',
1398
-                'post'   => $this->ID(),
1399
-            ),
1400
-            admin_url('admin.php')
1401
-        );
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * Implementation for EEI_Admin_Links interface method.
1407
-     *
1408
-     * @see EEI_Admin_Links for comments
1409
-     * @return string
1410
-     */
1411
-    public function get_admin_settings_link()
1412
-    {
1413
-        return EEH_URL::add_query_args_and_nonce(
1414
-            array(
1415
-                'page'   => 'espresso_events',
1416
-                'action' => 'default_event_settings',
1417
-            ),
1418
-            admin_url('admin.php')
1419
-        );
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * Implementation for EEI_Admin_Links interface method.
1425
-     *
1426
-     * @see EEI_Admin_Links for comments
1427
-     * @return string
1428
-     */
1429
-    public function get_admin_overview_link()
1430
-    {
1431
-        return EEH_URL::add_query_args_and_nonce(
1432
-            array(
1433
-                'page'   => 'espresso_events',
1434
-                'action' => 'default',
1435
-            ),
1436
-            admin_url('admin.php')
1437
-        );
1438
-    }
1439
-
1440
-
1441
-    /**
1442
-     * @return string|null
1443
-     * @throws EE_Error
1444
-     * @throws ReflectionException
1445
-     */
1446
-    public function registrationFormUuid(): ?string
1447
-    {
1448
-        return $this->get('FSC_UUID');
1449
-    }
1450
-
1451
-
1452
-    /**
1453
-     * Gets all the form sections for this event
1454
-     *
1455
-     * @return EE_Base_Class[]|EE_Form_Section[]
1456
-     * @throws EE_Error
1457
-     * @throws ReflectionException
1458
-     */
1459
-    public function registrationForm()
1460
-    {
1461
-        $FSC_UUID = $this->registrationFormUuid();
1462
-
1463
-        if (empty($FSC_UUID)) {
1464
-            return [];
1465
-        }
1466
-
1467
-        return EEM_Form_Section::instance()->get_all([
1468
-            [
1469
-                'OR' => [
1470
-                    'FSC_UUID'      => $FSC_UUID, // top level form
1471
-                    'FSC_belongsTo' => $FSC_UUID, // child form sections
1472
-                ]
1473
-                ],
1474
-            'order_by' => ['FSC_order' => 'ASC'],
1475
-        ]);
1476
-    }
1477
-
1478
-
1479
-    /**
1480
-     * @param string $UUID
1481
-     * @throws EE_Error
1482
-     */
1483
-    public function setRegistrationFormUuid(string $UUID): void
1484
-    {
1485
-        if (! Cuid::isCuid($UUID)) {
1486
-            throw new InvalidArgumentException(
1487
-                sprintf(
1488
-                /* translators: 1: UUID value, 2: UUID generator function. */
1489
-                    esc_html__(
1490
-                        'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1491
-                        'event_espresso'
1492
-                    ),
1493
-                    $UUID,
1494
-                    '`Cuid::cuid()`'
1495
-                )
1496
-            );
1497
-        }
1498
-        $this->set('FSC_UUID', $UUID);
1499
-    }
19
+	/**
20
+	 * cached value for the the logical active status for the event
21
+	 *
22
+	 * @see get_active_status()
23
+	 * @var string
24
+	 */
25
+	protected $_active_status = '';
26
+
27
+	/**
28
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
+	 *
30
+	 * @var EE_Datetime
31
+	 */
32
+	protected $_Primary_Datetime;
33
+
34
+	/**
35
+	 * @var EventSpacesCalculator $available_spaces_calculator
36
+	 */
37
+	protected $available_spaces_calculator;
38
+
39
+
40
+	/**
41
+	 * @param array  $props_n_values          incoming values
42
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
+	 *                                        used.)
44
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
+	 *                                        date_format and the second value is the time format
46
+	 * @return EE_Event
47
+	 * @throws EE_Error
48
+	 */
49
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
+	{
51
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
+	}
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values  incoming values from the database
58
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
+	 *                                the website will be used.
60
+	 * @return EE_Event
61
+	 * @throws EE_Error
62
+	 */
63
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
+	{
65
+		return new self($props_n_values, true, $timezone);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return EventSpacesCalculator
71
+	 * @throws \EE_Error
72
+	 */
73
+	public function getAvailableSpacesCalculator()
74
+	{
75
+		if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
77
+		}
78
+		return $this->available_spaces_calculator;
79
+	}
80
+
81
+
82
+	/**
83
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
+	 *
85
+	 * @param string $field_name
86
+	 * @param mixed  $field_value
87
+	 * @param bool   $use_default
88
+	 * @throws EE_Error
89
+	 */
90
+	public function set($field_name, $field_value, $use_default = false)
91
+	{
92
+		switch ($field_name) {
93
+			case 'status':
94
+				$this->set_status($field_value, $use_default);
95
+				break;
96
+			default:
97
+				parent::set($field_name, $field_value, $use_default);
98
+		}
99
+	}
100
+
101
+
102
+	/**
103
+	 *    set_status
104
+	 * Checks if event status is being changed to SOLD OUT
105
+	 * and updates event meta data with previous event status
106
+	 * so that we can revert things if/when the event is no longer sold out
107
+	 *
108
+	 * @access public
109
+	 * @param string $new_status
110
+	 * @param bool   $use_default
111
+	 * @return void
112
+	 * @throws EE_Error
113
+	 */
114
+	public function set_status($new_status = null, $use_default = false)
115
+	{
116
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
+		if (empty($new_status) && ! $use_default) {
118
+			return;
119
+		}
120
+		// get current Event status
121
+		$old_status = $this->status();
122
+		// if status has changed
123
+		if ($old_status !== $new_status) {
124
+			// TO sold_out
125
+			if ($new_status === EEM_Event::sold_out) {
126
+				// save the previous event status so that we can revert if the event is no longer sold out
127
+				$this->add_post_meta('_previous_event_status', $old_status);
128
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
+			// OR FROM  sold_out
130
+			} elseif ($old_status === EEM_Event::sold_out) {
131
+				$this->delete_post_meta('_previous_event_status');
132
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
+			}
134
+			// clear out the active status so that it gets reset the next time it is requested
135
+			$this->_active_status = null;
136
+			// update status
137
+			parent::set('status', $new_status, $use_default);
138
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
139
+			return;
140
+		}
141
+		// even though the old value matches the new value, it's still good to
142
+		// allow the parent set method to have a say
143
+		parent::set('status', $new_status, $use_default);
144
+	}
145
+
146
+
147
+	/**
148
+	 * Gets all the datetimes for this event
149
+	 *
150
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
+	 * @return EE_Base_Class[]|EE_Datetime[]
152
+	 * @throws EE_Error
153
+	 */
154
+	public function datetimes($query_params = array())
155
+	{
156
+		return $this->get_many_related('Datetime', $query_params);
157
+	}
158
+
159
+
160
+	/**
161
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
+	 *
163
+	 * @return EE_Base_Class[]|EE_Datetime[]
164
+	 * @throws EE_Error
165
+	 */
166
+	public function datetimes_in_chronological_order()
167
+	{
168
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
+	}
170
+
171
+
172
+	/**
173
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
+	 * after running our query, so that this timezone isn't set for EVERY query
176
+	 * on EEM_Datetime for the rest of the request, no?
177
+	 *
178
+	 * @param boolean $show_expired whether or not to include expired events
179
+	 * @param boolean $show_deleted whether or not to include deleted events
180
+	 * @param null    $limit
181
+	 * @return EE_Datetime[]
182
+	 * @throws EE_Error
183
+	 */
184
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
+	{
186
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
+			$this->ID(),
188
+			$show_expired,
189
+			$show_deleted,
190
+			$limit
191
+		);
192
+	}
193
+
194
+
195
+	/**
196
+	 * Returns one related datetime. Mostly only used by some legacy code.
197
+	 *
198
+	 * @return EE_Base_Class|EE_Datetime
199
+	 * @throws EE_Error
200
+	 */
201
+	public function first_datetime()
202
+	{
203
+		return $this->get_first_related('Datetime');
204
+	}
205
+
206
+
207
+	/**
208
+	 * Returns the 'primary' datetime for the event
209
+	 *
210
+	 * @param bool $try_to_exclude_expired
211
+	 * @param bool $try_to_exclude_deleted
212
+	 * @return EE_Datetime
213
+	 * @throws EE_Error
214
+	 */
215
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
+	{
217
+		if (! empty($this->_Primary_Datetime)) {
218
+			return $this->_Primary_Datetime;
219
+		}
220
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
+			$this->ID(),
222
+			$try_to_exclude_expired,
223
+			$try_to_exclude_deleted
224
+		);
225
+		return $this->_Primary_Datetime;
226
+	}
227
+
228
+
229
+	/**
230
+	 * Gets all the tickets available for purchase of this event
231
+	 *
232
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
+	 * @return EE_Base_Class[]|EE_Ticket[]
234
+	 * @throws EE_Error
235
+	 */
236
+	public function tickets($query_params = array())
237
+	{
238
+		// first get all datetimes
239
+		$datetimes = $this->datetimes_ordered();
240
+		if (! $datetimes) {
241
+			return array();
242
+		}
243
+		$datetime_ids = array();
244
+		foreach ($datetimes as $datetime) {
245
+			$datetime_ids[] = $datetime->ID();
246
+		}
247
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
+		// if incoming $query_params has where conditions let's merge but not override existing.
249
+		if (is_array($query_params) && isset($query_params[0])) {
250
+			$where_params = array_merge($query_params[0], $where_params);
251
+			unset($query_params[0]);
252
+		}
253
+		// now add $where_params to $query_params
254
+		$query_params[0] = $where_params;
255
+		return EEM_Ticket::instance()->get_all($query_params);
256
+	}
257
+
258
+
259
+	/**
260
+	 * get all unexpired untrashed tickets
261
+	 *
262
+	 * @return EE_Ticket[]
263
+	 * @throws EE_Error
264
+	 */
265
+	public function active_tickets()
266
+	{
267
+		return $this->tickets(
268
+			array(
269
+				array(
270
+					'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
+					'TKT_deleted'  => false,
272
+				),
273
+			)
274
+		);
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return bool
280
+	 * @throws EE_Error
281
+	 */
282
+	public function additional_limit()
283
+	{
284
+		return $this->get('EVT_additional_limit');
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return bool
290
+	 * @throws EE_Error
291
+	 */
292
+	public function allow_overflow()
293
+	{
294
+		return $this->get('EVT_allow_overflow');
295
+	}
296
+
297
+
298
+	/**
299
+	 * @return bool
300
+	 * @throws EE_Error
301
+	 */
302
+	public function created()
303
+	{
304
+		return $this->get('EVT_created');
305
+	}
306
+
307
+
308
+	/**
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 */
312
+	public function description()
313
+	{
314
+		return $this->get('EVT_desc');
315
+	}
316
+
317
+
318
+	/**
319
+	 * Runs do_shortcode and wpautop on the description
320
+	 *
321
+	 * @return string of html
322
+	 * @throws EE_Error
323
+	 */
324
+	public function description_filtered()
325
+	{
326
+		return $this->get_pretty('EVT_desc');
327
+	}
328
+
329
+
330
+	/**
331
+	 * @return bool
332
+	 * @throws EE_Error
333
+	 */
334
+	public function display_description()
335
+	{
336
+		return $this->get('EVT_display_desc');
337
+	}
338
+
339
+
340
+	/**
341
+	 * @return bool
342
+	 * @throws EE_Error
343
+	 */
344
+	public function display_ticket_selector()
345
+	{
346
+		return (bool) $this->get('EVT_display_ticket_selector');
347
+	}
348
+
349
+
350
+	/**
351
+	 * @return bool
352
+	 * @throws EE_Error
353
+	 */
354
+	public function external_url()
355
+	{
356
+		return $this->get('EVT_external_URL');
357
+	}
358
+
359
+
360
+	/**
361
+	 * @return bool
362
+	 * @throws EE_Error
363
+	 */
364
+	public function member_only()
365
+	{
366
+		return $this->get('EVT_member_only');
367
+	}
368
+
369
+
370
+	/**
371
+	 * @return bool
372
+	 * @throws EE_Error
373
+	 */
374
+	public function phone()
375
+	{
376
+		return $this->get('EVT_phone');
377
+	}
378
+
379
+
380
+	/**
381
+	 * @return bool
382
+	 * @throws EE_Error
383
+	 */
384
+	public function modified()
385
+	{
386
+		return $this->get('EVT_modified');
387
+	}
388
+
389
+
390
+	/**
391
+	 * @return bool
392
+	 * @throws EE_Error
393
+	 */
394
+	public function name()
395
+	{
396
+		return $this->get('EVT_name');
397
+	}
398
+
399
+
400
+	/**
401
+	 * @return bool
402
+	 * @throws EE_Error
403
+	 */
404
+	public function order()
405
+	{
406
+		return $this->get('EVT_order');
407
+	}
408
+
409
+
410
+	/**
411
+	 * @return bool|string
412
+	 * @throws EE_Error
413
+	 */
414
+	public function default_registration_status()
415
+	{
416
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
417
+		return ! empty($event_default_registration_status)
418
+			? $event_default_registration_status
419
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
420
+	}
421
+
422
+
423
+	/**
424
+	 * @param int  $num_words
425
+	 * @param null $more
426
+	 * @param bool $not_full_desc
427
+	 * @return bool|string
428
+	 * @throws EE_Error
429
+	 */
430
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
+	{
432
+		$short_desc = $this->get('EVT_short_desc');
433
+		if (! empty($short_desc) || $not_full_desc) {
434
+			return $short_desc;
435
+		}
436
+		$full_desc = $this->get('EVT_desc');
437
+		return wp_trim_words($full_desc, $num_words, $more);
438
+	}
439
+
440
+
441
+	/**
442
+	 * @return bool
443
+	 * @throws EE_Error
444
+	 */
445
+	public function slug()
446
+	{
447
+		return $this->get('EVT_slug');
448
+	}
449
+
450
+
451
+	/**
452
+	 * @return bool
453
+	 * @throws EE_Error
454
+	 */
455
+	public function timezone_string()
456
+	{
457
+		return $this->get('EVT_timezone_string');
458
+	}
459
+
460
+
461
+	/**
462
+	 * @return bool
463
+	 * @throws EE_Error
464
+	 */
465
+	public function visible_on()
466
+	{
467
+		return $this->get('EVT_visible_on');
468
+	}
469
+
470
+
471
+	/**
472
+	 * @return int
473
+	 * @throws EE_Error
474
+	 */
475
+	public function wp_user()
476
+	{
477
+		return $this->get('EVT_wp_user');
478
+	}
479
+
480
+
481
+	/**
482
+	 * @return bool
483
+	 * @throws EE_Error
484
+	 */
485
+	public function donations()
486
+	{
487
+		return $this->get('EVT_donations');
488
+	}
489
+
490
+
491
+	/**
492
+	 * @param $limit
493
+	 * @throws EE_Error
494
+	 */
495
+	public function set_additional_limit($limit)
496
+	{
497
+		$this->set('EVT_additional_limit', $limit);
498
+	}
499
+
500
+
501
+	/**
502
+	 * @param $created
503
+	 * @throws EE_Error
504
+	 */
505
+	public function set_created($created)
506
+	{
507
+		$this->set('EVT_created', $created);
508
+	}
509
+
510
+
511
+	/**
512
+	 * @param $desc
513
+	 * @throws EE_Error
514
+	 */
515
+	public function set_description($desc)
516
+	{
517
+		$this->set('EVT_desc', $desc);
518
+	}
519
+
520
+
521
+	/**
522
+	 * @param $display_desc
523
+	 * @throws EE_Error
524
+	 */
525
+	public function set_display_description($display_desc)
526
+	{
527
+		$this->set('EVT_display_desc', $display_desc);
528
+	}
529
+
530
+
531
+	/**
532
+	 * @param $display_ticket_selector
533
+	 * @throws EE_Error
534
+	 */
535
+	public function set_display_ticket_selector($display_ticket_selector)
536
+	{
537
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
+	}
539
+
540
+
541
+	/**
542
+	 * @param $external_url
543
+	 * @throws EE_Error
544
+	 */
545
+	public function set_external_url($external_url)
546
+	{
547
+		$this->set('EVT_external_URL', $external_url);
548
+	}
549
+
550
+
551
+	/**
552
+	 * @param $member_only
553
+	 * @throws EE_Error
554
+	 */
555
+	public function set_member_only($member_only)
556
+	{
557
+		$this->set('EVT_member_only', $member_only);
558
+	}
559
+
560
+
561
+	/**
562
+	 * @param $event_phone
563
+	 * @throws EE_Error
564
+	 */
565
+	public function set_event_phone($event_phone)
566
+	{
567
+		$this->set('EVT_phone', $event_phone);
568
+	}
569
+
570
+
571
+	/**
572
+	 * @param $modified
573
+	 * @throws EE_Error
574
+	 */
575
+	public function set_modified($modified)
576
+	{
577
+		$this->set('EVT_modified', $modified);
578
+	}
579
+
580
+
581
+	/**
582
+	 * @param $name
583
+	 * @throws EE_Error
584
+	 */
585
+	public function set_name($name)
586
+	{
587
+		$this->set('EVT_name', $name);
588
+	}
589
+
590
+
591
+	/**
592
+	 * @param $order
593
+	 * @throws EE_Error
594
+	 */
595
+	public function set_order($order)
596
+	{
597
+		$this->set('EVT_order', $order);
598
+	}
599
+
600
+
601
+	/**
602
+	 * @param $short_desc
603
+	 * @throws EE_Error
604
+	 */
605
+	public function set_short_description($short_desc)
606
+	{
607
+		$this->set('EVT_short_desc', $short_desc);
608
+	}
609
+
610
+
611
+	/**
612
+	 * @param $slug
613
+	 * @throws EE_Error
614
+	 */
615
+	public function set_slug($slug)
616
+	{
617
+		$this->set('EVT_slug', $slug);
618
+	}
619
+
620
+
621
+	/**
622
+	 * @param $timezone_string
623
+	 * @throws EE_Error
624
+	 */
625
+	public function set_timezone_string($timezone_string)
626
+	{
627
+		$this->set('EVT_timezone_string', $timezone_string);
628
+	}
629
+
630
+
631
+	/**
632
+	 * @param $visible_on
633
+	 * @throws EE_Error
634
+	 */
635
+	public function set_visible_on($visible_on)
636
+	{
637
+		$this->set('EVT_visible_on', $visible_on);
638
+	}
639
+
640
+
641
+	/**
642
+	 * @param $wp_user
643
+	 * @throws EE_Error
644
+	 */
645
+	public function set_wp_user($wp_user)
646
+	{
647
+		$this->set('EVT_wp_user', $wp_user);
648
+	}
649
+
650
+
651
+	/**
652
+	 * @param $default_registration_status
653
+	 * @throws EE_Error
654
+	 */
655
+	public function set_default_registration_status($default_registration_status)
656
+	{
657
+		$this->set('EVT_default_registration_status', $default_registration_status);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param $donations
663
+	 * @throws EE_Error
664
+	 */
665
+	public function set_donations($donations)
666
+	{
667
+		$this->set('EVT_donations', $donations);
668
+	}
669
+
670
+
671
+	/**
672
+	 * Adds a venue to this event
673
+	 *
674
+	 * @param int|EE_Venue /int $venue_id_or_obj
675
+	 * @return EE_Base_Class|EE_Venue
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 */
679
+	public function add_venue($venue_id_or_obj): EE_Venue
680
+	{
681
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
682
+	}
683
+
684
+
685
+	/**
686
+	 * Removes a venue from the event
687
+	 *
688
+	 * @param EE_Venue /int $venue_id_or_obj
689
+	 * @return EE_Base_Class|EE_Venue
690
+	 * @throws EE_Error
691
+	 * @throws ReflectionException
692
+	 */
693
+	public function remove_venue($venue_id_or_obj): EE_Venue
694
+	{
695
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
696
+	}
697
+
698
+
699
+	/**
700
+	 * Gets the venue related to the event. May provide additional $query_params if desired
701
+	 *
702
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
703
+	 * @return int
704
+	 * @throws EE_Error
705
+	 * @throws ReflectionException
706
+	 */
707
+	public function venue_ID(array $query_params = array()): int
708
+	{
709
+		$venue = $this->get_first_related('Venue', $query_params);
710
+		return $venue instanceof EE_Venue ? $venue->ID() : 0;
711
+	}
712
+
713
+
714
+	/**
715
+	 * Gets the venue related to the event. May provide additional $query_params if desired
716
+	 *
717
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
718
+	 * @return EE_Base_Class|EE_Venue
719
+	 * @throws EE_Error
720
+	 * @throws ReflectionException
721
+	 */
722
+	public function venue(array $query_params = array())
723
+	{
724
+		return $this->get_first_related('Venue', $query_params);
725
+	}
726
+
727
+
728
+	/**
729
+	 * @param array $query_params
730
+	 * @return EE_Base_Class[]|EE_Venue[]
731
+	 * @throws EE_Error
732
+	 * @throws ReflectionException
733
+	 * @deprecated $VID:$
734
+	 */
735
+	public function venues(array $query_params = array()): array
736
+	{
737
+		return (array) $this->venue($query_params);
738
+	}
739
+
740
+
741
+	/**
742
+	 * check if event id is present and if event is published
743
+	 *
744
+	 * @access public
745
+	 * @return boolean true yes, false no
746
+	 * @throws EE_Error
747
+	 */
748
+	private function _has_ID_and_is_published()
749
+	{
750
+		// first check if event id is present and not NULL,
751
+		// then check if this event is published (or any of the equivalent "published" statuses)
752
+		return
753
+			$this->ID() && $this->ID() !== null
754
+			&& (
755
+				$this->status() === 'publish'
756
+				|| $this->status() === EEM_Event::sold_out
757
+				|| $this->status() === EEM_Event::postponed
758
+				|| $this->status() === EEM_Event::cancelled
759
+			);
760
+	}
761
+
762
+
763
+	/**
764
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
765
+	 *
766
+	 * @access public
767
+	 * @return boolean true yes, false no
768
+	 * @throws EE_Error
769
+	 */
770
+	public function is_upcoming()
771
+	{
772
+		// check if event id is present and if this event is published
773
+		if ($this->is_inactive()) {
774
+			return false;
775
+		}
776
+		// set initial value
777
+		$upcoming = false;
778
+		// next let's get all datetimes and loop through them
779
+		$datetimes = $this->datetimes_in_chronological_order();
780
+		foreach ($datetimes as $datetime) {
781
+			if ($datetime instanceof EE_Datetime) {
782
+				// if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
783
+				if ($datetime->is_expired()) {
784
+					continue;
785
+				}
786
+				// if this dtt is active then we return false.
787
+				if ($datetime->is_active()) {
788
+					return false;
789
+				}
790
+				// otherwise let's check upcoming status
791
+				$upcoming = $datetime->is_upcoming();
792
+			}
793
+		}
794
+		return $upcoming;
795
+	}
796
+
797
+
798
+	/**
799
+	 * @return bool
800
+	 * @throws EE_Error
801
+	 */
802
+	public function is_active()
803
+	{
804
+		// check if event id is present and if this event is published
805
+		if ($this->is_inactive()) {
806
+			return false;
807
+		}
808
+		// set initial value
809
+		$active = false;
810
+		// next let's get all datetimes and loop through them
811
+		$datetimes = $this->datetimes_in_chronological_order();
812
+		foreach ($datetimes as $datetime) {
813
+			if ($datetime instanceof EE_Datetime) {
814
+				// if this dtt is expired then we continue cause one of the other datetimes might be active.
815
+				if ($datetime->is_expired()) {
816
+					continue;
817
+				}
818
+				// if this dtt is upcoming then we return false.
819
+				if ($datetime->is_upcoming()) {
820
+					return false;
821
+				}
822
+				// otherwise let's check active status
823
+				$active = $datetime->is_active();
824
+			}
825
+		}
826
+		return $active;
827
+	}
828
+
829
+
830
+	/**
831
+	 * @return bool
832
+	 * @throws EE_Error
833
+	 */
834
+	public function is_expired()
835
+	{
836
+		// check if event id is present and if this event is published
837
+		if ($this->is_inactive()) {
838
+			return false;
839
+		}
840
+		// set initial value
841
+		$expired = false;
842
+		// first let's get all datetimes and loop through them
843
+		$datetimes = $this->datetimes_in_chronological_order();
844
+		foreach ($datetimes as $datetime) {
845
+			if ($datetime instanceof EE_Datetime) {
846
+				// if this dtt is upcoming or active then we return false.
847
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
848
+					return false;
849
+				}
850
+				// otherwise let's check active status
851
+				$expired = $datetime->is_expired();
852
+			}
853
+		}
854
+		return $expired;
855
+	}
856
+
857
+
858
+	/**
859
+	 * @return bool
860
+	 * @throws EE_Error
861
+	 */
862
+	public function is_inactive()
863
+	{
864
+		// check if event id is present and if this event is published
865
+		if ($this->_has_ID_and_is_published()) {
866
+			return false;
867
+		}
868
+		return true;
869
+	}
870
+
871
+
872
+	/**
873
+	 * calculate spaces remaining based on "saleable" tickets
874
+	 *
875
+	 * @param array $tickets
876
+	 * @param bool  $filtered
877
+	 * @return int|float
878
+	 * @throws EE_Error
879
+	 * @throws DomainException
880
+	 * @throws UnexpectedEntityException
881
+	 */
882
+	public function spaces_remaining($tickets = array(), $filtered = true)
883
+	{
884
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
885
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
886
+		return $filtered
887
+			? apply_filters(
888
+				'FHEE_EE_Event__spaces_remaining',
889
+				$spaces_remaining,
890
+				$this,
891
+				$tickets
892
+			)
893
+			: $spaces_remaining;
894
+	}
895
+
896
+
897
+	/**
898
+	 *    perform_sold_out_status_check
899
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
900
+	 *    available... if NOT, then the event status will get toggled to 'sold_out'
901
+	 *
902
+	 * @return bool    return the ACTUAL sold out state.
903
+	 * @throws EE_Error
904
+	 * @throws DomainException
905
+	 * @throws UnexpectedEntityException
906
+	 */
907
+	public function perform_sold_out_status_check()
908
+	{
909
+		// get all tickets
910
+		$tickets = $this->tickets(
911
+			array(
912
+				'default_where_conditions' => 'none',
913
+				'order_by' => array('TKT_qty' => 'ASC'),
914
+			)
915
+		);
916
+		$all_expired = true;
917
+		foreach ($tickets as $ticket) {
918
+			if (! $ticket->is_expired()) {
919
+				$all_expired = false;
920
+				break;
921
+			}
922
+		}
923
+		// if all the tickets are just expired, then don't update the event status to sold out
924
+		if ($all_expired) {
925
+			return true;
926
+		}
927
+		$spaces_remaining = $this->spaces_remaining($tickets);
928
+		if ($spaces_remaining < 1) {
929
+			if ($this->status() !== EEM_Event::post_status_private) {
930
+				$this->set_status(EEM_Event::sold_out);
931
+				$this->save();
932
+			}
933
+			$sold_out = true;
934
+		} else {
935
+			$sold_out = false;
936
+			// was event previously marked as sold out ?
937
+			if ($this->status() === EEM_Event::sold_out) {
938
+				// revert status to previous value, if it was set
939
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
940
+				if ($previous_event_status) {
941
+					$this->set_status($previous_event_status);
942
+					$this->save();
943
+				}
944
+			}
945
+		}
946
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
947
+		return $sold_out;
948
+	}
949
+
950
+
951
+	/**
952
+	 * This returns the total remaining spaces for sale on this event.
953
+	 *
954
+	 * @uses EE_Event::total_available_spaces()
955
+	 * @return float|int
956
+	 * @throws EE_Error
957
+	 * @throws DomainException
958
+	 * @throws UnexpectedEntityException
959
+	 */
960
+	public function spaces_remaining_for_sale()
961
+	{
962
+		return $this->total_available_spaces(true);
963
+	}
964
+
965
+
966
+	/**
967
+	 * This returns the total spaces available for an event
968
+	 * while considering all the qtys on the tickets and the reg limits
969
+	 * on the datetimes attached to this event.
970
+	 *
971
+	 * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
972
+	 *                              If this is false, then we return the most tickets that could ever be sold
973
+	 *                              for this event with the datetime and tickets setup on the event under optimal
974
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
975
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
976
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
977
+	 *                              sold out, the more accurate the "live" total is.
978
+	 * @return float|int
979
+	 * @throws EE_Error
980
+	 * @throws DomainException
981
+	 * @throws UnexpectedEntityException
982
+	 */
983
+	public function total_available_spaces($consider_sold = false)
984
+	{
985
+		$spaces_available = $consider_sold
986
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
987
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
988
+		return apply_filters(
989
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
990
+			$spaces_available,
991
+			$this,
992
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
993
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
994
+		);
995
+	}
996
+
997
+
998
+	/**
999
+	 * Checks if the event is set to sold out
1000
+	 *
1001
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
1002
+	 *                      actual status but also to flip the status if necessary to sold
1003
+	 *                      out If false, we just check the existing status of the event
1004
+	 * @return boolean
1005
+	 * @throws EE_Error
1006
+	 */
1007
+	public function is_sold_out($actual = false)
1008
+	{
1009
+		if (! $actual) {
1010
+			return $this->status() === EEM_Event::sold_out;
1011
+		}
1012
+		return $this->perform_sold_out_status_check();
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * Checks if the event is marked as postponed
1018
+	 *
1019
+	 * @return boolean
1020
+	 */
1021
+	public function is_postponed()
1022
+	{
1023
+		return $this->status() === EEM_Event::postponed;
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * Checks if the event is marked as cancelled
1029
+	 *
1030
+	 * @return boolean
1031
+	 */
1032
+	public function is_cancelled()
1033
+	{
1034
+		return $this->status() === EEM_Event::cancelled;
1035
+	}
1036
+
1037
+
1038
+	/**
1039
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1040
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1041
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1042
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1043
+	 * the event is considered expired.
1044
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1045
+	 * status set on the EVENT when it is not published and thus is done
1046
+	 *
1047
+	 * @param bool $reset
1048
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1049
+	 * @throws EE_Error
1050
+	 */
1051
+	public function get_active_status($reset = false)
1052
+	{
1053
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1054
+		if (! empty($this->_active_status) && ! $reset) {
1055
+			return $this->_active_status;
1056
+		}
1057
+		// first check if event id is present on this object
1058
+		if (! $this->ID()) {
1059
+			return false;
1060
+		}
1061
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1062
+		// if event is published:
1063
+		if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1064
+			// active?
1065
+			if (
1066
+				EEM_Datetime::instance()->get_datetime_count_for_status(
1067
+					EE_Datetime::active,
1068
+					$where_params_for_event
1069
+				) > 0
1070
+			) {
1071
+				$this->_active_status = EE_Datetime::active;
1072
+			} else {
1073
+				// upcoming?
1074
+				if (
1075
+					EEM_Datetime::instance()->get_datetime_count_for_status(
1076
+						EE_Datetime::upcoming,
1077
+						$where_params_for_event
1078
+					) > 0
1079
+				) {
1080
+					$this->_active_status = EE_Datetime::upcoming;
1081
+				} else {
1082
+					// expired?
1083
+					if (
1084
+						EEM_Datetime::instance()->get_datetime_count_for_status(
1085
+							EE_Datetime::expired,
1086
+							$where_params_for_event
1087
+						) > 0
1088
+					) {
1089
+						$this->_active_status = EE_Datetime::expired;
1090
+					} else {
1091
+						// it would be odd if things make it this far because it basically means there are no datetime's
1092
+						// attached to the event.  So in this case it will just be considered inactive.
1093
+						$this->_active_status = EE_Datetime::inactive;
1094
+					}
1095
+				}
1096
+			}
1097
+		} else {
1098
+			// the event is not published, so let's just set it's active status according to its' post status
1099
+			switch ($this->status()) {
1100
+				case EEM_Event::sold_out:
1101
+					$this->_active_status = EE_Datetime::sold_out;
1102
+					break;
1103
+				case EEM_Event::cancelled:
1104
+					$this->_active_status = EE_Datetime::cancelled;
1105
+					break;
1106
+				case EEM_Event::postponed:
1107
+					$this->_active_status = EE_Datetime::postponed;
1108
+					break;
1109
+				default:
1110
+					$this->_active_status = EE_Datetime::inactive;
1111
+			}
1112
+		}
1113
+		return $this->_active_status;
1114
+	}
1115
+
1116
+
1117
+	/**
1118
+	 *    pretty_active_status
1119
+	 *
1120
+	 * @access public
1121
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1122
+	 * @return mixed void|string
1123
+	 * @throws EE_Error
1124
+	 */
1125
+	public function pretty_active_status($echo = true)
1126
+	{
1127
+		$active_status = $this->get_active_status();
1128
+		$status = '<span class="ee-status event-active-status-'
1129
+				  . $active_status
1130
+				  . '">'
1131
+				  . EEH_Template::pretty_status($active_status, false, 'sentence')
1132
+				  . '</span>';
1133
+		if ($echo) {
1134
+			echo $status;
1135
+			return '';
1136
+		}
1137
+		return $status;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * @return bool|int
1143
+	 * @throws EE_Error
1144
+	 */
1145
+	public function get_number_of_tickets_sold()
1146
+	{
1147
+		$tkt_sold = 0;
1148
+		if (! $this->ID()) {
1149
+			return 0;
1150
+		}
1151
+		$datetimes = $this->datetimes();
1152
+		foreach ($datetimes as $datetime) {
1153
+			if ($datetime instanceof EE_Datetime) {
1154
+				$tkt_sold += $datetime->sold();
1155
+			}
1156
+		}
1157
+		return $tkt_sold;
1158
+	}
1159
+
1160
+
1161
+	/**
1162
+	 * This just returns a count of all the registrations for this event
1163
+	 *
1164
+	 * @access  public
1165
+	 * @return int
1166
+	 * @throws EE_Error
1167
+	 */
1168
+	public function get_count_of_all_registrations()
1169
+	{
1170
+		return EEM_Event::instance()->count_related($this, 'Registration');
1171
+	}
1172
+
1173
+
1174
+	/**
1175
+	 * This returns the ticket with the earliest start time that is
1176
+	 * available for this event (across all datetimes attached to the event)
1177
+	 *
1178
+	 * @return EE_Base_Class|EE_Ticket|null
1179
+	 * @throws EE_Error
1180
+	 */
1181
+	public function get_ticket_with_earliest_start_time()
1182
+	{
1183
+		$where['Datetime.EVT_ID'] = $this->ID();
1184
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1185
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1186
+	}
1187
+
1188
+
1189
+	/**
1190
+	 * This returns the ticket with the latest end time that is available
1191
+	 * for this event (across all datetimes attached to the event)
1192
+	 *
1193
+	 * @return EE_Base_Class|EE_Ticket|null
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public function get_ticket_with_latest_end_time()
1197
+	{
1198
+		$where['Datetime.EVT_ID'] = $this->ID();
1199
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1200
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * This returns the number of different ticket types currently on sale for this event.
1206
+	 *
1207
+	 * @return int
1208
+	 * @throws EE_Error
1209
+	 */
1210
+	public function countTicketsOnSale()
1211
+	{
1212
+		$where = array(
1213
+			'Datetime.EVT_ID' => $this->ID(),
1214
+			'TKT_start_date'  => array('<', time()),
1215
+			'TKT_end_date'    => array('>', time()),
1216
+		);
1217
+		return EEM_Ticket::instance()->count(array($where));
1218
+	}
1219
+
1220
+
1221
+	/**
1222
+	 * This returns whether there are any tickets on sale for this event.
1223
+	 *
1224
+	 * @return bool true = YES tickets on sale.
1225
+	 * @throws EE_Error
1226
+	 */
1227
+	public function tickets_on_sale()
1228
+	{
1229
+		return $this->countTicketsOnSale() > 0;
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1235
+	 * to check for an external URL first
1236
+	 *
1237
+	 * @return string
1238
+	 * @throws EE_Error
1239
+	 */
1240
+	public function get_permalink()
1241
+	{
1242
+		if ($this->external_url()) {
1243
+			return $this->external_url();
1244
+		}
1245
+		return parent::get_permalink();
1246
+	}
1247
+
1248
+
1249
+	/**
1250
+	 * Gets the first term for 'espresso_event_categories' we can find
1251
+	 *
1252
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1253
+	 * @return EE_Base_Class|EE_Term|null
1254
+	 * @throws EE_Error
1255
+	 */
1256
+	public function first_event_category($query_params = array())
1257
+	{
1258
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1259
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1260
+		return EEM_Term::instance()->get_one($query_params);
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 * Gets all terms for 'espresso_event_categories' we can find
1266
+	 *
1267
+	 * @param array $query_params
1268
+	 * @return EE_Base_Class[]|EE_Term[]
1269
+	 * @throws EE_Error
1270
+	 */
1271
+	public function get_all_event_categories($query_params = array())
1272
+	{
1273
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1274
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1275
+		return EEM_Term::instance()->get_all($query_params);
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * Adds a question group to this event
1281
+	 *
1282
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1283
+	 * @param bool $for_primary if true, the question group will be added for the primary
1284
+	 *                                           registrant, if false will be added for others. default: false
1285
+	 * @return EE_Base_Class|EE_Question_Group
1286
+	 * @throws EE_Error
1287
+	 * @throws InvalidArgumentException
1288
+	 * @throws InvalidDataTypeException
1289
+	 * @throws InvalidInterfaceException
1290
+	 * @throws ReflectionException
1291
+	 */
1292
+	public function add_question_group($question_group_id_or_obj, $for_primary = false)
1293
+	{
1294
+		// If the row already exists, it will be updated. If it doesn't, it will be inserted.
1295
+		// That's in EE_HABTM_Relation::add_relation_to().
1296
+		return $this->_add_relation_to(
1297
+			$question_group_id_or_obj,
1298
+			'Question_Group',
1299
+			[
1300
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1301
+			]
1302
+		);
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 * Removes a question group from the event
1308
+	 *
1309
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1310
+	 * @param bool $for_primary if true, the question group will be removed from the primary
1311
+	 *                                           registrant, if false will be removed from others. default: false
1312
+	 * @return EE_Base_Class|EE_Question_Group
1313
+	 * @throws EE_Error
1314
+	 * @throws InvalidArgumentException
1315
+	 * @throws ReflectionException
1316
+	 * @throws InvalidDataTypeException
1317
+	 * @throws InvalidInterfaceException
1318
+	 */
1319
+	public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1320
+	{
1321
+		// If the question group is used for the other type (primary or additional)
1322
+		// then just update it. If not, delete it outright.
1323
+		$existing_relation = $this->get_first_related(
1324
+			'Event_Question_Group',
1325
+			[
1326
+				[
1327
+					'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1328
+				]
1329
+			]
1330
+		);
1331
+		$field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1332
+		$other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1333
+		if ($existing_relation->get($other_field) === false) {
1334
+			// Delete it. It's now no longer for primary or additional question groups.
1335
+			return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1336
+		}
1337
+		// Just update it. They'll still use this question group for the other category
1338
+		$existing_relation->save(
1339
+			[
1340
+				$field_to_update => false
1341
+			]
1342
+		);
1343
+	}
1344
+
1345
+
1346
+	/**
1347
+	 * Gets all the question groups, ordering them by QSG_order ascending
1348
+	 *
1349
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1350
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1351
+	 * @throws EE_Error
1352
+	 */
1353
+	public function question_groups($query_params = array())
1354
+	{
1355
+		$query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1356
+		return $this->get_many_related('Question_Group', $query_params);
1357
+	}
1358
+
1359
+
1360
+	/**
1361
+	 * Implementation for EEI_Has_Icon interface method.
1362
+	 *
1363
+	 * @see EEI_Visual_Representation for comments
1364
+	 * @return string
1365
+	 */
1366
+	public function get_icon()
1367
+	{
1368
+		return '<span class="dashicons dashicons-flag"></span>';
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 * Implementation for EEI_Admin_Links interface method.
1374
+	 *
1375
+	 * @see EEI_Admin_Links for comments
1376
+	 * @return string
1377
+	 * @throws EE_Error
1378
+	 */
1379
+	public function get_admin_details_link()
1380
+	{
1381
+		return $this->get_admin_edit_link();
1382
+	}
1383
+
1384
+
1385
+	/**
1386
+	 * Implementation for EEI_Admin_Links interface method.
1387
+	 *
1388
+	 * @see EEI_Admin_Links for comments
1389
+	 * @return string
1390
+	 * @throws EE_Error
1391
+	 */
1392
+	public function get_admin_edit_link()
1393
+	{
1394
+		return EEH_URL::add_query_args_and_nonce(
1395
+			array(
1396
+				'page'   => 'espresso_events',
1397
+				'action' => 'edit',
1398
+				'post'   => $this->ID(),
1399
+			),
1400
+			admin_url('admin.php')
1401
+		);
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * Implementation for EEI_Admin_Links interface method.
1407
+	 *
1408
+	 * @see EEI_Admin_Links for comments
1409
+	 * @return string
1410
+	 */
1411
+	public function get_admin_settings_link()
1412
+	{
1413
+		return EEH_URL::add_query_args_and_nonce(
1414
+			array(
1415
+				'page'   => 'espresso_events',
1416
+				'action' => 'default_event_settings',
1417
+			),
1418
+			admin_url('admin.php')
1419
+		);
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * Implementation for EEI_Admin_Links interface method.
1425
+	 *
1426
+	 * @see EEI_Admin_Links for comments
1427
+	 * @return string
1428
+	 */
1429
+	public function get_admin_overview_link()
1430
+	{
1431
+		return EEH_URL::add_query_args_and_nonce(
1432
+			array(
1433
+				'page'   => 'espresso_events',
1434
+				'action' => 'default',
1435
+			),
1436
+			admin_url('admin.php')
1437
+		);
1438
+	}
1439
+
1440
+
1441
+	/**
1442
+	 * @return string|null
1443
+	 * @throws EE_Error
1444
+	 * @throws ReflectionException
1445
+	 */
1446
+	public function registrationFormUuid(): ?string
1447
+	{
1448
+		return $this->get('FSC_UUID');
1449
+	}
1450
+
1451
+
1452
+	/**
1453
+	 * Gets all the form sections for this event
1454
+	 *
1455
+	 * @return EE_Base_Class[]|EE_Form_Section[]
1456
+	 * @throws EE_Error
1457
+	 * @throws ReflectionException
1458
+	 */
1459
+	public function registrationForm()
1460
+	{
1461
+		$FSC_UUID = $this->registrationFormUuid();
1462
+
1463
+		if (empty($FSC_UUID)) {
1464
+			return [];
1465
+		}
1466
+
1467
+		return EEM_Form_Section::instance()->get_all([
1468
+			[
1469
+				'OR' => [
1470
+					'FSC_UUID'      => $FSC_UUID, // top level form
1471
+					'FSC_belongsTo' => $FSC_UUID, // child form sections
1472
+				]
1473
+				],
1474
+			'order_by' => ['FSC_order' => 'ASC'],
1475
+		]);
1476
+	}
1477
+
1478
+
1479
+	/**
1480
+	 * @param string $UUID
1481
+	 * @throws EE_Error
1482
+	 */
1483
+	public function setRegistrationFormUuid(string $UUID): void
1484
+	{
1485
+		if (! Cuid::isCuid($UUID)) {
1486
+			throw new InvalidArgumentException(
1487
+				sprintf(
1488
+				/* translators: 1: UUID value, 2: UUID generator function. */
1489
+					esc_html__(
1490
+						'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1491
+						'event_espresso'
1492
+					),
1493
+					$UUID,
1494
+					'`Cuid::cuid()`'
1495
+				)
1496
+			);
1497
+		}
1498
+		$this->set('FSC_UUID', $UUID);
1499
+	}
1500 1500
 }
Please login to merge, or discard this patch.