Completed
Branch RELEASE (416965)
by
unknown
12:55 queued 13s
created
core/domain/entities/shortcodes/EspressoEventAttendees.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
         $attributes['limit'] = (int) $attributes['limit'];
117 117
         $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
118 118
         // don't display on archives unless 'display_on_archives' is true
119
-        if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
119
+        if ($attributes['limit'] === 0 || ( ! $display_on_archives && is_archive())) {
120 120
             return '';
121 121
         }
122 122
         try {
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
      */
318 318
     private function getDatetime(array $attributes)
319 319
     {
320
-        if (! empty($attributes['datetime_id'])) {
320
+        if ( ! empty($attributes['datetime_id'])) {
321 321
             $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
322 322
             if ($datetime instanceof EE_Datetime) {
323 323
                 return $datetime;
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
      */
338 338
     private function getTicket(array $attributes)
339 339
     {
340
-        if (! empty($attributes['ticket_id'])) {
340
+        if ( ! empty($attributes['ticket_id'])) {
341 341
             $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
342 342
             if ($ticket instanceof EE_Ticket) {
343 343
                 return $ticket;
@@ -354,7 +354,7 @@  discard block
 block discarded – undo
354 354
     private function setAdditionalQueryParams(array $attributes)
355 355
     {
356 356
         $reg_status_array = EEM_Registration::reg_status_array();
357
-        if (isset($reg_status_array[ $attributes['status'] ])) {
357
+        if (isset($reg_status_array[$attributes['status']])) {
358 358
             $this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
359 359
         }
360 360
         if (absint($attributes['limit'])) {
Please login to merge, or discard this patch.
Indentation   +313 added lines, -313 removed lines patch added patch discarded remove patch
@@ -32,342 +32,342 @@
 block discarded – undo
32 32
  */
33 33
 class EspressoEventAttendees extends EspressoShortcode
34 34
 {
35
-    private $query_params = array(
36
-        0 => array(),
37
-    );
35
+	private $query_params = array(
36
+		0 => array(),
37
+	);
38 38
 
39
-    private $template_args = array(
40
-        'contacts' => array(),
41
-        'event'    => null,
42
-        'datetime' => null,
43
-        'ticket'   => null,
44
-    );
39
+	private $template_args = array(
40
+		'contacts' => array(),
41
+		'event'    => null,
42
+		'datetime' => null,
43
+		'ticket'   => null,
44
+	);
45 45
 
46
-    /**
47
-     * the actual shortcode tag that gets registered with WordPress
48
-     *
49
-     * @return string
50
-     */
51
-    public function getTag()
52
-    {
53
-        return 'ESPRESSO_EVENT_ATTENDEES';
54
-    }
46
+	/**
47
+	 * the actual shortcode tag that gets registered with WordPress
48
+	 *
49
+	 * @return string
50
+	 */
51
+	public function getTag()
52
+	{
53
+		return 'ESPRESSO_EVENT_ATTENDEES';
54
+	}
55 55
 
56 56
 
57
-    /**
58
-     * the time in seconds to cache the results of the processShortcode() method
59
-     * 0 means the processShortcode() results will NOT be cached at all
60
-     *
61
-     * @return int
62
-     */
63
-    public function cacheExpiration()
64
-    {
65
-        return 0;
66
-    }
57
+	/**
58
+	 * the time in seconds to cache the results of the processShortcode() method
59
+	 * 0 means the processShortcode() results will NOT be cached at all
60
+	 *
61
+	 * @return int
62
+	 */
63
+	public function cacheExpiration()
64
+	{
65
+		return 0;
66
+	}
67 67
 
68 68
 
69
-    /**
70
-     * a place for adding any initialization code that needs to run prior to wp_header().
71
-     * this may be required for shortcodes that utilize a corresponding module,
72
-     * and need to enqueue assets for that module
73
-     *
74
-     * @return void
75
-     */
76
-    public function initializeShortcode()
77
-    {
78
-        $this->shortcodeHasBeenInitialized();
79
-    }
69
+	/**
70
+	 * a place for adding any initialization code that needs to run prior to wp_header().
71
+	 * this may be required for shortcodes that utilize a corresponding module,
72
+	 * and need to enqueue assets for that module
73
+	 *
74
+	 * @return void
75
+	 */
76
+	public function initializeShortcode()
77
+	{
78
+		$this->shortcodeHasBeenInitialized();
79
+	}
80 80
 
81 81
 
82
-    /**
83
-     * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
84
-     *  [ESPRESSO_EVENT_ATTENDEES]
85
-     *  - defaults to attendees for earliest active event, or earliest upcoming event.
86
-     *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
87
-     *  - attendees for specific event.
88
-     *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
89
-     *  - attendees for a specific datetime.
90
-     *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
91
-     *  - attendees for a specific ticket.
92
-     *  [ESPRESSO_EVENT_ATTENDEES status=all]
93
-     *  - specific registration status (use status id) or all for all attendees regardless of status.
94
-     *  Note default is to only return approved attendees
95
-     *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
96
-     *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
97
-     *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
98
-     *  - default is to not display attendees list on archive pages.
99
-     * Note: because of the relationship between event_id, ticket_id, and datetime_id:
100
-     * If more than one of those params is included, then preference is given to the following:
101
-     *  - event_id is used whenever its present and any others are ignored.
102
-     *  - if no event_id then datetime is used whenever its present and any others are ignored.
103
-     *  - otherwise ticket_id is used if present.
104
-     *
105
-     * @param array|string $attributes
106
-     * @return string
107
-     * @throws EE_Error
108
-     * @throws InvalidDataTypeException
109
-     * @throws InvalidInterfaceException
110
-     * @throws InvalidArgumentException
111
-     * @throws DomainException
112
-     * @throws ReflectionException
113
-     */
114
-    public function processShortcode($attributes = array())
115
-    {
116
-        // grab attributes and merge with defaults
117
-        $attributes = $this->getAttributes((array) $attributes);
118
-        $attributes['limit'] = (int) $attributes['limit'];
119
-        $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
120
-        // don't display on archives unless 'display_on_archives' is true
121
-        if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
122
-            return '';
123
-        }
124
-        try {
125
-            $this->setBaseTemplateArguments($attributes);
126
-            $this->validateEntities($attributes);
127
-            $this->setBaseQueryParams();
128
-        } catch (EntityNotFoundException $e) {
129
-            if (WP_DEBUG) {
130
-                return '<div class="important-notice ee-error">'
131
-                       . $e->getMessage()
132
-                       . '</div>';
133
-            }
134
-            return '';
135
-        }
136
-        $this->setAdditionalQueryParams($attributes);
137
-        // get contacts!
138
-        $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
139
-        // all set let's load up the template and return.
140
-        return EEH_Template::locate_template(
141
-            'loop-espresso_event_attendees.php',
142
-            $this->template_args
143
-        );
144
-    }
82
+	/**
83
+	 * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
84
+	 *  [ESPRESSO_EVENT_ATTENDEES]
85
+	 *  - defaults to attendees for earliest active event, or earliest upcoming event.
86
+	 *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
87
+	 *  - attendees for specific event.
88
+	 *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
89
+	 *  - attendees for a specific datetime.
90
+	 *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
91
+	 *  - attendees for a specific ticket.
92
+	 *  [ESPRESSO_EVENT_ATTENDEES status=all]
93
+	 *  - specific registration status (use status id) or all for all attendees regardless of status.
94
+	 *  Note default is to only return approved attendees
95
+	 *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
96
+	 *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
97
+	 *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
98
+	 *  - default is to not display attendees list on archive pages.
99
+	 * Note: because of the relationship between event_id, ticket_id, and datetime_id:
100
+	 * If more than one of those params is included, then preference is given to the following:
101
+	 *  - event_id is used whenever its present and any others are ignored.
102
+	 *  - if no event_id then datetime is used whenever its present and any others are ignored.
103
+	 *  - otherwise ticket_id is used if present.
104
+	 *
105
+	 * @param array|string $attributes
106
+	 * @return string
107
+	 * @throws EE_Error
108
+	 * @throws InvalidDataTypeException
109
+	 * @throws InvalidInterfaceException
110
+	 * @throws InvalidArgumentException
111
+	 * @throws DomainException
112
+	 * @throws ReflectionException
113
+	 */
114
+	public function processShortcode($attributes = array())
115
+	{
116
+		// grab attributes and merge with defaults
117
+		$attributes = $this->getAttributes((array) $attributes);
118
+		$attributes['limit'] = (int) $attributes['limit'];
119
+		$display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
120
+		// don't display on archives unless 'display_on_archives' is true
121
+		if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
122
+			return '';
123
+		}
124
+		try {
125
+			$this->setBaseTemplateArguments($attributes);
126
+			$this->validateEntities($attributes);
127
+			$this->setBaseQueryParams();
128
+		} catch (EntityNotFoundException $e) {
129
+			if (WP_DEBUG) {
130
+				return '<div class="important-notice ee-error">'
131
+					   . $e->getMessage()
132
+					   . '</div>';
133
+			}
134
+			return '';
135
+		}
136
+		$this->setAdditionalQueryParams($attributes);
137
+		// get contacts!
138
+		$this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
139
+		// all set let's load up the template and return.
140
+		return EEH_Template::locate_template(
141
+			'loop-espresso_event_attendees.php',
142
+			$this->template_args
143
+		);
144
+	}
145 145
 
146 146
 
147
-    /**
148
-     * merge incoming attributes with filtered defaults
149
-     *
150
-     * @param array $attributes
151
-     * @return array
152
-     */
153
-    private function getAttributes(array $attributes)
154
-    {
155
-        return (array) apply_filters(
156
-            'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
157
-            $attributes + array(
158
-                'event_id'            => null,
159
-                'datetime_id'         => null,
160
-                'ticket_id'           => null,
161
-                'status'              => EEM_Registration::status_id_approved,
162
-                'show_gravatar'       => false,
163
-                'display_on_archives' => false,
164
-                'limit'               => 999,
165
-            )
166
-        );
167
-    }
147
+	/**
148
+	 * merge incoming attributes with filtered defaults
149
+	 *
150
+	 * @param array $attributes
151
+	 * @return array
152
+	 */
153
+	private function getAttributes(array $attributes)
154
+	{
155
+		return (array) apply_filters(
156
+			'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
157
+			$attributes + array(
158
+				'event_id'            => null,
159
+				'datetime_id'         => null,
160
+				'ticket_id'           => null,
161
+				'status'              => EEM_Registration::status_id_approved,
162
+				'show_gravatar'       => false,
163
+				'display_on_archives' => false,
164
+				'limit'               => 999,
165
+			)
166
+		);
167
+	}
168 168
 
169 169
 
170
-    /**
171
-     * Set all the base template arguments from the incoming attributes.
172
-     * * Note: because of the relationship between event_id, ticket_id, and datetime_id:
173
-     * If more than one of those params is included, then preference is given to the following:
174
-     *  - event_id is used whenever its present and any others are ignored.
175
-     *  - if no event_id then datetime is used whenever its present and any others are ignored.
176
-     *  - otherwise ticket_id is used if present.
177
-     *
178
-     * @param array $attributes
179
-     * @throws EE_Error
180
-     * @throws InvalidDataTypeException
181
-     * @throws InvalidInterfaceException
182
-     * @throws InvalidArgumentException
183
-     * @throws ReflectionException
184
-     */
185
-    private function setBaseTemplateArguments(array $attributes)
186
-    {
187
-        $this->template_args['show_gravatar'] = $attributes['show_gravatar'];
188
-        $this->template_args['event'] = $this->getEvent($attributes);
189
-        $this->template_args['datetime'] = empty($attributes['event_id'])
190
-            ? $this->getDatetime($attributes)
191
-            : null;
192
-        $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id'])
193
-            ? $this->getTicket($attributes)
194
-            : null;
195
-    }
170
+	/**
171
+	 * Set all the base template arguments from the incoming attributes.
172
+	 * * Note: because of the relationship between event_id, ticket_id, and datetime_id:
173
+	 * If more than one of those params is included, then preference is given to the following:
174
+	 *  - event_id is used whenever its present and any others are ignored.
175
+	 *  - if no event_id then datetime is used whenever its present and any others are ignored.
176
+	 *  - otherwise ticket_id is used if present.
177
+	 *
178
+	 * @param array $attributes
179
+	 * @throws EE_Error
180
+	 * @throws InvalidDataTypeException
181
+	 * @throws InvalidInterfaceException
182
+	 * @throws InvalidArgumentException
183
+	 * @throws ReflectionException
184
+	 */
185
+	private function setBaseTemplateArguments(array $attributes)
186
+	{
187
+		$this->template_args['show_gravatar'] = $attributes['show_gravatar'];
188
+		$this->template_args['event'] = $this->getEvent($attributes);
189
+		$this->template_args['datetime'] = empty($attributes['event_id'])
190
+			? $this->getDatetime($attributes)
191
+			: null;
192
+		$this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id'])
193
+			? $this->getTicket($attributes)
194
+			: null;
195
+	}
196 196
 
197 197
 
198
-    /**
199
-     * Validates the presence of entities for the given attribute values.
200
-     *
201
-     * @param array $attributes
202
-     * @throws EntityNotFoundException
203
-     */
204
-    private function validateEntities(array $attributes)
205
-    {
206
-        if (
207
-            ! $this->template_args['event'] instanceof EE_Event
208
-            || (
209
-                empty($attributes['event_id'])
210
-                && $attributes['datetime_id']
211
-                && ! $this->template_args['datetime'] instanceof EE_Datetime
212
-            )
213
-            || (
214
-                empty($attributes['event_id'])
215
-                && empty($attributes['datetime_id'])
216
-                && $attributes['ticket_id']
217
-                && ! $this->template_args['ticket'] instanceof EE_Ticket
218
-            )
219
-        ) {
220
-            throw new EntityNotFoundException(
221
-                '',
222
-                '',
223
-                esc_html__(
224
-                    'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.',
225
-                    'event_espresso'
226
-                )
227
-            );
228
-        }
229
-    }
198
+	/**
199
+	 * Validates the presence of entities for the given attribute values.
200
+	 *
201
+	 * @param array $attributes
202
+	 * @throws EntityNotFoundException
203
+	 */
204
+	private function validateEntities(array $attributes)
205
+	{
206
+		if (
207
+			! $this->template_args['event'] instanceof EE_Event
208
+			|| (
209
+				empty($attributes['event_id'])
210
+				&& $attributes['datetime_id']
211
+				&& ! $this->template_args['datetime'] instanceof EE_Datetime
212
+			)
213
+			|| (
214
+				empty($attributes['event_id'])
215
+				&& empty($attributes['datetime_id'])
216
+				&& $attributes['ticket_id']
217
+				&& ! $this->template_args['ticket'] instanceof EE_Ticket
218
+			)
219
+		) {
220
+			throw new EntityNotFoundException(
221
+				'',
222
+				'',
223
+				esc_html__(
224
+					'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.',
225
+					'event_espresso'
226
+				)
227
+			);
228
+		}
229
+	}
230 230
 
231 231
 
232
-    /**
233
-     * Sets the query params for the base query elements.
234
-     */
235
-    private function setBaseQueryParams()
236
-    {
237
-        switch (true) {
238
-            case $this->template_args['datetime'] instanceof EE_Datetime:
239
-                $this->query_params = array(
240
-                    0                          => array(
241
-                        'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(),
242
-                    ),
243
-                    'default_where_conditions' => 'this_model_only',
244
-                );
245
-                break;
246
-            case $this->template_args['ticket'] instanceof EE_Ticket:
247
-                $this->query_params[0] = array(
248
-                    'Registration.TKT_ID' => $this->template_args['ticket']->ID(),
249
-                );
250
-                break;
251
-            case $this->template_args['event'] instanceof EE_Event:
252
-                $this->query_params[0] = array(
253
-                    'Registration.EVT_ID' => $this->template_args['event']->ID(),
254
-                );
255
-                break;
256
-        }
257
-    }
232
+	/**
233
+	 * Sets the query params for the base query elements.
234
+	 */
235
+	private function setBaseQueryParams()
236
+	{
237
+		switch (true) {
238
+			case $this->template_args['datetime'] instanceof EE_Datetime:
239
+				$this->query_params = array(
240
+					0                          => array(
241
+						'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(),
242
+					),
243
+					'default_where_conditions' => 'this_model_only',
244
+				);
245
+				break;
246
+			case $this->template_args['ticket'] instanceof EE_Ticket:
247
+				$this->query_params[0] = array(
248
+					'Registration.TKT_ID' => $this->template_args['ticket']->ID(),
249
+				);
250
+				break;
251
+			case $this->template_args['event'] instanceof EE_Event:
252
+				$this->query_params[0] = array(
253
+					'Registration.EVT_ID' => $this->template_args['event']->ID(),
254
+				);
255
+				break;
256
+		}
257
+	}
258 258
 
259 259
 
260
-    /**
261
-     * @param array $attributes
262
-     * @return EE_Event|null
263
-     * @throws EE_Error
264
-     * @throws InvalidDataTypeException
265
-     * @throws InvalidInterfaceException
266
-     * @throws InvalidArgumentException
267
-     * @throws ReflectionException
268
-     */
269
-    private function getEvent(array $attributes)
270
-    {
271
-        switch (true) {
272
-            case ! empty($attributes['event_id']):
273
-                $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
274
-                break;
275
-            case ! empty($attributes['datetime_id']):
276
-                $event = EEM_Event::instance()->get_one(array(
277
-                    array(
278
-                        'Datetime.DTT_ID' => $attributes['datetime_id'],
279
-                    ),
280
-                ));
281
-                break;
282
-            case ! empty($attributes['ticket_id']):
283
-                $event = EEM_Event::instance()->get_one(array(
284
-                    array(
285
-                        'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'],
286
-                    ),
287
-                    'default_where_conditions' => 'none'
288
-                ));
289
-                break;
290
-            case is_espresso_event():
291
-                $event = EEH_Event_View::get_event();
292
-                break;
293
-            default:
294
-                // one last shot...
295
-                // try getting the earliest active event
296
-                $events = EEM_Event::instance()->get_active_events(array(
297
-                    'limit'    => 1,
298
-                    'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
299
-                ));
300
-                //  if none then get the next upcoming
301
-                $events = empty($events)
302
-                    ? EEM_Event::instance()->get_upcoming_events(array(
303
-                        'limit'    => 1,
304
-                        'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
305
-                    ))
306
-                    : $events;
307
-                $event = reset($events);
308
-        }
260
+	/**
261
+	 * @param array $attributes
262
+	 * @return EE_Event|null
263
+	 * @throws EE_Error
264
+	 * @throws InvalidDataTypeException
265
+	 * @throws InvalidInterfaceException
266
+	 * @throws InvalidArgumentException
267
+	 * @throws ReflectionException
268
+	 */
269
+	private function getEvent(array $attributes)
270
+	{
271
+		switch (true) {
272
+			case ! empty($attributes['event_id']):
273
+				$event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
274
+				break;
275
+			case ! empty($attributes['datetime_id']):
276
+				$event = EEM_Event::instance()->get_one(array(
277
+					array(
278
+						'Datetime.DTT_ID' => $attributes['datetime_id'],
279
+					),
280
+				));
281
+				break;
282
+			case ! empty($attributes['ticket_id']):
283
+				$event = EEM_Event::instance()->get_one(array(
284
+					array(
285
+						'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'],
286
+					),
287
+					'default_where_conditions' => 'none'
288
+				));
289
+				break;
290
+			case is_espresso_event():
291
+				$event = EEH_Event_View::get_event();
292
+				break;
293
+			default:
294
+				// one last shot...
295
+				// try getting the earliest active event
296
+				$events = EEM_Event::instance()->get_active_events(array(
297
+					'limit'    => 1,
298
+					'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
299
+				));
300
+				//  if none then get the next upcoming
301
+				$events = empty($events)
302
+					? EEM_Event::instance()->get_upcoming_events(array(
303
+						'limit'    => 1,
304
+						'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
305
+					))
306
+					: $events;
307
+				$event = reset($events);
308
+		}
309 309
 
310
-        return $event instanceof EE_Event ? $event : null;
311
-    }
310
+		return $event instanceof EE_Event ? $event : null;
311
+	}
312 312
 
313 313
 
314
-    /**
315
-     * @param array $attributes
316
-     * @return EE_Datetime|null
317
-     * @throws EE_Error
318
-     * @throws InvalidDataTypeException
319
-     * @throws InvalidInterfaceException
320
-     * @throws InvalidArgumentException
321
-     */
322
-    private function getDatetime(array $attributes)
323
-    {
324
-        if (! empty($attributes['datetime_id'])) {
325
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
326
-            if ($datetime instanceof EE_Datetime) {
327
-                return $datetime;
328
-            }
329
-        }
330
-        return null;
331
-    }
314
+	/**
315
+	 * @param array $attributes
316
+	 * @return EE_Datetime|null
317
+	 * @throws EE_Error
318
+	 * @throws InvalidDataTypeException
319
+	 * @throws InvalidInterfaceException
320
+	 * @throws InvalidArgumentException
321
+	 */
322
+	private function getDatetime(array $attributes)
323
+	{
324
+		if (! empty($attributes['datetime_id'])) {
325
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
326
+			if ($datetime instanceof EE_Datetime) {
327
+				return $datetime;
328
+			}
329
+		}
330
+		return null;
331
+	}
332 332
 
333 333
 
334
-    /**
335
-     * @param array $attributes
336
-     * @return EE_Base_Class|EE_Ticket|null
337
-     * @throws EE_Error
338
-     * @throws InvalidDataTypeException
339
-     * @throws InvalidInterfaceException
340
-     * @throws InvalidArgumentException
341
-     */
342
-    private function getTicket(array $attributes)
343
-    {
344
-        if (! empty($attributes['ticket_id'])) {
345
-            $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
346
-            if ($ticket instanceof EE_Ticket) {
347
-                return $ticket;
348
-            }
349
-        }
350
-        return null;
351
-    }
334
+	/**
335
+	 * @param array $attributes
336
+	 * @return EE_Base_Class|EE_Ticket|null
337
+	 * @throws EE_Error
338
+	 * @throws InvalidDataTypeException
339
+	 * @throws InvalidInterfaceException
340
+	 * @throws InvalidArgumentException
341
+	 */
342
+	private function getTicket(array $attributes)
343
+	{
344
+		if (! empty($attributes['ticket_id'])) {
345
+			$ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
346
+			if ($ticket instanceof EE_Ticket) {
347
+				return $ticket;
348
+			}
349
+		}
350
+		return null;
351
+	}
352 352
 
353 353
 
354
-    /**
355
-     * @param array $attributes
356
-     * @throws EE_Error
357
-     */
358
-    private function setAdditionalQueryParams(array $attributes)
359
-    {
360
-        $reg_status_array = EEM_Registration::reg_status_array();
361
-        if (isset($reg_status_array[ $attributes['status'] ])) {
362
-            $this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
363
-        }
364
-        if (absint($attributes['limit'])) {
365
-            $this->query_params['limit'] = $attributes['limit'];
366
-        }
367
-        $this->query_params['group_by'] = array('ATT_ID');
368
-        $this->query_params['order_by'] = (array) apply_filters(
369
-            'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
370
-            array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
371
-        );
372
-    }
354
+	/**
355
+	 * @param array $attributes
356
+	 * @throws EE_Error
357
+	 */
358
+	private function setAdditionalQueryParams(array $attributes)
359
+	{
360
+		$reg_status_array = EEM_Registration::reg_status_array();
361
+		if (isset($reg_status_array[ $attributes['status'] ])) {
362
+			$this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
363
+		}
364
+		if (absint($attributes['limit'])) {
365
+			$this->query_params['limit'] = $attributes['limit'];
366
+		}
367
+		$this->query_params['group_by'] = array('ATT_ID');
368
+		$this->query_params['order_by'] = (array) apply_filters(
369
+			'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
370
+			array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
371
+		);
372
+	}
373 373
 }
Please login to merge, or discard this patch.
core/CPTs/EE_CPT_Strategy.core.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
         if (is_array($this->_CPTs)) {
129 129
             foreach ($this->_CPTs as $CPT_type => $CPT) {
130 130
                 if (isset($CPT['plural_slug'])) {
131
-                    $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type;
131
+                    $_CPT_endpoints [(string) $CPT['plural_slug']] = $CPT_type;
132 132
                 }
133 133
             }
134 134
         }
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
     public function pre_get_posts($WP_Query)
152 152
     {
153 153
         // check that post-type is set
154
-        if (! $WP_Query instanceof WP_Query) {
154
+        if ( ! $WP_Query instanceof WP_Query) {
155 155
             return;
156 156
         }
157 157
         // add our conditionals
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
             $terms = EEM_Term::instance()->get_all_CPT_post_tags();
196 196
             foreach ($terms as $term) {
197 197
                 if ($term instanceof EE_Term) {
198
-                    $this->_CPT_terms[ $term->slug() ] = $term;
198
+                    $this->_CPT_terms[$term->slug()] = $term;
199 199
                 }
200 200
             }
201 201
         }
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
             // loop thru our taxonomies
261 261
             foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) {
262 262
                 // check if one of our taxonomies is set as a query var
263
-                if (isset($WP_Query->query[ $CPT_taxonomy ])) {
263
+                if (isset($WP_Query->query[$CPT_taxonomy])) {
264 264
                     // but which CPT does that correspond to??? hmmm... guess we gotta go looping
265 265
                     foreach ($this->_CPTs as $post_type => $CPT) {
266 266
                         // verify our CPT has args, is public and has taxonomies set
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
                                     break;
285 285
                                 default:
286 286
                                     do_action(
287
-                                        'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type',
287
+                                        'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_'.$post_type.'_post_type',
288 288
                                         $WP_Query,
289 289
                                         $this
290 290
                                     );
@@ -309,11 +309,11 @@  discard block
 block discarded – undo
309 309
             // loop thru post_types as array
310 310
             foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) {
311 311
                 // is current query for an EE CPT ?
312
-                if (isset($this->_CPTs[ $post_type ])) {
312
+                if (isset($this->_CPTs[$post_type])) {
313 313
                     // is EE on or off ?
314 314
                     if (EE_Maintenance_Mode::instance()->level()) {
315 315
                         // reroute CPT template view to maintenance_mode.template.php
316
-                        if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) {
316
+                        if ( ! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) {
317 317
                             add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999);
318 318
                         }
319 319
                         if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) {
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
             'EventEspresso\core\CPTs\CptQueryModifier',
342 342
             array(
343 343
                 $post_type,
344
-                $this->_CPTs[ $post_type ],
344
+                $this->_CPTs[$post_type],
345 345
                 $WP_Query,
346 346
             )
347 347
         );
Please login to merge, or discard this patch.
Indentation   +445 added lines, -445 removed lines patch added patch discarded remove patch
@@ -16,449 +16,449 @@
 block discarded – undo
16 16
  */
17 17
 class EE_CPT_Strategy extends EE_Base
18 18
 {
19
-    /**
20
-     * @var EE_CPT_Strategy $_instance
21
-     */
22
-    private static $_instance;
23
-
24
-    /**
25
-     * the current page, if it utilizes CPTs
26
-     *
27
-     * @var array $CPT
28
-     */
29
-    protected $CPT;
30
-
31
-    /**
32
-     * return value from CustomPostTypeDefinitions::getDefinitions()
33
-     *
34
-     * @var array $_CPTs
35
-     */
36
-    protected $_CPTs = array();
37
-
38
-    /**
39
-     * @var array $_CPT_taxonomies
40
-     */
41
-    protected $_CPT_taxonomies = array();
42
-
43
-    /**
44
-     * @var array $_CPT_terms
45
-     */
46
-    protected $_CPT_terms = array();
47
-
48
-    /**
49
-     * @var array $_CPT_endpoints
50
-     */
51
-    protected $_CPT_endpoints = array();
52
-
53
-    /**
54
-     * @var EEM_Base $CPT_model
55
-     */
56
-    protected $CPT_model;
57
-
58
-    /**
59
-     * @var CptQueryModifier $query_modifier
60
-     */
61
-    protected $query_modifier;
62
-
63
-
64
-    /**
65
-     * @singleton method used to instantiate class object
66
-     * @param CustomPostTypeDefinitions|null $custom_post_types
67
-     * @param CustomTaxonomyDefinitions|null $taxonomies
68
-     * @return EE_CPT_Strategy
69
-     */
70
-    public static function instance(
71
-        $custom_post_types = null,
72
-        $taxonomies = null
73
-    ) {
74
-        // check if class object is instantiated
75
-        if (
76
-            ! self::$_instance instanceof EE_CPT_Strategy
77
-            && $custom_post_types instanceof CustomPostTypeDefinitions
78
-            && $taxonomies instanceof CustomTaxonomyDefinitions
79
-        ) {
80
-            self::$_instance = new self($custom_post_types, $taxonomies);
81
-        }
82
-        return self::$_instance;
83
-    }
84
-
85
-
86
-    /**
87
-     * @param CustomPostTypeDefinitions $custom_post_types
88
-     * @param CustomTaxonomyDefinitions $taxonomies
89
-     */
90
-    protected function __construct(
91
-        CustomPostTypeDefinitions $custom_post_types,
92
-        CustomTaxonomyDefinitions $taxonomies
93
-    ) {
94
-        // get CPT data
95
-        $this->_CPTs = $custom_post_types->getDefinitions();
96
-        $this->_CPT_endpoints = $this->_set_CPT_endpoints();
97
-        $this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions();
98
-        add_action('pre_get_posts', array($this, 'pre_get_posts'), 5);
99
-    }
100
-
101
-
102
-    /**
103
-     * @return array
104
-     */
105
-    public function get_CPT_endpoints()
106
-    {
107
-        return $this->_CPT_endpoints;
108
-    }
109
-
110
-
111
-    /**
112
-     * @return array
113
-     */
114
-    public function get_CPT_taxonomies()
115
-    {
116
-        return $this->_CPT_taxonomies;
117
-    }
118
-
119
-
120
-    /**
121
-     * add CPT "slugs" to array of default espresso "pages"
122
-     *
123
-     * @return array
124
-     */
125
-    private function _set_CPT_endpoints()
126
-    {
127
-        $_CPT_endpoints = array();
128
-        if (is_array($this->_CPTs)) {
129
-            foreach ($this->_CPTs as $CPT_type => $CPT) {
130
-                if (isset($CPT['plural_slug'])) {
131
-                    $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type;
132
-                }
133
-            }
134
-        }
135
-        return $_CPT_endpoints;
136
-    }
137
-
138
-
139
-    /**
140
-     * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to
141
-     * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and
142
-     * adding EE objects to the post to facilitate further querying of related data etc)
143
-     *
144
-     * @param WP_Query $WP_Query
145
-     * @return void
146
-     * @throws EE_Error
147
-     * @throws InvalidArgumentException
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     */
151
-    public function pre_get_posts($WP_Query)
152
-    {
153
-        // check that post-type is set
154
-        if (! $WP_Query instanceof WP_Query) {
155
-            return;
156
-        }
157
-        // add our conditionals
158
-        $this->_set_EE_tags_on_WP_Query($WP_Query);
159
-        // check for terms
160
-        $this->_set_post_type_for_terms($WP_Query);
161
-        // make sure paging is always set
162
-        $this->_set_paging($WP_Query);
163
-        // is a taxonomy set ?
164
-        $this->_set_CPT_taxonomies_on_WP_Query($WP_Query);
165
-        // loop thru post_types if set
166
-        $this->_process_WP_Query_post_types($WP_Query);
167
-    }
168
-
169
-
170
-    /**
171
-     * @param WP_Query $WP_Query
172
-     * @return void
173
-     */
174
-    private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query)
175
-    {
176
-        $WP_Query->is_espresso_event_single = false;
177
-        $WP_Query->is_espresso_event_archive = false;
178
-        $WP_Query->is_espresso_event_taxonomy = false;
179
-        $WP_Query->is_espresso_venue_single = false;
180
-        $WP_Query->is_espresso_venue_archive = false;
181
-        $WP_Query->is_espresso_venue_taxonomy = false;
182
-    }
183
-
184
-
185
-    /**
186
-     * @return void
187
-     * @throws EE_Error
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidDataTypeException
190
-     * @throws InvalidInterfaceException
191
-     */
192
-    private function _set_CPT_terms()
193
-    {
194
-        if (empty($this->_CPT_terms)) {
195
-            $terms = EEM_Term::instance()->get_all_CPT_post_tags();
196
-            foreach ($terms as $term) {
197
-                if ($term instanceof EE_Term) {
198
-                    $this->_CPT_terms[ $term->slug() ] = $term;
199
-                }
200
-            }
201
-        }
202
-    }
203
-
204
-
205
-    /**
206
-     * @param WP_Query $WP_Query
207
-     * @return void
208
-     * @throws EE_Error
209
-     * @throws InvalidArgumentException
210
-     * @throws InvalidDataTypeException
211
-     * @throws InvalidInterfaceException
212
-     */
213
-    private function _set_post_type_for_terms(WP_Query $WP_Query)
214
-    {
215
-        // is a tag set ?
216
-        if (isset($WP_Query->query['tag'])) {
217
-            // get term for tag
218
-            $term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']);
219
-            // verify the term
220
-            if ($term instanceof EE_Term) {
221
-                $term->post_type = array_merge(array('post', 'page'), (array) $term->post_type);
222
-                $term->post_type = apply_filters(
223
-                    'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type',
224
-                    $term->post_type,
225
-                    $term
226
-                );
227
-                // if a post type is already set
228
-                if (isset($WP_Query->query_vars['post_type'])) {
229
-                    // add to existing array
230
-                    $term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type);
231
-                }
232
-                // just set post_type to our CPT
233
-                $WP_Query->set('post_type', array_unique($term->post_type));
234
-            }
235
-        }
236
-    }
237
-
238
-
239
-    /**
240
-     * @param WP_Query $WP_Query
241
-     * @return void
242
-     */
243
-    public function _set_paging($WP_Query)
244
-    {
245
-        if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) {
246
-            $page = get_query_var('page') ? get_query_var('page') : null;
247
-            $paged = get_query_var('paged') ? get_query_var('paged') : $page;
248
-            $WP_Query->set('paged', $paged);
249
-        }
250
-    }
251
-
252
-
253
-    /**
254
-     * @param \WP_Query $WP_Query
255
-     */
256
-    protected function _set_CPT_taxonomies_on_WP_Query($WP_Query)
257
-    {
258
-        // is a taxonomy set ?
259
-        if ($WP_Query->is_tax) {
260
-            // loop thru our taxonomies
261
-            foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) {
262
-                // check if one of our taxonomies is set as a query var
263
-                if (isset($WP_Query->query[ $CPT_taxonomy ])) {
264
-                    // but which CPT does that correspond to??? hmmm... guess we gotta go looping
265
-                    foreach ($this->_CPTs as $post_type => $CPT) {
266
-                        // verify our CPT has args, is public and has taxonomies set
267
-                        if (
268
-                            isset($CPT['args']['public'])
269
-                            && $CPT['args']['public']
270
-                            && ! empty($CPT['args']['taxonomies'])
271
-                            && in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true)
272
-                        ) {
273
-                            // if so, then add this CPT post_type to the current query's array of post_types'
274
-                            $WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type'])
275
-                                ? (array) $WP_Query->query_vars['post_type']
276
-                                : array();
277
-                            $WP_Query->query_vars['post_type'][] = $post_type;
278
-                            switch ($post_type) {
279
-                                case 'espresso_events':
280
-                                    $WP_Query->is_espresso_event_taxonomy = true;
281
-                                    break;
282
-                                case 'espresso_venues':
283
-                                    $WP_Query->is_espresso_venue_taxonomy = true;
284
-                                    break;
285
-                                default:
286
-                                    do_action(
287
-                                        'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type',
288
-                                        $WP_Query,
289
-                                        $this
290
-                                    );
291
-                            }
292
-                        }
293
-                    }
294
-                }
295
-            }
296
-        }
297
-    }
298
-
299
-
300
-    /**
301
-     * @param \WP_Query $WP_Query
302
-     * @throws InvalidArgumentException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     */
306
-    protected function _process_WP_Query_post_types($WP_Query)
307
-    {
308
-        if (isset($WP_Query->query_vars['post_type'])) {
309
-            // loop thru post_types as array
310
-            foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) {
311
-                // is current query for an EE CPT ?
312
-                if (isset($this->_CPTs[ $post_type ])) {
313
-                    // is EE on or off ?
314
-                    if (EE_Maintenance_Mode::instance()->level()) {
315
-                        // reroute CPT template view to maintenance_mode.template.php
316
-                        if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) {
317
-                            add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999);
318
-                        }
319
-                        if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) {
320
-                            add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1);
321
-                        }
322
-                        return;
323
-                    }
324
-                    $this->_generate_CptQueryModifier($WP_Query, $post_type);
325
-                }
326
-            }
327
-        }
328
-    }
329
-
330
-
331
-    /**
332
-     * @param \WP_Query $WP_Query
333
-     * @param string    $post_type
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidDataTypeException
336
-     * @throws InvalidInterfaceException
337
-     */
338
-    protected function _generate_CptQueryModifier($WP_Query, $post_type)
339
-    {
340
-        $this->query_modifier = LoaderFactory::getLoader()->getShared(
341
-            'EventEspresso\core\CPTs\CptQueryModifier',
342
-            array(
343
-                $post_type,
344
-                $this->_CPTs[ $post_type ],
345
-                $WP_Query,
346
-            )
347
-        );
348
-        $this->_CPT_taxonomies = $this->query_modifier->taxonomies();
349
-    }
350
-
351
-
352
-    /**
353
-     * inject_EE_shortcode_placeholder
354
-     * in order to display the M-Mode notice on our CPT routes,
355
-     * we need to first inject what looks like one of our shortcodes,
356
-     * so that it can be replaced with the actual M-Mode notice
357
-     *
358
-     * @return string
359
-     */
360
-    public function inject_EE_shortcode_placeholder()
361
-    {
362
-        return '[ESPRESSO_';
363
-    }
364
-
365
-
366
-    /**
367
-     * @deprecated
368
-     * @since  4.8.41
369
-     * @return void
370
-     */
371
-    public function _possibly_set_ee_request_var()
372
-    {
373
-        $this->query_modifier->setRequestVarsIfCpt();
374
-    }
375
-
376
-
377
-    /**
378
-     * @deprecated
379
-     * @since  4.8.41
380
-     * @param  $SQL
381
-     * @return string
382
-     */
383
-    public function posts_fields($SQL)
384
-    {
385
-        if ($this->query_modifier instanceof CptQueryModifier) {
386
-            return $this->query_modifier->postsFields($SQL);
387
-        }
388
-        return $SQL;
389
-    }
390
-
391
-
392
-    /**
393
-     * @deprecated
394
-     * @since  4.8.41
395
-     * @param  $SQL
396
-     * @return string
397
-     */
398
-    public function posts_join($SQL)
399
-    {
400
-        if ($this->query_modifier instanceof CptQueryModifier) {
401
-            return $this->query_modifier->postsJoin($SQL);
402
-        }
403
-        return $SQL;
404
-    }
405
-
406
-
407
-    /**
408
-     * @deprecated
409
-     * @since  4.8.41
410
-     * @param  \WP_Post[] $posts
411
-     * @return \WP_Post[]
412
-     */
413
-    public function the_posts($posts)
414
-    {
415
-        if ($this->query_modifier instanceof CptQueryModifier) {
416
-            $this->query_modifier->thePosts($posts);
417
-        }
418
-        return $posts;
419
-    }
420
-
421
-
422
-    /**
423
-     * @deprecated
424
-     * @since  4.8.41
425
-     * @param $url
426
-     * @param $ID
427
-     * @return string
428
-     */
429
-    public function get_edit_post_link($url, $ID)
430
-    {
431
-        if ($this->query_modifier instanceof CptQueryModifier) {
432
-            return $this->query_modifier->getEditPostLink($url, $ID);
433
-        }
434
-        return '';
435
-    }
436
-
437
-
438
-    /**
439
-     * @deprecated
440
-     * @since  4.8.41
441
-     * @param null $WP_Query
442
-     */
443
-    protected function _do_template_filters($WP_Query = null)
444
-    {
445
-        if ($this->query_modifier instanceof CptQueryModifier) {
446
-            $this->query_modifier->addTemplateFilters();
447
-        }
448
-    }
449
-
450
-
451
-    /**
452
-     * @deprecated
453
-     * @since  4.8.41
454
-     * @param string $current_template Existing default template path derived for this page call.
455
-     * @return string the path to the full template file.
456
-     */
457
-    public function single_cpt_template($current_template)
458
-    {
459
-        if ($this->query_modifier instanceof CptQueryModifier) {
460
-            return $this->query_modifier->singleCptTemplate($current_template);
461
-        }
462
-        return $current_template;
463
-    }
19
+	/**
20
+	 * @var EE_CPT_Strategy $_instance
21
+	 */
22
+	private static $_instance;
23
+
24
+	/**
25
+	 * the current page, if it utilizes CPTs
26
+	 *
27
+	 * @var array $CPT
28
+	 */
29
+	protected $CPT;
30
+
31
+	/**
32
+	 * return value from CustomPostTypeDefinitions::getDefinitions()
33
+	 *
34
+	 * @var array $_CPTs
35
+	 */
36
+	protected $_CPTs = array();
37
+
38
+	/**
39
+	 * @var array $_CPT_taxonomies
40
+	 */
41
+	protected $_CPT_taxonomies = array();
42
+
43
+	/**
44
+	 * @var array $_CPT_terms
45
+	 */
46
+	protected $_CPT_terms = array();
47
+
48
+	/**
49
+	 * @var array $_CPT_endpoints
50
+	 */
51
+	protected $_CPT_endpoints = array();
52
+
53
+	/**
54
+	 * @var EEM_Base $CPT_model
55
+	 */
56
+	protected $CPT_model;
57
+
58
+	/**
59
+	 * @var CptQueryModifier $query_modifier
60
+	 */
61
+	protected $query_modifier;
62
+
63
+
64
+	/**
65
+	 * @singleton method used to instantiate class object
66
+	 * @param CustomPostTypeDefinitions|null $custom_post_types
67
+	 * @param CustomTaxonomyDefinitions|null $taxonomies
68
+	 * @return EE_CPT_Strategy
69
+	 */
70
+	public static function instance(
71
+		$custom_post_types = null,
72
+		$taxonomies = null
73
+	) {
74
+		// check if class object is instantiated
75
+		if (
76
+			! self::$_instance instanceof EE_CPT_Strategy
77
+			&& $custom_post_types instanceof CustomPostTypeDefinitions
78
+			&& $taxonomies instanceof CustomTaxonomyDefinitions
79
+		) {
80
+			self::$_instance = new self($custom_post_types, $taxonomies);
81
+		}
82
+		return self::$_instance;
83
+	}
84
+
85
+
86
+	/**
87
+	 * @param CustomPostTypeDefinitions $custom_post_types
88
+	 * @param CustomTaxonomyDefinitions $taxonomies
89
+	 */
90
+	protected function __construct(
91
+		CustomPostTypeDefinitions $custom_post_types,
92
+		CustomTaxonomyDefinitions $taxonomies
93
+	) {
94
+		// get CPT data
95
+		$this->_CPTs = $custom_post_types->getDefinitions();
96
+		$this->_CPT_endpoints = $this->_set_CPT_endpoints();
97
+		$this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions();
98
+		add_action('pre_get_posts', array($this, 'pre_get_posts'), 5);
99
+	}
100
+
101
+
102
+	/**
103
+	 * @return array
104
+	 */
105
+	public function get_CPT_endpoints()
106
+	{
107
+		return $this->_CPT_endpoints;
108
+	}
109
+
110
+
111
+	/**
112
+	 * @return array
113
+	 */
114
+	public function get_CPT_taxonomies()
115
+	{
116
+		return $this->_CPT_taxonomies;
117
+	}
118
+
119
+
120
+	/**
121
+	 * add CPT "slugs" to array of default espresso "pages"
122
+	 *
123
+	 * @return array
124
+	 */
125
+	private function _set_CPT_endpoints()
126
+	{
127
+		$_CPT_endpoints = array();
128
+		if (is_array($this->_CPTs)) {
129
+			foreach ($this->_CPTs as $CPT_type => $CPT) {
130
+				if (isset($CPT['plural_slug'])) {
131
+					$_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type;
132
+				}
133
+			}
134
+		}
135
+		return $_CPT_endpoints;
136
+	}
137
+
138
+
139
+	/**
140
+	 * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to
141
+	 * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and
142
+	 * adding EE objects to the post to facilitate further querying of related data etc)
143
+	 *
144
+	 * @param WP_Query $WP_Query
145
+	 * @return void
146
+	 * @throws EE_Error
147
+	 * @throws InvalidArgumentException
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 */
151
+	public function pre_get_posts($WP_Query)
152
+	{
153
+		// check that post-type is set
154
+		if (! $WP_Query instanceof WP_Query) {
155
+			return;
156
+		}
157
+		// add our conditionals
158
+		$this->_set_EE_tags_on_WP_Query($WP_Query);
159
+		// check for terms
160
+		$this->_set_post_type_for_terms($WP_Query);
161
+		// make sure paging is always set
162
+		$this->_set_paging($WP_Query);
163
+		// is a taxonomy set ?
164
+		$this->_set_CPT_taxonomies_on_WP_Query($WP_Query);
165
+		// loop thru post_types if set
166
+		$this->_process_WP_Query_post_types($WP_Query);
167
+	}
168
+
169
+
170
+	/**
171
+	 * @param WP_Query $WP_Query
172
+	 * @return void
173
+	 */
174
+	private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query)
175
+	{
176
+		$WP_Query->is_espresso_event_single = false;
177
+		$WP_Query->is_espresso_event_archive = false;
178
+		$WP_Query->is_espresso_event_taxonomy = false;
179
+		$WP_Query->is_espresso_venue_single = false;
180
+		$WP_Query->is_espresso_venue_archive = false;
181
+		$WP_Query->is_espresso_venue_taxonomy = false;
182
+	}
183
+
184
+
185
+	/**
186
+	 * @return void
187
+	 * @throws EE_Error
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidDataTypeException
190
+	 * @throws InvalidInterfaceException
191
+	 */
192
+	private function _set_CPT_terms()
193
+	{
194
+		if (empty($this->_CPT_terms)) {
195
+			$terms = EEM_Term::instance()->get_all_CPT_post_tags();
196
+			foreach ($terms as $term) {
197
+				if ($term instanceof EE_Term) {
198
+					$this->_CPT_terms[ $term->slug() ] = $term;
199
+				}
200
+			}
201
+		}
202
+	}
203
+
204
+
205
+	/**
206
+	 * @param WP_Query $WP_Query
207
+	 * @return void
208
+	 * @throws EE_Error
209
+	 * @throws InvalidArgumentException
210
+	 * @throws InvalidDataTypeException
211
+	 * @throws InvalidInterfaceException
212
+	 */
213
+	private function _set_post_type_for_terms(WP_Query $WP_Query)
214
+	{
215
+		// is a tag set ?
216
+		if (isset($WP_Query->query['tag'])) {
217
+			// get term for tag
218
+			$term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']);
219
+			// verify the term
220
+			if ($term instanceof EE_Term) {
221
+				$term->post_type = array_merge(array('post', 'page'), (array) $term->post_type);
222
+				$term->post_type = apply_filters(
223
+					'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type',
224
+					$term->post_type,
225
+					$term
226
+				);
227
+				// if a post type is already set
228
+				if (isset($WP_Query->query_vars['post_type'])) {
229
+					// add to existing array
230
+					$term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type);
231
+				}
232
+				// just set post_type to our CPT
233
+				$WP_Query->set('post_type', array_unique($term->post_type));
234
+			}
235
+		}
236
+	}
237
+
238
+
239
+	/**
240
+	 * @param WP_Query $WP_Query
241
+	 * @return void
242
+	 */
243
+	public function _set_paging($WP_Query)
244
+	{
245
+		if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) {
246
+			$page = get_query_var('page') ? get_query_var('page') : null;
247
+			$paged = get_query_var('paged') ? get_query_var('paged') : $page;
248
+			$WP_Query->set('paged', $paged);
249
+		}
250
+	}
251
+
252
+
253
+	/**
254
+	 * @param \WP_Query $WP_Query
255
+	 */
256
+	protected function _set_CPT_taxonomies_on_WP_Query($WP_Query)
257
+	{
258
+		// is a taxonomy set ?
259
+		if ($WP_Query->is_tax) {
260
+			// loop thru our taxonomies
261
+			foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) {
262
+				// check if one of our taxonomies is set as a query var
263
+				if (isset($WP_Query->query[ $CPT_taxonomy ])) {
264
+					// but which CPT does that correspond to??? hmmm... guess we gotta go looping
265
+					foreach ($this->_CPTs as $post_type => $CPT) {
266
+						// verify our CPT has args, is public and has taxonomies set
267
+						if (
268
+							isset($CPT['args']['public'])
269
+							&& $CPT['args']['public']
270
+							&& ! empty($CPT['args']['taxonomies'])
271
+							&& in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true)
272
+						) {
273
+							// if so, then add this CPT post_type to the current query's array of post_types'
274
+							$WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type'])
275
+								? (array) $WP_Query->query_vars['post_type']
276
+								: array();
277
+							$WP_Query->query_vars['post_type'][] = $post_type;
278
+							switch ($post_type) {
279
+								case 'espresso_events':
280
+									$WP_Query->is_espresso_event_taxonomy = true;
281
+									break;
282
+								case 'espresso_venues':
283
+									$WP_Query->is_espresso_venue_taxonomy = true;
284
+									break;
285
+								default:
286
+									do_action(
287
+										'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type',
288
+										$WP_Query,
289
+										$this
290
+									);
291
+							}
292
+						}
293
+					}
294
+				}
295
+			}
296
+		}
297
+	}
298
+
299
+
300
+	/**
301
+	 * @param \WP_Query $WP_Query
302
+	 * @throws InvalidArgumentException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 */
306
+	protected function _process_WP_Query_post_types($WP_Query)
307
+	{
308
+		if (isset($WP_Query->query_vars['post_type'])) {
309
+			// loop thru post_types as array
310
+			foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) {
311
+				// is current query for an EE CPT ?
312
+				if (isset($this->_CPTs[ $post_type ])) {
313
+					// is EE on or off ?
314
+					if (EE_Maintenance_Mode::instance()->level()) {
315
+						// reroute CPT template view to maintenance_mode.template.php
316
+						if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) {
317
+							add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999);
318
+						}
319
+						if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) {
320
+							add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1);
321
+						}
322
+						return;
323
+					}
324
+					$this->_generate_CptQueryModifier($WP_Query, $post_type);
325
+				}
326
+			}
327
+		}
328
+	}
329
+
330
+
331
+	/**
332
+	 * @param \WP_Query $WP_Query
333
+	 * @param string    $post_type
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidDataTypeException
336
+	 * @throws InvalidInterfaceException
337
+	 */
338
+	protected function _generate_CptQueryModifier($WP_Query, $post_type)
339
+	{
340
+		$this->query_modifier = LoaderFactory::getLoader()->getShared(
341
+			'EventEspresso\core\CPTs\CptQueryModifier',
342
+			array(
343
+				$post_type,
344
+				$this->_CPTs[ $post_type ],
345
+				$WP_Query,
346
+			)
347
+		);
348
+		$this->_CPT_taxonomies = $this->query_modifier->taxonomies();
349
+	}
350
+
351
+
352
+	/**
353
+	 * inject_EE_shortcode_placeholder
354
+	 * in order to display the M-Mode notice on our CPT routes,
355
+	 * we need to first inject what looks like one of our shortcodes,
356
+	 * so that it can be replaced with the actual M-Mode notice
357
+	 *
358
+	 * @return string
359
+	 */
360
+	public function inject_EE_shortcode_placeholder()
361
+	{
362
+		return '[ESPRESSO_';
363
+	}
364
+
365
+
366
+	/**
367
+	 * @deprecated
368
+	 * @since  4.8.41
369
+	 * @return void
370
+	 */
371
+	public function _possibly_set_ee_request_var()
372
+	{
373
+		$this->query_modifier->setRequestVarsIfCpt();
374
+	}
375
+
376
+
377
+	/**
378
+	 * @deprecated
379
+	 * @since  4.8.41
380
+	 * @param  $SQL
381
+	 * @return string
382
+	 */
383
+	public function posts_fields($SQL)
384
+	{
385
+		if ($this->query_modifier instanceof CptQueryModifier) {
386
+			return $this->query_modifier->postsFields($SQL);
387
+		}
388
+		return $SQL;
389
+	}
390
+
391
+
392
+	/**
393
+	 * @deprecated
394
+	 * @since  4.8.41
395
+	 * @param  $SQL
396
+	 * @return string
397
+	 */
398
+	public function posts_join($SQL)
399
+	{
400
+		if ($this->query_modifier instanceof CptQueryModifier) {
401
+			return $this->query_modifier->postsJoin($SQL);
402
+		}
403
+		return $SQL;
404
+	}
405
+
406
+
407
+	/**
408
+	 * @deprecated
409
+	 * @since  4.8.41
410
+	 * @param  \WP_Post[] $posts
411
+	 * @return \WP_Post[]
412
+	 */
413
+	public function the_posts($posts)
414
+	{
415
+		if ($this->query_modifier instanceof CptQueryModifier) {
416
+			$this->query_modifier->thePosts($posts);
417
+		}
418
+		return $posts;
419
+	}
420
+
421
+
422
+	/**
423
+	 * @deprecated
424
+	 * @since  4.8.41
425
+	 * @param $url
426
+	 * @param $ID
427
+	 * @return string
428
+	 */
429
+	public function get_edit_post_link($url, $ID)
430
+	{
431
+		if ($this->query_modifier instanceof CptQueryModifier) {
432
+			return $this->query_modifier->getEditPostLink($url, $ID);
433
+		}
434
+		return '';
435
+	}
436
+
437
+
438
+	/**
439
+	 * @deprecated
440
+	 * @since  4.8.41
441
+	 * @param null $WP_Query
442
+	 */
443
+	protected function _do_template_filters($WP_Query = null)
444
+	{
445
+		if ($this->query_modifier instanceof CptQueryModifier) {
446
+			$this->query_modifier->addTemplateFilters();
447
+		}
448
+	}
449
+
450
+
451
+	/**
452
+	 * @deprecated
453
+	 * @since  4.8.41
454
+	 * @param string $current_template Existing default template path derived for this page call.
455
+	 * @return string the path to the full template file.
456
+	 */
457
+	public function single_cpt_template($current_template)
458
+	{
459
+		if ($this->query_modifier instanceof CptQueryModifier) {
460
+			return $this->query_modifier->singleCptTemplate($current_template);
461
+		}
462
+		return $current_template;
463
+	}
464 464
 }
Please login to merge, or discard this patch.
core/CPTs/EE_CPT_Event_Strategy.core.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -122,13 +122,13 @@  discard block
 block discarded – undo
122 122
             )
123 123
         ) {
124 124
             // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
125
-            $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* ';
125
+            $SQL .= ', '.EEM_Datetime::instance()->table().'.* ';
126 126
             if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) {
127 127
                 // because we only want to retrieve the next upcoming datetime for each event:
128 128
                 // add something like:
129 129
                 // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date "
130 130
                 // to WP Query SELECT statement
131
-                $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
131
+                $SQL .= ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date ';
132 132
             }
133 133
         }
134 134
         return $SQL;
@@ -158,9 +158,9 @@  discard block
 block discarded – undo
158 158
             // adds something like:
159 159
             // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) "
160 160
             // to WP Query JOIN statement
161
-            $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table()
162
-                    . '.ID = ' . EEM_Datetime::instance()->table() . '.'
163
-                    . EEM_Event::instance()->primary_key_name() . ' ) ';
161
+            $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.EEM_Event::instance()->table()
162
+                    . '.ID = '.EEM_Datetime::instance()->table().'.'
163
+                    . EEM_Event::instance()->primary_key_name().' ) ';
164 164
         }
165 165
         return $SQL;
166 166
     }
@@ -190,8 +190,8 @@  discard block
 block discarded – undo
190 190
                 || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events)
191 191
                 || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events
192 192
             ) {
193
-                $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '"
194
-                        . current_time('mysql', true) . "' ";
193
+                $SQL .= ' AND '.EEM_Datetime::instance()->table().".DTT_EVT_end > '"
194
+                        . current_time('mysql', true)."' ";
195 195
             }
196 196
         }
197 197
         return $SQL;
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
             // but we want to only show each event only once
240 240
             // (whereas if we didn't group them by the post's ID, then we would end up with many repeats)
241 241
             global $wpdb;
242
-            $SQL = $wpdb->posts . '.ID ';
242
+            $SQL = $wpdb->posts.'.ID ';
243 243
         }
244 244
         return $SQL;
245 245
     }
Please login to merge, or discard this patch.
Indentation   +240 added lines, -240 removed lines patch added patch discarded remove patch
@@ -9,244 +9,244 @@
 block discarded – undo
9 9
  */
10 10
 class EE_CPT_Event_Strategy
11 11
 {
12
-    /**
13
-     * the current page, if it utilizes CPTs
14
-     *
15
-     * @var object $CPT
16
-     */
17
-    protected $CPT;
18
-
19
-
20
-    /**
21
-     * @param array|WP_Query|null $wp_query
22
-     * @param array         $CPT
23
-     */
24
-    public function __construct($wp_query, array $CPT = [])
25
-    {
26
-        if ($wp_query instanceof WP_Query) {
27
-            $WP_Query  = $wp_query;
28
-            $this->CPT = $CPT;
29
-        } else {
30
-            $WP_Query  = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null;
31
-            $this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null;
32
-        }
33
-        // !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
34
-        // here's the list of available filters in the WP_Query object
35
-        // 'posts_where'
36
-        // 'posts_where_paged'
37
-        // 'posts_groupby'
38
-        // 'posts_join_paged'
39
-        // 'posts_orderby'
40
-        // 'posts_distinct'
41
-        // 'post_limits'
42
-        // 'posts_fields'
43
-        // 'posts_join'
44
-        $this->_add_filters();
45
-        if ($WP_Query instanceof WP_Query) {
46
-            $WP_Query->is_espresso_event_single   = is_singular()
47
-                                                    && isset($WP_Query->query->post_type)
48
-                                                    && $WP_Query->query->post_type === 'espresso_events';
49
-            $WP_Query->is_espresso_event_archive  = is_post_type_archive('espresso_events');
50
-            $WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories');
51
-        }
52
-    }
53
-
54
-
55
-    /**
56
-     * When an instance of this class is created, we add our filters
57
-     * (which will get removed in case the next call to get_posts ISN'T
58
-     * for event CPTs)
59
-     */
60
-    protected function _add_filters()
61
-    {
62
-        add_filter('posts_fields', [$this, 'posts_fields'], 1, 2);
63
-        add_filter('posts_join', [$this, 'posts_join'], 1, 2);
64
-        add_filter('posts_where', [$this, 'posts_where'], 10, 2);
65
-        // add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 );
66
-        add_filter('posts_orderby', [$this, 'posts_orderby'], 1, 2);
67
-        add_filter('posts_groupby', [$this, 'posts_groupby'], 1, 2);
68
-        add_action('posts_selection', [$this, 'remove_filters']);
69
-    }
70
-
71
-
72
-    /**
73
-     * public access to _remove_filters()
74
-     *
75
-     * @since 4.9.63.p
76
-     */
77
-    public function remove_filters()
78
-    {
79
-        $this->_remove_filters();
80
-    }
81
-
82
-
83
-    /**
84
-     * Should eb called when the last filter or hook is fired for this CPT strategy.
85
-     * This is to avoid applying this CPT strategy for other posts or CPTs (eg,
86
-     * we don't want to join to the datetime table when querying for venues, do we!?)
87
-     */
88
-    protected function _remove_filters()
89
-    {
90
-        remove_filter('posts_fields', [$this, 'posts_fields'], 1);
91
-        remove_filter('posts_join', [$this, 'posts_join'], 1);
92
-        remove_filter('posts_where', [$this, 'posts_where']);
93
-        // remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 );
94
-        remove_filter('posts_orderby', [$this, 'posts_orderby'], 1);
95
-        remove_filter('posts_groupby', [$this, 'posts_groupby'], 1);
96
-        remove_action('posts_selection', [$this, 'remove_filters']);
97
-    }
98
-
99
-
100
-    /**
101
-     * @param string        $SQL
102
-     * @param WP_Query|null $wp_query
103
-     * @return    string
104
-     * @throws EE_Error
105
-     */
106
-    public function posts_fields($SQL, $wp_query)
107
-    {
108
-        if (
109
-            $wp_query instanceof WP_Query
110
-            && (
111
-                $wp_query->is_espresso_event_single
112
-                || $wp_query->is_espresso_event_archive
113
-                || $wp_query->is_espresso_event_taxonomy
114
-            )
115
-        ) {
116
-            // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
117
-            $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* ';
118
-            if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) {
119
-                // because we only want to retrieve the next upcoming datetime for each event:
120
-                // add something like:
121
-                // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date "
122
-                // to WP Query SELECT statement
123
-                $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
124
-            }
125
-        }
126
-        return $SQL;
127
-    }
128
-
129
-
130
-    /**
131
-     * @param string        $SQL
132
-     * @param WP_Query|null $wp_query
133
-     * @return string
134
-     * @throws EE_Error
135
-     */
136
-    public function posts_join($SQL, $wp_query)
137
-    {
138
-        if (
139
-            $wp_query instanceof WP_Query
140
-            && (
141
-                $wp_query->is_espresso_event_single
142
-                || $wp_query->is_espresso_event_archive
143
-                || $wp_query->is_espresso_event_taxonomy
144
-            )
145
-        ) {
146
-            // adds something like:
147
-            // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) "
148
-            // to WP Query JOIN statement
149
-            $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table()
150
-                    . '.ID = ' . EEM_Datetime::instance()->table() . '.'
151
-                    . EEM_Event::instance()->primary_key_name() . ' ) ';
152
-        }
153
-        return $SQL;
154
-    }
155
-
156
-
157
-    /**
158
-     * @param string        $SQL
159
-     * @param WP_Query|null $wp_query
160
-     * @return string
161
-     * @throws EE_Error
162
-     */
163
-    public function posts_where($SQL, $wp_query)
164
-    {
165
-        if (
166
-            $wp_query instanceof WP_Query
167
-            && (
168
-                $wp_query->is_espresso_event_archive
169
-                || $wp_query->is_espresso_event_taxonomy
170
-            )
171
-        ) {
172
-            if (
173
-                ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive)
174
-                || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events)
175
-                || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events
176
-            ) {
177
-                $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '"
178
-                        . current_time('mysql', true) . "' ";
179
-            }
180
-        }
181
-        return $SQL;
182
-    }
183
-
184
-
185
-    /**
186
-     * @param string        $SQL
187
-     * @param WP_Query|null $wp_query
188
-     * @return string
189
-     */
190
-    public function posts_orderby($SQL, $wp_query)
191
-    {
192
-        if (
193
-            $wp_query instanceof WP_Query
194
-            && (
195
-                $wp_query->is_espresso_event_archive
196
-                || $wp_query->is_espresso_event_taxonomy
197
-            )
198
-        ) {
199
-            $SQL = ' event_start_date ASC ';
200
-        }
201
-        return $SQL;
202
-    }
203
-
204
-
205
-    /**
206
-     * @param string        $SQL
207
-     * @param WP_Query|null $wp_query
208
-     * @return string
209
-     */
210
-    public function posts_groupby($SQL, $wp_query)
211
-    {
212
-        if (
213
-            $wp_query instanceof WP_Query
214
-            && (
215
-                $wp_query->is_espresso_event_archive
216
-                || $wp_query->is_espresso_event_taxonomy
217
-            )
218
-        ) {
219
-            // TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default)
220
-            // we're joining to the datetimes table, where there can be MANY datetimes for a single event,
221
-            // but we want to only show each event only once
222
-            // (whereas if we didn't group them by the post's ID, then we would end up with many repeats)
223
-            global $wpdb;
224
-            $SQL = $wpdb->posts . '.ID ';
225
-        }
226
-        return $SQL;
227
-    }
228
-
229
-
230
-    /**
231
-     * @param array         $posts
232
-     * @param WP_Query|null $wp_query
233
-     * @return array
234
-     */
235
-    public function the_posts($posts, $wp_query)
236
-    {
237
-        return $posts;
238
-    }
239
-
240
-
241
-    /**
242
-     * @param mixed           $meta_value
243
-     * @param int|string      $post_id
244
-     * @param int|string      $meta_key
245
-     * @param bool|int|string $single
246
-     * @return mixed
247
-     */
248
-    public function get_EE_post_type_metadata($meta_value, $post_id, $meta_key, $single)
249
-    {
250
-        return $meta_value;
251
-    }
12
+	/**
13
+	 * the current page, if it utilizes CPTs
14
+	 *
15
+	 * @var object $CPT
16
+	 */
17
+	protected $CPT;
18
+
19
+
20
+	/**
21
+	 * @param array|WP_Query|null $wp_query
22
+	 * @param array         $CPT
23
+	 */
24
+	public function __construct($wp_query, array $CPT = [])
25
+	{
26
+		if ($wp_query instanceof WP_Query) {
27
+			$WP_Query  = $wp_query;
28
+			$this->CPT = $CPT;
29
+		} else {
30
+			$WP_Query  = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null;
31
+			$this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null;
32
+		}
33
+		// !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
34
+		// here's the list of available filters in the WP_Query object
35
+		// 'posts_where'
36
+		// 'posts_where_paged'
37
+		// 'posts_groupby'
38
+		// 'posts_join_paged'
39
+		// 'posts_orderby'
40
+		// 'posts_distinct'
41
+		// 'post_limits'
42
+		// 'posts_fields'
43
+		// 'posts_join'
44
+		$this->_add_filters();
45
+		if ($WP_Query instanceof WP_Query) {
46
+			$WP_Query->is_espresso_event_single   = is_singular()
47
+													&& isset($WP_Query->query->post_type)
48
+													&& $WP_Query->query->post_type === 'espresso_events';
49
+			$WP_Query->is_espresso_event_archive  = is_post_type_archive('espresso_events');
50
+			$WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories');
51
+		}
52
+	}
53
+
54
+
55
+	/**
56
+	 * When an instance of this class is created, we add our filters
57
+	 * (which will get removed in case the next call to get_posts ISN'T
58
+	 * for event CPTs)
59
+	 */
60
+	protected function _add_filters()
61
+	{
62
+		add_filter('posts_fields', [$this, 'posts_fields'], 1, 2);
63
+		add_filter('posts_join', [$this, 'posts_join'], 1, 2);
64
+		add_filter('posts_where', [$this, 'posts_where'], 10, 2);
65
+		// add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 );
66
+		add_filter('posts_orderby', [$this, 'posts_orderby'], 1, 2);
67
+		add_filter('posts_groupby', [$this, 'posts_groupby'], 1, 2);
68
+		add_action('posts_selection', [$this, 'remove_filters']);
69
+	}
70
+
71
+
72
+	/**
73
+	 * public access to _remove_filters()
74
+	 *
75
+	 * @since 4.9.63.p
76
+	 */
77
+	public function remove_filters()
78
+	{
79
+		$this->_remove_filters();
80
+	}
81
+
82
+
83
+	/**
84
+	 * Should eb called when the last filter or hook is fired for this CPT strategy.
85
+	 * This is to avoid applying this CPT strategy for other posts or CPTs (eg,
86
+	 * we don't want to join to the datetime table when querying for venues, do we!?)
87
+	 */
88
+	protected function _remove_filters()
89
+	{
90
+		remove_filter('posts_fields', [$this, 'posts_fields'], 1);
91
+		remove_filter('posts_join', [$this, 'posts_join'], 1);
92
+		remove_filter('posts_where', [$this, 'posts_where']);
93
+		// remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 );
94
+		remove_filter('posts_orderby', [$this, 'posts_orderby'], 1);
95
+		remove_filter('posts_groupby', [$this, 'posts_groupby'], 1);
96
+		remove_action('posts_selection', [$this, 'remove_filters']);
97
+	}
98
+
99
+
100
+	/**
101
+	 * @param string        $SQL
102
+	 * @param WP_Query|null $wp_query
103
+	 * @return    string
104
+	 * @throws EE_Error
105
+	 */
106
+	public function posts_fields($SQL, $wp_query)
107
+	{
108
+		if (
109
+			$wp_query instanceof WP_Query
110
+			&& (
111
+				$wp_query->is_espresso_event_single
112
+				|| $wp_query->is_espresso_event_archive
113
+				|| $wp_query->is_espresso_event_taxonomy
114
+			)
115
+		) {
116
+			// adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
117
+			$SQL .= ', ' . EEM_Datetime::instance()->table() . '.* ';
118
+			if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) {
119
+				// because we only want to retrieve the next upcoming datetime for each event:
120
+				// add something like:
121
+				// ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date "
122
+				// to WP Query SELECT statement
123
+				$SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
124
+			}
125
+		}
126
+		return $SQL;
127
+	}
128
+
129
+
130
+	/**
131
+	 * @param string        $SQL
132
+	 * @param WP_Query|null $wp_query
133
+	 * @return string
134
+	 * @throws EE_Error
135
+	 */
136
+	public function posts_join($SQL, $wp_query)
137
+	{
138
+		if (
139
+			$wp_query instanceof WP_Query
140
+			&& (
141
+				$wp_query->is_espresso_event_single
142
+				|| $wp_query->is_espresso_event_archive
143
+				|| $wp_query->is_espresso_event_taxonomy
144
+			)
145
+		) {
146
+			// adds something like:
147
+			// " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) "
148
+			// to WP Query JOIN statement
149
+			$SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table()
150
+					. '.ID = ' . EEM_Datetime::instance()->table() . '.'
151
+					. EEM_Event::instance()->primary_key_name() . ' ) ';
152
+		}
153
+		return $SQL;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @param string        $SQL
159
+	 * @param WP_Query|null $wp_query
160
+	 * @return string
161
+	 * @throws EE_Error
162
+	 */
163
+	public function posts_where($SQL, $wp_query)
164
+	{
165
+		if (
166
+			$wp_query instanceof WP_Query
167
+			&& (
168
+				$wp_query->is_espresso_event_archive
169
+				|| $wp_query->is_espresso_event_taxonomy
170
+			)
171
+		) {
172
+			if (
173
+				! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive)
174
+				|| ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events)
175
+				|| ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events
176
+			) {
177
+				$SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '"
178
+						. current_time('mysql', true) . "' ";
179
+			}
180
+		}
181
+		return $SQL;
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param string        $SQL
187
+	 * @param WP_Query|null $wp_query
188
+	 * @return string
189
+	 */
190
+	public function posts_orderby($SQL, $wp_query)
191
+	{
192
+		if (
193
+			$wp_query instanceof WP_Query
194
+			&& (
195
+				$wp_query->is_espresso_event_archive
196
+				|| $wp_query->is_espresso_event_taxonomy
197
+			)
198
+		) {
199
+			$SQL = ' event_start_date ASC ';
200
+		}
201
+		return $SQL;
202
+	}
203
+
204
+
205
+	/**
206
+	 * @param string        $SQL
207
+	 * @param WP_Query|null $wp_query
208
+	 * @return string
209
+	 */
210
+	public function posts_groupby($SQL, $wp_query)
211
+	{
212
+		if (
213
+			$wp_query instanceof WP_Query
214
+			&& (
215
+				$wp_query->is_espresso_event_archive
216
+				|| $wp_query->is_espresso_event_taxonomy
217
+			)
218
+		) {
219
+			// TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default)
220
+			// we're joining to the datetimes table, where there can be MANY datetimes for a single event,
221
+			// but we want to only show each event only once
222
+			// (whereas if we didn't group them by the post's ID, then we would end up with many repeats)
223
+			global $wpdb;
224
+			$SQL = $wpdb->posts . '.ID ';
225
+		}
226
+		return $SQL;
227
+	}
228
+
229
+
230
+	/**
231
+	 * @param array         $posts
232
+	 * @param WP_Query|null $wp_query
233
+	 * @return array
234
+	 */
235
+	public function the_posts($posts, $wp_query)
236
+	{
237
+		return $posts;
238
+	}
239
+
240
+
241
+	/**
242
+	 * @param mixed           $meta_value
243
+	 * @param int|string      $post_id
244
+	 * @param int|string      $meta_key
245
+	 * @param bool|int|string $single
246
+	 * @return mixed
247
+	 */
248
+	public function get_EE_post_type_metadata($meta_value, $post_id, $meta_key, $single)
249
+	{
250
+		return $meta_value;
251
+	}
252 252
 }
Please login to merge, or discard this patch.
core/services/address/CountrySubRegionDao.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
         $data = [];
81 81
         if (empty($this->countries)) {
82 82
             $this->data_version = $this->getCountrySubRegionDataVersion();
83
-            $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
+            $data = $this->retrieveJsonData(self::REPO_URL.'countries.json');
84 84
         }
85 85
         if (empty($data)) {
86 86
             EE_Error::add_error(
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
      */
145 145
     private function processCountryData($CNT_ISO, $countries = array())
146 146
     {
147
-        if (! empty($countries)) {
147
+        if ( ! empty($countries)) {
148 148
             foreach ($countries as $key => $country) {
149 149
                 if (
150 150
                     $country instanceof stdClass
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
                     && ! empty($country->filename)
154 154
                 ) {
155 155
                     $country->sub_regions = $this->retrieveJsonData(
156
-                        self::REPO_URL . 'countries/' . $country->filename . '.json'
156
+                        self::REPO_URL.'countries/'.$country->filename.'.json'
157 157
                     );
158 158
                     return $this->saveSubRegionData($country, $country->sub_regions);
159 159
                 }
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
             foreach ($sub_regions as $sub_region) {
216 216
                 // remove country code from sub region code
217 217
                 $abbrev = str_replace(
218
-                    $country->code . '-',
218
+                    $country->code.'-',
219 219
                     '',
220 220
                     sanitize_text_field($sub_region->code)
221 221
                 );
Please login to merge, or discard this patch.
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -25,252 +25,252 @@
 block discarded – undo
25 25
  */
26 26
 class CountrySubRegionDao
27 27
 {
28
-    const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/';
28
+	const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/';
29 29
 
30
-    const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version';
30
+	const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version';
31 31
 
32
-    /**
33
-     * @var EEM_State $state_model
34
-     */
35
-    private $state_model;
32
+	/**
33
+	 * @var EEM_State $state_model
34
+	 */
35
+	private $state_model;
36 36
 
37
-    /**
38
-     * @var JsonValidator $json_validator
39
-     */
40
-    private $json_validator;
37
+	/**
38
+	 * @var JsonValidator $json_validator
39
+	 */
40
+	private $json_validator;
41 41
 
42
-    /**
43
-     * @var string $data_version
44
-     */
45
-    private $data_version;
42
+	/**
43
+	 * @var string $data_version
44
+	 */
45
+	private $data_version;
46 46
 
47
-    /**
48
-     * @var array $countries
49
-     */
50
-    private $countries = array();
47
+	/**
48
+	 * @var array $countries
49
+	 */
50
+	private $countries = array();
51 51
 
52 52
 
53
-    /**
54
-     * CountrySubRegionDao constructor.
55
-     *
56
-     * @param EEM_State     $state_model
57
-     * @param JsonValidator $json_validator
58
-     */
59
-    public function __construct(EEM_State $state_model, JsonValidator $json_validator)
60
-    {
61
-        $this->state_model = $state_model;
62
-        $this->json_validator = $json_validator;
63
-    }
53
+	/**
54
+	 * CountrySubRegionDao constructor.
55
+	 *
56
+	 * @param EEM_State     $state_model
57
+	 * @param JsonValidator $json_validator
58
+	 */
59
+	public function __construct(EEM_State $state_model, JsonValidator $json_validator)
60
+	{
61
+		$this->state_model = $state_model;
62
+		$this->json_validator = $json_validator;
63
+	}
64 64
 
65 65
 
66
-    /**
67
-     * @param EE_Country $country_object
68
-     * @return bool
69
-     * @throws EE_Error
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws ReflectionException
74
-     */
75
-    public function saveCountrySubRegions($country_object)
76
-    {
77
-        $CNT_ISO = $country_object->ID();
78
-        $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO)));
79
-        $data = [];
80
-        if (empty($this->countries)) {
81
-            $this->data_version = $this->getCountrySubRegionDataVersion();
82
-            $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
-        }
84
-        if (empty($data)) {
85
-            EE_Error::add_error(
86
-                'Country Subregion Data could not be retrieved',
87
-                __FILE__,
88
-                __METHOD__,
89
-                __LINE__
90
-            );
91
-        }
92
-        if (
93
-            ! $has_sub_regions
94
-            || (isset($data->version) && version_compare($data->version, $this->data_version))
95
-        ) {
96
-            if (
97
-                isset($data->countries)
98
-                && $this->processCountryData($CNT_ISO, $data->countries) > 0
99
-            ) {
100
-                $this->countries = $data->countries;
101
-                $this->updateCountrySubRegionDataVersion($data->version);
102
-                return true;
103
-            }
104
-        }
105
-        return false;
106
-    }
66
+	/**
67
+	 * @param EE_Country $country_object
68
+	 * @return bool
69
+	 * @throws EE_Error
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws ReflectionException
74
+	 */
75
+	public function saveCountrySubRegions($country_object)
76
+	{
77
+		$CNT_ISO = $country_object->ID();
78
+		$has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO)));
79
+		$data = [];
80
+		if (empty($this->countries)) {
81
+			$this->data_version = $this->getCountrySubRegionDataVersion();
82
+			$data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
+		}
84
+		if (empty($data)) {
85
+			EE_Error::add_error(
86
+				'Country Subregion Data could not be retrieved',
87
+				__FILE__,
88
+				__METHOD__,
89
+				__LINE__
90
+			);
91
+		}
92
+		if (
93
+			! $has_sub_regions
94
+			|| (isset($data->version) && version_compare($data->version, $this->data_version))
95
+		) {
96
+			if (
97
+				isset($data->countries)
98
+				&& $this->processCountryData($CNT_ISO, $data->countries) > 0
99
+			) {
100
+				$this->countries = $data->countries;
101
+				$this->updateCountrySubRegionDataVersion($data->version);
102
+				return true;
103
+			}
104
+		}
105
+		return false;
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * @since 4.9.70.p
111
-     * @return string
112
-     */
113
-    private function getCountrySubRegionDataVersion()
114
-    {
115
-        return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null);
116
-    }
109
+	/**
110
+	 * @since 4.9.70.p
111
+	 * @return string
112
+	 */
113
+	private function getCountrySubRegionDataVersion()
114
+	{
115
+		return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null);
116
+	}
117 117
 
118 118
 
119
-    /**
120
-     * @param string $version
121
-     */
122
-    private function updateCountrySubRegionDataVersion($version = '')
123
-    {
124
-        // add version option if it has never been added before, or update existing
125
-        if ($this->data_version === null) {
126
-            add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false);
127
-        } else {
128
-            update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version);
129
-        }
130
-    }
119
+	/**
120
+	 * @param string $version
121
+	 */
122
+	private function updateCountrySubRegionDataVersion($version = '')
123
+	{
124
+		// add version option if it has never been added before, or update existing
125
+		if ($this->data_version === null) {
126
+			add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false);
127
+		} else {
128
+			update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version);
129
+		}
130
+	}
131 131
 
132 132
 
133
-    /**
134
-     * @param string $CNT_ISO
135
-     * @param array  $countries
136
-     * @return int
137
-     * @throws EE_Error
138
-     * @throws InvalidArgumentException
139
-     * @throws InvalidDataTypeException
140
-     * @throws InvalidInterfaceException
141
-     * @throws ReflectionException
142
-     * @since 4.9.70.p
143
-     */
144
-    private function processCountryData($CNT_ISO, $countries = array())
145
-    {
146
-        if (! empty($countries)) {
147
-            foreach ($countries as $key => $country) {
148
-                if (
149
-                    $country instanceof stdClass
150
-                    && $country->code === $CNT_ISO
151
-                    && empty($country->sub_regions)
152
-                    && ! empty($country->filename)
153
-                ) {
154
-                    $country->sub_regions = $this->retrieveJsonData(
155
-                        self::REPO_URL . 'countries/' . $country->filename . '.json'
156
-                    );
157
-                    return $this->saveSubRegionData($country, $country->sub_regions);
158
-                }
159
-            }
160
-        }
161
-        return 0;
162
-    }
133
+	/**
134
+	 * @param string $CNT_ISO
135
+	 * @param array  $countries
136
+	 * @return int
137
+	 * @throws EE_Error
138
+	 * @throws InvalidArgumentException
139
+	 * @throws InvalidDataTypeException
140
+	 * @throws InvalidInterfaceException
141
+	 * @throws ReflectionException
142
+	 * @since 4.9.70.p
143
+	 */
144
+	private function processCountryData($CNT_ISO, $countries = array())
145
+	{
146
+		if (! empty($countries)) {
147
+			foreach ($countries as $key => $country) {
148
+				if (
149
+					$country instanceof stdClass
150
+					&& $country->code === $CNT_ISO
151
+					&& empty($country->sub_regions)
152
+					&& ! empty($country->filename)
153
+				) {
154
+					$country->sub_regions = $this->retrieveJsonData(
155
+						self::REPO_URL . 'countries/' . $country->filename . '.json'
156
+					);
157
+					return $this->saveSubRegionData($country, $country->sub_regions);
158
+				}
159
+			}
160
+		}
161
+		return 0;
162
+	}
163 163
 
164 164
 
165
-    /**
166
-     * @param string $url
167
-     * @return array
168
-     */
169
-    private function retrieveJsonData($url)
170
-    {
171
-        if (empty($url)) {
172
-            EE_Error::add_error(
173
-                'No URL was provided!',
174
-                __FILE__,
175
-                __METHOD__,
176
-                __LINE__
177
-            );
178
-            return array();
179
-        }
180
-        $request = wp_safe_remote_get($url);
181
-        if ($request instanceof WP_Error) {
182
-            EE_Error::add_error(
183
-                $request->get_error_message(),
184
-                __FILE__,
185
-                __METHOD__,
186
-                __LINE__
187
-            );
188
-            return array();
189
-        }
190
-        $body = wp_remote_retrieve_body($request);
191
-        $json = json_decode($body);
192
-        if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) {
193
-            return $json;
194
-        }
195
-        return array();
196
-    }
165
+	/**
166
+	 * @param string $url
167
+	 * @return array
168
+	 */
169
+	private function retrieveJsonData($url)
170
+	{
171
+		if (empty($url)) {
172
+			EE_Error::add_error(
173
+				'No URL was provided!',
174
+				__FILE__,
175
+				__METHOD__,
176
+				__LINE__
177
+			);
178
+			return array();
179
+		}
180
+		$request = wp_safe_remote_get($url);
181
+		if ($request instanceof WP_Error) {
182
+			EE_Error::add_error(
183
+				$request->get_error_message(),
184
+				__FILE__,
185
+				__METHOD__,
186
+				__LINE__
187
+			);
188
+			return array();
189
+		}
190
+		$body = wp_remote_retrieve_body($request);
191
+		$json = json_decode($body);
192
+		if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) {
193
+			return $json;
194
+		}
195
+		return array();
196
+	}
197 197
 
198 198
 
199
-    /**
200
-     * @param stdClass $country
201
-     * @param array    $sub_regions
202
-     * @return int
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function saveSubRegionData(stdClass $country, $sub_regions = array())
210
-    {
211
-        $results = 0;
212
-        if (is_array($sub_regions)) {
213
-            $existing_sub_regions = $this->getExistingStateAbbreviations($country->code);
214
-            foreach ($sub_regions as $sub_region) {
215
-                // remove country code from sub region code
216
-                $abbrev = str_replace(
217
-                    $country->code . '-',
218
-                    '',
219
-                    sanitize_text_field($sub_region->code)
220
-                );
221
-                // but NOT if sub region code results in only a number
222
-                if (absint($abbrev) !== 0) {
223
-                    $abbrev = sanitize_text_field($sub_region->code);
224
-                }
225
-                if (
226
-                    ! in_array($abbrev, $existing_sub_regions, true)
227
-                    && $this->state_model->insert(
228
-                        [
229
-                            // STA_ID CNT_ISO STA_abbrev STA_name STA_active
230
-                            'CNT_ISO'    => $country->code,
231
-                            'STA_abbrev' => $abbrev,
232
-                            'STA_name'   => sanitize_text_field($sub_region->name),
233
-                            'STA_active' => 1,
234
-                        ]
235
-                    )
236
-                ) {
237
-                    $results++;
238
-                }
239
-            }
240
-        }
241
-        return $results;
242
-    }
199
+	/**
200
+	 * @param stdClass $country
201
+	 * @param array    $sub_regions
202
+	 * @return int
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function saveSubRegionData(stdClass $country, $sub_regions = array())
210
+	{
211
+		$results = 0;
212
+		if (is_array($sub_regions)) {
213
+			$existing_sub_regions = $this->getExistingStateAbbreviations($country->code);
214
+			foreach ($sub_regions as $sub_region) {
215
+				// remove country code from sub region code
216
+				$abbrev = str_replace(
217
+					$country->code . '-',
218
+					'',
219
+					sanitize_text_field($sub_region->code)
220
+				);
221
+				// but NOT if sub region code results in only a number
222
+				if (absint($abbrev) !== 0) {
223
+					$abbrev = sanitize_text_field($sub_region->code);
224
+				}
225
+				if (
226
+					! in_array($abbrev, $existing_sub_regions, true)
227
+					&& $this->state_model->insert(
228
+						[
229
+							// STA_ID CNT_ISO STA_abbrev STA_name STA_active
230
+							'CNT_ISO'    => $country->code,
231
+							'STA_abbrev' => $abbrev,
232
+							'STA_name'   => sanitize_text_field($sub_region->name),
233
+							'STA_active' => 1,
234
+						]
235
+					)
236
+				) {
237
+					$results++;
238
+				}
239
+			}
240
+		}
241
+		return $results;
242
+	}
243 243
 
244 244
 
245
-    /**
246
-     * @param string $CNT_ISO
247
-     * @since 4.9.76.p
248
-     * @return array
249
-     * @throws EE_Error
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     * @throws ReflectionException
254
-     */
255
-    private function getExistingStateAbbreviations($CNT_ISO)
256
-    {
257
-        $existing_sub_region_IDs = [];
258
-        $existing_sub_regions = $this->state_model->get_all(array(
259
-            array(
260
-                'Country.CNT_ISO' => array(
261
-                    'IN',
262
-                    [$CNT_ISO]
263
-                )
264
-            ),
265
-            'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC')
266
-        ));
267
-        if (is_array($existing_sub_regions)) {
268
-            foreach ($existing_sub_regions as $existing_sub_region) {
269
-                if ($existing_sub_region instanceof EE_State) {
270
-                    $existing_sub_region_IDs[] = $existing_sub_region->abbrev();
271
-                }
272
-            }
273
-        }
274
-        return $existing_sub_region_IDs;
275
-    }
245
+	/**
246
+	 * @param string $CNT_ISO
247
+	 * @since 4.9.76.p
248
+	 * @return array
249
+	 * @throws EE_Error
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 * @throws ReflectionException
254
+	 */
255
+	private function getExistingStateAbbreviations($CNT_ISO)
256
+	{
257
+		$existing_sub_region_IDs = [];
258
+		$existing_sub_regions = $this->state_model->get_all(array(
259
+			array(
260
+				'Country.CNT_ISO' => array(
261
+					'IN',
262
+					[$CNT_ISO]
263
+				)
264
+			),
265
+			'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC')
266
+		));
267
+		if (is_array($existing_sub_regions)) {
268
+			foreach ($existing_sub_regions as $existing_sub_region) {
269
+				if ($existing_sub_region instanceof EE_State) {
270
+					$existing_sub_region_IDs[] = $existing_sub_region->abbrev();
271
+				}
272
+			}
273
+		}
274
+		return $existing_sub_region_IDs;
275
+	}
276 276
 }
Please login to merge, or discard this patch.
core/services/payment_methods/forms/PayPalSettingsForm.php 1 patch
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -20,202 +20,202 @@
 block discarded – undo
20 20
  */
21 21
 class PayPalSettingsForm extends EE_Payment_Method_Form
22 22
 {
23
-    /**
24
-     * @var string of HTML being the help tab link
25
-     */
26
-    protected $helpTabLink;
23
+	/**
24
+	 * @var string of HTML being the help tab link
25
+	 */
26
+	protected $helpTabLink;
27 27
 
28
-    public function __construct(array $options_array = array(), $help_tab_link = '')
29
-    {
30
-        $this->helpTabLink = $help_tab_link;
31
-        $options_array = array_replace_recursive(
32
-            array(
33
-                'extra_meta_inputs' => array(
34
-                    'api_username' => new EE_Text_Input(
35
-                        array(
36
-                            'html_label_text' => sprintf(
37
-                                // translators: %s link to help doc
38
-                                esc_html__('API Username %s', 'event_espresso'),
39
-                                $help_tab_link
40
-                            ),
41
-                            'required'        => true,
42
-                        )
43
-                    ),
44
-                    'api_password' => new EE_Text_Input(
45
-                        array(
46
-                            'html_label_text' => sprintf(
47
-                                // translators: %s link to help doc
48
-                                esc_html__('API Password %s', 'event_espresso'),
49
-                                $help_tab_link
50
-                            ),
51
-                            'required'        => true,
52
-                        )
53
-                    ),
54
-                    'api_signature' => new EE_Text_Input(
55
-                        array(
56
-                            'html_label_text' => sprintf(
57
-                                // translators: %s link to help doc
58
-                                esc_html__('API Signature %s', 'event_espresso'),
59
-                                $help_tab_link
60
-                            ),
61
-                            'required'        => true,
62
-                        )
63
-                    ),
64
-                )
65
-            ),
66
-            $options_array
67
-        );
68
-        parent::__construct($options_array);
69
-    }
28
+	public function __construct(array $options_array = array(), $help_tab_link = '')
29
+	{
30
+		$this->helpTabLink = $help_tab_link;
31
+		$options_array = array_replace_recursive(
32
+			array(
33
+				'extra_meta_inputs' => array(
34
+					'api_username' => new EE_Text_Input(
35
+						array(
36
+							'html_label_text' => sprintf(
37
+								// translators: %s link to help doc
38
+								esc_html__('API Username %s', 'event_espresso'),
39
+								$help_tab_link
40
+							),
41
+							'required'        => true,
42
+						)
43
+					),
44
+					'api_password' => new EE_Text_Input(
45
+						array(
46
+							'html_label_text' => sprintf(
47
+								// translators: %s link to help doc
48
+								esc_html__('API Password %s', 'event_espresso'),
49
+								$help_tab_link
50
+							),
51
+							'required'        => true,
52
+						)
53
+					),
54
+					'api_signature' => new EE_Text_Input(
55
+						array(
56
+							'html_label_text' => sprintf(
57
+								// translators: %s link to help doc
58
+								esc_html__('API Signature %s', 'event_espresso'),
59
+								$help_tab_link
60
+							),
61
+							'required'        => true,
62
+						)
63
+					),
64
+				)
65
+			),
66
+			$options_array
67
+		);
68
+		parent::__construct($options_array);
69
+	}
70 70
 
71
-    /**
72
-     * Tests the the PayPal API credentials work ok
73
-     * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string
74
-     * @throws EE_Error
75
-     */
76
-    protected function checkForCredentialsErrors()
77
-    {
78
-        $request_params = array(
79
-            'METHOD'    => 'GetBalance',
80
-            'VERSION'   => '204.0',
81
-            'USER'      => $this->get_input_value('api_username'),
82
-            'PWD'       => $this->get_input_value('api_password'),
83
-            'SIGNATURE' => $this->get_input_value('api_signature'),
84
-        );
85
-        $gateway_url = $this->get_input_value('PMD_debug_mode')
86
-            ? 'https://api-3t.sandbox.paypal.com/nvp'
87
-            : 'https://api-3t.paypal.com/nvp';
88
-        // Request Customer Details.
89
-        $response = wp_remote_post(
90
-            $gateway_url,
91
-            array(
92
-                'method'      => 'POST',
93
-                'timeout'     => 45,
94
-                'httpversion' => '1.1',
95
-                'cookies'     => array(),
96
-                'headers'     => array(),
97
-                'body'        => http_build_query($request_params, '', '&'),
98
-            )
99
-        );
100
-        if (is_wp_error($response) || empty($response['body'])) {
101
-            // If we got here then there was an error in this request.
102
-            // maybe is turned off. We don't know the credentials are invalid
103
-            EE_Error::add_error(
104
-                sprintf(
105
-                    // translators: %1$s Error message received from PayPal
106
-                    esc_html__(
107
-                        // @codingStandardsIgnoreStart
108
-                        'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s',
109
-                        // @codingStandardsIgnoreEnd
110
-                        'event_espresso'
111
-                    ),
112
-                    $response->get_error_message()
113
-                ),
114
-                __FILE__,
115
-                __FUNCTION__,
116
-                __LINE__
117
-            );
118
-        }
119
-        $response_args = array();
120
-        parse_str(urldecode($response['body']), $response_args);
71
+	/**
72
+	 * Tests the the PayPal API credentials work ok
73
+	 * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string
74
+	 * @throws EE_Error
75
+	 */
76
+	protected function checkForCredentialsErrors()
77
+	{
78
+		$request_params = array(
79
+			'METHOD'    => 'GetBalance',
80
+			'VERSION'   => '204.0',
81
+			'USER'      => $this->get_input_value('api_username'),
82
+			'PWD'       => $this->get_input_value('api_password'),
83
+			'SIGNATURE' => $this->get_input_value('api_signature'),
84
+		);
85
+		$gateway_url = $this->get_input_value('PMD_debug_mode')
86
+			? 'https://api-3t.sandbox.paypal.com/nvp'
87
+			: 'https://api-3t.paypal.com/nvp';
88
+		// Request Customer Details.
89
+		$response = wp_remote_post(
90
+			$gateway_url,
91
+			array(
92
+				'method'      => 'POST',
93
+				'timeout'     => 45,
94
+				'httpversion' => '1.1',
95
+				'cookies'     => array(),
96
+				'headers'     => array(),
97
+				'body'        => http_build_query($request_params, '', '&'),
98
+			)
99
+		);
100
+		if (is_wp_error($response) || empty($response['body'])) {
101
+			// If we got here then there was an error in this request.
102
+			// maybe is turned off. We don't know the credentials are invalid
103
+			EE_Error::add_error(
104
+				sprintf(
105
+					// translators: %1$s Error message received from PayPal
106
+					esc_html__(
107
+						// @codingStandardsIgnoreStart
108
+						'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s',
109
+						// @codingStandardsIgnoreEnd
110
+						'event_espresso'
111
+					),
112
+					$response->get_error_message()
113
+				),
114
+				__FILE__,
115
+				__FUNCTION__,
116
+				__LINE__
117
+			);
118
+		}
119
+		$response_args = array();
120
+		parse_str(urldecode($response['body']), $response_args);
121 121
 
122
-        if (empty($response_args['ACK'])) {
123
-            EE_Error::add_error(
124
-                esc_html__(
125
-                    'Your PayPal credentials could not be verified. Part of their response was missing.',
126
-                    'event_espresso'
127
-                ),
128
-                __FILE__,
129
-                __FUNCTION__,
130
-                __LINE__
131
-            );
132
-        }
133
-        if (
134
-            in_array(
135
-                $response_args['ACK'],
136
-                array(
137
-                'Success',
138
-                'SuccessWithWarning'
139
-                ),
140
-                true
141
-            )
142
-        ) {
143
-            return '';
144
-        } else {
145
-            return sprintf(
146
-                // translators: %1$s: PayPal response message, %2$s: PayPal response code
147
-                esc_html__(
148
-                    // @codingStandardsIgnoreStart
149
-                    'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.',
150
-                    // @codingStandardsIgnoreEnd
151
-                    'event_espresso'
152
-                ),
153
-                isset($response_args['L_LONGMESSAGE0'])
154
-                    ? $response_args['L_LONGMESSAGE0']
155
-                    : esc_html__('No error message received from PayPal', 'event_espresso'),
156
-                isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0
157
-            );
158
-        }
159
-    }
122
+		if (empty($response_args['ACK'])) {
123
+			EE_Error::add_error(
124
+				esc_html__(
125
+					'Your PayPal credentials could not be verified. Part of their response was missing.',
126
+					'event_espresso'
127
+				),
128
+				__FILE__,
129
+				__FUNCTION__,
130
+				__LINE__
131
+			);
132
+		}
133
+		if (
134
+			in_array(
135
+				$response_args['ACK'],
136
+				array(
137
+				'Success',
138
+				'SuccessWithWarning'
139
+				),
140
+				true
141
+			)
142
+		) {
143
+			return '';
144
+		} else {
145
+			return sprintf(
146
+				// translators: %1$s: PayPal response message, %2$s: PayPal response code
147
+				esc_html__(
148
+					// @codingStandardsIgnoreStart
149
+					'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.',
150
+					// @codingStandardsIgnoreEnd
151
+					'event_espresso'
152
+				),
153
+				isset($response_args['L_LONGMESSAGE0'])
154
+					? $response_args['L_LONGMESSAGE0']
155
+					: esc_html__('No error message received from PayPal', 'event_espresso'),
156
+				isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0
157
+			);
158
+		}
159
+	}
160 160
 
161
-    /**
162
-     * Gets the HTML to show the link to the help tab
163
-     * @return string
164
-     */
165
-    protected function helpTabLink()
166
-    {
167
-        return $this->helpTabLink;
168
-    }
161
+	/**
162
+	 * Gets the HTML to show the link to the help tab
163
+	 * @return string
164
+	 */
165
+	protected function helpTabLink()
166
+	{
167
+		return $this->helpTabLink;
168
+	}
169 169
 
170
-    /**
171
-     * Does the normal validation, but also verifies the PayPal API credentials work.
172
-     * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more
173
-     * tips) on each of the inputs that could be the cause of the problem.
174
-     * @throws EE_Error
175
-     */
176
-    public function _validate()
177
-    {
178
-        parent::_validate();
179
-        $credentials_message = $this->checkForCredentialsErrors();
180
-        if ($credentials_message !== '') {
181
-            $this->add_validation_error($credentials_message);
182
-            $this->get_input('PMD_debug_mode')->add_validation_error(
183
-                esc_html__(
184
-                    // @codingStandardsIgnoreStart
185
-                    'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".',
186
-                    // @codingStandardsIgnoreEnd
187
-                    'event_espresso'
188
-                )
189
-            );
190
-            $this->get_input('api_username')->add_validation_error(
191
-                sprintf(
192
-                    // translators: $1$s HTML for a link to the help tab
193
-                    esc_html__(
194
-                        'Are you sure this is your API username, not your login username? %1$s',
195
-                        'event_espresso'
196
-                    ),
197
-                    $this->helpTabLink()
198
-                )
199
-            );
200
-            $this->get_input('api_password')->add_validation_error(
201
-                sprintf(
202
-                    // translators: $1$s HTML for a link to the help tab
203
-                    esc_html__(
204
-                        'Are you sure this is your API password, not your login password? %1$s',
205
-                        'event_espresso'
206
-                    ),
207
-                    $this->helpTabLink()
208
-                )
209
-            );
210
-            $this->get_input('api_signature')->add_validation_error(
211
-                sprintf(
212
-                    // translators: $1$s HTML for a link to the help tab
213
-                    esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'),
214
-                    $this->helpTabLink()
215
-                )
216
-            );
217
-        }
218
-    }
170
+	/**
171
+	 * Does the normal validation, but also verifies the PayPal API credentials work.
172
+	 * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more
173
+	 * tips) on each of the inputs that could be the cause of the problem.
174
+	 * @throws EE_Error
175
+	 */
176
+	public function _validate()
177
+	{
178
+		parent::_validate();
179
+		$credentials_message = $this->checkForCredentialsErrors();
180
+		if ($credentials_message !== '') {
181
+			$this->add_validation_error($credentials_message);
182
+			$this->get_input('PMD_debug_mode')->add_validation_error(
183
+				esc_html__(
184
+					// @codingStandardsIgnoreStart
185
+					'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".',
186
+					// @codingStandardsIgnoreEnd
187
+					'event_espresso'
188
+				)
189
+			);
190
+			$this->get_input('api_username')->add_validation_error(
191
+				sprintf(
192
+					// translators: $1$s HTML for a link to the help tab
193
+					esc_html__(
194
+						'Are you sure this is your API username, not your login username? %1$s',
195
+						'event_espresso'
196
+					),
197
+					$this->helpTabLink()
198
+				)
199
+			);
200
+			$this->get_input('api_password')->add_validation_error(
201
+				sprintf(
202
+					// translators: $1$s HTML for a link to the help tab
203
+					esc_html__(
204
+						'Are you sure this is your API password, not your login password? %1$s',
205
+						'event_espresso'
206
+					),
207
+					$this->helpTabLink()
208
+				)
209
+			);
210
+			$this->get_input('api_signature')->add_validation_error(
211
+				sprintf(
212
+					// translators: $1$s HTML for a link to the help tab
213
+					esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'),
214
+					$this->helpTabLink()
215
+				)
216
+			);
217
+		}
218
+	}
219 219
 }
220 220
 // End of file PayPalSettingsForm.php
221 221
 // Location: ${NAMESPACE}/PayPalSettingsForm.php
Please login to merge, or discard this patch.
core/services/collections/CollectionDetails.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
      */
194 194
     protected function setCollectionInterface($collection_interface)
195 195
     {
196
-        if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
196
+        if ( ! (interface_exists($collection_interface) || class_exists($collection_interface))) {
197 197
             throw new InvalidInterfaceException($collection_interface);
198 198
         }
199 199
         $this->collection_interface = $collection_interface;
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
      */
222 222
     protected function setCollectionName($collection_name)
223 223
     {
224
-        if (! is_string($collection_name)) {
224
+        if ( ! is_string($collection_name)) {
225 225
             throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
226 226
         }
227 227
         $this->collection_name = str_replace(
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
      */
282 282
     protected function setIdentifierCallback($identifier_callback = 'identifier')
283 283
     {
284
-        if (! is_string($identifier_callback)) {
284
+        if ( ! is_string($identifier_callback)) {
285 285
             throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
286 286
         }
287 287
         $this->identifier_callback = $identifier_callback;
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
         $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
312 312
         // we know our default is a string, so if it's not a string now,
313 313
         // then that means the incoming parameter was something else
314
-        if (! is_string($this->file_mask)) {
314
+        if ( ! is_string($this->file_mask)) {
315 315
             throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
316 316
         }
317 317
     }
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
     public function setCollectionFQCNs($collection_FQCNs)
337 337
     {
338 338
         foreach ((array) $collection_FQCNs as $collection_FQCN) {
339
-            if (! empty($collection_FQCN)) {
339
+            if ( ! empty($collection_FQCN)) {
340 340
                 if (class_exists($collection_FQCN)) {
341 341
                     $this->collection_FQCNs[] = $collection_FQCN;
342 342
                 } else {
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
      */
359 359
     protected function getFQCNsFromPartialNamespace($partial_FQCN)
360 360
     {
361
-        if (! $this->file_locator instanceof FqcnLocator) {
361
+        if ( ! $this->file_locator instanceof FqcnLocator) {
362 362
             $this->file_locator = new FqcnLocator();
363 363
         }
364 364
         $this->file_locator->locate($partial_FQCN);
@@ -384,8 +384,8 @@  discard block
 block discarded – undo
384 384
     public function setCollectionPaths($collection_paths)
385 385
     {
386 386
         foreach ((array) $collection_paths as $collection_path) {
387
-            if (! empty($collection_path)) {
388
-                if (! is_readable($collection_path)) {
387
+            if ( ! empty($collection_path)) {
388
+                if ( ! is_readable($collection_path)) {
389 389
                     throw new InvalidFilePathException($collection_path);
390 390
                 }
391 391
                 $this->collection_paths[] = $collection_path;
Please login to merge, or discard this patch.
Indentation   +349 added lines, -349 removed lines patch added patch discarded remove patch
@@ -43,353 +43,353 @@
 block discarded – undo
43 43
  */
44 44
 class CollectionDetails implements CollectionDetailsInterface
45 45
 {
46
-    /**
47
-     * if $identifier_type is set to this,
48
-     * then the collection will use each object's spl_object_hash() as it's identifier
49
-     */
50
-    const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash';
51
-
52
-    /**
53
-     * if $identifier_type is set to this,
54
-     * then the collection will use each object's class name as it's identifier
55
-     */
56
-    const ID_CLASS_NAME = 'identifier-uses-object-class-name';
57
-
58
-    /**
59
-     * if $identifier_type is set to this,
60
-     * then the collection will use the return value from a specified callback method on each object
61
-     */
62
-    const ID_CALLBACK_METHOD = 'identifier-uses-callback-method';
63
-
64
-    /**
65
-     * The interface used for controlling what gets added to the collection
66
-     *
67
-     * @var string $collection_interface
68
-     */
69
-    protected $collection_interface = '';
70
-
71
-    /**
72
-     * a unique name used to identify the collection in filter names
73
-     * supplied value is run through sanitize_title_with_dashes(),
74
-     * but then also converts dashes to underscores
75
-     *
76
-     * @var string $collection_name
77
-     */
78
-    protected $collection_name = '';
79
-
80
-    /**
81
-     * what the collection uses for the object identifier.
82
-     * corresponds to one of the class constants above.
83
-     * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier
84
-     * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier
85
-     * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier
86
-     * defaults to using spl_object_hash() so that multiple objects of the same class can be added
87
-     *
88
-     * @var string $identifier_type
89
-     */
90
-    protected $identifier_type = CollectionDetails::ID_OBJECT_HASH;
91
-
92
-    /**
93
-     * the pattern applied to paths when searching for class files to add to the collection
94
-     * ie: "My_Awesome_*.class.php"
95
-     * defaults to "*.php"
96
-     *
97
-     * @var string $file_mask
98
-     */
99
-    protected $file_mask = '';
100
-
101
-    /**
102
-     * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD,
103
-     * then this specifies the method to use on each entity.
104
-     * If the callback method does not exist, then an exception will be thrown
105
-     *
106
-     * @var string $identifier_callback
107
-     */
108
-    protected $identifier_callback = '';
109
-
110
-    /**
111
-     * an array of Fully Qualified Class Names
112
-     *  for example:
113
-     *  $FQCNs = array(
114
-     *      '/Fully/Qualified/ClassNameA'
115
-     *      '/Fully/Qualified/Other/ClassNameB'
116
-     *  );
117
-     *
118
-     * @var array $collection_FQCNs
119
-     */
120
-    protected $collection_FQCNs = array();
121
-
122
-    /**
123
-     * an array of full server paths to folders containing files to be loaded into collection
124
-     *  for example:
125
-     *  $paths = array(
126
-     *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
127
-     *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
128
-     *  );
129
-     *
130
-     * @var array $collection_paths
131
-     */
132
-    protected $collection_paths = array();
133
-
134
-    /**
135
-     * @var LocatorInterface $file_locator
136
-     */
137
-    protected $file_locator;
138
-
139
-
140
-    /**
141
-     * CollectionDetails constructor.
142
-     *
143
-     * @access public
144
-     * @param string           $collection_name
145
-     * @param string           $collection_interface
146
-     * @param array            $collection_FQCNs
147
-     * @param array            $collection_paths
148
-     * @param string           $file_mask
149
-     * @param string           $identifier_type
150
-     * @param string           $identifier_callback
151
-     * @param LocatorInterface $file_locator
152
-     * @throws CollectionDetailsException
153
-     */
154
-    public function __construct(
155
-        $collection_name,
156
-        $collection_interface,
157
-        array $collection_FQCNs = array(),
158
-        array $collection_paths = array(),
159
-        $file_mask = '',
160
-        $identifier_type = CollectionDetails::ID_OBJECT_HASH,
161
-        $identifier_callback = '',
162
-        LocatorInterface $file_locator = null
163
-    ) {
164
-        try {
165
-            $this->setCollectionName($collection_name);
166
-            $this->setCollectionInterface($collection_interface);
167
-            $this->setCollectionFQCNs($collection_FQCNs);
168
-            $this->setCollectionPaths($collection_paths);
169
-            $this->setFileMasks($file_mask);
170
-            $this->setIdentifierType($identifier_type);
171
-            $this->setIdentifierCallback($identifier_callback);
172
-            $this->file_locator = $file_locator;
173
-        } catch (Exception $exception) {
174
-            throw new CollectionDetailsException($exception);
175
-        }
176
-    }
177
-
178
-
179
-    /**
180
-     * @access public
181
-     * @return mixed
182
-     */
183
-    public function getCollectionInterface()
184
-    {
185
-        return $this->collection_interface;
186
-    }
187
-
188
-
189
-    /**
190
-     * @access protected
191
-     * @param string $collection_interface
192
-     * @throws InvalidInterfaceException
193
-     */
194
-    protected function setCollectionInterface($collection_interface)
195
-    {
196
-        if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
197
-            throw new InvalidInterfaceException($collection_interface);
198
-        }
199
-        $this->collection_interface = $collection_interface;
200
-    }
201
-
202
-
203
-    /**
204
-     * the collection name will be used for creating dynamic filters
205
-     *
206
-     * @access public
207
-     * @return string
208
-     */
209
-    public function collectionName()
210
-    {
211
-        return $this->collection_name;
212
-    }
213
-
214
-
215
-    /**
216
-     * sanitizes collection name and converts spaces and dashes to underscores
217
-     *
218
-     * @access protected
219
-     * @param string $collection_name
220
-     * @throws InvalidDataTypeException
221
-     */
222
-    protected function setCollectionName($collection_name)
223
-    {
224
-        if (! is_string($collection_name)) {
225
-            throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
226
-        }
227
-        $this->collection_name = str_replace(
228
-            '-',
229
-            '_',
230
-            sanitize_title_with_dashes($collection_name, '', 'save')
231
-        );
232
-    }
233
-
234
-
235
-    /**
236
-     * @access public
237
-     * @return string
238
-     */
239
-    public function identifierType()
240
-    {
241
-        return $this->identifier_type;
242
-    }
243
-
244
-
245
-    /**
246
-     * @access protected
247
-     * @param string $identifier_type
248
-     * @throws InvalidIdentifierException
249
-     */
250
-    protected function setIdentifierType($identifier_type)
251
-    {
252
-        if (
253
-            ! ($identifier_type === CollectionDetails::ID_CLASS_NAME
254
-               || $identifier_type === CollectionDetails::ID_OBJECT_HASH
255
-               || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD
256
-            )
257
-        ) {
258
-            throw new InvalidIdentifierException(
259
-                $identifier_type,
260
-                'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD'
261
-            );
262
-        }
263
-        $this->identifier_type = $identifier_type;
264
-    }
265
-
266
-
267
-    /**
268
-     * @access public
269
-     * @return string
270
-     */
271
-    public function identifierCallback()
272
-    {
273
-        return $this->identifier_callback;
274
-    }
275
-
276
-
277
-    /**
278
-     * @access protected
279
-     * @param string $identifier_callback
280
-     * @throws InvalidDataTypeException
281
-     */
282
-    protected function setIdentifierCallback($identifier_callback = 'identifier')
283
-    {
284
-        if (! is_string($identifier_callback)) {
285
-            throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
286
-        }
287
-        $this->identifier_callback = $identifier_callback;
288
-    }
289
-
290
-
291
-    /**
292
-     * @access public
293
-     * @return string
294
-     */
295
-    public function getFileMask()
296
-    {
297
-        return $this->file_mask;
298
-    }
299
-
300
-
301
-    /**
302
-     * sets the file mask which is then used to filter what files get loaded
303
-     * when searching for classes to add to the collection. Defaults to '*.php'
304
-     *
305
-     * @access protected
306
-     * @param string $file_mask
307
-     * @throws InvalidDataTypeException
308
-     */
309
-    protected function setFileMasks($file_mask)
310
-    {
311
-        $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
312
-        // we know our default is a string, so if it's not a string now,
313
-        // then that means the incoming parameter was something else
314
-        if (! is_string($this->file_mask)) {
315
-            throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
316
-        }
317
-    }
318
-
319
-
320
-    /**
321
-     * @access public
322
-     * @return array
323
-     */
324
-    public function getCollectionFQCNs()
325
-    {
326
-        return $this->collection_FQCNs;
327
-    }
328
-
329
-
330
-    /**
331
-     * @access public
332
-     * @param string|array $collection_FQCNs
333
-     * @throws InvalidClassException
334
-     * @throws InvalidDataTypeException
335
-     */
336
-    public function setCollectionFQCNs($collection_FQCNs)
337
-    {
338
-        foreach ((array) $collection_FQCNs as $collection_FQCN) {
339
-            if (! empty($collection_FQCN)) {
340
-                if (class_exists($collection_FQCN)) {
341
-                    $this->collection_FQCNs[] = $collection_FQCN;
342
-                } else {
343
-                    foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) {
344
-                        $this->collection_FQCNs[] = $FQCN;
345
-                    }
346
-                }
347
-            }
348
-        }
349
-    }
350
-
351
-
352
-    /**
353
-     * @access protected
354
-     * @param  string $partial_FQCN
355
-     * @return array
356
-     * @throws InvalidDataTypeException
357
-     * @throws InvalidClassException
358
-     */
359
-    protected function getFQCNsFromPartialNamespace($partial_FQCN)
360
-    {
361
-        if (! $this->file_locator instanceof FqcnLocator) {
362
-            $this->file_locator = new FqcnLocator();
363
-        }
364
-        $this->file_locator->locate($partial_FQCN);
365
-        return $this->file_locator->getFQCNs();
366
-    }
367
-
368
-
369
-    /**
370
-     * @access public
371
-     * @return array
372
-     */
373
-    public function getCollectionPaths()
374
-    {
375
-        return $this->collection_paths;
376
-    }
377
-
378
-
379
-    /**
380
-     * @access public
381
-     * @param string|array $collection_paths
382
-     * @throws InvalidFilePathException
383
-     */
384
-    public function setCollectionPaths($collection_paths)
385
-    {
386
-        foreach ((array) $collection_paths as $collection_path) {
387
-            if (! empty($collection_path)) {
388
-                if (! is_readable($collection_path)) {
389
-                    throw new InvalidFilePathException($collection_path);
390
-                }
391
-                $this->collection_paths[] = $collection_path;
392
-            }
393
-        }
394
-    }
46
+	/**
47
+	 * if $identifier_type is set to this,
48
+	 * then the collection will use each object's spl_object_hash() as it's identifier
49
+	 */
50
+	const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash';
51
+
52
+	/**
53
+	 * if $identifier_type is set to this,
54
+	 * then the collection will use each object's class name as it's identifier
55
+	 */
56
+	const ID_CLASS_NAME = 'identifier-uses-object-class-name';
57
+
58
+	/**
59
+	 * if $identifier_type is set to this,
60
+	 * then the collection will use the return value from a specified callback method on each object
61
+	 */
62
+	const ID_CALLBACK_METHOD = 'identifier-uses-callback-method';
63
+
64
+	/**
65
+	 * The interface used for controlling what gets added to the collection
66
+	 *
67
+	 * @var string $collection_interface
68
+	 */
69
+	protected $collection_interface = '';
70
+
71
+	/**
72
+	 * a unique name used to identify the collection in filter names
73
+	 * supplied value is run through sanitize_title_with_dashes(),
74
+	 * but then also converts dashes to underscores
75
+	 *
76
+	 * @var string $collection_name
77
+	 */
78
+	protected $collection_name = '';
79
+
80
+	/**
81
+	 * what the collection uses for the object identifier.
82
+	 * corresponds to one of the class constants above.
83
+	 * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier
84
+	 * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier
85
+	 * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier
86
+	 * defaults to using spl_object_hash() so that multiple objects of the same class can be added
87
+	 *
88
+	 * @var string $identifier_type
89
+	 */
90
+	protected $identifier_type = CollectionDetails::ID_OBJECT_HASH;
91
+
92
+	/**
93
+	 * the pattern applied to paths when searching for class files to add to the collection
94
+	 * ie: "My_Awesome_*.class.php"
95
+	 * defaults to "*.php"
96
+	 *
97
+	 * @var string $file_mask
98
+	 */
99
+	protected $file_mask = '';
100
+
101
+	/**
102
+	 * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD,
103
+	 * then this specifies the method to use on each entity.
104
+	 * If the callback method does not exist, then an exception will be thrown
105
+	 *
106
+	 * @var string $identifier_callback
107
+	 */
108
+	protected $identifier_callback = '';
109
+
110
+	/**
111
+	 * an array of Fully Qualified Class Names
112
+	 *  for example:
113
+	 *  $FQCNs = array(
114
+	 *      '/Fully/Qualified/ClassNameA'
115
+	 *      '/Fully/Qualified/Other/ClassNameB'
116
+	 *  );
117
+	 *
118
+	 * @var array $collection_FQCNs
119
+	 */
120
+	protected $collection_FQCNs = array();
121
+
122
+	/**
123
+	 * an array of full server paths to folders containing files to be loaded into collection
124
+	 *  for example:
125
+	 *  $paths = array(
126
+	 *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
127
+	 *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
128
+	 *  );
129
+	 *
130
+	 * @var array $collection_paths
131
+	 */
132
+	protected $collection_paths = array();
133
+
134
+	/**
135
+	 * @var LocatorInterface $file_locator
136
+	 */
137
+	protected $file_locator;
138
+
139
+
140
+	/**
141
+	 * CollectionDetails constructor.
142
+	 *
143
+	 * @access public
144
+	 * @param string           $collection_name
145
+	 * @param string           $collection_interface
146
+	 * @param array            $collection_FQCNs
147
+	 * @param array            $collection_paths
148
+	 * @param string           $file_mask
149
+	 * @param string           $identifier_type
150
+	 * @param string           $identifier_callback
151
+	 * @param LocatorInterface $file_locator
152
+	 * @throws CollectionDetailsException
153
+	 */
154
+	public function __construct(
155
+		$collection_name,
156
+		$collection_interface,
157
+		array $collection_FQCNs = array(),
158
+		array $collection_paths = array(),
159
+		$file_mask = '',
160
+		$identifier_type = CollectionDetails::ID_OBJECT_HASH,
161
+		$identifier_callback = '',
162
+		LocatorInterface $file_locator = null
163
+	) {
164
+		try {
165
+			$this->setCollectionName($collection_name);
166
+			$this->setCollectionInterface($collection_interface);
167
+			$this->setCollectionFQCNs($collection_FQCNs);
168
+			$this->setCollectionPaths($collection_paths);
169
+			$this->setFileMasks($file_mask);
170
+			$this->setIdentifierType($identifier_type);
171
+			$this->setIdentifierCallback($identifier_callback);
172
+			$this->file_locator = $file_locator;
173
+		} catch (Exception $exception) {
174
+			throw new CollectionDetailsException($exception);
175
+		}
176
+	}
177
+
178
+
179
+	/**
180
+	 * @access public
181
+	 * @return mixed
182
+	 */
183
+	public function getCollectionInterface()
184
+	{
185
+		return $this->collection_interface;
186
+	}
187
+
188
+
189
+	/**
190
+	 * @access protected
191
+	 * @param string $collection_interface
192
+	 * @throws InvalidInterfaceException
193
+	 */
194
+	protected function setCollectionInterface($collection_interface)
195
+	{
196
+		if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
197
+			throw new InvalidInterfaceException($collection_interface);
198
+		}
199
+		$this->collection_interface = $collection_interface;
200
+	}
201
+
202
+
203
+	/**
204
+	 * the collection name will be used for creating dynamic filters
205
+	 *
206
+	 * @access public
207
+	 * @return string
208
+	 */
209
+	public function collectionName()
210
+	{
211
+		return $this->collection_name;
212
+	}
213
+
214
+
215
+	/**
216
+	 * sanitizes collection name and converts spaces and dashes to underscores
217
+	 *
218
+	 * @access protected
219
+	 * @param string $collection_name
220
+	 * @throws InvalidDataTypeException
221
+	 */
222
+	protected function setCollectionName($collection_name)
223
+	{
224
+		if (! is_string($collection_name)) {
225
+			throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
226
+		}
227
+		$this->collection_name = str_replace(
228
+			'-',
229
+			'_',
230
+			sanitize_title_with_dashes($collection_name, '', 'save')
231
+		);
232
+	}
233
+
234
+
235
+	/**
236
+	 * @access public
237
+	 * @return string
238
+	 */
239
+	public function identifierType()
240
+	{
241
+		return $this->identifier_type;
242
+	}
243
+
244
+
245
+	/**
246
+	 * @access protected
247
+	 * @param string $identifier_type
248
+	 * @throws InvalidIdentifierException
249
+	 */
250
+	protected function setIdentifierType($identifier_type)
251
+	{
252
+		if (
253
+			! ($identifier_type === CollectionDetails::ID_CLASS_NAME
254
+			   || $identifier_type === CollectionDetails::ID_OBJECT_HASH
255
+			   || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD
256
+			)
257
+		) {
258
+			throw new InvalidIdentifierException(
259
+				$identifier_type,
260
+				'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD'
261
+			);
262
+		}
263
+		$this->identifier_type = $identifier_type;
264
+	}
265
+
266
+
267
+	/**
268
+	 * @access public
269
+	 * @return string
270
+	 */
271
+	public function identifierCallback()
272
+	{
273
+		return $this->identifier_callback;
274
+	}
275
+
276
+
277
+	/**
278
+	 * @access protected
279
+	 * @param string $identifier_callback
280
+	 * @throws InvalidDataTypeException
281
+	 */
282
+	protected function setIdentifierCallback($identifier_callback = 'identifier')
283
+	{
284
+		if (! is_string($identifier_callback)) {
285
+			throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
286
+		}
287
+		$this->identifier_callback = $identifier_callback;
288
+	}
289
+
290
+
291
+	/**
292
+	 * @access public
293
+	 * @return string
294
+	 */
295
+	public function getFileMask()
296
+	{
297
+		return $this->file_mask;
298
+	}
299
+
300
+
301
+	/**
302
+	 * sets the file mask which is then used to filter what files get loaded
303
+	 * when searching for classes to add to the collection. Defaults to '*.php'
304
+	 *
305
+	 * @access protected
306
+	 * @param string $file_mask
307
+	 * @throws InvalidDataTypeException
308
+	 */
309
+	protected function setFileMasks($file_mask)
310
+	{
311
+		$this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
312
+		// we know our default is a string, so if it's not a string now,
313
+		// then that means the incoming parameter was something else
314
+		if (! is_string($this->file_mask)) {
315
+			throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
316
+		}
317
+	}
318
+
319
+
320
+	/**
321
+	 * @access public
322
+	 * @return array
323
+	 */
324
+	public function getCollectionFQCNs()
325
+	{
326
+		return $this->collection_FQCNs;
327
+	}
328
+
329
+
330
+	/**
331
+	 * @access public
332
+	 * @param string|array $collection_FQCNs
333
+	 * @throws InvalidClassException
334
+	 * @throws InvalidDataTypeException
335
+	 */
336
+	public function setCollectionFQCNs($collection_FQCNs)
337
+	{
338
+		foreach ((array) $collection_FQCNs as $collection_FQCN) {
339
+			if (! empty($collection_FQCN)) {
340
+				if (class_exists($collection_FQCN)) {
341
+					$this->collection_FQCNs[] = $collection_FQCN;
342
+				} else {
343
+					foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) {
344
+						$this->collection_FQCNs[] = $FQCN;
345
+					}
346
+				}
347
+			}
348
+		}
349
+	}
350
+
351
+
352
+	/**
353
+	 * @access protected
354
+	 * @param  string $partial_FQCN
355
+	 * @return array
356
+	 * @throws InvalidDataTypeException
357
+	 * @throws InvalidClassException
358
+	 */
359
+	protected function getFQCNsFromPartialNamespace($partial_FQCN)
360
+	{
361
+		if (! $this->file_locator instanceof FqcnLocator) {
362
+			$this->file_locator = new FqcnLocator();
363
+		}
364
+		$this->file_locator->locate($partial_FQCN);
365
+		return $this->file_locator->getFQCNs();
366
+	}
367
+
368
+
369
+	/**
370
+	 * @access public
371
+	 * @return array
372
+	 */
373
+	public function getCollectionPaths()
374
+	{
375
+		return $this->collection_paths;
376
+	}
377
+
378
+
379
+	/**
380
+	 * @access public
381
+	 * @param string|array $collection_paths
382
+	 * @throws InvalidFilePathException
383
+	 */
384
+	public function setCollectionPaths($collection_paths)
385
+	{
386
+		foreach ((array) $collection_paths as $collection_path) {
387
+			if (! empty($collection_path)) {
388
+				if (! is_readable($collection_path)) {
389
+					throw new InvalidFilePathException($collection_path);
390
+				}
391
+				$this->collection_paths[] = $collection_path;
392
+			}
393
+		}
394
+	}
395 395
 }
Please login to merge, or discard this patch.
core/services/notifications/PersistentAdminNoticeManager.php 2 patches
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
      */
86 86
     public function setReturnUrl($return_url)
87 87
     {
88
-        if (! is_string($return_url)) {
88
+        if ( ! is_string($return_url)) {
89 89
             throw new InvalidDataTypeException('$return_url', $return_url, 'string');
90 90
         }
91 91
         $this->return_url = $return_url;
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      */
103 103
     protected function getPersistentAdminNoticeCollection()
104 104
     {
105
-        if (! $this->notice_collection instanceof Collection) {
105
+        if ( ! $this->notice_collection instanceof Collection) {
106 106
             $this->notice_collection = new Collection(
107 107
                 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
108 108
             );
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
     protected function retrieveStoredNotices()
126 126
     {
127 127
         $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
128
-        if (! empty($persistent_admin_notices)) {
128
+        if ( ! empty($persistent_admin_notices)) {
129 129
             foreach ($persistent_admin_notices as $name => $details) {
130 130
                 if (is_array($details)) {
131 131
                     if (
@@ -247,14 +247,14 @@  discard block
 block discarded – undo
247 247
     {
248 248
         wp_register_script(
249 249
             'espresso_core',
250
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
250
+            EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js',
251 251
             array('jquery'),
252 252
             EVENT_ESPRESSO_VERSION,
253 253
             true
254 254
         );
255 255
         wp_register_script(
256 256
             'ee_error_js',
257
-            EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
257
+            EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js',
258 258
             array('espresso_core'),
259 259
             EVENT_ESPRESSO_VERSION,
260 260
             true
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
         // used in template
286 286
         $persistent_admin_notice_name = $persistent_admin_notice->getName();
287 287
         $persistent_admin_notice_message = $persistent_admin_notice->getMessage();
288
-        require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php';
288
+        require EE_TEMPLATES.'/notifications/persistent_admin_notice.template.php';
289 289
     }
290 290
 
291 291
 
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
     {
311 311
         $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name);
312 312
         $this->notice_collection = $this->getPersistentAdminNoticeCollection();
313
-        if (! empty($pan_name) && $this->notice_collection->has($pan_name)) {
313
+        if ( ! empty($pan_name) && $this->notice_collection->has($pan_name)) {
314 314
             /** @var PersistentAdminNotice $persistent_admin_notice */
315 315
             $persistent_admin_notice = $this->notice_collection->get($pan_name);
316 316
             $persistent_admin_notice->setDismissed(true);
@@ -360,10 +360,10 @@  discard block
 block discarded – undo
360 360
             foreach ($this->notice_collection as $persistent_admin_notice) {
361 361
                 // are we deleting this notice ?
362 362
                 if ($persistent_admin_notice->getPurge()) {
363
-                    unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]);
363
+                    unset($persistent_admin_notices[$persistent_admin_notice->getName()]);
364 364
                 } else {
365 365
                     /** @var PersistentAdminNotice $persistent_admin_notice */
366
-                    $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array(
366
+                    $persistent_admin_notices[$persistent_admin_notice->getName()] = array(
367 367
                         'message'     => $persistent_admin_notice->getMessage(),
368 368
                         'capability'  => $persistent_admin_notice->getCapability(),
369 369
                         'cap_context' => $persistent_admin_notice->getCapContext(),
Please login to merge, or discard this patch.
Indentation   +389 added lines, -389 removed lines patch added patch discarded remove patch
@@ -30,393 +30,393 @@
 block discarded – undo
30 30
  */
31 31
 class PersistentAdminNoticeManager
32 32
 {
33
-    const WP_OPTION_KEY = 'ee_pers_admin_notices';
34
-
35
-    /**
36
-     * @var Collection|PersistentAdminNotice[] $notice_collection
37
-     */
38
-    private $notice_collection;
39
-
40
-    /**
41
-     * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the
42
-     * persistent admin notice was displayed, and ultimately dismissed from.
43
-     *
44
-     * @var string $return_url
45
-     */
46
-    private $return_url;
47
-
48
-    /**
49
-     * @var CapabilitiesChecker $capabilities_checker
50
-     */
51
-    private $capabilities_checker;
52
-
53
-    /**
54
-     * @var RequestInterface $request
55
-     */
56
-    private $request;
57
-
58
-
59
-    /**
60
-     * PersistentAdminNoticeManager constructor
61
-     *
62
-     * @param CapabilitiesChecker $capabilities_checker
63
-     * @param RequestInterface    $request
64
-     * @param string              $return_url where to  redirect to after dismissing notices
65
-     * @throws InvalidDataTypeException
66
-     */
67
-    public function __construct(
68
-        CapabilitiesChecker $capabilities_checker,
69
-        RequestInterface $request,
70
-        $return_url = ''
71
-    ) {
72
-        $return_url = (string) $return_url;
73
-        $this->setReturnUrl($return_url);
74
-        $this->capabilities_checker = $capabilities_checker;
75
-        $this->request = $request;
76
-        // setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10,
77
-        // and we want to retrieve and generate any nag notices at the last possible moment
78
-        add_action('admin_notices', array($this, 'displayNotices'), 9);
79
-        add_action('network_admin_notices', array($this, 'displayNotices'), 9);
80
-        add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice'));
81
-        add_action('shutdown', array($this, 'registerAndSaveNotices'), 998);
82
-    }
83
-
84
-
85
-    /**
86
-     * @param string $return_url
87
-     * @throws InvalidDataTypeException
88
-     */
89
-    public function setReturnUrl($return_url)
90
-    {
91
-        if (! is_string($return_url)) {
92
-            throw new InvalidDataTypeException('$return_url', $return_url, 'string');
93
-        }
94
-        $this->return_url = $return_url;
95
-    }
96
-
97
-
98
-    /**
99
-     * @return Collection
100
-     * @throws InvalidEntityException
101
-     * @throws InvalidInterfaceException
102
-     * @throws InvalidDataTypeException
103
-     * @throws DomainException
104
-     * @throws DuplicateCollectionIdentifierException
105
-     */
106
-    protected function getPersistentAdminNoticeCollection()
107
-    {
108
-        if (! $this->notice_collection instanceof Collection) {
109
-            $this->notice_collection = new Collection(
110
-                'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
111
-            );
112
-            $this->retrieveStoredNotices();
113
-            $this->registerNotices();
114
-        }
115
-        return $this->notice_collection;
116
-    }
117
-
118
-
119
-    /**
120
-     * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db
121
-     *
122
-     * @return void
123
-     * @throws InvalidEntityException
124
-     * @throws DomainException
125
-     * @throws InvalidDataTypeException
126
-     * @throws DuplicateCollectionIdentifierException
127
-     */
128
-    protected function retrieveStoredNotices()
129
-    {
130
-        $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
131
-        if (! empty($persistent_admin_notices)) {
132
-            foreach ($persistent_admin_notices as $name => $details) {
133
-                if (is_array($details)) {
134
-                    if (
135
-                        ! isset(
136
-                            $details['message'],
137
-                            $details['capability'],
138
-                            $details['cap_context'],
139
-                            $details['dismissed']
140
-                        )
141
-                    ) {
142
-                        throw new DomainException(
143
-                            sprintf(
144
-                                esc_html__(
145
-                                    'The "%1$s" PersistentAdminNotice could not be retrieved from the database.',
146
-                                    'event_espresso'
147
-                                ),
148
-                                $name
149
-                            )
150
-                        );
151
-                    }
152
-                    // new format for nag notices
153
-                    $this->notice_collection->add(
154
-                        new PersistentAdminNotice(
155
-                            $name,
156
-                            $details['message'],
157
-                            false,
158
-                            $details['capability'],
159
-                            $details['cap_context'],
160
-                            $details['dismissed']
161
-                        ),
162
-                        sanitize_key($name)
163
-                    );
164
-                } else {
165
-                    try {
166
-                        // old nag notices, that we want to convert to the new format
167
-                        $this->notice_collection->add(
168
-                            new PersistentAdminNotice(
169
-                                $name,
170
-                                (string) $details,
171
-                                false,
172
-                                '',
173
-                                '',
174
-                                empty($details)
175
-                            ),
176
-                            sanitize_key($name)
177
-                        );
178
-                    } catch (Exception $e) {
179
-                        EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
180
-                    }
181
-                }
182
-                // each notice will self register when the action hook in registerNotices is triggered
183
-            }
184
-        }
185
-    }
186
-
187
-
188
-    /**
189
-     * exposes the Persistent Admin Notice Collection via an action
190
-     * so that PersistentAdminNotice objects can be added and/or removed
191
-     * without compromising the actual collection like a filter would
192
-     */
193
-    protected function registerNotices()
194
-    {
195
-        do_action(
196
-            'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices',
197
-            $this->notice_collection
198
-        );
199
-    }
200
-
201
-
202
-    /**
203
-     * @throws DomainException
204
-     * @throws InvalidClassException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws InvalidEntityException
208
-     * @throws DuplicateCollectionIdentifierException
209
-     */
210
-    public function displayNotices()
211
-    {
212
-        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
213
-        if ($this->notice_collection->hasObjects()) {
214
-            $enqueue_assets = false;
215
-            // and display notices
216
-            foreach ($this->notice_collection as $persistent_admin_notice) {
217
-                /** @var PersistentAdminNotice $persistent_admin_notice */
218
-                // don't display notices that have already been dismissed
219
-                if ($persistent_admin_notice->getDismissed()) {
220
-                    continue;
221
-                }
222
-                try {
223
-                    $this->capabilities_checker->processCapCheck(
224
-                        $persistent_admin_notice->getCapCheck()
225
-                    );
226
-                } catch (InsufficientPermissionsException $e) {
227
-                    // user does not have required cap, so skip to next notice
228
-                    // and just eat the exception - nom nom nom nom
229
-                    continue;
230
-                }
231
-                if ($persistent_admin_notice->getMessage() === '') {
232
-                    continue;
233
-                }
234
-                $this->displayPersistentAdminNotice($persistent_admin_notice);
235
-                $enqueue_assets = true;
236
-            }
237
-            if ($enqueue_assets) {
238
-                $this->enqueueAssets();
239
-            }
240
-        }
241
-    }
242
-
243
-
244
-    /**
245
-     * does what it's named
246
-     *
247
-     * @return void
248
-     */
249
-    public function enqueueAssets()
250
-    {
251
-        wp_register_script(
252
-            'espresso_core',
253
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
254
-            array('jquery'),
255
-            EVENT_ESPRESSO_VERSION,
256
-            true
257
-        );
258
-        wp_register_script(
259
-            'ee_error_js',
260
-            EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
261
-            array('espresso_core'),
262
-            EVENT_ESPRESSO_VERSION,
263
-            true
264
-        );
265
-        wp_localize_script(
266
-            'ee_error_js',
267
-            'ee_dismiss',
268
-            array(
269
-                'return_url'    => urlencode($this->return_url),
270
-                'ajax_url'      => WP_AJAX_URL,
271
-                'unknown_error' => wp_strip_all_tags(
272
-                    __(
273
-                        'An unknown error has occurred on the server while attempting to dismiss this notice.',
274
-                        'event_espresso'
275
-                    )
276
-                ),
277
-            )
278
-        );
279
-        wp_enqueue_script('ee_error_js');
280
-    }
281
-
282
-
283
-    /**
284
-     * displayPersistentAdminNoticeHtml
285
-     *
286
-     * @param  PersistentAdminNotice $persistent_admin_notice
287
-     */
288
-    protected function displayPersistentAdminNotice($persistent_admin_notice)
289
-    {
290
-        // used in template
291
-        $persistent_admin_notice_name = $persistent_admin_notice->getName();
292
-        $persistent_admin_notice_message = $persistent_admin_notice->getMessage();
293
-        require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php';
294
-    }
295
-
296
-
297
-    /**
298
-     * dismissNotice
299
-     *
300
-     * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
301
-     * @param bool   $purge    if true, then delete it from the db
302
-     * @param bool   $return   forget all of this AJAX or redirect nonsense, and just return
303
-     * @return void
304
-     * @throws InvalidEntityException
305
-     * @throws InvalidInterfaceException
306
-     * @throws InvalidDataTypeException
307
-     * @throws DomainException
308
-     * @throws InvalidArgumentException
309
-     * @throws InvalidArgumentException
310
-     * @throws InvalidArgumentException
311
-     * @throws InvalidArgumentException
312
-     * @throws DuplicateCollectionIdentifierException
313
-     */
314
-    public function dismissNotice($pan_name = '', $purge = false, $return = false)
315
-    {
316
-        $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name);
317
-        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
318
-        if (! empty($pan_name) && $this->notice_collection->has($pan_name)) {
319
-            /** @var PersistentAdminNotice $persistent_admin_notice */
320
-            $persistent_admin_notice = $this->notice_collection->get($pan_name);
321
-            $persistent_admin_notice->setDismissed(true);
322
-            $persistent_admin_notice->setPurge($purge);
323
-            $this->saveNotices();
324
-        }
325
-        if ($return) {
326
-            return;
327
-        }
328
-        if ($this->request->isAjax()) {
329
-            // grab any notices and concatenate into string
330
-            echo wp_json_encode(
331
-                array(
332
-                    'errors' => implode('<br />', EE_Error::get_notices(false)),
333
-                )
334
-            );
335
-            exit();
336
-        }
337
-        // save errors to a transient to be displayed on next request (after redirect)
338
-        EE_Error::get_notices(false, true);
339
-        wp_safe_redirect(
340
-            urldecode(
341
-                $this->request->getRequestParam('return_url', '')
342
-            )
343
-        );
344
-    }
345
-
346
-
347
-    /**
348
-     * saveNotices
349
-     *
350
-     * @throws DomainException
351
-     * @throws InvalidDataTypeException
352
-     * @throws InvalidInterfaceException
353
-     * @throws InvalidEntityException
354
-     * @throws DuplicateCollectionIdentifierException
355
-     */
356
-    public function saveNotices()
357
-    {
358
-        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
359
-        if ($this->notice_collection->hasObjects()) {
360
-            $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
361
-            // maybe initialize persistent_admin_notices
362
-            if (empty($persistent_admin_notices)) {
363
-                add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no');
364
-            }
365
-            foreach ($this->notice_collection as $persistent_admin_notice) {
366
-                // are we deleting this notice ?
367
-                if ($persistent_admin_notice->getPurge()) {
368
-                    unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]);
369
-                } else {
370
-                    /** @var PersistentAdminNotice $persistent_admin_notice */
371
-                    $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array(
372
-                        'message'     => $persistent_admin_notice->getMessage(),
373
-                        'capability'  => $persistent_admin_notice->getCapability(),
374
-                        'cap_context' => $persistent_admin_notice->getCapContext(),
375
-                        'dismissed'   => $persistent_admin_notice->getDismissed(),
376
-                    );
377
-                }
378
-            }
379
-            update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices);
380
-        }
381
-    }
382
-
383
-
384
-    /**
385
-     * @throws DomainException
386
-     * @throws InvalidDataTypeException
387
-     * @throws InvalidEntityException
388
-     * @throws InvalidInterfaceException
389
-     * @throws DuplicateCollectionIdentifierException
390
-     */
391
-    public function registerAndSaveNotices()
392
-    {
393
-        $this->getPersistentAdminNoticeCollection();
394
-        $this->registerNotices();
395
-        $this->saveNotices();
396
-        add_filter(
397
-            'PersistentAdminNoticeManager__registerAndSaveNotices__complete',
398
-            '__return_true'
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * @throws DomainException
405
-     * @throws InvalidDataTypeException
406
-     * @throws InvalidEntityException
407
-     * @throws InvalidInterfaceException
408
-     * @throws InvalidArgumentException
409
-     * @throws DuplicateCollectionIdentifierException
410
-     */
411
-    public static function loadRegisterAndSaveNotices()
412
-    {
413
-        /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
414
-        $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
415
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
416
-        );
417
-        // if shutdown has already run, then call registerAndSaveNotices() manually
418
-        if (did_action('shutdown')) {
419
-            $persistent_admin_notice_manager->registerAndSaveNotices();
420
-        }
421
-    }
33
+	const WP_OPTION_KEY = 'ee_pers_admin_notices';
34
+
35
+	/**
36
+	 * @var Collection|PersistentAdminNotice[] $notice_collection
37
+	 */
38
+	private $notice_collection;
39
+
40
+	/**
41
+	 * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the
42
+	 * persistent admin notice was displayed, and ultimately dismissed from.
43
+	 *
44
+	 * @var string $return_url
45
+	 */
46
+	private $return_url;
47
+
48
+	/**
49
+	 * @var CapabilitiesChecker $capabilities_checker
50
+	 */
51
+	private $capabilities_checker;
52
+
53
+	/**
54
+	 * @var RequestInterface $request
55
+	 */
56
+	private $request;
57
+
58
+
59
+	/**
60
+	 * PersistentAdminNoticeManager constructor
61
+	 *
62
+	 * @param CapabilitiesChecker $capabilities_checker
63
+	 * @param RequestInterface    $request
64
+	 * @param string              $return_url where to  redirect to after dismissing notices
65
+	 * @throws InvalidDataTypeException
66
+	 */
67
+	public function __construct(
68
+		CapabilitiesChecker $capabilities_checker,
69
+		RequestInterface $request,
70
+		$return_url = ''
71
+	) {
72
+		$return_url = (string) $return_url;
73
+		$this->setReturnUrl($return_url);
74
+		$this->capabilities_checker = $capabilities_checker;
75
+		$this->request = $request;
76
+		// setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10,
77
+		// and we want to retrieve and generate any nag notices at the last possible moment
78
+		add_action('admin_notices', array($this, 'displayNotices'), 9);
79
+		add_action('network_admin_notices', array($this, 'displayNotices'), 9);
80
+		add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice'));
81
+		add_action('shutdown', array($this, 'registerAndSaveNotices'), 998);
82
+	}
83
+
84
+
85
+	/**
86
+	 * @param string $return_url
87
+	 * @throws InvalidDataTypeException
88
+	 */
89
+	public function setReturnUrl($return_url)
90
+	{
91
+		if (! is_string($return_url)) {
92
+			throw new InvalidDataTypeException('$return_url', $return_url, 'string');
93
+		}
94
+		$this->return_url = $return_url;
95
+	}
96
+
97
+
98
+	/**
99
+	 * @return Collection
100
+	 * @throws InvalidEntityException
101
+	 * @throws InvalidInterfaceException
102
+	 * @throws InvalidDataTypeException
103
+	 * @throws DomainException
104
+	 * @throws DuplicateCollectionIdentifierException
105
+	 */
106
+	protected function getPersistentAdminNoticeCollection()
107
+	{
108
+		if (! $this->notice_collection instanceof Collection) {
109
+			$this->notice_collection = new Collection(
110
+				'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
111
+			);
112
+			$this->retrieveStoredNotices();
113
+			$this->registerNotices();
114
+		}
115
+		return $this->notice_collection;
116
+	}
117
+
118
+
119
+	/**
120
+	 * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db
121
+	 *
122
+	 * @return void
123
+	 * @throws InvalidEntityException
124
+	 * @throws DomainException
125
+	 * @throws InvalidDataTypeException
126
+	 * @throws DuplicateCollectionIdentifierException
127
+	 */
128
+	protected function retrieveStoredNotices()
129
+	{
130
+		$persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
131
+		if (! empty($persistent_admin_notices)) {
132
+			foreach ($persistent_admin_notices as $name => $details) {
133
+				if (is_array($details)) {
134
+					if (
135
+						! isset(
136
+							$details['message'],
137
+							$details['capability'],
138
+							$details['cap_context'],
139
+							$details['dismissed']
140
+						)
141
+					) {
142
+						throw new DomainException(
143
+							sprintf(
144
+								esc_html__(
145
+									'The "%1$s" PersistentAdminNotice could not be retrieved from the database.',
146
+									'event_espresso'
147
+								),
148
+								$name
149
+							)
150
+						);
151
+					}
152
+					// new format for nag notices
153
+					$this->notice_collection->add(
154
+						new PersistentAdminNotice(
155
+							$name,
156
+							$details['message'],
157
+							false,
158
+							$details['capability'],
159
+							$details['cap_context'],
160
+							$details['dismissed']
161
+						),
162
+						sanitize_key($name)
163
+					);
164
+				} else {
165
+					try {
166
+						// old nag notices, that we want to convert to the new format
167
+						$this->notice_collection->add(
168
+							new PersistentAdminNotice(
169
+								$name,
170
+								(string) $details,
171
+								false,
172
+								'',
173
+								'',
174
+								empty($details)
175
+							),
176
+							sanitize_key($name)
177
+						);
178
+					} catch (Exception $e) {
179
+						EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
180
+					}
181
+				}
182
+				// each notice will self register when the action hook in registerNotices is triggered
183
+			}
184
+		}
185
+	}
186
+
187
+
188
+	/**
189
+	 * exposes the Persistent Admin Notice Collection via an action
190
+	 * so that PersistentAdminNotice objects can be added and/or removed
191
+	 * without compromising the actual collection like a filter would
192
+	 */
193
+	protected function registerNotices()
194
+	{
195
+		do_action(
196
+			'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices',
197
+			$this->notice_collection
198
+		);
199
+	}
200
+
201
+
202
+	/**
203
+	 * @throws DomainException
204
+	 * @throws InvalidClassException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws InvalidEntityException
208
+	 * @throws DuplicateCollectionIdentifierException
209
+	 */
210
+	public function displayNotices()
211
+	{
212
+		$this->notice_collection = $this->getPersistentAdminNoticeCollection();
213
+		if ($this->notice_collection->hasObjects()) {
214
+			$enqueue_assets = false;
215
+			// and display notices
216
+			foreach ($this->notice_collection as $persistent_admin_notice) {
217
+				/** @var PersistentAdminNotice $persistent_admin_notice */
218
+				// don't display notices that have already been dismissed
219
+				if ($persistent_admin_notice->getDismissed()) {
220
+					continue;
221
+				}
222
+				try {
223
+					$this->capabilities_checker->processCapCheck(
224
+						$persistent_admin_notice->getCapCheck()
225
+					);
226
+				} catch (InsufficientPermissionsException $e) {
227
+					// user does not have required cap, so skip to next notice
228
+					// and just eat the exception - nom nom nom nom
229
+					continue;
230
+				}
231
+				if ($persistent_admin_notice->getMessage() === '') {
232
+					continue;
233
+				}
234
+				$this->displayPersistentAdminNotice($persistent_admin_notice);
235
+				$enqueue_assets = true;
236
+			}
237
+			if ($enqueue_assets) {
238
+				$this->enqueueAssets();
239
+			}
240
+		}
241
+	}
242
+
243
+
244
+	/**
245
+	 * does what it's named
246
+	 *
247
+	 * @return void
248
+	 */
249
+	public function enqueueAssets()
250
+	{
251
+		wp_register_script(
252
+			'espresso_core',
253
+			EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
254
+			array('jquery'),
255
+			EVENT_ESPRESSO_VERSION,
256
+			true
257
+		);
258
+		wp_register_script(
259
+			'ee_error_js',
260
+			EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
261
+			array('espresso_core'),
262
+			EVENT_ESPRESSO_VERSION,
263
+			true
264
+		);
265
+		wp_localize_script(
266
+			'ee_error_js',
267
+			'ee_dismiss',
268
+			array(
269
+				'return_url'    => urlencode($this->return_url),
270
+				'ajax_url'      => WP_AJAX_URL,
271
+				'unknown_error' => wp_strip_all_tags(
272
+					__(
273
+						'An unknown error has occurred on the server while attempting to dismiss this notice.',
274
+						'event_espresso'
275
+					)
276
+				),
277
+			)
278
+		);
279
+		wp_enqueue_script('ee_error_js');
280
+	}
281
+
282
+
283
+	/**
284
+	 * displayPersistentAdminNoticeHtml
285
+	 *
286
+	 * @param  PersistentAdminNotice $persistent_admin_notice
287
+	 */
288
+	protected function displayPersistentAdminNotice($persistent_admin_notice)
289
+	{
290
+		// used in template
291
+		$persistent_admin_notice_name = $persistent_admin_notice->getName();
292
+		$persistent_admin_notice_message = $persistent_admin_notice->getMessage();
293
+		require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php';
294
+	}
295
+
296
+
297
+	/**
298
+	 * dismissNotice
299
+	 *
300
+	 * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
301
+	 * @param bool   $purge    if true, then delete it from the db
302
+	 * @param bool   $return   forget all of this AJAX or redirect nonsense, and just return
303
+	 * @return void
304
+	 * @throws InvalidEntityException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws InvalidDataTypeException
307
+	 * @throws DomainException
308
+	 * @throws InvalidArgumentException
309
+	 * @throws InvalidArgumentException
310
+	 * @throws InvalidArgumentException
311
+	 * @throws InvalidArgumentException
312
+	 * @throws DuplicateCollectionIdentifierException
313
+	 */
314
+	public function dismissNotice($pan_name = '', $purge = false, $return = false)
315
+	{
316
+		$pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name);
317
+		$this->notice_collection = $this->getPersistentAdminNoticeCollection();
318
+		if (! empty($pan_name) && $this->notice_collection->has($pan_name)) {
319
+			/** @var PersistentAdminNotice $persistent_admin_notice */
320
+			$persistent_admin_notice = $this->notice_collection->get($pan_name);
321
+			$persistent_admin_notice->setDismissed(true);
322
+			$persistent_admin_notice->setPurge($purge);
323
+			$this->saveNotices();
324
+		}
325
+		if ($return) {
326
+			return;
327
+		}
328
+		if ($this->request->isAjax()) {
329
+			// grab any notices and concatenate into string
330
+			echo wp_json_encode(
331
+				array(
332
+					'errors' => implode('<br />', EE_Error::get_notices(false)),
333
+				)
334
+			);
335
+			exit();
336
+		}
337
+		// save errors to a transient to be displayed on next request (after redirect)
338
+		EE_Error::get_notices(false, true);
339
+		wp_safe_redirect(
340
+			urldecode(
341
+				$this->request->getRequestParam('return_url', '')
342
+			)
343
+		);
344
+	}
345
+
346
+
347
+	/**
348
+	 * saveNotices
349
+	 *
350
+	 * @throws DomainException
351
+	 * @throws InvalidDataTypeException
352
+	 * @throws InvalidInterfaceException
353
+	 * @throws InvalidEntityException
354
+	 * @throws DuplicateCollectionIdentifierException
355
+	 */
356
+	public function saveNotices()
357
+	{
358
+		$this->notice_collection = $this->getPersistentAdminNoticeCollection();
359
+		if ($this->notice_collection->hasObjects()) {
360
+			$persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
361
+			// maybe initialize persistent_admin_notices
362
+			if (empty($persistent_admin_notices)) {
363
+				add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no');
364
+			}
365
+			foreach ($this->notice_collection as $persistent_admin_notice) {
366
+				// are we deleting this notice ?
367
+				if ($persistent_admin_notice->getPurge()) {
368
+					unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]);
369
+				} else {
370
+					/** @var PersistentAdminNotice $persistent_admin_notice */
371
+					$persistent_admin_notices[ $persistent_admin_notice->getName() ] = array(
372
+						'message'     => $persistent_admin_notice->getMessage(),
373
+						'capability'  => $persistent_admin_notice->getCapability(),
374
+						'cap_context' => $persistent_admin_notice->getCapContext(),
375
+						'dismissed'   => $persistent_admin_notice->getDismissed(),
376
+					);
377
+				}
378
+			}
379
+			update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices);
380
+		}
381
+	}
382
+
383
+
384
+	/**
385
+	 * @throws DomainException
386
+	 * @throws InvalidDataTypeException
387
+	 * @throws InvalidEntityException
388
+	 * @throws InvalidInterfaceException
389
+	 * @throws DuplicateCollectionIdentifierException
390
+	 */
391
+	public function registerAndSaveNotices()
392
+	{
393
+		$this->getPersistentAdminNoticeCollection();
394
+		$this->registerNotices();
395
+		$this->saveNotices();
396
+		add_filter(
397
+			'PersistentAdminNoticeManager__registerAndSaveNotices__complete',
398
+			'__return_true'
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * @throws DomainException
405
+	 * @throws InvalidDataTypeException
406
+	 * @throws InvalidEntityException
407
+	 * @throws InvalidInterfaceException
408
+	 * @throws InvalidArgumentException
409
+	 * @throws DuplicateCollectionIdentifierException
410
+	 */
411
+	public static function loadRegisterAndSaveNotices()
412
+	{
413
+		/** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
414
+		$persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
415
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
416
+		);
417
+		// if shutdown has already run, then call registerAndSaveNotices() manually
418
+		if (did_action('shutdown')) {
419
+			$persistent_admin_notice_manager->registerAndSaveNotices();
420
+		}
421
+	}
422 422
 }
Please login to merge, or discard this patch.
core/services/cache/TransientCacheStorage.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@  discard block
 block discarded – undo
57 57
         // round current time down to closest 5 minutes to simplify scheduling
58 58
         $this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
59 59
         $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
60
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
60
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
61 61
             add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
62 62
         }
63 63
     }
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
      */
191 191
     public function get($transient_key, $standard_cache = true)
192 192
     {
193
-        if (isset($this->transients[ $transient_key ])) {
193
+        if (isset($this->transients[$transient_key])) {
194 194
             // to avoid cache stampedes (AKA:dogpiles) for standard cache items,
195 195
             // check if known cache expires within the next minute,
196 196
             // and if so, remove it from our tracking and and return nothing.
@@ -199,17 +199,17 @@  discard block
 block discarded – undo
199 199
             // until it gets replaced with the refreshed content
200 200
             if (
201 201
                 $standard_cache
202
-                && $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS
202
+                && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS
203 203
             ) {
204
-                unset($this->transients[ $transient_key ]);
204
+                unset($this->transients[$transient_key]);
205 205
                 $this->updateTransients();
206 206
                 return null;
207 207
             }
208 208
 
209 209
             // for non standard cache items, remove the key from our tracking,
210 210
             // but proceed to retrieve the transient so that it also gets removed from the db
211
-            if ($this->transients[ $transient_key ] <= time()) {
212
-                unset($this->transients[ $transient_key ]);
211
+            if ($this->transients[$transient_key] <= time()) {
212
+                unset($this->transients[$transient_key]);
213 213
                 $this->updateTransients();
214 214
             }
215 215
         }
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
         // and round to the closest 15 minutes
283 283
         $expiration = $this->roundTimestamp($expiration);
284 284
         // save transients to clear using their ID as the key to avoid duplicates
285
-        $this->transients[ $transient_key ] = $expiration;
285
+        $this->transients[$transient_key] = $expiration;
286 286
         $this->updateTransients();
287 287
     }
288 288
 
@@ -334,8 +334,8 @@  discard block
 block discarded – undo
334 334
                 if ($expiration > $this->current_time) {
335 335
                     continue;
336 336
                 }
337
-                if (! $expiration || ! $transient_key) {
338
-                    unset($this->transients[ $transient_key ]);
337
+                if ( ! $expiration || ! $transient_key) {
338
+                    unset($this->transients[$transient_key]);
339 339
                     $update = true;
340 340
                     continue;
341 341
                 }
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
                 ? str_replace('_transient_', '', $transient_key)
375 375
                 : $transient_key;
376 376
             delete_transient($transient_key);
377
-            unset($this->transients[ $transient_key ]);
377
+            unset($this->transients[$transient_key]);
378 378
             $counter++;
379 379
         }
380 380
         return $counter > 0;
Please login to merge, or discard this patch.
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -15,367 +15,367 @@
 block discarded – undo
15 15
  */
16 16
 class TransientCacheStorage implements CacheStorageInterface
17 17
 {
18
-    /**
19
-     * wp-option option_name for tracking transients
20
-     *
21
-     * @type string
22
-     */
23
-    const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
24
-
25
-    /**
26
-     * @var int $current_time
27
-     */
28
-    private $current_time;
29
-
30
-    /**
31
-     * how often to perform transient cleanup
32
-     *
33
-     * @var string $transient_cleanup_frequency
34
-     */
35
-    private $transient_cleanup_frequency;
36
-
37
-    /**
38
-     * options for how often to perform transient cleanup
39
-     *
40
-     * @var array $transient_cleanup_frequency_options
41
-     */
42
-    private $transient_cleanup_frequency_options = array();
43
-
44
-    /**
45
-     * @var array $transients
46
-     */
47
-    private $transients;
48
-
49
-
50
-    /**
51
-     * TransientCacheStorage constructor.
52
-     */
53
-    public function __construct()
54
-    {
55
-        $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
56
-        // round current time down to closest 5 minutes to simplify scheduling
57
-        $this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
58
-        $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
59
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
60
-            add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
61
-        }
62
-    }
63
-
64
-
65
-    /**
66
-     * Sets how often transient cleanup occurs
67
-     *
68
-     * @return string
69
-     */
70
-    private function setTransientCleanupFrequency()
71
-    {
72
-        // sets how often transients are cleaned up
73
-        $this->transient_cleanup_frequency_options = apply_filters(
74
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
75
-            array(
76
-                'off',
77
-                '15-minutes',
78
-                'hour',
79
-                '12-hours',
80
-                'day',
81
-            )
82
-        );
83
-        $transient_cleanup_frequency = apply_filters(
84
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule',
85
-            'hour'
86
-        );
87
-        return in_array(
88
-            $transient_cleanup_frequency,
89
-            $this->transient_cleanup_frequency_options,
90
-            true
91
-        )
92
-            ? $transient_cleanup_frequency
93
-            : 'hour';
94
-    }
95
-
96
-
97
-    /**
98
-     * we need to be able to round timestamps off to match the set transient cleanup frequency
99
-     * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
100
-     * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
101
-     * during the next scheduled cleanup after its expiration.
102
-     * We also round off the current time timestamp to the closest 5 minutes
103
-     * just to make the timestamps a little easier to round which helps with debugging.
104
-     *
105
-     * @param int    $timestamp [required]
106
-     * @param string $cleanup_frequency
107
-     * @param bool   $round_up
108
-     * @return int
109
-     */
110
-    private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
111
-    {
112
-        $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
113
-        // in order to round the time to the closest xx minutes (or hours),
114
-        // we take the minutes (or hours) portion of the timestamp and divide it by xx,
115
-        // round down to a whole number, then multiply by xx to bring us almost back up to where we were
116
-        // why round down ? so the minutes (or hours) don't go over 60 (or 24)
117
-        // and bump the hour, which could bump the day, which could bump the month, etc,
118
-        // which would be bad because we don't always want to round up,
119
-        // but when we do we can easily achieve that by simply adding the desired offset,
120
-        $minutes = '00';
121
-        $hours = 'H';
122
-        switch ($cleanup_frequency) {
123
-            case '5-minutes':
124
-                $minutes = floor((int) date('i', $timestamp) / 5) * 5;
125
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
126
-                $offset = MINUTE_IN_SECONDS * 5;
127
-                break;
128
-            case '15-minutes':
129
-                $minutes = floor((int) date('i', $timestamp) / 15) * 15;
130
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
131
-                $offset = MINUTE_IN_SECONDS * 15;
132
-                break;
133
-            case '12-hours':
134
-                $hours = floor((int) date('H', $timestamp) / 12) * 12;
135
-                $hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
136
-                $offset = HOUR_IN_SECONDS * 12;
137
-                break;
138
-            case 'day':
139
-                $hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
140
-                $offset = DAY_IN_SECONDS;
141
-                break;
142
-            case 'hour':
143
-            default:
144
-                $offset = HOUR_IN_SECONDS;
145
-                break;
146
-        }
147
-        $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
148
-        $rounded_timestamp += $round_up ? $offset : 0;
149
-        return apply_filters(
150
-            'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
151
-            $rounded_timestamp,
152
-            $timestamp,
153
-            $cleanup_frequency,
154
-            $round_up
155
-        );
156
-    }
157
-
158
-
159
-    /**
160
-     * Saves supplied data to a transient
161
-     * if an expiration is set, then it automatically schedules the transient for cleanup
162
-     *
163
-     * @param string $transient_key [required]
164
-     * @param string $data          [required]
165
-     * @param int    $expiration    number of seconds until the cache expires
166
-     * @return bool
167
-     */
168
-    public function add($transient_key, $data, $expiration = 0)
169
-    {
170
-        $expiration = (int) abs($expiration);
171
-        $saved = set_transient($transient_key, $data, $expiration);
172
-        if ($saved && $expiration) {
173
-            $this->scheduleTransientCleanup($transient_key, $expiration);
174
-        }
175
-        return $saved;
176
-    }
177
-
178
-
179
-    /**
180
-     * retrieves transient data
181
-     * automatically triggers early cache refresh for standard cache items
182
-     * in order to avoid cache stampedes on busy sites.
183
-     * For non-standard cache items like PHP Session data where early refreshing is not wanted,
184
-     * the $standard_cache parameter should be set to false when retrieving data
185
-     *
186
-     * @param string $transient_key [required]
187
-     * @param bool   $standard_cache
188
-     * @return mixed|null
189
-     */
190
-    public function get($transient_key, $standard_cache = true)
191
-    {
192
-        if (isset($this->transients[ $transient_key ])) {
193
-            // to avoid cache stampedes (AKA:dogpiles) for standard cache items,
194
-            // check if known cache expires within the next minute,
195
-            // and if so, remove it from our tracking and and return nothing.
196
-            // this should trigger the cache content to be regenerated during this request,
197
-            // while allowing any following requests to still access the existing cache
198
-            // until it gets replaced with the refreshed content
199
-            if (
200
-                $standard_cache
201
-                && $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS
202
-            ) {
203
-                unset($this->transients[ $transient_key ]);
204
-                $this->updateTransients();
205
-                return null;
206
-            }
207
-
208
-            // for non standard cache items, remove the key from our tracking,
209
-            // but proceed to retrieve the transient so that it also gets removed from the db
210
-            if ($this->transients[ $transient_key ] <= time()) {
211
-                unset($this->transients[ $transient_key ]);
212
-                $this->updateTransients();
213
-            }
214
-        }
215
-
216
-        $content = get_transient($transient_key);
217
-        return $content !== false ? $content : null;
218
-    }
219
-
220
-
221
-    /**
222
-     * delete a single transient and remove tracking
223
-     *
224
-     * @param string $transient_key [required] full or partial transient key to be deleted
225
-     */
226
-    public function delete($transient_key)
227
-    {
228
-        $this->deleteMany(array($transient_key));
229
-    }
230
-
231
-
232
-    /**
233
-     * delete multiple transients and remove tracking
234
-     *
235
-     * @param array $transient_keys [required] array of full or partial transient keys to be deleted
236
-     * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
237
-     *                              and proceed directly to deleting those entries from the cache storage
238
-     */
239
-    public function deleteMany($transient_keys, $force_delete = false)
240
-    {
241
-        $full_transient_keys = $force_delete ? $transient_keys : array();
242
-        if (empty($full_transient_keys)) {
243
-            foreach ($this->transients as $transient_key => $expiration) {
244
-                foreach ($transient_keys as $transient_key_to_delete) {
245
-                    if (strpos($transient_key, $transient_key_to_delete) !== false) {
246
-                        $full_transient_keys[] = $transient_key;
247
-                    }
248
-                }
249
-            }
250
-        }
251
-        if ($this->deleteTransientKeys($full_transient_keys)) {
252
-            $this->updateTransients();
253
-        }
254
-    }
255
-
256
-
257
-    /**
258
-     * sorts transients numerically by timestamp
259
-     * then saves the transient schedule to a WP option
260
-     */
261
-    private function updateTransients()
262
-    {
263
-        asort($this->transients, SORT_NUMERIC);
264
-        update_option(
265
-            TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
266
-            $this->transients
267
-        );
268
-    }
269
-
270
-
271
-    /**
272
-     * schedules a transient for cleanup by adding it to the transient tracking
273
-     *
274
-     * @param string $transient_key [required]
275
-     * @param int    $expiration    [required]
276
-     */
277
-    private function scheduleTransientCleanup($transient_key, $expiration)
278
-    {
279
-        // make sure a valid future timestamp is set
280
-        $expiration += $expiration < time() ? time() : 0;
281
-        // and round to the closest 15 minutes
282
-        $expiration = $this->roundTimestamp($expiration);
283
-        // save transients to clear using their ID as the key to avoid duplicates
284
-        $this->transients[ $transient_key ] = $expiration;
285
-        $this->updateTransients();
286
-    }
287
-
288
-
289
-    /**
290
-     * Since our tracked transients are sorted by their timestamps
291
-     * we can grab the first transient and see when it is scheduled for cleanup.
292
-     * If that timestamp is less than or equal to the current time,
293
-     * then cleanup is triggered
294
-     */
295
-    public function checkTransientCleanupSchedule()
296
-    {
297
-        if (empty($this->transients)) {
298
-            return;
299
-        }
300
-        // when do we run the next cleanup job?
301
-        reset($this->transients);
302
-        $next_scheduled_cleanup = current($this->transients);
303
-        // if the next cleanup job is scheduled for the current hour
304
-        if ($next_scheduled_cleanup <= $this->current_time) {
305
-            if ($this->cleanupExpiredTransients()) {
306
-                $this->updateTransients();
307
-            }
308
-        }
309
-    }
310
-
311
-
312
-    /**
313
-     * loops through the array of tracked transients,
314
-     * compiles a list of those that have expired, and sends that list off for deletion.
315
-     * Also removes any bad records from the transients array
316
-     *
317
-     * @return bool
318
-     */
319
-    private function cleanupExpiredTransients()
320
-    {
321
-        $update = false;
322
-        // filter the query limit. Set to 0 to turn off garbage collection
323
-        $limit = (int) abs(
324
-            apply_filters(
325
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
326
-                50
327
-            )
328
-        );
329
-        // non-zero LIMIT means take out the trash
330
-        if ($limit) {
331
-            $transient_keys = array();
332
-            foreach ($this->transients as $transient_key => $expiration) {
333
-                if ($expiration > $this->current_time) {
334
-                    continue;
335
-                }
336
-                if (! $expiration || ! $transient_key) {
337
-                    unset($this->transients[ $transient_key ]);
338
-                    $update = true;
339
-                    continue;
340
-                }
341
-                $transient_keys[] = $transient_key;
342
-            }
343
-            // delete expired keys, but maintain value of $update if nothing is deleted
344
-            $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
345
-            do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
346
-        }
347
-        return $update;
348
-    }
349
-
350
-
351
-    /**
352
-     * calls delete_transient() on each transient key provided, up to the specified limit
353
-     *
354
-     * @param array $transient_keys [required]
355
-     * @param int   $limit
356
-     * @return bool
357
-     */
358
-    private function deleteTransientKeys(array $transient_keys, $limit = 50)
359
-    {
360
-        if (empty($transient_keys)) {
361
-            return false;
362
-        }
363
-        $counter = 0;
364
-        foreach ($transient_keys as $transient_key) {
365
-            if ($counter === $limit) {
366
-                break;
367
-            }
368
-            // remove any transient prefixes
369
-            $transient_key = strpos($transient_key, '_transient_timeout_') === 0
370
-                ? str_replace('_transient_timeout_', '', $transient_key)
371
-                : $transient_key;
372
-            $transient_key = strpos($transient_key, '_transient_') === 0
373
-                ? str_replace('_transient_', '', $transient_key)
374
-                : $transient_key;
375
-            delete_transient($transient_key);
376
-            unset($this->transients[ $transient_key ]);
377
-            $counter++;
378
-        }
379
-        return $counter > 0;
380
-    }
18
+	/**
19
+	 * wp-option option_name for tracking transients
20
+	 *
21
+	 * @type string
22
+	 */
23
+	const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
24
+
25
+	/**
26
+	 * @var int $current_time
27
+	 */
28
+	private $current_time;
29
+
30
+	/**
31
+	 * how often to perform transient cleanup
32
+	 *
33
+	 * @var string $transient_cleanup_frequency
34
+	 */
35
+	private $transient_cleanup_frequency;
36
+
37
+	/**
38
+	 * options for how often to perform transient cleanup
39
+	 *
40
+	 * @var array $transient_cleanup_frequency_options
41
+	 */
42
+	private $transient_cleanup_frequency_options = array();
43
+
44
+	/**
45
+	 * @var array $transients
46
+	 */
47
+	private $transients;
48
+
49
+
50
+	/**
51
+	 * TransientCacheStorage constructor.
52
+	 */
53
+	public function __construct()
54
+	{
55
+		$this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
56
+		// round current time down to closest 5 minutes to simplify scheduling
57
+		$this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
58
+		$this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
59
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
60
+			add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
61
+		}
62
+	}
63
+
64
+
65
+	/**
66
+	 * Sets how often transient cleanup occurs
67
+	 *
68
+	 * @return string
69
+	 */
70
+	private function setTransientCleanupFrequency()
71
+	{
72
+		// sets how often transients are cleaned up
73
+		$this->transient_cleanup_frequency_options = apply_filters(
74
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
75
+			array(
76
+				'off',
77
+				'15-minutes',
78
+				'hour',
79
+				'12-hours',
80
+				'day',
81
+			)
82
+		);
83
+		$transient_cleanup_frequency = apply_filters(
84
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule',
85
+			'hour'
86
+		);
87
+		return in_array(
88
+			$transient_cleanup_frequency,
89
+			$this->transient_cleanup_frequency_options,
90
+			true
91
+		)
92
+			? $transient_cleanup_frequency
93
+			: 'hour';
94
+	}
95
+
96
+
97
+	/**
98
+	 * we need to be able to round timestamps off to match the set transient cleanup frequency
99
+	 * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
100
+	 * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
101
+	 * during the next scheduled cleanup after its expiration.
102
+	 * We also round off the current time timestamp to the closest 5 minutes
103
+	 * just to make the timestamps a little easier to round which helps with debugging.
104
+	 *
105
+	 * @param int    $timestamp [required]
106
+	 * @param string $cleanup_frequency
107
+	 * @param bool   $round_up
108
+	 * @return int
109
+	 */
110
+	private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
111
+	{
112
+		$cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
113
+		// in order to round the time to the closest xx minutes (or hours),
114
+		// we take the minutes (or hours) portion of the timestamp and divide it by xx,
115
+		// round down to a whole number, then multiply by xx to bring us almost back up to where we were
116
+		// why round down ? so the minutes (or hours) don't go over 60 (or 24)
117
+		// and bump the hour, which could bump the day, which could bump the month, etc,
118
+		// which would be bad because we don't always want to round up,
119
+		// but when we do we can easily achieve that by simply adding the desired offset,
120
+		$minutes = '00';
121
+		$hours = 'H';
122
+		switch ($cleanup_frequency) {
123
+			case '5-minutes':
124
+				$minutes = floor((int) date('i', $timestamp) / 5) * 5;
125
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
126
+				$offset = MINUTE_IN_SECONDS * 5;
127
+				break;
128
+			case '15-minutes':
129
+				$minutes = floor((int) date('i', $timestamp) / 15) * 15;
130
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
131
+				$offset = MINUTE_IN_SECONDS * 15;
132
+				break;
133
+			case '12-hours':
134
+				$hours = floor((int) date('H', $timestamp) / 12) * 12;
135
+				$hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
136
+				$offset = HOUR_IN_SECONDS * 12;
137
+				break;
138
+			case 'day':
139
+				$hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
140
+				$offset = DAY_IN_SECONDS;
141
+				break;
142
+			case 'hour':
143
+			default:
144
+				$offset = HOUR_IN_SECONDS;
145
+				break;
146
+		}
147
+		$rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
148
+		$rounded_timestamp += $round_up ? $offset : 0;
149
+		return apply_filters(
150
+			'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
151
+			$rounded_timestamp,
152
+			$timestamp,
153
+			$cleanup_frequency,
154
+			$round_up
155
+		);
156
+	}
157
+
158
+
159
+	/**
160
+	 * Saves supplied data to a transient
161
+	 * if an expiration is set, then it automatically schedules the transient for cleanup
162
+	 *
163
+	 * @param string $transient_key [required]
164
+	 * @param string $data          [required]
165
+	 * @param int    $expiration    number of seconds until the cache expires
166
+	 * @return bool
167
+	 */
168
+	public function add($transient_key, $data, $expiration = 0)
169
+	{
170
+		$expiration = (int) abs($expiration);
171
+		$saved = set_transient($transient_key, $data, $expiration);
172
+		if ($saved && $expiration) {
173
+			$this->scheduleTransientCleanup($transient_key, $expiration);
174
+		}
175
+		return $saved;
176
+	}
177
+
178
+
179
+	/**
180
+	 * retrieves transient data
181
+	 * automatically triggers early cache refresh for standard cache items
182
+	 * in order to avoid cache stampedes on busy sites.
183
+	 * For non-standard cache items like PHP Session data where early refreshing is not wanted,
184
+	 * the $standard_cache parameter should be set to false when retrieving data
185
+	 *
186
+	 * @param string $transient_key [required]
187
+	 * @param bool   $standard_cache
188
+	 * @return mixed|null
189
+	 */
190
+	public function get($transient_key, $standard_cache = true)
191
+	{
192
+		if (isset($this->transients[ $transient_key ])) {
193
+			// to avoid cache stampedes (AKA:dogpiles) for standard cache items,
194
+			// check if known cache expires within the next minute,
195
+			// and if so, remove it from our tracking and and return nothing.
196
+			// this should trigger the cache content to be regenerated during this request,
197
+			// while allowing any following requests to still access the existing cache
198
+			// until it gets replaced with the refreshed content
199
+			if (
200
+				$standard_cache
201
+				&& $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS
202
+			) {
203
+				unset($this->transients[ $transient_key ]);
204
+				$this->updateTransients();
205
+				return null;
206
+			}
207
+
208
+			// for non standard cache items, remove the key from our tracking,
209
+			// but proceed to retrieve the transient so that it also gets removed from the db
210
+			if ($this->transients[ $transient_key ] <= time()) {
211
+				unset($this->transients[ $transient_key ]);
212
+				$this->updateTransients();
213
+			}
214
+		}
215
+
216
+		$content = get_transient($transient_key);
217
+		return $content !== false ? $content : null;
218
+	}
219
+
220
+
221
+	/**
222
+	 * delete a single transient and remove tracking
223
+	 *
224
+	 * @param string $transient_key [required] full or partial transient key to be deleted
225
+	 */
226
+	public function delete($transient_key)
227
+	{
228
+		$this->deleteMany(array($transient_key));
229
+	}
230
+
231
+
232
+	/**
233
+	 * delete multiple transients and remove tracking
234
+	 *
235
+	 * @param array $transient_keys [required] array of full or partial transient keys to be deleted
236
+	 * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
237
+	 *                              and proceed directly to deleting those entries from the cache storage
238
+	 */
239
+	public function deleteMany($transient_keys, $force_delete = false)
240
+	{
241
+		$full_transient_keys = $force_delete ? $transient_keys : array();
242
+		if (empty($full_transient_keys)) {
243
+			foreach ($this->transients as $transient_key => $expiration) {
244
+				foreach ($transient_keys as $transient_key_to_delete) {
245
+					if (strpos($transient_key, $transient_key_to_delete) !== false) {
246
+						$full_transient_keys[] = $transient_key;
247
+					}
248
+				}
249
+			}
250
+		}
251
+		if ($this->deleteTransientKeys($full_transient_keys)) {
252
+			$this->updateTransients();
253
+		}
254
+	}
255
+
256
+
257
+	/**
258
+	 * sorts transients numerically by timestamp
259
+	 * then saves the transient schedule to a WP option
260
+	 */
261
+	private function updateTransients()
262
+	{
263
+		asort($this->transients, SORT_NUMERIC);
264
+		update_option(
265
+			TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
266
+			$this->transients
267
+		);
268
+	}
269
+
270
+
271
+	/**
272
+	 * schedules a transient for cleanup by adding it to the transient tracking
273
+	 *
274
+	 * @param string $transient_key [required]
275
+	 * @param int    $expiration    [required]
276
+	 */
277
+	private function scheduleTransientCleanup($transient_key, $expiration)
278
+	{
279
+		// make sure a valid future timestamp is set
280
+		$expiration += $expiration < time() ? time() : 0;
281
+		// and round to the closest 15 minutes
282
+		$expiration = $this->roundTimestamp($expiration);
283
+		// save transients to clear using their ID as the key to avoid duplicates
284
+		$this->transients[ $transient_key ] = $expiration;
285
+		$this->updateTransients();
286
+	}
287
+
288
+
289
+	/**
290
+	 * Since our tracked transients are sorted by their timestamps
291
+	 * we can grab the first transient and see when it is scheduled for cleanup.
292
+	 * If that timestamp is less than or equal to the current time,
293
+	 * then cleanup is triggered
294
+	 */
295
+	public function checkTransientCleanupSchedule()
296
+	{
297
+		if (empty($this->transients)) {
298
+			return;
299
+		}
300
+		// when do we run the next cleanup job?
301
+		reset($this->transients);
302
+		$next_scheduled_cleanup = current($this->transients);
303
+		// if the next cleanup job is scheduled for the current hour
304
+		if ($next_scheduled_cleanup <= $this->current_time) {
305
+			if ($this->cleanupExpiredTransients()) {
306
+				$this->updateTransients();
307
+			}
308
+		}
309
+	}
310
+
311
+
312
+	/**
313
+	 * loops through the array of tracked transients,
314
+	 * compiles a list of those that have expired, and sends that list off for deletion.
315
+	 * Also removes any bad records from the transients array
316
+	 *
317
+	 * @return bool
318
+	 */
319
+	private function cleanupExpiredTransients()
320
+	{
321
+		$update = false;
322
+		// filter the query limit. Set to 0 to turn off garbage collection
323
+		$limit = (int) abs(
324
+			apply_filters(
325
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
326
+				50
327
+			)
328
+		);
329
+		// non-zero LIMIT means take out the trash
330
+		if ($limit) {
331
+			$transient_keys = array();
332
+			foreach ($this->transients as $transient_key => $expiration) {
333
+				if ($expiration > $this->current_time) {
334
+					continue;
335
+				}
336
+				if (! $expiration || ! $transient_key) {
337
+					unset($this->transients[ $transient_key ]);
338
+					$update = true;
339
+					continue;
340
+				}
341
+				$transient_keys[] = $transient_key;
342
+			}
343
+			// delete expired keys, but maintain value of $update if nothing is deleted
344
+			$update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
345
+			do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
346
+		}
347
+		return $update;
348
+	}
349
+
350
+
351
+	/**
352
+	 * calls delete_transient() on each transient key provided, up to the specified limit
353
+	 *
354
+	 * @param array $transient_keys [required]
355
+	 * @param int   $limit
356
+	 * @return bool
357
+	 */
358
+	private function deleteTransientKeys(array $transient_keys, $limit = 50)
359
+	{
360
+		if (empty($transient_keys)) {
361
+			return false;
362
+		}
363
+		$counter = 0;
364
+		foreach ($transient_keys as $transient_key) {
365
+			if ($counter === $limit) {
366
+				break;
367
+			}
368
+			// remove any transient prefixes
369
+			$transient_key = strpos($transient_key, '_transient_timeout_') === 0
370
+				? str_replace('_transient_timeout_', '', $transient_key)
371
+				: $transient_key;
372
+			$transient_key = strpos($transient_key, '_transient_') === 0
373
+				? str_replace('_transient_', '', $transient_key)
374
+				: $transient_key;
375
+			delete_transient($transient_key);
376
+			unset($this->transients[ $transient_key ]);
377
+			$counter++;
378
+		}
379
+		return $counter > 0;
380
+	}
381 381
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Datetime.class.php 2 patches
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -533,7 +533,7 @@  discard block
 block discarded – undo
533 533
             $date_or_time,
534 534
             $echo
535 535
         );
536
-        if (! $echo) {
536
+        if ( ! $echo) {
537 537
             return $dtt;
538 538
         }
539 539
         return '';
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
             '&nbsp;',
636 636
             $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
637 637
         );
638
-        return $start !== $end ? $start . $conjunction . $end : $start;
638
+        return $start !== $end ? $start.$conjunction.$end : $start;
639 639
     }
640 640
 
641 641
 
@@ -743,7 +743,7 @@  discard block
 block discarded – undo
743 743
             '&nbsp;',
744 744
             $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
745 745
         );
746
-        return $start !== $end ? $start . $conjunction . $end : $start;
746
+        return $start !== $end ? $start.$conjunction.$end : $start;
747 747
     }
748 748
 
749 749
 
@@ -788,7 +788,7 @@  discard block
 block discarded – undo
788 788
     ) {
789 789
         $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
790 790
         $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
791
-        $full_format = $dt_format . $separator . $tm_format;
791
+        $full_format = $dt_format.$separator.$tm_format;
792 792
         // the range output depends on various conditions
793 793
         switch (true) {
794 794
             // start date timestamp and end date timestamp are the same.
@@ -1029,7 +1029,7 @@  discard block
 block discarded – undo
1029 1029
         // tickets remaining available for purchase
1030 1030
         // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1031 1031
         $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1032
-        if (! $consider_tickets) {
1032
+        if ( ! $consider_tickets) {
1033 1033
             return $dtt_remaining;
1034 1034
         }
1035 1035
         $tickets_remaining = $this->tickets_remaining();
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
     {
1054 1054
         $sum = 0;
1055 1055
         $tickets = $this->tickets($query_params);
1056
-        if (! empty($tickets)) {
1056
+        if ( ! empty($tickets)) {
1057 1057
             foreach ($tickets as $ticket) {
1058 1058
                 if ($ticket instanceof EE_Ticket) {
1059 1059
                     // get the actual amount of tickets that can be sold
@@ -1204,7 +1204,7 @@  discard block
 block discarded – undo
1204 1204
     {
1205 1205
         if ($use_dtt_name) {
1206 1206
             $dtt_name = $this->name();
1207
-            if (! empty($dtt_name)) {
1207
+            if ( ! empty($dtt_name)) {
1208 1208
                 return $dtt_name;
1209 1209
             }
1210 1210
         }
@@ -1212,14 +1212,14 @@  discard block
 block discarded – undo
1212 1212
         if (
1213 1213
             date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1214 1214
         ) {
1215
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
+            $display_date = $this->start_date('M j\, Y g:i a').' - '.$this->end_date('M j\, Y g:i a');
1216 1216
             // next condition is if its the same month but different day
1217 1217
         } else {
1218 1218
             if (
1219 1219
                 date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1220 1220
                 && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1221 1221
             ) {
1222
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1222
+                $display_date = $this->start_date('M j\, g:i a').' - '.$this->end_date('M j\, g:i a Y');
1223 1223
             } else {
1224 1224
                 $display_date = $this->start_date('F j\, Y')
1225 1225
                                 . ' @ '
Please login to merge, or discard this patch.
Indentation   +1552 added lines, -1552 removed lines patch added patch discarded remove patch
@@ -12,1560 +12,1560 @@
 block discarded – undo
12 12
  */
13 13
 class EE_Datetime extends EE_Soft_Delete_Base_Class
14 14
 {
15
-    /**
16
-     * constant used by get_active_status, indicates datetime has no more available spaces
17
-     */
18
-    const sold_out = 'DTS';
19
-
20
-    /**
21
-     * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
22
-     */
23
-    const active = 'DTA';
24
-
25
-    /**
26
-     * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
27
-     * expired
28
-     */
29
-    const upcoming = 'DTU';
30
-
31
-    /**
32
-     * Datetime is postponed
33
-     */
34
-    const postponed = 'DTP';
35
-
36
-    /**
37
-     * Datetime is cancelled
38
-     */
39
-    const cancelled = 'DTC';
40
-
41
-    /**
42
-     * constant used by get_active_status, indicates datetime has expired (event is over)
43
-     */
44
-    const expired = 'DTE';
45
-
46
-    /**
47
-     * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
48
-     */
49
-    const inactive = 'DTI';
50
-
51
-
52
-    /**
53
-     * @param array  $props_n_values    incoming values
54
-     * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
55
-     * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
56
-     *                                  and the second value is the time format
57
-     * @return EE_Datetime
58
-     * @throws ReflectionException
59
-     * @throws InvalidArgumentException
60
-     * @throws InvalidInterfaceException
61
-     * @throws InvalidDataTypeException
62
-     * @throws EE_Error
63
-     */
64
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
65
-    {
66
-        $has_object = parent::_check_for_object(
67
-            $props_n_values,
68
-            __CLASS__,
69
-            $timezone,
70
-            $date_formats
71
-        );
72
-        return $has_object
73
-            ? $has_object
74
-            : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Datetime
83
-     * @throws ReflectionException
84
-     * @throws InvalidArgumentException
85
-     * @throws InvalidInterfaceException
86
-     * @throws InvalidDataTypeException
87
-     * @throws EE_Error
88
-     */
89
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
90
-    {
91
-        return new self($props_n_values, true, $timezone);
92
-    }
93
-
94
-
95
-    /**
96
-     * @param $name
97
-     * @throws ReflectionException
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidInterfaceException
100
-     * @throws InvalidDataTypeException
101
-     * @throws EE_Error
102
-     */
103
-    public function set_name($name)
104
-    {
105
-        $this->set('DTT_name', $name);
106
-    }
107
-
108
-
109
-    /**
110
-     * @param $description
111
-     * @throws ReflectionException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidInterfaceException
114
-     * @throws InvalidDataTypeException
115
-     * @throws EE_Error
116
-     */
117
-    public function set_description($description)
118
-    {
119
-        $this->set('DTT_description', $description);
120
-    }
121
-
122
-
123
-    /**
124
-     * Set event start date
125
-     * set the start date for an event
126
-     *
127
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
128
-     * @throws ReflectionException
129
-     * @throws InvalidArgumentException
130
-     * @throws InvalidInterfaceException
131
-     * @throws InvalidDataTypeException
132
-     * @throws EE_Error
133
-     */
134
-    public function set_start_date($date)
135
-    {
136
-        $this->_set_date_for($date, 'DTT_EVT_start');
137
-    }
138
-
139
-
140
-    /**
141
-     * Set event start time
142
-     * set the start time for an event
143
-     *
144
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
145
-     * @throws ReflectionException
146
-     * @throws InvalidArgumentException
147
-     * @throws InvalidInterfaceException
148
-     * @throws InvalidDataTypeException
149
-     * @throws EE_Error
150
-     */
151
-    public function set_start_time($time)
152
-    {
153
-        $this->_set_time_for($time, 'DTT_EVT_start');
154
-    }
155
-
156
-
157
-    /**
158
-     * Set event end date
159
-     * set the end date for an event
160
-     *
161
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
162
-     * @throws ReflectionException
163
-     * @throws InvalidArgumentException
164
-     * @throws InvalidInterfaceException
165
-     * @throws InvalidDataTypeException
166
-     * @throws EE_Error
167
-     */
168
-    public function set_end_date($date)
169
-    {
170
-        $this->_set_date_for($date, 'DTT_EVT_end');
171
-    }
172
-
173
-
174
-    /**
175
-     * Set event end time
176
-     * set the end time for an event
177
-     *
178
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
179
-     * @throws ReflectionException
180
-     * @throws InvalidArgumentException
181
-     * @throws InvalidInterfaceException
182
-     * @throws InvalidDataTypeException
183
-     * @throws EE_Error
184
-     */
185
-    public function set_end_time($time)
186
-    {
187
-        $this->_set_time_for($time, 'DTT_EVT_end');
188
-    }
189
-
190
-
191
-    /**
192
-     * Set registration limit
193
-     * set the maximum number of attendees that can be registered for this datetime slot
194
-     *
195
-     * @param int|float $reg_limit
196
-     * @throws ReflectionException
197
-     * @throws InvalidArgumentException
198
-     * @throws InvalidInterfaceException
199
-     * @throws InvalidDataTypeException
200
-     * @throws EE_Error
201
-     */
202
-    public function set_reg_limit($reg_limit)
203
-    {
204
-        $this->set('DTT_reg_limit', $reg_limit);
205
-    }
206
-
207
-
208
-    /**
209
-     * get the number of tickets sold for this datetime slot
210
-     *
211
-     * @return mixed int on success, FALSE on fail
212
-     * @throws ReflectionException
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidInterfaceException
215
-     * @throws InvalidDataTypeException
216
-     * @throws EE_Error
217
-     */
218
-    public function sold()
219
-    {
220
-        return $this->get_raw('DTT_sold');
221
-    }
222
-
223
-
224
-    /**
225
-     * @param int $sold
226
-     * @throws ReflectionException
227
-     * @throws InvalidArgumentException
228
-     * @throws InvalidInterfaceException
229
-     * @throws InvalidDataTypeException
230
-     * @throws EE_Error
231
-     */
232
-    public function set_sold($sold)
233
-    {
234
-        // sold can not go below zero
235
-        $sold = max(0, $sold);
236
-        $this->set('DTT_sold', $sold);
237
-    }
238
-
239
-
240
-    /**
241
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
242
-     * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
243
-     *
244
-     * @param int $qty
245
-     * @param boolean $also_decrease_reserved
246
-     * @return boolean indicating success
247
-     * @throws ReflectionException
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidInterfaceException
250
-     * @throws InvalidDataTypeException
251
-     * @throws EE_Error
252
-     */
253
-    public function increaseSold($qty = 1, $also_decrease_reserved = true)
254
-    {
255
-        $qty = absint($qty);
256
-        if ($also_decrease_reserved) {
257
-            $success = $this->adjustNumericFieldsInDb(
258
-                [
259
-                    'DTT_reserved' => $qty * -1,
260
-                    'DTT_sold' => $qty
261
-                ]
262
-            );
263
-        } else {
264
-            $success = $this->adjustNumericFieldsInDb(
265
-                [
266
-                    'DTT_sold' => $qty
267
-                ]
268
-            );
269
-        }
270
-
271
-        do_action(
272
-            'AHEE__EE_Datetime__increase_sold',
273
-            $this,
274
-            $qty,
275
-            $this->sold(),
276
-            $success
277
-        );
278
-        return $success;
279
-    }
280
-
281
-
282
-    /**
283
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
284
-     * to save afterwards.)
285
-     *
286
-     * @param int $qty
287
-     * @return boolean indicating success
288
-     * @throws ReflectionException
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidInterfaceException
291
-     * @throws InvalidDataTypeException
292
-     * @throws EE_Error
293
-     */
294
-    public function decreaseSold($qty = 1)
295
-    {
296
-        $qty = absint($qty);
297
-        $success = $this->adjustNumericFieldsInDb(
298
-            [
299
-                'DTT_sold' => $qty * -1
300
-            ]
301
-        );
302
-        do_action(
303
-            'AHEE__EE_Datetime__decrease_sold',
304
-            $this,
305
-            $qty,
306
-            $this->sold(),
307
-            $success
308
-        );
309
-        return $success;
310
-    }
311
-
312
-
313
-    /**
314
-     * Gets qty of reserved tickets for this datetime
315
-     *
316
-     * @return int
317
-     * @throws ReflectionException
318
-     * @throws InvalidArgumentException
319
-     * @throws InvalidInterfaceException
320
-     * @throws InvalidDataTypeException
321
-     * @throws EE_Error
322
-     */
323
-    public function reserved()
324
-    {
325
-        return $this->get_raw('DTT_reserved');
326
-    }
327
-
328
-
329
-    /**
330
-     * Sets qty of reserved tickets for this datetime
331
-     *
332
-     * @param int $reserved
333
-     * @throws ReflectionException
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidInterfaceException
336
-     * @throws InvalidDataTypeException
337
-     * @throws EE_Error
338
-     */
339
-    public function set_reserved($reserved)
340
-    {
341
-        // reserved can not go below zero
342
-        $reserved = max(0, $reserved);
343
-        $this->set('DTT_reserved', $reserved);
344
-    }
345
-
346
-
347
-    /**
348
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
349
-     *
350
-     * @param int $qty
351
-     * @return boolean indicating success
352
-     * @throws ReflectionException
353
-     * @throws InvalidArgumentException
354
-     * @throws InvalidInterfaceException
355
-     * @throws InvalidDataTypeException
356
-     * @throws EE_Error
357
-     */
358
-    public function increaseReserved($qty = 1)
359
-    {
360
-        $qty = absint($qty);
361
-        $success = $this->incrementFieldConditionallyInDb(
362
-            'DTT_reserved',
363
-            'DTT_sold',
364
-            'DTT_reg_limit',
365
-            $qty
366
-        );
367
-        do_action(
368
-            'AHEE__EE_Datetime__increase_reserved',
369
-            $this,
370
-            $qty,
371
-            $this->reserved(),
372
-            $success
373
-        );
374
-        return $success;
375
-    }
376
-
377
-
378
-    /**
379
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
380
-     *
381
-     * @param int $qty
382
-     * @return boolean indicating success
383
-     * @throws ReflectionException
384
-     * @throws InvalidArgumentException
385
-     * @throws InvalidInterfaceException
386
-     * @throws InvalidDataTypeException
387
-     * @throws EE_Error
388
-     */
389
-    public function decreaseReserved($qty = 1)
390
-    {
391
-        $qty = absint($qty);
392
-        $success = $this->adjustNumericFieldsInDb(
393
-            [
394
-                'DTT_reserved' => $qty * -1
395
-            ]
396
-        );
397
-        do_action(
398
-            'AHEE__EE_Datetime__decrease_reserved',
399
-            $this,
400
-            $qty,
401
-            $this->reserved(),
402
-            $success
403
-        );
404
-        return $success;
405
-    }
406
-
407
-
408
-    /**
409
-     * total sold and reserved tickets
410
-     *
411
-     * @return int
412
-     * @throws ReflectionException
413
-     * @throws InvalidArgumentException
414
-     * @throws InvalidInterfaceException
415
-     * @throws InvalidDataTypeException
416
-     * @throws EE_Error
417
-     */
418
-    public function sold_and_reserved()
419
-    {
420
-        return $this->sold() + $this->reserved();
421
-    }
422
-
423
-
424
-    /**
425
-     * returns the datetime name
426
-     *
427
-     * @return string
428
-     * @throws ReflectionException
429
-     * @throws InvalidArgumentException
430
-     * @throws InvalidInterfaceException
431
-     * @throws InvalidDataTypeException
432
-     * @throws EE_Error
433
-     */
434
-    public function name()
435
-    {
436
-        return $this->get('DTT_name');
437
-    }
438
-
439
-
440
-    /**
441
-     * returns the datetime description
442
-     *
443
-     * @return string
444
-     * @throws ReflectionException
445
-     * @throws InvalidArgumentException
446
-     * @throws InvalidInterfaceException
447
-     * @throws InvalidDataTypeException
448
-     * @throws EE_Error
449
-     */
450
-    public function description()
451
-    {
452
-        return $this->get('DTT_description');
453
-    }
454
-
455
-
456
-    /**
457
-     * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
458
-     *
459
-     * @return boolean  TRUE if is primary, FALSE if not.
460
-     * @throws ReflectionException
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidInterfaceException
463
-     * @throws InvalidDataTypeException
464
-     * @throws EE_Error
465
-     */
466
-    public function is_primary()
467
-    {
468
-        return $this->get('DTT_is_primary');
469
-    }
470
-
471
-
472
-    /**
473
-     * This helper simply returns the order for the datetime
474
-     *
475
-     * @return int  The order of the datetime for this event.
476
-     * @throws ReflectionException
477
-     * @throws InvalidArgumentException
478
-     * @throws InvalidInterfaceException
479
-     * @throws InvalidDataTypeException
480
-     * @throws EE_Error
481
-     */
482
-    public function order()
483
-    {
484
-        return $this->get('DTT_order');
485
-    }
486
-
487
-
488
-    /**
489
-     * This helper simply returns the parent id for the datetime
490
-     *
491
-     * @return int
492
-     * @throws ReflectionException
493
-     * @throws InvalidArgumentException
494
-     * @throws InvalidInterfaceException
495
-     * @throws InvalidDataTypeException
496
-     * @throws EE_Error
497
-     */
498
-    public function parent()
499
-    {
500
-        return $this->get('DTT_parent');
501
-    }
502
-
503
-
504
-    /**
505
-     * show date and/or time
506
-     *
507
-     * @param string $date_or_time    whether to display a date or time or both
508
-     * @param string $start_or_end    whether to display start or end datetimes
509
-     * @param string $dt_frmt
510
-     * @param string $tm_frmt
511
-     * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
512
-     *                                otherwise we use the standard formats)
513
-     * @return string|bool  string on success, FALSE on fail
514
-     * @throws ReflectionException
515
-     * @throws InvalidArgumentException
516
-     * @throws InvalidInterfaceException
517
-     * @throws InvalidDataTypeException
518
-     * @throws EE_Error
519
-     */
520
-    private function _show_datetime(
521
-        $date_or_time = null,
522
-        $start_or_end = 'start',
523
-        $dt_frmt = '',
524
-        $tm_frmt = '',
525
-        $echo = false
526
-    ) {
527
-        $field_name = "DTT_EVT_{$start_or_end}";
528
-        $dtt = $this->_get_datetime(
529
-            $field_name,
530
-            $dt_frmt,
531
-            $tm_frmt,
532
-            $date_or_time,
533
-            $echo
534
-        );
535
-        if (! $echo) {
536
-            return $dtt;
537
-        }
538
-        return '';
539
-    }
540
-
541
-
542
-    /**
543
-     * get event start date.  Provide either the date format, or NULL to re-use the
544
-     * last-used format, or '' to use the default date format
545
-     *
546
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
547
-     * @return mixed            string on success, FALSE on fail
548
-     * @throws ReflectionException
549
-     * @throws InvalidArgumentException
550
-     * @throws InvalidInterfaceException
551
-     * @throws InvalidDataTypeException
552
-     * @throws EE_Error
553
-     */
554
-    public function start_date($dt_frmt = '')
555
-    {
556
-        return $this->_show_datetime('D', 'start', $dt_frmt);
557
-    }
558
-
559
-
560
-    /**
561
-     * Echoes start_date()
562
-     *
563
-     * @param string $dt_frmt
564
-     * @throws ReflectionException
565
-     * @throws InvalidArgumentException
566
-     * @throws InvalidInterfaceException
567
-     * @throws InvalidDataTypeException
568
-     * @throws EE_Error
569
-     */
570
-    public function e_start_date($dt_frmt = '')
571
-    {
572
-        $this->_show_datetime('D', 'start', $dt_frmt, null, true);
573
-    }
574
-
575
-
576
-    /**
577
-     * get end date. Provide either the date format, or NULL to re-use the
578
-     * last-used format, or '' to use the default date format
579
-     *
580
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
581
-     * @return mixed            string on success, FALSE on fail
582
-     * @throws ReflectionException
583
-     * @throws InvalidArgumentException
584
-     * @throws InvalidInterfaceException
585
-     * @throws InvalidDataTypeException
586
-     * @throws EE_Error
587
-     */
588
-    public function end_date($dt_frmt = '')
589
-    {
590
-        return $this->_show_datetime('D', 'end', $dt_frmt);
591
-    }
592
-
593
-
594
-    /**
595
-     * Echoes the end date. See end_date()
596
-     *
597
-     * @param string $dt_frmt
598
-     * @throws ReflectionException
599
-     * @throws InvalidArgumentException
600
-     * @throws InvalidInterfaceException
601
-     * @throws InvalidDataTypeException
602
-     * @throws EE_Error
603
-     */
604
-    public function e_end_date($dt_frmt = '')
605
-    {
606
-        $this->_show_datetime('D', 'end', $dt_frmt, null, true);
607
-    }
608
-
609
-
610
-    /**
611
-     * get date_range - meaning the start AND end date
612
-     *
613
-     * @access public
614
-     * @param string $dt_frmt     string representation of date format defaults to WP settings
615
-     * @param string $conjunction conjunction junction what's your function ?
616
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
617
-     * @return mixed              string on success, FALSE on fail
618
-     * @throws ReflectionException
619
-     * @throws InvalidArgumentException
620
-     * @throws InvalidInterfaceException
621
-     * @throws InvalidDataTypeException
622
-     * @throws EE_Error
623
-     */
624
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
625
-    {
626
-        $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
627
-        $start = str_replace(
628
-            ' ',
629
-            '&nbsp;',
630
-            $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
631
-        );
632
-        $end = str_replace(
633
-            ' ',
634
-            '&nbsp;',
635
-            $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
636
-        );
637
-        return $start !== $end ? $start . $conjunction . $end : $start;
638
-    }
639
-
640
-
641
-    /**
642
-     * @param string $dt_frmt
643
-     * @param string $conjunction
644
-     * @throws ReflectionException
645
-     * @throws InvalidArgumentException
646
-     * @throws InvalidInterfaceException
647
-     * @throws InvalidDataTypeException
648
-     * @throws EE_Error
649
-     */
650
-    public function e_date_range($dt_frmt = '', $conjunction = ' - ')
651
-    {
652
-        echo esc_html($this->date_range($dt_frmt, $conjunction));
653
-    }
654
-
655
-
656
-    /**
657
-     * get start time
658
-     *
659
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
660
-     * @return mixed        string on success, FALSE on fail
661
-     * @throws ReflectionException
662
-     * @throws InvalidArgumentException
663
-     * @throws InvalidInterfaceException
664
-     * @throws InvalidDataTypeException
665
-     * @throws EE_Error
666
-     */
667
-    public function start_time($tm_format = '')
668
-    {
669
-        return $this->_show_datetime('T', 'start', null, $tm_format);
670
-    }
671
-
672
-
673
-    /**
674
-     * @param string $tm_format
675
-     * @throws ReflectionException
676
-     * @throws InvalidArgumentException
677
-     * @throws InvalidInterfaceException
678
-     * @throws InvalidDataTypeException
679
-     * @throws EE_Error
680
-     */
681
-    public function e_start_time($tm_format = '')
682
-    {
683
-        $this->_show_datetime('T', 'start', null, $tm_format, true);
684
-    }
685
-
686
-
687
-    /**
688
-     * get end time
689
-     *
690
-     * @param string $tm_format string representation of time format defaults to 'g:i a'
691
-     * @return mixed                string on success, FALSE on fail
692
-     * @throws ReflectionException
693
-     * @throws InvalidArgumentException
694
-     * @throws InvalidInterfaceException
695
-     * @throws InvalidDataTypeException
696
-     * @throws EE_Error
697
-     */
698
-    public function end_time($tm_format = '')
699
-    {
700
-        return $this->_show_datetime('T', 'end', null, $tm_format);
701
-    }
702
-
703
-
704
-    /**
705
-     * @param string $tm_format
706
-     * @throws ReflectionException
707
-     * @throws InvalidArgumentException
708
-     * @throws InvalidInterfaceException
709
-     * @throws InvalidDataTypeException
710
-     * @throws EE_Error
711
-     */
712
-    public function e_end_time($tm_format = '')
713
-    {
714
-        $this->_show_datetime('T', 'end', null, $tm_format, true);
715
-    }
716
-
717
-
718
-    /**
719
-     * get time_range
720
-     *
721
-     * @access public
722
-     * @param string $tm_format   string representation of time format defaults to 'g:i a'
723
-     * @param string $conjunction conjunction junction what's your function ?
724
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
725
-     * @return mixed              string on success, FALSE on fail
726
-     * @throws ReflectionException
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidInterfaceException
729
-     * @throws InvalidDataTypeException
730
-     * @throws EE_Error
731
-     */
732
-    public function time_range($tm_format = '', $conjunction = ' - ')
733
-    {
734
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
735
-        $start = str_replace(
736
-            ' ',
737
-            '&nbsp;',
738
-            $this->get_i18n_datetime('DTT_EVT_start', $tm_format)
739
-        );
740
-        $end = str_replace(
741
-            ' ',
742
-            '&nbsp;',
743
-            $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
744
-        );
745
-        return $start !== $end ? $start . $conjunction . $end : $start;
746
-    }
747
-
748
-
749
-    /**
750
-     * @param string $tm_format
751
-     * @param string $conjunction
752
-     * @throws ReflectionException
753
-     * @throws InvalidArgumentException
754
-     * @throws InvalidInterfaceException
755
-     * @throws InvalidDataTypeException
756
-     * @throws EE_Error
757
-     */
758
-    public function e_time_range($tm_format = '', $conjunction = ' - ')
759
-    {
760
-        echo esc_html($this->time_range($tm_format, $conjunction));
761
-    }
762
-
763
-
764
-    /**
765
-     * This returns a range representation of the date and times.
766
-     * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
767
-     * Also, the return value is localized.
768
-     *
769
-     * @param string $dt_format
770
-     * @param string $tm_format
771
-     * @param string $conjunction used between two different dates or times.
772
-     *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
773
-     * @param string $separator   used between the date and time formats.
774
-     *                            ex: Dec 1, 2016{$separator}2pm
775
-     * @return string
776
-     * @throws ReflectionException
777
-     * @throws InvalidArgumentException
778
-     * @throws InvalidInterfaceException
779
-     * @throws InvalidDataTypeException
780
-     * @throws EE_Error
781
-     */
782
-    public function date_and_time_range(
783
-        $dt_format = '',
784
-        $tm_format = '',
785
-        $conjunction = ' - ',
786
-        $separator = ' '
787
-    ) {
788
-        $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
789
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
790
-        $full_format = $dt_format . $separator . $tm_format;
791
-        // the range output depends on various conditions
792
-        switch (true) {
793
-            // start date timestamp and end date timestamp are the same.
794
-            case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
795
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
796
-                break;
797
-            // start and end date are the same but times are different
798
-            case ($this->start_date() === $this->end_date()):
799
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
800
-                          . $conjunction
801
-                          . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
802
-                break;
803
-            // all other conditions
804
-            default:
805
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
806
-                          . $conjunction
807
-                          . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
808
-                break;
809
-        }
810
-        return $output;
811
-    }
812
-
813
-
814
-    /**
815
-     * This echos the results of date and time range.
816
-     *
817
-     * @see date_and_time_range() for more details on purpose.
818
-     * @param string $dt_format
819
-     * @param string $tm_format
820
-     * @param string $conjunction
821
-     * @return void
822
-     * @throws ReflectionException
823
-     * @throws InvalidArgumentException
824
-     * @throws InvalidInterfaceException
825
-     * @throws InvalidDataTypeException
826
-     * @throws EE_Error
827
-     */
828
-    public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
829
-    {
830
-        echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction));
831
-    }
832
-
833
-
834
-    /**
835
-     * get start date and start time
836
-     *
837
-     * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
838
-     * @param    string $tm_format - string representation of time format defaults to 'g:i a'
839
-     * @return    mixed    string on success, FALSE on fail
840
-     * @throws ReflectionException
841
-     * @throws InvalidArgumentException
842
-     * @throws InvalidInterfaceException
843
-     * @throws InvalidDataTypeException
844
-     * @throws EE_Error
845
-     */
846
-    public function start_date_and_time($dt_format = '', $tm_format = '')
847
-    {
848
-        return $this->_show_datetime('', 'start', $dt_format, $tm_format);
849
-    }
850
-
851
-
852
-    /**
853
-     * @param string $dt_frmt
854
-     * @param string $tm_format
855
-     * @throws ReflectionException
856
-     * @throws InvalidArgumentException
857
-     * @throws InvalidInterfaceException
858
-     * @throws InvalidDataTypeException
859
-     * @throws EE_Error
860
-     */
861
-    public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
862
-    {
863
-        $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
864
-    }
865
-
866
-
867
-    /**
868
-     * Shows the length of the event (start to end time).
869
-     * Can be shown in 'seconds','minutes','hours', or 'days'.
870
-     * By default, rounds up. (So if you use 'days', and then event
871
-     * only occurs for 1 hour, it will return 1 day).
872
-     *
873
-     * @param string $units 'seconds','minutes','hours','days'
874
-     * @param bool   $round_up
875
-     * @return float|int|mixed
876
-     * @throws ReflectionException
877
-     * @throws InvalidArgumentException
878
-     * @throws InvalidInterfaceException
879
-     * @throws InvalidDataTypeException
880
-     * @throws EE_Error
881
-     */
882
-    public function length($units = 'seconds', $round_up = false)
883
-    {
884
-        $start = $this->get_raw('DTT_EVT_start');
885
-        $end = $this->get_raw('DTT_EVT_end');
886
-        $length_in_units = $end - $start;
887
-        switch ($units) {
888
-            // NOTE: We purposefully don't use "break;" in order to chain the divisions
889
-            /** @noinspection PhpMissingBreakStatementInspection */
890
-            // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
891
-            case 'days':
892
-                $length_in_units /= 24;
893
-            /** @noinspection PhpMissingBreakStatementInspection */
894
-            case 'hours':
895
-                // fall through is intentional
896
-                $length_in_units /= 60;
897
-            /** @noinspection PhpMissingBreakStatementInspection */
898
-            case 'minutes':
899
-                // fall through is intentional
900
-                $length_in_units /= 60;
901
-            case 'seconds':
902
-            default:
903
-                $length_in_units = ceil($length_in_units);
904
-        }
905
-        // phpcs:enable
906
-        if ($round_up) {
907
-            $length_in_units = max($length_in_units, 1);
908
-        }
909
-        return $length_in_units;
910
-    }
911
-
912
-
913
-    /**
914
-     *        get end date and time
915
-     *
916
-     * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
917
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
918
-     * @return    mixed                string on success, FALSE on fail
919
-     * @throws ReflectionException
920
-     * @throws InvalidArgumentException
921
-     * @throws InvalidInterfaceException
922
-     * @throws InvalidDataTypeException
923
-     * @throws EE_Error
924
-     */
925
-    public function end_date_and_time($dt_frmt = '', $tm_format = '')
926
-    {
927
-        return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
928
-    }
929
-
930
-
931
-    /**
932
-     * @param string $dt_frmt
933
-     * @param string $tm_format
934
-     * @throws ReflectionException
935
-     * @throws InvalidArgumentException
936
-     * @throws InvalidInterfaceException
937
-     * @throws InvalidDataTypeException
938
-     * @throws EE_Error
939
-     */
940
-    public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
941
-    {
942
-        $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
943
-    }
944
-
945
-
946
-    /**
947
-     *        get start timestamp
948
-     *
949
-     * @return        int
950
-     * @throws ReflectionException
951
-     * @throws InvalidArgumentException
952
-     * @throws InvalidInterfaceException
953
-     * @throws InvalidDataTypeException
954
-     * @throws EE_Error
955
-     */
956
-    public function start()
957
-    {
958
-        return $this->get_raw('DTT_EVT_start');
959
-    }
960
-
961
-
962
-    /**
963
-     *        get end timestamp
964
-     *
965
-     * @return        int
966
-     * @throws ReflectionException
967
-     * @throws InvalidArgumentException
968
-     * @throws InvalidInterfaceException
969
-     * @throws InvalidDataTypeException
970
-     * @throws EE_Error
971
-     */
972
-    public function end()
973
-    {
974
-        return $this->get_raw('DTT_EVT_end');
975
-    }
976
-
977
-
978
-    /**
979
-     *    get the registration limit for this datetime slot
980
-     *
981
-     * @return int|float                int = finite limit   EE_INF(float) = unlimited
982
-     * @throws ReflectionException
983
-     * @throws InvalidArgumentException
984
-     * @throws InvalidInterfaceException
985
-     * @throws InvalidDataTypeException
986
-     * @throws EE_Error
987
-     */
988
-    public function reg_limit()
989
-    {
990
-        return $this->get_raw('DTT_reg_limit');
991
-    }
992
-
993
-
994
-    /**
995
-     *    have the tickets sold for this datetime, met or exceed the registration limit ?
996
-     *
997
-     * @return boolean
998
-     * @throws ReflectionException
999
-     * @throws InvalidArgumentException
1000
-     * @throws InvalidInterfaceException
1001
-     * @throws InvalidDataTypeException
1002
-     * @throws EE_Error
1003
-     */
1004
-    public function sold_out()
1005
-    {
1006
-        return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * return the total number of spaces remaining at this venue.
1012
-     * This only takes the venue's capacity into account, NOT the tickets available for sale
1013
-     *
1014
-     * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1015
-     *                               Because if all tickets attached to this datetime have no spaces left,
1016
-     *                               then this datetime IS effectively sold out.
1017
-     *                               However, there are cases where we just want to know the spaces
1018
-     *                               remaining for this particular datetime, hence the flag.
1019
-     * @return int|float
1020
-     * @throws ReflectionException
1021
-     * @throws InvalidArgumentException
1022
-     * @throws InvalidInterfaceException
1023
-     * @throws InvalidDataTypeException
1024
-     * @throws EE_Error
1025
-     */
1026
-    public function spaces_remaining($consider_tickets = false)
1027
-    {
1028
-        // tickets remaining available for purchase
1029
-        // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1030
-        $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1031
-        if (! $consider_tickets) {
1032
-            return $dtt_remaining;
1033
-        }
1034
-        $tickets_remaining = $this->tickets_remaining();
1035
-        return min($dtt_remaining, $tickets_remaining);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Counts the total tickets available
1041
-     * (from all the different types of tickets which are available for this datetime).
1042
-     *
1043
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1044
-     * @return int
1045
-     * @throws ReflectionException
1046
-     * @throws InvalidArgumentException
1047
-     * @throws InvalidInterfaceException
1048
-     * @throws InvalidDataTypeException
1049
-     * @throws EE_Error
1050
-     */
1051
-    public function tickets_remaining($query_params = array())
1052
-    {
1053
-        $sum = 0;
1054
-        $tickets = $this->tickets($query_params);
1055
-        if (! empty($tickets)) {
1056
-            foreach ($tickets as $ticket) {
1057
-                if ($ticket instanceof EE_Ticket) {
1058
-                    // get the actual amount of tickets that can be sold
1059
-                    $qty = $ticket->qty('saleable');
1060
-                    if ($qty === EE_INF) {
1061
-                        return EE_INF;
1062
-                    }
1063
-                    // no negative ticket quantities plz
1064
-                    if ($qty > 0) {
1065
-                        $sum += $qty;
1066
-                    }
1067
-                }
1068
-            }
1069
-        }
1070
-        return $sum;
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * Gets the count of all the tickets available at this datetime (not ticket types)
1076
-     * before any were sold
1077
-     *
1078
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1079
-     * @return int
1080
-     * @throws ReflectionException
1081
-     * @throws InvalidArgumentException
1082
-     * @throws InvalidInterfaceException
1083
-     * @throws InvalidDataTypeException
1084
-     * @throws EE_Error
1085
-     */
1086
-    public function sum_tickets_initially_available($query_params = array())
1087
-    {
1088
-        return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * Returns the lesser-of-the two: spaces remaining at this datetime, or
1094
-     * the total tickets remaining (a sum of the tickets remaining for each ticket type
1095
-     * that is available for this datetime).
1096
-     *
1097
-     * @return int
1098
-     * @throws ReflectionException
1099
-     * @throws InvalidArgumentException
1100
-     * @throws InvalidInterfaceException
1101
-     * @throws InvalidDataTypeException
1102
-     * @throws EE_Error
1103
-     */
1104
-    public function total_tickets_available_at_this_datetime()
1105
-    {
1106
-        return $this->spaces_remaining(true);
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * This simply compares the internal dtt for the given string with NOW
1112
-     * and determines if the date is upcoming or not.
1113
-     *
1114
-     * @access public
1115
-     * @return boolean
1116
-     * @throws ReflectionException
1117
-     * @throws InvalidArgumentException
1118
-     * @throws InvalidInterfaceException
1119
-     * @throws InvalidDataTypeException
1120
-     * @throws EE_Error
1121
-     */
1122
-    public function is_upcoming()
1123
-    {
1124
-        return ($this->get_raw('DTT_EVT_start') > time());
1125
-    }
1126
-
1127
-
1128
-    /**
1129
-     * This simply compares the internal datetime for the given string with NOW
1130
-     * and returns if the date is active (i.e. start and end time)
1131
-     *
1132
-     * @return boolean
1133
-     * @throws ReflectionException
1134
-     * @throws InvalidArgumentException
1135
-     * @throws InvalidInterfaceException
1136
-     * @throws InvalidDataTypeException
1137
-     * @throws EE_Error
1138
-     */
1139
-    public function is_active()
1140
-    {
1141
-        return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * This simply compares the internal dtt for the given string with NOW
1147
-     * and determines if the date is expired or not.
1148
-     *
1149
-     * @return boolean
1150
-     * @throws ReflectionException
1151
-     * @throws InvalidArgumentException
1152
-     * @throws InvalidInterfaceException
1153
-     * @throws InvalidDataTypeException
1154
-     * @throws EE_Error
1155
-     */
1156
-    public function is_expired()
1157
-    {
1158
-        return ($this->get_raw('DTT_EVT_end') < time());
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * This returns the active status for whether an event is active, upcoming, or expired
1164
-     *
1165
-     * @return int return value will be one of the EE_Datetime status constants.
1166
-     * @throws ReflectionException
1167
-     * @throws InvalidArgumentException
1168
-     * @throws InvalidInterfaceException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws EE_Error
1171
-     */
1172
-    public function get_active_status()
1173
-    {
1174
-        $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1175
-        if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1176
-            return EE_Datetime::sold_out;
1177
-        }
1178
-        if ($this->is_expired()) {
1179
-            return EE_Datetime::expired;
1180
-        }
1181
-        if ($this->is_upcoming()) {
1182
-            return EE_Datetime::upcoming;
1183
-        }
1184
-        if ($this->is_active()) {
1185
-            return EE_Datetime::active;
1186
-        }
1187
-        return null;
1188
-    }
1189
-
1190
-
1191
-    /**
1192
-     * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1193
-     *
1194
-     * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1195
-     * @return string
1196
-     * @throws ReflectionException
1197
-     * @throws InvalidArgumentException
1198
-     * @throws InvalidInterfaceException
1199
-     * @throws InvalidDataTypeException
1200
-     * @throws EE_Error
1201
-     */
1202
-    public function get_dtt_display_name($use_dtt_name = false)
1203
-    {
1204
-        if ($use_dtt_name) {
1205
-            $dtt_name = $this->name();
1206
-            if (! empty($dtt_name)) {
1207
-                return $dtt_name;
1208
-            }
1209
-        }
1210
-        // first condition is to see if the months are different
1211
-        if (
1212
-            date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
-        ) {
1214
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
-            // next condition is if its the same month but different day
1216
-        } else {
1217
-            if (
1218
-                date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1219
-                && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1220
-            ) {
1221
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1222
-            } else {
1223
-                $display_date = $this->start_date('F j\, Y')
1224
-                                . ' @ '
1225
-                                . $this->start_date('g:i a')
1226
-                                . ' - '
1227
-                                . $this->end_date('g:i a');
1228
-            }
1229
-        }
1230
-        return $display_date;
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * Gets all the tickets for this datetime
1236
-     *
1237
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1238
-     * @return EE_Base_Class[]|EE_Ticket[]
1239
-     * @throws ReflectionException
1240
-     * @throws InvalidArgumentException
1241
-     * @throws InvalidInterfaceException
1242
-     * @throws InvalidDataTypeException
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function tickets($query_params = array())
1246
-    {
1247
-        return $this->get_many_related('Ticket', $query_params);
1248
-    }
1249
-
1250
-
1251
-    /**
1252
-     * Gets all the ticket types currently available for purchase
1253
-     *
1254
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1255
-     * @return EE_Ticket[]
1256
-     * @throws ReflectionException
1257
-     * @throws InvalidArgumentException
1258
-     * @throws InvalidInterfaceException
1259
-     * @throws InvalidDataTypeException
1260
-     * @throws EE_Error
1261
-     */
1262
-    public function ticket_types_available_for_purchase($query_params = array())
1263
-    {
1264
-        // first check if datetime is valid
1265
-        if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1266
-            return array();
1267
-        }
1268
-        if (empty($query_params)) {
1269
-            $query_params = array(
1270
-                array(
1271
-                    'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1272
-                    'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1273
-                    'TKT_deleted'    => false,
1274
-                ),
1275
-            );
1276
-        }
1277
-        return $this->tickets($query_params);
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * @return EE_Base_Class|EE_Event
1283
-     * @throws ReflectionException
1284
-     * @throws InvalidArgumentException
1285
-     * @throws InvalidInterfaceException
1286
-     * @throws InvalidDataTypeException
1287
-     * @throws EE_Error
1288
-     */
1289
-    public function event()
1290
-    {
1291
-        return $this->get_first_related('Event');
1292
-    }
1293
-
1294
-
1295
-    /**
1296
-     * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1297
-     * (via the tickets).
1298
-     *
1299
-     * @return int
1300
-     * @throws ReflectionException
1301
-     * @throws InvalidArgumentException
1302
-     * @throws InvalidInterfaceException
1303
-     * @throws InvalidDataTypeException
1304
-     * @throws EE_Error
1305
-     */
1306
-    public function update_sold()
1307
-    {
1308
-        $count_regs_for_this_datetime = EEM_Registration::instance()->count(
1309
-            array(
1310
-                array(
1311
-                    'STS_ID'                 => EEM_Registration::status_id_approved,
1312
-                    'REG_deleted'            => 0,
1313
-                    'Ticket.Datetime.DTT_ID' => $this->ID(),
1314
-                ),
1315
-            )
1316
-        );
1317
-        $this->set_sold($count_regs_for_this_datetime);
1318
-        $this->save();
1319
-        return $count_regs_for_this_datetime;
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * Adds a venue to this event
1325
-     *
1326
-     * @param int|EE_Venue /int $venue_id_or_obj
1327
-     * @return EE_Base_Class|EE_Venue
1328
-     * @throws EE_Error
1329
-     * @throws ReflectionException
1330
-     */
1331
-    public function add_venue($venue_id_or_obj)
1332
-    {
1333
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     * Removes a venue from the event
1339
-     *
1340
-     * @param EE_Venue /int $venue_id_or_obj
1341
-     * @return EE_Base_Class|EE_Venue
1342
-     * @throws EE_Error
1343
-     * @throws ReflectionException
1344
-     */
1345
-    public function remove_venue($venue_id_or_obj)
1346
-    {
1347
-        $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1348
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1349
-    }
1350
-
1351
-
1352
-    /**
1353
-     * Gets the venue related to the event. May provide additional $query_params if desired
1354
-     *
1355
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1356
-     * @return int
1357
-     * @throws EE_Error
1358
-     * @throws ReflectionException
1359
-     */
1360
-    public function venue_ID($query_params = [])
1361
-    {
1362
-        $venue = $this->get_first_related('Venue', $query_params);
1363
-        return $venue instanceof EE_Venue
1364
-            ? $venue->ID()
1365
-            : 0;
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * Gets the venue related to the event. May provide additional $query_params if desired
1371
-     *
1372
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1373
-     * @return EE_Base_Class|EE_Venue
1374
-     * @throws EE_Error
1375
-     * @throws ReflectionException
1376
-     */
1377
-    public function venue($query_params = [])
1378
-    {
1379
-        return $this->get_first_related('Venue', $query_params);
1380
-    }
1381
-
1382
-
1383
-    /**
1384
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1385
-     * @param string                   $relationName
1386
-     * @param array                    $extra_join_model_fields_n_values
1387
-     * @param string|null              $cache_id
1388
-     * @return EE_Base_Class
1389
-     * @throws EE_Error
1390
-     * @throws ReflectionException
1391
-     * @since   $VID:$
1392
-     */
1393
-    public function _add_relation_to(
1394
-        $otherObjectModelObjectOrID,
1395
-        $relationName,
1396
-        $extra_join_model_fields_n_values = [],
1397
-        $cache_id = null
1398
-    ) {
1399
-        // if we're adding a new relation to a ticket
1400
-        if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1401
-            /** @var EE_Ticket $ticket */
1402
-            $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
-            $this->increaseSold($ticket->sold(), false);
1404
-            $this->increaseReserved($ticket->reserved());
1405
-            $this->save();
1406
-            $otherObjectModelObjectOrID = $ticket;
1407
-        }
1408
-        return parent::_add_relation_to(
1409
-            $otherObjectModelObjectOrID,
1410
-            $relationName,
1411
-            $extra_join_model_fields_n_values,
1412
-            $cache_id
1413
-        );
1414
-    }
1415
-
1416
-
1417
-    /**
1418
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1419
-     * @param string                   $relationName
1420
-     * @param array                    $where_query
1421
-     * @return bool|EE_Base_Class|null
1422
-     * @throws EE_Error
1423
-     * @throws ReflectionException
1424
-     * @since   $VID:$
1425
-     */
1426
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1427
-    {
1428
-        if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1429
-            /** @var EE_Ticket $ticket */
1430
-            $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1431
-            $this->decreaseSold($ticket->sold());
1432
-            $this->decreaseReserved($ticket->reserved());
1433
-            $this->save();
1434
-            $otherObjectModelObjectOrID = $ticket;
1435
-        }
1436
-        return parent::_remove_relation_to(
1437
-            $otherObjectModelObjectOrID,
1438
-            $relationName,
1439
-            $where_query
1440
-        );
1441
-    }
1442
-
1443
-
1444
-    /**
1445
-     * Removes ALL the related things for the $relationName.
1446
-     *
1447
-     * @param string $relationName
1448
-     * @param array  $where_query_params
1449
-     * @return EE_Base_Class
1450
-     * @throws ReflectionException
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidInterfaceException
1453
-     * @throws InvalidDataTypeException
1454
-     * @throws EE_Error
1455
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
1456
-     */
1457
-    public function _remove_relations($relationName, $where_query_params = [])
1458
-    {
1459
-        if ($relationName === 'Ticket') {
1460
-            $tickets = $this->tickets();
1461
-            foreach ($tickets as $ticket) {
1462
-                $this->decreaseSold($ticket->sold());
1463
-                $this->decreaseReserved($ticket->reserved());
1464
-                $this->save();
1465
-            }
1466
-        }
1467
-        return parent::_remove_relations($relationName, $where_query_params);
1468
-    }
1469
-
1470
-
1471
-    /*******************************************************************
15
+	/**
16
+	 * constant used by get_active_status, indicates datetime has no more available spaces
17
+	 */
18
+	const sold_out = 'DTS';
19
+
20
+	/**
21
+	 * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
22
+	 */
23
+	const active = 'DTA';
24
+
25
+	/**
26
+	 * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
27
+	 * expired
28
+	 */
29
+	const upcoming = 'DTU';
30
+
31
+	/**
32
+	 * Datetime is postponed
33
+	 */
34
+	const postponed = 'DTP';
35
+
36
+	/**
37
+	 * Datetime is cancelled
38
+	 */
39
+	const cancelled = 'DTC';
40
+
41
+	/**
42
+	 * constant used by get_active_status, indicates datetime has expired (event is over)
43
+	 */
44
+	const expired = 'DTE';
45
+
46
+	/**
47
+	 * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
48
+	 */
49
+	const inactive = 'DTI';
50
+
51
+
52
+	/**
53
+	 * @param array  $props_n_values    incoming values
54
+	 * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
55
+	 * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
56
+	 *                                  and the second value is the time format
57
+	 * @return EE_Datetime
58
+	 * @throws ReflectionException
59
+	 * @throws InvalidArgumentException
60
+	 * @throws InvalidInterfaceException
61
+	 * @throws InvalidDataTypeException
62
+	 * @throws EE_Error
63
+	 */
64
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
65
+	{
66
+		$has_object = parent::_check_for_object(
67
+			$props_n_values,
68
+			__CLASS__,
69
+			$timezone,
70
+			$date_formats
71
+		);
72
+		return $has_object
73
+			? $has_object
74
+			: new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Datetime
83
+	 * @throws ReflectionException
84
+	 * @throws InvalidArgumentException
85
+	 * @throws InvalidInterfaceException
86
+	 * @throws InvalidDataTypeException
87
+	 * @throws EE_Error
88
+	 */
89
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
90
+	{
91
+		return new self($props_n_values, true, $timezone);
92
+	}
93
+
94
+
95
+	/**
96
+	 * @param $name
97
+	 * @throws ReflectionException
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidInterfaceException
100
+	 * @throws InvalidDataTypeException
101
+	 * @throws EE_Error
102
+	 */
103
+	public function set_name($name)
104
+	{
105
+		$this->set('DTT_name', $name);
106
+	}
107
+
108
+
109
+	/**
110
+	 * @param $description
111
+	 * @throws ReflectionException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidInterfaceException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws EE_Error
116
+	 */
117
+	public function set_description($description)
118
+	{
119
+		$this->set('DTT_description', $description);
120
+	}
121
+
122
+
123
+	/**
124
+	 * Set event start date
125
+	 * set the start date for an event
126
+	 *
127
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
128
+	 * @throws ReflectionException
129
+	 * @throws InvalidArgumentException
130
+	 * @throws InvalidInterfaceException
131
+	 * @throws InvalidDataTypeException
132
+	 * @throws EE_Error
133
+	 */
134
+	public function set_start_date($date)
135
+	{
136
+		$this->_set_date_for($date, 'DTT_EVT_start');
137
+	}
138
+
139
+
140
+	/**
141
+	 * Set event start time
142
+	 * set the start time for an event
143
+	 *
144
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
145
+	 * @throws ReflectionException
146
+	 * @throws InvalidArgumentException
147
+	 * @throws InvalidInterfaceException
148
+	 * @throws InvalidDataTypeException
149
+	 * @throws EE_Error
150
+	 */
151
+	public function set_start_time($time)
152
+	{
153
+		$this->_set_time_for($time, 'DTT_EVT_start');
154
+	}
155
+
156
+
157
+	/**
158
+	 * Set event end date
159
+	 * set the end date for an event
160
+	 *
161
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
162
+	 * @throws ReflectionException
163
+	 * @throws InvalidArgumentException
164
+	 * @throws InvalidInterfaceException
165
+	 * @throws InvalidDataTypeException
166
+	 * @throws EE_Error
167
+	 */
168
+	public function set_end_date($date)
169
+	{
170
+		$this->_set_date_for($date, 'DTT_EVT_end');
171
+	}
172
+
173
+
174
+	/**
175
+	 * Set event end time
176
+	 * set the end time for an event
177
+	 *
178
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
179
+	 * @throws ReflectionException
180
+	 * @throws InvalidArgumentException
181
+	 * @throws InvalidInterfaceException
182
+	 * @throws InvalidDataTypeException
183
+	 * @throws EE_Error
184
+	 */
185
+	public function set_end_time($time)
186
+	{
187
+		$this->_set_time_for($time, 'DTT_EVT_end');
188
+	}
189
+
190
+
191
+	/**
192
+	 * Set registration limit
193
+	 * set the maximum number of attendees that can be registered for this datetime slot
194
+	 *
195
+	 * @param int|float $reg_limit
196
+	 * @throws ReflectionException
197
+	 * @throws InvalidArgumentException
198
+	 * @throws InvalidInterfaceException
199
+	 * @throws InvalidDataTypeException
200
+	 * @throws EE_Error
201
+	 */
202
+	public function set_reg_limit($reg_limit)
203
+	{
204
+		$this->set('DTT_reg_limit', $reg_limit);
205
+	}
206
+
207
+
208
+	/**
209
+	 * get the number of tickets sold for this datetime slot
210
+	 *
211
+	 * @return mixed int on success, FALSE on fail
212
+	 * @throws ReflectionException
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidInterfaceException
215
+	 * @throws InvalidDataTypeException
216
+	 * @throws EE_Error
217
+	 */
218
+	public function sold()
219
+	{
220
+		return $this->get_raw('DTT_sold');
221
+	}
222
+
223
+
224
+	/**
225
+	 * @param int $sold
226
+	 * @throws ReflectionException
227
+	 * @throws InvalidArgumentException
228
+	 * @throws InvalidInterfaceException
229
+	 * @throws InvalidDataTypeException
230
+	 * @throws EE_Error
231
+	 */
232
+	public function set_sold($sold)
233
+	{
234
+		// sold can not go below zero
235
+		$sold = max(0, $sold);
236
+		$this->set('DTT_sold', $sold);
237
+	}
238
+
239
+
240
+	/**
241
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
242
+	 * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
243
+	 *
244
+	 * @param int $qty
245
+	 * @param boolean $also_decrease_reserved
246
+	 * @return boolean indicating success
247
+	 * @throws ReflectionException
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidInterfaceException
250
+	 * @throws InvalidDataTypeException
251
+	 * @throws EE_Error
252
+	 */
253
+	public function increaseSold($qty = 1, $also_decrease_reserved = true)
254
+	{
255
+		$qty = absint($qty);
256
+		if ($also_decrease_reserved) {
257
+			$success = $this->adjustNumericFieldsInDb(
258
+				[
259
+					'DTT_reserved' => $qty * -1,
260
+					'DTT_sold' => $qty
261
+				]
262
+			);
263
+		} else {
264
+			$success = $this->adjustNumericFieldsInDb(
265
+				[
266
+					'DTT_sold' => $qty
267
+				]
268
+			);
269
+		}
270
+
271
+		do_action(
272
+			'AHEE__EE_Datetime__increase_sold',
273
+			$this,
274
+			$qty,
275
+			$this->sold(),
276
+			$success
277
+		);
278
+		return $success;
279
+	}
280
+
281
+
282
+	/**
283
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
284
+	 * to save afterwards.)
285
+	 *
286
+	 * @param int $qty
287
+	 * @return boolean indicating success
288
+	 * @throws ReflectionException
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidInterfaceException
291
+	 * @throws InvalidDataTypeException
292
+	 * @throws EE_Error
293
+	 */
294
+	public function decreaseSold($qty = 1)
295
+	{
296
+		$qty = absint($qty);
297
+		$success = $this->adjustNumericFieldsInDb(
298
+			[
299
+				'DTT_sold' => $qty * -1
300
+			]
301
+		);
302
+		do_action(
303
+			'AHEE__EE_Datetime__decrease_sold',
304
+			$this,
305
+			$qty,
306
+			$this->sold(),
307
+			$success
308
+		);
309
+		return $success;
310
+	}
311
+
312
+
313
+	/**
314
+	 * Gets qty of reserved tickets for this datetime
315
+	 *
316
+	 * @return int
317
+	 * @throws ReflectionException
318
+	 * @throws InvalidArgumentException
319
+	 * @throws InvalidInterfaceException
320
+	 * @throws InvalidDataTypeException
321
+	 * @throws EE_Error
322
+	 */
323
+	public function reserved()
324
+	{
325
+		return $this->get_raw('DTT_reserved');
326
+	}
327
+
328
+
329
+	/**
330
+	 * Sets qty of reserved tickets for this datetime
331
+	 *
332
+	 * @param int $reserved
333
+	 * @throws ReflectionException
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidInterfaceException
336
+	 * @throws InvalidDataTypeException
337
+	 * @throws EE_Error
338
+	 */
339
+	public function set_reserved($reserved)
340
+	{
341
+		// reserved can not go below zero
342
+		$reserved = max(0, $reserved);
343
+		$this->set('DTT_reserved', $reserved);
344
+	}
345
+
346
+
347
+	/**
348
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
349
+	 *
350
+	 * @param int $qty
351
+	 * @return boolean indicating success
352
+	 * @throws ReflectionException
353
+	 * @throws InvalidArgumentException
354
+	 * @throws InvalidInterfaceException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws EE_Error
357
+	 */
358
+	public function increaseReserved($qty = 1)
359
+	{
360
+		$qty = absint($qty);
361
+		$success = $this->incrementFieldConditionallyInDb(
362
+			'DTT_reserved',
363
+			'DTT_sold',
364
+			'DTT_reg_limit',
365
+			$qty
366
+		);
367
+		do_action(
368
+			'AHEE__EE_Datetime__increase_reserved',
369
+			$this,
370
+			$qty,
371
+			$this->reserved(),
372
+			$success
373
+		);
374
+		return $success;
375
+	}
376
+
377
+
378
+	/**
379
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
380
+	 *
381
+	 * @param int $qty
382
+	 * @return boolean indicating success
383
+	 * @throws ReflectionException
384
+	 * @throws InvalidArgumentException
385
+	 * @throws InvalidInterfaceException
386
+	 * @throws InvalidDataTypeException
387
+	 * @throws EE_Error
388
+	 */
389
+	public function decreaseReserved($qty = 1)
390
+	{
391
+		$qty = absint($qty);
392
+		$success = $this->adjustNumericFieldsInDb(
393
+			[
394
+				'DTT_reserved' => $qty * -1
395
+			]
396
+		);
397
+		do_action(
398
+			'AHEE__EE_Datetime__decrease_reserved',
399
+			$this,
400
+			$qty,
401
+			$this->reserved(),
402
+			$success
403
+		);
404
+		return $success;
405
+	}
406
+
407
+
408
+	/**
409
+	 * total sold and reserved tickets
410
+	 *
411
+	 * @return int
412
+	 * @throws ReflectionException
413
+	 * @throws InvalidArgumentException
414
+	 * @throws InvalidInterfaceException
415
+	 * @throws InvalidDataTypeException
416
+	 * @throws EE_Error
417
+	 */
418
+	public function sold_and_reserved()
419
+	{
420
+		return $this->sold() + $this->reserved();
421
+	}
422
+
423
+
424
+	/**
425
+	 * returns the datetime name
426
+	 *
427
+	 * @return string
428
+	 * @throws ReflectionException
429
+	 * @throws InvalidArgumentException
430
+	 * @throws InvalidInterfaceException
431
+	 * @throws InvalidDataTypeException
432
+	 * @throws EE_Error
433
+	 */
434
+	public function name()
435
+	{
436
+		return $this->get('DTT_name');
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns the datetime description
442
+	 *
443
+	 * @return string
444
+	 * @throws ReflectionException
445
+	 * @throws InvalidArgumentException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws EE_Error
449
+	 */
450
+	public function description()
451
+	{
452
+		return $this->get('DTT_description');
453
+	}
454
+
455
+
456
+	/**
457
+	 * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
458
+	 *
459
+	 * @return boolean  TRUE if is primary, FALSE if not.
460
+	 * @throws ReflectionException
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidInterfaceException
463
+	 * @throws InvalidDataTypeException
464
+	 * @throws EE_Error
465
+	 */
466
+	public function is_primary()
467
+	{
468
+		return $this->get('DTT_is_primary');
469
+	}
470
+
471
+
472
+	/**
473
+	 * This helper simply returns the order for the datetime
474
+	 *
475
+	 * @return int  The order of the datetime for this event.
476
+	 * @throws ReflectionException
477
+	 * @throws InvalidArgumentException
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws EE_Error
481
+	 */
482
+	public function order()
483
+	{
484
+		return $this->get('DTT_order');
485
+	}
486
+
487
+
488
+	/**
489
+	 * This helper simply returns the parent id for the datetime
490
+	 *
491
+	 * @return int
492
+	 * @throws ReflectionException
493
+	 * @throws InvalidArgumentException
494
+	 * @throws InvalidInterfaceException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws EE_Error
497
+	 */
498
+	public function parent()
499
+	{
500
+		return $this->get('DTT_parent');
501
+	}
502
+
503
+
504
+	/**
505
+	 * show date and/or time
506
+	 *
507
+	 * @param string $date_or_time    whether to display a date or time or both
508
+	 * @param string $start_or_end    whether to display start or end datetimes
509
+	 * @param string $dt_frmt
510
+	 * @param string $tm_frmt
511
+	 * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
512
+	 *                                otherwise we use the standard formats)
513
+	 * @return string|bool  string on success, FALSE on fail
514
+	 * @throws ReflectionException
515
+	 * @throws InvalidArgumentException
516
+	 * @throws InvalidInterfaceException
517
+	 * @throws InvalidDataTypeException
518
+	 * @throws EE_Error
519
+	 */
520
+	private function _show_datetime(
521
+		$date_or_time = null,
522
+		$start_or_end = 'start',
523
+		$dt_frmt = '',
524
+		$tm_frmt = '',
525
+		$echo = false
526
+	) {
527
+		$field_name = "DTT_EVT_{$start_or_end}";
528
+		$dtt = $this->_get_datetime(
529
+			$field_name,
530
+			$dt_frmt,
531
+			$tm_frmt,
532
+			$date_or_time,
533
+			$echo
534
+		);
535
+		if (! $echo) {
536
+			return $dtt;
537
+		}
538
+		return '';
539
+	}
540
+
541
+
542
+	/**
543
+	 * get event start date.  Provide either the date format, or NULL to re-use the
544
+	 * last-used format, or '' to use the default date format
545
+	 *
546
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
547
+	 * @return mixed            string on success, FALSE on fail
548
+	 * @throws ReflectionException
549
+	 * @throws InvalidArgumentException
550
+	 * @throws InvalidInterfaceException
551
+	 * @throws InvalidDataTypeException
552
+	 * @throws EE_Error
553
+	 */
554
+	public function start_date($dt_frmt = '')
555
+	{
556
+		return $this->_show_datetime('D', 'start', $dt_frmt);
557
+	}
558
+
559
+
560
+	/**
561
+	 * Echoes start_date()
562
+	 *
563
+	 * @param string $dt_frmt
564
+	 * @throws ReflectionException
565
+	 * @throws InvalidArgumentException
566
+	 * @throws InvalidInterfaceException
567
+	 * @throws InvalidDataTypeException
568
+	 * @throws EE_Error
569
+	 */
570
+	public function e_start_date($dt_frmt = '')
571
+	{
572
+		$this->_show_datetime('D', 'start', $dt_frmt, null, true);
573
+	}
574
+
575
+
576
+	/**
577
+	 * get end date. Provide either the date format, or NULL to re-use the
578
+	 * last-used format, or '' to use the default date format
579
+	 *
580
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
581
+	 * @return mixed            string on success, FALSE on fail
582
+	 * @throws ReflectionException
583
+	 * @throws InvalidArgumentException
584
+	 * @throws InvalidInterfaceException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws EE_Error
587
+	 */
588
+	public function end_date($dt_frmt = '')
589
+	{
590
+		return $this->_show_datetime('D', 'end', $dt_frmt);
591
+	}
592
+
593
+
594
+	/**
595
+	 * Echoes the end date. See end_date()
596
+	 *
597
+	 * @param string $dt_frmt
598
+	 * @throws ReflectionException
599
+	 * @throws InvalidArgumentException
600
+	 * @throws InvalidInterfaceException
601
+	 * @throws InvalidDataTypeException
602
+	 * @throws EE_Error
603
+	 */
604
+	public function e_end_date($dt_frmt = '')
605
+	{
606
+		$this->_show_datetime('D', 'end', $dt_frmt, null, true);
607
+	}
608
+
609
+
610
+	/**
611
+	 * get date_range - meaning the start AND end date
612
+	 *
613
+	 * @access public
614
+	 * @param string $dt_frmt     string representation of date format defaults to WP settings
615
+	 * @param string $conjunction conjunction junction what's your function ?
616
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
617
+	 * @return mixed              string on success, FALSE on fail
618
+	 * @throws ReflectionException
619
+	 * @throws InvalidArgumentException
620
+	 * @throws InvalidInterfaceException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws EE_Error
623
+	 */
624
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
625
+	{
626
+		$dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
627
+		$start = str_replace(
628
+			' ',
629
+			'&nbsp;',
630
+			$this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
631
+		);
632
+		$end = str_replace(
633
+			' ',
634
+			'&nbsp;',
635
+			$this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
636
+		);
637
+		return $start !== $end ? $start . $conjunction . $end : $start;
638
+	}
639
+
640
+
641
+	/**
642
+	 * @param string $dt_frmt
643
+	 * @param string $conjunction
644
+	 * @throws ReflectionException
645
+	 * @throws InvalidArgumentException
646
+	 * @throws InvalidInterfaceException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws EE_Error
649
+	 */
650
+	public function e_date_range($dt_frmt = '', $conjunction = ' - ')
651
+	{
652
+		echo esc_html($this->date_range($dt_frmt, $conjunction));
653
+	}
654
+
655
+
656
+	/**
657
+	 * get start time
658
+	 *
659
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
660
+	 * @return mixed        string on success, FALSE on fail
661
+	 * @throws ReflectionException
662
+	 * @throws InvalidArgumentException
663
+	 * @throws InvalidInterfaceException
664
+	 * @throws InvalidDataTypeException
665
+	 * @throws EE_Error
666
+	 */
667
+	public function start_time($tm_format = '')
668
+	{
669
+		return $this->_show_datetime('T', 'start', null, $tm_format);
670
+	}
671
+
672
+
673
+	/**
674
+	 * @param string $tm_format
675
+	 * @throws ReflectionException
676
+	 * @throws InvalidArgumentException
677
+	 * @throws InvalidInterfaceException
678
+	 * @throws InvalidDataTypeException
679
+	 * @throws EE_Error
680
+	 */
681
+	public function e_start_time($tm_format = '')
682
+	{
683
+		$this->_show_datetime('T', 'start', null, $tm_format, true);
684
+	}
685
+
686
+
687
+	/**
688
+	 * get end time
689
+	 *
690
+	 * @param string $tm_format string representation of time format defaults to 'g:i a'
691
+	 * @return mixed                string on success, FALSE on fail
692
+	 * @throws ReflectionException
693
+	 * @throws InvalidArgumentException
694
+	 * @throws InvalidInterfaceException
695
+	 * @throws InvalidDataTypeException
696
+	 * @throws EE_Error
697
+	 */
698
+	public function end_time($tm_format = '')
699
+	{
700
+		return $this->_show_datetime('T', 'end', null, $tm_format);
701
+	}
702
+
703
+
704
+	/**
705
+	 * @param string $tm_format
706
+	 * @throws ReflectionException
707
+	 * @throws InvalidArgumentException
708
+	 * @throws InvalidInterfaceException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws EE_Error
711
+	 */
712
+	public function e_end_time($tm_format = '')
713
+	{
714
+		$this->_show_datetime('T', 'end', null, $tm_format, true);
715
+	}
716
+
717
+
718
+	/**
719
+	 * get time_range
720
+	 *
721
+	 * @access public
722
+	 * @param string $tm_format   string representation of time format defaults to 'g:i a'
723
+	 * @param string $conjunction conjunction junction what's your function ?
724
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
725
+	 * @return mixed              string on success, FALSE on fail
726
+	 * @throws ReflectionException
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidInterfaceException
729
+	 * @throws InvalidDataTypeException
730
+	 * @throws EE_Error
731
+	 */
732
+	public function time_range($tm_format = '', $conjunction = ' - ')
733
+	{
734
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
735
+		$start = str_replace(
736
+			' ',
737
+			'&nbsp;',
738
+			$this->get_i18n_datetime('DTT_EVT_start', $tm_format)
739
+		);
740
+		$end = str_replace(
741
+			' ',
742
+			'&nbsp;',
743
+			$this->get_i18n_datetime('DTT_EVT_end', $tm_format)
744
+		);
745
+		return $start !== $end ? $start . $conjunction . $end : $start;
746
+	}
747
+
748
+
749
+	/**
750
+	 * @param string $tm_format
751
+	 * @param string $conjunction
752
+	 * @throws ReflectionException
753
+	 * @throws InvalidArgumentException
754
+	 * @throws InvalidInterfaceException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws EE_Error
757
+	 */
758
+	public function e_time_range($tm_format = '', $conjunction = ' - ')
759
+	{
760
+		echo esc_html($this->time_range($tm_format, $conjunction));
761
+	}
762
+
763
+
764
+	/**
765
+	 * This returns a range representation of the date and times.
766
+	 * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
767
+	 * Also, the return value is localized.
768
+	 *
769
+	 * @param string $dt_format
770
+	 * @param string $tm_format
771
+	 * @param string $conjunction used between two different dates or times.
772
+	 *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
773
+	 * @param string $separator   used between the date and time formats.
774
+	 *                            ex: Dec 1, 2016{$separator}2pm
775
+	 * @return string
776
+	 * @throws ReflectionException
777
+	 * @throws InvalidArgumentException
778
+	 * @throws InvalidInterfaceException
779
+	 * @throws InvalidDataTypeException
780
+	 * @throws EE_Error
781
+	 */
782
+	public function date_and_time_range(
783
+		$dt_format = '',
784
+		$tm_format = '',
785
+		$conjunction = ' - ',
786
+		$separator = ' '
787
+	) {
788
+		$dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
789
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
790
+		$full_format = $dt_format . $separator . $tm_format;
791
+		// the range output depends on various conditions
792
+		switch (true) {
793
+			// start date timestamp and end date timestamp are the same.
794
+			case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
795
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
796
+				break;
797
+			// start and end date are the same but times are different
798
+			case ($this->start_date() === $this->end_date()):
799
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
800
+						  . $conjunction
801
+						  . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
802
+				break;
803
+			// all other conditions
804
+			default:
805
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
806
+						  . $conjunction
807
+						  . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
808
+				break;
809
+		}
810
+		return $output;
811
+	}
812
+
813
+
814
+	/**
815
+	 * This echos the results of date and time range.
816
+	 *
817
+	 * @see date_and_time_range() for more details on purpose.
818
+	 * @param string $dt_format
819
+	 * @param string $tm_format
820
+	 * @param string $conjunction
821
+	 * @return void
822
+	 * @throws ReflectionException
823
+	 * @throws InvalidArgumentException
824
+	 * @throws InvalidInterfaceException
825
+	 * @throws InvalidDataTypeException
826
+	 * @throws EE_Error
827
+	 */
828
+	public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
829
+	{
830
+		echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction));
831
+	}
832
+
833
+
834
+	/**
835
+	 * get start date and start time
836
+	 *
837
+	 * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
838
+	 * @param    string $tm_format - string representation of time format defaults to 'g:i a'
839
+	 * @return    mixed    string on success, FALSE on fail
840
+	 * @throws ReflectionException
841
+	 * @throws InvalidArgumentException
842
+	 * @throws InvalidInterfaceException
843
+	 * @throws InvalidDataTypeException
844
+	 * @throws EE_Error
845
+	 */
846
+	public function start_date_and_time($dt_format = '', $tm_format = '')
847
+	{
848
+		return $this->_show_datetime('', 'start', $dt_format, $tm_format);
849
+	}
850
+
851
+
852
+	/**
853
+	 * @param string $dt_frmt
854
+	 * @param string $tm_format
855
+	 * @throws ReflectionException
856
+	 * @throws InvalidArgumentException
857
+	 * @throws InvalidInterfaceException
858
+	 * @throws InvalidDataTypeException
859
+	 * @throws EE_Error
860
+	 */
861
+	public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
862
+	{
863
+		$this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
864
+	}
865
+
866
+
867
+	/**
868
+	 * Shows the length of the event (start to end time).
869
+	 * Can be shown in 'seconds','minutes','hours', or 'days'.
870
+	 * By default, rounds up. (So if you use 'days', and then event
871
+	 * only occurs for 1 hour, it will return 1 day).
872
+	 *
873
+	 * @param string $units 'seconds','minutes','hours','days'
874
+	 * @param bool   $round_up
875
+	 * @return float|int|mixed
876
+	 * @throws ReflectionException
877
+	 * @throws InvalidArgumentException
878
+	 * @throws InvalidInterfaceException
879
+	 * @throws InvalidDataTypeException
880
+	 * @throws EE_Error
881
+	 */
882
+	public function length($units = 'seconds', $round_up = false)
883
+	{
884
+		$start = $this->get_raw('DTT_EVT_start');
885
+		$end = $this->get_raw('DTT_EVT_end');
886
+		$length_in_units = $end - $start;
887
+		switch ($units) {
888
+			// NOTE: We purposefully don't use "break;" in order to chain the divisions
889
+			/** @noinspection PhpMissingBreakStatementInspection */
890
+			// phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
891
+			case 'days':
892
+				$length_in_units /= 24;
893
+			/** @noinspection PhpMissingBreakStatementInspection */
894
+			case 'hours':
895
+				// fall through is intentional
896
+				$length_in_units /= 60;
897
+			/** @noinspection PhpMissingBreakStatementInspection */
898
+			case 'minutes':
899
+				// fall through is intentional
900
+				$length_in_units /= 60;
901
+			case 'seconds':
902
+			default:
903
+				$length_in_units = ceil($length_in_units);
904
+		}
905
+		// phpcs:enable
906
+		if ($round_up) {
907
+			$length_in_units = max($length_in_units, 1);
908
+		}
909
+		return $length_in_units;
910
+	}
911
+
912
+
913
+	/**
914
+	 *        get end date and time
915
+	 *
916
+	 * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
917
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
918
+	 * @return    mixed                string on success, FALSE on fail
919
+	 * @throws ReflectionException
920
+	 * @throws InvalidArgumentException
921
+	 * @throws InvalidInterfaceException
922
+	 * @throws InvalidDataTypeException
923
+	 * @throws EE_Error
924
+	 */
925
+	public function end_date_and_time($dt_frmt = '', $tm_format = '')
926
+	{
927
+		return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
928
+	}
929
+
930
+
931
+	/**
932
+	 * @param string $dt_frmt
933
+	 * @param string $tm_format
934
+	 * @throws ReflectionException
935
+	 * @throws InvalidArgumentException
936
+	 * @throws InvalidInterfaceException
937
+	 * @throws InvalidDataTypeException
938
+	 * @throws EE_Error
939
+	 */
940
+	public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
941
+	{
942
+		$this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
943
+	}
944
+
945
+
946
+	/**
947
+	 *        get start timestamp
948
+	 *
949
+	 * @return        int
950
+	 * @throws ReflectionException
951
+	 * @throws InvalidArgumentException
952
+	 * @throws InvalidInterfaceException
953
+	 * @throws InvalidDataTypeException
954
+	 * @throws EE_Error
955
+	 */
956
+	public function start()
957
+	{
958
+		return $this->get_raw('DTT_EVT_start');
959
+	}
960
+
961
+
962
+	/**
963
+	 *        get end timestamp
964
+	 *
965
+	 * @return        int
966
+	 * @throws ReflectionException
967
+	 * @throws InvalidArgumentException
968
+	 * @throws InvalidInterfaceException
969
+	 * @throws InvalidDataTypeException
970
+	 * @throws EE_Error
971
+	 */
972
+	public function end()
973
+	{
974
+		return $this->get_raw('DTT_EVT_end');
975
+	}
976
+
977
+
978
+	/**
979
+	 *    get the registration limit for this datetime slot
980
+	 *
981
+	 * @return int|float                int = finite limit   EE_INF(float) = unlimited
982
+	 * @throws ReflectionException
983
+	 * @throws InvalidArgumentException
984
+	 * @throws InvalidInterfaceException
985
+	 * @throws InvalidDataTypeException
986
+	 * @throws EE_Error
987
+	 */
988
+	public function reg_limit()
989
+	{
990
+		return $this->get_raw('DTT_reg_limit');
991
+	}
992
+
993
+
994
+	/**
995
+	 *    have the tickets sold for this datetime, met or exceed the registration limit ?
996
+	 *
997
+	 * @return boolean
998
+	 * @throws ReflectionException
999
+	 * @throws InvalidArgumentException
1000
+	 * @throws InvalidInterfaceException
1001
+	 * @throws InvalidDataTypeException
1002
+	 * @throws EE_Error
1003
+	 */
1004
+	public function sold_out()
1005
+	{
1006
+		return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * return the total number of spaces remaining at this venue.
1012
+	 * This only takes the venue's capacity into account, NOT the tickets available for sale
1013
+	 *
1014
+	 * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1015
+	 *                               Because if all tickets attached to this datetime have no spaces left,
1016
+	 *                               then this datetime IS effectively sold out.
1017
+	 *                               However, there are cases where we just want to know the spaces
1018
+	 *                               remaining for this particular datetime, hence the flag.
1019
+	 * @return int|float
1020
+	 * @throws ReflectionException
1021
+	 * @throws InvalidArgumentException
1022
+	 * @throws InvalidInterfaceException
1023
+	 * @throws InvalidDataTypeException
1024
+	 * @throws EE_Error
1025
+	 */
1026
+	public function spaces_remaining($consider_tickets = false)
1027
+	{
1028
+		// tickets remaining available for purchase
1029
+		// no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1030
+		$dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1031
+		if (! $consider_tickets) {
1032
+			return $dtt_remaining;
1033
+		}
1034
+		$tickets_remaining = $this->tickets_remaining();
1035
+		return min($dtt_remaining, $tickets_remaining);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Counts the total tickets available
1041
+	 * (from all the different types of tickets which are available for this datetime).
1042
+	 *
1043
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1044
+	 * @return int
1045
+	 * @throws ReflectionException
1046
+	 * @throws InvalidArgumentException
1047
+	 * @throws InvalidInterfaceException
1048
+	 * @throws InvalidDataTypeException
1049
+	 * @throws EE_Error
1050
+	 */
1051
+	public function tickets_remaining($query_params = array())
1052
+	{
1053
+		$sum = 0;
1054
+		$tickets = $this->tickets($query_params);
1055
+		if (! empty($tickets)) {
1056
+			foreach ($tickets as $ticket) {
1057
+				if ($ticket instanceof EE_Ticket) {
1058
+					// get the actual amount of tickets that can be sold
1059
+					$qty = $ticket->qty('saleable');
1060
+					if ($qty === EE_INF) {
1061
+						return EE_INF;
1062
+					}
1063
+					// no negative ticket quantities plz
1064
+					if ($qty > 0) {
1065
+						$sum += $qty;
1066
+					}
1067
+				}
1068
+			}
1069
+		}
1070
+		return $sum;
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * Gets the count of all the tickets available at this datetime (not ticket types)
1076
+	 * before any were sold
1077
+	 *
1078
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1079
+	 * @return int
1080
+	 * @throws ReflectionException
1081
+	 * @throws InvalidArgumentException
1082
+	 * @throws InvalidInterfaceException
1083
+	 * @throws InvalidDataTypeException
1084
+	 * @throws EE_Error
1085
+	 */
1086
+	public function sum_tickets_initially_available($query_params = array())
1087
+	{
1088
+		return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * Returns the lesser-of-the two: spaces remaining at this datetime, or
1094
+	 * the total tickets remaining (a sum of the tickets remaining for each ticket type
1095
+	 * that is available for this datetime).
1096
+	 *
1097
+	 * @return int
1098
+	 * @throws ReflectionException
1099
+	 * @throws InvalidArgumentException
1100
+	 * @throws InvalidInterfaceException
1101
+	 * @throws InvalidDataTypeException
1102
+	 * @throws EE_Error
1103
+	 */
1104
+	public function total_tickets_available_at_this_datetime()
1105
+	{
1106
+		return $this->spaces_remaining(true);
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * This simply compares the internal dtt for the given string with NOW
1112
+	 * and determines if the date is upcoming or not.
1113
+	 *
1114
+	 * @access public
1115
+	 * @return boolean
1116
+	 * @throws ReflectionException
1117
+	 * @throws InvalidArgumentException
1118
+	 * @throws InvalidInterfaceException
1119
+	 * @throws InvalidDataTypeException
1120
+	 * @throws EE_Error
1121
+	 */
1122
+	public function is_upcoming()
1123
+	{
1124
+		return ($this->get_raw('DTT_EVT_start') > time());
1125
+	}
1126
+
1127
+
1128
+	/**
1129
+	 * This simply compares the internal datetime for the given string with NOW
1130
+	 * and returns if the date is active (i.e. start and end time)
1131
+	 *
1132
+	 * @return boolean
1133
+	 * @throws ReflectionException
1134
+	 * @throws InvalidArgumentException
1135
+	 * @throws InvalidInterfaceException
1136
+	 * @throws InvalidDataTypeException
1137
+	 * @throws EE_Error
1138
+	 */
1139
+	public function is_active()
1140
+	{
1141
+		return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * This simply compares the internal dtt for the given string with NOW
1147
+	 * and determines if the date is expired or not.
1148
+	 *
1149
+	 * @return boolean
1150
+	 * @throws ReflectionException
1151
+	 * @throws InvalidArgumentException
1152
+	 * @throws InvalidInterfaceException
1153
+	 * @throws InvalidDataTypeException
1154
+	 * @throws EE_Error
1155
+	 */
1156
+	public function is_expired()
1157
+	{
1158
+		return ($this->get_raw('DTT_EVT_end') < time());
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * This returns the active status for whether an event is active, upcoming, or expired
1164
+	 *
1165
+	 * @return int return value will be one of the EE_Datetime status constants.
1166
+	 * @throws ReflectionException
1167
+	 * @throws InvalidArgumentException
1168
+	 * @throws InvalidInterfaceException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws EE_Error
1171
+	 */
1172
+	public function get_active_status()
1173
+	{
1174
+		$total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1175
+		if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1176
+			return EE_Datetime::sold_out;
1177
+		}
1178
+		if ($this->is_expired()) {
1179
+			return EE_Datetime::expired;
1180
+		}
1181
+		if ($this->is_upcoming()) {
1182
+			return EE_Datetime::upcoming;
1183
+		}
1184
+		if ($this->is_active()) {
1185
+			return EE_Datetime::active;
1186
+		}
1187
+		return null;
1188
+	}
1189
+
1190
+
1191
+	/**
1192
+	 * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1193
+	 *
1194
+	 * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1195
+	 * @return string
1196
+	 * @throws ReflectionException
1197
+	 * @throws InvalidArgumentException
1198
+	 * @throws InvalidInterfaceException
1199
+	 * @throws InvalidDataTypeException
1200
+	 * @throws EE_Error
1201
+	 */
1202
+	public function get_dtt_display_name($use_dtt_name = false)
1203
+	{
1204
+		if ($use_dtt_name) {
1205
+			$dtt_name = $this->name();
1206
+			if (! empty($dtt_name)) {
1207
+				return $dtt_name;
1208
+			}
1209
+		}
1210
+		// first condition is to see if the months are different
1211
+		if (
1212
+			date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
+		) {
1214
+			$display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
+			// next condition is if its the same month but different day
1216
+		} else {
1217
+			if (
1218
+				date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1219
+				&& date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1220
+			) {
1221
+				$display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1222
+			} else {
1223
+				$display_date = $this->start_date('F j\, Y')
1224
+								. ' @ '
1225
+								. $this->start_date('g:i a')
1226
+								. ' - '
1227
+								. $this->end_date('g:i a');
1228
+			}
1229
+		}
1230
+		return $display_date;
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * Gets all the tickets for this datetime
1236
+	 *
1237
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1238
+	 * @return EE_Base_Class[]|EE_Ticket[]
1239
+	 * @throws ReflectionException
1240
+	 * @throws InvalidArgumentException
1241
+	 * @throws InvalidInterfaceException
1242
+	 * @throws InvalidDataTypeException
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function tickets($query_params = array())
1246
+	{
1247
+		return $this->get_many_related('Ticket', $query_params);
1248
+	}
1249
+
1250
+
1251
+	/**
1252
+	 * Gets all the ticket types currently available for purchase
1253
+	 *
1254
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1255
+	 * @return EE_Ticket[]
1256
+	 * @throws ReflectionException
1257
+	 * @throws InvalidArgumentException
1258
+	 * @throws InvalidInterfaceException
1259
+	 * @throws InvalidDataTypeException
1260
+	 * @throws EE_Error
1261
+	 */
1262
+	public function ticket_types_available_for_purchase($query_params = array())
1263
+	{
1264
+		// first check if datetime is valid
1265
+		if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1266
+			return array();
1267
+		}
1268
+		if (empty($query_params)) {
1269
+			$query_params = array(
1270
+				array(
1271
+					'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1272
+					'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1273
+					'TKT_deleted'    => false,
1274
+				),
1275
+			);
1276
+		}
1277
+		return $this->tickets($query_params);
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * @return EE_Base_Class|EE_Event
1283
+	 * @throws ReflectionException
1284
+	 * @throws InvalidArgumentException
1285
+	 * @throws InvalidInterfaceException
1286
+	 * @throws InvalidDataTypeException
1287
+	 * @throws EE_Error
1288
+	 */
1289
+	public function event()
1290
+	{
1291
+		return $this->get_first_related('Event');
1292
+	}
1293
+
1294
+
1295
+	/**
1296
+	 * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1297
+	 * (via the tickets).
1298
+	 *
1299
+	 * @return int
1300
+	 * @throws ReflectionException
1301
+	 * @throws InvalidArgumentException
1302
+	 * @throws InvalidInterfaceException
1303
+	 * @throws InvalidDataTypeException
1304
+	 * @throws EE_Error
1305
+	 */
1306
+	public function update_sold()
1307
+	{
1308
+		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
1309
+			array(
1310
+				array(
1311
+					'STS_ID'                 => EEM_Registration::status_id_approved,
1312
+					'REG_deleted'            => 0,
1313
+					'Ticket.Datetime.DTT_ID' => $this->ID(),
1314
+				),
1315
+			)
1316
+		);
1317
+		$this->set_sold($count_regs_for_this_datetime);
1318
+		$this->save();
1319
+		return $count_regs_for_this_datetime;
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * Adds a venue to this event
1325
+	 *
1326
+	 * @param int|EE_Venue /int $venue_id_or_obj
1327
+	 * @return EE_Base_Class|EE_Venue
1328
+	 * @throws EE_Error
1329
+	 * @throws ReflectionException
1330
+	 */
1331
+	public function add_venue($venue_id_or_obj)
1332
+	{
1333
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 * Removes a venue from the event
1339
+	 *
1340
+	 * @param EE_Venue /int $venue_id_or_obj
1341
+	 * @return EE_Base_Class|EE_Venue
1342
+	 * @throws EE_Error
1343
+	 * @throws ReflectionException
1344
+	 */
1345
+	public function remove_venue($venue_id_or_obj)
1346
+	{
1347
+		$venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1348
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1349
+	}
1350
+
1351
+
1352
+	/**
1353
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1354
+	 *
1355
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1356
+	 * @return int
1357
+	 * @throws EE_Error
1358
+	 * @throws ReflectionException
1359
+	 */
1360
+	public function venue_ID($query_params = [])
1361
+	{
1362
+		$venue = $this->get_first_related('Venue', $query_params);
1363
+		return $venue instanceof EE_Venue
1364
+			? $venue->ID()
1365
+			: 0;
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1371
+	 *
1372
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1373
+	 * @return EE_Base_Class|EE_Venue
1374
+	 * @throws EE_Error
1375
+	 * @throws ReflectionException
1376
+	 */
1377
+	public function venue($query_params = [])
1378
+	{
1379
+		return $this->get_first_related('Venue', $query_params);
1380
+	}
1381
+
1382
+
1383
+	/**
1384
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1385
+	 * @param string                   $relationName
1386
+	 * @param array                    $extra_join_model_fields_n_values
1387
+	 * @param string|null              $cache_id
1388
+	 * @return EE_Base_Class
1389
+	 * @throws EE_Error
1390
+	 * @throws ReflectionException
1391
+	 * @since   $VID:$
1392
+	 */
1393
+	public function _add_relation_to(
1394
+		$otherObjectModelObjectOrID,
1395
+		$relationName,
1396
+		$extra_join_model_fields_n_values = [],
1397
+		$cache_id = null
1398
+	) {
1399
+		// if we're adding a new relation to a ticket
1400
+		if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1401
+			/** @var EE_Ticket $ticket */
1402
+			$ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
+			$this->increaseSold($ticket->sold(), false);
1404
+			$this->increaseReserved($ticket->reserved());
1405
+			$this->save();
1406
+			$otherObjectModelObjectOrID = $ticket;
1407
+		}
1408
+		return parent::_add_relation_to(
1409
+			$otherObjectModelObjectOrID,
1410
+			$relationName,
1411
+			$extra_join_model_fields_n_values,
1412
+			$cache_id
1413
+		);
1414
+	}
1415
+
1416
+
1417
+	/**
1418
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1419
+	 * @param string                   $relationName
1420
+	 * @param array                    $where_query
1421
+	 * @return bool|EE_Base_Class|null
1422
+	 * @throws EE_Error
1423
+	 * @throws ReflectionException
1424
+	 * @since   $VID:$
1425
+	 */
1426
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1427
+	{
1428
+		if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1429
+			/** @var EE_Ticket $ticket */
1430
+			$ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1431
+			$this->decreaseSold($ticket->sold());
1432
+			$this->decreaseReserved($ticket->reserved());
1433
+			$this->save();
1434
+			$otherObjectModelObjectOrID = $ticket;
1435
+		}
1436
+		return parent::_remove_relation_to(
1437
+			$otherObjectModelObjectOrID,
1438
+			$relationName,
1439
+			$where_query
1440
+		);
1441
+	}
1442
+
1443
+
1444
+	/**
1445
+	 * Removes ALL the related things for the $relationName.
1446
+	 *
1447
+	 * @param string $relationName
1448
+	 * @param array  $where_query_params
1449
+	 * @return EE_Base_Class
1450
+	 * @throws ReflectionException
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidInterfaceException
1453
+	 * @throws InvalidDataTypeException
1454
+	 * @throws EE_Error
1455
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
1456
+	 */
1457
+	public function _remove_relations($relationName, $where_query_params = [])
1458
+	{
1459
+		if ($relationName === 'Ticket') {
1460
+			$tickets = $this->tickets();
1461
+			foreach ($tickets as $ticket) {
1462
+				$this->decreaseSold($ticket->sold());
1463
+				$this->decreaseReserved($ticket->reserved());
1464
+				$this->save();
1465
+			}
1466
+		}
1467
+		return parent::_remove_relations($relationName, $where_query_params);
1468
+	}
1469
+
1470
+
1471
+	/*******************************************************************
1472 1472
      ***********************  DEPRECATED METHODS  **********************
1473 1473
      *******************************************************************/
1474 1474
 
1475 1475
 
1476
-    /**
1477
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
1478
-     *
1479
-     * @deprecated 4.9.80.p
1480
-     * @param int $qty
1481
-     * @return boolean
1482
-     * @throws ReflectionException
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidInterfaceException
1485
-     * @throws InvalidDataTypeException
1486
-     * @throws EE_Error
1487
-     */
1488
-    public function increase_sold($qty = 1)
1489
-    {
1490
-        EE_Error::doing_it_wrong(
1491
-            __FUNCTION__,
1492
-            esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1493
-            '4.9.80.p',
1494
-            '5.0.0.p'
1495
-        );
1496
-        return $this->increaseSold($qty);
1497
-    }
1498
-
1499
-
1500
-    /**
1501
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1502
-     * to save afterwards.)
1503
-     *
1504
-     * @deprecated 4.9.80.p
1505
-     * @param int $qty
1506
-     * @return boolean
1507
-     * @throws ReflectionException
1508
-     * @throws InvalidArgumentException
1509
-     * @throws InvalidInterfaceException
1510
-     * @throws InvalidDataTypeException
1511
-     * @throws EE_Error
1512
-     */
1513
-    public function decrease_sold($qty = 1)
1514
-    {
1515
-        EE_Error::doing_it_wrong(
1516
-            __FUNCTION__,
1517
-            esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1518
-            '4.9.80.p',
1519
-            '5.0.0.p'
1520
-        );
1521
-        return $this->decreaseSold($qty);
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1527
-     *
1528
-     * @deprecated 4.9.80.p
1529
-     * @param int $qty
1530
-     * @return boolean indicating success
1531
-     * @throws ReflectionException
1532
-     * @throws InvalidArgumentException
1533
-     * @throws InvalidInterfaceException
1534
-     * @throws InvalidDataTypeException
1535
-     * @throws EE_Error
1536
-     */
1537
-    public function increase_reserved($qty = 1)
1538
-    {
1539
-        EE_Error::doing_it_wrong(
1540
-            __FUNCTION__,
1541
-            esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1542
-            '4.9.80.p',
1543
-            '5.0.0.p'
1544
-        );
1545
-        return $this->increaseReserved($qty);
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1551
-     *
1552
-     * @deprecated 4.9.80.p
1553
-     * @param int $qty
1554
-     * @return boolean
1555
-     * @throws ReflectionException
1556
-     * @throws InvalidArgumentException
1557
-     * @throws InvalidInterfaceException
1558
-     * @throws InvalidDataTypeException
1559
-     * @throws EE_Error
1560
-     */
1561
-    public function decrease_reserved($qty = 1)
1562
-    {
1563
-        EE_Error::doing_it_wrong(
1564
-            __FUNCTION__,
1565
-            esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1566
-            '4.9.80.p',
1567
-            '5.0.0.p'
1568
-        );
1569
-        return $this->decreaseReserved($qty);
1570
-    }
1476
+	/**
1477
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
1478
+	 *
1479
+	 * @deprecated 4.9.80.p
1480
+	 * @param int $qty
1481
+	 * @return boolean
1482
+	 * @throws ReflectionException
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidInterfaceException
1485
+	 * @throws InvalidDataTypeException
1486
+	 * @throws EE_Error
1487
+	 */
1488
+	public function increase_sold($qty = 1)
1489
+	{
1490
+		EE_Error::doing_it_wrong(
1491
+			__FUNCTION__,
1492
+			esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1493
+			'4.9.80.p',
1494
+			'5.0.0.p'
1495
+		);
1496
+		return $this->increaseSold($qty);
1497
+	}
1498
+
1499
+
1500
+	/**
1501
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1502
+	 * to save afterwards.)
1503
+	 *
1504
+	 * @deprecated 4.9.80.p
1505
+	 * @param int $qty
1506
+	 * @return boolean
1507
+	 * @throws ReflectionException
1508
+	 * @throws InvalidArgumentException
1509
+	 * @throws InvalidInterfaceException
1510
+	 * @throws InvalidDataTypeException
1511
+	 * @throws EE_Error
1512
+	 */
1513
+	public function decrease_sold($qty = 1)
1514
+	{
1515
+		EE_Error::doing_it_wrong(
1516
+			__FUNCTION__,
1517
+			esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1518
+			'4.9.80.p',
1519
+			'5.0.0.p'
1520
+		);
1521
+		return $this->decreaseSold($qty);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1527
+	 *
1528
+	 * @deprecated 4.9.80.p
1529
+	 * @param int $qty
1530
+	 * @return boolean indicating success
1531
+	 * @throws ReflectionException
1532
+	 * @throws InvalidArgumentException
1533
+	 * @throws InvalidInterfaceException
1534
+	 * @throws InvalidDataTypeException
1535
+	 * @throws EE_Error
1536
+	 */
1537
+	public function increase_reserved($qty = 1)
1538
+	{
1539
+		EE_Error::doing_it_wrong(
1540
+			__FUNCTION__,
1541
+			esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1542
+			'4.9.80.p',
1543
+			'5.0.0.p'
1544
+		);
1545
+		return $this->increaseReserved($qty);
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1551
+	 *
1552
+	 * @deprecated 4.9.80.p
1553
+	 * @param int $qty
1554
+	 * @return boolean
1555
+	 * @throws ReflectionException
1556
+	 * @throws InvalidArgumentException
1557
+	 * @throws InvalidInterfaceException
1558
+	 * @throws InvalidDataTypeException
1559
+	 * @throws EE_Error
1560
+	 */
1561
+	public function decrease_reserved($qty = 1)
1562
+	{
1563
+		EE_Error::doing_it_wrong(
1564
+			__FUNCTION__,
1565
+			esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1566
+			'4.9.80.p',
1567
+			'5.0.0.p'
1568
+		);
1569
+		return $this->decreaseReserved($qty);
1570
+	}
1571 1571
 }
Please login to merge, or discard this patch.