Completed
Branch models-cleanup/main (de94a1)
by
unknown
86:45 queued 77:08
created
core/db_classes/EE_CPT_Base.class.php 3 patches
Doc Comments   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@  discard block
 block discarded – undo
35 35
      *
36 36
      * @param string      $category_name
37 37
      * @param string|null $category_description    optional
38
-     * @param int|null    $parent_term_taxonomy_id optional
38
+     * @param integer    $parent_term_taxonomy_id optional
39 39
      * @return EE_Term_Taxonomy
40 40
      * @throws EE_Error
41 41
      * @throws ReflectionException
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
      *
171 171
      * @link   http://codex.wordpress.org/Function_Reference/get_the_post_thumbnail
172 172
      * @access protected
173
-     * @param string|array $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
173
+     * @param string $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
174 174
      *                           representing width and height in pixels (i.e. array(32,32) ).
175 175
      * @param string|array $attr Optional. Query string or array of attributes.
176 176
      * @return string HTML image element
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
      * This is a method for restoring this_obj using details from the given $revision_id
216 216
      *
217 217
      * @param int   $revision_id       ID of the revision we're getting data from
218
-     * @param array $related_obj_names if included this will be used to restore for related obj
218
+     * @param string[] $related_obj_names if included this will be used to restore for related obj
219 219
      *                                 if not included then we just do restore on the meta.
220 220
      *                                 We will accept an array of related_obj_names for restoration here.
221 221
      * @param array $where_query       You can optionally include an array of key=>value pairs
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
      *
281 281
      * @param string $meta_key
282 282
      * @param bool   $single
283
-     * @return mixed
283
+     * @return null|string
284 284
      * @throws EE_Error
285 285
      */
286 286
     public function get_post_meta(string $meta_key = '', bool $single = false)
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
      * Wrapper for add_post_meta, http://codex.wordpress.org/Function_Reference/add_post_meta
317 317
      *
318 318
      * @param string $meta_key
319
-     * @param mixed $meta_value
319
+     * @param string $meta_value
320 320
      * @param bool  $unique     If postmeta for this $meta_key already exists,
321 321
      *                          whether to add an additional item or not
322 322
      * @return boolean          Boolean true, except if the $unique argument was set to true
Please login to merge, or discard this patch.
Indentation   +482 added lines, -482 removed lines patch added patch discarded remove patch
@@ -12,486 +12,486 @@
 block discarded – undo
12 12
 abstract class EE_CPT_Base extends EE_Soft_Delete_Base_Class
13 13
 {
14 14
 
15
-    /**
16
-     * This is a property for holding cached feature images on CPT objects.
17
-     * Cache's are set on the first "feature_image()" method call.
18
-     * Each key in the array corresponds to the requested size.
19
-     *
20
-     * @var array
21
-     */
22
-    protected $_feature_image = [];
23
-
24
-    /**
25
-     * @var WP_Post the WP_Post that corresponds with this CPT model object
26
-     */
27
-    protected $_wp_post;
28
-
29
-
30
-    abstract public function wp_user();
31
-
32
-
33
-    /**
34
-     * Adds to the specified event category. If it category doesn't exist, creates it.
35
-     *
36
-     * @param string      $category_name
37
-     * @param string|null $category_description    optional
38
-     * @param int|null    $parent_term_taxonomy_id optional
39
-     * @return EE_Term_Taxonomy
40
-     * @throws EE_Error
41
-     * @throws ReflectionException
42
-     */
43
-    public function add_event_category(
44
-        string $category_name,
45
-        string $category_description = '',
46
-        int $parent_term_taxonomy_id = 0
47
-    ): EE_Term_Taxonomy {
48
-        return $this->get_model()->add_event_category(
49
-            $this,
50
-            $category_name,
51
-            $category_description,
52
-            $parent_term_taxonomy_id
53
-        );
54
-    }
55
-
56
-
57
-    /**
58
-     * Removes the event category by specified name from being related ot this event
59
-     *
60
-     * @param string $category_name
61
-     * @return bool
62
-     * @throws EE_Error
63
-     * @throws ReflectionException
64
-     */
65
-    public function remove_event_category(string $category_name): bool
66
-    {
67
-        return $this->get_model()->remove_event_category($this, $category_name);
68
-    }
69
-
70
-
71
-    /**
72
-     * Removes the relation to the specified term taxonomy, and maintains the
73
-     * data integrity of the term taxonomy provided
74
-     *
75
-     * @param EE_Term_Taxonomy $term_taxonomy
76
-     * @return EE_Base_Class the relation was removed from
77
-     * @throws EE_Error
78
-     * @throws ReflectionException
79
-     */
80
-    public function remove_relation_to_term_taxonomy(EE_Term_Taxonomy $term_taxonomy): ?EE_Base_Class
81
-    {
82
-        if (! $term_taxonomy) {
83
-            EE_Error::add_error(
84
-                sprintf(
85
-                    esc_html__(
86
-                        "No Term_Taxonomy provided which to remove from model object of type %s and id %d",
87
-                        "event_espresso"
88
-                    ),
89
-                    get_class($this),
90
-                    $this->ID()
91
-                ),
92
-                __FILE__,
93
-                __FUNCTION__,
94
-                __LINE__
95
-            );
96
-            return null;
97
-        }
98
-        $term_taxonomy->set_count($term_taxonomy->count() - 1);
99
-        $term_taxonomy->save();
100
-        return $this->_remove_relation_to($term_taxonomy, 'Term_Taxonomy');
101
-    }
102
-
103
-
104
-    /**
105
-     * The main purpose of this method is to return the post type for the model object
106
-     *
107
-     * @return string
108
-     * @throws EE_Error
109
-     * @throws ReflectionException
110
-     */
111
-    public function post_type(): string
112
-    {
113
-        return $this->get_model()->post_type();
114
-    }
115
-
116
-
117
-    /**
118
-     * The main purpose of this method is to return the parent for the model object
119
-     *
120
-     * @return int
121
-     * @throws EE_Error
122
-     */
123
-    public function parent(): int
124
-    {
125
-        return $this->get('parent');
126
-    }
127
-
128
-
129
-    /**
130
-     * return the _status property
131
-     *
132
-     * @return string
133
-     * @throws EE_Error
134
-     */
135
-    public function status(): string
136
-    {
137
-        return $this->get('status');
138
-    }
139
-
140
-
141
-    /**
142
-     * @param string $status
143
-     * @throws EE_Error
144
-     * @throws ReflectionException
145
-     */
146
-    public function set_status(string $status)
147
-    {
148
-        $this->set('status', $status);
149
-    }
150
-
151
-
152
-    /**
153
-     * See _get_feature_image. Returns the HTML to display a featured image
154
-     *
155
-     * @param string       $size
156
-     * @param string|array $attr
157
-     * @return string of html
158
-     * @throws EE_Error
159
-     * @throws ReflectionException
160
-     */
161
-    public function feature_image(string $size = 'thumbnail', $attr = ''): string
162
-    {
163
-        return $this->_get_feature_image($size, $attr);
164
-    }
165
-
166
-
167
-    /**
168
-     * This calls the equivalent model method for retrieving the feature image
169
-     * which in turn is a wrapper for WordPress' get_the_post_thumbnail() function.
170
-     *
171
-     * @link   http://codex.wordpress.org/Function_Reference/get_the_post_thumbnail
172
-     * @access protected
173
-     * @param string|array $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
174
-     *                           representing width and height in pixels (i.e. array(32,32) ).
175
-     * @param string|array $attr Optional. Query string or array of attributes.
176
-     * @return string HTML image element
177
-     * @throws EE_Error
178
-     * @throws ReflectionException
179
-     */
180
-    protected function _get_feature_image($size, $attr): string
181
-    {
182
-        // first let's see if we already have the _feature_image property set
183
-        // AND if it has a cached element on it FOR the given size
184
-        $attr_key                           = is_array($attr)
185
-            ? implode('_', $attr)
186
-            : $attr;
187
-        $cache_key                          = is_array($size)
188
-            ? implode('_', $size) . $attr_key
189
-            : $size . $attr_key;
190
-        $this->_feature_image[ $cache_key ] = $this->_feature_image[ $cache_key ]
191
-                                              ?? $this->get_model()->get_feature_image($this->ID(), $size, $attr);
192
-        return $this->_feature_image[ $cache_key ];
193
-    }
194
-
195
-
196
-    /**
197
-     * This uses the wp "wp_get_attachment_image_src()" function to return the feature image for the current class
198
-     * using the given size params.
199
-     *
200
-     * @param string|array $size  can either be a string: 'thumbnail', 'medium', 'large', 'full' OR 2-item array
201
-     *                            representing width and height in pixels eg. array(32,32).
202
-     * @return string|boolean          the url of the image or false if not found
203
-     * @throws EE_Error
204
-     */
205
-    public function feature_image_url($size = 'thumbnail')
206
-    {
207
-        $attachment = wp_get_attachment_image_src(get_post_thumbnail_id($this->ID()), $size);
208
-        return ! empty($attachment)
209
-            ? $attachment[0]
210
-            : false;
211
-    }
212
-
213
-
214
-    /**
215
-     * This is a method for restoring this_obj using details from the given $revision_id
216
-     *
217
-     * @param int   $revision_id       ID of the revision we're getting data from
218
-     * @param array $related_obj_names if included this will be used to restore for related obj
219
-     *                                 if not included then we just do restore on the meta.
220
-     *                                 We will accept an array of related_obj_names for restoration here.
221
-     * @param array $where_query       You can optionally include an array of key=>value pairs
222
-     *                                 that allow you to further constrict the relation to being added.
223
-     *                                 However, keep in mind that the columns (keys) given
224
-     *                                 must match a column on the JOIN table and currently
225
-     *                                 only the HABTM models accept these additional conditions.
226
-     *                                 Also remember that if an exact match isn't found for these extra cols/val pairs,
227
-     *                                 then a NEW row is created in the join table.
228
-     *                                 This array is INDEXED by RELATED OBJ NAME (so it corresponds with the obj_names
229
-     *                                 sent);
230
-     * @return void
231
-     * @throws EE_Error
232
-     * @throws ReflectionException
233
-     */
234
-    public function restore_revision(int $revision_id, array $related_obj_names = [], array $where_query = [])
235
-    {
236
-        // get revision object
237
-        $revision_obj = $this->get_model()->get_one_by_ID($revision_id);
238
-        if ($revision_obj instanceof EE_CPT_Base) {
239
-            // no related_obj_name so we assume we're saving a revision on this object.
240
-            if (empty($related_obj_names)) {
241
-                $fields = $this->get_model()->get_meta_table_fields();
242
-                foreach ($fields as $field) {
243
-                    $this->set($field, $revision_obj->get($field));
244
-                }
245
-                $this->save();
246
-            }
247
-            foreach ($related_obj_names as $related_name) {
248
-                // related_obj_name so we're saving a revision on an object related to this object
249
-                // do we have $where_query params for this related object?  If we do then we include that.
250
-                $cols_n_values         = $where_query[ $related_name ] ?? [];
251
-                $where_params          = ! empty($cols_n_values)
252
-                    ? [$cols_n_values]
253
-                    : [];
254
-                $related_objs          = $this->get_many_related($related_name, $where_params);
255
-                $revision_related_objs = $revision_obj->get_many_related($related_name, $where_params);
256
-                // load helper
257
-                // remove related objs from this object that are not in revision
258
-                // array_diff *should* work cause I think objects are indexed by ID?
259
-                $related_to_remove = EEH_Array::object_array_diff($related_objs, $revision_related_objs);
260
-                foreach ($related_to_remove as $rr) {
261
-                    $this->_remove_relation_to($rr, $related_name, $cols_n_values);
262
-                }
263
-                // add all related objs attached to revision to this object
264
-                foreach ($revision_related_objs as $r_obj) {
265
-                    $this->_add_relation_to($r_obj, $related_name, $cols_n_values);
266
-                }
267
-            }
268
-        }
269
-    }
270
-
271
-
272
-    /**
273
-     * Wrapper for get_post_meta, http://codex.wordpress.org/Function_Reference/get_post_meta
274
-     * If only $id is set:
275
-     *  it will return all meta values in an associative array.
276
-     * If $single is set to false, or left blank:
277
-     *  the function returns an array containing all values of the specified key.
278
-     * If $single is set to true:
279
-     *  the function returns the first value of the specified key (not in an array)
280
-     *
281
-     * @param string $meta_key
282
-     * @param bool   $single
283
-     * @return mixed
284
-     * @throws EE_Error
285
-     */
286
-    public function get_post_meta(string $meta_key = '', bool $single = false)
287
-    {
288
-        return get_post_meta($this->ID(), $meta_key, $single);
289
-    }
290
-
291
-
292
-    /**
293
-     * Wrapper for update_post_meta, http://codex.wordpress.org/Function_Reference/update_post_meta
294
-     * Returns meta_id if the meta doesn't exist,
295
-     * otherwise returns true on success and false on failure.
296
-     * NOTE: If the meta_value passed to this function is the same
297
-     * as the value that is already in the database, this function returns false.
298
-     *
299
-     * @param string $meta_key
300
-     * @param mixed  $meta_value
301
-     * @param mixed  $prev_value
302
-     * @return bool|int
303
-     * @throws EE_Error
304
-     * @throws ReflectionException
305
-     */
306
-    public function update_post_meta(string $meta_key, $meta_value, $prev_value = null)
307
-    {
308
-        if (! $this->ID()) {
309
-            $this->save();
310
-        }
311
-        return update_post_meta($this->ID(), $meta_key, $meta_value, $prev_value);
312
-    }
313
-
314
-
315
-    /**
316
-     * Wrapper for add_post_meta, http://codex.wordpress.org/Function_Reference/add_post_meta
317
-     *
318
-     * @param string $meta_key
319
-     * @param mixed $meta_value
320
-     * @param bool  $unique     If postmeta for this $meta_key already exists,
321
-     *                          whether to add an additional item or not
322
-     * @return boolean          Boolean true, except if the $unique argument was set to true
323
-     *                          and a custom field with the given key already exists,
324
-     *                          in which case false is returned.
325
-     * @throws EE_Error
326
-     * @throws ReflectionException
327
-     */
328
-    public function add_post_meta(string $meta_key, $meta_value, bool $unique = false): bool
329
-    {
330
-        if ($this->ID()) {
331
-            $this->save();
332
-        }
333
-        return add_post_meta($this->ID(), $meta_key, $meta_value, $unique);
334
-    }
335
-
336
-
337
-    /**
338
-     * Wrapper for delete_post_meta, http://codex.wordpress.org/Function_Reference/delete_post_meta
339
-     *
340
-     * @param string $meta_key
341
-     * @param mixed $meta_value
342
-     * @return boolean False for failure. True for success.
343
-     * @throws EE_Error
344
-     */
345
-    public function delete_post_meta(string $meta_key, $meta_value = ''): bool
346
-    {
347
-        if (! $this->ID()) {
348
-            // there is obviously no postmeta for this if it's not saved
349
-            // so let's just report this as a success
350
-            return true;
351
-        }
352
-        return delete_post_meta($this->ID(), $meta_key, $meta_value);
353
-    }
354
-
355
-
356
-    /**
357
-     * Gets the URL for viewing this event on the front-end
358
-     *
359
-     * @return string
360
-     * @throws EE_Error
361
-     */
362
-    public function get_permalink(): string
363
-    {
364
-        return get_permalink($this->ID());
365
-    }
366
-
367
-
368
-    /**
369
-     * Gets all the term-taxonomies for this CPT
370
-     *
371
-     * @param array $query_params
372
-     * @return EE_Term_Taxonomy[]
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     */
376
-    public function term_taxonomies(array $query_params = []): array
377
-    {
378
-        return $this->get_many_related('Term_Taxonomy', $query_params);
379
-    }
380
-
381
-
382
-    /**
383
-     * @return string[]
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public function get_custom_post_statuses(): array
388
-    {
389
-        return $this->get_model()->get_custom_post_statuses();
390
-    }
391
-
392
-
393
-    /**
394
-     * @return string[]
395
-     * @throws EE_Error
396
-     * @throws ReflectionException
397
-     */
398
-    public function get_all_post_statuses(): array
399
-    {
400
-        return $this->get_model()->get_status_array();
401
-    }
402
-
403
-
404
-    /**
405
-     * When fetching a new value for a post field that uses the global $post for rendering,
406
-     * set the global $post temporarily to be this model object; and afterwards restore it
407
-     *
408
-     * @param string      $field_name
409
-     * @param bool        $pretty
410
-     * @param string|null $extra_cache_ref
411
-     * @return mixed
412
-     * @throws EE_Error
413
-     * @throws ReflectionException
414
-     */
415
-    protected function _get_fresh_property(string $field_name, bool $pretty = false, string $extra_cache_ref = '')
416
-    {
417
-        global $post;
418
-
419
-        if (
420
-            $pretty
421
-            && (
422
-                ! ($post instanceof WP_Post && $post->ID)
423
-                || absint($post->ID) !== $this->ID()
424
-            )
425
-            && $this->get_model()->field_settings_for($field_name) instanceof EE_Post_Content_Field
426
-        ) {
427
-            $old_post     = $post;
428
-            $post         = $this->wp_post();
429
-            $return_value = parent::_get_fresh_property($field_name, $pretty, $extra_cache_ref);
430
-            $post         = $old_post;
431
-        } else {
432
-            $return_value = parent::_get_fresh_property($field_name, $pretty, $extra_cache_ref);
433
-        }
434
-        return $return_value;
435
-    }
436
-
437
-
438
-    /**
439
-     * Returns the WP post associated with this CPT model object.
440
-     * If this CPT is saved, fetches it from the DB.
441
-     * Otherwise, create an unsaved WP_POst object. Caches the post internally.
442
-     *
443
-     * @return WP_Post
444
-     * @throws EE_Error
445
-     * @throws ReflectionException
446
-     */
447
-    public function wp_post(): WP_Post
448
-    {
449
-        global $wpdb;
450
-        if (! $this->_wp_post instanceof WP_Post) {
451
-            if ($this->ID()) {
452
-                $this->_wp_post = get_post($this->ID());
453
-            } else {
454
-                $simulated_db_result = new stdClass();
455
-                $field_settings      = $this->get_model()->field_settings(true);
456
-                foreach ($field_settings as $field_name => $field_obj) {
457
-                    if (
458
-                        $this->get_model()->get_table_obj_by_alias($field_obj->get_table_alias())
459
-                             ->get_table_name() === $wpdb->posts
460
-                    ) {
461
-                        $column = $field_obj->get_table_column();
462
-
463
-                        if ($field_obj instanceof EE_Datetime_Field) {
464
-                            $value_on_model_obj = $this->get_DateTime_object($field_name);
465
-                        } elseif ($field_obj->is_db_only_field()) {
466
-                            $value_on_model_obj = $field_obj->get_default_value();
467
-                        } else {
468
-                            $value_on_model_obj = $this->get_raw($field_name);
469
-                        }
470
-                        $simulated_db_result->{$column} = $field_obj->prepare_for_use_in_db($value_on_model_obj);
471
-                    }
472
-                }
473
-                $this->_wp_post = new WP_Post($simulated_db_result);
474
-            }
475
-            // and let's make retrieving the EE CPT object easy too
476
-            $classname = get_class($this);
477
-            if (! isset($this->_wp_post->{$classname})) {
478
-                $this->_wp_post->{$classname} = $this;
479
-            }
480
-        }
481
-        return $this->_wp_post;
482
-    }
483
-
484
-
485
-    /**
486
-     * Don't serialize the WP Post. That's just duplicate data and we want to avoid recursion
487
-     *
488
-     * @return array
489
-     * @throws EE_Error
490
-     * @throws ReflectionException
491
-     */
492
-    public function __sleep()
493
-    {
494
-        $properties_to_serialize = parent::__sleep();
495
-        return array_diff($properties_to_serialize, ['_wp_post']);
496
-    }
15
+	/**
16
+	 * This is a property for holding cached feature images on CPT objects.
17
+	 * Cache's are set on the first "feature_image()" method call.
18
+	 * Each key in the array corresponds to the requested size.
19
+	 *
20
+	 * @var array
21
+	 */
22
+	protected $_feature_image = [];
23
+
24
+	/**
25
+	 * @var WP_Post the WP_Post that corresponds with this CPT model object
26
+	 */
27
+	protected $_wp_post;
28
+
29
+
30
+	abstract public function wp_user();
31
+
32
+
33
+	/**
34
+	 * Adds to the specified event category. If it category doesn't exist, creates it.
35
+	 *
36
+	 * @param string      $category_name
37
+	 * @param string|null $category_description    optional
38
+	 * @param int|null    $parent_term_taxonomy_id optional
39
+	 * @return EE_Term_Taxonomy
40
+	 * @throws EE_Error
41
+	 * @throws ReflectionException
42
+	 */
43
+	public function add_event_category(
44
+		string $category_name,
45
+		string $category_description = '',
46
+		int $parent_term_taxonomy_id = 0
47
+	): EE_Term_Taxonomy {
48
+		return $this->get_model()->add_event_category(
49
+			$this,
50
+			$category_name,
51
+			$category_description,
52
+			$parent_term_taxonomy_id
53
+		);
54
+	}
55
+
56
+
57
+	/**
58
+	 * Removes the event category by specified name from being related ot this event
59
+	 *
60
+	 * @param string $category_name
61
+	 * @return bool
62
+	 * @throws EE_Error
63
+	 * @throws ReflectionException
64
+	 */
65
+	public function remove_event_category(string $category_name): bool
66
+	{
67
+		return $this->get_model()->remove_event_category($this, $category_name);
68
+	}
69
+
70
+
71
+	/**
72
+	 * Removes the relation to the specified term taxonomy, and maintains the
73
+	 * data integrity of the term taxonomy provided
74
+	 *
75
+	 * @param EE_Term_Taxonomy $term_taxonomy
76
+	 * @return EE_Base_Class the relation was removed from
77
+	 * @throws EE_Error
78
+	 * @throws ReflectionException
79
+	 */
80
+	public function remove_relation_to_term_taxonomy(EE_Term_Taxonomy $term_taxonomy): ?EE_Base_Class
81
+	{
82
+		if (! $term_taxonomy) {
83
+			EE_Error::add_error(
84
+				sprintf(
85
+					esc_html__(
86
+						"No Term_Taxonomy provided which to remove from model object of type %s and id %d",
87
+						"event_espresso"
88
+					),
89
+					get_class($this),
90
+					$this->ID()
91
+				),
92
+				__FILE__,
93
+				__FUNCTION__,
94
+				__LINE__
95
+			);
96
+			return null;
97
+		}
98
+		$term_taxonomy->set_count($term_taxonomy->count() - 1);
99
+		$term_taxonomy->save();
100
+		return $this->_remove_relation_to($term_taxonomy, 'Term_Taxonomy');
101
+	}
102
+
103
+
104
+	/**
105
+	 * The main purpose of this method is to return the post type for the model object
106
+	 *
107
+	 * @return string
108
+	 * @throws EE_Error
109
+	 * @throws ReflectionException
110
+	 */
111
+	public function post_type(): string
112
+	{
113
+		return $this->get_model()->post_type();
114
+	}
115
+
116
+
117
+	/**
118
+	 * The main purpose of this method is to return the parent for the model object
119
+	 *
120
+	 * @return int
121
+	 * @throws EE_Error
122
+	 */
123
+	public function parent(): int
124
+	{
125
+		return $this->get('parent');
126
+	}
127
+
128
+
129
+	/**
130
+	 * return the _status property
131
+	 *
132
+	 * @return string
133
+	 * @throws EE_Error
134
+	 */
135
+	public function status(): string
136
+	{
137
+		return $this->get('status');
138
+	}
139
+
140
+
141
+	/**
142
+	 * @param string $status
143
+	 * @throws EE_Error
144
+	 * @throws ReflectionException
145
+	 */
146
+	public function set_status(string $status)
147
+	{
148
+		$this->set('status', $status);
149
+	}
150
+
151
+
152
+	/**
153
+	 * See _get_feature_image. Returns the HTML to display a featured image
154
+	 *
155
+	 * @param string       $size
156
+	 * @param string|array $attr
157
+	 * @return string of html
158
+	 * @throws EE_Error
159
+	 * @throws ReflectionException
160
+	 */
161
+	public function feature_image(string $size = 'thumbnail', $attr = ''): string
162
+	{
163
+		return $this->_get_feature_image($size, $attr);
164
+	}
165
+
166
+
167
+	/**
168
+	 * This calls the equivalent model method for retrieving the feature image
169
+	 * which in turn is a wrapper for WordPress' get_the_post_thumbnail() function.
170
+	 *
171
+	 * @link   http://codex.wordpress.org/Function_Reference/get_the_post_thumbnail
172
+	 * @access protected
173
+	 * @param string|array $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
174
+	 *                           representing width and height in pixels (i.e. array(32,32) ).
175
+	 * @param string|array $attr Optional. Query string or array of attributes.
176
+	 * @return string HTML image element
177
+	 * @throws EE_Error
178
+	 * @throws ReflectionException
179
+	 */
180
+	protected function _get_feature_image($size, $attr): string
181
+	{
182
+		// first let's see if we already have the _feature_image property set
183
+		// AND if it has a cached element on it FOR the given size
184
+		$attr_key                           = is_array($attr)
185
+			? implode('_', $attr)
186
+			: $attr;
187
+		$cache_key                          = is_array($size)
188
+			? implode('_', $size) . $attr_key
189
+			: $size . $attr_key;
190
+		$this->_feature_image[ $cache_key ] = $this->_feature_image[ $cache_key ]
191
+											  ?? $this->get_model()->get_feature_image($this->ID(), $size, $attr);
192
+		return $this->_feature_image[ $cache_key ];
193
+	}
194
+
195
+
196
+	/**
197
+	 * This uses the wp "wp_get_attachment_image_src()" function to return the feature image for the current class
198
+	 * using the given size params.
199
+	 *
200
+	 * @param string|array $size  can either be a string: 'thumbnail', 'medium', 'large', 'full' OR 2-item array
201
+	 *                            representing width and height in pixels eg. array(32,32).
202
+	 * @return string|boolean          the url of the image or false if not found
203
+	 * @throws EE_Error
204
+	 */
205
+	public function feature_image_url($size = 'thumbnail')
206
+	{
207
+		$attachment = wp_get_attachment_image_src(get_post_thumbnail_id($this->ID()), $size);
208
+		return ! empty($attachment)
209
+			? $attachment[0]
210
+			: false;
211
+	}
212
+
213
+
214
+	/**
215
+	 * This is a method for restoring this_obj using details from the given $revision_id
216
+	 *
217
+	 * @param int   $revision_id       ID of the revision we're getting data from
218
+	 * @param array $related_obj_names if included this will be used to restore for related obj
219
+	 *                                 if not included then we just do restore on the meta.
220
+	 *                                 We will accept an array of related_obj_names for restoration here.
221
+	 * @param array $where_query       You can optionally include an array of key=>value pairs
222
+	 *                                 that allow you to further constrict the relation to being added.
223
+	 *                                 However, keep in mind that the columns (keys) given
224
+	 *                                 must match a column on the JOIN table and currently
225
+	 *                                 only the HABTM models accept these additional conditions.
226
+	 *                                 Also remember that if an exact match isn't found for these extra cols/val pairs,
227
+	 *                                 then a NEW row is created in the join table.
228
+	 *                                 This array is INDEXED by RELATED OBJ NAME (so it corresponds with the obj_names
229
+	 *                                 sent);
230
+	 * @return void
231
+	 * @throws EE_Error
232
+	 * @throws ReflectionException
233
+	 */
234
+	public function restore_revision(int $revision_id, array $related_obj_names = [], array $where_query = [])
235
+	{
236
+		// get revision object
237
+		$revision_obj = $this->get_model()->get_one_by_ID($revision_id);
238
+		if ($revision_obj instanceof EE_CPT_Base) {
239
+			// no related_obj_name so we assume we're saving a revision on this object.
240
+			if (empty($related_obj_names)) {
241
+				$fields = $this->get_model()->get_meta_table_fields();
242
+				foreach ($fields as $field) {
243
+					$this->set($field, $revision_obj->get($field));
244
+				}
245
+				$this->save();
246
+			}
247
+			foreach ($related_obj_names as $related_name) {
248
+				// related_obj_name so we're saving a revision on an object related to this object
249
+				// do we have $where_query params for this related object?  If we do then we include that.
250
+				$cols_n_values         = $where_query[ $related_name ] ?? [];
251
+				$where_params          = ! empty($cols_n_values)
252
+					? [$cols_n_values]
253
+					: [];
254
+				$related_objs          = $this->get_many_related($related_name, $where_params);
255
+				$revision_related_objs = $revision_obj->get_many_related($related_name, $where_params);
256
+				// load helper
257
+				// remove related objs from this object that are not in revision
258
+				// array_diff *should* work cause I think objects are indexed by ID?
259
+				$related_to_remove = EEH_Array::object_array_diff($related_objs, $revision_related_objs);
260
+				foreach ($related_to_remove as $rr) {
261
+					$this->_remove_relation_to($rr, $related_name, $cols_n_values);
262
+				}
263
+				// add all related objs attached to revision to this object
264
+				foreach ($revision_related_objs as $r_obj) {
265
+					$this->_add_relation_to($r_obj, $related_name, $cols_n_values);
266
+				}
267
+			}
268
+		}
269
+	}
270
+
271
+
272
+	/**
273
+	 * Wrapper for get_post_meta, http://codex.wordpress.org/Function_Reference/get_post_meta
274
+	 * If only $id is set:
275
+	 *  it will return all meta values in an associative array.
276
+	 * If $single is set to false, or left blank:
277
+	 *  the function returns an array containing all values of the specified key.
278
+	 * If $single is set to true:
279
+	 *  the function returns the first value of the specified key (not in an array)
280
+	 *
281
+	 * @param string $meta_key
282
+	 * @param bool   $single
283
+	 * @return mixed
284
+	 * @throws EE_Error
285
+	 */
286
+	public function get_post_meta(string $meta_key = '', bool $single = false)
287
+	{
288
+		return get_post_meta($this->ID(), $meta_key, $single);
289
+	}
290
+
291
+
292
+	/**
293
+	 * Wrapper for update_post_meta, http://codex.wordpress.org/Function_Reference/update_post_meta
294
+	 * Returns meta_id if the meta doesn't exist,
295
+	 * otherwise returns true on success and false on failure.
296
+	 * NOTE: If the meta_value passed to this function is the same
297
+	 * as the value that is already in the database, this function returns false.
298
+	 *
299
+	 * @param string $meta_key
300
+	 * @param mixed  $meta_value
301
+	 * @param mixed  $prev_value
302
+	 * @return bool|int
303
+	 * @throws EE_Error
304
+	 * @throws ReflectionException
305
+	 */
306
+	public function update_post_meta(string $meta_key, $meta_value, $prev_value = null)
307
+	{
308
+		if (! $this->ID()) {
309
+			$this->save();
310
+		}
311
+		return update_post_meta($this->ID(), $meta_key, $meta_value, $prev_value);
312
+	}
313
+
314
+
315
+	/**
316
+	 * Wrapper for add_post_meta, http://codex.wordpress.org/Function_Reference/add_post_meta
317
+	 *
318
+	 * @param string $meta_key
319
+	 * @param mixed $meta_value
320
+	 * @param bool  $unique     If postmeta for this $meta_key already exists,
321
+	 *                          whether to add an additional item or not
322
+	 * @return boolean          Boolean true, except if the $unique argument was set to true
323
+	 *                          and a custom field with the given key already exists,
324
+	 *                          in which case false is returned.
325
+	 * @throws EE_Error
326
+	 * @throws ReflectionException
327
+	 */
328
+	public function add_post_meta(string $meta_key, $meta_value, bool $unique = false): bool
329
+	{
330
+		if ($this->ID()) {
331
+			$this->save();
332
+		}
333
+		return add_post_meta($this->ID(), $meta_key, $meta_value, $unique);
334
+	}
335
+
336
+
337
+	/**
338
+	 * Wrapper for delete_post_meta, http://codex.wordpress.org/Function_Reference/delete_post_meta
339
+	 *
340
+	 * @param string $meta_key
341
+	 * @param mixed $meta_value
342
+	 * @return boolean False for failure. True for success.
343
+	 * @throws EE_Error
344
+	 */
345
+	public function delete_post_meta(string $meta_key, $meta_value = ''): bool
346
+	{
347
+		if (! $this->ID()) {
348
+			// there is obviously no postmeta for this if it's not saved
349
+			// so let's just report this as a success
350
+			return true;
351
+		}
352
+		return delete_post_meta($this->ID(), $meta_key, $meta_value);
353
+	}
354
+
355
+
356
+	/**
357
+	 * Gets the URL for viewing this event on the front-end
358
+	 *
359
+	 * @return string
360
+	 * @throws EE_Error
361
+	 */
362
+	public function get_permalink(): string
363
+	{
364
+		return get_permalink($this->ID());
365
+	}
366
+
367
+
368
+	/**
369
+	 * Gets all the term-taxonomies for this CPT
370
+	 *
371
+	 * @param array $query_params
372
+	 * @return EE_Term_Taxonomy[]
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 */
376
+	public function term_taxonomies(array $query_params = []): array
377
+	{
378
+		return $this->get_many_related('Term_Taxonomy', $query_params);
379
+	}
380
+
381
+
382
+	/**
383
+	 * @return string[]
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public function get_custom_post_statuses(): array
388
+	{
389
+		return $this->get_model()->get_custom_post_statuses();
390
+	}
391
+
392
+
393
+	/**
394
+	 * @return string[]
395
+	 * @throws EE_Error
396
+	 * @throws ReflectionException
397
+	 */
398
+	public function get_all_post_statuses(): array
399
+	{
400
+		return $this->get_model()->get_status_array();
401
+	}
402
+
403
+
404
+	/**
405
+	 * When fetching a new value for a post field that uses the global $post for rendering,
406
+	 * set the global $post temporarily to be this model object; and afterwards restore it
407
+	 *
408
+	 * @param string      $field_name
409
+	 * @param bool        $pretty
410
+	 * @param string|null $extra_cache_ref
411
+	 * @return mixed
412
+	 * @throws EE_Error
413
+	 * @throws ReflectionException
414
+	 */
415
+	protected function _get_fresh_property(string $field_name, bool $pretty = false, string $extra_cache_ref = '')
416
+	{
417
+		global $post;
418
+
419
+		if (
420
+			$pretty
421
+			&& (
422
+				! ($post instanceof WP_Post && $post->ID)
423
+				|| absint($post->ID) !== $this->ID()
424
+			)
425
+			&& $this->get_model()->field_settings_for($field_name) instanceof EE_Post_Content_Field
426
+		) {
427
+			$old_post     = $post;
428
+			$post         = $this->wp_post();
429
+			$return_value = parent::_get_fresh_property($field_name, $pretty, $extra_cache_ref);
430
+			$post         = $old_post;
431
+		} else {
432
+			$return_value = parent::_get_fresh_property($field_name, $pretty, $extra_cache_ref);
433
+		}
434
+		return $return_value;
435
+	}
436
+
437
+
438
+	/**
439
+	 * Returns the WP post associated with this CPT model object.
440
+	 * If this CPT is saved, fetches it from the DB.
441
+	 * Otherwise, create an unsaved WP_POst object. Caches the post internally.
442
+	 *
443
+	 * @return WP_Post
444
+	 * @throws EE_Error
445
+	 * @throws ReflectionException
446
+	 */
447
+	public function wp_post(): WP_Post
448
+	{
449
+		global $wpdb;
450
+		if (! $this->_wp_post instanceof WP_Post) {
451
+			if ($this->ID()) {
452
+				$this->_wp_post = get_post($this->ID());
453
+			} else {
454
+				$simulated_db_result = new stdClass();
455
+				$field_settings      = $this->get_model()->field_settings(true);
456
+				foreach ($field_settings as $field_name => $field_obj) {
457
+					if (
458
+						$this->get_model()->get_table_obj_by_alias($field_obj->get_table_alias())
459
+							 ->get_table_name() === $wpdb->posts
460
+					) {
461
+						$column = $field_obj->get_table_column();
462
+
463
+						if ($field_obj instanceof EE_Datetime_Field) {
464
+							$value_on_model_obj = $this->get_DateTime_object($field_name);
465
+						} elseif ($field_obj->is_db_only_field()) {
466
+							$value_on_model_obj = $field_obj->get_default_value();
467
+						} else {
468
+							$value_on_model_obj = $this->get_raw($field_name);
469
+						}
470
+						$simulated_db_result->{$column} = $field_obj->prepare_for_use_in_db($value_on_model_obj);
471
+					}
472
+				}
473
+				$this->_wp_post = new WP_Post($simulated_db_result);
474
+			}
475
+			// and let's make retrieving the EE CPT object easy too
476
+			$classname = get_class($this);
477
+			if (! isset($this->_wp_post->{$classname})) {
478
+				$this->_wp_post->{$classname} = $this;
479
+			}
480
+		}
481
+		return $this->_wp_post;
482
+	}
483
+
484
+
485
+	/**
486
+	 * Don't serialize the WP Post. That's just duplicate data and we want to avoid recursion
487
+	 *
488
+	 * @return array
489
+	 * @throws EE_Error
490
+	 * @throws ReflectionException
491
+	 */
492
+	public function __sleep()
493
+	{
494
+		$properties_to_serialize = parent::__sleep();
495
+		return array_diff($properties_to_serialize, ['_wp_post']);
496
+	}
497 497
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
      */
80 80
     public function remove_relation_to_term_taxonomy(EE_Term_Taxonomy $term_taxonomy): ?EE_Base_Class
81 81
     {
82
-        if (! $term_taxonomy) {
82
+        if ( ! $term_taxonomy) {
83 83
             EE_Error::add_error(
84 84
                 sprintf(
85 85
                     esc_html__(
@@ -185,11 +185,11 @@  discard block
 block discarded – undo
185 185
             ? implode('_', $attr)
186 186
             : $attr;
187 187
         $cache_key                          = is_array($size)
188
-            ? implode('_', $size) . $attr_key
189
-            : $size . $attr_key;
190
-        $this->_feature_image[ $cache_key ] = $this->_feature_image[ $cache_key ]
188
+            ? implode('_', $size).$attr_key
189
+            : $size.$attr_key;
190
+        $this->_feature_image[$cache_key] = $this->_feature_image[$cache_key]
191 191
                                               ?? $this->get_model()->get_feature_image($this->ID(), $size, $attr);
192
-        return $this->_feature_image[ $cache_key ];
192
+        return $this->_feature_image[$cache_key];
193 193
     }
194 194
 
195 195
 
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
             foreach ($related_obj_names as $related_name) {
248 248
                 // related_obj_name so we're saving a revision on an object related to this object
249 249
                 // do we have $where_query params for this related object?  If we do then we include that.
250
-                $cols_n_values         = $where_query[ $related_name ] ?? [];
250
+                $cols_n_values         = $where_query[$related_name] ?? [];
251 251
                 $where_params          = ! empty($cols_n_values)
252 252
                     ? [$cols_n_values]
253 253
                     : [];
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
      */
306 306
     public function update_post_meta(string $meta_key, $meta_value, $prev_value = null)
307 307
     {
308
-        if (! $this->ID()) {
308
+        if ( ! $this->ID()) {
309 309
             $this->save();
310 310
         }
311 311
         return update_post_meta($this->ID(), $meta_key, $meta_value, $prev_value);
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
      */
345 345
     public function delete_post_meta(string $meta_key, $meta_value = ''): bool
346 346
     {
347
-        if (! $this->ID()) {
347
+        if ( ! $this->ID()) {
348 348
             // there is obviously no postmeta for this if it's not saved
349 349
             // so let's just report this as a success
350 350
             return true;
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
     public function wp_post(): WP_Post
448 448
     {
449 449
         global $wpdb;
450
-        if (! $this->_wp_post instanceof WP_Post) {
450
+        if ( ! $this->_wp_post instanceof WP_Post) {
451 451
             if ($this->ID()) {
452 452
                 $this->_wp_post = get_post($this->ID());
453 453
             } else {
@@ -474,7 +474,7 @@  discard block
 block discarded – undo
474 474
             }
475 475
             // and let's make retrieving the EE CPT object easy too
476 476
             $classname = get_class($this);
477
-            if (! isset($this->_wp_post->{$classname})) {
477
+            if ( ! isset($this->_wp_post->{$classname})) {
478 478
                 $this->_wp_post->{$classname} = $this;
479 479
             }
480 480
         }
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
      * Removes a venue from the event
722 722
      *
723 723
      * @param EE_Venue /int $venue_id_or_obj
724
-     * @return EE_Venue|null
724
+     * @return EE_Base_Class
725 725
      * @throws EE_Error
726 726
      * @throws ReflectionException
727 727
      */
@@ -881,7 +881,7 @@  discard block
 block discarded – undo
881 881
     /**
882 882
      * calculate spaces remaining based on "saleable" tickets
883 883
      *
884
-     * @param array $tickets
884
+     * @param EE_Ticket[] $tickets
885 885
      * @param bool  $filtered
886 886
      * @return int|float
887 887
      * @throws EE_Error
@@ -1272,7 +1272,7 @@  discard block
 block discarded – undo
1272 1272
      *
1273 1273
      * @param array $query_params @see
1274 1274
      *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1275
-     * @return EE_Term|null
1275
+     * @return null|EE_Base_Class
1276 1276
      * @throws EE_Error
1277 1277
      * @throws ReflectionException
1278 1278
      */
Please login to merge, or discard this patch.
Indentation   +1450 added lines, -1450 removed lines patch added patch discarded remove patch
@@ -15,1454 +15,1454 @@
 block discarded – undo
15 15
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
16 16
 {
17 17
 
18
-    /**
19
-     * cached value for the the logical active status for the event
20
-     *
21
-     * @see get_active_status()
22
-     * @var string
23
-     */
24
-    protected $_active_status = '';
25
-
26
-    /**
27
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
-     *
29
-     * @var EE_Datetime
30
-     */
31
-    protected $_Primary_Datetime;
32
-
33
-    /**
34
-     * @var EventSpacesCalculator $available_spaces_calculator
35
-     */
36
-    protected $available_spaces_calculator;
37
-
38
-
39
-    /**
40
-     * @param array  $props_n_values          incoming values
41
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
42
-     *                                        used.)
43
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
44
-     *                                        date_format and the second value is the time format
45
-     * @return EE_Event
46
-     * @throws EE_Error
47
-     * @throws ReflectionException
48
-     */
49
-    public static function new_instance(
50
-        array $props_n_values = [],
51
-        string $timezone = '',
52
-        array $date_formats = []
53
-    ): EE_Event {
54
-        /** @var EE_Event $has_object */
55
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
56
-        return $has_object
57
-            ?: new self($props_n_values, false, $timezone, $date_formats);
58
-    }
59
-
60
-
61
-    /**
62
-     * @param array  $props_n_values  incoming values from the database
63
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
64
-     *                                the website will be used.
65
-     * @return EE_Event
66
-     * @throws EE_Error
67
-     * @throws ReflectionException
68
-     */
69
-    public static function new_instance_from_db(array $props_n_values = [], string $timezone = ''): EE_Event
70
-    {
71
-        return new self($props_n_values, true, $timezone);
72
-    }
73
-
74
-
75
-    /**
76
-     * @return EventSpacesCalculator
77
-     * @throws EE_Error
78
-     */
79
-    public function getAvailableSpacesCalculator(): EventSpacesCalculator
80
-    {
81
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
82
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
83
-        }
84
-        return $this->available_spaces_calculator;
85
-    }
86
-
87
-
88
-    /**
89
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
90
-     *
91
-     * @param string $field_name
92
-     * @param mixed  $field_value
93
-     * @param bool   $use_default
94
-     * @throws EE_Error
95
-     * @throws ReflectionException
96
-     */
97
-    public function set(string $field_name, $field_value, bool $use_default = false)
98
-    {
99
-        switch ($field_name) {
100
-            case 'status':
101
-                $this->set_status($field_value, $use_default);
102
-                break;
103
-            default:
104
-                parent::set($field_name, $field_value, $use_default);
105
-        }
106
-    }
107
-
108
-
109
-    /**
110
-     * set_status
111
-     * Checks if event status is being changed to SOLD OUT
112
-     * and updates event meta data with previous event status
113
-     * so that we can revert things if/when the event is no longer sold out
114
-     *
115
-     * @param string|null $status
116
-     * @return void
117
-     * @throws EE_Error
118
-     * @throws ReflectionException
119
-     */
120
-    public function set_status(string $status = null, bool $use_default = false)
121
-    {
122
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
123
-        if (empty($status) && ! $use_default) {
124
-            return;
125
-        }
126
-        // get current Event status
127
-        $old_status = $this->status();
128
-        // if status has changed
129
-        if ($old_status !== $status) {
130
-            // TO sold_out
131
-            if ($status === EEM_Event::sold_out) {
132
-                // save the previous event status so that we can revert if the event is no longer sold out
133
-                $this->add_post_meta('_previous_event_status', $old_status);
134
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $status);
135
-                // OR FROM  sold_out
136
-            } elseif ($old_status === EEM_Event::sold_out) {
137
-                $this->delete_post_meta('_previous_event_status');
138
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $status);
139
-            }
140
-            // clear out the active status so that it gets reset the next time it is requested
141
-            $this->_active_status = null;
142
-            // update status
143
-            parent::set('status', $status, $use_default);
144
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
145
-            return;
146
-        }
147
-        // even though the old value matches the new value, it's still good to
148
-        // allow the parent set method to have a say
149
-        parent::set('status', $status, $use_default);
150
-    }
151
-
152
-
153
-    /**
154
-     * Gets all the datetimes for this event
155
-     *
156
-     * @param array $query_params @see
157
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
158
-     * @return EE_Datetime[]
159
-     * @throws EE_Error
160
-     * @throws ReflectionException
161
-     */
162
-    public function datetimes(array $query_params = []): array
163
-    {
164
-        return $this->get_many_related('Datetime', $query_params);
165
-    }
166
-
167
-
168
-    /**
169
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
170
-     *
171
-     * @return EE_Datetime[]
172
-     * @throws EE_Error
173
-     * @throws ReflectionException
174
-     */
175
-    public function datetimes_in_chronological_order(): array
176
-    {
177
-        return $this->get_many_related('Datetime', ['order_by' => ['DTT_EVT_start' => 'ASC']]);
178
-    }
179
-
180
-
181
-    /**
182
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
183
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
184
-     * after running our query, so that this timezone isn't set for EVERY query
185
-     * on EEM_Datetime for the rest of the request, no?
186
-     *
187
-     * @param boolean $show_expired whether or not to include expired events
188
-     * @param boolean $show_deleted whether or not to include deleted events
189
-     * @param int    $limit
190
-     * @return EE_Datetime[]
191
-     * @throws EE_Error
192
-     * @throws ReflectionException
193
-     */
194
-    public function datetimes_ordered(bool $show_expired = true, bool $show_deleted = false, int $limit = 0): array
195
-    {
196
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
197
-            $this->ID(),
198
-            $show_expired,
199
-            $show_deleted,
200
-            $limit
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * Returns one related datetime. Mostly only used by some legacy code.
207
-     *
208
-     * @return EE_Datetime
209
-     * @throws EE_Error
210
-     * @throws ReflectionException
211
-     */
212
-    public function first_datetime(): EE_Datetime
213
-    {
214
-        return $this->get_first_related('Datetime');
215
-    }
216
-
217
-
218
-    /**
219
-     * Returns the 'primary' datetime for the event
220
-     *
221
-     * @param bool $try_to_exclude_expired
222
-     * @param bool $try_to_exclude_deleted
223
-     * @return EE_Datetime
224
-     * @throws EE_Error
225
-     * @throws ReflectionException
226
-     */
227
-    public function primary_datetime(
228
-        bool $try_to_exclude_expired = true,
229
-        bool $try_to_exclude_deleted = true
230
-    ): EE_Datetime {
231
-        if (! empty($this->_Primary_Datetime)) {
232
-            return $this->_Primary_Datetime;
233
-        }
234
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
235
-            $this->ID(),
236
-            $try_to_exclude_expired,
237
-            $try_to_exclude_deleted
238
-        );
239
-        return $this->_Primary_Datetime;
240
-    }
241
-
242
-
243
-    /**
244
-     * Gets all the tickets available for purchase of this event
245
-     *
246
-     * @param array $query_params @see
247
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
248
-     * @return EE_Ticket[]
249
-     * @throws EE_Error
250
-     * @throws ReflectionException
251
-     */
252
-    public function tickets(array $query_params = []): array
253
-    {
254
-        // first get all datetimes
255
-        $datetimes = $this->datetimes_ordered();
256
-        if (! $datetimes) {
257
-            return [];
258
-        }
259
-        $datetime_ids = [];
260
-        foreach ($datetimes as $datetime) {
261
-            $datetime_ids[] = $datetime->ID();
262
-        }
263
-        $where_params = ['Datetime.DTT_ID' => ['IN', $datetime_ids]];
264
-        // if incoming $query_params has where conditions let's merge but not override existing.
265
-        if (is_array($query_params) && isset($query_params[0])) {
266
-            $where_params = array_merge($query_params[0], $where_params);
267
-            unset($query_params[0]);
268
-        }
269
-        // now add $where_params to $query_params
270
-        $query_params[0] = $where_params;
271
-        return EEM_Ticket::instance()->get_all($query_params);
272
-    }
273
-
274
-
275
-    /**
276
-     * get all unexpired untrashed tickets
277
-     *
278
-     * @return EE_Ticket[]
279
-     * @throws EE_Error
280
-     * @throws ReflectionException
281
-     */
282
-    public function active_tickets(): array
283
-    {
284
-        return $this->tickets(
285
-            [
286
-                [
287
-                    'TKT_end_date' => ['>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')],
288
-                    'TKT_deleted'  => false,
289
-                ],
290
-            ]
291
-        );
292
-    }
293
-
294
-
295
-    /**
296
-     * @return bool
297
-     * @throws EE_Error
298
-     */
299
-    public function additional_limit(): bool
300
-    {
301
-        return $this->get('EVT_additional_limit');
302
-    }
303
-
304
-
305
-    /**
306
-     * @return bool
307
-     * @throws EE_Error
308
-     */
309
-    public function allow_overflow(): bool
310
-    {
311
-        return $this->get('EVT_allow_overflow');
312
-    }
313
-
314
-
315
-    /**
316
-     * @return bool
317
-     * @throws EE_Error
318
-     */
319
-    public function created(): bool
320
-    {
321
-        return $this->get('EVT_created');
322
-    }
323
-
324
-
325
-    /**
326
-     * @return bool
327
-     * @throws EE_Error
328
-     */
329
-    public function description(): bool
330
-    {
331
-        return $this->get('EVT_desc');
332
-    }
333
-
334
-
335
-    /**
336
-     * Runs do_shortcode and wpautop on the description
337
-     *
338
-     * @return string of html
339
-     * @throws EE_Error
340
-     */
341
-    public function description_filtered(): string
342
-    {
343
-        return $this->get_pretty('EVT_desc');
344
-    }
345
-
346
-
347
-    /**
348
-     * @return bool
349
-     * @throws EE_Error
350
-     */
351
-    public function display_description(): bool
352
-    {
353
-        return $this->get('EVT_display_desc');
354
-    }
355
-
356
-
357
-    /**
358
-     * @return bool
359
-     * @throws EE_Error
360
-     */
361
-    public function display_ticket_selector(): bool
362
-    {
363
-        return (bool) $this->get('EVT_display_ticket_selector');
364
-    }
365
-
366
-
367
-    /**
368
-     * @return bool
369
-     * @throws EE_Error
370
-     */
371
-    public function external_url(): bool
372
-    {
373
-        return $this->get('EVT_external_URL');
374
-    }
375
-
376
-
377
-    /**
378
-     * @return bool
379
-     * @throws EE_Error
380
-     */
381
-    public function member_only(): bool
382
-    {
383
-        return $this->get('EVT_member_only');
384
-    }
385
-
386
-
387
-    /**
388
-     * @return bool
389
-     * @throws EE_Error
390
-     */
391
-    public function phone(): bool
392
-    {
393
-        return $this->get('EVT_phone');
394
-    }
395
-
396
-
397
-    /**
398
-     * @return bool
399
-     * @throws EE_Error
400
-     */
401
-    public function modified(): bool
402
-    {
403
-        return $this->get('EVT_modified');
404
-    }
405
-
406
-
407
-    /**
408
-     * @return bool
409
-     * @throws EE_Error
410
-     */
411
-    public function name(): bool
412
-    {
413
-        return $this->get('EVT_name');
414
-    }
415
-
416
-
417
-    /**
418
-     * @return bool
419
-     * @throws EE_Error
420
-     */
421
-    public function order(): bool
422
-    {
423
-        return $this->get('EVT_order');
424
-    }
425
-
426
-
427
-    /**
428
-     * @return bool|string
429
-     * @throws EE_Error
430
-     */
431
-    public function default_registration_status()
432
-    {
433
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
434
-        return ! empty($event_default_registration_status)
435
-            ? $event_default_registration_status
436
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
437
-    }
438
-
439
-
440
-    /**
441
-     * @param int  $num_words
442
-     * @param string|null $more
443
-     * @param bool $not_full_desc
444
-     * @return bool|string
445
-     * @throws EE_Error
446
-     */
447
-    public function short_description(int $num_words = 55, string $more = null, bool $not_full_desc = false)
448
-    {
449
-        $short_desc = $this->get('EVT_short_desc');
450
-        if (! empty($short_desc) || $not_full_desc) {
451
-            return $short_desc;
452
-        }
453
-        $full_desc = $this->get('EVT_desc');
454
-        return wp_trim_words($full_desc, $num_words, $more);
455
-    }
456
-
457
-
458
-    /**
459
-     * @return string
460
-     * @throws EE_Error
461
-     */
462
-    public function slug(): string
463
-    {
464
-        return $this->get('EVT_slug');
465
-    }
466
-
467
-
468
-    /**
469
-     * @return string
470
-     * @throws EE_Error
471
-     */
472
-    public function timezone_string(): string
473
-    {
474
-        return $this->get('EVT_timezone_string');
475
-    }
476
-
477
-
478
-    /**
479
-     * @return string
480
-     * @throws EE_Error
481
-     */
482
-    public function visible_on(): string
483
-    {
484
-        return $this->get('EVT_visible_on');
485
-    }
486
-
487
-
488
-    /**
489
-     * @return int
490
-     * @throws EE_Error
491
-     */
492
-    public function wp_user(): int
493
-    {
494
-        return $this->get('EVT_wp_user');
495
-    }
496
-
497
-
498
-    /**
499
-     * @return bool
500
-     * @throws EE_Error
501
-     */
502
-    public function donations(): bool
503
-    {
504
-        return $this->get('EVT_donations');
505
-    }
506
-
507
-
508
-    /**
509
-     * @param $limit
510
-     * @throws EE_Error
511
-     * @throws ReflectionException
512
-     */
513
-    public function set_additional_limit($limit)
514
-    {
515
-        $this->set('EVT_additional_limit', $limit);
516
-    }
517
-
518
-
519
-    /**
520
-     * @param $created
521
-     * @throws EE_Error
522
-     * @throws ReflectionException
523
-     */
524
-    public function set_created($created)
525
-    {
526
-        $this->set('EVT_created', $created);
527
-    }
528
-
529
-
530
-    /**
531
-     * @param $desc
532
-     * @throws EE_Error
533
-     * @throws ReflectionException
534
-     */
535
-    public function set_description($desc)
536
-    {
537
-        $this->set('EVT_desc', $desc);
538
-    }
539
-
540
-
541
-    /**
542
-     * @param $display_desc
543
-     * @throws EE_Error
544
-     * @throws ReflectionException
545
-     */
546
-    public function set_display_description($display_desc)
547
-    {
548
-        $this->set('EVT_display_desc', $display_desc);
549
-    }
550
-
551
-
552
-    /**
553
-     * @param $display_ticket_selector
554
-     * @throws EE_Error
555
-     * @throws ReflectionException
556
-     */
557
-    public function set_display_ticket_selector($display_ticket_selector)
558
-    {
559
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
560
-    }
561
-
562
-
563
-    /**
564
-     * @param $external_url
565
-     * @throws EE_Error
566
-     * @throws ReflectionException
567
-     */
568
-    public function set_external_url($external_url)
569
-    {
570
-        $this->set('EVT_external_URL', $external_url);
571
-    }
572
-
573
-
574
-    /**
575
-     * @param $member_only
576
-     * @throws EE_Error
577
-     * @throws ReflectionException
578
-     */
579
-    public function set_member_only($member_only)
580
-    {
581
-        $this->set('EVT_member_only', $member_only);
582
-    }
583
-
584
-
585
-    /**
586
-     * @param $event_phone
587
-     * @throws EE_Error
588
-     * @throws ReflectionException
589
-     */
590
-    public function set_event_phone($event_phone)
591
-    {
592
-        $this->set('EVT_phone', $event_phone);
593
-    }
594
-
595
-
596
-    /**
597
-     * @param $modified
598
-     * @throws EE_Error
599
-     * @throws ReflectionException
600
-     */
601
-    public function set_modified($modified)
602
-    {
603
-        $this->set('EVT_modified', $modified);
604
-    }
605
-
606
-
607
-    /**
608
-     * @param $name
609
-     * @throws EE_Error
610
-     * @throws ReflectionException
611
-     */
612
-    public function set_name($name)
613
-    {
614
-        $this->set('EVT_name', $name);
615
-    }
616
-
617
-
618
-    /**
619
-     * @param $order
620
-     * @throws EE_Error
621
-     * @throws ReflectionException
622
-     */
623
-    public function set_order($order)
624
-    {
625
-        $this->set('EVT_order', $order);
626
-    }
627
-
628
-
629
-    /**
630
-     * @param $short_desc
631
-     * @throws EE_Error
632
-     * @throws ReflectionException
633
-     */
634
-    public function set_short_description($short_desc)
635
-    {
636
-        $this->set('EVT_short_desc', $short_desc);
637
-    }
638
-
639
-
640
-    /**
641
-     * @param $slug
642
-     * @throws EE_Error
643
-     * @throws ReflectionException
644
-     */
645
-    public function set_slug($slug)
646
-    {
647
-        $this->set('EVT_slug', $slug);
648
-    }
649
-
650
-
651
-    /**
652
-     * @param $timezone_string
653
-     * @throws EE_Error
654
-     * @throws ReflectionException
655
-     */
656
-    public function set_timezone_string($timezone_string)
657
-    {
658
-        $this->set('EVT_timezone_string', $timezone_string);
659
-    }
660
-
661
-
662
-    /**
663
-     * @param $visible_on
664
-     * @throws EE_Error
665
-     * @throws ReflectionException
666
-     */
667
-    public function set_visible_on($visible_on)
668
-    {
669
-        $this->set('EVT_visible_on', $visible_on);
670
-    }
671
-
672
-
673
-    /**
674
-     * @param $wp_user
675
-     * @throws EE_Error
676
-     * @throws ReflectionException
677
-     */
678
-    public function set_wp_user($wp_user)
679
-    {
680
-        $this->set('EVT_wp_user', $wp_user);
681
-    }
682
-
683
-
684
-    /**
685
-     * @param $default_registration_status
686
-     * @throws EE_Error
687
-     * @throws ReflectionException
688
-     */
689
-    public function set_default_registration_status($default_registration_status)
690
-    {
691
-        $this->set('EVT_default_registration_status', $default_registration_status);
692
-    }
693
-
694
-
695
-    /**
696
-     * @param $donations
697
-     * @throws EE_Error
698
-     * @throws ReflectionException
699
-     */
700
-    public function set_donations($donations)
701
-    {
702
-        $this->set('EVT_donations', $donations);
703
-    }
704
-
705
-
706
-    /**
707
-     * Adds a venue to this event
708
-     *
709
-     * @param EE_Venue /int $venue_id_or_obj
710
-     * @return EE_Venue
711
-     * @throws EE_Error
712
-     * @throws ReflectionException
713
-     */
714
-    public function add_venue($venue_id_or_obj): EE_Venue
715
-    {
716
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
717
-    }
718
-
719
-
720
-    /**
721
-     * Removes a venue from the event
722
-     *
723
-     * @param EE_Venue /int $venue_id_or_obj
724
-     * @return EE_Venue|null
725
-     * @throws EE_Error
726
-     * @throws ReflectionException
727
-     */
728
-    public function remove_venue($venue_id_or_obj): ?EE_Venue
729
-    {
730
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
731
-    }
732
-
733
-
734
-    /**
735
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
736
-     *
737
-     * @param array $query_params @see
738
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
739
-     * @return EE_Venue[]
740
-     * @throws EE_Error
741
-     * @throws ReflectionException
742
-     */
743
-    public function venues(array $query_params = []): array
744
-    {
745
-        return $this->get_many_related('Venue', $query_params);
746
-    }
747
-
748
-
749
-    /**
750
-     * check if event id is present and if event is published
751
-     *
752
-     * @return boolean true yes, false no
753
-     * @throws EE_Error
754
-     */
755
-    private function _has_ID_and_is_published(): bool
756
-    {
757
-        // first check if event id is present and not NULL,
758
-        // then check if this event is published (or any of the equivalent "published" statuses)
759
-        return
760
-            $this->ID() && $this->ID() !== null
761
-            && (
762
-                $this->status() === 'publish'
763
-                || $this->status() === EEM_Event::sold_out
764
-                || $this->status() === EEM_Event::postponed
765
-                || $this->status() === EEM_Event::cancelled
766
-            );
767
-    }
768
-
769
-
770
-    /**
771
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
772
-     *
773
-     * @return boolean true yes, false no
774
-     * @throws EE_Error
775
-     * @throws ReflectionException
776
-     */
777
-    public function is_upcoming(): bool
778
-    {
779
-        // check if event id is present and if this event is published
780
-        if ($this->is_inactive()) {
781
-            return false;
782
-        }
783
-        // set initial value
784
-        $upcoming = false;
785
-        // next let's get all datetimes and loop through them
786
-        $datetimes = $this->datetimes_in_chronological_order();
787
-        foreach ($datetimes as $datetime) {
788
-            if ($datetime instanceof EE_Datetime) {
789
-                // if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
790
-                if ($datetime->is_expired()) {
791
-                    continue;
792
-                }
793
-                // if this dtt is active then we return false.
794
-                if ($datetime->is_active()) {
795
-                    return false;
796
-                }
797
-                // otherwise let's check upcoming status
798
-                $upcoming = $datetime->is_upcoming();
799
-            }
800
-        }
801
-        return $upcoming;
802
-    }
803
-
804
-
805
-    /**
806
-     * @return bool
807
-     * @throws EE_Error
808
-     * @throws ReflectionException
809
-     */
810
-    public function is_active(): bool
811
-    {
812
-        // check if event id is present and if this event is published
813
-        if ($this->is_inactive()) {
814
-            return false;
815
-        }
816
-        // set initial value
817
-        $active = false;
818
-        // next let's get all datetimes and loop through them
819
-        $datetimes = $this->datetimes_in_chronological_order();
820
-        foreach ($datetimes as $datetime) {
821
-            if ($datetime instanceof EE_Datetime) {
822
-                // if this dtt is expired then we continue cause one of the other datetimes might be active.
823
-                if ($datetime->is_expired()) {
824
-                    continue;
825
-                }
826
-                // if this dtt is upcoming then we return false.
827
-                if ($datetime->is_upcoming()) {
828
-                    return false;
829
-                }
830
-                // otherwise let's check active status
831
-                $active = $datetime->is_active();
832
-            }
833
-        }
834
-        return $active;
835
-    }
836
-
837
-
838
-    /**
839
-     * @return bool
840
-     * @throws EE_Error
841
-     * @throws ReflectionException
842
-     */
843
-    public function is_expired(): bool
844
-    {
845
-        // check if event id is present and if this event is published
846
-        if ($this->is_inactive()) {
847
-            return false;
848
-        }
849
-        // set initial value
850
-        $expired = false;
851
-        // first let's get all datetimes and loop through them
852
-        $datetimes = $this->datetimes_in_chronological_order();
853
-        foreach ($datetimes as $datetime) {
854
-            if ($datetime instanceof EE_Datetime) {
855
-                // if this dtt is upcoming or active then we return false.
856
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
857
-                    return false;
858
-                }
859
-                // otherwise let's check active status
860
-                $expired = $datetime->is_expired();
861
-            }
862
-        }
863
-        return $expired;
864
-    }
865
-
866
-
867
-    /**
868
-     * @return bool
869
-     * @throws EE_Error
870
-     */
871
-    public function is_inactive(): bool
872
-    {
873
-        // check if event id is present and if this event is published
874
-        if ($this->_has_ID_and_is_published()) {
875
-            return false;
876
-        }
877
-        return true;
878
-    }
879
-
880
-
881
-    /**
882
-     * calculate spaces remaining based on "saleable" tickets
883
-     *
884
-     * @param array $tickets
885
-     * @param bool  $filtered
886
-     * @return int|float
887
-     * @throws EE_Error
888
-     * @throws DomainException
889
-     * @throws UnexpectedEntityException
890
-     */
891
-    public function spaces_remaining(array $tickets = [], bool $filtered = true)
892
-    {
893
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
894
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
895
-        return $filtered
896
-            ? apply_filters(
897
-                'FHEE_EE_Event__spaces_remaining',
898
-                $spaces_remaining,
899
-                $this,
900
-                $tickets
901
-            )
902
-            : $spaces_remaining;
903
-    }
904
-
905
-
906
-    /**
907
-     *    perform_sold_out_status_check
908
-     *    checks all of this event's datetime reg_limit - sold values to determine if ANY datetimes have spaces
909
-     *    available... if NOT, then the event status will get toggled to 'sold_out'
910
-     *
911
-     * @return bool    return the ACTUAL sold out state.
912
-     * @throws EE_Error
913
-     * @throws DomainException
914
-     * @throws UnexpectedEntityException
915
-     * @throws ReflectionException
916
-     */
917
-    public function perform_sold_out_status_check(): bool
918
-    {
919
-        // get all tickets
920
-        $tickets     = $this->tickets(
921
-            [
922
-                'default_where_conditions' => 'none',
923
-                'order_by'                 => ['TKT_qty' => 'ASC'],
924
-            ]
925
-        );
926
-        $all_expired = true;
927
-        foreach ($tickets as $ticket) {
928
-            if (! $ticket->is_expired()) {
929
-                $all_expired = false;
930
-                break;
931
-            }
932
-        }
933
-        // if all the tickets are just expired, then don't update the event status to sold out
934
-        if ($all_expired) {
935
-            return true;
936
-        }
937
-        $spaces_remaining = $this->spaces_remaining($tickets);
938
-        if ($spaces_remaining < 1) {
939
-            if ($this->status() !== EEM_Event::post_status_private) {
940
-                $this->set_status(EEM_Event::sold_out);
941
-                $this->save();
942
-            }
943
-            $sold_out = true;
944
-        } else {
945
-            $sold_out = false;
946
-            // was event previously marked as sold out ?
947
-            if ($this->status() === EEM_Event::sold_out) {
948
-                // revert status to previous value, if it was set
949
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
950
-                if ($previous_event_status) {
951
-                    $this->set_status($previous_event_status);
952
-                    $this->save();
953
-                }
954
-            }
955
-        }
956
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
957
-        return $sold_out;
958
-    }
959
-
960
-
961
-    /**
962
-     * This returns the total remaining spaces for sale on this event.
963
-     *
964
-     * @return float|int
965
-     * @throws EE_Error
966
-     * @throws DomainException
967
-     * @throws UnexpectedEntityException
968
-     * @uses EE_Event::total_available_spaces()
969
-     */
970
-    public function spaces_remaining_for_sale()
971
-    {
972
-        return $this->total_available_spaces(true);
973
-    }
974
-
975
-
976
-    /**
977
-     * This returns the total spaces available for an event
978
-     * while considering all the qtys on the tickets and the reg limits
979
-     * on the datetimes attached to this event.
980
-     *
981
-     * @param bool $consider_sold   Whether to consider any tickets that have already sold in our calculation.
982
-     *                              If this is false, then we return the most tickets that could ever be sold
983
-     *                              for this event with the datetime and tickets setup on the event under optimal
984
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
985
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
986
-     *                              may appear to equal remaining tickets.  However, the more tickets are
987
-     *                              sold out, the more accurate the "live" total is.
988
-     * @return float|int
989
-     * @throws EE_Error
990
-     * @throws DomainException
991
-     * @throws UnexpectedEntityException
992
-     */
993
-    public function total_available_spaces(bool $consider_sold = false)
994
-    {
995
-        $spaces_available = $consider_sold
996
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
997
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
998
-        return apply_filters(
999
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
1000
-            $spaces_available,
1001
-            $this,
1002
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
1003
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
1004
-        );
1005
-    }
1006
-
1007
-
1008
-    /**
1009
-     * Checks if the event is set to sold out
1010
-     *
1011
-     * @param bool $actual  whether or not to perform calculations to not only figure the
1012
-     *                      actual status but also to flip the status if necessary to sold
1013
-     *                      out If false, we just check the existing status of the event
1014
-     * @return boolean
1015
-     * @throws EE_Error
1016
-     * @throws ReflectionException
1017
-     */
1018
-    public function is_sold_out(bool $actual = false): bool
1019
-    {
1020
-        if (! $actual) {
1021
-            return $this->status() === EEM_Event::sold_out;
1022
-        }
1023
-        return $this->perform_sold_out_status_check();
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * Checks if the event is marked as postponed
1029
-     *
1030
-     * @return boolean
1031
-     * @throws EE_Error
1032
-     * @throws EE_Error
1033
-     */
1034
-    public function is_postponed(): bool
1035
-    {
1036
-        return $this->status() === EEM_Event::postponed;
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * Checks if the event is marked as cancelled
1042
-     *
1043
-     * @return boolean
1044
-     * @throws EE_Error
1045
-     * @throws EE_Error
1046
-     */
1047
-    public function is_cancelled(): bool
1048
-    {
1049
-        return $this->status() === EEM_Event::cancelled;
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1055
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1056
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1057
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1058
-     * the event is considered expired.
1059
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1060
-     * status set on the EVENT when it is not published and thus is done
1061
-     *
1062
-     * @param bool $reset
1063
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1064
-     * @throws EE_Error
1065
-     * @throws ReflectionException
1066
-     */
1067
-    public function get_active_status(bool $reset = false)
1068
-    {
1069
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1070
-        if (! empty($this->_active_status) && ! $reset) {
1071
-            return $this->_active_status;
1072
-        }
1073
-        // first check if event id is present on this object
1074
-        if (! $this->ID()) {
1075
-            return false;
1076
-        }
1077
-        $where_params_for_event = [['EVT_ID' => $this->ID()]];
1078
-        // if event is published:
1079
-        if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1080
-            // active?
1081
-            if (
1082
-                EEM_Datetime::instance()->get_datetime_count_for_status(
1083
-                    EE_Datetime::active,
1084
-                    $where_params_for_event
1085
-                ) > 0
1086
-            ) {
1087
-                $this->_active_status = EE_Datetime::active;
1088
-            } else {
1089
-                // upcoming?
1090
-                if (
1091
-                    EEM_Datetime::instance()->get_datetime_count_for_status(
1092
-                        EE_Datetime::upcoming,
1093
-                        $where_params_for_event
1094
-                    ) > 0
1095
-                ) {
1096
-                    $this->_active_status = EE_Datetime::upcoming;
1097
-                } else {
1098
-                    // expired?
1099
-                    if (
1100
-                        EEM_Datetime::instance()->get_datetime_count_for_status(
1101
-                            EE_Datetime::expired,
1102
-                            $where_params_for_event
1103
-                        ) > 0
1104
-                    ) {
1105
-                        $this->_active_status = EE_Datetime::expired;
1106
-                    } else {
1107
-                        // it would be odd if things make it this far because it basically means there are no datetime's
1108
-                        // attached to the event.  So in this case it will just be considered inactive.
1109
-                        $this->_active_status = EE_Datetime::inactive;
1110
-                    }
1111
-                }
1112
-            }
1113
-        } else {
1114
-            // the event is not published, so let's just set it's active status according to its' post status
1115
-            switch ($this->status()) {
1116
-                case EEM_Event::sold_out:
1117
-                    $this->_active_status = EE_Datetime::sold_out;
1118
-                    break;
1119
-                case EEM_Event::cancelled:
1120
-                    $this->_active_status = EE_Datetime::cancelled;
1121
-                    break;
1122
-                case EEM_Event::postponed:
1123
-                    $this->_active_status = EE_Datetime::postponed;
1124
-                    break;
1125
-                default:
1126
-                    $this->_active_status = EE_Datetime::inactive;
1127
-            }
1128
-        }
1129
-        return $this->_active_status;
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     *    pretty_active_status
1135
-     *
1136
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1137
-     * @return string string
1138
-     * @throws EE_Error
1139
-     * @throws ReflectionException
1140
-     */
1141
-    public function pretty_active_status(bool $echo = true): string
1142
-    {
1143
-        $active_status = $this->get_active_status();
1144
-        $status        = '<span class="ee-status event-active-status-'
1145
-                         . $active_status
1146
-                         . '">'
1147
-                         . EEH_Template::pretty_status($active_status, false, 'sentence')
1148
-                         . '</span>';
1149
-        if ($echo) {
1150
-            echo $status;
1151
-            return '';
1152
-        }
1153
-        return $status;
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * @return bool|int
1159
-     * @throws EE_Error
1160
-     * @throws ReflectionException
1161
-     */
1162
-    public function get_number_of_tickets_sold()
1163
-    {
1164
-        $tkt_sold = 0;
1165
-        if (! $this->ID()) {
1166
-            return 0;
1167
-        }
1168
-        $datetimes = $this->datetimes();
1169
-        foreach ($datetimes as $datetime) {
1170
-            if ($datetime instanceof EE_Datetime) {
1171
-                $tkt_sold += $datetime->sold();
1172
-            }
1173
-        }
1174
-        return $tkt_sold;
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * This just returns a count of all the registrations for this event
1180
-     *
1181
-     * @return int
1182
-     * @throws EE_Error
1183
-     * @throws ReflectionException
1184
-     */
1185
-    public function get_count_of_all_registrations(): int
1186
-    {
1187
-        return EEM_Event::instance()->count_related($this, 'Registration');
1188
-    }
1189
-
1190
-
1191
-    /**
1192
-     * This returns the ticket with the earliest start time that is
1193
-     * available for this event (across all datetimes attached to the event)
1194
-     *
1195
-     * @return EE_Ticket|null
1196
-     * @throws EE_Error
1197
-     * @throws ReflectionException
1198
-     */
1199
-    public function get_ticket_with_earliest_start_time(): ?EE_Ticket
1200
-    {
1201
-        $where['Datetime.EVT_ID'] = $this->ID();
1202
-        $query_params             = [$where, 'order_by' => ['TKT_start_date' => 'ASC']];
1203
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * This returns the ticket with the latest end time that is available
1209
-     * for this event (across all datetimes attached to the event)
1210
-     *
1211
-     * @return EE_Ticket|null
1212
-     * @throws EE_Error
1213
-     * @throws ReflectionException
1214
-     */
1215
-    public function get_ticket_with_latest_end_time(): ?EE_Ticket
1216
-    {
1217
-        $where['Datetime.EVT_ID'] = $this->ID();
1218
-        $query_params             = [$where, 'order_by' => ['TKT_end_date' => 'DESC']];
1219
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * This returns the number of different ticket types currently on sale for this event.
1225
-     *
1226
-     * @return int
1227
-     * @throws EE_Error
1228
-     * @throws ReflectionException
1229
-     */
1230
-    public function countTicketsOnSale(): int
1231
-    {
1232
-        $where = [
1233
-            'Datetime.EVT_ID' => $this->ID(),
1234
-            'TKT_start_date'  => ['<', time()],
1235
-            'TKT_end_date'    => ['>', time()],
1236
-        ];
1237
-        return EEM_Ticket::instance()->count([$where]);
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     * This returns whether there are any tickets on sale for this event.
1243
-     *
1244
-     * @return bool true = YES tickets on sale.
1245
-     * @throws EE_Error
1246
-     * @throws ReflectionException
1247
-     */
1248
-    public function tickets_on_sale(): bool
1249
-    {
1250
-        return $this->countTicketsOnSale() > 0;
1251
-    }
1252
-
1253
-
1254
-    /**
1255
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1256
-     * to check for an external URL first
1257
-     *
1258
-     * @return string
1259
-     * @throws EE_Error
1260
-     */
1261
-    public function get_permalink(): string
1262
-    {
1263
-        if ($this->external_url()) {
1264
-            return $this->external_url();
1265
-        }
1266
-        return parent::get_permalink();
1267
-    }
1268
-
1269
-
1270
-    /**
1271
-     * Gets the first term for 'espresso_event_categories' we can find
1272
-     *
1273
-     * @param array $query_params @see
1274
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1275
-     * @return EE_Term|null
1276
-     * @throws EE_Error
1277
-     * @throws ReflectionException
1278
-     */
1279
-    public function first_event_category(array $query_params = []): ?EE_Term
1280
-    {
1281
-        $query_params[0]['Term_Taxonomy.taxonomy']     = 'espresso_event_categories';
1282
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1283
-        return EEM_Term::instance()->get_one($query_params);
1284
-    }
1285
-
1286
-
1287
-    /**
1288
-     * Gets all terms for 'espresso_event_categories' we can find
1289
-     *
1290
-     * @param array $query_params
1291
-     * @return EE_Term[]
1292
-     * @throws EE_Error
1293
-     * @throws ReflectionException
1294
-     */
1295
-    public function get_all_event_categories(array $query_params = []): array
1296
-    {
1297
-        $query_params[0]['Term_Taxonomy.taxonomy']     = 'espresso_event_categories';
1298
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1299
-        return EEM_Term::instance()->get_all($query_params);
1300
-    }
1301
-
1302
-
1303
-    /**
1304
-     * Adds a question group to this event
1305
-     *
1306
-     * @param EE_Question_Group|int $question_group_id_or_obj
1307
-     * @param bool                  $for_primary if true, the question group will be added for the primary
1308
-     *                                           registrant, if false will be added for others. default: false
1309
-     * @return EE_Question_Group
1310
-     * @throws EE_Error
1311
-     * @throws InvalidArgumentException
1312
-     * @throws InvalidDataTypeException
1313
-     * @throws InvalidInterfaceException
1314
-     * @throws ReflectionException
1315
-     */
1316
-    public function add_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group
1317
-    {
1318
-        // If the row already exists, it will be updated. If it doesn't, it will be inserted.
1319
-        // That's in EE_HABTM_Relation::add_relation_to().
1320
-        return $this->_add_relation_to(
1321
-            $question_group_id_or_obj,
1322
-            'Question_Group',
1323
-            [
1324
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true,
1325
-            ]
1326
-        );
1327
-    }
1328
-
1329
-
1330
-    /**
1331
-     * Removes a question group from the event
1332
-     *
1333
-     * @param EE_Question_Group|int $question_group_id_or_obj
1334
-     * @param bool                  $for_primary if true, the question group will be removed from the primary
1335
-     *                                           registrant, if false will be removed from others. default: false
1336
-     * @return EE_Question_Group
1337
-     * @throws EE_Error
1338
-     * @throws InvalidArgumentException
1339
-     * @throws ReflectionException
1340
-     * @throws InvalidDataTypeException
1341
-     * @throws InvalidInterfaceException
1342
-     */
1343
-    public function remove_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group
1344
-    {
1345
-        // If the question group is used for the other type (primary or additional)
1346
-        // then just update it. If not, delete it outright.
1347
-        $existing_relation = $this->get_first_related(
1348
-            'Event_Question_Group',
1349
-            [
1350
-                [
1351
-                    'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj),
1352
-                ],
1353
-            ]
1354
-        );
1355
-        $field_to_update   = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1356
-        $other_field       = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1357
-        if ($existing_relation->get($other_field) === false) {
1358
-            // Delete it. It's now no longer for primary or additional question groups.
1359
-            return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1360
-        }
1361
-        // Just update it. They'll still use this question group for the other category
1362
-        $existing_relation->save(
1363
-            [
1364
-                $field_to_update => false,
1365
-            ]
1366
-        );
1367
-        return $question_group_id_or_obj;
1368
-    }
1369
-
1370
-
1371
-    /**
1372
-     * Gets all the question groups, ordering them by QSG_order ascending
1373
-     *
1374
-     * @param array $query_params @see
1375
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1376
-     * @return EE_Question_Group[]
1377
-     * @throws EE_Error
1378
-     * @throws ReflectionException
1379
-     */
1380
-    public function question_groups(array $query_params = []): array
1381
-    {
1382
-        $query_params = ! empty($query_params)
1383
-            ? $query_params
1384
-            : ['order_by' => ['QSG_order' => 'ASC']];
1385
-        return $this->get_many_related('Question_Group', $query_params);
1386
-    }
1387
-
1388
-
1389
-    /**
1390
-     * Implementation for EEI_Has_Icon interface method.
1391
-     *
1392
-     * @return string
1393
-     * @see EEI_Visual_Representation for comments
1394
-     */
1395
-    public function get_icon(): string
1396
-    {
1397
-        return '<span class="dashicons dashicons-flag"></span>';
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * Implementation for EEI_Admin_Links interface method.
1403
-     *
1404
-     * @return string
1405
-     * @throws EE_Error
1406
-     * @see EEI_Admin_Links for comments
1407
-     */
1408
-    public function get_admin_details_link(): string
1409
-    {
1410
-        return $this->get_admin_edit_link();
1411
-    }
1412
-
1413
-
1414
-    /**
1415
-     * Implementation for EEI_Admin_Links interface method.
1416
-     *
1417
-     * @return string
1418
-     * @throws EE_Error
1419
-     * @see EEI_Admin_Links for comments
1420
-     */
1421
-    public function get_admin_edit_link(): string
1422
-    {
1423
-        return EEH_URL::add_query_args_and_nonce(
1424
-            [
1425
-                'page'   => 'espresso_events',
1426
-                'action' => 'edit',
1427
-                'post'   => $this->ID(),
1428
-            ],
1429
-            admin_url('admin.php')
1430
-        );
1431
-    }
1432
-
1433
-
1434
-    /**
1435
-     * Implementation for EEI_Admin_Links interface method.
1436
-     *
1437
-     * @return string
1438
-     * @see EEI_Admin_Links for comments
1439
-     */
1440
-    public function get_admin_settings_link(): string
1441
-    {
1442
-        return EEH_URL::add_query_args_and_nonce(
1443
-            [
1444
-                'page'   => 'espresso_events',
1445
-                'action' => 'default_event_settings',
1446
-            ],
1447
-            admin_url('admin.php')
1448
-        );
1449
-    }
1450
-
1451
-
1452
-    /**
1453
-     * Implementation for EEI_Admin_Links interface method.
1454
-     *
1455
-     * @return string
1456
-     * @see EEI_Admin_Links for comments
1457
-     */
1458
-    public function get_admin_overview_link(): string
1459
-    {
1460
-        return EEH_URL::add_query_args_and_nonce(
1461
-            [
1462
-                'page'   => 'espresso_events',
1463
-                'action' => 'default',
1464
-            ],
1465
-            admin_url('admin.php')
1466
-        );
1467
-    }
18
+	/**
19
+	 * cached value for the the logical active status for the event
20
+	 *
21
+	 * @see get_active_status()
22
+	 * @var string
23
+	 */
24
+	protected $_active_status = '';
25
+
26
+	/**
27
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
+	 *
29
+	 * @var EE_Datetime
30
+	 */
31
+	protected $_Primary_Datetime;
32
+
33
+	/**
34
+	 * @var EventSpacesCalculator $available_spaces_calculator
35
+	 */
36
+	protected $available_spaces_calculator;
37
+
38
+
39
+	/**
40
+	 * @param array  $props_n_values          incoming values
41
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
42
+	 *                                        used.)
43
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
44
+	 *                                        date_format and the second value is the time format
45
+	 * @return EE_Event
46
+	 * @throws EE_Error
47
+	 * @throws ReflectionException
48
+	 */
49
+	public static function new_instance(
50
+		array $props_n_values = [],
51
+		string $timezone = '',
52
+		array $date_formats = []
53
+	): EE_Event {
54
+		/** @var EE_Event $has_object */
55
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
56
+		return $has_object
57
+			?: new self($props_n_values, false, $timezone, $date_formats);
58
+	}
59
+
60
+
61
+	/**
62
+	 * @param array  $props_n_values  incoming values from the database
63
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
64
+	 *                                the website will be used.
65
+	 * @return EE_Event
66
+	 * @throws EE_Error
67
+	 * @throws ReflectionException
68
+	 */
69
+	public static function new_instance_from_db(array $props_n_values = [], string $timezone = ''): EE_Event
70
+	{
71
+		return new self($props_n_values, true, $timezone);
72
+	}
73
+
74
+
75
+	/**
76
+	 * @return EventSpacesCalculator
77
+	 * @throws EE_Error
78
+	 */
79
+	public function getAvailableSpacesCalculator(): EventSpacesCalculator
80
+	{
81
+		if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
82
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
83
+		}
84
+		return $this->available_spaces_calculator;
85
+	}
86
+
87
+
88
+	/**
89
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
90
+	 *
91
+	 * @param string $field_name
92
+	 * @param mixed  $field_value
93
+	 * @param bool   $use_default
94
+	 * @throws EE_Error
95
+	 * @throws ReflectionException
96
+	 */
97
+	public function set(string $field_name, $field_value, bool $use_default = false)
98
+	{
99
+		switch ($field_name) {
100
+			case 'status':
101
+				$this->set_status($field_value, $use_default);
102
+				break;
103
+			default:
104
+				parent::set($field_name, $field_value, $use_default);
105
+		}
106
+	}
107
+
108
+
109
+	/**
110
+	 * set_status
111
+	 * Checks if event status is being changed to SOLD OUT
112
+	 * and updates event meta data with previous event status
113
+	 * so that we can revert things if/when the event is no longer sold out
114
+	 *
115
+	 * @param string|null $status
116
+	 * @return void
117
+	 * @throws EE_Error
118
+	 * @throws ReflectionException
119
+	 */
120
+	public function set_status(string $status = null, bool $use_default = false)
121
+	{
122
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
123
+		if (empty($status) && ! $use_default) {
124
+			return;
125
+		}
126
+		// get current Event status
127
+		$old_status = $this->status();
128
+		// if status has changed
129
+		if ($old_status !== $status) {
130
+			// TO sold_out
131
+			if ($status === EEM_Event::sold_out) {
132
+				// save the previous event status so that we can revert if the event is no longer sold out
133
+				$this->add_post_meta('_previous_event_status', $old_status);
134
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $status);
135
+				// OR FROM  sold_out
136
+			} elseif ($old_status === EEM_Event::sold_out) {
137
+				$this->delete_post_meta('_previous_event_status');
138
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $status);
139
+			}
140
+			// clear out the active status so that it gets reset the next time it is requested
141
+			$this->_active_status = null;
142
+			// update status
143
+			parent::set('status', $status, $use_default);
144
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
145
+			return;
146
+		}
147
+		// even though the old value matches the new value, it's still good to
148
+		// allow the parent set method to have a say
149
+		parent::set('status', $status, $use_default);
150
+	}
151
+
152
+
153
+	/**
154
+	 * Gets all the datetimes for this event
155
+	 *
156
+	 * @param array $query_params @see
157
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
158
+	 * @return EE_Datetime[]
159
+	 * @throws EE_Error
160
+	 * @throws ReflectionException
161
+	 */
162
+	public function datetimes(array $query_params = []): array
163
+	{
164
+		return $this->get_many_related('Datetime', $query_params);
165
+	}
166
+
167
+
168
+	/**
169
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
170
+	 *
171
+	 * @return EE_Datetime[]
172
+	 * @throws EE_Error
173
+	 * @throws ReflectionException
174
+	 */
175
+	public function datetimes_in_chronological_order(): array
176
+	{
177
+		return $this->get_many_related('Datetime', ['order_by' => ['DTT_EVT_start' => 'ASC']]);
178
+	}
179
+
180
+
181
+	/**
182
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
183
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
184
+	 * after running our query, so that this timezone isn't set for EVERY query
185
+	 * on EEM_Datetime for the rest of the request, no?
186
+	 *
187
+	 * @param boolean $show_expired whether or not to include expired events
188
+	 * @param boolean $show_deleted whether or not to include deleted events
189
+	 * @param int    $limit
190
+	 * @return EE_Datetime[]
191
+	 * @throws EE_Error
192
+	 * @throws ReflectionException
193
+	 */
194
+	public function datetimes_ordered(bool $show_expired = true, bool $show_deleted = false, int $limit = 0): array
195
+	{
196
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
197
+			$this->ID(),
198
+			$show_expired,
199
+			$show_deleted,
200
+			$limit
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * Returns one related datetime. Mostly only used by some legacy code.
207
+	 *
208
+	 * @return EE_Datetime
209
+	 * @throws EE_Error
210
+	 * @throws ReflectionException
211
+	 */
212
+	public function first_datetime(): EE_Datetime
213
+	{
214
+		return $this->get_first_related('Datetime');
215
+	}
216
+
217
+
218
+	/**
219
+	 * Returns the 'primary' datetime for the event
220
+	 *
221
+	 * @param bool $try_to_exclude_expired
222
+	 * @param bool $try_to_exclude_deleted
223
+	 * @return EE_Datetime
224
+	 * @throws EE_Error
225
+	 * @throws ReflectionException
226
+	 */
227
+	public function primary_datetime(
228
+		bool $try_to_exclude_expired = true,
229
+		bool $try_to_exclude_deleted = true
230
+	): EE_Datetime {
231
+		if (! empty($this->_Primary_Datetime)) {
232
+			return $this->_Primary_Datetime;
233
+		}
234
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
235
+			$this->ID(),
236
+			$try_to_exclude_expired,
237
+			$try_to_exclude_deleted
238
+		);
239
+		return $this->_Primary_Datetime;
240
+	}
241
+
242
+
243
+	/**
244
+	 * Gets all the tickets available for purchase of this event
245
+	 *
246
+	 * @param array $query_params @see
247
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
248
+	 * @return EE_Ticket[]
249
+	 * @throws EE_Error
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function tickets(array $query_params = []): array
253
+	{
254
+		// first get all datetimes
255
+		$datetimes = $this->datetimes_ordered();
256
+		if (! $datetimes) {
257
+			return [];
258
+		}
259
+		$datetime_ids = [];
260
+		foreach ($datetimes as $datetime) {
261
+			$datetime_ids[] = $datetime->ID();
262
+		}
263
+		$where_params = ['Datetime.DTT_ID' => ['IN', $datetime_ids]];
264
+		// if incoming $query_params has where conditions let's merge but not override existing.
265
+		if (is_array($query_params) && isset($query_params[0])) {
266
+			$where_params = array_merge($query_params[0], $where_params);
267
+			unset($query_params[0]);
268
+		}
269
+		// now add $where_params to $query_params
270
+		$query_params[0] = $where_params;
271
+		return EEM_Ticket::instance()->get_all($query_params);
272
+	}
273
+
274
+
275
+	/**
276
+	 * get all unexpired untrashed tickets
277
+	 *
278
+	 * @return EE_Ticket[]
279
+	 * @throws EE_Error
280
+	 * @throws ReflectionException
281
+	 */
282
+	public function active_tickets(): array
283
+	{
284
+		return $this->tickets(
285
+			[
286
+				[
287
+					'TKT_end_date' => ['>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')],
288
+					'TKT_deleted'  => false,
289
+				],
290
+			]
291
+		);
292
+	}
293
+
294
+
295
+	/**
296
+	 * @return bool
297
+	 * @throws EE_Error
298
+	 */
299
+	public function additional_limit(): bool
300
+	{
301
+		return $this->get('EVT_additional_limit');
302
+	}
303
+
304
+
305
+	/**
306
+	 * @return bool
307
+	 * @throws EE_Error
308
+	 */
309
+	public function allow_overflow(): bool
310
+	{
311
+		return $this->get('EVT_allow_overflow');
312
+	}
313
+
314
+
315
+	/**
316
+	 * @return bool
317
+	 * @throws EE_Error
318
+	 */
319
+	public function created(): bool
320
+	{
321
+		return $this->get('EVT_created');
322
+	}
323
+
324
+
325
+	/**
326
+	 * @return bool
327
+	 * @throws EE_Error
328
+	 */
329
+	public function description(): bool
330
+	{
331
+		return $this->get('EVT_desc');
332
+	}
333
+
334
+
335
+	/**
336
+	 * Runs do_shortcode and wpautop on the description
337
+	 *
338
+	 * @return string of html
339
+	 * @throws EE_Error
340
+	 */
341
+	public function description_filtered(): string
342
+	{
343
+		return $this->get_pretty('EVT_desc');
344
+	}
345
+
346
+
347
+	/**
348
+	 * @return bool
349
+	 * @throws EE_Error
350
+	 */
351
+	public function display_description(): bool
352
+	{
353
+		return $this->get('EVT_display_desc');
354
+	}
355
+
356
+
357
+	/**
358
+	 * @return bool
359
+	 * @throws EE_Error
360
+	 */
361
+	public function display_ticket_selector(): bool
362
+	{
363
+		return (bool) $this->get('EVT_display_ticket_selector');
364
+	}
365
+
366
+
367
+	/**
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 */
371
+	public function external_url(): bool
372
+	{
373
+		return $this->get('EVT_external_URL');
374
+	}
375
+
376
+
377
+	/**
378
+	 * @return bool
379
+	 * @throws EE_Error
380
+	 */
381
+	public function member_only(): bool
382
+	{
383
+		return $this->get('EVT_member_only');
384
+	}
385
+
386
+
387
+	/**
388
+	 * @return bool
389
+	 * @throws EE_Error
390
+	 */
391
+	public function phone(): bool
392
+	{
393
+		return $this->get('EVT_phone');
394
+	}
395
+
396
+
397
+	/**
398
+	 * @return bool
399
+	 * @throws EE_Error
400
+	 */
401
+	public function modified(): bool
402
+	{
403
+		return $this->get('EVT_modified');
404
+	}
405
+
406
+
407
+	/**
408
+	 * @return bool
409
+	 * @throws EE_Error
410
+	 */
411
+	public function name(): bool
412
+	{
413
+		return $this->get('EVT_name');
414
+	}
415
+
416
+
417
+	/**
418
+	 * @return bool
419
+	 * @throws EE_Error
420
+	 */
421
+	public function order(): bool
422
+	{
423
+		return $this->get('EVT_order');
424
+	}
425
+
426
+
427
+	/**
428
+	 * @return bool|string
429
+	 * @throws EE_Error
430
+	 */
431
+	public function default_registration_status()
432
+	{
433
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
434
+		return ! empty($event_default_registration_status)
435
+			? $event_default_registration_status
436
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
437
+	}
438
+
439
+
440
+	/**
441
+	 * @param int  $num_words
442
+	 * @param string|null $more
443
+	 * @param bool $not_full_desc
444
+	 * @return bool|string
445
+	 * @throws EE_Error
446
+	 */
447
+	public function short_description(int $num_words = 55, string $more = null, bool $not_full_desc = false)
448
+	{
449
+		$short_desc = $this->get('EVT_short_desc');
450
+		if (! empty($short_desc) || $not_full_desc) {
451
+			return $short_desc;
452
+		}
453
+		$full_desc = $this->get('EVT_desc');
454
+		return wp_trim_words($full_desc, $num_words, $more);
455
+	}
456
+
457
+
458
+	/**
459
+	 * @return string
460
+	 * @throws EE_Error
461
+	 */
462
+	public function slug(): string
463
+	{
464
+		return $this->get('EVT_slug');
465
+	}
466
+
467
+
468
+	/**
469
+	 * @return string
470
+	 * @throws EE_Error
471
+	 */
472
+	public function timezone_string(): string
473
+	{
474
+		return $this->get('EVT_timezone_string');
475
+	}
476
+
477
+
478
+	/**
479
+	 * @return string
480
+	 * @throws EE_Error
481
+	 */
482
+	public function visible_on(): string
483
+	{
484
+		return $this->get('EVT_visible_on');
485
+	}
486
+
487
+
488
+	/**
489
+	 * @return int
490
+	 * @throws EE_Error
491
+	 */
492
+	public function wp_user(): int
493
+	{
494
+		return $this->get('EVT_wp_user');
495
+	}
496
+
497
+
498
+	/**
499
+	 * @return bool
500
+	 * @throws EE_Error
501
+	 */
502
+	public function donations(): bool
503
+	{
504
+		return $this->get('EVT_donations');
505
+	}
506
+
507
+
508
+	/**
509
+	 * @param $limit
510
+	 * @throws EE_Error
511
+	 * @throws ReflectionException
512
+	 */
513
+	public function set_additional_limit($limit)
514
+	{
515
+		$this->set('EVT_additional_limit', $limit);
516
+	}
517
+
518
+
519
+	/**
520
+	 * @param $created
521
+	 * @throws EE_Error
522
+	 * @throws ReflectionException
523
+	 */
524
+	public function set_created($created)
525
+	{
526
+		$this->set('EVT_created', $created);
527
+	}
528
+
529
+
530
+	/**
531
+	 * @param $desc
532
+	 * @throws EE_Error
533
+	 * @throws ReflectionException
534
+	 */
535
+	public function set_description($desc)
536
+	{
537
+		$this->set('EVT_desc', $desc);
538
+	}
539
+
540
+
541
+	/**
542
+	 * @param $display_desc
543
+	 * @throws EE_Error
544
+	 * @throws ReflectionException
545
+	 */
546
+	public function set_display_description($display_desc)
547
+	{
548
+		$this->set('EVT_display_desc', $display_desc);
549
+	}
550
+
551
+
552
+	/**
553
+	 * @param $display_ticket_selector
554
+	 * @throws EE_Error
555
+	 * @throws ReflectionException
556
+	 */
557
+	public function set_display_ticket_selector($display_ticket_selector)
558
+	{
559
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
560
+	}
561
+
562
+
563
+	/**
564
+	 * @param $external_url
565
+	 * @throws EE_Error
566
+	 * @throws ReflectionException
567
+	 */
568
+	public function set_external_url($external_url)
569
+	{
570
+		$this->set('EVT_external_URL', $external_url);
571
+	}
572
+
573
+
574
+	/**
575
+	 * @param $member_only
576
+	 * @throws EE_Error
577
+	 * @throws ReflectionException
578
+	 */
579
+	public function set_member_only($member_only)
580
+	{
581
+		$this->set('EVT_member_only', $member_only);
582
+	}
583
+
584
+
585
+	/**
586
+	 * @param $event_phone
587
+	 * @throws EE_Error
588
+	 * @throws ReflectionException
589
+	 */
590
+	public function set_event_phone($event_phone)
591
+	{
592
+		$this->set('EVT_phone', $event_phone);
593
+	}
594
+
595
+
596
+	/**
597
+	 * @param $modified
598
+	 * @throws EE_Error
599
+	 * @throws ReflectionException
600
+	 */
601
+	public function set_modified($modified)
602
+	{
603
+		$this->set('EVT_modified', $modified);
604
+	}
605
+
606
+
607
+	/**
608
+	 * @param $name
609
+	 * @throws EE_Error
610
+	 * @throws ReflectionException
611
+	 */
612
+	public function set_name($name)
613
+	{
614
+		$this->set('EVT_name', $name);
615
+	}
616
+
617
+
618
+	/**
619
+	 * @param $order
620
+	 * @throws EE_Error
621
+	 * @throws ReflectionException
622
+	 */
623
+	public function set_order($order)
624
+	{
625
+		$this->set('EVT_order', $order);
626
+	}
627
+
628
+
629
+	/**
630
+	 * @param $short_desc
631
+	 * @throws EE_Error
632
+	 * @throws ReflectionException
633
+	 */
634
+	public function set_short_description($short_desc)
635
+	{
636
+		$this->set('EVT_short_desc', $short_desc);
637
+	}
638
+
639
+
640
+	/**
641
+	 * @param $slug
642
+	 * @throws EE_Error
643
+	 * @throws ReflectionException
644
+	 */
645
+	public function set_slug($slug)
646
+	{
647
+		$this->set('EVT_slug', $slug);
648
+	}
649
+
650
+
651
+	/**
652
+	 * @param $timezone_string
653
+	 * @throws EE_Error
654
+	 * @throws ReflectionException
655
+	 */
656
+	public function set_timezone_string($timezone_string)
657
+	{
658
+		$this->set('EVT_timezone_string', $timezone_string);
659
+	}
660
+
661
+
662
+	/**
663
+	 * @param $visible_on
664
+	 * @throws EE_Error
665
+	 * @throws ReflectionException
666
+	 */
667
+	public function set_visible_on($visible_on)
668
+	{
669
+		$this->set('EVT_visible_on', $visible_on);
670
+	}
671
+
672
+
673
+	/**
674
+	 * @param $wp_user
675
+	 * @throws EE_Error
676
+	 * @throws ReflectionException
677
+	 */
678
+	public function set_wp_user($wp_user)
679
+	{
680
+		$this->set('EVT_wp_user', $wp_user);
681
+	}
682
+
683
+
684
+	/**
685
+	 * @param $default_registration_status
686
+	 * @throws EE_Error
687
+	 * @throws ReflectionException
688
+	 */
689
+	public function set_default_registration_status($default_registration_status)
690
+	{
691
+		$this->set('EVT_default_registration_status', $default_registration_status);
692
+	}
693
+
694
+
695
+	/**
696
+	 * @param $donations
697
+	 * @throws EE_Error
698
+	 * @throws ReflectionException
699
+	 */
700
+	public function set_donations($donations)
701
+	{
702
+		$this->set('EVT_donations', $donations);
703
+	}
704
+
705
+
706
+	/**
707
+	 * Adds a venue to this event
708
+	 *
709
+	 * @param EE_Venue /int $venue_id_or_obj
710
+	 * @return EE_Venue
711
+	 * @throws EE_Error
712
+	 * @throws ReflectionException
713
+	 */
714
+	public function add_venue($venue_id_or_obj): EE_Venue
715
+	{
716
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
717
+	}
718
+
719
+
720
+	/**
721
+	 * Removes a venue from the event
722
+	 *
723
+	 * @param EE_Venue /int $venue_id_or_obj
724
+	 * @return EE_Venue|null
725
+	 * @throws EE_Error
726
+	 * @throws ReflectionException
727
+	 */
728
+	public function remove_venue($venue_id_or_obj): ?EE_Venue
729
+	{
730
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
731
+	}
732
+
733
+
734
+	/**
735
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
736
+	 *
737
+	 * @param array $query_params @see
738
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
739
+	 * @return EE_Venue[]
740
+	 * @throws EE_Error
741
+	 * @throws ReflectionException
742
+	 */
743
+	public function venues(array $query_params = []): array
744
+	{
745
+		return $this->get_many_related('Venue', $query_params);
746
+	}
747
+
748
+
749
+	/**
750
+	 * check if event id is present and if event is published
751
+	 *
752
+	 * @return boolean true yes, false no
753
+	 * @throws EE_Error
754
+	 */
755
+	private function _has_ID_and_is_published(): bool
756
+	{
757
+		// first check if event id is present and not NULL,
758
+		// then check if this event is published (or any of the equivalent "published" statuses)
759
+		return
760
+			$this->ID() && $this->ID() !== null
761
+			&& (
762
+				$this->status() === 'publish'
763
+				|| $this->status() === EEM_Event::sold_out
764
+				|| $this->status() === EEM_Event::postponed
765
+				|| $this->status() === EEM_Event::cancelled
766
+			);
767
+	}
768
+
769
+
770
+	/**
771
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
772
+	 *
773
+	 * @return boolean true yes, false no
774
+	 * @throws EE_Error
775
+	 * @throws ReflectionException
776
+	 */
777
+	public function is_upcoming(): bool
778
+	{
779
+		// check if event id is present and if this event is published
780
+		if ($this->is_inactive()) {
781
+			return false;
782
+		}
783
+		// set initial value
784
+		$upcoming = false;
785
+		// next let's get all datetimes and loop through them
786
+		$datetimes = $this->datetimes_in_chronological_order();
787
+		foreach ($datetimes as $datetime) {
788
+			if ($datetime instanceof EE_Datetime) {
789
+				// if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
790
+				if ($datetime->is_expired()) {
791
+					continue;
792
+				}
793
+				// if this dtt is active then we return false.
794
+				if ($datetime->is_active()) {
795
+					return false;
796
+				}
797
+				// otherwise let's check upcoming status
798
+				$upcoming = $datetime->is_upcoming();
799
+			}
800
+		}
801
+		return $upcoming;
802
+	}
803
+
804
+
805
+	/**
806
+	 * @return bool
807
+	 * @throws EE_Error
808
+	 * @throws ReflectionException
809
+	 */
810
+	public function is_active(): bool
811
+	{
812
+		// check if event id is present and if this event is published
813
+		if ($this->is_inactive()) {
814
+			return false;
815
+		}
816
+		// set initial value
817
+		$active = false;
818
+		// next let's get all datetimes and loop through them
819
+		$datetimes = $this->datetimes_in_chronological_order();
820
+		foreach ($datetimes as $datetime) {
821
+			if ($datetime instanceof EE_Datetime) {
822
+				// if this dtt is expired then we continue cause one of the other datetimes might be active.
823
+				if ($datetime->is_expired()) {
824
+					continue;
825
+				}
826
+				// if this dtt is upcoming then we return false.
827
+				if ($datetime->is_upcoming()) {
828
+					return false;
829
+				}
830
+				// otherwise let's check active status
831
+				$active = $datetime->is_active();
832
+			}
833
+		}
834
+		return $active;
835
+	}
836
+
837
+
838
+	/**
839
+	 * @return bool
840
+	 * @throws EE_Error
841
+	 * @throws ReflectionException
842
+	 */
843
+	public function is_expired(): bool
844
+	{
845
+		// check if event id is present and if this event is published
846
+		if ($this->is_inactive()) {
847
+			return false;
848
+		}
849
+		// set initial value
850
+		$expired = false;
851
+		// first let's get all datetimes and loop through them
852
+		$datetimes = $this->datetimes_in_chronological_order();
853
+		foreach ($datetimes as $datetime) {
854
+			if ($datetime instanceof EE_Datetime) {
855
+				// if this dtt is upcoming or active then we return false.
856
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
857
+					return false;
858
+				}
859
+				// otherwise let's check active status
860
+				$expired = $datetime->is_expired();
861
+			}
862
+		}
863
+		return $expired;
864
+	}
865
+
866
+
867
+	/**
868
+	 * @return bool
869
+	 * @throws EE_Error
870
+	 */
871
+	public function is_inactive(): bool
872
+	{
873
+		// check if event id is present and if this event is published
874
+		if ($this->_has_ID_and_is_published()) {
875
+			return false;
876
+		}
877
+		return true;
878
+	}
879
+
880
+
881
+	/**
882
+	 * calculate spaces remaining based on "saleable" tickets
883
+	 *
884
+	 * @param array $tickets
885
+	 * @param bool  $filtered
886
+	 * @return int|float
887
+	 * @throws EE_Error
888
+	 * @throws DomainException
889
+	 * @throws UnexpectedEntityException
890
+	 */
891
+	public function spaces_remaining(array $tickets = [], bool $filtered = true)
892
+	{
893
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
894
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
895
+		return $filtered
896
+			? apply_filters(
897
+				'FHEE_EE_Event__spaces_remaining',
898
+				$spaces_remaining,
899
+				$this,
900
+				$tickets
901
+			)
902
+			: $spaces_remaining;
903
+	}
904
+
905
+
906
+	/**
907
+	 *    perform_sold_out_status_check
908
+	 *    checks all of this event's datetime reg_limit - sold values to determine if ANY datetimes have spaces
909
+	 *    available... if NOT, then the event status will get toggled to 'sold_out'
910
+	 *
911
+	 * @return bool    return the ACTUAL sold out state.
912
+	 * @throws EE_Error
913
+	 * @throws DomainException
914
+	 * @throws UnexpectedEntityException
915
+	 * @throws ReflectionException
916
+	 */
917
+	public function perform_sold_out_status_check(): bool
918
+	{
919
+		// get all tickets
920
+		$tickets     = $this->tickets(
921
+			[
922
+				'default_where_conditions' => 'none',
923
+				'order_by'                 => ['TKT_qty' => 'ASC'],
924
+			]
925
+		);
926
+		$all_expired = true;
927
+		foreach ($tickets as $ticket) {
928
+			if (! $ticket->is_expired()) {
929
+				$all_expired = false;
930
+				break;
931
+			}
932
+		}
933
+		// if all the tickets are just expired, then don't update the event status to sold out
934
+		if ($all_expired) {
935
+			return true;
936
+		}
937
+		$spaces_remaining = $this->spaces_remaining($tickets);
938
+		if ($spaces_remaining < 1) {
939
+			if ($this->status() !== EEM_Event::post_status_private) {
940
+				$this->set_status(EEM_Event::sold_out);
941
+				$this->save();
942
+			}
943
+			$sold_out = true;
944
+		} else {
945
+			$sold_out = false;
946
+			// was event previously marked as sold out ?
947
+			if ($this->status() === EEM_Event::sold_out) {
948
+				// revert status to previous value, if it was set
949
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
950
+				if ($previous_event_status) {
951
+					$this->set_status($previous_event_status);
952
+					$this->save();
953
+				}
954
+			}
955
+		}
956
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
957
+		return $sold_out;
958
+	}
959
+
960
+
961
+	/**
962
+	 * This returns the total remaining spaces for sale on this event.
963
+	 *
964
+	 * @return float|int
965
+	 * @throws EE_Error
966
+	 * @throws DomainException
967
+	 * @throws UnexpectedEntityException
968
+	 * @uses EE_Event::total_available_spaces()
969
+	 */
970
+	public function spaces_remaining_for_sale()
971
+	{
972
+		return $this->total_available_spaces(true);
973
+	}
974
+
975
+
976
+	/**
977
+	 * This returns the total spaces available for an event
978
+	 * while considering all the qtys on the tickets and the reg limits
979
+	 * on the datetimes attached to this event.
980
+	 *
981
+	 * @param bool $consider_sold   Whether to consider any tickets that have already sold in our calculation.
982
+	 *                              If this is false, then we return the most tickets that could ever be sold
983
+	 *                              for this event with the datetime and tickets setup on the event under optimal
984
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
985
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
986
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
987
+	 *                              sold out, the more accurate the "live" total is.
988
+	 * @return float|int
989
+	 * @throws EE_Error
990
+	 * @throws DomainException
991
+	 * @throws UnexpectedEntityException
992
+	 */
993
+	public function total_available_spaces(bool $consider_sold = false)
994
+	{
995
+		$spaces_available = $consider_sold
996
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
997
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
998
+		return apply_filters(
999
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
1000
+			$spaces_available,
1001
+			$this,
1002
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
1003
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
1004
+		);
1005
+	}
1006
+
1007
+
1008
+	/**
1009
+	 * Checks if the event is set to sold out
1010
+	 *
1011
+	 * @param bool $actual  whether or not to perform calculations to not only figure the
1012
+	 *                      actual status but also to flip the status if necessary to sold
1013
+	 *                      out If false, we just check the existing status of the event
1014
+	 * @return boolean
1015
+	 * @throws EE_Error
1016
+	 * @throws ReflectionException
1017
+	 */
1018
+	public function is_sold_out(bool $actual = false): bool
1019
+	{
1020
+		if (! $actual) {
1021
+			return $this->status() === EEM_Event::sold_out;
1022
+		}
1023
+		return $this->perform_sold_out_status_check();
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * Checks if the event is marked as postponed
1029
+	 *
1030
+	 * @return boolean
1031
+	 * @throws EE_Error
1032
+	 * @throws EE_Error
1033
+	 */
1034
+	public function is_postponed(): bool
1035
+	{
1036
+		return $this->status() === EEM_Event::postponed;
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * Checks if the event is marked as cancelled
1042
+	 *
1043
+	 * @return boolean
1044
+	 * @throws EE_Error
1045
+	 * @throws EE_Error
1046
+	 */
1047
+	public function is_cancelled(): bool
1048
+	{
1049
+		return $this->status() === EEM_Event::cancelled;
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1055
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1056
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1057
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1058
+	 * the event is considered expired.
1059
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1060
+	 * status set on the EVENT when it is not published and thus is done
1061
+	 *
1062
+	 * @param bool $reset
1063
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1064
+	 * @throws EE_Error
1065
+	 * @throws ReflectionException
1066
+	 */
1067
+	public function get_active_status(bool $reset = false)
1068
+	{
1069
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1070
+		if (! empty($this->_active_status) && ! $reset) {
1071
+			return $this->_active_status;
1072
+		}
1073
+		// first check if event id is present on this object
1074
+		if (! $this->ID()) {
1075
+			return false;
1076
+		}
1077
+		$where_params_for_event = [['EVT_ID' => $this->ID()]];
1078
+		// if event is published:
1079
+		if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1080
+			// active?
1081
+			if (
1082
+				EEM_Datetime::instance()->get_datetime_count_for_status(
1083
+					EE_Datetime::active,
1084
+					$where_params_for_event
1085
+				) > 0
1086
+			) {
1087
+				$this->_active_status = EE_Datetime::active;
1088
+			} else {
1089
+				// upcoming?
1090
+				if (
1091
+					EEM_Datetime::instance()->get_datetime_count_for_status(
1092
+						EE_Datetime::upcoming,
1093
+						$where_params_for_event
1094
+					) > 0
1095
+				) {
1096
+					$this->_active_status = EE_Datetime::upcoming;
1097
+				} else {
1098
+					// expired?
1099
+					if (
1100
+						EEM_Datetime::instance()->get_datetime_count_for_status(
1101
+							EE_Datetime::expired,
1102
+							$where_params_for_event
1103
+						) > 0
1104
+					) {
1105
+						$this->_active_status = EE_Datetime::expired;
1106
+					} else {
1107
+						// it would be odd if things make it this far because it basically means there are no datetime's
1108
+						// attached to the event.  So in this case it will just be considered inactive.
1109
+						$this->_active_status = EE_Datetime::inactive;
1110
+					}
1111
+				}
1112
+			}
1113
+		} else {
1114
+			// the event is not published, so let's just set it's active status according to its' post status
1115
+			switch ($this->status()) {
1116
+				case EEM_Event::sold_out:
1117
+					$this->_active_status = EE_Datetime::sold_out;
1118
+					break;
1119
+				case EEM_Event::cancelled:
1120
+					$this->_active_status = EE_Datetime::cancelled;
1121
+					break;
1122
+				case EEM_Event::postponed:
1123
+					$this->_active_status = EE_Datetime::postponed;
1124
+					break;
1125
+				default:
1126
+					$this->_active_status = EE_Datetime::inactive;
1127
+			}
1128
+		}
1129
+		return $this->_active_status;
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 *    pretty_active_status
1135
+	 *
1136
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1137
+	 * @return string string
1138
+	 * @throws EE_Error
1139
+	 * @throws ReflectionException
1140
+	 */
1141
+	public function pretty_active_status(bool $echo = true): string
1142
+	{
1143
+		$active_status = $this->get_active_status();
1144
+		$status        = '<span class="ee-status event-active-status-'
1145
+						 . $active_status
1146
+						 . '">'
1147
+						 . EEH_Template::pretty_status($active_status, false, 'sentence')
1148
+						 . '</span>';
1149
+		if ($echo) {
1150
+			echo $status;
1151
+			return '';
1152
+		}
1153
+		return $status;
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * @return bool|int
1159
+	 * @throws EE_Error
1160
+	 * @throws ReflectionException
1161
+	 */
1162
+	public function get_number_of_tickets_sold()
1163
+	{
1164
+		$tkt_sold = 0;
1165
+		if (! $this->ID()) {
1166
+			return 0;
1167
+		}
1168
+		$datetimes = $this->datetimes();
1169
+		foreach ($datetimes as $datetime) {
1170
+			if ($datetime instanceof EE_Datetime) {
1171
+				$tkt_sold += $datetime->sold();
1172
+			}
1173
+		}
1174
+		return $tkt_sold;
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * This just returns a count of all the registrations for this event
1180
+	 *
1181
+	 * @return int
1182
+	 * @throws EE_Error
1183
+	 * @throws ReflectionException
1184
+	 */
1185
+	public function get_count_of_all_registrations(): int
1186
+	{
1187
+		return EEM_Event::instance()->count_related($this, 'Registration');
1188
+	}
1189
+
1190
+
1191
+	/**
1192
+	 * This returns the ticket with the earliest start time that is
1193
+	 * available for this event (across all datetimes attached to the event)
1194
+	 *
1195
+	 * @return EE_Ticket|null
1196
+	 * @throws EE_Error
1197
+	 * @throws ReflectionException
1198
+	 */
1199
+	public function get_ticket_with_earliest_start_time(): ?EE_Ticket
1200
+	{
1201
+		$where['Datetime.EVT_ID'] = $this->ID();
1202
+		$query_params             = [$where, 'order_by' => ['TKT_start_date' => 'ASC']];
1203
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * This returns the ticket with the latest end time that is available
1209
+	 * for this event (across all datetimes attached to the event)
1210
+	 *
1211
+	 * @return EE_Ticket|null
1212
+	 * @throws EE_Error
1213
+	 * @throws ReflectionException
1214
+	 */
1215
+	public function get_ticket_with_latest_end_time(): ?EE_Ticket
1216
+	{
1217
+		$where['Datetime.EVT_ID'] = $this->ID();
1218
+		$query_params             = [$where, 'order_by' => ['TKT_end_date' => 'DESC']];
1219
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * This returns the number of different ticket types currently on sale for this event.
1225
+	 *
1226
+	 * @return int
1227
+	 * @throws EE_Error
1228
+	 * @throws ReflectionException
1229
+	 */
1230
+	public function countTicketsOnSale(): int
1231
+	{
1232
+		$where = [
1233
+			'Datetime.EVT_ID' => $this->ID(),
1234
+			'TKT_start_date'  => ['<', time()],
1235
+			'TKT_end_date'    => ['>', time()],
1236
+		];
1237
+		return EEM_Ticket::instance()->count([$where]);
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 * This returns whether there are any tickets on sale for this event.
1243
+	 *
1244
+	 * @return bool true = YES tickets on sale.
1245
+	 * @throws EE_Error
1246
+	 * @throws ReflectionException
1247
+	 */
1248
+	public function tickets_on_sale(): bool
1249
+	{
1250
+		return $this->countTicketsOnSale() > 0;
1251
+	}
1252
+
1253
+
1254
+	/**
1255
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1256
+	 * to check for an external URL first
1257
+	 *
1258
+	 * @return string
1259
+	 * @throws EE_Error
1260
+	 */
1261
+	public function get_permalink(): string
1262
+	{
1263
+		if ($this->external_url()) {
1264
+			return $this->external_url();
1265
+		}
1266
+		return parent::get_permalink();
1267
+	}
1268
+
1269
+
1270
+	/**
1271
+	 * Gets the first term for 'espresso_event_categories' we can find
1272
+	 *
1273
+	 * @param array $query_params @see
1274
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1275
+	 * @return EE_Term|null
1276
+	 * @throws EE_Error
1277
+	 * @throws ReflectionException
1278
+	 */
1279
+	public function first_event_category(array $query_params = []): ?EE_Term
1280
+	{
1281
+		$query_params[0]['Term_Taxonomy.taxonomy']     = 'espresso_event_categories';
1282
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1283
+		return EEM_Term::instance()->get_one($query_params);
1284
+	}
1285
+
1286
+
1287
+	/**
1288
+	 * Gets all terms for 'espresso_event_categories' we can find
1289
+	 *
1290
+	 * @param array $query_params
1291
+	 * @return EE_Term[]
1292
+	 * @throws EE_Error
1293
+	 * @throws ReflectionException
1294
+	 */
1295
+	public function get_all_event_categories(array $query_params = []): array
1296
+	{
1297
+		$query_params[0]['Term_Taxonomy.taxonomy']     = 'espresso_event_categories';
1298
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1299
+		return EEM_Term::instance()->get_all($query_params);
1300
+	}
1301
+
1302
+
1303
+	/**
1304
+	 * Adds a question group to this event
1305
+	 *
1306
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1307
+	 * @param bool                  $for_primary if true, the question group will be added for the primary
1308
+	 *                                           registrant, if false will be added for others. default: false
1309
+	 * @return EE_Question_Group
1310
+	 * @throws EE_Error
1311
+	 * @throws InvalidArgumentException
1312
+	 * @throws InvalidDataTypeException
1313
+	 * @throws InvalidInterfaceException
1314
+	 * @throws ReflectionException
1315
+	 */
1316
+	public function add_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group
1317
+	{
1318
+		// If the row already exists, it will be updated. If it doesn't, it will be inserted.
1319
+		// That's in EE_HABTM_Relation::add_relation_to().
1320
+		return $this->_add_relation_to(
1321
+			$question_group_id_or_obj,
1322
+			'Question_Group',
1323
+			[
1324
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true,
1325
+			]
1326
+		);
1327
+	}
1328
+
1329
+
1330
+	/**
1331
+	 * Removes a question group from the event
1332
+	 *
1333
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1334
+	 * @param bool                  $for_primary if true, the question group will be removed from the primary
1335
+	 *                                           registrant, if false will be removed from others. default: false
1336
+	 * @return EE_Question_Group
1337
+	 * @throws EE_Error
1338
+	 * @throws InvalidArgumentException
1339
+	 * @throws ReflectionException
1340
+	 * @throws InvalidDataTypeException
1341
+	 * @throws InvalidInterfaceException
1342
+	 */
1343
+	public function remove_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group
1344
+	{
1345
+		// If the question group is used for the other type (primary or additional)
1346
+		// then just update it. If not, delete it outright.
1347
+		$existing_relation = $this->get_first_related(
1348
+			'Event_Question_Group',
1349
+			[
1350
+				[
1351
+					'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj),
1352
+				],
1353
+			]
1354
+		);
1355
+		$field_to_update   = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1356
+		$other_field       = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1357
+		if ($existing_relation->get($other_field) === false) {
1358
+			// Delete it. It's now no longer for primary or additional question groups.
1359
+			return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1360
+		}
1361
+		// Just update it. They'll still use this question group for the other category
1362
+		$existing_relation->save(
1363
+			[
1364
+				$field_to_update => false,
1365
+			]
1366
+		);
1367
+		return $question_group_id_or_obj;
1368
+	}
1369
+
1370
+
1371
+	/**
1372
+	 * Gets all the question groups, ordering them by QSG_order ascending
1373
+	 *
1374
+	 * @param array $query_params @see
1375
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1376
+	 * @return EE_Question_Group[]
1377
+	 * @throws EE_Error
1378
+	 * @throws ReflectionException
1379
+	 */
1380
+	public function question_groups(array $query_params = []): array
1381
+	{
1382
+		$query_params = ! empty($query_params)
1383
+			? $query_params
1384
+			: ['order_by' => ['QSG_order' => 'ASC']];
1385
+		return $this->get_many_related('Question_Group', $query_params);
1386
+	}
1387
+
1388
+
1389
+	/**
1390
+	 * Implementation for EEI_Has_Icon interface method.
1391
+	 *
1392
+	 * @return string
1393
+	 * @see EEI_Visual_Representation for comments
1394
+	 */
1395
+	public function get_icon(): string
1396
+	{
1397
+		return '<span class="dashicons dashicons-flag"></span>';
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * Implementation for EEI_Admin_Links interface method.
1403
+	 *
1404
+	 * @return string
1405
+	 * @throws EE_Error
1406
+	 * @see EEI_Admin_Links for comments
1407
+	 */
1408
+	public function get_admin_details_link(): string
1409
+	{
1410
+		return $this->get_admin_edit_link();
1411
+	}
1412
+
1413
+
1414
+	/**
1415
+	 * Implementation for EEI_Admin_Links interface method.
1416
+	 *
1417
+	 * @return string
1418
+	 * @throws EE_Error
1419
+	 * @see EEI_Admin_Links for comments
1420
+	 */
1421
+	public function get_admin_edit_link(): string
1422
+	{
1423
+		return EEH_URL::add_query_args_and_nonce(
1424
+			[
1425
+				'page'   => 'espresso_events',
1426
+				'action' => 'edit',
1427
+				'post'   => $this->ID(),
1428
+			],
1429
+			admin_url('admin.php')
1430
+		);
1431
+	}
1432
+
1433
+
1434
+	/**
1435
+	 * Implementation for EEI_Admin_Links interface method.
1436
+	 *
1437
+	 * @return string
1438
+	 * @see EEI_Admin_Links for comments
1439
+	 */
1440
+	public function get_admin_settings_link(): string
1441
+	{
1442
+		return EEH_URL::add_query_args_and_nonce(
1443
+			[
1444
+				'page'   => 'espresso_events',
1445
+				'action' => 'default_event_settings',
1446
+			],
1447
+			admin_url('admin.php')
1448
+		);
1449
+	}
1450
+
1451
+
1452
+	/**
1453
+	 * Implementation for EEI_Admin_Links interface method.
1454
+	 *
1455
+	 * @return string
1456
+	 * @see EEI_Admin_Links for comments
1457
+	 */
1458
+	public function get_admin_overview_link(): string
1459
+	{
1460
+		return EEH_URL::add_query_args_and_nonce(
1461
+			[
1462
+				'page'   => 'espresso_events',
1463
+				'action' => 'default',
1464
+			],
1465
+			admin_url('admin.php')
1466
+		);
1467
+	}
1468 1468
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
      */
79 79
     public function getAvailableSpacesCalculator(): EventSpacesCalculator
80 80
     {
81
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
81
+        if ( ! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
82 82
             $this->available_spaces_calculator = new EventSpacesCalculator($this);
83 83
         }
84 84
         return $this->available_spaces_calculator;
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
         bool $try_to_exclude_expired = true,
229 229
         bool $try_to_exclude_deleted = true
230 230
     ): EE_Datetime {
231
-        if (! empty($this->_Primary_Datetime)) {
231
+        if ( ! empty($this->_Primary_Datetime)) {
232 232
             return $this->_Primary_Datetime;
233 233
         }
234 234
         $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
     {
254 254
         // first get all datetimes
255 255
         $datetimes = $this->datetimes_ordered();
256
-        if (! $datetimes) {
256
+        if ( ! $datetimes) {
257 257
             return [];
258 258
         }
259 259
         $datetime_ids = [];
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
     public function short_description(int $num_words = 55, string $more = null, bool $not_full_desc = false)
448 448
     {
449 449
         $short_desc = $this->get('EVT_short_desc');
450
-        if (! empty($short_desc) || $not_full_desc) {
450
+        if ( ! empty($short_desc) || $not_full_desc) {
451 451
             return $short_desc;
452 452
         }
453 453
         $full_desc = $this->get('EVT_desc');
@@ -917,7 +917,7 @@  discard block
 block discarded – undo
917 917
     public function perform_sold_out_status_check(): bool
918 918
     {
919 919
         // get all tickets
920
-        $tickets     = $this->tickets(
920
+        $tickets = $this->tickets(
921 921
             [
922 922
                 'default_where_conditions' => 'none',
923 923
                 'order_by'                 => ['TKT_qty' => 'ASC'],
@@ -925,7 +925,7 @@  discard block
 block discarded – undo
925 925
         );
926 926
         $all_expired = true;
927 927
         foreach ($tickets as $ticket) {
928
-            if (! $ticket->is_expired()) {
928
+            if ( ! $ticket->is_expired()) {
929 929
                 $all_expired = false;
930 930
                 break;
931 931
             }
@@ -1017,7 +1017,7 @@  discard block
 block discarded – undo
1017 1017
      */
1018 1018
     public function is_sold_out(bool $actual = false): bool
1019 1019
     {
1020
-        if (! $actual) {
1020
+        if ( ! $actual) {
1021 1021
             return $this->status() === EEM_Event::sold_out;
1022 1022
         }
1023 1023
         return $this->perform_sold_out_status_check();
@@ -1067,11 +1067,11 @@  discard block
 block discarded – undo
1067 1067
     public function get_active_status(bool $reset = false)
1068 1068
     {
1069 1069
         // if the active status has already been set, then just use that value (unless we are resetting it)
1070
-        if (! empty($this->_active_status) && ! $reset) {
1070
+        if ( ! empty($this->_active_status) && ! $reset) {
1071 1071
             return $this->_active_status;
1072 1072
         }
1073 1073
         // first check if event id is present on this object
1074
-        if (! $this->ID()) {
1074
+        if ( ! $this->ID()) {
1075 1075
             return false;
1076 1076
         }
1077 1077
         $where_params_for_event = [['EVT_ID' => $this->ID()]];
@@ -1162,7 +1162,7 @@  discard block
 block discarded – undo
1162 1162
     public function get_number_of_tickets_sold()
1163 1163
     {
1164 1164
         $tkt_sold = 0;
1165
-        if (! $this->ID()) {
1165
+        if ( ! $this->ID()) {
1166 1166
             return 0;
1167 1167
         }
1168 1168
         $datetimes = $this->datetimes();
@@ -1353,7 +1353,7 @@  discard block
 block discarded – undo
1353 1353
             ]
1354 1354
         );
1355 1355
         $field_to_update   = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1356
-        $other_field       = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1356
+        $other_field       = EEM_Event_Question_Group::instance()->fieldNameForContext( ! $for_primary);
1357 1357
         if ($existing_relation->get($other_field) === false) {
1358 1358
             // Delete it. It's now no longer for primary or additional question groups.
1359 1359
             return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
Please login to merge, or discard this patch.
core/db_models/EEM_Answer.model.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
      * on the attendee or in the answer table. This function finds its value regardless)
95 95
      *
96 96
      * @param EE_Registration $registration
97
-     * @param int|string      $question_id
97
+     * @param integer      $question_id
98 98
      * @param bool            $pretty_answer whether to call 'pretty_value' or just 'value'
99 99
      * @return string
100 100
      * @throws EE_Error
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
      * Gets the EE_Answer object for the question for this registration (if it exists)
126 126
      *
127 127
      * @param EE_Registration $registration
128
-     * @param int|null        $question_id
128
+     * @param integer        $question_id
129 129
      * @return EE_Answer
130 130
      * @throws EE_Error
131 131
      * @throws ReflectionException
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
      * Gets the string answer to the question for this registration's attendee
147 147
      *
148 148
      * @param EE_Registration $registration
149
-     * @param int|string      $question_system_id if an INT this is understood to be the question's ID; if a string
149
+     * @param integer      $question_system_id if an INT this is understood to be the question's ID; if a string
150 150
      *                                            then it should be its QST_system value. Passing in the QST_system
151 151
      *                                            value is more efficient
152 152
      * @param boolean         $pretty_answer
Please login to merge, or discard this patch.
Indentation   +200 added lines, -200 removed lines patch added patch discarded remove patch
@@ -10,213 +10,213 @@
 block discarded – undo
10 10
 class EEM_Answer extends EEM_Base
11 11
 {
12 12
 
13
-    /**
14
-     * private instance of the EEM_Answer object
15
-     *
16
-     * @var EEM_Answer
17
-     */
18
-    protected static $_instance;
13
+	/**
14
+	 * private instance of the EEM_Answer object
15
+	 *
16
+	 * @var EEM_Answer
17
+	 */
18
+	protected static $_instance;
19 19
 
20
-    /**
21
-     * Mapping from system question ids to attendee field names
22
-     *
23
-     * @var array
24
-     * @deprecated since version 4.8.8
25
-     */
26
-    protected $_question_id_to_att_field_map
27
-        = [
28
-            EEM_Attendee::fname_question_id    => 'ATT_fname',
29
-            EEM_Attendee::lname_question_id    => 'ATT_lname',
30
-            EEM_Attendee::email_question_id    => 'ATT_email',
31
-            EEM_Attendee::address_question_id  => 'ATT_address',
32
-            EEM_Attendee::address2_question_id => 'ATT_address2',
33
-            EEM_Attendee::city_question_id     => 'ATT_city',
34
-            EEM_Attendee::state_question_id    => 'STA_ID',
35
-            EEM_Attendee::country_question_id  => 'CNT_ISO',
36
-            EEM_Attendee::zip_question_id      => 'ATT_zip',
37
-            EEM_Attendee::phone_question_id    => 'ATT_phone',
38
-        ];
20
+	/**
21
+	 * Mapping from system question ids to attendee field names
22
+	 *
23
+	 * @var array
24
+	 * @deprecated since version 4.8.8
25
+	 */
26
+	protected $_question_id_to_att_field_map
27
+		= [
28
+			EEM_Attendee::fname_question_id    => 'ATT_fname',
29
+			EEM_Attendee::lname_question_id    => 'ATT_lname',
30
+			EEM_Attendee::email_question_id    => 'ATT_email',
31
+			EEM_Attendee::address_question_id  => 'ATT_address',
32
+			EEM_Attendee::address2_question_id => 'ATT_address2',
33
+			EEM_Attendee::city_question_id     => 'ATT_city',
34
+			EEM_Attendee::state_question_id    => 'STA_ID',
35
+			EEM_Attendee::country_question_id  => 'CNT_ISO',
36
+			EEM_Attendee::zip_question_id      => 'ATT_zip',
37
+			EEM_Attendee::phone_question_id    => 'ATT_phone',
38
+		];
39 39
 
40 40
 
41
-    /**
42
-     *  constructor
43
-     *
44
-     * @param string $timezone
45
-     * @throws EE_Error
46
-     */
47
-    protected function __construct(string $timezone = '')
48
-    {
49
-        $this->singular_item           = esc_html__('Answer', 'event_espresso');
50
-        $this->plural_item             = esc_html__('Answers', 'event_espresso');
51
-        $this->_tables                 = [
52
-            'Answer' => new EE_Primary_Table('esp_answer', 'ANS_ID'),
53
-        ];
54
-        $this->_fields                 = [
55
-            'Answer' => [
56
-                'ANS_ID'    => new EE_Primary_Key_Int_Field(
57
-                    'ANS_ID',
58
-                    esc_html__('Answer ID', 'event_espresso')
59
-                ),
60
-                'REG_ID'    => new EE_Foreign_Key_Int_Field(
61
-                    'REG_ID',
62
-                    esc_html__('Registration ID', 'event_espresso'),
63
-                    false,
64
-                    0,
65
-                    'Registration'
66
-                ),
67
-                'QST_ID'    => new EE_Foreign_Key_Int_Field(
68
-                    'QST_ID',
69
-                    esc_html__('Question ID', 'event_espresso'),
70
-                    false,
71
-                    0,
72
-                    'Question'
73
-                ),
74
-                'ANS_value' => new EE_Maybe_Serialized_Simple_HTML_Field(
75
-                    'ANS_value',
76
-                    esc_html__('Answer Value', 'event_espresso'),
77
-                    false,
78
-                    ''
79
-                ),
80
-            ],
81
-        ];
82
-        $this->_model_relations        = [
83
-            'Registration' => new EE_Belongs_To_Relation(),
84
-            'Question'     => new EE_Belongs_To_Relation(),
85
-        ];
86
-        $this->_model_chain_to_wp_user = 'Registration.Event';
87
-        $this->_caps_slug              = 'registrations';
88
-        parent::__construct($timezone);
89
-    }
41
+	/**
42
+	 *  constructor
43
+	 *
44
+	 * @param string $timezone
45
+	 * @throws EE_Error
46
+	 */
47
+	protected function __construct(string $timezone = '')
48
+	{
49
+		$this->singular_item           = esc_html__('Answer', 'event_espresso');
50
+		$this->plural_item             = esc_html__('Answers', 'event_espresso');
51
+		$this->_tables                 = [
52
+			'Answer' => new EE_Primary_Table('esp_answer', 'ANS_ID'),
53
+		];
54
+		$this->_fields                 = [
55
+			'Answer' => [
56
+				'ANS_ID'    => new EE_Primary_Key_Int_Field(
57
+					'ANS_ID',
58
+					esc_html__('Answer ID', 'event_espresso')
59
+				),
60
+				'REG_ID'    => new EE_Foreign_Key_Int_Field(
61
+					'REG_ID',
62
+					esc_html__('Registration ID', 'event_espresso'),
63
+					false,
64
+					0,
65
+					'Registration'
66
+				),
67
+				'QST_ID'    => new EE_Foreign_Key_Int_Field(
68
+					'QST_ID',
69
+					esc_html__('Question ID', 'event_espresso'),
70
+					false,
71
+					0,
72
+					'Question'
73
+				),
74
+				'ANS_value' => new EE_Maybe_Serialized_Simple_HTML_Field(
75
+					'ANS_value',
76
+					esc_html__('Answer Value', 'event_espresso'),
77
+					false,
78
+					''
79
+				),
80
+			],
81
+		];
82
+		$this->_model_relations        = [
83
+			'Registration' => new EE_Belongs_To_Relation(),
84
+			'Question'     => new EE_Belongs_To_Relation(),
85
+		];
86
+		$this->_model_chain_to_wp_user = 'Registration.Event';
87
+		$this->_caps_slug              = 'registrations';
88
+		parent::__construct($timezone);
89
+	}
90 90
 
91 91
 
92
-    /**
93
-     * Gets the string answer to the question for this registration (it could either be stored
94
-     * on the attendee or in the answer table. This function finds its value regardless)
95
-     *
96
-     * @param EE_Registration $registration
97
-     * @param int|string      $question_id
98
-     * @param bool            $pretty_answer whether to call 'pretty_value' or just 'value'
99
-     * @return string
100
-     * @throws EE_Error
101
-     * @throws ReflectionException
102
-     */
103
-    public function get_answer_value_to_question(
104
-        EE_Registration $registration,
105
-        $question_id = 0,
106
-        bool $pretty_answer = false
107
-    ): string {
108
-        $value = $this->get_attendee_property_answer_value($registration, $question_id, $pretty_answer);
109
-        if ($value === null) {
110
-            $answer_obj = $this->get_registration_question_answer_object($registration, $question_id);
111
-            if ($answer_obj instanceof EE_Answer) {
112
-                $value = $pretty_answer ? $answer_obj->pretty_value() : $answer_obj->value();
113
-            }
114
-        }
115
-        return apply_filters(
116
-            'FHEE__EEM_Answer__get_answer_value_to_question__answer_value',
117
-            $value,
118
-            $registration,
119
-            $question_id
120
-        );
121
-    }
92
+	/**
93
+	 * Gets the string answer to the question for this registration (it could either be stored
94
+	 * on the attendee or in the answer table. This function finds its value regardless)
95
+	 *
96
+	 * @param EE_Registration $registration
97
+	 * @param int|string      $question_id
98
+	 * @param bool            $pretty_answer whether to call 'pretty_value' or just 'value'
99
+	 * @return string
100
+	 * @throws EE_Error
101
+	 * @throws ReflectionException
102
+	 */
103
+	public function get_answer_value_to_question(
104
+		EE_Registration $registration,
105
+		$question_id = 0,
106
+		bool $pretty_answer = false
107
+	): string {
108
+		$value = $this->get_attendee_property_answer_value($registration, $question_id, $pretty_answer);
109
+		if ($value === null) {
110
+			$answer_obj = $this->get_registration_question_answer_object($registration, $question_id);
111
+			if ($answer_obj instanceof EE_Answer) {
112
+				$value = $pretty_answer ? $answer_obj->pretty_value() : $answer_obj->value();
113
+			}
114
+		}
115
+		return apply_filters(
116
+			'FHEE__EEM_Answer__get_answer_value_to_question__answer_value',
117
+			$value,
118
+			$registration,
119
+			$question_id
120
+		);
121
+	}
122 122
 
123 123
 
124
-    /**
125
-     * Gets the EE_Answer object for the question for this registration (if it exists)
126
-     *
127
-     * @param EE_Registration $registration
128
-     * @param int|null        $question_id
129
-     * @return EE_Answer
130
-     * @throws EE_Error
131
-     * @throws ReflectionException
132
-     */
133
-    public function get_registration_question_answer_object(EE_Registration $registration, int $question_id = 0):
134
-    EE_Answer {
135
-        $answer_obj = $this->get_one([['QST_ID' => $question_id, 'REG_ID' => $registration->ID()]]);
136
-        return apply_filters(
137
-            'FHEE__EEM_Answer__get_registration_question_answer_object__answer_obj',
138
-            $answer_obj,
139
-            $registration,
140
-            $question_id
141
-        );
142
-    }
124
+	/**
125
+	 * Gets the EE_Answer object for the question for this registration (if it exists)
126
+	 *
127
+	 * @param EE_Registration $registration
128
+	 * @param int|null        $question_id
129
+	 * @return EE_Answer
130
+	 * @throws EE_Error
131
+	 * @throws ReflectionException
132
+	 */
133
+	public function get_registration_question_answer_object(EE_Registration $registration, int $question_id = 0):
134
+	EE_Answer {
135
+		$answer_obj = $this->get_one([['QST_ID' => $question_id, 'REG_ID' => $registration->ID()]]);
136
+		return apply_filters(
137
+			'FHEE__EEM_Answer__get_registration_question_answer_object__answer_obj',
138
+			$answer_obj,
139
+			$registration,
140
+			$question_id
141
+		);
142
+	}
143 143
 
144 144
 
145
-    /**
146
-     * Gets the string answer to the question for this registration's attendee
147
-     *
148
-     * @param EE_Registration $registration
149
-     * @param int|string      $question_system_id if an INT this is understood to be the question's ID; if a string
150
-     *                                            then it should be its QST_system value. Passing in the QST_system
151
-     *                                            value is more efficient
152
-     * @param boolean         $pretty_answer
153
-     * @return string|null                        if the registration has no attendee, or the question_system_id is
154
-     *                                            not a QST_ID or QST_system for a question corresponding to an
155
-     *                                            attendee field, returns null
156
-     * @throws EE_Error
157
-     * @throws ReflectionException
158
-     */
159
-    public function get_attendee_property_answer_value(
160
-        EE_Registration $registration,
161
-        $question_system_id = 0,
162
-        bool $pretty_answer = false
163
-    ): ?string {
164
-        $value = null;
165
-        // backward compat: we still want to find the question's ID
166
-        if (is_numeric($question_system_id)) {
167
-            // find this question's QST_system value
168
-            $question_id        = $question_system_id;
169
-            $question_system_id = EEM_Question::instance()->get_var(
170
-                [['QST_ID' => $question_system_id]],
171
-                'QST_system'
172
-            );
173
-        } else {
174
-            $question_id = (int) EEM_Question::instance()->get_var(
175
-                [['QST_system' => $question_system_id]],
176
-                'QST_ID'
177
-            );
178
-        }
179
-        // only bother checking if the registration has an attendee
180
-        if ($registration->attendee() instanceof EE_Attendee) {
181
-            $field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question($question_system_id);
182
-            if ($field_name) {
183
-                if ($pretty_answer) {
184
-                    switch($field_name ) {
185
-                        case 'STA_ID':
186
-                            $state = $registration->attendee()->state_obj();
187
-                            $value
188
-                                   = $state instanceof EE_State
189
-                                ? $state->name()
190
-                                : sprintf(
191
-                                    esc_html__('Unknown State (%s)', 'event_espresso'),
192
-                                    $registration->attendee()->state_ID()
193
-                                );
194
-                            break;
195
-                        case 'CNT_ISO':
196
-                            $country = $registration->attendee()->country_obj();
197
-                            $value   = $country instanceof EE_Country
198
-                                ? $country->name()
199
-                                : sprintf(
200
-                                    esc_html__('Unknown Country (%s)', 'event_espresso'),
201
-                                    $registration->attendee()->country_ID()
202
-                                );
203
-                            break;
204
-                        default:
205
-                            $value = $registration->attendee()->get_pretty($field_name);
206
-                    }
207
-                    // if field name is blank, leave the value as null too
208
-                } else {
209
-                    $value = $registration->attendee()->get($field_name);
210
-                }
211
-            }
212
-            // if no field was found, leave value blank
213
-        }
214
-        return apply_filters(
215
-            'FHEE__EEM_Answer__get_attendee_question_answer_value__answer_value',
216
-            $value,
217
-            $registration,
218
-            $question_id,
219
-            $question_system_id
220
-        );
221
-    }
145
+	/**
146
+	 * Gets the string answer to the question for this registration's attendee
147
+	 *
148
+	 * @param EE_Registration $registration
149
+	 * @param int|string      $question_system_id if an INT this is understood to be the question's ID; if a string
150
+	 *                                            then it should be its QST_system value. Passing in the QST_system
151
+	 *                                            value is more efficient
152
+	 * @param boolean         $pretty_answer
153
+	 * @return string|null                        if the registration has no attendee, or the question_system_id is
154
+	 *                                            not a QST_ID or QST_system for a question corresponding to an
155
+	 *                                            attendee field, returns null
156
+	 * @throws EE_Error
157
+	 * @throws ReflectionException
158
+	 */
159
+	public function get_attendee_property_answer_value(
160
+		EE_Registration $registration,
161
+		$question_system_id = 0,
162
+		bool $pretty_answer = false
163
+	): ?string {
164
+		$value = null;
165
+		// backward compat: we still want to find the question's ID
166
+		if (is_numeric($question_system_id)) {
167
+			// find this question's QST_system value
168
+			$question_id        = $question_system_id;
169
+			$question_system_id = EEM_Question::instance()->get_var(
170
+				[['QST_ID' => $question_system_id]],
171
+				'QST_system'
172
+			);
173
+		} else {
174
+			$question_id = (int) EEM_Question::instance()->get_var(
175
+				[['QST_system' => $question_system_id]],
176
+				'QST_ID'
177
+			);
178
+		}
179
+		// only bother checking if the registration has an attendee
180
+		if ($registration->attendee() instanceof EE_Attendee) {
181
+			$field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question($question_system_id);
182
+			if ($field_name) {
183
+				if ($pretty_answer) {
184
+					switch($field_name ) {
185
+						case 'STA_ID':
186
+							$state = $registration->attendee()->state_obj();
187
+							$value
188
+								   = $state instanceof EE_State
189
+								? $state->name()
190
+								: sprintf(
191
+									esc_html__('Unknown State (%s)', 'event_espresso'),
192
+									$registration->attendee()->state_ID()
193
+								);
194
+							break;
195
+						case 'CNT_ISO':
196
+							$country = $registration->attendee()->country_obj();
197
+							$value   = $country instanceof EE_Country
198
+								? $country->name()
199
+								: sprintf(
200
+									esc_html__('Unknown Country (%s)', 'event_espresso'),
201
+									$registration->attendee()->country_ID()
202
+								);
203
+							break;
204
+						default:
205
+							$value = $registration->attendee()->get_pretty($field_name);
206
+					}
207
+					// if field name is blank, leave the value as null too
208
+				} else {
209
+					$value = $registration->attendee()->get($field_name);
210
+				}
211
+			}
212
+			// if no field was found, leave value blank
213
+		}
214
+		return apply_filters(
215
+			'FHEE__EEM_Answer__get_attendee_question_answer_value__answer_value',
216
+			$value,
217
+			$registration,
218
+			$question_id,
219
+			$question_system_id
220
+		);
221
+	}
222 222
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
                 ),
80 80
             ],
81 81
         ];
82
-        $this->_model_relations        = [
82
+        $this->_model_relations = [
83 83
             'Registration' => new EE_Belongs_To_Relation(),
84 84
             'Question'     => new EE_Belongs_To_Relation(),
85 85
         ];
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
             $field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question($question_system_id);
182 182
             if ($field_name) {
183 183
                 if ($pretty_answer) {
184
-                    switch($field_name ) {
184
+                    switch ($field_name) {
185 185
                         case 'STA_ID':
186 186
                             $state = $registration->attendee()->state_obj();
187 187
                             $value
Please login to merge, or discard this patch.
core/db_models/EEM_Attendee.model.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
      * Gets all the attendees for a transaction (by using the esp_registration as a join table)
324 324
      *
325 325
      * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID
326
-     * @return EE_Attendee[]|null
326
+     * @return EE_Base_Class[]
327 327
      * @throws EE_Error
328 328
      * @throws ReflectionException
329 329
      */
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
      * retrieve  a single attendee from db via their ID
346 346
      *
347 347
      * @param int $ATT_ID
348
-     * @return EE_Attendee[]|null array on success, FALSE on fail
348
+     * @return EE_Base_Class|null array on success, FALSE on fail
349 349
      * @throws EE_Error
350 350
      * @throws ReflectionException
351 351
      * @deprecated
@@ -361,7 +361,7 @@  discard block
 block discarded – undo
361 361
      * retrieve  a single attendee from db via their ID
362 362
      *
363 363
      * @param array $where_cols_n_values
364
-     * @return EE_Attendee|null entity on success, null on fail
364
+     * @return null|EE_Base_Class entity on success, null on fail
365 365
      * @throws EE_Error
366 366
      * @throws ReflectionException
367 367
      */
Please login to merge, or discard this patch.
Indentation   +413 added lines, -413 removed lines patch added patch discarded remove patch
@@ -12,425 +12,425 @@
 block discarded – undo
12 12
 class EEM_Attendee extends EEM_CPT_Base
13 13
 {
14 14
 
15
-    // private instance of the Attendee object
16
-    protected static $_instance;
15
+	// private instance of the Attendee object
16
+	protected static $_instance;
17 17
 
18
-    /**
19
-     * QST_system for questions are strings not integers now,
20
-     * so these constants are deprecated.
21
-     * Please instead use the EEM_Attendee::system_question_* constants
22
-     *
23
-     * @deprecated
24
-     */
25
-    const fname_question_id = 1;
18
+	/**
19
+	 * QST_system for questions are strings not integers now,
20
+	 * so these constants are deprecated.
21
+	 * Please instead use the EEM_Attendee::system_question_* constants
22
+	 *
23
+	 * @deprecated
24
+	 */
25
+	const fname_question_id = 1;
26 26
 
27
-    /**
28
-     * @deprecated
29
-     */
30
-    const lname_question_id = 2;
27
+	/**
28
+	 * @deprecated
29
+	 */
30
+	const lname_question_id = 2;
31 31
 
32 32
 
33
-    /**
34
-     * @deprecated
35
-     */
36
-    const email_question_id = 3;
33
+	/**
34
+	 * @deprecated
35
+	 */
36
+	const email_question_id = 3;
37 37
 
38 38
 
39
-    /**
40
-     * @deprecated
41
-     */
42
-    const address_question_id = 4;
39
+	/**
40
+	 * @deprecated
41
+	 */
42
+	const address_question_id = 4;
43 43
 
44 44
 
45
-    /**
46
-     * @deprecated
47
-     */
48
-    const address2_question_id = 5;
49
-
50
-
51
-    /**
52
-     * @deprecated
53
-     */
54
-    const city_question_id = 6;
55
-
56
-
57
-    /**
58
-     * @deprecated
59
-     */
60
-    const state_question_id = 7;
61
-
62
-
63
-    /**
64
-     * @deprecated
65
-     */
66
-    const country_question_id = 8;
67
-
68
-
69
-    /**
70
-     * @deprecated
71
-     */
72
-    const zip_question_id = 9;
73
-
74
-
75
-    /**
76
-     * @deprecated
77
-     */
78
-    const phone_question_id = 10;
79
-
80
-    /**
81
-     * When looking for questions that correspond to attendee fields,
82
-     * look for the question with this QST_system value.
83
-     * These replace the old constants like EEM_Attendee::*_question_id
84
-     */
85
-    const system_question_fname         = 'fname';
86
-
87
-    const system_question_lname         = 'lname';
88
-
89
-    const system_question_email         = 'email';
90
-
91
-    const system_question_email_confirm = 'email_confirm';
92
-
93
-    const system_question_address       = 'address';
94
-
95
-    const system_question_address2      = 'address2';
96
-
97
-    const system_question_city          = 'city';
98
-
99
-    const system_question_state         = 'state';
100
-
101
-    const system_question_country       = 'country';
102
-
103
-    const system_question_zip           = 'zip';
104
-
105
-    const system_question_phone         = 'phone';
106
-
107
-    /**
108
-     * Keys are all the EEM_Attendee::system_question_* constants, which are
109
-     * also all the values of QST_system in the questions table, and values
110
-     * are their corresponding Attendee field names
111
-     *
112
-     * @var array
113
-     */
114
-    protected $_system_question_to_attendee_field_name
115
-        = [
116
-            EEM_Attendee::system_question_fname    => 'ATT_fname',
117
-            EEM_Attendee::system_question_lname    => 'ATT_lname',
118
-            EEM_Attendee::system_question_email    => 'ATT_email',
119
-            EEM_Attendee::system_question_address  => 'ATT_address',
120
-            EEM_Attendee::system_question_address2 => 'ATT_address2',
121
-            EEM_Attendee::system_question_city     => 'ATT_city',
122
-            EEM_Attendee::system_question_state    => 'STA_ID',
123
-            EEM_Attendee::system_question_country  => 'CNT_ISO',
124
-            EEM_Attendee::system_question_zip      => 'ATT_zip',
125
-            EEM_Attendee::system_question_phone    => 'ATT_phone',
126
-        ];
127
-
128
-
129
-    /**
130
-     * EEM_Attendee constructor.
131
-     *
132
-     * @param string                 $timezone
133
-     * @param ModelFieldFactory|null $model_field_factory
134
-     * @throws EE_Error
135
-     * @throws InvalidArgumentException
136
-     */
137
-    protected function __construct(string $timezone = '', ModelFieldFactory $model_field_factory = null)
138
-    {
139
-        $this->singular_item           = esc_html__('Attendee', 'event_espresso');
140
-        $this->plural_item             = esc_html__('Attendees', 'event_espresso');
141
-        $this->_tables                 = [
142
-            'Attendee_CPT'  => new EE_Primary_Table('posts', 'ID'),
143
-            'Attendee_Meta' => new EE_Secondary_Table(
144
-                'esp_attendee_meta',
145
-                'ATTM_ID',
146
-                'ATT_ID'
147
-            ),
148
-        ];
149
-        $this->_fields                 = [
150
-            'Attendee_CPT'  => [
151
-                'ATT_ID'        => $model_field_factory->createPrimaryKeyIntField(
152
-                    'ID',
153
-                    esc_html__('Attendee ID', 'event_espresso')
154
-                ),
155
-                'ATT_full_name' => $model_field_factory->createPlainTextField(
156
-                    'post_title',
157
-                    esc_html__('Attendee Full Name', 'event_espresso'),
158
-                    false,
159
-                    esc_html__('Unknown', 'event_espresso')
160
-                ),
161
-                'ATT_bio'       => $model_field_factory->createPostContentField(
162
-                    'post_content',
163
-                    esc_html__('Attendee Biography', 'event_espresso'),
164
-                    false,
165
-                    esc_html__('No Biography Provided', 'event_espresso')
166
-                ),
167
-                'ATT_slug'      => $model_field_factory->createSlugField(
168
-                    'post_name',
169
-                    esc_html__('Attendee URL Slug', 'event_espresso')
170
-                ),
171
-                'ATT_created'   => $model_field_factory->createDatetimeField(
172
-                    'post_date',
173
-                    esc_html__('Time Attendee Created', 'event_espresso')
174
-                ),
175
-                'ATT_short_bio' => $model_field_factory->createSimpleHtmlField(
176
-                    'post_excerpt',
177
-                    esc_html__('Attendee Short Biography', 'event_espresso'),
178
-                    true,
179
-                    esc_html__('No Biography Provided', 'event_espresso')
180
-                ),
181
-                'ATT_modified'  => $model_field_factory->createDatetimeField(
182
-                    'post_modified',
183
-                    esc_html__('Time Attendee Last Modified', 'event_espresso')
184
-                ),
185
-                'ATT_author'    => $model_field_factory->createWpUserField(
186
-                    'post_author',
187
-                    esc_html__('Creator ID of the first Event attended', 'event_espresso'),
188
-                    false
189
-                ),
190
-                'ATT_parent'    => $model_field_factory->createDbOnlyIntField(
191
-                    'post_parent',
192
-                    esc_html__('Parent Attendee (unused)', 'event_espresso'),
193
-                    false,
194
-                    0
195
-                ),
196
-                'post_type'     => $model_field_factory->createWpPostTypeField('espresso_attendees'),
197
-                'status'        => $model_field_factory->createWpPostStatusField(
198
-                    'post_status',
199
-                    esc_html__('Attendee Status', 'event_espresso'),
200
-                    false,
201
-                    'publish'
202
-                ),
203
-                'password'      => new EE_Password_Field(
204
-                    'post_password',
205
-                    esc_html__('Password', 'event_espresso'),
206
-                    false,
207
-                    '',
208
-                    [
209
-                        'ATT_bio',
210
-                        'ATT_short_bio',
211
-                        'ATT_address',
212
-                        'ATT_address2',
213
-                        'ATT_city',
214
-                        'STA_ID',
215
-                        'CNT_ISO',
216
-                        'ATT_zip',
217
-                        'ATT_email',
218
-                        'ATT_phone',
219
-                    ]
220
-                ),
221
-            ],
222
-            'Attendee_Meta' => [
223
-                'ATTM_ID'      => $model_field_factory->createDbOnlyIntField(
224
-                    'ATTM_ID',
225
-                    esc_html__('Attendee Meta Row ID', 'event_espresso'),
226
-                    false
227
-                ),
228
-                'ATT_ID_fk'    => $model_field_factory->createDbOnlyIntField(
229
-                    'ATT_ID',
230
-                    esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'),
231
-                    false
232
-                ),
233
-                'ATT_fname'    => $model_field_factory->createPlainTextField(
234
-                    'ATT_fname',
235
-                    esc_html__('First Name', 'event_espresso')
236
-                ),
237
-                'ATT_lname'    => $model_field_factory->createPlainTextField(
238
-                    'ATT_lname',
239
-                    esc_html__('Last Name', 'event_espresso')
240
-                ),
241
-                'ATT_address'  => $model_field_factory->createPlainTextField(
242
-                    'ATT_address',
243
-                    esc_html__('Address Part 1', 'event_espresso')
244
-                ),
245
-                'ATT_address2' => $model_field_factory->createPlainTextField(
246
-                    'ATT_address2',
247
-                    esc_html__('Address Part 2', 'event_espresso')
248
-                ),
249
-                'ATT_city'     => $model_field_factory->createPlainTextField(
250
-                    'ATT_city',
251
-                    esc_html__('City', 'event_espresso')
252
-                ),
253
-                'STA_ID'       => $model_field_factory->createForeignKeyIntField(
254
-                    'STA_ID',
255
-                    esc_html__('State', 'event_espresso'),
256
-                    true,
257
-                    0,
258
-                    'State'
259
-                ),
260
-                'CNT_ISO'      => $model_field_factory->createForeignKeyStringField(
261
-                    'CNT_ISO',
262
-                    esc_html__('Country', 'event_espresso'),
263
-                    true,
264
-                    '',
265
-                    'Country'
266
-                ),
267
-                'ATT_zip'      => $model_field_factory->createPlainTextField(
268
-                    'ATT_zip',
269
-                    esc_html__('ZIP/Postal Code', 'event_espresso')
270
-                ),
271
-                'ATT_email'    => $model_field_factory->createEmailField(
272
-                    'ATT_email',
273
-                    esc_html__('Email Address', 'event_espresso')
274
-                ),
275
-                'ATT_phone'    => $model_field_factory->createPlainTextField(
276
-                    'ATT_phone',
277
-                    esc_html__('Phone', 'event_espresso')
278
-                ),
279
-            ],
280
-        ];
281
-        $this->_model_relations        = [
282
-            'Registration'      => new EE_Has_Many_Relation(),
283
-            'State'             => new EE_Belongs_To_Relation(),
284
-            'Country'           => new EE_Belongs_To_Relation(),
285
-            'Event'             => new EE_HABTM_Relation('Registration', false),
286
-            'WP_User'           => new EE_Belongs_To_Relation(),
287
-            'Message'           => new EE_Has_Many_Any_Relation(false),
288
-            // allow deletion of attendees even if they have messages in the queue for them.
289
-            'Term_Relationship' => new EE_Has_Many_Relation(),
290
-            'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
291
-        ];
292
-        $this->_caps_slug              = 'contacts';
293
-        $this->model_chain_to_password = '';
294
-        parent::__construct($timezone);
295
-    }
296
-
297
-
298
-    /**
299
-     * Gets the name of the field on the attendee model corresponding to the system question string
300
-     * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name
301
-     *
302
-     * @param string $system_question_string
303
-     * @return string|null if not found
304
-     */
305
-    public function get_attendee_field_for_system_question(string $system_question_string): ?string
306
-    {
307
-        return $this->_system_question_to_attendee_field_name[ $system_question_string ] ?? null;
308
-    }
309
-
310
-
311
-    /**
312
-     * Gets mapping from esp_question.QST_system values to their corresponding attendee field names
313
-     *
314
-     * @return array
315
-     */
316
-    public function system_question_to_attendee_field_mapping(): array
317
-    {
318
-        return $this->_system_question_to_attendee_field_name;
319
-    }
320
-
321
-
322
-    /**
323
-     * Gets all the attendees for a transaction (by using the esp_registration as a join table)
324
-     *
325
-     * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID
326
-     * @return EE_Attendee[]|null
327
-     * @throws EE_Error
328
-     * @throws ReflectionException
329
-     */
330
-    public function get_attendees_for_transaction($transaction_id_or_obj): ?array
331
-    {
332
-        return $this->get_all(
333
-            [
334
-                [
335
-                    'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction
336
-                        ? $transaction_id_or_obj->ID()
337
-                        : $transaction_id_or_obj,
338
-                ],
339
-            ]
340
-        );
341
-    }
342
-
343
-
344
-    /**
345
-     * retrieve  a single attendee from db via their ID
346
-     *
347
-     * @param int $ATT_ID
348
-     * @return EE_Attendee[]|null array on success, FALSE on fail
349
-     * @throws EE_Error
350
-     * @throws ReflectionException
351
-     * @deprecated
352
-     */
353
-    public function get_attendee_by_ID(int $ATT_ID = 0): ?EE_Attendee
354
-    {
355
-        // retrieve a particular EE_Attendee
356
-        return $this->get_one_by_ID($ATT_ID);
357
-    }
358
-
359
-
360
-    /**
361
-     * retrieve  a single attendee from db via their ID
362
-     *
363
-     * @param array $where_cols_n_values
364
-     * @return EE_Attendee|null entity on success, null on fail
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    public function get_attendee(array $where_cols_n_values = []): ?EE_Attendee
369
-    {
370
-        if (empty($where_cols_n_values)) {
371
-            return null;
372
-        }
373
-        $attendee = $this->get_all([$where_cols_n_values]);
374
-        if (! empty($attendee)) {
375
-            return array_shift($attendee);
376
-        }
377
-        return null;
378
-    }
379
-
380
-
381
-    /**
382
-     * Search for an existing Attendee record in the DB
383
-     *
384
-     * @param array $where_cols_n_values
385
-     * @return EE_Attendee|null
386
-     * @throws EE_Error
387
-     * @throws ReflectionException
388
-     */
389
-    public function find_existing_attendee(array $where_cols_n_values = []): ?EE_Attendee
390
-    {
391
-        // search by combo of first and last names plus the email address
392
-        $attendee_data_keys = [
393
-            'ATT_fname' => $this->_ATT_fname,
394
-            'ATT_lname' => $this->_ATT_lname,
395
-            'ATT_email' => $this->_ATT_email,
396
-        ];
397
-        // no search params means attendee object already exists.
398
-        $where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values)
399
-            ? $where_cols_n_values
400
-            : $attendee_data_keys;
401
-        $valid_data          = true;
402
-        // check for required values
403
-        $valid_data = isset($where_cols_n_values['ATT_fname'])
404
-                      && ! empty($where_cols_n_values['ATT_fname'])
405
-                      && $valid_data;
406
-        $valid_data = isset($where_cols_n_values['ATT_lname'])
407
-                      && ! empty($where_cols_n_values['ATT_lname'])
408
-                      && $valid_data;
409
-        $valid_data = isset($where_cols_n_values['ATT_email'])
410
-                      && ! empty($where_cols_n_values['ATT_email'])
411
-                      && $valid_data;
412
-        if ($valid_data) {
413
-            $attendee = $this->get_attendee($where_cols_n_values);
414
-            if ($attendee instanceof EE_Attendee) {
415
-                return $attendee;
416
-            }
417
-        }
418
-        return null;
419
-    }
420
-
421
-
422
-    /**
423
-     * Takes an incoming array of EE_Registration ids
424
-     * and sends back a list of corresponding non duplicate EE_Attendee objects.
425
-     *
426
-     * @param array $ids array of EE_Registration ids
427
-     * @return EE_Attendee[]
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     * @since  4.3.0
431
-     */
432
-    public function get_array_of_contacts_from_reg_ids(array $ids): array
433
-    {
434
-        return $this->get_all([['Registration.REG_ID' => ['in', $ids]]]);
435
-    }
45
+	/**
46
+	 * @deprecated
47
+	 */
48
+	const address2_question_id = 5;
49
+
50
+
51
+	/**
52
+	 * @deprecated
53
+	 */
54
+	const city_question_id = 6;
55
+
56
+
57
+	/**
58
+	 * @deprecated
59
+	 */
60
+	const state_question_id = 7;
61
+
62
+
63
+	/**
64
+	 * @deprecated
65
+	 */
66
+	const country_question_id = 8;
67
+
68
+
69
+	/**
70
+	 * @deprecated
71
+	 */
72
+	const zip_question_id = 9;
73
+
74
+
75
+	/**
76
+	 * @deprecated
77
+	 */
78
+	const phone_question_id = 10;
79
+
80
+	/**
81
+	 * When looking for questions that correspond to attendee fields,
82
+	 * look for the question with this QST_system value.
83
+	 * These replace the old constants like EEM_Attendee::*_question_id
84
+	 */
85
+	const system_question_fname         = 'fname';
86
+
87
+	const system_question_lname         = 'lname';
88
+
89
+	const system_question_email         = 'email';
90
+
91
+	const system_question_email_confirm = 'email_confirm';
92
+
93
+	const system_question_address       = 'address';
94
+
95
+	const system_question_address2      = 'address2';
96
+
97
+	const system_question_city          = 'city';
98
+
99
+	const system_question_state         = 'state';
100
+
101
+	const system_question_country       = 'country';
102
+
103
+	const system_question_zip           = 'zip';
104
+
105
+	const system_question_phone         = 'phone';
106
+
107
+	/**
108
+	 * Keys are all the EEM_Attendee::system_question_* constants, which are
109
+	 * also all the values of QST_system in the questions table, and values
110
+	 * are their corresponding Attendee field names
111
+	 *
112
+	 * @var array
113
+	 */
114
+	protected $_system_question_to_attendee_field_name
115
+		= [
116
+			EEM_Attendee::system_question_fname    => 'ATT_fname',
117
+			EEM_Attendee::system_question_lname    => 'ATT_lname',
118
+			EEM_Attendee::system_question_email    => 'ATT_email',
119
+			EEM_Attendee::system_question_address  => 'ATT_address',
120
+			EEM_Attendee::system_question_address2 => 'ATT_address2',
121
+			EEM_Attendee::system_question_city     => 'ATT_city',
122
+			EEM_Attendee::system_question_state    => 'STA_ID',
123
+			EEM_Attendee::system_question_country  => 'CNT_ISO',
124
+			EEM_Attendee::system_question_zip      => 'ATT_zip',
125
+			EEM_Attendee::system_question_phone    => 'ATT_phone',
126
+		];
127
+
128
+
129
+	/**
130
+	 * EEM_Attendee constructor.
131
+	 *
132
+	 * @param string                 $timezone
133
+	 * @param ModelFieldFactory|null $model_field_factory
134
+	 * @throws EE_Error
135
+	 * @throws InvalidArgumentException
136
+	 */
137
+	protected function __construct(string $timezone = '', ModelFieldFactory $model_field_factory = null)
138
+	{
139
+		$this->singular_item           = esc_html__('Attendee', 'event_espresso');
140
+		$this->plural_item             = esc_html__('Attendees', 'event_espresso');
141
+		$this->_tables                 = [
142
+			'Attendee_CPT'  => new EE_Primary_Table('posts', 'ID'),
143
+			'Attendee_Meta' => new EE_Secondary_Table(
144
+				'esp_attendee_meta',
145
+				'ATTM_ID',
146
+				'ATT_ID'
147
+			),
148
+		];
149
+		$this->_fields                 = [
150
+			'Attendee_CPT'  => [
151
+				'ATT_ID'        => $model_field_factory->createPrimaryKeyIntField(
152
+					'ID',
153
+					esc_html__('Attendee ID', 'event_espresso')
154
+				),
155
+				'ATT_full_name' => $model_field_factory->createPlainTextField(
156
+					'post_title',
157
+					esc_html__('Attendee Full Name', 'event_espresso'),
158
+					false,
159
+					esc_html__('Unknown', 'event_espresso')
160
+				),
161
+				'ATT_bio'       => $model_field_factory->createPostContentField(
162
+					'post_content',
163
+					esc_html__('Attendee Biography', 'event_espresso'),
164
+					false,
165
+					esc_html__('No Biography Provided', 'event_espresso')
166
+				),
167
+				'ATT_slug'      => $model_field_factory->createSlugField(
168
+					'post_name',
169
+					esc_html__('Attendee URL Slug', 'event_espresso')
170
+				),
171
+				'ATT_created'   => $model_field_factory->createDatetimeField(
172
+					'post_date',
173
+					esc_html__('Time Attendee Created', 'event_espresso')
174
+				),
175
+				'ATT_short_bio' => $model_field_factory->createSimpleHtmlField(
176
+					'post_excerpt',
177
+					esc_html__('Attendee Short Biography', 'event_espresso'),
178
+					true,
179
+					esc_html__('No Biography Provided', 'event_espresso')
180
+				),
181
+				'ATT_modified'  => $model_field_factory->createDatetimeField(
182
+					'post_modified',
183
+					esc_html__('Time Attendee Last Modified', 'event_espresso')
184
+				),
185
+				'ATT_author'    => $model_field_factory->createWpUserField(
186
+					'post_author',
187
+					esc_html__('Creator ID of the first Event attended', 'event_espresso'),
188
+					false
189
+				),
190
+				'ATT_parent'    => $model_field_factory->createDbOnlyIntField(
191
+					'post_parent',
192
+					esc_html__('Parent Attendee (unused)', 'event_espresso'),
193
+					false,
194
+					0
195
+				),
196
+				'post_type'     => $model_field_factory->createWpPostTypeField('espresso_attendees'),
197
+				'status'        => $model_field_factory->createWpPostStatusField(
198
+					'post_status',
199
+					esc_html__('Attendee Status', 'event_espresso'),
200
+					false,
201
+					'publish'
202
+				),
203
+				'password'      => new EE_Password_Field(
204
+					'post_password',
205
+					esc_html__('Password', 'event_espresso'),
206
+					false,
207
+					'',
208
+					[
209
+						'ATT_bio',
210
+						'ATT_short_bio',
211
+						'ATT_address',
212
+						'ATT_address2',
213
+						'ATT_city',
214
+						'STA_ID',
215
+						'CNT_ISO',
216
+						'ATT_zip',
217
+						'ATT_email',
218
+						'ATT_phone',
219
+					]
220
+				),
221
+			],
222
+			'Attendee_Meta' => [
223
+				'ATTM_ID'      => $model_field_factory->createDbOnlyIntField(
224
+					'ATTM_ID',
225
+					esc_html__('Attendee Meta Row ID', 'event_espresso'),
226
+					false
227
+				),
228
+				'ATT_ID_fk'    => $model_field_factory->createDbOnlyIntField(
229
+					'ATT_ID',
230
+					esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'),
231
+					false
232
+				),
233
+				'ATT_fname'    => $model_field_factory->createPlainTextField(
234
+					'ATT_fname',
235
+					esc_html__('First Name', 'event_espresso')
236
+				),
237
+				'ATT_lname'    => $model_field_factory->createPlainTextField(
238
+					'ATT_lname',
239
+					esc_html__('Last Name', 'event_espresso')
240
+				),
241
+				'ATT_address'  => $model_field_factory->createPlainTextField(
242
+					'ATT_address',
243
+					esc_html__('Address Part 1', 'event_espresso')
244
+				),
245
+				'ATT_address2' => $model_field_factory->createPlainTextField(
246
+					'ATT_address2',
247
+					esc_html__('Address Part 2', 'event_espresso')
248
+				),
249
+				'ATT_city'     => $model_field_factory->createPlainTextField(
250
+					'ATT_city',
251
+					esc_html__('City', 'event_espresso')
252
+				),
253
+				'STA_ID'       => $model_field_factory->createForeignKeyIntField(
254
+					'STA_ID',
255
+					esc_html__('State', 'event_espresso'),
256
+					true,
257
+					0,
258
+					'State'
259
+				),
260
+				'CNT_ISO'      => $model_field_factory->createForeignKeyStringField(
261
+					'CNT_ISO',
262
+					esc_html__('Country', 'event_espresso'),
263
+					true,
264
+					'',
265
+					'Country'
266
+				),
267
+				'ATT_zip'      => $model_field_factory->createPlainTextField(
268
+					'ATT_zip',
269
+					esc_html__('ZIP/Postal Code', 'event_espresso')
270
+				),
271
+				'ATT_email'    => $model_field_factory->createEmailField(
272
+					'ATT_email',
273
+					esc_html__('Email Address', 'event_espresso')
274
+				),
275
+				'ATT_phone'    => $model_field_factory->createPlainTextField(
276
+					'ATT_phone',
277
+					esc_html__('Phone', 'event_espresso')
278
+				),
279
+			],
280
+		];
281
+		$this->_model_relations        = [
282
+			'Registration'      => new EE_Has_Many_Relation(),
283
+			'State'             => new EE_Belongs_To_Relation(),
284
+			'Country'           => new EE_Belongs_To_Relation(),
285
+			'Event'             => new EE_HABTM_Relation('Registration', false),
286
+			'WP_User'           => new EE_Belongs_To_Relation(),
287
+			'Message'           => new EE_Has_Many_Any_Relation(false),
288
+			// allow deletion of attendees even if they have messages in the queue for them.
289
+			'Term_Relationship' => new EE_Has_Many_Relation(),
290
+			'Term_Taxonomy'     => new EE_HABTM_Relation('Term_Relationship'),
291
+		];
292
+		$this->_caps_slug              = 'contacts';
293
+		$this->model_chain_to_password = '';
294
+		parent::__construct($timezone);
295
+	}
296
+
297
+
298
+	/**
299
+	 * Gets the name of the field on the attendee model corresponding to the system question string
300
+	 * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name
301
+	 *
302
+	 * @param string $system_question_string
303
+	 * @return string|null if not found
304
+	 */
305
+	public function get_attendee_field_for_system_question(string $system_question_string): ?string
306
+	{
307
+		return $this->_system_question_to_attendee_field_name[ $system_question_string ] ?? null;
308
+	}
309
+
310
+
311
+	/**
312
+	 * Gets mapping from esp_question.QST_system values to their corresponding attendee field names
313
+	 *
314
+	 * @return array
315
+	 */
316
+	public function system_question_to_attendee_field_mapping(): array
317
+	{
318
+		return $this->_system_question_to_attendee_field_name;
319
+	}
320
+
321
+
322
+	/**
323
+	 * Gets all the attendees for a transaction (by using the esp_registration as a join table)
324
+	 *
325
+	 * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID
326
+	 * @return EE_Attendee[]|null
327
+	 * @throws EE_Error
328
+	 * @throws ReflectionException
329
+	 */
330
+	public function get_attendees_for_transaction($transaction_id_or_obj): ?array
331
+	{
332
+		return $this->get_all(
333
+			[
334
+				[
335
+					'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction
336
+						? $transaction_id_or_obj->ID()
337
+						: $transaction_id_or_obj,
338
+				],
339
+			]
340
+		);
341
+	}
342
+
343
+
344
+	/**
345
+	 * retrieve  a single attendee from db via their ID
346
+	 *
347
+	 * @param int $ATT_ID
348
+	 * @return EE_Attendee[]|null array on success, FALSE on fail
349
+	 * @throws EE_Error
350
+	 * @throws ReflectionException
351
+	 * @deprecated
352
+	 */
353
+	public function get_attendee_by_ID(int $ATT_ID = 0): ?EE_Attendee
354
+	{
355
+		// retrieve a particular EE_Attendee
356
+		return $this->get_one_by_ID($ATT_ID);
357
+	}
358
+
359
+
360
+	/**
361
+	 * retrieve  a single attendee from db via their ID
362
+	 *
363
+	 * @param array $where_cols_n_values
364
+	 * @return EE_Attendee|null entity on success, null on fail
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	public function get_attendee(array $where_cols_n_values = []): ?EE_Attendee
369
+	{
370
+		if (empty($where_cols_n_values)) {
371
+			return null;
372
+		}
373
+		$attendee = $this->get_all([$where_cols_n_values]);
374
+		if (! empty($attendee)) {
375
+			return array_shift($attendee);
376
+		}
377
+		return null;
378
+	}
379
+
380
+
381
+	/**
382
+	 * Search for an existing Attendee record in the DB
383
+	 *
384
+	 * @param array $where_cols_n_values
385
+	 * @return EE_Attendee|null
386
+	 * @throws EE_Error
387
+	 * @throws ReflectionException
388
+	 */
389
+	public function find_existing_attendee(array $where_cols_n_values = []): ?EE_Attendee
390
+	{
391
+		// search by combo of first and last names plus the email address
392
+		$attendee_data_keys = [
393
+			'ATT_fname' => $this->_ATT_fname,
394
+			'ATT_lname' => $this->_ATT_lname,
395
+			'ATT_email' => $this->_ATT_email,
396
+		];
397
+		// no search params means attendee object already exists.
398
+		$where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values)
399
+			? $where_cols_n_values
400
+			: $attendee_data_keys;
401
+		$valid_data          = true;
402
+		// check for required values
403
+		$valid_data = isset($where_cols_n_values['ATT_fname'])
404
+					  && ! empty($where_cols_n_values['ATT_fname'])
405
+					  && $valid_data;
406
+		$valid_data = isset($where_cols_n_values['ATT_lname'])
407
+					  && ! empty($where_cols_n_values['ATT_lname'])
408
+					  && $valid_data;
409
+		$valid_data = isset($where_cols_n_values['ATT_email'])
410
+					  && ! empty($where_cols_n_values['ATT_email'])
411
+					  && $valid_data;
412
+		if ($valid_data) {
413
+			$attendee = $this->get_attendee($where_cols_n_values);
414
+			if ($attendee instanceof EE_Attendee) {
415
+				return $attendee;
416
+			}
417
+		}
418
+		return null;
419
+	}
420
+
421
+
422
+	/**
423
+	 * Takes an incoming array of EE_Registration ids
424
+	 * and sends back a list of corresponding non duplicate EE_Attendee objects.
425
+	 *
426
+	 * @param array $ids array of EE_Registration ids
427
+	 * @return EE_Attendee[]
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 * @since  4.3.0
431
+	 */
432
+	public function get_array_of_contacts_from_reg_ids(array $ids): array
433
+	{
434
+		return $this->get_all([['Registration.REG_ID' => ['in', $ids]]]);
435
+	}
436 436
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
                 'ATT_ID'
147 147
             ),
148 148
         ];
149
-        $this->_fields                 = [
149
+        $this->_fields = [
150 150
             'Attendee_CPT'  => [
151 151
                 'ATT_ID'        => $model_field_factory->createPrimaryKeyIntField(
152 152
                     'ID',
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
                 ),
279 279
             ],
280 280
         ];
281
-        $this->_model_relations        = [
281
+        $this->_model_relations = [
282 282
             'Registration'      => new EE_Has_Many_Relation(),
283 283
             'State'             => new EE_Belongs_To_Relation(),
284 284
             'Country'           => new EE_Belongs_To_Relation(),
@@ -304,7 +304,7 @@  discard block
 block discarded – undo
304 304
      */
305 305
     public function get_attendee_field_for_system_question(string $system_question_string): ?string
306 306
     {
307
-        return $this->_system_question_to_attendee_field_name[ $system_question_string ] ?? null;
307
+        return $this->_system_question_to_attendee_field_name[$system_question_string] ?? null;
308 308
     }
309 309
 
310 310
 
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
             return null;
372 372
         }
373 373
         $attendee = $this->get_all([$where_cols_n_values]);
374
-        if (! empty($attendee)) {
374
+        if ( ! empty($attendee)) {
375 375
             return array_shift($attendee);
376 376
         }
377 377
         return null;
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -656,7 +656,7 @@
 block discarded – undo
656 656
     /**
657 657
      * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658 658
      *
659
-     * @param array $include           If included you can restrict the statuses we return counts for by including the
659
+     * @param string[] $include           If included you can restrict the statuses we return counts for by including the
660 660
      *                                 statuses you want counts for as values in the array.  An empty array returns
661 661
      *                                 counts for all valid statuses.
662 662
      * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
Please login to merge, or discard this patch.
Indentation   +847 added lines, -847 removed lines patch added patch discarded remove patch
@@ -13,851 +13,851 @@
 block discarded – undo
13 13
 class EEM_Datetime extends EEM_Soft_Delete_Base
14 14
 {
15 15
 
16
-    /**
17
-     * @var EEM_Datetime $_instance
18
-     */
19
-    protected static $_instance;
20
-
21
-
22
-    /**
23
-     * private constructor to prevent direct creation
24
-     *
25
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
-     *                         (and any incoming timezone data that gets saved).
27
-     *                         Note this just sends the timezone info to the date time model field objects.
28
-     *                         Default is NULL
29
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
-     * @throws EE_Error
31
-     * @throws InvalidArgumentException
32
-     * @throws InvalidArgumentException
33
-     */
34
-    protected function __construct(string $timezone = '')
35
-    {
36
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
-        $this->_tables                 = [
39
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
-        ];
41
-        $this->_fields                 = [
42
-            'Datetime' => [
43
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
-                    'DTT_ID',
45
-                    esc_html__('Datetime ID', 'event_espresso')
46
-                ),
47
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
-                    'EVT_ID',
49
-                    esc_html__('Event ID', 'event_espresso'),
50
-                    false,
51
-                    0,
52
-                    'Event'
53
-                ),
54
-                'DTT_name'        => new EE_Plain_Text_Field(
55
-                    'DTT_name',
56
-                    esc_html__('Datetime Name', 'event_espresso'),
57
-                    false,
58
-                    ''
59
-                ),
60
-                'DTT_description' => new EE_Post_Content_Field(
61
-                    'DTT_description',
62
-                    esc_html__('Description for Datetime', 'event_espresso'),
63
-                    false,
64
-                    ''
65
-                ),
66
-                'DTT_EVT_start'   => new EE_Datetime_Field(
67
-                    'DTT_EVT_start',
68
-                    esc_html__('Start time/date of Event', 'event_espresso'),
69
-                    false,
70
-                    EE_Datetime_Field::now,
71
-                    $timezone
72
-                ),
73
-                'DTT_EVT_end'     => new EE_Datetime_Field(
74
-                    'DTT_EVT_end',
75
-                    esc_html__('End time/date of Event', 'event_espresso'),
76
-                    false,
77
-                    EE_Datetime_Field::now,
78
-                    $timezone
79
-                ),
80
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
81
-                    'DTT_reg_limit',
82
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
83
-                    true,
84
-                    EE_INF
85
-                ),
86
-                'DTT_sold'        => new EE_Integer_Field(
87
-                    'DTT_sold',
88
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
89
-                    true,
90
-                    0
91
-                ),
92
-                'DTT_reserved'    => new EE_Integer_Field(
93
-                    'DTT_reserved',
94
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
95
-                    false,
96
-                    0
97
-                ),
98
-                'DTT_is_primary'  => new EE_Boolean_Field(
99
-                    'DTT_is_primary',
100
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
101
-                    false,
102
-                    false
103
-                ),
104
-                'DTT_order'       => new EE_Integer_Field(
105
-                    'DTT_order',
106
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
107
-                    false,
108
-                    0
109
-                ),
110
-                'DTT_parent'      => new EE_Integer_Field(
111
-                    'DTT_parent',
112
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
113
-                    true,
114
-                    0
115
-                ),
116
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
117
-                    'DTT_deleted',
118
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
119
-                    false,
120
-                    false
121
-                ),
122
-            ],
123
-        ];
124
-        $this->_model_relations        = [
125
-            'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
126
-            'Event'           => new EE_Belongs_To_Relation(),
127
-            'Checkin'         => new EE_Has_Many_Relation(),
128
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
129
-        ];
130
-        $path_to_event_model           = 'Event';
131
-        $this->model_chain_to_password = $path_to_event_model;
132
-        $this->_model_chain_to_wp_user = $path_to_event_model;
133
-        // this model is generally available for reading
134
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
135
-            $path_to_event_model
136
-        );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
138
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
139
-            $path_to_event_model
140
-        );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
142
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
143
-            $path_to_event_model
144
-        );
145
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
146
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
147
-            $path_to_event_model,
148
-            EEM_Base::caps_edit
149
-        );
150
-        parent::__construct($timezone);
151
-    }
152
-
153
-
154
-    /**
155
-     * create new blank datetime
156
-     *
157
-     * @access public
158
-     * @return EE_Datetime[]
159
-     * @throws EE_Error
160
-     * @throws InvalidArgumentException
161
-     * @throws InvalidDataTypeException
162
-     * @throws ReflectionException
163
-     * @throws InvalidInterfaceException
164
-     */
165
-    public function create_new_blank_datetime(): array
166
-    {
167
-        // makes sure timezone is always set.
168
-        $timezone_string = $this->get_timezone();
169
-        /**
170
-         * Filters the initial start date for the new datetime.
171
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
172
-         *
173
-         * @param int $start_date Unix timestamp representing now + 30 days in seconds.
174
-         * @return int Unix timestamp
175
-         */
176
-        $start_date = apply_filters(
177
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
178
-            $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
179
-        );
180
-        /**
181
-         * Filters the initial end date for the new datetime.
182
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
183
-         *
184
-         * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185
-         * @return int Unix timestamp
186
-         */
187
-        $end_date       = apply_filters(
188
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189
-            $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190
-        );
191
-        $blank_datetime = EE_Datetime::new_instance(
192
-            [
193
-                'DTT_EVT_start' => $start_date,
194
-                'DTT_EVT_end'   => $end_date,
195
-                'DTT_order'     => 1,
196
-                'DTT_reg_limit' => EE_INF,
197
-            ],
198
-            $timezone_string
199
-        );
200
-        /**
201
-         * Filters the initial start time and format for the new EE_Datetime instance.
202
-         *
203
-         * @param array $start_time An array having size 2.  First element is the time, second element is the time
204
-         *                          format.
205
-         * @return array
206
-         */
207
-        $start_time = apply_filters(
208
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
209
-            ['8am', 'ga']
210
-        );
211
-        /**
212
-         * Filters the initial end time and format for the new EE_Datetime instance.
213
-         *
214
-         * @param array $end_time An array having size 2.  First element is the time, second element is the time
215
-         *                        format
216
-         * @return array
217
-         */
218
-        $end_time = apply_filters(
219
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
220
-            ['5pm', 'ga']
221
-        );
222
-        $this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
223
-        $blank_datetime->set_start_time(
224
-            $this->convert_datetime_for_query(
225
-                'DTT_EVT_start',
226
-                $start_time[0],
227
-                $start_time[1],
228
-                $timezone_string
229
-            )
230
-        );
231
-        $blank_datetime->set_end_time(
232
-            $this->convert_datetime_for_query(
233
-                'DTT_EVT_end',
234
-                $end_time[0],
235
-                $end_time[1],
236
-                $timezone_string
237
-            )
238
-        );
239
-        return [$blank_datetime];
240
-    }
241
-
242
-
243
-    /**
244
-     * Validates whether the start_time and end_time are in the expected format.
245
-     *
246
-     * @param array $start_time
247
-     * @param array $end_time
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidDataTypeException
250
-     */
251
-    private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252
-    {
253
-        if (! is_array($start_time)) {
254
-            throw new InvalidDataTypeException('start_time', $start_time, 'array');
255
-        }
256
-        if (! is_array($end_time)) {
257
-            throw new InvalidDataTypeException('end_time', $end_time, 'array');
258
-        }
259
-        if (count($start_time) !== 2) {
260
-            throw new InvalidArgumentException(
261
-                sprintf(
262
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
263
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
264
-                    '$start_time'
265
-                )
266
-            );
267
-        }
268
-        if (count($end_time) !== 2) {
269
-            throw new InvalidArgumentException(
270
-                sprintf(
271
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
273
-                    '$end_time'
274
-                )
275
-            );
276
-        }
277
-    }
278
-
279
-
280
-    /**
281
-     * get event start date from db
282
-     *
283
-     * @access public
284
-     * @param int $EVT_ID
285
-     * @return EE_Datetime[] array on success, FALSE on fail
286
-     * @throws EE_Error
287
-     * @throws ReflectionException
288
-     */
289
-    public function get_all_event_dates(int $EVT_ID = 0): array
290
-    {
291
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
292
-            return $this->create_new_blank_datetime();
293
-        }
294
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
295
-        if (empty($results)) {
296
-            return $this->create_new_blank_datetime();
297
-        }
298
-        return $results;
299
-    }
300
-
301
-
302
-    /**
303
-     * get all datetimes attached to an event ordered by the DTT_order field
304
-     *
305
-     * @public
306
-     * @param int     $EVT_ID     event id
307
-     * @param boolean $include_expired
308
-     * @param boolean $include_deleted
309
-     * @param int     $limit      If included then limit the count of results by
310
-     *                            the given number
311
-     * @return EE_Datetime[]
312
-     * @throws EE_Error
313
-     * @throws ReflectionException
314
-     */
315
-    public function get_datetimes_for_event_ordered_by_DTT_order(
316
-        int $EVT_ID,
317
-        bool $include_expired = true,
318
-        bool $include_deleted = true,
319
-        int $limit = 0
320
-    ): array {
321
-        $prev_data_prep_value = $this->prepModelForQuery();
322
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
323
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
324
-        $query_params         = $this->addDefaultWhereConditions($query_params);
325
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
326
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
327
-    }
328
-
329
-
330
-    /**
331
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
332
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
333
-     * and then the earlier datetimes are the most important.
334
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
335
-     *
336
-     * @param int $EVT_ID
337
-     * @param int $limit
338
-     * @return EE_Datetime[]
339
-     * @throws EE_Error
340
-     * @throws ReflectionException
341
-     */
342
-    public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, int $limit = 0): array
343
-    {
344
-        $query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
345
-        $query_params    = $this->addDefaultWhereConditions($query_params);
346
-        $query_params    = $this->addDefaultQueryParams($query_params, $limit);
347
-        return $this->get_all($query_params);
348
-    }
349
-
350
-
351
-    /**
352
-     * @param int     $EVT_ID
353
-     * @param boolean $include_expired
354
-     * @param boolean $include_deleted
355
-     * @return EE_Datetime
356
-     * @throws EE_Error
357
-     * @throws ReflectionException
358
-     */
359
-    public function get_oldest_datetime_for_event(
360
-        int $EVT_ID,
361
-        bool $include_expired = false,
362
-        bool $include_deleted = false
363
-    ): ?EE_Datetime {
364
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
365
-            $EVT_ID,
366
-            $include_expired,
367
-            $include_deleted,
368
-            1
369
-        );
370
-        if ($results) {
371
-            return array_shift($results);
372
-        }
373
-        return null;
374
-    }
375
-
376
-
377
-    /**
378
-     * Gets the 'primary' datetime for an event.
379
-     *
380
-     * @param int  $EVT_ID
381
-     * @param bool $try_to_exclude_expired
382
-     * @param bool $try_to_exclude_deleted
383
-     * @return EE_Datetime
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public function get_primary_datetime_for_event(
388
-        int $EVT_ID,
389
-        bool $try_to_exclude_expired = true,
390
-        bool $try_to_exclude_deleted = true
391
-    ): ?EE_Datetime {
392
-        if ($try_to_exclude_expired) {
393
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID);
394
-            if ($non_expired) {
395
-                return $non_expired;
396
-            }
397
-        }
398
-        if ($try_to_exclude_deleted) {
399
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
400
-            if ($expired_even) {
401
-                return $expired_even;
402
-            }
403
-        }
404
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
405
-    }
406
-
407
-
408
-    /**
409
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
410
-     * only by start date
411
-     *
412
-     * @param int     $EVT_ID
413
-     * @param boolean $include_expired
414
-     * @param boolean $include_deleted
415
-     * @param int     $limit
416
-     * @return EE_Datetime[]
417
-     * @throws EE_Error
418
-     * @throws ReflectionException
419
-     */
420
-    public function get_datetimes_for_event_ordered_by_start_time(
421
-        int $EVT_ID,
422
-        bool $include_expired = true,
423
-        bool $include_deleted = true,
424
-        int $limit = 0
425
-    ): array {
426
-        $prev_data_prep_value = $this->prepModelForQuery();
427
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
428
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
429
-        $query_params         = $this->addDefaultWhereConditions(
430
-            $query_params,
431
-            EEM_Base::default_where_conditions_this_only
432
-        );
433
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
440
-     * only by start date
441
-     *
442
-     * @param int     $TKT_ID
443
-     * @param boolean $include_expired
444
-     * @param boolean $include_deleted
445
-     * @param int     $limit
446
-     * @return EE_Datetime[]
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    public function get_datetimes_for_ticket_ordered_by_start_time(
451
-        int $TKT_ID,
452
-        bool $include_expired = true,
453
-        bool $include_deleted = true,
454
-        int $limit = 0
455
-    ): array {
456
-        $prev_data_prep_value = $this->prepModelForQuery();
457
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
458
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
459
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit);
460
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
461
-    }
462
-
463
-
464
-    /**
465
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
466
-     * datetimes.
467
-     *
468
-     * @param int     $TKT_ID            ID of ticket to retrieve the datetimes for
469
-     * @param boolean $include_expired   whether to include expired datetimes or not
470
-     * @param boolean $include_deleted   whether to include trashed datetimes or not.
471
-     * @param int     $limit             if null, no limit, if int then limit results by
472
-     *                                   that number
473
-     * @return EE_Datetime[]
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
478
-        int $TKT_ID,
479
-        bool $include_expired = true,
480
-        bool $include_deleted = true,
481
-        int $limit = 0
482
-    ): array {
483
-        $prev_data_prep_value = $this->prepModelForQuery();
484
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
485
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
486
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
487
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
488
-    }
489
-
490
-
491
-    /**
492
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
493
-     * reason it doesn't exist, we consider the earliest event the most important)
494
-     *
495
-     * @param int $EVT_ID
496
-     * @return EE_Datetime
497
-     * @throws EE_Error
498
-     * @throws ReflectionException
499
-     */
500
-    public function get_most_important_datetime_for_event(int $EVT_ID): ?EE_Datetime
501
-    {
502
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
503
-        if ($results) {
504
-            return array_shift($results);
505
-        }
506
-        return null;
507
-    }
508
-
509
-
510
-    /**
511
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
512
-     * grouped by month and year.
513
-     *
514
-     * @param array  $where_params       @see
515
-     *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
516
-     * @param string $evt_active_status  A string representing the evt active status to filter the months by.
517
-     *                                   Can be:
518
-     *                                   - '' = no filter
519
-     *                                   - upcoming = Published events with at least one upcoming datetime.
520
-     *                                   - expired = Events with all datetimes expired.
521
-     *                                   - active = Events that are published and have at least one datetime that
522
-     *                                   starts before now and ends after now.
523
-     *                                   - inactive = Events that are either not published.
524
-     * @return EE_Base_Class[]
525
-     * @throws EE_Error
526
-     * @throws InvalidArgumentException
527
-     * @throws InvalidArgumentException
528
-     * @throws ReflectionException
529
-     */
530
-    public function get_dtt_months_and_years(array $where_params, string $evt_active_status = ''): array
531
-    {
532
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
-        switch ($evt_active_status) {
535
-            case 'upcoming':
536
-                $where_params['Event.status'] = 'publish';
537
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
-                if (isset($where_params['DTT_EVT_start'])) {
539
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
-                }
541
-                $where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
-                break;
543
-            case 'expired':
544
-                if (isset($where_params['Event.status'])) {
545
-                    unset($where_params['Event.status']);
546
-                }
547
-                // get events to exclude
548
-                $exclude_query[0] = array_merge(
549
-                    $where_params,
550
-                    ['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
-                );
552
-                // first get all events that have datetimes where its not expired.
553
-                $event_ids = $this->_get_all_wpdb_results(
554
-                    $exclude_query,
555
-                    OBJECT_K,
556
-                    'Datetime.EVT_ID'
557
-                );
558
-                $event_ids = array_keys($event_ids);
559
-                if (isset($where_params['DTT_EVT_end'])) {
560
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
-                }
562
-                $where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
-                $where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
-                break;
565
-            case 'active':
566
-                $where_params['Event.status'] = 'publish';
567
-                if (isset($where_params['DTT_EVT_start'])) {
568
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
-                }
570
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
-                }
573
-                $where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
-                $where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
-                break;
576
-            case 'inactive':
577
-                if (isset($where_params['Event.status'])) {
578
-                    unset($where_params['Event.status']);
579
-                }
580
-                if (isset($where_params['OR'])) {
581
-                    $where_params['AND']['OR'] = $where_params['OR'];
582
-                }
583
-                if (isset($where_params['DTT_EVT_end'])) {
584
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
-                    unset($where_params['DTT_EVT_end']);
586
-                }
587
-                if (isset($where_params['DTT_EVT_start'])) {
588
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
-                    unset($where_params['DTT_EVT_start']);
590
-                }
591
-                $where_params['AND']['Event.status'] = ['!=', 'publish'];
592
-                break;
593
-        }
594
-        $query_params[0]          = $where_params;
595
-        $query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
-        $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
-
598
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
-            $this->get_timezone(),
600
-            'DTT_EVT_start'
601
-        );
602
-        $columns_to_select = [
603
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
-        ];
607
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
-    }
609
-
610
-
611
-    /**
612
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
613
-     * for the tickets for each datetime)
614
-     *
615
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
-     * @throws EE_Error
617
-     * @throws ReflectionException
618
-     */
619
-    public function update_sold(array $datetimes)
620
-    {
621
-        EE_Error::doing_it_wrong(
622
-            __FUNCTION__,
623
-            esc_html__(
624
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
-                'event_espresso'
626
-            ),
627
-            '4.9.32.rc.005'
628
-        );
629
-        foreach ($datetimes as $datetime) {
630
-            $datetime->update_sold();
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     *    Gets the total number of tickets available at a particular datetime
637
-     *    (does NOT take into account the datetime's spaces available)
638
-     *
639
-     * @param int   $DTT_ID
640
-     * @param array $query_params
641
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
-     *             tickets attached to datetime then FALSE is returned.
643
-     * @throws EE_Error
644
-     * @throws ReflectionException
645
-     */
646
-    public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = []): int
647
-    {
648
-        $datetime = $this->get_one_by_ID($DTT_ID);
649
-        if ($datetime instanceof EE_Datetime) {
650
-            return $datetime->tickets_remaining($query_params);
651
-        }
652
-        return 0;
653
-    }
654
-
655
-
656
-    /**
657
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
-     *
659
-     * @param array $include           If included you can restrict the statuses we return counts for by including the
660
-     *                                 statuses you want counts for as values in the array.  An empty array returns
661
-     *                                 counts for all valid statuses.
662
-     * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
664
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
-     * @throws EE_Error
666
-     * @throws ReflectionException
667
-     *                                 statuses used as index keys are: EE_Datetime::active EE_Datetime::upcoming
668
-     *                                 EE_Datetime::expired
669
-     */
670
-    public function get_datetime_counts_by_status(array $include = [], array $query_params = []): array
671
-    {
672
-        // only accept where conditions for this query.
673
-        $_where            = $query_params[0] ?? [];
674
-        $status_query_args = [
675
-            EE_Datetime::active   => array_merge(
676
-                $_where,
677
-                ['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
678
-            ),
679
-            EE_Datetime::upcoming => array_merge(
680
-                $_where,
681
-                ['DTT_EVT_start' => ['>', time()]]
682
-            ),
683
-            EE_Datetime::expired  => array_merge(
684
-                $_where,
685
-                ['DTT_EVT_end' => ['<', time()]]
686
-            ),
687
-        ];
688
-        if (! empty($include)) {
689
-            foreach (array_keys($status_query_args) as $status) {
690
-                if (! in_array($status, $include, true)) {
691
-                    unset($status_query_args[ $status ]);
692
-                }
693
-            }
694
-        }
695
-        // loop through and query counts for each statuses.
696
-        $status_query_results = [];
697
-        foreach ($status_query_args as $status => $status_where_conditions) {
698
-            $status_query_results[ $status ] = EEM_Datetime::count(
699
-                [$status_where_conditions],
700
-                'DTT_ID',
701
-                true
702
-            );
703
-        }
704
-        return $status_query_results;
705
-    }
706
-
707
-
708
-    /**
709
-     * Returns the specific count for a given Datetime status matching any given query_params.
710
-     *
711
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
712
-     * @param array  $query_params
713
-     * @return int
714
-     * @throws EE_Error
715
-     * @throws ReflectionException
716
-     */
717
-    public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718
-    {
719
-        $count = $this->get_datetime_counts_by_status([$status], $query_params);
720
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
721
-    }
722
-
723
-
724
-    /**
725
-     * @return bool|int
726
-     * @since   $VID:$
727
-     */
728
-    private function prepModelForQuery()
729
-    {
730
-        $prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
731
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
732
-        return $prev_data_prep_value;
733
-    }
734
-
735
-
736
-    /**
737
-     * @param array    $query_params
738
-     * @param bool|int $prev_data_prep_value
739
-     * @return EE_Datetime[]
740
-     * @throws EE_Error
741
-     * @throws ReflectionException
742
-     * @since   $VID:$
743
-     */
744
-    private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value): array
745
-    {
746
-        $result = $this->get_all($query_params);
747
-        $this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
748
-        return $result;
749
-    }
750
-
751
-
752
-    /**
753
-     * @param array  $query_params
754
-     * @param int    $limit
755
-     * @param string $order_by
756
-     * @return array
757
-     * @since   $VID:$
758
-     */
759
-    private function addDefaultQueryParams(
760
-        array $query_params,
761
-        int $limit = 0,
762
-        string $order_by = 'DTT_EVT_start'
763
-    ): array {
764
-        $query_params = $this->addOrderByQueryParams($query_params, $order_by);
765
-        return $this->addLimitQueryParams($query_params, $limit);
766
-    }
767
-
768
-
769
-    /**
770
-     * @param array  $query_params
771
-     * @param string $default_where_conditions
772
-     * @return array
773
-     * @since   $VID:$
774
-     */
775
-    private function addDefaultWhereConditions(
776
-        array $query_params,
777
-        string $default_where_conditions = EEM_Base::default_where_conditions_none
778
-    ): array {
779
-        $query_params['default_where_conditions'] = $default_where_conditions;
780
-        return $query_params;
781
-    }
782
-
783
-
784
-    /**
785
-     * @param array $where_params
786
-     * @param bool  $include_deleted
787
-     * @param bool  $include_expired
788
-     * @return array
789
-     * @since   $VID:$
790
-     */
791
-    private function addDefaultWhereParams(array $where_params,
792
-                                           bool $include_deleted = true,
793
-                                           bool $include_expired = true): array
794
-    {
795
-        $where_params = $this->addExpiredWhereParams($where_params, $include_expired);
796
-        return $this->addDeletedWhereParams($where_params, $include_deleted);
797
-    }
798
-
799
-
800
-    /**
801
-     * @param array $where_params
802
-     * @param bool  $include_deleted
803
-     * @return array
804
-     * @since   $VID:$
805
-     */
806
-    private function addDeletedWhereParams(array $where_params, bool $include_deleted = true): array
807
-    {
808
-        $deleted                     = $include_deleted ? [true, false] : [false];
809
-        $where_params['DTT_deleted'] = ['IN', $deleted];
810
-        return $where_params;
811
-    }
812
-
813
-
814
-    /**
815
-     * @param array $where_params
816
-     * @param bool  $include_expired
817
-     * @return array
818
-     * @since   $VID:$
819
-     */
820
-    private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821
-    {
822
-        if (! $include_expired) {
823
-            $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824
-        }
825
-        return $where_params;
826
-    }
827
-
828
-
829
-    /**
830
-     * @param array $query_params
831
-     * @param int   $limit
832
-     * @return array
833
-     * @since   $VID:$
834
-     */
835
-    private function addLimitQueryParams(array $query_params, int $limit = 0): array
836
-    {
837
-        if ($limit) {
838
-            $query_params['limit'] = $limit;
839
-        }
840
-        return $query_params;
841
-    }
842
-
843
-
844
-    /**
845
-     * @param array  $query_params
846
-     * @param string $order_by
847
-     * @param string $order
848
-     * @return array
849
-     * @since   $VID:$
850
-     */
851
-    private function addOrderByQueryParams(array $query_params,
852
-                                           string $order_by = 'DTT_EVT_start',
853
-                                           string $order = 'ASC'): array
854
-    {
855
-        $order                    = $order === 'ASC' ? 'ASC' : 'DESC';
856
-        $valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
857
-        $order_by                 = in_array($order_by, $valid_order_columns, true)
858
-            ? $order_by
859
-            : 'DTT_EVT_start';
860
-        $query_params['order_by'] = [$order_by => $order];
861
-        return $query_params;
862
-    }
16
+	/**
17
+	 * @var EEM_Datetime $_instance
18
+	 */
19
+	protected static $_instance;
20
+
21
+
22
+	/**
23
+	 * private constructor to prevent direct creation
24
+	 *
25
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
26
+	 *                         (and any incoming timezone data that gets saved).
27
+	 *                         Note this just sends the timezone info to the date time model field objects.
28
+	 *                         Default is NULL
29
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
30
+	 * @throws EE_Error
31
+	 * @throws InvalidArgumentException
32
+	 * @throws InvalidArgumentException
33
+	 */
34
+	protected function __construct(string $timezone = '')
35
+	{
36
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
37
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
38
+		$this->_tables                 = [
39
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
40
+		];
41
+		$this->_fields                 = [
42
+			'Datetime' => [
43
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
44
+					'DTT_ID',
45
+					esc_html__('Datetime ID', 'event_espresso')
46
+				),
47
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
48
+					'EVT_ID',
49
+					esc_html__('Event ID', 'event_espresso'),
50
+					false,
51
+					0,
52
+					'Event'
53
+				),
54
+				'DTT_name'        => new EE_Plain_Text_Field(
55
+					'DTT_name',
56
+					esc_html__('Datetime Name', 'event_espresso'),
57
+					false,
58
+					''
59
+				),
60
+				'DTT_description' => new EE_Post_Content_Field(
61
+					'DTT_description',
62
+					esc_html__('Description for Datetime', 'event_espresso'),
63
+					false,
64
+					''
65
+				),
66
+				'DTT_EVT_start'   => new EE_Datetime_Field(
67
+					'DTT_EVT_start',
68
+					esc_html__('Start time/date of Event', 'event_espresso'),
69
+					false,
70
+					EE_Datetime_Field::now,
71
+					$timezone
72
+				),
73
+				'DTT_EVT_end'     => new EE_Datetime_Field(
74
+					'DTT_EVT_end',
75
+					esc_html__('End time/date of Event', 'event_espresso'),
76
+					false,
77
+					EE_Datetime_Field::now,
78
+					$timezone
79
+				),
80
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
81
+					'DTT_reg_limit',
82
+					esc_html__('Registration Limit for this time', 'event_espresso'),
83
+					true,
84
+					EE_INF
85
+				),
86
+				'DTT_sold'        => new EE_Integer_Field(
87
+					'DTT_sold',
88
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
89
+					true,
90
+					0
91
+				),
92
+				'DTT_reserved'    => new EE_Integer_Field(
93
+					'DTT_reserved',
94
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
95
+					false,
96
+					0
97
+				),
98
+				'DTT_is_primary'  => new EE_Boolean_Field(
99
+					'DTT_is_primary',
100
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
101
+					false,
102
+					false
103
+				),
104
+				'DTT_order'       => new EE_Integer_Field(
105
+					'DTT_order',
106
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
107
+					false,
108
+					0
109
+				),
110
+				'DTT_parent'      => new EE_Integer_Field(
111
+					'DTT_parent',
112
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
113
+					true,
114
+					0
115
+				),
116
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
117
+					'DTT_deleted',
118
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
119
+					false,
120
+					false
121
+				),
122
+			],
123
+		];
124
+		$this->_model_relations        = [
125
+			'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
126
+			'Event'           => new EE_Belongs_To_Relation(),
127
+			'Checkin'         => new EE_Has_Many_Relation(),
128
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
129
+		];
130
+		$path_to_event_model           = 'Event';
131
+		$this->model_chain_to_password = $path_to_event_model;
132
+		$this->_model_chain_to_wp_user = $path_to_event_model;
133
+		// this model is generally available for reading
134
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
135
+			$path_to_event_model
136
+		);
137
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
138
+																  = new EE_Restriction_Generator_Event_Related_Protected(
139
+			$path_to_event_model
140
+		);
141
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]
142
+																  = new EE_Restriction_Generator_Event_Related_Protected(
143
+			$path_to_event_model
144
+		);
145
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]
146
+																  = new EE_Restriction_Generator_Event_Related_Protected(
147
+			$path_to_event_model,
148
+			EEM_Base::caps_edit
149
+		);
150
+		parent::__construct($timezone);
151
+	}
152
+
153
+
154
+	/**
155
+	 * create new blank datetime
156
+	 *
157
+	 * @access public
158
+	 * @return EE_Datetime[]
159
+	 * @throws EE_Error
160
+	 * @throws InvalidArgumentException
161
+	 * @throws InvalidDataTypeException
162
+	 * @throws ReflectionException
163
+	 * @throws InvalidInterfaceException
164
+	 */
165
+	public function create_new_blank_datetime(): array
166
+	{
167
+		// makes sure timezone is always set.
168
+		$timezone_string = $this->get_timezone();
169
+		/**
170
+		 * Filters the initial start date for the new datetime.
171
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
172
+		 *
173
+		 * @param int $start_date Unix timestamp representing now + 30 days in seconds.
174
+		 * @return int Unix timestamp
175
+		 */
176
+		$start_date = apply_filters(
177
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
178
+			$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
179
+		);
180
+		/**
181
+		 * Filters the initial end date for the new datetime.
182
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
183
+		 *
184
+		 * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185
+		 * @return int Unix timestamp
186
+		 */
187
+		$end_date       = apply_filters(
188
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189
+			$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190
+		);
191
+		$blank_datetime = EE_Datetime::new_instance(
192
+			[
193
+				'DTT_EVT_start' => $start_date,
194
+				'DTT_EVT_end'   => $end_date,
195
+				'DTT_order'     => 1,
196
+				'DTT_reg_limit' => EE_INF,
197
+			],
198
+			$timezone_string
199
+		);
200
+		/**
201
+		 * Filters the initial start time and format for the new EE_Datetime instance.
202
+		 *
203
+		 * @param array $start_time An array having size 2.  First element is the time, second element is the time
204
+		 *                          format.
205
+		 * @return array
206
+		 */
207
+		$start_time = apply_filters(
208
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
209
+			['8am', 'ga']
210
+		);
211
+		/**
212
+		 * Filters the initial end time and format for the new EE_Datetime instance.
213
+		 *
214
+		 * @param array $end_time An array having size 2.  First element is the time, second element is the time
215
+		 *                        format
216
+		 * @return array
217
+		 */
218
+		$end_time = apply_filters(
219
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
220
+			['5pm', 'ga']
221
+		);
222
+		$this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
223
+		$blank_datetime->set_start_time(
224
+			$this->convert_datetime_for_query(
225
+				'DTT_EVT_start',
226
+				$start_time[0],
227
+				$start_time[1],
228
+				$timezone_string
229
+			)
230
+		);
231
+		$blank_datetime->set_end_time(
232
+			$this->convert_datetime_for_query(
233
+				'DTT_EVT_end',
234
+				$end_time[0],
235
+				$end_time[1],
236
+				$timezone_string
237
+			)
238
+		);
239
+		return [$blank_datetime];
240
+	}
241
+
242
+
243
+	/**
244
+	 * Validates whether the start_time and end_time are in the expected format.
245
+	 *
246
+	 * @param array $start_time
247
+	 * @param array $end_time
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidDataTypeException
250
+	 */
251
+	private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252
+	{
253
+		if (! is_array($start_time)) {
254
+			throw new InvalidDataTypeException('start_time', $start_time, 'array');
255
+		}
256
+		if (! is_array($end_time)) {
257
+			throw new InvalidDataTypeException('end_time', $end_time, 'array');
258
+		}
259
+		if (count($start_time) !== 2) {
260
+			throw new InvalidArgumentException(
261
+				sprintf(
262
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
263
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
264
+					'$start_time'
265
+				)
266
+			);
267
+		}
268
+		if (count($end_time) !== 2) {
269
+			throw new InvalidArgumentException(
270
+				sprintf(
271
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
273
+					'$end_time'
274
+				)
275
+			);
276
+		}
277
+	}
278
+
279
+
280
+	/**
281
+	 * get event start date from db
282
+	 *
283
+	 * @access public
284
+	 * @param int $EVT_ID
285
+	 * @return EE_Datetime[] array on success, FALSE on fail
286
+	 * @throws EE_Error
287
+	 * @throws ReflectionException
288
+	 */
289
+	public function get_all_event_dates(int $EVT_ID = 0): array
290
+	{
291
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
292
+			return $this->create_new_blank_datetime();
293
+		}
294
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
295
+		if (empty($results)) {
296
+			return $this->create_new_blank_datetime();
297
+		}
298
+		return $results;
299
+	}
300
+
301
+
302
+	/**
303
+	 * get all datetimes attached to an event ordered by the DTT_order field
304
+	 *
305
+	 * @public
306
+	 * @param int     $EVT_ID     event id
307
+	 * @param boolean $include_expired
308
+	 * @param boolean $include_deleted
309
+	 * @param int     $limit      If included then limit the count of results by
310
+	 *                            the given number
311
+	 * @return EE_Datetime[]
312
+	 * @throws EE_Error
313
+	 * @throws ReflectionException
314
+	 */
315
+	public function get_datetimes_for_event_ordered_by_DTT_order(
316
+		int $EVT_ID,
317
+		bool $include_expired = true,
318
+		bool $include_deleted = true,
319
+		int $limit = 0
320
+	): array {
321
+		$prev_data_prep_value = $this->prepModelForQuery();
322
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
323
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
324
+		$query_params         = $this->addDefaultWhereConditions($query_params);
325
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
326
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
327
+	}
328
+
329
+
330
+	/**
331
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
332
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
333
+	 * and then the earlier datetimes are the most important.
334
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
335
+	 *
336
+	 * @param int $EVT_ID
337
+	 * @param int $limit
338
+	 * @return EE_Datetime[]
339
+	 * @throws EE_Error
340
+	 * @throws ReflectionException
341
+	 */
342
+	public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, int $limit = 0): array
343
+	{
344
+		$query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
345
+		$query_params    = $this->addDefaultWhereConditions($query_params);
346
+		$query_params    = $this->addDefaultQueryParams($query_params, $limit);
347
+		return $this->get_all($query_params);
348
+	}
349
+
350
+
351
+	/**
352
+	 * @param int     $EVT_ID
353
+	 * @param boolean $include_expired
354
+	 * @param boolean $include_deleted
355
+	 * @return EE_Datetime
356
+	 * @throws EE_Error
357
+	 * @throws ReflectionException
358
+	 */
359
+	public function get_oldest_datetime_for_event(
360
+		int $EVT_ID,
361
+		bool $include_expired = false,
362
+		bool $include_deleted = false
363
+	): ?EE_Datetime {
364
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
365
+			$EVT_ID,
366
+			$include_expired,
367
+			$include_deleted,
368
+			1
369
+		);
370
+		if ($results) {
371
+			return array_shift($results);
372
+		}
373
+		return null;
374
+	}
375
+
376
+
377
+	/**
378
+	 * Gets the 'primary' datetime for an event.
379
+	 *
380
+	 * @param int  $EVT_ID
381
+	 * @param bool $try_to_exclude_expired
382
+	 * @param bool $try_to_exclude_deleted
383
+	 * @return EE_Datetime
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public function get_primary_datetime_for_event(
388
+		int $EVT_ID,
389
+		bool $try_to_exclude_expired = true,
390
+		bool $try_to_exclude_deleted = true
391
+	): ?EE_Datetime {
392
+		if ($try_to_exclude_expired) {
393
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID);
394
+			if ($non_expired) {
395
+				return $non_expired;
396
+			}
397
+		}
398
+		if ($try_to_exclude_deleted) {
399
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
400
+			if ($expired_even) {
401
+				return $expired_even;
402
+			}
403
+		}
404
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
405
+	}
406
+
407
+
408
+	/**
409
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
410
+	 * only by start date
411
+	 *
412
+	 * @param int     $EVT_ID
413
+	 * @param boolean $include_expired
414
+	 * @param boolean $include_deleted
415
+	 * @param int     $limit
416
+	 * @return EE_Datetime[]
417
+	 * @throws EE_Error
418
+	 * @throws ReflectionException
419
+	 */
420
+	public function get_datetimes_for_event_ordered_by_start_time(
421
+		int $EVT_ID,
422
+		bool $include_expired = true,
423
+		bool $include_deleted = true,
424
+		int $limit = 0
425
+	): array {
426
+		$prev_data_prep_value = $this->prepModelForQuery();
427
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
428
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
429
+		$query_params         = $this->addDefaultWhereConditions(
430
+			$query_params,
431
+			EEM_Base::default_where_conditions_this_only
432
+		);
433
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
440
+	 * only by start date
441
+	 *
442
+	 * @param int     $TKT_ID
443
+	 * @param boolean $include_expired
444
+	 * @param boolean $include_deleted
445
+	 * @param int     $limit
446
+	 * @return EE_Datetime[]
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	public function get_datetimes_for_ticket_ordered_by_start_time(
451
+		int $TKT_ID,
452
+		bool $include_expired = true,
453
+		bool $include_deleted = true,
454
+		int $limit = 0
455
+	): array {
456
+		$prev_data_prep_value = $this->prepModelForQuery();
457
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
458
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
459
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit);
460
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
461
+	}
462
+
463
+
464
+	/**
465
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
466
+	 * datetimes.
467
+	 *
468
+	 * @param int     $TKT_ID            ID of ticket to retrieve the datetimes for
469
+	 * @param boolean $include_expired   whether to include expired datetimes or not
470
+	 * @param boolean $include_deleted   whether to include trashed datetimes or not.
471
+	 * @param int     $limit             if null, no limit, if int then limit results by
472
+	 *                                   that number
473
+	 * @return EE_Datetime[]
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
478
+		int $TKT_ID,
479
+		bool $include_expired = true,
480
+		bool $include_deleted = true,
481
+		int $limit = 0
482
+	): array {
483
+		$prev_data_prep_value = $this->prepModelForQuery();
484
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
485
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
486
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
487
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
488
+	}
489
+
490
+
491
+	/**
492
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
493
+	 * reason it doesn't exist, we consider the earliest event the most important)
494
+	 *
495
+	 * @param int $EVT_ID
496
+	 * @return EE_Datetime
497
+	 * @throws EE_Error
498
+	 * @throws ReflectionException
499
+	 */
500
+	public function get_most_important_datetime_for_event(int $EVT_ID): ?EE_Datetime
501
+	{
502
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
503
+		if ($results) {
504
+			return array_shift($results);
505
+		}
506
+		return null;
507
+	}
508
+
509
+
510
+	/**
511
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
512
+	 * grouped by month and year.
513
+	 *
514
+	 * @param array  $where_params       @see
515
+	 *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
516
+	 * @param string $evt_active_status  A string representing the evt active status to filter the months by.
517
+	 *                                   Can be:
518
+	 *                                   - '' = no filter
519
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
520
+	 *                                   - expired = Events with all datetimes expired.
521
+	 *                                   - active = Events that are published and have at least one datetime that
522
+	 *                                   starts before now and ends after now.
523
+	 *                                   - inactive = Events that are either not published.
524
+	 * @return EE_Base_Class[]
525
+	 * @throws EE_Error
526
+	 * @throws InvalidArgumentException
527
+	 * @throws InvalidArgumentException
528
+	 * @throws ReflectionException
529
+	 */
530
+	public function get_dtt_months_and_years(array $where_params, string $evt_active_status = ''): array
531
+	{
532
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
+		switch ($evt_active_status) {
535
+			case 'upcoming':
536
+				$where_params['Event.status'] = 'publish';
537
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
+				if (isset($where_params['DTT_EVT_start'])) {
539
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
+				}
541
+				$where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
+				break;
543
+			case 'expired':
544
+				if (isset($where_params['Event.status'])) {
545
+					unset($where_params['Event.status']);
546
+				}
547
+				// get events to exclude
548
+				$exclude_query[0] = array_merge(
549
+					$where_params,
550
+					['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
+				);
552
+				// first get all events that have datetimes where its not expired.
553
+				$event_ids = $this->_get_all_wpdb_results(
554
+					$exclude_query,
555
+					OBJECT_K,
556
+					'Datetime.EVT_ID'
557
+				);
558
+				$event_ids = array_keys($event_ids);
559
+				if (isset($where_params['DTT_EVT_end'])) {
560
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
+				}
562
+				$where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
+				$where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
+				break;
565
+			case 'active':
566
+				$where_params['Event.status'] = 'publish';
567
+				if (isset($where_params['DTT_EVT_start'])) {
568
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
+				}
570
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
+				}
573
+				$where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
+				$where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
+				break;
576
+			case 'inactive':
577
+				if (isset($where_params['Event.status'])) {
578
+					unset($where_params['Event.status']);
579
+				}
580
+				if (isset($where_params['OR'])) {
581
+					$where_params['AND']['OR'] = $where_params['OR'];
582
+				}
583
+				if (isset($where_params['DTT_EVT_end'])) {
584
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
+					unset($where_params['DTT_EVT_end']);
586
+				}
587
+				if (isset($where_params['DTT_EVT_start'])) {
588
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
+					unset($where_params['DTT_EVT_start']);
590
+				}
591
+				$where_params['AND']['Event.status'] = ['!=', 'publish'];
592
+				break;
593
+		}
594
+		$query_params[0]          = $where_params;
595
+		$query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
+		$query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
+
598
+		$query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
+			$this->get_timezone(),
600
+			'DTT_EVT_start'
601
+		);
602
+		$columns_to_select = [
603
+			'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
+			'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
+			'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
+		];
607
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
+	}
609
+
610
+
611
+	/**
612
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
613
+	 * for the tickets for each datetime)
614
+	 *
615
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
+	 * @throws EE_Error
617
+	 * @throws ReflectionException
618
+	 */
619
+	public function update_sold(array $datetimes)
620
+	{
621
+		EE_Error::doing_it_wrong(
622
+			__FUNCTION__,
623
+			esc_html__(
624
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
+				'event_espresso'
626
+			),
627
+			'4.9.32.rc.005'
628
+		);
629
+		foreach ($datetimes as $datetime) {
630
+			$datetime->update_sold();
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 *    Gets the total number of tickets available at a particular datetime
637
+	 *    (does NOT take into account the datetime's spaces available)
638
+	 *
639
+	 * @param int   $DTT_ID
640
+	 * @param array $query_params
641
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
+	 *             tickets attached to datetime then FALSE is returned.
643
+	 * @throws EE_Error
644
+	 * @throws ReflectionException
645
+	 */
646
+	public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = []): int
647
+	{
648
+		$datetime = $this->get_one_by_ID($DTT_ID);
649
+		if ($datetime instanceof EE_Datetime) {
650
+			return $datetime->tickets_remaining($query_params);
651
+		}
652
+		return 0;
653
+	}
654
+
655
+
656
+	/**
657
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
+	 *
659
+	 * @param array $include           If included you can restrict the statuses we return counts for by including the
660
+	 *                                 statuses you want counts for as values in the array.  An empty array returns
661
+	 *                                 counts for all valid statuses.
662
+	 * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
664
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
+	 * @throws EE_Error
666
+	 * @throws ReflectionException
667
+	 *                                 statuses used as index keys are: EE_Datetime::active EE_Datetime::upcoming
668
+	 *                                 EE_Datetime::expired
669
+	 */
670
+	public function get_datetime_counts_by_status(array $include = [], array $query_params = []): array
671
+	{
672
+		// only accept where conditions for this query.
673
+		$_where            = $query_params[0] ?? [];
674
+		$status_query_args = [
675
+			EE_Datetime::active   => array_merge(
676
+				$_where,
677
+				['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
678
+			),
679
+			EE_Datetime::upcoming => array_merge(
680
+				$_where,
681
+				['DTT_EVT_start' => ['>', time()]]
682
+			),
683
+			EE_Datetime::expired  => array_merge(
684
+				$_where,
685
+				['DTT_EVT_end' => ['<', time()]]
686
+			),
687
+		];
688
+		if (! empty($include)) {
689
+			foreach (array_keys($status_query_args) as $status) {
690
+				if (! in_array($status, $include, true)) {
691
+					unset($status_query_args[ $status ]);
692
+				}
693
+			}
694
+		}
695
+		// loop through and query counts for each statuses.
696
+		$status_query_results = [];
697
+		foreach ($status_query_args as $status => $status_where_conditions) {
698
+			$status_query_results[ $status ] = EEM_Datetime::count(
699
+				[$status_where_conditions],
700
+				'DTT_ID',
701
+				true
702
+			);
703
+		}
704
+		return $status_query_results;
705
+	}
706
+
707
+
708
+	/**
709
+	 * Returns the specific count for a given Datetime status matching any given query_params.
710
+	 *
711
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
712
+	 * @param array  $query_params
713
+	 * @return int
714
+	 * @throws EE_Error
715
+	 * @throws ReflectionException
716
+	 */
717
+	public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718
+	{
719
+		$count = $this->get_datetime_counts_by_status([$status], $query_params);
720
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
721
+	}
722
+
723
+
724
+	/**
725
+	 * @return bool|int
726
+	 * @since   $VID:$
727
+	 */
728
+	private function prepModelForQuery()
729
+	{
730
+		$prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
731
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
732
+		return $prev_data_prep_value;
733
+	}
734
+
735
+
736
+	/**
737
+	 * @param array    $query_params
738
+	 * @param bool|int $prev_data_prep_value
739
+	 * @return EE_Datetime[]
740
+	 * @throws EE_Error
741
+	 * @throws ReflectionException
742
+	 * @since   $VID:$
743
+	 */
744
+	private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value): array
745
+	{
746
+		$result = $this->get_all($query_params);
747
+		$this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
748
+		return $result;
749
+	}
750
+
751
+
752
+	/**
753
+	 * @param array  $query_params
754
+	 * @param int    $limit
755
+	 * @param string $order_by
756
+	 * @return array
757
+	 * @since   $VID:$
758
+	 */
759
+	private function addDefaultQueryParams(
760
+		array $query_params,
761
+		int $limit = 0,
762
+		string $order_by = 'DTT_EVT_start'
763
+	): array {
764
+		$query_params = $this->addOrderByQueryParams($query_params, $order_by);
765
+		return $this->addLimitQueryParams($query_params, $limit);
766
+	}
767
+
768
+
769
+	/**
770
+	 * @param array  $query_params
771
+	 * @param string $default_where_conditions
772
+	 * @return array
773
+	 * @since   $VID:$
774
+	 */
775
+	private function addDefaultWhereConditions(
776
+		array $query_params,
777
+		string $default_where_conditions = EEM_Base::default_where_conditions_none
778
+	): array {
779
+		$query_params['default_where_conditions'] = $default_where_conditions;
780
+		return $query_params;
781
+	}
782
+
783
+
784
+	/**
785
+	 * @param array $where_params
786
+	 * @param bool  $include_deleted
787
+	 * @param bool  $include_expired
788
+	 * @return array
789
+	 * @since   $VID:$
790
+	 */
791
+	private function addDefaultWhereParams(array $where_params,
792
+										   bool $include_deleted = true,
793
+										   bool $include_expired = true): array
794
+	{
795
+		$where_params = $this->addExpiredWhereParams($where_params, $include_expired);
796
+		return $this->addDeletedWhereParams($where_params, $include_deleted);
797
+	}
798
+
799
+
800
+	/**
801
+	 * @param array $where_params
802
+	 * @param bool  $include_deleted
803
+	 * @return array
804
+	 * @since   $VID:$
805
+	 */
806
+	private function addDeletedWhereParams(array $where_params, bool $include_deleted = true): array
807
+	{
808
+		$deleted                     = $include_deleted ? [true, false] : [false];
809
+		$where_params['DTT_deleted'] = ['IN', $deleted];
810
+		return $where_params;
811
+	}
812
+
813
+
814
+	/**
815
+	 * @param array $where_params
816
+	 * @param bool  $include_expired
817
+	 * @return array
818
+	 * @since   $VID:$
819
+	 */
820
+	private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821
+	{
822
+		if (! $include_expired) {
823
+			$where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824
+		}
825
+		return $where_params;
826
+	}
827
+
828
+
829
+	/**
830
+	 * @param array $query_params
831
+	 * @param int   $limit
832
+	 * @return array
833
+	 * @since   $VID:$
834
+	 */
835
+	private function addLimitQueryParams(array $query_params, int $limit = 0): array
836
+	{
837
+		if ($limit) {
838
+			$query_params['limit'] = $limit;
839
+		}
840
+		return $query_params;
841
+	}
842
+
843
+
844
+	/**
845
+	 * @param array  $query_params
846
+	 * @param string $order_by
847
+	 * @param string $order
848
+	 * @return array
849
+	 * @since   $VID:$
850
+	 */
851
+	private function addOrderByQueryParams(array $query_params,
852
+										   string $order_by = 'DTT_EVT_start',
853
+										   string $order = 'ASC'): array
854
+	{
855
+		$order                    = $order === 'ASC' ? 'ASC' : 'DESC';
856
+		$valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
857
+		$order_by                 = in_array($order_by, $valid_order_columns, true)
858
+			? $order_by
859
+			: 'DTT_EVT_start';
860
+		$query_params['order_by'] = [$order_by => $order];
861
+		return $query_params;
862
+	}
863 863
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
                 ),
122 122
             ],
123 123
         ];
124
-        $this->_model_relations        = [
124
+        $this->_model_relations = [
125 125
             'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
126 126
             'Event'           => new EE_Belongs_To_Relation(),
127 127
             'Checkin'         => new EE_Has_Many_Relation(),
@@ -131,18 +131,18 @@  discard block
 block discarded – undo
131 131
         $this->model_chain_to_password = $path_to_event_model;
132 132
         $this->_model_chain_to_wp_user = $path_to_event_model;
133 133
         // this model is generally available for reading
134
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
134
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public(
135 135
             $path_to_event_model
136 136
         );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
137
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin]
138 138
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
139 139
             $path_to_event_model
140 140
         );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
141
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]
142 142
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
143 143
             $path_to_event_model
144 144
         );
145
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
145
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]
146 146
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
147 147
             $path_to_event_model,
148 148
             EEM_Base::caps_edit
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
          * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185 185
          * @return int Unix timestamp
186 186
          */
187
-        $end_date       = apply_filters(
187
+        $end_date = apply_filters(
188 188
             'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189 189
             $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190 190
         );
@@ -250,10 +250,10 @@  discard block
 block discarded – undo
250 250
      */
251 251
     private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252 252
     {
253
-        if (! is_array($start_time)) {
253
+        if ( ! is_array($start_time)) {
254 254
             throw new InvalidDataTypeException('start_time', $start_time, 'array');
255 255
         }
256
-        if (! is_array($end_time)) {
256
+        if ( ! is_array($end_time)) {
257 257
             throw new InvalidDataTypeException('end_time', $end_time, 'array');
258 258
         }
259 259
         if (count($start_time) !== 2) {
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     public function get_all_event_dates(int $EVT_ID = 0): array
290 290
     {
291
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
291
+        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
292 292
             return $this->create_new_blank_datetime();
293 293
         }
294 294
         $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
             $query_params,
431 431
             EEM_Base::default_where_conditions_this_only
432 432
         );
433
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
433
+        $query_params = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434 434
         return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435 435
     }
436 436
 
@@ -595,14 +595,14 @@  discard block
 block discarded – undo
595 595
         $query_params['group_by'] = ['dtt_year', 'dtt_month'];
596 596
         $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597 597
 
598
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
598
+        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599 599
             $this->get_timezone(),
600 600
             'DTT_EVT_start'
601 601
         );
602 602
         $columns_to_select = [
603
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
603
+            'dtt_year'      => ['YEAR('.$query_interval.')', '%s'],
604
+            'dtt_month'     => ['MONTHNAME('.$query_interval.')', '%s'],
605
+            'dtt_month_num' => ['MONTH('.$query_interval.')', '%s'],
606 606
         ];
607 607
         return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608 608
     }
@@ -685,17 +685,17 @@  discard block
 block discarded – undo
685 685
                 ['DTT_EVT_end' => ['<', time()]]
686 686
             ),
687 687
         ];
688
-        if (! empty($include)) {
688
+        if ( ! empty($include)) {
689 689
             foreach (array_keys($status_query_args) as $status) {
690
-                if (! in_array($status, $include, true)) {
691
-                    unset($status_query_args[ $status ]);
690
+                if ( ! in_array($status, $include, true)) {
691
+                    unset($status_query_args[$status]);
692 692
                 }
693 693
             }
694 694
         }
695 695
         // loop through and query counts for each statuses.
696 696
         $status_query_results = [];
697 697
         foreach ($status_query_args as $status => $status_where_conditions) {
698
-            $status_query_results[ $status ] = EEM_Datetime::count(
698
+            $status_query_results[$status] = EEM_Datetime::count(
699 699
                 [$status_where_conditions],
700 700
                 'DTT_ID',
701 701
                 true
@@ -717,7 +717,7 @@  discard block
 block discarded – undo
717 717
     public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718 718
     {
719 719
         $count = $this->get_datetime_counts_by_status([$status], $query_params);
720
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
720
+        return ! empty($count[$status]) ? $count[$status] : 0;
721 721
     }
722 722
 
723 723
 
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
      */
820 820
     private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821 821
     {
822
-        if (! $include_expired) {
822
+        if ( ! $include_expired) {
823 823
             $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824 824
         }
825 825
         return $where_params;
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -314,7 +314,7 @@
 block discarded – undo
314 314
     /**
315 315
      * Used to override the default for the additional limit field.
316 316
      *
317
-     * @param $additional_limit
317
+     * @param integer $additional_limit
318 318
      */
319 319
     public static function set_default_additional_limit($additional_limit)
320 320
     {
Please login to merge, or discard this patch.
Indentation   +948 added lines, -948 removed lines patch added patch discarded remove patch
@@ -14,952 +14,952 @@
 block discarded – undo
14 14
 class EEM_Event extends EEM_CPT_Base
15 15
 {
16 16
 
17
-    /**
18
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
-     * event
20
-     */
21
-    const sold_out = 'sold_out';
22
-
23
-    /**
24
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
-     * date)
26
-     */
27
-    const postponed = 'postponed';
28
-
29
-    /**
30
-     * constant used by status(), indicating that the event will no longer occur
31
-     */
32
-    const cancelled = 'cancelled';
33
-
34
-
35
-    /**
36
-     * @var string
37
-     */
38
-    protected static $_default_reg_status;
39
-
40
-
41
-    /**
42
-     * This is the default for the additional limit field.
43
-     *
44
-     * @var int
45
-     */
46
-    protected static $_default_additional_limit = 10;
47
-
48
-
49
-    /**
50
-     * private instance of the Event object
51
-     *
52
-     * @var EEM_Event
53
-     */
54
-    protected static $_instance;
55
-
56
-
57
-    /**
58
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
59
-     *
60
-     * @param string $timezone
61
-     * @throws EE_Error
62
-     * @throws ReflectionException
63
-     */
64
-    protected function __construct(string $timezone = '')
65
-    {
66
-        EE_Registry::instance()->load_model('Registration');
67
-        $this->singular_item = esc_html__('Event', 'event_espresso');
68
-        $this->plural_item   = esc_html__('Events', 'event_espresso');
69
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
70
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
71
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
72
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
-        $this->_custom_stati       = apply_filters(
76
-            'AFEE__EEM_Event__construct___custom_stati',
77
-            [
78
-                EEM_Event::cancelled => [
79
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
80
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
81
-                ],
82
-                EEM_Event::postponed => [
83
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
84
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
85
-                ],
86
-                EEM_Event::sold_out  => [
87
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
88
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
89
-                ],
90
-            ]
91
-        );
92
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
93
-            : self::$_default_reg_status;
94
-        $this->_tables             = [
95
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97
-        ];
98
-        $this->_fields             = [
99
-            'Event_CPT'  => [
100
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
101
-                    'ID',
102
-                    esc_html__('Post ID for Event', 'event_espresso')
103
-                ),
104
-                'EVT_name'       => new EE_Plain_Text_Field(
105
-                    'post_title',
106
-                    esc_html__('Event Name', 'event_espresso'),
107
-                    false,
108
-                    ''
109
-                ),
110
-                'EVT_desc'       => new EE_Post_Content_Field(
111
-                    'post_content',
112
-                    esc_html__('Event Description', 'event_espresso'),
113
-                    false,
114
-                    ''
115
-                ),
116
-                'EVT_slug'       => new EE_Slug_Field(
117
-                    'post_name',
118
-                    esc_html__('Event Slug', 'event_espresso'),
119
-                    false,
120
-                    ''
121
-                ),
122
-                'EVT_created'    => new EE_Datetime_Field(
123
-                    'post_date',
124
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
125
-                    false,
126
-                    EE_Datetime_Field::now
127
-                ),
128
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
129
-                    'post_excerpt',
130
-                    esc_html__('Event Short Description', 'event_espresso'),
131
-                    false,
132
-                    ''
133
-                ),
134
-                'EVT_modified'   => new EE_Datetime_Field(
135
-                    'post_modified',
136
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
137
-                    false,
138
-                    EE_Datetime_Field::now
139
-                ),
140
-                'EVT_wp_user'    => new EE_WP_User_Field(
141
-                    'post_author',
142
-                    esc_html__('Event Creator ID', 'event_espresso'),
143
-                    false
144
-                ),
145
-                'parent'         => new EE_Integer_Field(
146
-                    'post_parent',
147
-                    esc_html__('Event Parent ID', 'event_espresso'),
148
-                    false,
149
-                    0
150
-                ),
151
-                'EVT_order'      => new EE_Integer_Field(
152
-                    'menu_order',
153
-                    esc_html__('Event Menu Order', 'event_espresso'),
154
-                    false,
155
-                    1
156
-                ),
157
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
158
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
159
-                'status'         => new EE_WP_Post_Status_Field(
160
-                    'post_status',
161
-                    esc_html__('Event Status', 'event_espresso'),
162
-                    false,
163
-                    'draft',
164
-                    $this->_custom_stati
165
-                ),
166
-                'password'       => new EE_Password_Field(
167
-                    'post_password',
168
-                    esc_html__('Password', 'event_espresso'),
169
-                    false,
170
-                    '',
171
-                    [
172
-                        'EVT_desc',
173
-                        'EVT_short_desc',
174
-                        'EVT_display_desc',
175
-                        'EVT_display_ticket_selector',
176
-                        'EVT_visible_on',
177
-                        'EVT_additional_limit',
178
-                        'EVT_default_registration_status',
179
-                        'EVT_member_only',
180
-                        'EVT_phone',
181
-                        'EVT_allow_overflow',
182
-                        'EVT_timezone_string',
183
-                        'EVT_external_URL',
184
-                        'EVT_donations',
185
-                    ]
186
-                ),
187
-            ],
188
-            'Event_Meta' => [
189
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
190
-                    'EVTM_ID',
191
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
192
-                    false
193
-                ),
194
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
195
-                    'EVT_ID',
196
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
197
-                    false
198
-                ),
199
-                'EVT_display_desc'                => new EE_Boolean_Field(
200
-                    'EVT_display_desc',
201
-                    esc_html__('Display Description Flag', 'event_espresso'),
202
-                    false,
203
-                    true
204
-                ),
205
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
206
-                    'EVT_display_ticket_selector',
207
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
208
-                    false,
209
-                    true
210
-                ),
211
-                'EVT_visible_on'                  => new EE_Datetime_Field(
212
-                    'EVT_visible_on',
213
-                    esc_html__('Event Visible Date', 'event_espresso'),
214
-                    true,
215
-                    EE_Datetime_Field::now
216
-                ),
217
-                'EVT_additional_limit'            => new EE_Integer_Field(
218
-                    'EVT_additional_limit',
219
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
220
-                    true,
221
-                    self::$_default_additional_limit
222
-                ),
223
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
224
-                    'EVT_default_registration_status',
225
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
226
-                    false,
227
-                    EEM_Event::$_default_reg_status,
228
-                    EEM_Registration::reg_status_array()
229
-                ),
230
-                'EVT_member_only'                 => new EE_Boolean_Field(
231
-                    'EVT_member_only',
232
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
233
-                    false,
234
-                    false
235
-                ),
236
-                'EVT_phone'                       => new EE_Plain_Text_Field(
237
-                    'EVT_phone',
238
-                    esc_html__('Event Phone Number', 'event_espresso'),
239
-                    false,
240
-                    ''
241
-                ),
242
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
243
-                    'EVT_allow_overflow',
244
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
245
-                    false,
246
-                    false
247
-                ),
248
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
249
-                    'EVT_timezone_string',
250
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
251
-                    false,
252
-                    ''
253
-                ),
254
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
255
-                    'EVT_external_URL',
256
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
257
-                    true
258
-                ),
259
-                'EVT_donations'                   => new EE_Boolean_Field(
260
-                    'EVT_donations',
261
-                    esc_html__('Accept Donations?', 'event_espresso'),
262
-                    false,
263
-                    false
264
-                ),
265
-            ],
266
-        ];
267
-        $this->_model_relations    = [
268
-            'Registration'           => new EE_Has_Many_Relation(),
269
-            'Datetime'               => new EE_Has_Many_Relation(),
270
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
271
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
272
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
273
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
274
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
275
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
276
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
277
-            'WP_User'                => new EE_Belongs_To_Relation(),
278
-        ];
279
-        // this model is generally available for reading
280
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
-        $this->model_chain_to_password                            = '';
282
-        parent::__construct($timezone);
283
-    }
284
-
285
-
286
-    /**
287
-     * @param string $default_reg_status
288
-     * @throws EE_Error
289
-     * @throws EE_Error
290
-     */
291
-    public static function set_default_reg_status(string $default_reg_status)
292
-    {
293
-        self::$_default_reg_status = $default_reg_status;
294
-        // if EEM_Event has already been instantiated,
295
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
296
-        if (self::$_instance instanceof EEM_Event) {
297
-            $default_reg_status = new EE_Enum_Text_Field(
298
-                'EVT_default_registration_status',
299
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
-                false,
301
-                $default_reg_status,
302
-                EEM_Registration::reg_status_array()
303
-            );
304
-            $default_reg_status->_construct_finalize(
305
-                'Event_Meta',
306
-                'EVT_default_registration_status',
307
-                'EEM_Event'
308
-            );
309
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
-        }
311
-    }
312
-
313
-
314
-    /**
315
-     * Used to override the default for the additional limit field.
316
-     *
317
-     * @param $additional_limit
318
-     */
319
-    public static function set_default_additional_limit($additional_limit)
320
-    {
321
-        self::$_default_additional_limit = (int) $additional_limit;
322
-        if (self::$_instance instanceof EEM_Event) {
323
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
324
-                'EVT_additional_limit',
325
-                esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
326
-                true,
327
-                self::$_default_additional_limit
328
-            );
329
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
330
-                'Event_Meta',
331
-                'EVT_additional_limit',
332
-                'EEM_Event'
333
-            );
334
-        }
335
-    }
336
-
337
-
338
-    /**
339
-     * Return what is currently set as the default additional limit for the event.
340
-     *
341
-     * @return int
342
-     */
343
-    public static function get_default_additional_limit(): int
344
-    {
345
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
346
-    }
347
-
348
-
349
-    /**
350
-     * get_question_groups
351
-     *
352
-     * @return array
353
-     * @throws EE_Error
354
-     * @throws ReflectionException
355
-     */
356
-    public function get_all_question_groups(): array
357
-    {
358
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
359
-            [
360
-                ['QSG_deleted' => false],
361
-                'order_by' => ['QSG_order' => 'ASC'],
362
-            ]
363
-        );
364
-    }
365
-
366
-
367
-    /**
368
-     * get_question_groups
369
-     *
370
-     * @param int $EVT_ID
371
-     * @return array|bool
372
-     * @throws EE_Error
373
-     * @throws ReflectionException
374
-     */
375
-    public function get_all_event_question_groups(int $EVT_ID = 0)
376
-    {
377
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
378
-            EE_Error::add_error(
379
-                esc_html__(
380
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
381
-                    'event_espresso'
382
-                ),
383
-                __FILE__,
384
-                __FUNCTION__,
385
-                __LINE__
386
-            );
387
-            return false;
388
-        }
389
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
390
-            [
391
-                ['EVT_ID' => $EVT_ID],
392
-            ]
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * get_question_groups
399
-     *
400
-     * @param int     $EVT_ID
401
-     * @param boolean $for_primary_attendee
402
-     * @return array|bool
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     * @throws ReflectionException
406
-     * @throws InvalidDataTypeException
407
-     * @throws InvalidInterfaceException
408
-     */
409
-    public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410
-    {
411
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
412
-            EE_Error::add_error(
413
-                esc_html__(
414
-                // @codingStandardsIgnoreStart
415
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
416
-                    // @codingStandardsIgnoreEnd
417
-                    'event_espresso'
418
-                ),
419
-                __FILE__,
420
-                __FUNCTION__,
421
-                __LINE__
422
-            );
423
-            return false;
424
-        }
425
-        $query_params = [
426
-            [
427
-                'EVT_ID'                                                                         => $EVT_ID,
428
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true,
429
-            ],
430
-        ];
431
-        if ($for_primary_attendee) {
432
-            $query_params[0]['EQG_primary'] = true;
433
-        } else {
434
-            $query_params[0]['EQG_additional'] = true;
435
-        }
436
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
437
-    }
438
-
439
-
440
-    /**
441
-     * get_question_groups
442
-     *
443
-     * @param int             $EVT_ID
444
-     * @param EE_Registration $registration
445
-     * @return array|bool
446
-     * @throws EE_Error
447
-     * @throws InvalidArgumentException
448
-     * @throws InvalidDataTypeException
449
-     * @throws InvalidInterfaceException
450
-     * @throws ReflectionException
451
-     */
452
-    public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453
-    {
454
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
455
-            EE_Error::add_error(
456
-                esc_html__(
457
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
458
-                    'event_espresso'
459
-                ),
460
-                __FILE__,
461
-                __FUNCTION__,
462
-                __LINE__
463
-            );
464
-            return false;
465
-        }
466
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
467
-            [
468
-                [
469
-                    'Event_Question_Group.EVT_ID' => $EVT_ID,
470
-                    'Event_Question_Group.'
471
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext(
472
-                        $registration->is_primary_registrant()
473
-                    )                             => true,
474
-                ],
475
-                'order_by' => ['QSG_order' => 'ASC'],
476
-            ]
477
-        );
478
-    }
479
-
480
-
481
-    /**
482
-     * get_question_target_db_column
483
-     *
484
-     * @param string $QSG_IDs csv list of $QSG IDs
485
-     * @return array|bool
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     */
489
-    public function get_questions_in_groups(string $QSG_IDs = '')
490
-    {
491
-        if (empty($QSG_IDs)) {
492
-            EE_Error::add_error(
493
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
494
-                __FILE__,
495
-                __FUNCTION__,
496
-                __LINE__
497
-            );
498
-            return false;
499
-        }
500
-        return EE_Registry::instance()->load_model('Question')->get_all(
501
-            [
502
-                [
503
-                    'Question_Group.QSG_ID' => ['IN', $QSG_IDs],
504
-                    'QST_deleted'           => false,
505
-                    'QST_admin_only'        => is_admin(),
506
-                ],
507
-                'order_by' => 'QST_order',
508
-            ]
509
-        );
510
-    }
511
-
512
-
513
-    /**
514
-     * get_options_for_question
515
-     *
516
-     * @param string $QST_IDs csv list of $QST IDs
517
-     * @return array|bool
518
-     * @throws EE_Error
519
-     * @throws ReflectionException
520
-     */
521
-    public function get_options_for_question(string $QST_IDs)
522
-    {
523
-        if (empty($QST_IDs)) {
524
-            EE_Error::add_error(
525
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
526
-                __FILE__,
527
-                __FUNCTION__,
528
-                __LINE__
529
-            );
530
-            return false;
531
-        }
532
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
533
-            [
534
-                [
535
-                    'Question.QST_ID' => ['IN', $QST_IDs],
536
-                    'QSO_deleted'     => false,
537
-                ],
538
-                'order_by' => 'QSO_ID',
539
-            ]
540
-        );
541
-    }
542
-
543
-
544
-    /**
545
-     * Gets all events that are published
546
-     * and have event start time earlier than now and an event end time later than now
547
-     *
548
-     * @param array $query_params  An array of query params to further filter on
549
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
550
-     * @param bool  $count         whether to return the count or not (default FALSE)
551
-     * @return EE_Event[]|int
552
-     * @throws EE_Error
553
-     * @throws ReflectionException
554
-     */
555
-    public function get_active_events(array $query_params, bool $count = false)
556
-    {
557
-        if (array_key_exists(0, $query_params)) {
558
-            $where_params = $query_params[0];
559
-            unset($query_params[0]);
560
-        } else {
561
-            $where_params = [];
562
-        }
563
-        // if we have count make sure we don't include group by
564
-        if ($count && isset($query_params['group_by'])) {
565
-            unset($query_params['group_by']);
566
-        }
567
-        // let's add specific query_params for active_events
568
-        // keep in mind this will override any sent status in the query AND any date queries.
569
-        $where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
570
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
571
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
572
-            $where_params['Datetime.DTT_EVT_start******'] = [
573
-                '<',
574
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
575
-            ];
576
-        } else {
577
-            $where_params['Datetime.DTT_EVT_start'] = [
578
-                '<',
579
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
580
-            ];
581
-        }
582
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
583
-            $where_params['Datetime.DTT_EVT_end*****'] = [
584
-                '>',
585
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
586
-            ];
587
-        } else {
588
-            $where_params['Datetime.DTT_EVT_end'] = [
589
-                '>',
590
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
591
-            ];
592
-        }
593
-        $query_params[0] = $where_params;
594
-        // don't use $query_params with count()
595
-        // because we don't want to include additional query clauses like "GROUP BY"
596
-        return $count
597
-            ? $this->count([$where_params], 'EVT_ID', true)
598
-            : $this->get_all($query_params);
599
-    }
600
-
601
-
602
-    /**
603
-     * get all events that are published and have an event start time later than now
604
-     *
605
-     * @param array $query_params  An array of query params to further filter on
606
-     *                             (Note that status and DTT_EVT_start will be overridden)
607
-     * @param bool  $count         whether to return the count or not (default FALSE)
608
-     * @return EE_Event[]|int
609
-     * @throws EE_Error
610
-     * @throws ReflectionException
611
-     */
612
-    public function get_upcoming_events(array $query_params, bool $count = false)
613
-    {
614
-        if (array_key_exists(0, $query_params)) {
615
-            $where_params = $query_params[0];
616
-            unset($query_params[0]);
617
-        } else {
618
-            $where_params = [];
619
-        }
620
-        // if we have count make sure we don't include group by
621
-        if ($count && isset($query_params['group_by'])) {
622
-            unset($query_params['group_by']);
623
-        }
624
-        // let's add specific query_params for active_events
625
-        // keep in mind this will override any sent status in the query AND any date queries.
626
-        // we need to pull events with a status of publish and sold_out
627
-        $event_status = ['publish', EEM_Event::sold_out];
628
-        // check if the user can read private events and if so add the 'private status to the were params'
629
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
630
-            $event_status[] = 'private';
631
-        }
632
-        $where_params['status'] = ['IN', $event_status];
633
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
634
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
635
-            $where_params['Datetime.DTT_EVT_start*****'] = [
636
-                '>',
637
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
-            ];
639
-        } else {
640
-            $where_params['Datetime.DTT_EVT_start'] = [
641
-                '>',
642
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
643
-            ];
644
-        }
645
-        $query_params[0] = $where_params;
646
-        // don't use $query_params with count()
647
-        // because we don't want to include additional query clauses like "GROUP BY"
648
-        return $count
649
-            ? $this->count([$where_params], 'EVT_ID', true)
650
-            : $this->get_all($query_params);
651
-    }
652
-
653
-
654
-    /**
655
-     * Gets all events that are published
656
-     * and have an event end time later than now
657
-     *
658
-     * @param array $query_params  An array of query params to further filter on
659
-     *                             (note that status and DTT_EVT_end will be overridden)
660
-     * @param bool  $count         whether to return the count or not (default FALSE)
661
-     * @return EE_Event[]|int
662
-     * @throws EE_Error
663
-     * @throws ReflectionException
664
-     */
665
-    public function get_active_and_upcoming_events(array $query_params, bool $count = false)
666
-    {
667
-        if (array_key_exists(0, $query_params)) {
668
-            $where_params = $query_params[0];
669
-            unset($query_params[0]);
670
-        } else {
671
-            $where_params = [];
672
-        }
673
-        // if we have count make sure we don't include group by
674
-        if ($count && isset($query_params['group_by'])) {
675
-            unset($query_params['group_by']);
676
-        }
677
-        // let's add specific query_params for active_events
678
-        // keep in mind this will override any sent status in the query AND any date queries.
679
-        $where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
680
-        // add where params for DTT_EVT_end
681
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
682
-            $where_params['Datetime.DTT_EVT_end*****'] = [
683
-                '>',
684
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
-            ];
686
-        } else {
687
-            $where_params['Datetime.DTT_EVT_end'] = [
688
-                '>',
689
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
690
-            ];
691
-        }
692
-        $query_params[0] = $where_params;
693
-        // don't use $query_params with count()
694
-        // because we don't want to include additional query clauses like "GROUP BY"
695
-        return $count
696
-            ? $this->count([$where_params], 'EVT_ID', true)
697
-            : $this->get_all($query_params);
698
-    }
699
-
700
-
701
-    /**
702
-     * This only returns events that are expired.
703
-     * They may still be published but all their datetimes have expired.
704
-     *
705
-     * @param array $query_params  An array of query params to further filter on
706
-     *                             (note that status and DTT_EVT_end will be overridden)
707
-     * @param bool  $count         whether to return the count or not (default FALSE)
708
-     * @return EE_Event[]|int
709
-     * @throws EE_Error
710
-     * @throws ReflectionException
711
-     */
712
-    public function get_expired_events(array $query_params, bool $count = false)
713
-    {
714
-        $where_params = $query_params[0] ?? [];
715
-        // if we have count make sure we don't include group by
716
-        if ($count && isset($query_params['group_by'])) {
717
-            unset($query_params['group_by']);
718
-        }
719
-        // let's add specific query_params for active_events
720
-        // keep in mind this will override any sent status in the query AND any date queries.
721
-        if (isset($where_params['status'])) {
722
-            unset($where_params['status']);
723
-        }
724
-        $exclude_query = $query_params;
725
-        if (isset($exclude_query[0])) {
726
-            unset($exclude_query[0]);
727
-        }
728
-        $exclude_query[0] = [
729
-            'Datetime.DTT_EVT_end' => [
730
-                '>',
731
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
732
-            ],
733
-        ];
734
-        // first get all events that have datetimes where its not expired.
735
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
736
-        $event_ids = array_keys($event_ids);
737
-        // if we have any additional query_params, let's add them to the 'AND' condition
738
-        $and_condition = [
739
-            'Datetime.DTT_EVT_end' => ['<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')],
740
-            'EVT_ID'               => ['NOT IN', $event_ids],
741
-        ];
742
-        if (isset($where_params['OR'])) {
743
-            $and_condition['OR'] = $where_params['OR'];
744
-            unset($where_params['OR']);
745
-        }
746
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
747
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
748
-            unset($where_params['Datetime.DTT_EVT_end']);
749
-        }
750
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
751
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
752
-            unset($where_params['Datetime.DTT_EVT_start']);
753
-        }
754
-        // merge remaining $where params with the and conditions.
755
-        $where_params['AND'] = array_merge($and_condition, $where_params);
756
-        $query_params[0]     = $where_params;
757
-        // don't use $query_params with count()
758
-        // because we don't want to include additional query clauses like "GROUP BY"
759
-        return $count
760
-            ? $this->count([$where_params], 'EVT_ID', true)
761
-            : $this->get_all($query_params);
762
-    }
763
-
764
-
765
-    /**
766
-     * This basically just returns the events that do not have the publish status.
767
-     *
768
-     * @param array   $query_params  An array of query params to further filter on
769
-     *                               (note that status will be overwritten)
770
-     * @param boolean $count         whether to return the count or not (default FALSE)
771
-     * @return EE_Event[]|int
772
-     * @throws EE_Error
773
-     * @throws ReflectionException
774
-     */
775
-    public function get_inactive_events(array $query_params, bool $count = false)
776
-    {
777
-        $where_params = $query_params[0] ?? [];
778
-        // let's add in specific query_params for inactive events.
779
-        if (isset($where_params['status'])) {
780
-            unset($where_params['status']);
781
-        }
782
-        // if we have count make sure we don't include group by
783
-        if ($count && isset($query_params['group_by'])) {
784
-            unset($query_params['group_by']);
785
-        }
786
-        // if we have any additional query_params, let's add them to the 'AND' condition
787
-        $where_params['AND']['status'] = ['!=', 'publish'];
788
-        if (isset($where_params['OR'])) {
789
-            $where_params['AND']['OR'] = $where_params['OR'];
790
-            unset($where_params['OR']);
791
-        }
792
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
793
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
794
-            unset($where_params['Datetime.DTT_EVT_end']);
795
-        }
796
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
797
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
798
-            unset($where_params['Datetime.DTT_EVT_start']);
799
-        }
800
-        $query_params[0] = $where_params;
801
-        // don't use $query_params with count()
802
-        // because we don't want to include additional query clauses like "GROUP BY"
803
-        return $count
804
-            ? $this->count([$where_params], 'EVT_ID', true)
805
-            : $this->get_all($query_params);
806
-    }
807
-
808
-
809
-    /**
810
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
811
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
812
-     * attached to the event. See parent for param descriptions
813
-     *
814
-     * @param        $id_or_obj
815
-     * @param        $other_model_id_or_obj
816
-     * @param string $relationName
817
-     * @param array  $extra_join_model_fields_n_values
818
-     * @return EE_Base_Class
819
-     * @throws EE_Error
820
-     * @throws ReflectionException
821
-     */
822
-    public function add_relationship_to(
823
-        $id_or_obj,
824
-        $other_model_id_or_obj,
825
-        $relationName,
826
-        $extra_join_model_fields_n_values = []
827
-    ): EE_Base_Class {
828
-        if ($relationName === 'Price') {
829
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
830
-            $price = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
831
-            // if EVT_ID = 0, then this is a default
832
-            if ((int) $price->get('EVT_ID') === 0) {
833
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
834
-                $price->set('PRC_ID', 0);
835
-            }
836
-            // run parent
837
-            return parent::add_relationship_to(
838
-                $id_or_obj,
839
-                $price,
840
-                $relationName,
841
-                $extra_join_model_fields_n_values
842
-            );
843
-        }
844
-        // otherwise carry on as normal
845
-        return parent::add_relationship_to(
846
-            $id_or_obj,
847
-            $other_model_id_or_obj,
848
-            $relationName,
849
-            $extra_join_model_fields_n_values
850
-        );
851
-    }
852
-
853
-
854
-
855
-    /******************** DEPRECATED METHODS ********************/
856
-
857
-
858
-    /**
859
-     * _get_question_target_db_column
860
-     *
861
-     * @param EE_Registration $registration    (so existing answers for registration are included)
862
-     * @param int             $EVT_ID          so all question groups are included for event (not just answers from
863
-     *                                         registration).
864
-     * @return    array
865
-     * @throws ReflectionException
866
-     * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
867
-     *                                         EE_Registration_Custom_Questions_Form located in
868
-     *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
869
-     * @access     public
870
-     */
871
-    public function assemble_array_of_groups_questions_and_options(
872
-        EE_Registration $registration,
873
-        int $EVT_ID = 0
874
-    ): array {
875
-        if (empty($EVT_ID)) {
876
-            throw new EE_Error(
877
-                __(
878
-                    'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
879
-                    'event_espresso'
880
-                )
881
-            );
882
-        }
883
-        $questions = [];
884
-        // get all question groups for event
885
-        $question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
-        if (! empty($question_groups)) {
887
-            foreach ($question_groups as $question_group) {
888
-                $QSG_ID = $question_group->ID();
889
-                $questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
-                $questions[ $QSG_ID ]['QSG_questions'] = [];
891
-                $question_groups_questions                           = $question_group->questions();
892
-                foreach ($question_groups_questions as $question_groups_question) {
893
-                    if ($question_groups_question->is_system_question()) {
894
-                        continue;
895
-                    }
896
-                    $QGQ_ID = $question_groups_question->ID();
897
-                    $answer = EEM_Answer::instance()->get_one(
898
-                        [
899
-                            [
900
-                                'QST_ID' => $QGQ_ID,
901
-                                'REG_ID' => $registration->ID(),
902
-                            ],
903
-                        ]
904
-                    );
905
-                    $answer = $answer instanceof EE_Answer
906
-                        ? $answer
907
-                        : EEM_Answer::instance()->create_default_object();
908
-                    $question_name = $question_id = $QGQ_ID;
909
-                    $ANS_ID = $answer->ID();
910
-                    $question_name = ! empty($ANS_ID)
911
-                        ? '[' . $question_name . '][' . $ANS_ID . ']'
912
-                        : '[' . $question_name . ']';
913
-                    $input_name = '';
914
-                    $input_id = sanitize_key($question_groups_question->display_text());
915
-                    $input_class
916
-                            = '';
917
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
918
-                            = $question_groups_question->model_field_array();
919
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
920
-                                                                                           . $input_name
921
-                                                                                           . $question_name;
922
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
927
-                    // leave responses as-is, don't convert stuff into html entities please!
928
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
929
-                    if (
930
-                        $question_groups_question->type() == 'RADIO_BTN'
931
-                        || $question_groups_question->type() == 'CHECKBOX'
932
-                        || $question_groups_question->type() == 'DROPDOWN'
933
-                    ) {
934
-                        $question_options = $question_groups_question->options(true, $answer->value());
935
-                        if (is_array($question_options)) {
936
-                            foreach ($question_options as $QSO_ID => $question_option) {
937
-                                $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
938
-                                    = $question_option->model_field_array();
939
-                            }
940
-                        }
941
-                    }
942
-                }
943
-            }
944
-        }
945
-        return $questions;
946
-    }
947
-
948
-
949
-    /**
950
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
951
-     *                             or an stdClass where each property is the name of a column,
952
-     * @return EE_Base_Class
953
-     * @throws EE_Error
954
-     * @throws ReflectionException
955
-     */
956
-    public function instantiate_class_from_array_or_object($cols_n_values)
957
-    {
958
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
959
-        if ($classInstance instanceof EE_Event) {
960
-            // events have their timezone defined in the DB, so use it immediately
961
-            $this->set_timezone($classInstance->get_timezone());
962
-        }
963
-        return $classInstance;
964
-    }
17
+	/**
18
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
+	 * event
20
+	 */
21
+	const sold_out = 'sold_out';
22
+
23
+	/**
24
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
+	 * date)
26
+	 */
27
+	const postponed = 'postponed';
28
+
29
+	/**
30
+	 * constant used by status(), indicating that the event will no longer occur
31
+	 */
32
+	const cancelled = 'cancelled';
33
+
34
+
35
+	/**
36
+	 * @var string
37
+	 */
38
+	protected static $_default_reg_status;
39
+
40
+
41
+	/**
42
+	 * This is the default for the additional limit field.
43
+	 *
44
+	 * @var int
45
+	 */
46
+	protected static $_default_additional_limit = 10;
47
+
48
+
49
+	/**
50
+	 * private instance of the Event object
51
+	 *
52
+	 * @var EEM_Event
53
+	 */
54
+	protected static $_instance;
55
+
56
+
57
+	/**
58
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
59
+	 *
60
+	 * @param string $timezone
61
+	 * @throws EE_Error
62
+	 * @throws ReflectionException
63
+	 */
64
+	protected function __construct(string $timezone = '')
65
+	{
66
+		EE_Registry::instance()->load_model('Registration');
67
+		$this->singular_item = esc_html__('Event', 'event_espresso');
68
+		$this->plural_item   = esc_html__('Events', 'event_espresso');
69
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
70
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
71
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
72
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
+		$this->_custom_stati       = apply_filters(
76
+			'AFEE__EEM_Event__construct___custom_stati',
77
+			[
78
+				EEM_Event::cancelled => [
79
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
80
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
81
+				],
82
+				EEM_Event::postponed => [
83
+					'label'  => esc_html__('Postponed', 'event_espresso'),
84
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
85
+				],
86
+				EEM_Event::sold_out  => [
87
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
88
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
89
+				],
90
+			]
91
+		);
92
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
93
+			: self::$_default_reg_status;
94
+		$this->_tables             = [
95
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97
+		];
98
+		$this->_fields             = [
99
+			'Event_CPT'  => [
100
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
101
+					'ID',
102
+					esc_html__('Post ID for Event', 'event_espresso')
103
+				),
104
+				'EVT_name'       => new EE_Plain_Text_Field(
105
+					'post_title',
106
+					esc_html__('Event Name', 'event_espresso'),
107
+					false,
108
+					''
109
+				),
110
+				'EVT_desc'       => new EE_Post_Content_Field(
111
+					'post_content',
112
+					esc_html__('Event Description', 'event_espresso'),
113
+					false,
114
+					''
115
+				),
116
+				'EVT_slug'       => new EE_Slug_Field(
117
+					'post_name',
118
+					esc_html__('Event Slug', 'event_espresso'),
119
+					false,
120
+					''
121
+				),
122
+				'EVT_created'    => new EE_Datetime_Field(
123
+					'post_date',
124
+					esc_html__('Date/Time Event Created', 'event_espresso'),
125
+					false,
126
+					EE_Datetime_Field::now
127
+				),
128
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
129
+					'post_excerpt',
130
+					esc_html__('Event Short Description', 'event_espresso'),
131
+					false,
132
+					''
133
+				),
134
+				'EVT_modified'   => new EE_Datetime_Field(
135
+					'post_modified',
136
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
137
+					false,
138
+					EE_Datetime_Field::now
139
+				),
140
+				'EVT_wp_user'    => new EE_WP_User_Field(
141
+					'post_author',
142
+					esc_html__('Event Creator ID', 'event_espresso'),
143
+					false
144
+				),
145
+				'parent'         => new EE_Integer_Field(
146
+					'post_parent',
147
+					esc_html__('Event Parent ID', 'event_espresso'),
148
+					false,
149
+					0
150
+				),
151
+				'EVT_order'      => new EE_Integer_Field(
152
+					'menu_order',
153
+					esc_html__('Event Menu Order', 'event_espresso'),
154
+					false,
155
+					1
156
+				),
157
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
158
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
159
+				'status'         => new EE_WP_Post_Status_Field(
160
+					'post_status',
161
+					esc_html__('Event Status', 'event_espresso'),
162
+					false,
163
+					'draft',
164
+					$this->_custom_stati
165
+				),
166
+				'password'       => new EE_Password_Field(
167
+					'post_password',
168
+					esc_html__('Password', 'event_espresso'),
169
+					false,
170
+					'',
171
+					[
172
+						'EVT_desc',
173
+						'EVT_short_desc',
174
+						'EVT_display_desc',
175
+						'EVT_display_ticket_selector',
176
+						'EVT_visible_on',
177
+						'EVT_additional_limit',
178
+						'EVT_default_registration_status',
179
+						'EVT_member_only',
180
+						'EVT_phone',
181
+						'EVT_allow_overflow',
182
+						'EVT_timezone_string',
183
+						'EVT_external_URL',
184
+						'EVT_donations',
185
+					]
186
+				),
187
+			],
188
+			'Event_Meta' => [
189
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
190
+					'EVTM_ID',
191
+					esc_html__('Event Meta Row ID', 'event_espresso'),
192
+					false
193
+				),
194
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
195
+					'EVT_ID',
196
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
197
+					false
198
+				),
199
+				'EVT_display_desc'                => new EE_Boolean_Field(
200
+					'EVT_display_desc',
201
+					esc_html__('Display Description Flag', 'event_espresso'),
202
+					false,
203
+					true
204
+				),
205
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
206
+					'EVT_display_ticket_selector',
207
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
208
+					false,
209
+					true
210
+				),
211
+				'EVT_visible_on'                  => new EE_Datetime_Field(
212
+					'EVT_visible_on',
213
+					esc_html__('Event Visible Date', 'event_espresso'),
214
+					true,
215
+					EE_Datetime_Field::now
216
+				),
217
+				'EVT_additional_limit'            => new EE_Integer_Field(
218
+					'EVT_additional_limit',
219
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
220
+					true,
221
+					self::$_default_additional_limit
222
+				),
223
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
224
+					'EVT_default_registration_status',
225
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
226
+					false,
227
+					EEM_Event::$_default_reg_status,
228
+					EEM_Registration::reg_status_array()
229
+				),
230
+				'EVT_member_only'                 => new EE_Boolean_Field(
231
+					'EVT_member_only',
232
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
233
+					false,
234
+					false
235
+				),
236
+				'EVT_phone'                       => new EE_Plain_Text_Field(
237
+					'EVT_phone',
238
+					esc_html__('Event Phone Number', 'event_espresso'),
239
+					false,
240
+					''
241
+				),
242
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
243
+					'EVT_allow_overflow',
244
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
245
+					false,
246
+					false
247
+				),
248
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
249
+					'EVT_timezone_string',
250
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
251
+					false,
252
+					''
253
+				),
254
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
255
+					'EVT_external_URL',
256
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
257
+					true
258
+				),
259
+				'EVT_donations'                   => new EE_Boolean_Field(
260
+					'EVT_donations',
261
+					esc_html__('Accept Donations?', 'event_espresso'),
262
+					false,
263
+					false
264
+				),
265
+			],
266
+		];
267
+		$this->_model_relations    = [
268
+			'Registration'           => new EE_Has_Many_Relation(),
269
+			'Datetime'               => new EE_Has_Many_Relation(),
270
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
271
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
272
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
273
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
274
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
275
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
276
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
277
+			'WP_User'                => new EE_Belongs_To_Relation(),
278
+		];
279
+		// this model is generally available for reading
280
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
+		$this->model_chain_to_password                            = '';
282
+		parent::__construct($timezone);
283
+	}
284
+
285
+
286
+	/**
287
+	 * @param string $default_reg_status
288
+	 * @throws EE_Error
289
+	 * @throws EE_Error
290
+	 */
291
+	public static function set_default_reg_status(string $default_reg_status)
292
+	{
293
+		self::$_default_reg_status = $default_reg_status;
294
+		// if EEM_Event has already been instantiated,
295
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
296
+		if (self::$_instance instanceof EEM_Event) {
297
+			$default_reg_status = new EE_Enum_Text_Field(
298
+				'EVT_default_registration_status',
299
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
+				false,
301
+				$default_reg_status,
302
+				EEM_Registration::reg_status_array()
303
+			);
304
+			$default_reg_status->_construct_finalize(
305
+				'Event_Meta',
306
+				'EVT_default_registration_status',
307
+				'EEM_Event'
308
+			);
309
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
+		}
311
+	}
312
+
313
+
314
+	/**
315
+	 * Used to override the default for the additional limit field.
316
+	 *
317
+	 * @param $additional_limit
318
+	 */
319
+	public static function set_default_additional_limit($additional_limit)
320
+	{
321
+		self::$_default_additional_limit = (int) $additional_limit;
322
+		if (self::$_instance instanceof EEM_Event) {
323
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
324
+				'EVT_additional_limit',
325
+				esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
326
+				true,
327
+				self::$_default_additional_limit
328
+			);
329
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
330
+				'Event_Meta',
331
+				'EVT_additional_limit',
332
+				'EEM_Event'
333
+			);
334
+		}
335
+	}
336
+
337
+
338
+	/**
339
+	 * Return what is currently set as the default additional limit for the event.
340
+	 *
341
+	 * @return int
342
+	 */
343
+	public static function get_default_additional_limit(): int
344
+	{
345
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
346
+	}
347
+
348
+
349
+	/**
350
+	 * get_question_groups
351
+	 *
352
+	 * @return array
353
+	 * @throws EE_Error
354
+	 * @throws ReflectionException
355
+	 */
356
+	public function get_all_question_groups(): array
357
+	{
358
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
359
+			[
360
+				['QSG_deleted' => false],
361
+				'order_by' => ['QSG_order' => 'ASC'],
362
+			]
363
+		);
364
+	}
365
+
366
+
367
+	/**
368
+	 * get_question_groups
369
+	 *
370
+	 * @param int $EVT_ID
371
+	 * @return array|bool
372
+	 * @throws EE_Error
373
+	 * @throws ReflectionException
374
+	 */
375
+	public function get_all_event_question_groups(int $EVT_ID = 0)
376
+	{
377
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
378
+			EE_Error::add_error(
379
+				esc_html__(
380
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
381
+					'event_espresso'
382
+				),
383
+				__FILE__,
384
+				__FUNCTION__,
385
+				__LINE__
386
+			);
387
+			return false;
388
+		}
389
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
390
+			[
391
+				['EVT_ID' => $EVT_ID],
392
+			]
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * get_question_groups
399
+	 *
400
+	 * @param int     $EVT_ID
401
+	 * @param boolean $for_primary_attendee
402
+	 * @return array|bool
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 * @throws ReflectionException
406
+	 * @throws InvalidDataTypeException
407
+	 * @throws InvalidInterfaceException
408
+	 */
409
+	public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410
+	{
411
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
412
+			EE_Error::add_error(
413
+				esc_html__(
414
+				// @codingStandardsIgnoreStart
415
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
416
+					// @codingStandardsIgnoreEnd
417
+					'event_espresso'
418
+				),
419
+				__FILE__,
420
+				__FUNCTION__,
421
+				__LINE__
422
+			);
423
+			return false;
424
+		}
425
+		$query_params = [
426
+			[
427
+				'EVT_ID'                                                                         => $EVT_ID,
428
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true,
429
+			],
430
+		];
431
+		if ($for_primary_attendee) {
432
+			$query_params[0]['EQG_primary'] = true;
433
+		} else {
434
+			$query_params[0]['EQG_additional'] = true;
435
+		}
436
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
437
+	}
438
+
439
+
440
+	/**
441
+	 * get_question_groups
442
+	 *
443
+	 * @param int             $EVT_ID
444
+	 * @param EE_Registration $registration
445
+	 * @return array|bool
446
+	 * @throws EE_Error
447
+	 * @throws InvalidArgumentException
448
+	 * @throws InvalidDataTypeException
449
+	 * @throws InvalidInterfaceException
450
+	 * @throws ReflectionException
451
+	 */
452
+	public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453
+	{
454
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
455
+			EE_Error::add_error(
456
+				esc_html__(
457
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
458
+					'event_espresso'
459
+				),
460
+				__FILE__,
461
+				__FUNCTION__,
462
+				__LINE__
463
+			);
464
+			return false;
465
+		}
466
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
467
+			[
468
+				[
469
+					'Event_Question_Group.EVT_ID' => $EVT_ID,
470
+					'Event_Question_Group.'
471
+					. EEM_Event_Question_Group::instance()->fieldNameForContext(
472
+						$registration->is_primary_registrant()
473
+					)                             => true,
474
+				],
475
+				'order_by' => ['QSG_order' => 'ASC'],
476
+			]
477
+		);
478
+	}
479
+
480
+
481
+	/**
482
+	 * get_question_target_db_column
483
+	 *
484
+	 * @param string $QSG_IDs csv list of $QSG IDs
485
+	 * @return array|bool
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 */
489
+	public function get_questions_in_groups(string $QSG_IDs = '')
490
+	{
491
+		if (empty($QSG_IDs)) {
492
+			EE_Error::add_error(
493
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
494
+				__FILE__,
495
+				__FUNCTION__,
496
+				__LINE__
497
+			);
498
+			return false;
499
+		}
500
+		return EE_Registry::instance()->load_model('Question')->get_all(
501
+			[
502
+				[
503
+					'Question_Group.QSG_ID' => ['IN', $QSG_IDs],
504
+					'QST_deleted'           => false,
505
+					'QST_admin_only'        => is_admin(),
506
+				],
507
+				'order_by' => 'QST_order',
508
+			]
509
+		);
510
+	}
511
+
512
+
513
+	/**
514
+	 * get_options_for_question
515
+	 *
516
+	 * @param string $QST_IDs csv list of $QST IDs
517
+	 * @return array|bool
518
+	 * @throws EE_Error
519
+	 * @throws ReflectionException
520
+	 */
521
+	public function get_options_for_question(string $QST_IDs)
522
+	{
523
+		if (empty($QST_IDs)) {
524
+			EE_Error::add_error(
525
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
526
+				__FILE__,
527
+				__FUNCTION__,
528
+				__LINE__
529
+			);
530
+			return false;
531
+		}
532
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
533
+			[
534
+				[
535
+					'Question.QST_ID' => ['IN', $QST_IDs],
536
+					'QSO_deleted'     => false,
537
+				],
538
+				'order_by' => 'QSO_ID',
539
+			]
540
+		);
541
+	}
542
+
543
+
544
+	/**
545
+	 * Gets all events that are published
546
+	 * and have event start time earlier than now and an event end time later than now
547
+	 *
548
+	 * @param array $query_params  An array of query params to further filter on
549
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
550
+	 * @param bool  $count         whether to return the count or not (default FALSE)
551
+	 * @return EE_Event[]|int
552
+	 * @throws EE_Error
553
+	 * @throws ReflectionException
554
+	 */
555
+	public function get_active_events(array $query_params, bool $count = false)
556
+	{
557
+		if (array_key_exists(0, $query_params)) {
558
+			$where_params = $query_params[0];
559
+			unset($query_params[0]);
560
+		} else {
561
+			$where_params = [];
562
+		}
563
+		// if we have count make sure we don't include group by
564
+		if ($count && isset($query_params['group_by'])) {
565
+			unset($query_params['group_by']);
566
+		}
567
+		// let's add specific query_params for active_events
568
+		// keep in mind this will override any sent status in the query AND any date queries.
569
+		$where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
570
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
571
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
572
+			$where_params['Datetime.DTT_EVT_start******'] = [
573
+				'<',
574
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
575
+			];
576
+		} else {
577
+			$where_params['Datetime.DTT_EVT_start'] = [
578
+				'<',
579
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
580
+			];
581
+		}
582
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
583
+			$where_params['Datetime.DTT_EVT_end*****'] = [
584
+				'>',
585
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
586
+			];
587
+		} else {
588
+			$where_params['Datetime.DTT_EVT_end'] = [
589
+				'>',
590
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
591
+			];
592
+		}
593
+		$query_params[0] = $where_params;
594
+		// don't use $query_params with count()
595
+		// because we don't want to include additional query clauses like "GROUP BY"
596
+		return $count
597
+			? $this->count([$where_params], 'EVT_ID', true)
598
+			: $this->get_all($query_params);
599
+	}
600
+
601
+
602
+	/**
603
+	 * get all events that are published and have an event start time later than now
604
+	 *
605
+	 * @param array $query_params  An array of query params to further filter on
606
+	 *                             (Note that status and DTT_EVT_start will be overridden)
607
+	 * @param bool  $count         whether to return the count or not (default FALSE)
608
+	 * @return EE_Event[]|int
609
+	 * @throws EE_Error
610
+	 * @throws ReflectionException
611
+	 */
612
+	public function get_upcoming_events(array $query_params, bool $count = false)
613
+	{
614
+		if (array_key_exists(0, $query_params)) {
615
+			$where_params = $query_params[0];
616
+			unset($query_params[0]);
617
+		} else {
618
+			$where_params = [];
619
+		}
620
+		// if we have count make sure we don't include group by
621
+		if ($count && isset($query_params['group_by'])) {
622
+			unset($query_params['group_by']);
623
+		}
624
+		// let's add specific query_params for active_events
625
+		// keep in mind this will override any sent status in the query AND any date queries.
626
+		// we need to pull events with a status of publish and sold_out
627
+		$event_status = ['publish', EEM_Event::sold_out];
628
+		// check if the user can read private events and if so add the 'private status to the were params'
629
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
630
+			$event_status[] = 'private';
631
+		}
632
+		$where_params['status'] = ['IN', $event_status];
633
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
634
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
635
+			$where_params['Datetime.DTT_EVT_start*****'] = [
636
+				'>',
637
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
+			];
639
+		} else {
640
+			$where_params['Datetime.DTT_EVT_start'] = [
641
+				'>',
642
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
643
+			];
644
+		}
645
+		$query_params[0] = $where_params;
646
+		// don't use $query_params with count()
647
+		// because we don't want to include additional query clauses like "GROUP BY"
648
+		return $count
649
+			? $this->count([$where_params], 'EVT_ID', true)
650
+			: $this->get_all($query_params);
651
+	}
652
+
653
+
654
+	/**
655
+	 * Gets all events that are published
656
+	 * and have an event end time later than now
657
+	 *
658
+	 * @param array $query_params  An array of query params to further filter on
659
+	 *                             (note that status and DTT_EVT_end will be overridden)
660
+	 * @param bool  $count         whether to return the count or not (default FALSE)
661
+	 * @return EE_Event[]|int
662
+	 * @throws EE_Error
663
+	 * @throws ReflectionException
664
+	 */
665
+	public function get_active_and_upcoming_events(array $query_params, bool $count = false)
666
+	{
667
+		if (array_key_exists(0, $query_params)) {
668
+			$where_params = $query_params[0];
669
+			unset($query_params[0]);
670
+		} else {
671
+			$where_params = [];
672
+		}
673
+		// if we have count make sure we don't include group by
674
+		if ($count && isset($query_params['group_by'])) {
675
+			unset($query_params['group_by']);
676
+		}
677
+		// let's add specific query_params for active_events
678
+		// keep in mind this will override any sent status in the query AND any date queries.
679
+		$where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
680
+		// add where params for DTT_EVT_end
681
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
682
+			$where_params['Datetime.DTT_EVT_end*****'] = [
683
+				'>',
684
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
+			];
686
+		} else {
687
+			$where_params['Datetime.DTT_EVT_end'] = [
688
+				'>',
689
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
690
+			];
691
+		}
692
+		$query_params[0] = $where_params;
693
+		// don't use $query_params with count()
694
+		// because we don't want to include additional query clauses like "GROUP BY"
695
+		return $count
696
+			? $this->count([$where_params], 'EVT_ID', true)
697
+			: $this->get_all($query_params);
698
+	}
699
+
700
+
701
+	/**
702
+	 * This only returns events that are expired.
703
+	 * They may still be published but all their datetimes have expired.
704
+	 *
705
+	 * @param array $query_params  An array of query params to further filter on
706
+	 *                             (note that status and DTT_EVT_end will be overridden)
707
+	 * @param bool  $count         whether to return the count or not (default FALSE)
708
+	 * @return EE_Event[]|int
709
+	 * @throws EE_Error
710
+	 * @throws ReflectionException
711
+	 */
712
+	public function get_expired_events(array $query_params, bool $count = false)
713
+	{
714
+		$where_params = $query_params[0] ?? [];
715
+		// if we have count make sure we don't include group by
716
+		if ($count && isset($query_params['group_by'])) {
717
+			unset($query_params['group_by']);
718
+		}
719
+		// let's add specific query_params for active_events
720
+		// keep in mind this will override any sent status in the query AND any date queries.
721
+		if (isset($where_params['status'])) {
722
+			unset($where_params['status']);
723
+		}
724
+		$exclude_query = $query_params;
725
+		if (isset($exclude_query[0])) {
726
+			unset($exclude_query[0]);
727
+		}
728
+		$exclude_query[0] = [
729
+			'Datetime.DTT_EVT_end' => [
730
+				'>',
731
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
732
+			],
733
+		];
734
+		// first get all events that have datetimes where its not expired.
735
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
736
+		$event_ids = array_keys($event_ids);
737
+		// if we have any additional query_params, let's add them to the 'AND' condition
738
+		$and_condition = [
739
+			'Datetime.DTT_EVT_end' => ['<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')],
740
+			'EVT_ID'               => ['NOT IN', $event_ids],
741
+		];
742
+		if (isset($where_params['OR'])) {
743
+			$and_condition['OR'] = $where_params['OR'];
744
+			unset($where_params['OR']);
745
+		}
746
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
747
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
748
+			unset($where_params['Datetime.DTT_EVT_end']);
749
+		}
750
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
751
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
752
+			unset($where_params['Datetime.DTT_EVT_start']);
753
+		}
754
+		// merge remaining $where params with the and conditions.
755
+		$where_params['AND'] = array_merge($and_condition, $where_params);
756
+		$query_params[0]     = $where_params;
757
+		// don't use $query_params with count()
758
+		// because we don't want to include additional query clauses like "GROUP BY"
759
+		return $count
760
+			? $this->count([$where_params], 'EVT_ID', true)
761
+			: $this->get_all($query_params);
762
+	}
763
+
764
+
765
+	/**
766
+	 * This basically just returns the events that do not have the publish status.
767
+	 *
768
+	 * @param array   $query_params  An array of query params to further filter on
769
+	 *                               (note that status will be overwritten)
770
+	 * @param boolean $count         whether to return the count or not (default FALSE)
771
+	 * @return EE_Event[]|int
772
+	 * @throws EE_Error
773
+	 * @throws ReflectionException
774
+	 */
775
+	public function get_inactive_events(array $query_params, bool $count = false)
776
+	{
777
+		$where_params = $query_params[0] ?? [];
778
+		// let's add in specific query_params for inactive events.
779
+		if (isset($where_params['status'])) {
780
+			unset($where_params['status']);
781
+		}
782
+		// if we have count make sure we don't include group by
783
+		if ($count && isset($query_params['group_by'])) {
784
+			unset($query_params['group_by']);
785
+		}
786
+		// if we have any additional query_params, let's add them to the 'AND' condition
787
+		$where_params['AND']['status'] = ['!=', 'publish'];
788
+		if (isset($where_params['OR'])) {
789
+			$where_params['AND']['OR'] = $where_params['OR'];
790
+			unset($where_params['OR']);
791
+		}
792
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
793
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
794
+			unset($where_params['Datetime.DTT_EVT_end']);
795
+		}
796
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
797
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
798
+			unset($where_params['Datetime.DTT_EVT_start']);
799
+		}
800
+		$query_params[0] = $where_params;
801
+		// don't use $query_params with count()
802
+		// because we don't want to include additional query clauses like "GROUP BY"
803
+		return $count
804
+			? $this->count([$where_params], 'EVT_ID', true)
805
+			: $this->get_all($query_params);
806
+	}
807
+
808
+
809
+	/**
810
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
811
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
812
+	 * attached to the event. See parent for param descriptions
813
+	 *
814
+	 * @param        $id_or_obj
815
+	 * @param        $other_model_id_or_obj
816
+	 * @param string $relationName
817
+	 * @param array  $extra_join_model_fields_n_values
818
+	 * @return EE_Base_Class
819
+	 * @throws EE_Error
820
+	 * @throws ReflectionException
821
+	 */
822
+	public function add_relationship_to(
823
+		$id_or_obj,
824
+		$other_model_id_or_obj,
825
+		$relationName,
826
+		$extra_join_model_fields_n_values = []
827
+	): EE_Base_Class {
828
+		if ($relationName === 'Price') {
829
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
830
+			$price = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
831
+			// if EVT_ID = 0, then this is a default
832
+			if ((int) $price->get('EVT_ID') === 0) {
833
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
834
+				$price->set('PRC_ID', 0);
835
+			}
836
+			// run parent
837
+			return parent::add_relationship_to(
838
+				$id_or_obj,
839
+				$price,
840
+				$relationName,
841
+				$extra_join_model_fields_n_values
842
+			);
843
+		}
844
+		// otherwise carry on as normal
845
+		return parent::add_relationship_to(
846
+			$id_or_obj,
847
+			$other_model_id_or_obj,
848
+			$relationName,
849
+			$extra_join_model_fields_n_values
850
+		);
851
+	}
852
+
853
+
854
+
855
+	/******************** DEPRECATED METHODS ********************/
856
+
857
+
858
+	/**
859
+	 * _get_question_target_db_column
860
+	 *
861
+	 * @param EE_Registration $registration    (so existing answers for registration are included)
862
+	 * @param int             $EVT_ID          so all question groups are included for event (not just answers from
863
+	 *                                         registration).
864
+	 * @return    array
865
+	 * @throws ReflectionException
866
+	 * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
867
+	 *                                         EE_Registration_Custom_Questions_Form located in
868
+	 *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
869
+	 * @access     public
870
+	 */
871
+	public function assemble_array_of_groups_questions_and_options(
872
+		EE_Registration $registration,
873
+		int $EVT_ID = 0
874
+	): array {
875
+		if (empty($EVT_ID)) {
876
+			throw new EE_Error(
877
+				__(
878
+					'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
879
+					'event_espresso'
880
+				)
881
+			);
882
+		}
883
+		$questions = [];
884
+		// get all question groups for event
885
+		$question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
+		if (! empty($question_groups)) {
887
+			foreach ($question_groups as $question_group) {
888
+				$QSG_ID = $question_group->ID();
889
+				$questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
+				$questions[ $QSG_ID ]['QSG_questions'] = [];
891
+				$question_groups_questions                           = $question_group->questions();
892
+				foreach ($question_groups_questions as $question_groups_question) {
893
+					if ($question_groups_question->is_system_question()) {
894
+						continue;
895
+					}
896
+					$QGQ_ID = $question_groups_question->ID();
897
+					$answer = EEM_Answer::instance()->get_one(
898
+						[
899
+							[
900
+								'QST_ID' => $QGQ_ID,
901
+								'REG_ID' => $registration->ID(),
902
+							],
903
+						]
904
+					);
905
+					$answer = $answer instanceof EE_Answer
906
+						? $answer
907
+						: EEM_Answer::instance()->create_default_object();
908
+					$question_name = $question_id = $QGQ_ID;
909
+					$ANS_ID = $answer->ID();
910
+					$question_name = ! empty($ANS_ID)
911
+						? '[' . $question_name . '][' . $ANS_ID . ']'
912
+						: '[' . $question_name . ']';
913
+					$input_name = '';
914
+					$input_id = sanitize_key($question_groups_question->display_text());
915
+					$input_class
916
+							= '';
917
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
918
+							= $question_groups_question->model_field_array();
919
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
920
+																						   . $input_name
921
+																						   . $question_name;
922
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
927
+					// leave responses as-is, don't convert stuff into html entities please!
928
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
929
+					if (
930
+						$question_groups_question->type() == 'RADIO_BTN'
931
+						|| $question_groups_question->type() == 'CHECKBOX'
932
+						|| $question_groups_question->type() == 'DROPDOWN'
933
+					) {
934
+						$question_options = $question_groups_question->options(true, $answer->value());
935
+						if (is_array($question_options)) {
936
+							foreach ($question_options as $QSO_ID => $question_option) {
937
+								$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
938
+									= $question_option->model_field_array();
939
+							}
940
+						}
941
+					}
942
+				}
943
+			}
944
+		}
945
+		return $questions;
946
+	}
947
+
948
+
949
+	/**
950
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
951
+	 *                             or an stdClass where each property is the name of a column,
952
+	 * @return EE_Base_Class
953
+	 * @throws EE_Error
954
+	 * @throws ReflectionException
955
+	 */
956
+	public function instantiate_class_from_array_or_object($cols_n_values)
957
+	{
958
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
959
+		if ($classInstance instanceof EE_Event) {
960
+			// events have their timezone defined in the DB, so use it immediately
961
+			$this->set_timezone($classInstance->get_timezone());
962
+		}
963
+		return $classInstance;
964
+	}
965 965
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
         // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73 73
         // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74 74
         //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
-        $this->_custom_stati       = apply_filters(
75
+        $this->_custom_stati = apply_filters(
76 76
             'AFEE__EEM_Event__construct___custom_stati',
77 77
             [
78 78
                 EEM_Event::cancelled => [
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
             'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96 96
             'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97 97
         ];
98
-        $this->_fields             = [
98
+        $this->_fields = [
99 99
             'Event_CPT'  => [
100 100
                 'EVT_ID'         => new EE_Primary_Key_Int_Field(
101 101
                     'ID',
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
                 ),
265 265
             ],
266 266
         ];
267
-        $this->_model_relations    = [
267
+        $this->_model_relations = [
268 268
             'Registration'           => new EE_Has_Many_Relation(),
269 269
             'Datetime'               => new EE_Has_Many_Relation(),
270 270
             'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
             'WP_User'                => new EE_Belongs_To_Relation(),
278 278
         ];
279 279
         // this model is generally available for reading
280
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
280
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
281 281
         $this->model_chain_to_password                            = '';
282 282
         parent::__construct($timezone);
283 283
     }
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
      */
375 375
     public function get_all_event_question_groups(int $EVT_ID = 0)
376 376
     {
377
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
377
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
378 378
             EE_Error::add_error(
379 379
                 esc_html__(
380 380
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
      */
409 409
     public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410 410
     {
411
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
411
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
412 412
             EE_Error::add_error(
413 413
                 esc_html__(
414 414
                 // @codingStandardsIgnoreStart
@@ -451,7 +451,7 @@  discard block
 block discarded – undo
451 451
      */
452 452
     public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453 453
     {
454
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
454
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
455 455
             EE_Error::add_error(
456 456
                 esc_html__(
457 457
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -883,12 +883,12 @@  discard block
 block discarded – undo
883 883
         $questions = [];
884 884
         // get all question groups for event
885 885
         $question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
-        if (! empty($question_groups)) {
886
+        if ( ! empty($question_groups)) {
887 887
             foreach ($question_groups as $question_group) {
888 888
                 $QSG_ID = $question_group->ID();
889
-                $questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
-                $questions[ $QSG_ID ]['QSG_questions'] = [];
891
-                $question_groups_questions                           = $question_group->questions();
889
+                $questions[$QSG_ID]                  = $question_group->model_field_array();
890
+                $questions[$QSG_ID]['QSG_questions'] = [];
891
+                $question_groups_questions = $question_group->questions();
892 892
                 foreach ($question_groups_questions as $question_groups_question) {
893 893
                     if ($question_groups_question->is_system_question()) {
894 894
                         continue;
@@ -908,24 +908,24 @@  discard block
 block discarded – undo
908 908
                     $question_name = $question_id = $QGQ_ID;
909 909
                     $ANS_ID = $answer->ID();
910 910
                     $question_name = ! empty($ANS_ID)
911
-                        ? '[' . $question_name . '][' . $ANS_ID . ']'
912
-                        : '[' . $question_name . ']';
911
+                        ? '['.$question_name.']['.$ANS_ID.']'
912
+                        : '['.$question_name.']';
913 913
                     $input_name = '';
914 914
                     $input_id = sanitize_key($question_groups_question->display_text());
915 915
                     $input_class
916 916
                             = '';
917
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
917
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]
918 918
                             = $question_groups_question->model_field_array();
919
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
919
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_name'] = 'qstn'
920 920
                                                                                            . $input_name
921 921
                                                                                            . $question_name;
922
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
922
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_id'] = $input_id.'-'.$question_id;
923
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_class'] = $input_class;
924
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_options'] = [];
925
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['qst_obj'] = $question_groups_question;
926
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['ans_obj'] = $answer;
927 927
                     // leave responses as-is, don't convert stuff into html entities please!
928
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
928
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['htmlentities'] = false;
929 929
                     if (
930 930
                         $question_groups_question->type() == 'RADIO_BTN'
931 931
                         || $question_groups_question->type() == 'CHECKBOX'
@@ -934,7 +934,7 @@  discard block
 block discarded – undo
934 934
                         $question_options = $question_groups_question->options(true, $answer->value());
935 935
                         if (is_array($question_options)) {
936 936
                             foreach ($question_options as $QSO_ID => $question_option) {
937
-                                $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
937
+                                $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_options'][$QSO_ID]
938 938
                                     = $question_option->model_field_array();
939 939
                             }
940 940
                         }
Please login to merge, or discard this patch.
core/db_models/EEM_Event_Message_Template.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@
 block discarded – undo
19 19
     /**
20 20
      * protected constructor to prevent direct creation
21 21
      *
22
-     * @param null $timezone
22
+     * @param string|null $timezone
23 23
      * @throws EE_Error
24 24
      */
25 25
     protected function __construct(string $timezone = '')
Please login to merge, or discard this patch.
Indentation   +104 added lines, -104 removed lines patch added patch discarded remove patch
@@ -12,117 +12,117 @@
 block discarded – undo
12 12
 class EEM_Event_Message_Template extends EEM_Base
13 13
 {
14 14
 
15
-    // private instance of the EEM_Event_Message_Template object
16
-    protected static $_instance;
15
+	// private instance of the EEM_Event_Message_Template object
16
+	protected static $_instance;
17 17
 
18 18
 
19
-    /**
20
-     * protected constructor to prevent direct creation
21
-     *
22
-     * @param null $timezone
23
-     * @throws EE_Error
24
-     */
25
-    protected function __construct(string $timezone = '')
26
-    {
27
-        $this->singular_item = esc_html__('Event Message Template', 'event_espresso');
28
-        $this->plural_item   = esc_html__('Event Message Templates', 'event_espresso');
19
+	/**
20
+	 * protected constructor to prevent direct creation
21
+	 *
22
+	 * @param null $timezone
23
+	 * @throws EE_Error
24
+	 */
25
+	protected function __construct(string $timezone = '')
26
+	{
27
+		$this->singular_item = esc_html__('Event Message Template', 'event_espresso');
28
+		$this->plural_item   = esc_html__('Event Message Templates', 'event_espresso');
29 29
 
30
-        $this->_tables          = [
31
-            'Event_Message_Template' => new EE_Primary_Table('esp_event_message_template', 'EMT_ID'),
32
-        ];
33
-        $this->_fields          = [
34
-            'Event_Message_Template' => [
35
-                'EMT_ID' => new EE_Primary_Key_Int_Field(
36
-                    'EMT_ID',
37
-                    esc_html__('Event Message Template ID', 'event_espresso')
38
-                ),
39
-                'EVT_ID' => new EE_Foreign_Key_Int_Field(
40
-                    'EVT_ID',
41
-                    esc_html__('The ID to the Event', 'event_espresso'),
42
-                    false,
43
-                    0,
44
-                    'Event'
45
-                ),
46
-                'GRP_ID' => new EE_Foreign_Key_Int_Field(
47
-                    'GRP_ID',
48
-                    esc_html__('The ID to the Message Template Group', 'event_espresso'),
49
-                    false,
50
-                    0,
51
-                    'Message_Template_Group'
52
-                ),
53
-            ],
54
-        ];
55
-        $this->_model_relations = [
56
-            'Event'                  => new EE_Belongs_To_Relation(),
57
-            'Message_Template_Group' => new EE_Belongs_To_Relation(),
58
-        ];
59
-        $path_to_event          = 'Event';
60
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
61
-            $path_to_event
62
-        );
63
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
64
-            $path_to_event
65
-        );
66
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
67
-            $path_to_event
68
-        );
69
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected(
70
-            $path_to_event,
71
-            EEM_Base::caps_edit
72
-        );
73
-        parent::__construct($timezone);
74
-    }
30
+		$this->_tables          = [
31
+			'Event_Message_Template' => new EE_Primary_Table('esp_event_message_template', 'EMT_ID'),
32
+		];
33
+		$this->_fields          = [
34
+			'Event_Message_Template' => [
35
+				'EMT_ID' => new EE_Primary_Key_Int_Field(
36
+					'EMT_ID',
37
+					esc_html__('Event Message Template ID', 'event_espresso')
38
+				),
39
+				'EVT_ID' => new EE_Foreign_Key_Int_Field(
40
+					'EVT_ID',
41
+					esc_html__('The ID to the Event', 'event_espresso'),
42
+					false,
43
+					0,
44
+					'Event'
45
+				),
46
+				'GRP_ID' => new EE_Foreign_Key_Int_Field(
47
+					'GRP_ID',
48
+					esc_html__('The ID to the Message Template Group', 'event_espresso'),
49
+					false,
50
+					0,
51
+					'Message_Template_Group'
52
+				),
53
+			],
54
+		];
55
+		$this->_model_relations = [
56
+			'Event'                  => new EE_Belongs_To_Relation(),
57
+			'Message_Template_Group' => new EE_Belongs_To_Relation(),
58
+		];
59
+		$path_to_event          = 'Event';
60
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
61
+			$path_to_event
62
+		);
63
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
64
+			$path_to_event
65
+		);
66
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
67
+			$path_to_event
68
+		);
69
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected(
70
+			$path_to_event,
71
+			EEM_Base::caps_edit
72
+		);
73
+		parent::__construct($timezone);
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * helper method to simply return an array of event ids for events attached to the given
79
-     * message template group.
80
-     *
81
-     * @param int $GRP_ID The MTP group we want attached events for.
82
-     * @return  array               An array of event ids.
83
-     * @throws EE_Error
84
-     * @throws ReflectionException
85
-     * @since 4.3.0
86
-     */
87
-    public function get_attached_event_ids(int $GRP_ID): array
88
-    {
89
-        $event_ids = $this->_get_all_wpdb_results([['GRP_ID' => $GRP_ID]], ARRAY_N, 'EVT_ID');
90
-        return call_user_func_array('array_merge', $event_ids);
91
-    }
77
+	/**
78
+	 * helper method to simply return an array of event ids for events attached to the given
79
+	 * message template group.
80
+	 *
81
+	 * @param int $GRP_ID The MTP group we want attached events for.
82
+	 * @return  array               An array of event ids.
83
+	 * @throws EE_Error
84
+	 * @throws ReflectionException
85
+	 * @since 4.3.0
86
+	 */
87
+	public function get_attached_event_ids(int $GRP_ID): array
88
+	{
89
+		$event_ids = $this->_get_all_wpdb_results([['GRP_ID' => $GRP_ID]], ARRAY_N, 'EVT_ID');
90
+		return call_user_func_array('array_merge', $event_ids);
91
+	}
92 92
 
93 93
 
94
-    /**
95
-     * helper method for clearing event/group relations for the given event ids and grp ids.
96
-     *
97
-     * @param array $GRP_IDs An array of GRP_IDs. Optional. If empty then there must be EVT IDs.
98
-     * @param array $EVT_IDs An array of EVT_IDs.  Optional. If empty then there must be GRP IDs.
99
-     * @return int             How many rows were deleted.
100
-     * @throws EE_Error
101
-     * @throws EE_Error
102
-     * @throws ReflectionException
103
-     */
104
-    public function delete_event_group_relations(array $GRP_IDs = [], array $EVT_IDs = []): int
105
-    {
106
-        if (empty($GRP_IDs) && empty($EVT_IDs)) {
107
-            throw new EE_Error(
108
-                sprintf(
109
-                    esc_html__(
110
-                        '%s requires either an array of GRP_IDs or EVT_IDs or both, but both cannot be empty.',
111
-                        'event_espresso'
112
-                    ),
113
-                    __METHOD__
114
-                )
115
-            );
116
-        }
94
+	/**
95
+	 * helper method for clearing event/group relations for the given event ids and grp ids.
96
+	 *
97
+	 * @param array $GRP_IDs An array of GRP_IDs. Optional. If empty then there must be EVT IDs.
98
+	 * @param array $EVT_IDs An array of EVT_IDs.  Optional. If empty then there must be GRP IDs.
99
+	 * @return int             How many rows were deleted.
100
+	 * @throws EE_Error
101
+	 * @throws EE_Error
102
+	 * @throws ReflectionException
103
+	 */
104
+	public function delete_event_group_relations(array $GRP_IDs = [], array $EVT_IDs = []): int
105
+	{
106
+		if (empty($GRP_IDs) && empty($EVT_IDs)) {
107
+			throw new EE_Error(
108
+				sprintf(
109
+					esc_html__(
110
+						'%s requires either an array of GRP_IDs or EVT_IDs or both, but both cannot be empty.',
111
+						'event_espresso'
112
+					),
113
+					__METHOD__
114
+				)
115
+			);
116
+		}
117 117
 
118
-        $where = [];
119
-        if (! empty($GRP_IDs)) {
120
-            $where['GRP_ID'] = ['IN', $GRP_IDs];
121
-        }
122
-        if (! empty($EVT_IDs)) {
123
-            $where['EVT_ID'] = ['IN', $EVT_IDs];
124
-        }
118
+		$where = [];
119
+		if (! empty($GRP_IDs)) {
120
+			$where['GRP_ID'] = ['IN', $GRP_IDs];
121
+		}
122
+		if (! empty($EVT_IDs)) {
123
+			$where['EVT_ID'] = ['IN', $EVT_IDs];
124
+		}
125 125
 
126
-        return $this->delete([$where], false);
127
-    }
126
+		return $this->delete([$where], false);
127
+	}
128 128
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -56,17 +56,17 @@  discard block
 block discarded – undo
56 56
             'Event'                  => new EE_Belongs_To_Relation(),
57 57
             'Message_Template_Group' => new EE_Belongs_To_Relation(),
58 58
         ];
59
-        $path_to_event          = 'Event';
60
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
59
+        $path_to_event = 'Event';
60
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public(
61 61
             $path_to_event
62 62
         );
63
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
63
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected(
64 64
             $path_to_event
65 65
         );
66
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
66
+        $this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected(
67 67
             $path_to_event
68 68
         );
69
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected(
69
+        $this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected(
70 70
             $path_to_event,
71 71
             EEM_Base::caps_edit
72 72
         );
@@ -116,10 +116,10 @@  discard block
 block discarded – undo
116 116
         }
117 117
 
118 118
         $where = [];
119
-        if (! empty($GRP_IDs)) {
119
+        if ( ! empty($GRP_IDs)) {
120 120
             $where['GRP_ID'] = ['IN', $GRP_IDs];
121 121
         }
122
-        if (! empty($EVT_IDs)) {
122
+        if ( ! empty($EVT_IDs)) {
123 123
             $where['EVT_ID'] = ['IN', $EVT_IDs];
124 124
         }
125 125
 
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
      *
430 430
      * @param int $TXN_ID
431 431
      * @param int $TKT_ID
432
-     * @return EE_Line_Item|null
432
+     * @return null|EE_Base_Class
433 433
      * @throws EE_Error
434 434
      * @throws InvalidArgumentException
435 435
      * @throws InvalidDataTypeException
@@ -456,7 +456,7 @@  discard block
 block discarded – undo
456 456
      *
457 457
      * @param EE_Line_Item $parent_line_item
458 458
      * @param EE_Promotion $promotion
459
-     * @return EE_Line_Item|null
459
+     * @return null|EE_Base_Class
460 460
      * @throws EE_Error
461 461
      * @throws InvalidArgumentException
462 462
      * @throws InvalidDataTypeException
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
      * In order to support that, we'd probably need a LIN_ID on registrations or something.
516 516
      *
517 517
      * @param EE_Registration $registration
518
-     * @return EE_Line_Item|null
518
+     * @return null|EE_Base_Class
519 519
      * @throws EE_Error
520 520
      * @throws ReflectionException
521 521
      */
Please login to merge, or discard this patch.
Indentation   +627 added lines, -627 removed lines patch added patch discarded remove patch
@@ -28,634 +28,634 @@
 block discarded – undo
28 28
 class EEM_Line_Item extends EEM_Base
29 29
 {
30 30
 
31
-    /**
32
-     * Tax sub-total is just the total of all the taxes, which should be children
33
-     * of this line item. There should only ever be one tax sub-total, and it should
34
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
35
-     */
36
-    const type_tax_sub_total = 'tax-sub-total';
37
-
38
-    /**
39
-     * Tax line items indicate a tax applied to all the taxable line items.
40
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
41
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
42
-     */
43
-    const type_tax = 'tax';
44
-
45
-    /**
46
-     * Indicating individual items purchased, or discounts or surcharges.
47
-     * The sum of all the regular line items  plus the tax items should equal the grand total.
48
-     * Possible children are sub-line-items and cancellations.
49
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
50
-     * LIN_totals. Its LIN_percent = 0.
51
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
52
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
53
-     */
54
-    const type_line_item = 'line-item';
55
-
56
-    /**
57
-     * Line item indicating all the factors that make a single line item.
58
-     * Sub-line items should have NO children line items.
59
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
60
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
61
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
62
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
63
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
64
-     */
65
-    const type_sub_line_item = 'sub-item';
66
-
67
-    /**
68
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
69
-     * Direct children should be event subtotals.
70
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
71
-     */
72
-    const type_sub_total = 'sub-total';
73
-
74
-    /**
75
-     * Line item for the grand total of an order.
76
-     * Its direct children should be tax subtotals and (pre-tax) subtotals,
77
-     * and possibly a regular line item indicating a transaction-wide discount/surcharge.
78
-     * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount.
79
-     */
80
-    const type_total = 'total';
81
-
82
-    /**
83
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
84
-     * should be created, indicating the quantity that were cancelled
85
-     * (because a line item could have a quantity of 1, and its cancellation item
86
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
87
-     * cancelled, and only one remains).
88
-     * When items are refunded, a cancellation line item should be made, which points
89
-     * to teh payment model object which actually refunded the payment.
90
-     * Cancellations should NOT have any children line items; the should NOT affect
91
-     * any calculations, and are only meant as a record that cancellations have occurred.
92
-     * Their LIN_percent should be 0.
93
-     */
94
-    const type_cancellation = 'cancellation';
95
-
96
-    // various line item object types
97
-    const OBJ_TYPE_EVENT       = 'Event';
98
-
99
-    const OBJ_TYPE_PRICE       = 'Price';
100
-
101
-    const OBJ_TYPE_PROMOTION   = 'Promotion';
102
-
103
-    const OBJ_TYPE_TICKET      = 'Ticket';
104
-
105
-    const OBJ_TYPE_TRANSACTION = 'Transaction';
106
-
107
-    /**
108
-     * @var EEM_Line_Item $_instance
109
-     */
110
-    protected static $_instance;
111
-
112
-
113
-    /**
114
-     * private constructor to prevent direct creation
115
-     *
116
-     * @Constructor
117
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
118
-     *                         (and any incoming timezone data that gets saved).
119
-     *                         Note this just sends the timezone info to the date time model field objects.
120
-     *                         Default is NULL
121
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
122
-     * @throws EE_Error
123
-     * @throws InvalidArgumentException
124
-     */
125
-    protected function __construct(string $timezone = '')
126
-    {
127
-        $this->singular_item = esc_html__('Line Item', 'event_espresso');
128
-        $this->plural_item   = esc_html__('Line Items', 'event_espresso');
129
-
130
-        $this->_tables                 = [
131
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'),
132
-        ];
133
-        $line_items_can_be_for         = apply_filters(
134
-            'FHEE__EEM_Line_Item__line_items_can_be_for',
135
-            ['Ticket', 'Price', 'Event']
136
-        );
137
-        $this->_fields                 = [
138
-            'Line_Item' => [
139
-                'LIN_ID'         => new EE_Primary_Key_Int_Field(
140
-                    'LIN_ID',
141
-                    esc_html__('ID', 'event_espresso')
142
-                ),
143
-                'LIN_code'       => new EE_Slug_Field(
144
-                    'LIN_code',
145
-                    esc_html__('Code for index into Cart', 'event_espresso'),
146
-                    true
147
-                ),
148
-                'TXN_ID'         => new EE_Foreign_Key_Int_Field(
149
-                    'TXN_ID',
150
-                    esc_html__('Transaction ID', 'event_espresso'),
151
-                    true,
152
-                    null,
153
-                    'Transaction'
154
-                ),
155
-                'LIN_name'       => new EE_Full_HTML_Field(
156
-                    'LIN_name',
157
-                    esc_html__('Line Item Name', 'event_espresso'),
158
-                    false,
159
-                    ''
160
-                ),
161
-                'LIN_desc'       => new EE_Full_HTML_Field(
162
-                    'LIN_desc',
163
-                    esc_html__('Line Item Description', 'event_espresso'),
164
-                    true
165
-                ),
166
-                'LIN_unit_price' => new EE_Money_Field(
167
-                    'LIN_unit_price',
168
-                    esc_html__('Unit Price', 'event_espresso'),
169
-                    false,
170
-                    0
171
-                ),
172
-                'LIN_percent'    => new EE_Float_Field(
173
-                    'LIN_percent',
174
-                    esc_html__('Percent', 'event_espresso'),
175
-                    false,
176
-                    0
177
-                ),
178
-                'LIN_is_taxable' => new EE_Boolean_Field(
179
-                    'LIN_is_taxable',
180
-                    esc_html__('Taxable', 'event_espresso'),
181
-                    false,
182
-                    false
183
-                ),
184
-                'LIN_order'      => new EE_Integer_Field(
185
-                    'LIN_order',
186
-                    esc_html__('Order of Application towards total of parent', 'event_espresso'),
187
-                    false,
188
-                    1
189
-                ),
190
-                'LIN_total'      => new EE_Money_Field(
191
-                    'LIN_total',
192
-                    esc_html__('Total (unit price x quantity)', 'event_espresso'),
193
-                    false,
194
-                    0
195
-                ),
196
-                'LIN_quantity'   => new EE_Integer_Field(
197
-                    'LIN_quantity',
198
-                    esc_html__('Quantity', 'event_espresso'),
199
-                    true,
200
-                    1
201
-                ),
202
-                'LIN_parent'     => new EE_Integer_Field(
203
-                    'LIN_parent',
204
-                    esc_html__(
205
-                        "Parent ID (this item goes towards that Line Item's total)",
206
-                        'event_espresso'
207
-                    ),
208
-                    true,
209
-                    null
210
-                ),
211
-                'LIN_type'       => new EE_Enum_Text_Field(
212
-                    'LIN_type',
213
-                    esc_html__('Type', 'event_espresso'),
214
-                    false,
215
-                    'line-item',
216
-                    [
217
-                        self::type_line_item     => esc_html__('Line Item', 'event_espresso'),
218
-                        self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'),
219
-                        self::type_sub_total     => esc_html__('Subtotal', 'event_espresso'),
220
-                        self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'),
221
-                        self::type_tax           => esc_html__('Tax', 'event_espresso'),
222
-                        self::type_total         => esc_html__('Total', 'event_espresso'),
223
-                        self::type_cancellation  => esc_html__('Cancellation', 'event_espresso'),
224
-                    ]
225
-                ),
226
-                'OBJ_ID'         => new EE_Foreign_Key_Int_Field(
227
-                    'OBJ_ID',
228
-                    esc_html__('ID of Item purchased.', 'event_espresso'),
229
-                    true,
230
-                    null,
231
-                    $line_items_can_be_for
232
-                ),
233
-                'OBJ_type'       => new EE_Any_Foreign_Model_Name_Field(
234
-                    'OBJ_type',
235
-                    esc_html__('Model Name this Line Item is for', 'event_espresso'),
236
-                    true,
237
-                    null,
238
-                    $line_items_can_be_for
239
-                ),
240
-                'LIN_timestamp'  => new EE_Datetime_Field(
241
-                    'LIN_timestamp',
242
-                    esc_html__('When the line item was created', 'event_espresso'),
243
-                    false,
244
-                    EE_Datetime_Field::now,
245
-                    $timezone
246
-                ),
247
-            ],
248
-        ];
249
-        $this->_model_relations        = [
250
-            'Transaction' => new EE_Belongs_To_Relation(),
251
-            'Ticket'      => new EE_Belongs_To_Any_Relation(),
252
-            'Price'       => new EE_Belongs_To_Any_Relation(),
253
-            'Event'       => new EE_Belongs_To_Any_Relation(),
254
-        ];
255
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
256
-        $this->_caps_slug              = 'transactions';
257
-        parent::__construct($timezone);
258
-    }
259
-
260
-
261
-    /**
262
-     * Gets all the line items for this transaction of the given type
263
-     *
264
-     * @param string             $line_item_type like one of EEM_Line_Item::type_*
265
-     * @param EE_Transaction|int $transaction
266
-     * @return EE_Line_Item[]
267
-     * @throws EE_Error
268
-     * @throws InvalidArgumentException
269
-     * @throws InvalidDataTypeException
270
-     * @throws InvalidInterfaceException
271
-     * @throws ReflectionException
272
-     */
273
-    public function get_all_of_type_for_transaction(string $line_item_type, $transaction): array
274
-    {
275
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
276
-        return $this->get_all(
277
-            [
278
-                [
279
-                    'LIN_type' => $line_item_type,
280
-                    'TXN_ID'   => $transaction,
281
-                ],
282
-            ]
283
-        );
284
-    }
285
-
286
-
287
-    /**
288
-     * Gets all line items unrelated to tickets that are normal line items
289
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
290
-     *
291
-     * @param EE_Transaction|int $transaction
292
-     * @return EE_Line_Item[]
293
-     * @throws EE_Error
294
-     * @throws InvalidArgumentException
295
-     * @throws InvalidDataTypeException
296
-     * @throws InvalidInterfaceException
297
-     * @throws ReflectionException
298
-     */
299
-    public function get_all_non_ticket_line_items_for_transaction($transaction): array
300
-    {
301
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
302
-        return $this->get_all(
303
-            [
304
-                [
305
-                    'LIN_type' => self::type_line_item,
306
-                    'TXN_ID'   => $transaction,
307
-                    'OR'       => [
308
-                        'OBJ_type*notticket' => ['!=', EEM_Line_Item::OBJ_TYPE_TICKET],
309
-                        'OBJ_type*null'      => ['IS_NULL'],
310
-                    ],
311
-                ],
312
-            ]
313
-        );
314
-    }
315
-
316
-
317
-    /**
318
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
319
-     * This needs to be very efficient
320
-     * because if there are spam bots afoot there will be LOTS of line items. Also MySQL doesn't allow a limit when
321
-     * deleting and joining tables like this.
322
-     *
323
-     * @return int count of how many deleted
324
-     * @throws EE_Error
325
-     * @throws InvalidArgumentException
326
-     * @throws InvalidDataTypeException
327
-     * @throws InvalidInterfaceException
328
-     */
329
-    public function delete_line_items_with_no_transaction(): int
330
-    {
331
-        global $wpdb;
332
-        $time_to_leave_alone = apply_filters(
333
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
334
-            WEEK_IN_SECONDS
335
-        );
336
-        $query               = $wpdb->prepare(
337
-            'DELETE li
31
+	/**
32
+	 * Tax sub-total is just the total of all the taxes, which should be children
33
+	 * of this line item. There should only ever be one tax sub-total, and it should
34
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
35
+	 */
36
+	const type_tax_sub_total = 'tax-sub-total';
37
+
38
+	/**
39
+	 * Tax line items indicate a tax applied to all the taxable line items.
40
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
41
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
42
+	 */
43
+	const type_tax = 'tax';
44
+
45
+	/**
46
+	 * Indicating individual items purchased, or discounts or surcharges.
47
+	 * The sum of all the regular line items  plus the tax items should equal the grand total.
48
+	 * Possible children are sub-line-items and cancellations.
49
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
50
+	 * LIN_totals. Its LIN_percent = 0.
51
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
52
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
53
+	 */
54
+	const type_line_item = 'line-item';
55
+
56
+	/**
57
+	 * Line item indicating all the factors that make a single line item.
58
+	 * Sub-line items should have NO children line items.
59
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
60
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
61
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
62
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
63
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
64
+	 */
65
+	const type_sub_line_item = 'sub-item';
66
+
67
+	/**
68
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
69
+	 * Direct children should be event subtotals.
70
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
71
+	 */
72
+	const type_sub_total = 'sub-total';
73
+
74
+	/**
75
+	 * Line item for the grand total of an order.
76
+	 * Its direct children should be tax subtotals and (pre-tax) subtotals,
77
+	 * and possibly a regular line item indicating a transaction-wide discount/surcharge.
78
+	 * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount.
79
+	 */
80
+	const type_total = 'total';
81
+
82
+	/**
83
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
84
+	 * should be created, indicating the quantity that were cancelled
85
+	 * (because a line item could have a quantity of 1, and its cancellation item
86
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
87
+	 * cancelled, and only one remains).
88
+	 * When items are refunded, a cancellation line item should be made, which points
89
+	 * to teh payment model object which actually refunded the payment.
90
+	 * Cancellations should NOT have any children line items; the should NOT affect
91
+	 * any calculations, and are only meant as a record that cancellations have occurred.
92
+	 * Their LIN_percent should be 0.
93
+	 */
94
+	const type_cancellation = 'cancellation';
95
+
96
+	// various line item object types
97
+	const OBJ_TYPE_EVENT       = 'Event';
98
+
99
+	const OBJ_TYPE_PRICE       = 'Price';
100
+
101
+	const OBJ_TYPE_PROMOTION   = 'Promotion';
102
+
103
+	const OBJ_TYPE_TICKET      = 'Ticket';
104
+
105
+	const OBJ_TYPE_TRANSACTION = 'Transaction';
106
+
107
+	/**
108
+	 * @var EEM_Line_Item $_instance
109
+	 */
110
+	protected static $_instance;
111
+
112
+
113
+	/**
114
+	 * private constructor to prevent direct creation
115
+	 *
116
+	 * @Constructor
117
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
118
+	 *                         (and any incoming timezone data that gets saved).
119
+	 *                         Note this just sends the timezone info to the date time model field objects.
120
+	 *                         Default is NULL
121
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
122
+	 * @throws EE_Error
123
+	 * @throws InvalidArgumentException
124
+	 */
125
+	protected function __construct(string $timezone = '')
126
+	{
127
+		$this->singular_item = esc_html__('Line Item', 'event_espresso');
128
+		$this->plural_item   = esc_html__('Line Items', 'event_espresso');
129
+
130
+		$this->_tables                 = [
131
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'),
132
+		];
133
+		$line_items_can_be_for         = apply_filters(
134
+			'FHEE__EEM_Line_Item__line_items_can_be_for',
135
+			['Ticket', 'Price', 'Event']
136
+		);
137
+		$this->_fields                 = [
138
+			'Line_Item' => [
139
+				'LIN_ID'         => new EE_Primary_Key_Int_Field(
140
+					'LIN_ID',
141
+					esc_html__('ID', 'event_espresso')
142
+				),
143
+				'LIN_code'       => new EE_Slug_Field(
144
+					'LIN_code',
145
+					esc_html__('Code for index into Cart', 'event_espresso'),
146
+					true
147
+				),
148
+				'TXN_ID'         => new EE_Foreign_Key_Int_Field(
149
+					'TXN_ID',
150
+					esc_html__('Transaction ID', 'event_espresso'),
151
+					true,
152
+					null,
153
+					'Transaction'
154
+				),
155
+				'LIN_name'       => new EE_Full_HTML_Field(
156
+					'LIN_name',
157
+					esc_html__('Line Item Name', 'event_espresso'),
158
+					false,
159
+					''
160
+				),
161
+				'LIN_desc'       => new EE_Full_HTML_Field(
162
+					'LIN_desc',
163
+					esc_html__('Line Item Description', 'event_espresso'),
164
+					true
165
+				),
166
+				'LIN_unit_price' => new EE_Money_Field(
167
+					'LIN_unit_price',
168
+					esc_html__('Unit Price', 'event_espresso'),
169
+					false,
170
+					0
171
+				),
172
+				'LIN_percent'    => new EE_Float_Field(
173
+					'LIN_percent',
174
+					esc_html__('Percent', 'event_espresso'),
175
+					false,
176
+					0
177
+				),
178
+				'LIN_is_taxable' => new EE_Boolean_Field(
179
+					'LIN_is_taxable',
180
+					esc_html__('Taxable', 'event_espresso'),
181
+					false,
182
+					false
183
+				),
184
+				'LIN_order'      => new EE_Integer_Field(
185
+					'LIN_order',
186
+					esc_html__('Order of Application towards total of parent', 'event_espresso'),
187
+					false,
188
+					1
189
+				),
190
+				'LIN_total'      => new EE_Money_Field(
191
+					'LIN_total',
192
+					esc_html__('Total (unit price x quantity)', 'event_espresso'),
193
+					false,
194
+					0
195
+				),
196
+				'LIN_quantity'   => new EE_Integer_Field(
197
+					'LIN_quantity',
198
+					esc_html__('Quantity', 'event_espresso'),
199
+					true,
200
+					1
201
+				),
202
+				'LIN_parent'     => new EE_Integer_Field(
203
+					'LIN_parent',
204
+					esc_html__(
205
+						"Parent ID (this item goes towards that Line Item's total)",
206
+						'event_espresso'
207
+					),
208
+					true,
209
+					null
210
+				),
211
+				'LIN_type'       => new EE_Enum_Text_Field(
212
+					'LIN_type',
213
+					esc_html__('Type', 'event_espresso'),
214
+					false,
215
+					'line-item',
216
+					[
217
+						self::type_line_item     => esc_html__('Line Item', 'event_espresso'),
218
+						self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'),
219
+						self::type_sub_total     => esc_html__('Subtotal', 'event_espresso'),
220
+						self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'),
221
+						self::type_tax           => esc_html__('Tax', 'event_espresso'),
222
+						self::type_total         => esc_html__('Total', 'event_espresso'),
223
+						self::type_cancellation  => esc_html__('Cancellation', 'event_espresso'),
224
+					]
225
+				),
226
+				'OBJ_ID'         => new EE_Foreign_Key_Int_Field(
227
+					'OBJ_ID',
228
+					esc_html__('ID of Item purchased.', 'event_espresso'),
229
+					true,
230
+					null,
231
+					$line_items_can_be_for
232
+				),
233
+				'OBJ_type'       => new EE_Any_Foreign_Model_Name_Field(
234
+					'OBJ_type',
235
+					esc_html__('Model Name this Line Item is for', 'event_espresso'),
236
+					true,
237
+					null,
238
+					$line_items_can_be_for
239
+				),
240
+				'LIN_timestamp'  => new EE_Datetime_Field(
241
+					'LIN_timestamp',
242
+					esc_html__('When the line item was created', 'event_espresso'),
243
+					false,
244
+					EE_Datetime_Field::now,
245
+					$timezone
246
+				),
247
+			],
248
+		];
249
+		$this->_model_relations        = [
250
+			'Transaction' => new EE_Belongs_To_Relation(),
251
+			'Ticket'      => new EE_Belongs_To_Any_Relation(),
252
+			'Price'       => new EE_Belongs_To_Any_Relation(),
253
+			'Event'       => new EE_Belongs_To_Any_Relation(),
254
+		];
255
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
256
+		$this->_caps_slug              = 'transactions';
257
+		parent::__construct($timezone);
258
+	}
259
+
260
+
261
+	/**
262
+	 * Gets all the line items for this transaction of the given type
263
+	 *
264
+	 * @param string             $line_item_type like one of EEM_Line_Item::type_*
265
+	 * @param EE_Transaction|int $transaction
266
+	 * @return EE_Line_Item[]
267
+	 * @throws EE_Error
268
+	 * @throws InvalidArgumentException
269
+	 * @throws InvalidDataTypeException
270
+	 * @throws InvalidInterfaceException
271
+	 * @throws ReflectionException
272
+	 */
273
+	public function get_all_of_type_for_transaction(string $line_item_type, $transaction): array
274
+	{
275
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
276
+		return $this->get_all(
277
+			[
278
+				[
279
+					'LIN_type' => $line_item_type,
280
+					'TXN_ID'   => $transaction,
281
+				],
282
+			]
283
+		);
284
+	}
285
+
286
+
287
+	/**
288
+	 * Gets all line items unrelated to tickets that are normal line items
289
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
290
+	 *
291
+	 * @param EE_Transaction|int $transaction
292
+	 * @return EE_Line_Item[]
293
+	 * @throws EE_Error
294
+	 * @throws InvalidArgumentException
295
+	 * @throws InvalidDataTypeException
296
+	 * @throws InvalidInterfaceException
297
+	 * @throws ReflectionException
298
+	 */
299
+	public function get_all_non_ticket_line_items_for_transaction($transaction): array
300
+	{
301
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
302
+		return $this->get_all(
303
+			[
304
+				[
305
+					'LIN_type' => self::type_line_item,
306
+					'TXN_ID'   => $transaction,
307
+					'OR'       => [
308
+						'OBJ_type*notticket' => ['!=', EEM_Line_Item::OBJ_TYPE_TICKET],
309
+						'OBJ_type*null'      => ['IS_NULL'],
310
+					],
311
+				],
312
+			]
313
+		);
314
+	}
315
+
316
+
317
+	/**
318
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
319
+	 * This needs to be very efficient
320
+	 * because if there are spam bots afoot there will be LOTS of line items. Also MySQL doesn't allow a limit when
321
+	 * deleting and joining tables like this.
322
+	 *
323
+	 * @return int count of how many deleted
324
+	 * @throws EE_Error
325
+	 * @throws InvalidArgumentException
326
+	 * @throws InvalidDataTypeException
327
+	 * @throws InvalidInterfaceException
328
+	 */
329
+	public function delete_line_items_with_no_transaction(): int
330
+	{
331
+		global $wpdb;
332
+		$time_to_leave_alone = apply_filters(
333
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
334
+			WEEK_IN_SECONDS
335
+		);
336
+		$query               = $wpdb->prepare(
337
+			'DELETE li
338 338
 				FROM ' . $this->table() . ' li
339 339
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
340 340
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
341
-            // use GMT time because that's what TXN_timestamps are in
342
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
343
-        );
344
-        return $wpdb->query($query);
345
-    }
346
-
347
-
348
-    /**
349
-     * get_line_item_for_transaction_object
350
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
351
-     *
352
-     * @param int           $TXN_ID
353
-     * @param EE_Base_Class $object
354
-     * @return EE_Line_Item[]
355
-     * @throws EE_Error
356
-     * @throws InvalidArgumentException
357
-     * @throws InvalidDataTypeException
358
-     * @throws InvalidInterfaceException
359
-     * @throws ReflectionException
360
-     */
361
-    public function get_line_item_for_transaction_object(int $TXN_ID, EE_Base_Class $object): array
362
-    {
363
-        return $this->get_all(
364
-            [
365
-                [
366
-                    'TXN_ID'   => $TXN_ID,
367
-                    'OBJ_type' => str_replace('EE_', '', get_class($object)),
368
-                    'OBJ_ID'   => $object->ID(),
369
-                ],
370
-            ]
371
-        );
372
-    }
373
-
374
-
375
-    /**
376
-     * get_object_line_items_for_transaction
377
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
378
-     *
379
-     * @param int    $TXN_ID
380
-     * @param string $OBJ_type
381
-     * @param array  $OBJ_IDs
382
-     * @return EE_Line_Item[]
383
-     * @throws EE_Error
384
-     * @throws ReflectionException
385
-     */
386
-    public function get_object_line_items_for_transaction(
387
-        int $TXN_ID,
388
-        string $OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT,
389
-        array $OBJ_IDs = []
390
-    ): array {
391
-        $query_params = [
392
-            'OBJ_type' => $OBJ_type,
393
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
394
-            'OBJ_ID'   => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? ['IN', $OBJ_IDs] : $OBJ_IDs,
395
-        ];
396
-        if ($TXN_ID) {
397
-            $query_params['TXN_ID'] = $TXN_ID;
398
-        }
399
-        return $this->get_all([$query_params]);
400
-    }
401
-
402
-
403
-    /**
404
-     * get_all_ticket_line_items_for_transaction
405
-     *
406
-     * @param EE_Transaction $transaction
407
-     * @return EE_Line_Item[]
408
-     * @throws EE_Error
409
-     * @throws InvalidArgumentException
410
-     * @throws InvalidDataTypeException
411
-     * @throws InvalidInterfaceException
412
-     * @throws ReflectionException
413
-     */
414
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction): array
415
-    {
416
-        return $this->get_all(
417
-            [
418
-                [
419
-                    'TXN_ID'   => $transaction->ID(),
420
-                    'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
421
-                ],
422
-            ]
423
-        );
424
-    }
425
-
426
-
427
-    /**
428
-     * get_ticket_line_item_for_transaction
429
-     *
430
-     * @param int $TXN_ID
431
-     * @param int $TKT_ID
432
-     * @return EE_Line_Item|null
433
-     * @throws EE_Error
434
-     * @throws InvalidArgumentException
435
-     * @throws InvalidDataTypeException
436
-     * @throws InvalidInterfaceException
437
-     * @throws ReflectionException
438
-     */
439
-    public function get_ticket_line_item_for_transaction(int $TXN_ID, int $TKT_ID): ?EE_Line_Item
440
-    {
441
-        return $this->get_one(
442
-            [
443
-                [
444
-                    'TXN_ID'   => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
445
-                    'OBJ_ID'   => $TKT_ID,
446
-                    'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
447
-                ],
448
-            ]
449
-        );
450
-    }
451
-
452
-
453
-    /**
454
-     * get_existing_promotion_line_item
455
-     * searches the cart for existing line items for the specified promotion
456
-     *
457
-     * @param EE_Line_Item $parent_line_item
458
-     * @param EE_Promotion $promotion
459
-     * @return EE_Line_Item|null
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidDataTypeException
463
-     * @throws InvalidInterfaceException
464
-     * @throws ReflectionException
465
-     * @since 1.0.0
466
-     */
467
-    public function get_existing_promotion_line_item(
468
-        EE_Line_Item $parent_line_item,
469
-        EE_Promotion $promotion
470
-    ): ?EE_Line_Item {
471
-        return $this->get_one(
472
-            [
473
-                [
474
-                    'TXN_ID'     => $parent_line_item->TXN_ID(),
475
-                    'LIN_parent' => $parent_line_item->ID(),
476
-                    'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
477
-                    'OBJ_ID'     => $promotion->ID(),
478
-                ],
479
-            ]
480
-        );
481
-    }
482
-
483
-
484
-    /**
485
-     * get_all_promotion_line_items
486
-     * searches the cart for any and all existing promotion line items
487
-     *
488
-     * @param EE_Line_Item $parent_line_item
489
-     * @return EE_Line_Item[]
490
-     * @throws EE_Error
491
-     * @throws InvalidArgumentException
492
-     * @throws InvalidDataTypeException
493
-     * @throws InvalidInterfaceException
494
-     * @throws ReflectionException
495
-     * @since   1.0.0
496
-     */
497
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item): array
498
-    {
499
-        return $this->get_all(
500
-            [
501
-                [
502
-                    'TXN_ID'     => $parent_line_item->TXN_ID(),
503
-                    'LIN_parent' => $parent_line_item->ID(),
504
-                    'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
505
-                ],
506
-            ]
507
-        );
508
-    }
509
-
510
-
511
-    /**
512
-     * Gets the registration's corresponding line item.
513
-     * Note: basically does NOT support having multiple line items for a single ticket,
514
-     * which would happen if some of the registrations had a price modifier while others didn't.
515
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
516
-     *
517
-     * @param EE_Registration $registration
518
-     * @return EE_Line_Item|null
519
-     * @throws EE_Error
520
-     * @throws ReflectionException
521
-     */
522
-    public function get_line_item_for_registration(EE_Registration $registration): ?EE_Line_Item
523
-    {
524
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
525
-    }
526
-
527
-
528
-    /**
529
-     * Gets the query params used to retrieve a specific line item for the given registration
530
-     *
531
-     * @param EE_Registration $registration
532
-     * @param array           $original_query_params any extra query params you'd like to be merged with
533
-     * @return array @see
534
-     *                                               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
535
-     * @throws EE_Error
536
-     */
537
-    public function line_item_for_registration_query_params(
538
-        EE_Registration $registration,
539
-        array $original_query_params = []
540
-    ): array {
541
-        return array_replace_recursive(
542
-            $original_query_params,
543
-            [
544
-                [
545
-                    'OBJ_ID'   => $registration->ticket_ID(),
546
-                    'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
547
-                    'TXN_ID'   => $registration->transaction_ID(),
548
-                ],
549
-            ]
550
-        );
551
-    }
552
-
553
-
554
-    /**
555
-     * @return EE_Line_Item[]
556
-     * @throws InvalidInterfaceException
557
-     * @throws InvalidDataTypeException
558
-     * @throws EE_Error
559
-     * @throws InvalidArgumentException
560
-     * @throws ReflectionException
561
-     */
562
-    public function get_total_line_items_with_no_transaction(): array
563
-    {
564
-        return $this->get_total_line_items_for_carts();
565
-    }
566
-
567
-
568
-    /**
569
-     * @return EE_Line_Item[]
570
-     * @throws InvalidInterfaceException
571
-     * @throws InvalidDataTypeException
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws ReflectionException
575
-     */
576
-    public function get_total_line_items_for_active_carts(): array
577
-    {
578
-        return $this->get_total_line_items_for_carts(false);
579
-    }
580
-
581
-
582
-    /**
583
-     * @return EE_Line_Item[]
584
-     * @throws InvalidInterfaceException
585
-     * @throws InvalidDataTypeException
586
-     * @throws EE_Error
587
-     * @throws InvalidArgumentException
588
-     * @throws ReflectionException
589
-     */
590
-    public function get_total_line_items_for_expired_carts(): array
591
-    {
592
-        return $this->get_total_line_items_for_carts(true);
593
-    }
594
-
595
-
596
-    /**
597
-     * Returns an array of grand total line items where the TXN_ID is 0.
598
-     * If $expired is set to true, then only line items for expired sessions will be returned.
599
-     * If $expired is set to false, then only line items for active sessions will be returned.
600
-     *
601
-     * @param bool|null $expired
602
-     * @return EE_Line_Item[]
603
-     * @throws EE_Error
604
-     * @throws InvalidArgumentException
605
-     * @throws InvalidDataTypeException
606
-     * @throws InvalidInterfaceException
607
-     * @throws ReflectionException
608
-     */
609
-    private function get_total_line_items_for_carts(bool $expired = null): array
610
-    {
611
-        $where_params = [
612
-            'TXN_ID'   => 0,
613
-            'LIN_type' => 'total',
614
-        ];
615
-        if ($expired !== null) {
616
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
617
-            $session_lifespan              = LoaderFactory::getLoader()->getShared(
618
-                'EventEspresso\core\domain\values\session\SessionLifespan'
619
-            );
620
-            $expired                       = filter_var($expired, FILTER_VALIDATE_BOOLEAN);
621
-            $where_params['LIN_timestamp'] = [
622
-                $expired ? '<=' : '>',
623
-                $session_lifespan->expiration(),
624
-            ];
625
-        }
626
-        return $this->get_all([$where_params]);
627
-    }
628
-
629
-
630
-    /**
631
-     * Returns an array of ticket total line items where the TXN_ID is 0
632
-     * AND the timestamp is older than the session lifespan.
633
-     *
634
-     * @param int $timestamp
635
-     * @return EE_Line_Item[]
636
-     * @throws EE_Error
637
-     * @throws InvalidArgumentException
638
-     * @throws InvalidDataTypeException
639
-     * @throws InvalidInterfaceException
640
-     * @throws ReflectionException
641
-     */
642
-    public function getTicketLineItemsForExpiredCarts(int $timestamp = 0): array
643
-    {
644
-        if (! absint($timestamp)) {
645
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
646
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
647
-                'EventEspresso\core\domain\values\session\SessionLifespan'
648
-            );
649
-            $timestamp        = $session_lifespan->expiration();
650
-        }
651
-        return $this->get_all(
652
-            [
653
-                [
654
-                    'TXN_ID'        => 0,
655
-                    'OBJ_type'      => EEM_Line_Item::OBJ_TYPE_TICKET,
656
-                    'LIN_timestamp' => ['<=', $timestamp],
657
-                ],
658
-            ]
659
-        );
660
-    }
341
+			// use GMT time because that's what TXN_timestamps are in
342
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
343
+		);
344
+		return $wpdb->query($query);
345
+	}
346
+
347
+
348
+	/**
349
+	 * get_line_item_for_transaction_object
350
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
351
+	 *
352
+	 * @param int           $TXN_ID
353
+	 * @param EE_Base_Class $object
354
+	 * @return EE_Line_Item[]
355
+	 * @throws EE_Error
356
+	 * @throws InvalidArgumentException
357
+	 * @throws InvalidDataTypeException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws ReflectionException
360
+	 */
361
+	public function get_line_item_for_transaction_object(int $TXN_ID, EE_Base_Class $object): array
362
+	{
363
+		return $this->get_all(
364
+			[
365
+				[
366
+					'TXN_ID'   => $TXN_ID,
367
+					'OBJ_type' => str_replace('EE_', '', get_class($object)),
368
+					'OBJ_ID'   => $object->ID(),
369
+				],
370
+			]
371
+		);
372
+	}
373
+
374
+
375
+	/**
376
+	 * get_object_line_items_for_transaction
377
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
378
+	 *
379
+	 * @param int    $TXN_ID
380
+	 * @param string $OBJ_type
381
+	 * @param array  $OBJ_IDs
382
+	 * @return EE_Line_Item[]
383
+	 * @throws EE_Error
384
+	 * @throws ReflectionException
385
+	 */
386
+	public function get_object_line_items_for_transaction(
387
+		int $TXN_ID,
388
+		string $OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT,
389
+		array $OBJ_IDs = []
390
+	): array {
391
+		$query_params = [
392
+			'OBJ_type' => $OBJ_type,
393
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
394
+			'OBJ_ID'   => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? ['IN', $OBJ_IDs] : $OBJ_IDs,
395
+		];
396
+		if ($TXN_ID) {
397
+			$query_params['TXN_ID'] = $TXN_ID;
398
+		}
399
+		return $this->get_all([$query_params]);
400
+	}
401
+
402
+
403
+	/**
404
+	 * get_all_ticket_line_items_for_transaction
405
+	 *
406
+	 * @param EE_Transaction $transaction
407
+	 * @return EE_Line_Item[]
408
+	 * @throws EE_Error
409
+	 * @throws InvalidArgumentException
410
+	 * @throws InvalidDataTypeException
411
+	 * @throws InvalidInterfaceException
412
+	 * @throws ReflectionException
413
+	 */
414
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction): array
415
+	{
416
+		return $this->get_all(
417
+			[
418
+				[
419
+					'TXN_ID'   => $transaction->ID(),
420
+					'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
421
+				],
422
+			]
423
+		);
424
+	}
425
+
426
+
427
+	/**
428
+	 * get_ticket_line_item_for_transaction
429
+	 *
430
+	 * @param int $TXN_ID
431
+	 * @param int $TKT_ID
432
+	 * @return EE_Line_Item|null
433
+	 * @throws EE_Error
434
+	 * @throws InvalidArgumentException
435
+	 * @throws InvalidDataTypeException
436
+	 * @throws InvalidInterfaceException
437
+	 * @throws ReflectionException
438
+	 */
439
+	public function get_ticket_line_item_for_transaction(int $TXN_ID, int $TKT_ID): ?EE_Line_Item
440
+	{
441
+		return $this->get_one(
442
+			[
443
+				[
444
+					'TXN_ID'   => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
445
+					'OBJ_ID'   => $TKT_ID,
446
+					'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
447
+				],
448
+			]
449
+		);
450
+	}
451
+
452
+
453
+	/**
454
+	 * get_existing_promotion_line_item
455
+	 * searches the cart for existing line items for the specified promotion
456
+	 *
457
+	 * @param EE_Line_Item $parent_line_item
458
+	 * @param EE_Promotion $promotion
459
+	 * @return EE_Line_Item|null
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidDataTypeException
463
+	 * @throws InvalidInterfaceException
464
+	 * @throws ReflectionException
465
+	 * @since 1.0.0
466
+	 */
467
+	public function get_existing_promotion_line_item(
468
+		EE_Line_Item $parent_line_item,
469
+		EE_Promotion $promotion
470
+	): ?EE_Line_Item {
471
+		return $this->get_one(
472
+			[
473
+				[
474
+					'TXN_ID'     => $parent_line_item->TXN_ID(),
475
+					'LIN_parent' => $parent_line_item->ID(),
476
+					'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
477
+					'OBJ_ID'     => $promotion->ID(),
478
+				],
479
+			]
480
+		);
481
+	}
482
+
483
+
484
+	/**
485
+	 * get_all_promotion_line_items
486
+	 * searches the cart for any and all existing promotion line items
487
+	 *
488
+	 * @param EE_Line_Item $parent_line_item
489
+	 * @return EE_Line_Item[]
490
+	 * @throws EE_Error
491
+	 * @throws InvalidArgumentException
492
+	 * @throws InvalidDataTypeException
493
+	 * @throws InvalidInterfaceException
494
+	 * @throws ReflectionException
495
+	 * @since   1.0.0
496
+	 */
497
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item): array
498
+	{
499
+		return $this->get_all(
500
+			[
501
+				[
502
+					'TXN_ID'     => $parent_line_item->TXN_ID(),
503
+					'LIN_parent' => $parent_line_item->ID(),
504
+					'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
505
+				],
506
+			]
507
+		);
508
+	}
509
+
510
+
511
+	/**
512
+	 * Gets the registration's corresponding line item.
513
+	 * Note: basically does NOT support having multiple line items for a single ticket,
514
+	 * which would happen if some of the registrations had a price modifier while others didn't.
515
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
516
+	 *
517
+	 * @param EE_Registration $registration
518
+	 * @return EE_Line_Item|null
519
+	 * @throws EE_Error
520
+	 * @throws ReflectionException
521
+	 */
522
+	public function get_line_item_for_registration(EE_Registration $registration): ?EE_Line_Item
523
+	{
524
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
525
+	}
526
+
527
+
528
+	/**
529
+	 * Gets the query params used to retrieve a specific line item for the given registration
530
+	 *
531
+	 * @param EE_Registration $registration
532
+	 * @param array           $original_query_params any extra query params you'd like to be merged with
533
+	 * @return array @see
534
+	 *                                               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
535
+	 * @throws EE_Error
536
+	 */
537
+	public function line_item_for_registration_query_params(
538
+		EE_Registration $registration,
539
+		array $original_query_params = []
540
+	): array {
541
+		return array_replace_recursive(
542
+			$original_query_params,
543
+			[
544
+				[
545
+					'OBJ_ID'   => $registration->ticket_ID(),
546
+					'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
547
+					'TXN_ID'   => $registration->transaction_ID(),
548
+				],
549
+			]
550
+		);
551
+	}
552
+
553
+
554
+	/**
555
+	 * @return EE_Line_Item[]
556
+	 * @throws InvalidInterfaceException
557
+	 * @throws InvalidDataTypeException
558
+	 * @throws EE_Error
559
+	 * @throws InvalidArgumentException
560
+	 * @throws ReflectionException
561
+	 */
562
+	public function get_total_line_items_with_no_transaction(): array
563
+	{
564
+		return $this->get_total_line_items_for_carts();
565
+	}
566
+
567
+
568
+	/**
569
+	 * @return EE_Line_Item[]
570
+	 * @throws InvalidInterfaceException
571
+	 * @throws InvalidDataTypeException
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws ReflectionException
575
+	 */
576
+	public function get_total_line_items_for_active_carts(): array
577
+	{
578
+		return $this->get_total_line_items_for_carts(false);
579
+	}
580
+
581
+
582
+	/**
583
+	 * @return EE_Line_Item[]
584
+	 * @throws InvalidInterfaceException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws EE_Error
587
+	 * @throws InvalidArgumentException
588
+	 * @throws ReflectionException
589
+	 */
590
+	public function get_total_line_items_for_expired_carts(): array
591
+	{
592
+		return $this->get_total_line_items_for_carts(true);
593
+	}
594
+
595
+
596
+	/**
597
+	 * Returns an array of grand total line items where the TXN_ID is 0.
598
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
599
+	 * If $expired is set to false, then only line items for active sessions will be returned.
600
+	 *
601
+	 * @param bool|null $expired
602
+	 * @return EE_Line_Item[]
603
+	 * @throws EE_Error
604
+	 * @throws InvalidArgumentException
605
+	 * @throws InvalidDataTypeException
606
+	 * @throws InvalidInterfaceException
607
+	 * @throws ReflectionException
608
+	 */
609
+	private function get_total_line_items_for_carts(bool $expired = null): array
610
+	{
611
+		$where_params = [
612
+			'TXN_ID'   => 0,
613
+			'LIN_type' => 'total',
614
+		];
615
+		if ($expired !== null) {
616
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
617
+			$session_lifespan              = LoaderFactory::getLoader()->getShared(
618
+				'EventEspresso\core\domain\values\session\SessionLifespan'
619
+			);
620
+			$expired                       = filter_var($expired, FILTER_VALIDATE_BOOLEAN);
621
+			$where_params['LIN_timestamp'] = [
622
+				$expired ? '<=' : '>',
623
+				$session_lifespan->expiration(),
624
+			];
625
+		}
626
+		return $this->get_all([$where_params]);
627
+	}
628
+
629
+
630
+	/**
631
+	 * Returns an array of ticket total line items where the TXN_ID is 0
632
+	 * AND the timestamp is older than the session lifespan.
633
+	 *
634
+	 * @param int $timestamp
635
+	 * @return EE_Line_Item[]
636
+	 * @throws EE_Error
637
+	 * @throws InvalidArgumentException
638
+	 * @throws InvalidDataTypeException
639
+	 * @throws InvalidInterfaceException
640
+	 * @throws ReflectionException
641
+	 */
642
+	public function getTicketLineItemsForExpiredCarts(int $timestamp = 0): array
643
+	{
644
+		if (! absint($timestamp)) {
645
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
646
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
647
+				'EventEspresso\core\domain\values\session\SessionLifespan'
648
+			);
649
+			$timestamp        = $session_lifespan->expiration();
650
+		}
651
+		return $this->get_all(
652
+			[
653
+				[
654
+					'TXN_ID'        => 0,
655
+					'OBJ_type'      => EEM_Line_Item::OBJ_TYPE_TICKET,
656
+					'LIN_timestamp' => ['<=', $timestamp],
657
+				],
658
+			]
659
+		);
660
+	}
661 661
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
             'FHEE__EEM_Line_Item__line_items_can_be_for',
135 135
             ['Ticket', 'Price', 'Event']
136 136
         );
137
-        $this->_fields                 = [
137
+        $this->_fields = [
138 138
             'Line_Item' => [
139 139
                 'LIN_ID'         => new EE_Primary_Key_Int_Field(
140 140
                     'LIN_ID',
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
                 ),
247 247
             ],
248 248
         ];
249
-        $this->_model_relations        = [
249
+        $this->_model_relations = [
250 250
             'Transaction' => new EE_Belongs_To_Relation(),
251 251
             'Ticket'      => new EE_Belongs_To_Any_Relation(),
252 252
             'Price'       => new EE_Belongs_To_Any_Relation(),
@@ -333,10 +333,10 @@  discard block
 block discarded – undo
333 333
             'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
334 334
             WEEK_IN_SECONDS
335 335
         );
336
-        $query               = $wpdb->prepare(
336
+        $query = $wpdb->prepare(
337 337
             'DELETE li
338
-				FROM ' . $this->table() . ' li
339
-				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
338
+				FROM ' . $this->table().' li
339
+				LEFT JOIN ' . EEM_Transaction::instance()->table().' t ON li.TXN_ID = t.TXN_ID
340 340
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
341 341
             // use GMT time because that's what TXN_timestamps are in
342 342
             date('Y-m-d H:i:s', time() - $time_to_leave_alone)
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
      */
642 642
     public function getTicketLineItemsForExpiredCarts(int $timestamp = 0): array
643 643
     {
644
-        if (! absint($timestamp)) {
644
+        if ( ! absint($timestamp)) {
645 645
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
646 646
             $session_lifespan = LoaderFactory::getLoader()->getShared(
647 647
                 'EventEspresso\core\domain\values\session\SessionLifespan'
Please login to merge, or discard this patch.
core/db_models/EEM_Message_Template_Group.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -395,7 +395,7 @@
 block discarded – undo
395 395
     /**
396 396
      * This sends things to the validator for the given messenger and message type.
397 397
      *
398
-     * @param array  $fields       the incoming fields to check.
398
+     * @param string  $fields       the incoming fields to check.
399 399
      *                             Note this array is in the formatted fields from the form fields setup.
400 400
      *                             So we need to reformat this into an array of expected field refs by the validator.
401 401
      *                             Note also that this is not only the fields for the Message Template Group
Please login to merge, or discard this patch.
Indentation   +478 added lines, -478 removed lines patch added patch discarded remove patch
@@ -12,482 +12,482 @@
 block discarded – undo
12 12
 class EEM_Message_Template_Group extends EEM_Soft_Delete_Base
13 13
 {
14 14
 
15
-    // private instance of the EEM_Message_Template_Group object
16
-    protected static $_instance;
17
-
18
-
19
-    protected function __construct(string $timezone = '')
20
-    {
21
-        $this->singular_item    = esc_html__('Message Template Group', 'event_espresso');
22
-        $this->plural_item      = esc_html__('Message Template Groups', 'event_espresso');
23
-        $this->_tables          = [
24
-            'Message_Template_Group' => new EE_Primary_Table('esp_message_template_group', 'GRP_ID'),
25
-        ];
26
-        $this->_fields          = [
27
-            'Message_Template_Group' => [
28
-                'GRP_ID'           => new EE_Primary_Key_Int_Field(
29
-                    'GRP_ID', esc_html__('Message Template Group ID', 'event_espresso')
30
-                ),
31
-                'MTP_name'         => new EE_Plain_Text_Field(
32
-                    'MTP_name', esc_html__('The name of the template group', 'event_espresso'), false, ''
33
-                ),
34
-                'MTP_description'  => new EE_Simple_HTML_Field(
35
-                    'MTP_description',
36
-                    esc_html__('A brief description about this template.', 'event_espresso'),
37
-                    false,
38
-                    ''
39
-                ),
40
-                'MTP_user_id'      => new EE_WP_User_Field(
41
-                    'MTP_user_id',
42
-                    esc_html__('Template Creator ID', 'event_espresso'),
43
-                    false
44
-                ),
45
-                'MTP_messenger'    => new EE_Plain_Text_Field(
46
-                    'MTP_messenger',
47
-                    esc_html__('Messenger Used for Template', 'event_espresso'),
48
-                    false,
49
-                    'email'
50
-                ),
51
-                'MTP_message_type' => new EE_Plain_Text_Field(
52
-                    'MTP_message_type',
53
-                    esc_html__('Message Type', 'event_espresso'),
54
-                    false,
55
-                    'registration'
56
-                ),
57
-                'MTP_is_global'    => new EE_Boolean_Field(
58
-                    'MTP_is_global',
59
-                    esc_html__('Flag indicating if Template Group is Global', 'event_espresso'),
60
-                    false,
61
-                    true
62
-                ),
63
-                'MTP_is_override'  => new EE_Boolean_Field(
64
-                    'MTP_is_override',
65
-                    esc_html__('Flag indicating if Template Group overrides any other Templates for the messenger/message type combination',
66
-                               'event_espresso'),
67
-                    false,
68
-                    false
69
-                ),
70
-                'MTP_deleted'      => new EE_Trashed_Flag_Field(
71
-                    'MTP_deleted',
72
-                    esc_html__('Flag indicating whether this has been trashed', 'event_espresso'),
73
-                    false,
74
-                    false
75
-                ),
76
-                'MTP_is_active'    => new EE_Boolean_Field(
77
-                    'MTP_is_active',
78
-                    esc_html__('Flag indicating whether template group is active', 'event_espresso'),
79
-                    false,
80
-                    true
81
-                ),
82
-            ],
83
-        ];
84
-        $this->_model_relations = [
85
-            'Message_Template' => new EE_Has_Many_Relation(),
86
-            'Message'          => new EE_Has_Many_Relation(),
87
-            'Event'            => new EE_HABTM_Relation('Event_Message_Template'),
88
-            'WP_User'          => new EE_Belongs_To_Relation(),
89
-        ];
90
-        foreach ($this->_cap_contexts_to_cap_action_map as $context => $action) {
91
-            $this->_cap_restriction_generators[ $context ] = new EE_Restriction_Generator_Global('MTP_is_global');
92
-        }
93
-        $this->_caps_slug = 'messages';
94
-
95
-        parent::__construct($timezone);
96
-    }
97
-
98
-
99
-    /**
100
-     * get_all_trashed_message_templates_by_event
101
-     *
102
-     * @param int      $EVT_ID specific event id
103
-     * @param string   $orderby
104
-     * @param string   $order
105
-     * @param int|null $limit
106
-     * @param bool     $count
107
-     * @return EE_Message_Template_Group[]|int message template objects that are attached to a specific event.
108
-     */
109
-    public function get_all_trashed_message_templates_by_event(
110
-        int $EVT_ID,
111
-        string $orderby = 'GRP_ID',
112
-        string $order = 'ASC',
113
-        int $limit = null,
114
-        bool $count = false
115
-    ) {
116
-        $query_params = [['Event.EVT_ID' => $EVT_ID], 'order_by' => [$orderby => $order], 'limit' => $limit];
117
-        return $count
118
-            ? $this->count_deleted($query_params, 'GRP_ID', true)
119
-            : $this->get_all_deleted($query_params);
120
-    }
121
-
122
-
123
-    /**
124
-     * get_all_message_templates_by_messenger
125
-     *
126
-     * @param string $messenger
127
-     * @param string $orderby
128
-     * @param string $order
129
-     * @return EE_Message_Template_Group[] all (including trashed or inactive) message template group objects for the
130
-     * given messenger
131
-     */
132
-    public function get_all_message_templates_by_messenger(string $messenger,
133
-                                                           string $orderby = 'GRP_ID',
134
-                                                           string $order = 'ASC'): array
135
-    {
136
-        return $this->get_all_deleted_and_undeleted(
137
-            [['MTP_messenger' => $messenger], 'order_by' => [$orderby => $order]]
138
-        );
139
-    }
140
-
141
-
142
-    /**
143
-     * This simply adds on any messenger/message type filters that may be present in the $_POST global
144
-     *
145
-     * @param array $_where any existing where conditions to append these to.
146
-     * @return EE_Message_Template_Group[] original where conditions or original with additional filters.
147
-     */
148
-    protected function _maybe_mtp_filters(array $_where = []): array
149
-    {
150
-        // account for messenger or message type filters
151
-        if (
152
-            isset($_REQUEST['ee_messenger_filter_by'])
153
-            && $_REQUEST['ee_messenger_filter_by'] != 'none_selected'
154
-            && $_REQUEST['ee_messenger_filter_by'] != 'all'
155
-        ) {
156
-            $_where['MTP_messenger'] = $_REQUEST['ee_messenger_filter_by'];
157
-        }
158
-
159
-        if (
160
-            isset($_REQUEST['ee_message_type_filter_by'])
161
-            && $_REQUEST['ee_message_type_filter_by'] != 'none_selected'
162
-        ) {
163
-            $_where['MTP_message_type'] = $_REQUEST['ee_message_type_filter_by'];
164
-        }
165
-
166
-        return $_where;
167
-    }
168
-
169
-
170
-    /**
171
-     * get_all_active_message_templates groups
172
-     *
173
-     * @param string   $orderby
174
-     * @param string   $order
175
-     * @param int|null $limit
176
-     * @param bool     $count
177
-     * @param bool     $global
178
-     * @param bool     $user_check
179
-     * @return EE_Message_Template_Group[]|int all active (non_trashed, active) message template objects
180
-     * @throws EE_Error
181
-     * @throws ReflectionException
182
-     */
183
-    public function get_all_active_message_templates(
184
-        string $orderby = 'GRP_ID',
185
-        string $order = 'ASC',
186
-        int $limit = null,
187
-        bool $count = false,
188
-        bool $global = true,
189
-        bool $user_check = false
190
-    ): array {
191
-        $_where                  = $global ? ['MTP_is_global' => true] : ['MTP_is_global' => false];
192
-        $_where['MTP_is_active'] = true;
193
-        $_where                  = $this->_maybe_mtp_filters($_where);
194
-
195
-        if (
196
-            $user_check
197
-            && ! $global
198
-            && ! EE_Registry::instance()->CAP->current_user_can(
199
-                'ee_read_others_messages',
200
-                'get_all_active_message_templates'
201
-            )
202
-        ) {
203
-            $_where['MTP_user_id'] = get_current_user_id();
204
-        }
205
-
206
-        $query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
207
-
208
-        return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
209
-    }
210
-
211
-
212
-    /**
213
-     *    retrieve ALL message_template groups from db regardless of wht
214
-     *
215
-     * @access    public
216
-     * @param string   $orderby
217
-     * @param string   $order
218
-     * @param int|null $limit
219
-     * @param bool     $count
220
-     * @return EE_Message_Template_Group[]
221
-     */
222
-    public function get_all_message_templates(
223
-        string $orderby = 'GRP_ID',
224
-        string $order = 'ASC',
225
-        int $limit = null,
226
-        bool $count = false
227
-    ): array {
228
-        $_where = $this->_maybe_mtp_filters();
229
-
230
-        $query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
231
-
232
-        return $count
233
-            ? $this->count_deleted_and_undeleted($query_params, 'GRP_ID', true)
234
-            : $this->get_all_deleted_and_undeleted($query_params);
235
-    }
236
-
237
-
238
-    /**
239
-     * This gets all the custom templates attached to a specific event
240
-     *
241
-     * @param int   $EVT_ID       event id
242
-     * @param array $query_params @see
243
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
244
-     * @return  EE_Message_Template_Group[]
245
-     * @throws EE_Error
246
-     * @throws ReflectionException
247
-     */
248
-    public function get_all_custom_templates_by_event(int $EVT_ID, array $query_params = []): array
249
-    {
250
-        $where = array_merge($query_params, ['Event.EVT_ID' => $EVT_ID]);
251
-        return $this->get_all([$where]);
252
-    }
253
-
254
-
255
-    /**
256
-     * get_all_trashed_grouped_message_templates
257
-     * this returns ONLY the template groups where ALL contexts are trashed and none of the group are non-trashed
258
-     *
259
-     * @param string   $orderby
260
-     * @param string   $order
261
-     * @param int|null $limit
262
-     * @param bool     $count
263
-     * @param bool     $global
264
-     * @return EE_Message_Template_Group[]|int message template groups.
265
-     */
266
-    public function get_all_trashed_grouped_message_templates(
267
-        string $orderby = 'GRP_ID',
268
-        string $order = 'ASC',
269
-        int $limit = null,
270
-        bool $count = false,
271
-        bool $global = true
272
-    ) {
273
-        $_where                  = $global ? ['MTP_is_global' => true] : ['MTP_is_global' => false];
274
-        $_where['MTP_is_active'] = true;
275
-        $_where                  = $this->_maybe_mtp_filters($_where);
276
-
277
-        $query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
278
-
279
-        return $count
280
-            ? $this->count_deleted($query_params, 'GRP_ID', true)
281
-            : $this->get_all_deleted($query_params);
282
-    }
283
-
284
-
285
-    /**
286
-     * this returns the message template group(s) for a given event, messenger, and message template
287
-     *
288
-     * @param string   $messenger
289
-     * @param string   $message_type
290
-     * @param int      $evt_id
291
-     * @param string   $orderby pointless at this point but still included
292
-     * @param string   $order
293
-     * @param int|null $limit
294
-     * @param bool     $count   true = just return count, false = objects
295
-     * @param bool     $active  ignore "active" or not. (default only return active)
296
-     * @return EE_Message_Template_Group[]|int depending on $count.
297
-     * @throws EE_Error
298
-     * @throws ReflectionException
299
-     */
300
-    public function get_event_message_templates_by_m_and_mt_and_evt(
301
-        string $messenger,
302
-        string $message_type,
303
-        int $evt_id,
304
-        string $orderby = 'GRP_ID',
305
-        string $order = 'ASC',
306
-        int $limit = null,
307
-        bool $count = false,
308
-        bool $active = true
309
-    ) {
310
-        $_where = [
311
-            'MTP_messenger'    => $messenger,
312
-            'MTP_message_type' => $message_type,
313
-            'Event.EVT_ID'     => $evt_id,
314
-            'MTP_is_global'    => true,
315
-            'MTP_is_active'    => $active,
316
-        ];
317
-
318
-        $query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
319
-
320
-        return $count
321
-            ? $this->count($query_params, 'GRP_ID', true)
322
-            : $this->get_all($query_params);
323
-    }
324
-
325
-
326
-    /**
327
-     * get all GLOBAL message template groups for the given messenger and message type
328
-     *
329
-     * @param string   $messenger    slug for messenger
330
-     * @param string   $message_type slug for message type
331
-     * @param string   $orderby      what column to orderby
332
-     * @param string   $order        ASC or DESC
333
-     * @param int|null $limit
334
-     * @param bool     $count        true = just return count, false = objects
335
-     * @param bool     $active       ignore "active" or not. (default only return active) -
336
-     *                               'all' means return both inactive AND inactive.
337
-     * @return EE_Message_Template_Group[]|int               message template objects that are global (i.e. non-event)
338
-     * @throws EE_Error
339
-     * @throws ReflectionException
340
-     */
341
-    public function get_global_message_template_by_m_and_mt(
342
-        string $messenger,
343
-        string $message_type,
344
-        string $orderby = 'GRP_ID',
345
-        string $order = 'ASC',
346
-        int $limit = null,
347
-        bool $count = false,
348
-        bool $active = true
349
-    ) {
350
-        $_where = [
351
-            'MTP_messenger'    => $messenger,
352
-            'MTP_message_type' => $message_type,
353
-            'MTP_is_global'    => true,
354
-        ];
355
-
356
-        if ($active != 'all') {
357
-            $_where['MTP_is_active'] = $active;
358
-        }
359
-
360
-        $query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
361
-
362
-        return $count
363
-            ? $this->count($query_params, 'GRP_ID', true)
364
-            : $this->get_all($query_params);
365
-    }
366
-
367
-
368
-    /**
369
-     * get all custom message template groups for the given messenger and message type
370
-     *
371
-     * @param string $messenger
372
-     * @param string $message_type
373
-     * @param array  $query_params same as EEM_Base->get_all()
374
-     * @return EE_Message_Template_Group[]
375
-     * @throws EE_Error
376
-     * @throws ReflectionException
377
-     */
378
-    public function get_custom_message_template_by_m_and_mt(string $messenger, string $message_type, array $query_params = []): array
379
-    {
380
-        return $this->get_all(
381
-            array_merge(
382
-                $query_params,
383
-                [
384
-                    [
385
-                        'MTP_is_global'    => false,
386
-                        'MTP_messenger'    => $messenger,
387
-                        'MTP_message_type' => $message_type,
388
-                    ],
389
-                ]
390
-            )
391
-        );
392
-    }
393
-
394
-
395
-    /**
396
-     * This sends things to the validator for the given messenger and message type.
397
-     *
398
-     * @param array  $fields       the incoming fields to check.
399
-     *                             Note this array is in the formatted fields from the form fields setup.
400
-     *                             So we need to reformat this into an array of expected field refs by the validator.
401
-     *                             Note also that this is not only the fields for the Message Template Group
402
-     *                             but ALSO for Message Template.
403
-     * @param string $context      The context the fields were obtained from.
404
-     * @param string $messenger    The messenger we are validating
405
-     * @param string $message_type The message type we are validating.
406
-     * @return mixed If the fields all check out then we return true otherwise error messages are returned
407
-     *                             (indexed by field name);
408
-     * @throws EE_Error
409
-     * @throws ReflectionException
410
-     */
411
-    public function validate(array $fields, string $context, string $messenger, string $message_type)
412
-    {
413
-
414
-        $assembled_fields = [];
415
-
416
-        // let's loop through all the fields and set them up in the right format
417
-        foreach ($fields as $value) {
418
-            // first let's figure out if the value['content'] in the current index is an array.
419
-            //  If it is then this is special fields that are used in parsing special shortcodes (i.e. 'attendee_list').
420
-            if (is_array($value['content'])) {
421
-                $assembled_fields[ $value['name'] ] = $value['content']['main'];
422
-                // loop through the content and get the other fields.
423
-                foreach ($value['content'] as $name => $val) {
424
-                    if ($name == 'main') {
425
-                        continue;
426
-                    }
427
-                    $assembled_fields[ $name ] = $val;
428
-                }
429
-                continue;
430
-            }
431
-
432
-            // okay if we're here then this is just a straight field=>$value arrangement
433
-            $assembled_fields[ $value['name'] ] = $value['content'];
434
-        }
435
-
436
-        // now we've got the assembled_fields.
437
-        // We need to setup the string for the appropriate validator class and call that.
438
-        $m_ref  = ucwords(str_replace('_', ' ', $messenger));
439
-        $m_ref  = str_replace(' ', '_', $m_ref);
440
-        $mt_ref = ucwords(str_replace('_', ' ', $message_type));
441
-        $mt_ref = str_replace(' ', '_', $mt_ref);
442
-
443
-        $classname = 'EE_Messages_' . $m_ref . '_' . $mt_ref . '_Validator';
444
-
445
-        if (! class_exists($classname)) {
446
-            $msg[] = esc_html__('The Validator class was unable to load', 'event_espresso');
447
-            $msg[] = sprintf(
448
-                esc_html__(
449
-                    'The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class',
450
-                    'event_espresso'
451
-                ),
452
-                $classname
453
-            );
454
-            throw new EE_Error(implode('||', $msg));
455
-        }
456
-
457
-        $a      = new ReflectionClass($classname);
458
-        $_VLD   = $a->newInstance($assembled_fields, $context);
459
-        return $_VLD->validate();
460
-    }
461
-
462
-
463
-    /**
464
-     * Updates all message template groups matching the incoming arguments to inactive status.
465
-     *
466
-     * @param array $messenger_names    The messenger slugs.
467
-     *                                  If empty then all templates matching the message types are marked inactive.
468
-     *                                  Otherwise only templates matching the messengers and message types.
469
-     * @param array $message_type_names The message type slugs.
470
-     *                                  If empty then all templates matching the messengers are marked inactive.
471
-     *                                  Otherwise only templates matching the messengers and message types.
472
-     *
473
-     * @return int  count of updated records.
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public function deactivate_message_template_groups_for(
478
-        array $messenger_names = [],
479
-        array $message_type_names = []
480
-    ): int {
481
-        $query_args = [];
482
-        if (empty($messenger_names) && empty($message_type_names)) {
483
-            return 0;
484
-        }
485
-        if (! empty($messenger_names)) {
486
-            $query_args[0]['MTP_messenger'] = ['IN', $messenger_names];
487
-        }
488
-        if (! empty($message_type_names)) {
489
-            $query_args[0]['MTP_message_type'] = ['IN', $message_type_names];
490
-        }
491
-        return $this->update(['MTP_is_active' => false], $query_args);
492
-    }
15
+	// private instance of the EEM_Message_Template_Group object
16
+	protected static $_instance;
17
+
18
+
19
+	protected function __construct(string $timezone = '')
20
+	{
21
+		$this->singular_item    = esc_html__('Message Template Group', 'event_espresso');
22
+		$this->plural_item      = esc_html__('Message Template Groups', 'event_espresso');
23
+		$this->_tables          = [
24
+			'Message_Template_Group' => new EE_Primary_Table('esp_message_template_group', 'GRP_ID'),
25
+		];
26
+		$this->_fields          = [
27
+			'Message_Template_Group' => [
28
+				'GRP_ID'           => new EE_Primary_Key_Int_Field(
29
+					'GRP_ID', esc_html__('Message Template Group ID', 'event_espresso')
30
+				),
31
+				'MTP_name'         => new EE_Plain_Text_Field(
32
+					'MTP_name', esc_html__('The name of the template group', 'event_espresso'), false, ''
33
+				),
34
+				'MTP_description'  => new EE_Simple_HTML_Field(
35
+					'MTP_description',
36
+					esc_html__('A brief description about this template.', 'event_espresso'),
37
+					false,
38
+					''
39
+				),
40
+				'MTP_user_id'      => new EE_WP_User_Field(
41
+					'MTP_user_id',
42
+					esc_html__('Template Creator ID', 'event_espresso'),
43
+					false
44
+				),
45
+				'MTP_messenger'    => new EE_Plain_Text_Field(
46
+					'MTP_messenger',
47
+					esc_html__('Messenger Used for Template', 'event_espresso'),
48
+					false,
49
+					'email'
50
+				),
51
+				'MTP_message_type' => new EE_Plain_Text_Field(
52
+					'MTP_message_type',
53
+					esc_html__('Message Type', 'event_espresso'),
54
+					false,
55
+					'registration'
56
+				),
57
+				'MTP_is_global'    => new EE_Boolean_Field(
58
+					'MTP_is_global',
59
+					esc_html__('Flag indicating if Template Group is Global', 'event_espresso'),
60
+					false,
61
+					true
62
+				),
63
+				'MTP_is_override'  => new EE_Boolean_Field(
64
+					'MTP_is_override',
65
+					esc_html__('Flag indicating if Template Group overrides any other Templates for the messenger/message type combination',
66
+							   'event_espresso'),
67
+					false,
68
+					false
69
+				),
70
+				'MTP_deleted'      => new EE_Trashed_Flag_Field(
71
+					'MTP_deleted',
72
+					esc_html__('Flag indicating whether this has been trashed', 'event_espresso'),
73
+					false,
74
+					false
75
+				),
76
+				'MTP_is_active'    => new EE_Boolean_Field(
77
+					'MTP_is_active',
78
+					esc_html__('Flag indicating whether template group is active', 'event_espresso'),
79
+					false,
80
+					true
81
+				),
82
+			],
83
+		];
84
+		$this->_model_relations = [
85
+			'Message_Template' => new EE_Has_Many_Relation(),
86
+			'Message'          => new EE_Has_Many_Relation(),
87
+			'Event'            => new EE_HABTM_Relation('Event_Message_Template'),
88
+			'WP_User'          => new EE_Belongs_To_Relation(),
89
+		];
90
+		foreach ($this->_cap_contexts_to_cap_action_map as $context => $action) {
91
+			$this->_cap_restriction_generators[ $context ] = new EE_Restriction_Generator_Global('MTP_is_global');
92
+		}
93
+		$this->_caps_slug = 'messages';
94
+
95
+		parent::__construct($timezone);
96
+	}
97
+
98
+
99
+	/**
100
+	 * get_all_trashed_message_templates_by_event
101
+	 *
102
+	 * @param int      $EVT_ID specific event id
103
+	 * @param string   $orderby
104
+	 * @param string   $order
105
+	 * @param int|null $limit
106
+	 * @param bool     $count
107
+	 * @return EE_Message_Template_Group[]|int message template objects that are attached to a specific event.
108
+	 */
109
+	public function get_all_trashed_message_templates_by_event(
110
+		int $EVT_ID,
111
+		string $orderby = 'GRP_ID',
112
+		string $order = 'ASC',
113
+		int $limit = null,
114
+		bool $count = false
115
+	) {
116
+		$query_params = [['Event.EVT_ID' => $EVT_ID], 'order_by' => [$orderby => $order], 'limit' => $limit];
117
+		return $count
118
+			? $this->count_deleted($query_params, 'GRP_ID', true)
119
+			: $this->get_all_deleted($query_params);
120
+	}
121
+
122
+
123
+	/**
124
+	 * get_all_message_templates_by_messenger
125
+	 *
126
+	 * @param string $messenger
127
+	 * @param string $orderby
128
+	 * @param string $order
129
+	 * @return EE_Message_Template_Group[] all (including trashed or inactive) message template group objects for the
130
+	 * given messenger
131
+	 */
132
+	public function get_all_message_templates_by_messenger(string $messenger,
133
+														   string $orderby = 'GRP_ID',
134
+														   string $order = 'ASC'): array
135
+	{
136
+		return $this->get_all_deleted_and_undeleted(
137
+			[['MTP_messenger' => $messenger], 'order_by' => [$orderby => $order]]
138
+		);
139
+	}
140
+
141
+
142
+	/**
143
+	 * This simply adds on any messenger/message type filters that may be present in the $_POST global
144
+	 *
145
+	 * @param array $_where any existing where conditions to append these to.
146
+	 * @return EE_Message_Template_Group[] original where conditions or original with additional filters.
147
+	 */
148
+	protected function _maybe_mtp_filters(array $_where = []): array
149
+	{
150
+		// account for messenger or message type filters
151
+		if (
152
+			isset($_REQUEST['ee_messenger_filter_by'])
153
+			&& $_REQUEST['ee_messenger_filter_by'] != 'none_selected'
154
+			&& $_REQUEST['ee_messenger_filter_by'] != 'all'
155
+		) {
156
+			$_where['MTP_messenger'] = $_REQUEST['ee_messenger_filter_by'];
157
+		}
158
+
159
+		if (
160
+			isset($_REQUEST['ee_message_type_filter_by'])
161
+			&& $_REQUEST['ee_message_type_filter_by'] != 'none_selected'
162
+		) {
163
+			$_where['MTP_message_type'] = $_REQUEST['ee_message_type_filter_by'];
164
+		}
165
+
166
+		return $_where;
167
+	}
168
+
169
+
170
+	/**
171
+	 * get_all_active_message_templates groups
172
+	 *
173
+	 * @param string   $orderby
174
+	 * @param string   $order
175
+	 * @param int|null $limit
176
+	 * @param bool     $count
177
+	 * @param bool     $global
178
+	 * @param bool     $user_check
179
+	 * @return EE_Message_Template_Group[]|int all active (non_trashed, active) message template objects
180
+	 * @throws EE_Error
181
+	 * @throws ReflectionException
182
+	 */
183
+	public function get_all_active_message_templates(
184
+		string $orderby = 'GRP_ID',
185
+		string $order = 'ASC',
186
+		int $limit = null,
187
+		bool $count = false,
188
+		bool $global = true,
189
+		bool $user_check = false
190
+	): array {
191
+		$_where                  = $global ? ['MTP_is_global' => true] : ['MTP_is_global' => false];
192
+		$_where['MTP_is_active'] = true;
193
+		$_where                  = $this->_maybe_mtp_filters($_where);
194
+
195
+		if (
196
+			$user_check
197
+			&& ! $global
198
+			&& ! EE_Registry::instance()->CAP->current_user_can(
199
+				'ee_read_others_messages',
200
+				'get_all_active_message_templates'
201
+			)
202
+		) {
203
+			$_where['MTP_user_id'] = get_current_user_id();
204
+		}
205
+
206
+		$query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
207
+
208
+		return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
209
+	}
210
+
211
+
212
+	/**
213
+	 *    retrieve ALL message_template groups from db regardless of wht
214
+	 *
215
+	 * @access    public
216
+	 * @param string   $orderby
217
+	 * @param string   $order
218
+	 * @param int|null $limit
219
+	 * @param bool     $count
220
+	 * @return EE_Message_Template_Group[]
221
+	 */
222
+	public function get_all_message_templates(
223
+		string $orderby = 'GRP_ID',
224
+		string $order = 'ASC',
225
+		int $limit = null,
226
+		bool $count = false
227
+	): array {
228
+		$_where = $this->_maybe_mtp_filters();
229
+
230
+		$query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
231
+
232
+		return $count
233
+			? $this->count_deleted_and_undeleted($query_params, 'GRP_ID', true)
234
+			: $this->get_all_deleted_and_undeleted($query_params);
235
+	}
236
+
237
+
238
+	/**
239
+	 * This gets all the custom templates attached to a specific event
240
+	 *
241
+	 * @param int   $EVT_ID       event id
242
+	 * @param array $query_params @see
243
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
244
+	 * @return  EE_Message_Template_Group[]
245
+	 * @throws EE_Error
246
+	 * @throws ReflectionException
247
+	 */
248
+	public function get_all_custom_templates_by_event(int $EVT_ID, array $query_params = []): array
249
+	{
250
+		$where = array_merge($query_params, ['Event.EVT_ID' => $EVT_ID]);
251
+		return $this->get_all([$where]);
252
+	}
253
+
254
+
255
+	/**
256
+	 * get_all_trashed_grouped_message_templates
257
+	 * this returns ONLY the template groups where ALL contexts are trashed and none of the group are non-trashed
258
+	 *
259
+	 * @param string   $orderby
260
+	 * @param string   $order
261
+	 * @param int|null $limit
262
+	 * @param bool     $count
263
+	 * @param bool     $global
264
+	 * @return EE_Message_Template_Group[]|int message template groups.
265
+	 */
266
+	public function get_all_trashed_grouped_message_templates(
267
+		string $orderby = 'GRP_ID',
268
+		string $order = 'ASC',
269
+		int $limit = null,
270
+		bool $count = false,
271
+		bool $global = true
272
+	) {
273
+		$_where                  = $global ? ['MTP_is_global' => true] : ['MTP_is_global' => false];
274
+		$_where['MTP_is_active'] = true;
275
+		$_where                  = $this->_maybe_mtp_filters($_where);
276
+
277
+		$query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
278
+
279
+		return $count
280
+			? $this->count_deleted($query_params, 'GRP_ID', true)
281
+			: $this->get_all_deleted($query_params);
282
+	}
283
+
284
+
285
+	/**
286
+	 * this returns the message template group(s) for a given event, messenger, and message template
287
+	 *
288
+	 * @param string   $messenger
289
+	 * @param string   $message_type
290
+	 * @param int      $evt_id
291
+	 * @param string   $orderby pointless at this point but still included
292
+	 * @param string   $order
293
+	 * @param int|null $limit
294
+	 * @param bool     $count   true = just return count, false = objects
295
+	 * @param bool     $active  ignore "active" or not. (default only return active)
296
+	 * @return EE_Message_Template_Group[]|int depending on $count.
297
+	 * @throws EE_Error
298
+	 * @throws ReflectionException
299
+	 */
300
+	public function get_event_message_templates_by_m_and_mt_and_evt(
301
+		string $messenger,
302
+		string $message_type,
303
+		int $evt_id,
304
+		string $orderby = 'GRP_ID',
305
+		string $order = 'ASC',
306
+		int $limit = null,
307
+		bool $count = false,
308
+		bool $active = true
309
+	) {
310
+		$_where = [
311
+			'MTP_messenger'    => $messenger,
312
+			'MTP_message_type' => $message_type,
313
+			'Event.EVT_ID'     => $evt_id,
314
+			'MTP_is_global'    => true,
315
+			'MTP_is_active'    => $active,
316
+		];
317
+
318
+		$query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
319
+
320
+		return $count
321
+			? $this->count($query_params, 'GRP_ID', true)
322
+			: $this->get_all($query_params);
323
+	}
324
+
325
+
326
+	/**
327
+	 * get all GLOBAL message template groups for the given messenger and message type
328
+	 *
329
+	 * @param string   $messenger    slug for messenger
330
+	 * @param string   $message_type slug for message type
331
+	 * @param string   $orderby      what column to orderby
332
+	 * @param string   $order        ASC or DESC
333
+	 * @param int|null $limit
334
+	 * @param bool     $count        true = just return count, false = objects
335
+	 * @param bool     $active       ignore "active" or not. (default only return active) -
336
+	 *                               'all' means return both inactive AND inactive.
337
+	 * @return EE_Message_Template_Group[]|int               message template objects that are global (i.e. non-event)
338
+	 * @throws EE_Error
339
+	 * @throws ReflectionException
340
+	 */
341
+	public function get_global_message_template_by_m_and_mt(
342
+		string $messenger,
343
+		string $message_type,
344
+		string $orderby = 'GRP_ID',
345
+		string $order = 'ASC',
346
+		int $limit = null,
347
+		bool $count = false,
348
+		bool $active = true
349
+	) {
350
+		$_where = [
351
+			'MTP_messenger'    => $messenger,
352
+			'MTP_message_type' => $message_type,
353
+			'MTP_is_global'    => true,
354
+		];
355
+
356
+		if ($active != 'all') {
357
+			$_where['MTP_is_active'] = $active;
358
+		}
359
+
360
+		$query_params = [$_where, 'order_by' => [$orderby => $order], 'limit' => $limit];
361
+
362
+		return $count
363
+			? $this->count($query_params, 'GRP_ID', true)
364
+			: $this->get_all($query_params);
365
+	}
366
+
367
+
368
+	/**
369
+	 * get all custom message template groups for the given messenger and message type
370
+	 *
371
+	 * @param string $messenger
372
+	 * @param string $message_type
373
+	 * @param array  $query_params same as EEM_Base->get_all()
374
+	 * @return EE_Message_Template_Group[]
375
+	 * @throws EE_Error
376
+	 * @throws ReflectionException
377
+	 */
378
+	public function get_custom_message_template_by_m_and_mt(string $messenger, string $message_type, array $query_params = []): array
379
+	{
380
+		return $this->get_all(
381
+			array_merge(
382
+				$query_params,
383
+				[
384
+					[
385
+						'MTP_is_global'    => false,
386
+						'MTP_messenger'    => $messenger,
387
+						'MTP_message_type' => $message_type,
388
+					],
389
+				]
390
+			)
391
+		);
392
+	}
393
+
394
+
395
+	/**
396
+	 * This sends things to the validator for the given messenger and message type.
397
+	 *
398
+	 * @param array  $fields       the incoming fields to check.
399
+	 *                             Note this array is in the formatted fields from the form fields setup.
400
+	 *                             So we need to reformat this into an array of expected field refs by the validator.
401
+	 *                             Note also that this is not only the fields for the Message Template Group
402
+	 *                             but ALSO for Message Template.
403
+	 * @param string $context      The context the fields were obtained from.
404
+	 * @param string $messenger    The messenger we are validating
405
+	 * @param string $message_type The message type we are validating.
406
+	 * @return mixed If the fields all check out then we return true otherwise error messages are returned
407
+	 *                             (indexed by field name);
408
+	 * @throws EE_Error
409
+	 * @throws ReflectionException
410
+	 */
411
+	public function validate(array $fields, string $context, string $messenger, string $message_type)
412
+	{
413
+
414
+		$assembled_fields = [];
415
+
416
+		// let's loop through all the fields and set them up in the right format
417
+		foreach ($fields as $value) {
418
+			// first let's figure out if the value['content'] in the current index is an array.
419
+			//  If it is then this is special fields that are used in parsing special shortcodes (i.e. 'attendee_list').
420
+			if (is_array($value['content'])) {
421
+				$assembled_fields[ $value['name'] ] = $value['content']['main'];
422
+				// loop through the content and get the other fields.
423
+				foreach ($value['content'] as $name => $val) {
424
+					if ($name == 'main') {
425
+						continue;
426
+					}
427
+					$assembled_fields[ $name ] = $val;
428
+				}
429
+				continue;
430
+			}
431
+
432
+			// okay if we're here then this is just a straight field=>$value arrangement
433
+			$assembled_fields[ $value['name'] ] = $value['content'];
434
+		}
435
+
436
+		// now we've got the assembled_fields.
437
+		// We need to setup the string for the appropriate validator class and call that.
438
+		$m_ref  = ucwords(str_replace('_', ' ', $messenger));
439
+		$m_ref  = str_replace(' ', '_', $m_ref);
440
+		$mt_ref = ucwords(str_replace('_', ' ', $message_type));
441
+		$mt_ref = str_replace(' ', '_', $mt_ref);
442
+
443
+		$classname = 'EE_Messages_' . $m_ref . '_' . $mt_ref . '_Validator';
444
+
445
+		if (! class_exists($classname)) {
446
+			$msg[] = esc_html__('The Validator class was unable to load', 'event_espresso');
447
+			$msg[] = sprintf(
448
+				esc_html__(
449
+					'The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class',
450
+					'event_espresso'
451
+				),
452
+				$classname
453
+			);
454
+			throw new EE_Error(implode('||', $msg));
455
+		}
456
+
457
+		$a      = new ReflectionClass($classname);
458
+		$_VLD   = $a->newInstance($assembled_fields, $context);
459
+		return $_VLD->validate();
460
+	}
461
+
462
+
463
+	/**
464
+	 * Updates all message template groups matching the incoming arguments to inactive status.
465
+	 *
466
+	 * @param array $messenger_names    The messenger slugs.
467
+	 *                                  If empty then all templates matching the message types are marked inactive.
468
+	 *                                  Otherwise only templates matching the messengers and message types.
469
+	 * @param array $message_type_names The message type slugs.
470
+	 *                                  If empty then all templates matching the messengers are marked inactive.
471
+	 *                                  Otherwise only templates matching the messengers and message types.
472
+	 *
473
+	 * @return int  count of updated records.
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function deactivate_message_template_groups_for(
478
+		array $messenger_names = [],
479
+		array $message_type_names = []
480
+	): int {
481
+		$query_args = [];
482
+		if (empty($messenger_names) && empty($message_type_names)) {
483
+			return 0;
484
+		}
485
+		if (! empty($messenger_names)) {
486
+			$query_args[0]['MTP_messenger'] = ['IN', $messenger_names];
487
+		}
488
+		if (! empty($message_type_names)) {
489
+			$query_args[0]['MTP_message_type'] = ['IN', $message_type_names];
490
+		}
491
+		return $this->update(['MTP_is_active' => false], $query_args);
492
+	}
493 493
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
             'WP_User'          => new EE_Belongs_To_Relation(),
89 89
         ];
90 90
         foreach ($this->_cap_contexts_to_cap_action_map as $context => $action) {
91
-            $this->_cap_restriction_generators[ $context ] = new EE_Restriction_Generator_Global('MTP_is_global');
91
+            $this->_cap_restriction_generators[$context] = new EE_Restriction_Generator_Global('MTP_is_global');
92 92
         }
93 93
         $this->_caps_slug = 'messages';
94 94
 
@@ -418,19 +418,19 @@  discard block
 block discarded – undo
418 418
             // first let's figure out if the value['content'] in the current index is an array.
419 419
             //  If it is then this is special fields that are used in parsing special shortcodes (i.e. 'attendee_list').
420 420
             if (is_array($value['content'])) {
421
-                $assembled_fields[ $value['name'] ] = $value['content']['main'];
421
+                $assembled_fields[$value['name']] = $value['content']['main'];
422 422
                 // loop through the content and get the other fields.
423 423
                 foreach ($value['content'] as $name => $val) {
424 424
                     if ($name == 'main') {
425 425
                         continue;
426 426
                     }
427
-                    $assembled_fields[ $name ] = $val;
427
+                    $assembled_fields[$name] = $val;
428 428
                 }
429 429
                 continue;
430 430
             }
431 431
 
432 432
             // okay if we're here then this is just a straight field=>$value arrangement
433
-            $assembled_fields[ $value['name'] ] = $value['content'];
433
+            $assembled_fields[$value['name']] = $value['content'];
434 434
         }
435 435
 
436 436
         // now we've got the assembled_fields.
@@ -440,9 +440,9 @@  discard block
 block discarded – undo
440 440
         $mt_ref = ucwords(str_replace('_', ' ', $message_type));
441 441
         $mt_ref = str_replace(' ', '_', $mt_ref);
442 442
 
443
-        $classname = 'EE_Messages_' . $m_ref . '_' . $mt_ref . '_Validator';
443
+        $classname = 'EE_Messages_'.$m_ref.'_'.$mt_ref.'_Validator';
444 444
 
445
-        if (! class_exists($classname)) {
445
+        if ( ! class_exists($classname)) {
446 446
             $msg[] = esc_html__('The Validator class was unable to load', 'event_espresso');
447 447
             $msg[] = sprintf(
448 448
                 esc_html__(
@@ -482,10 +482,10 @@  discard block
 block discarded – undo
482 482
         if (empty($messenger_names) && empty($message_type_names)) {
483 483
             return 0;
484 484
         }
485
-        if (! empty($messenger_names)) {
485
+        if ( ! empty($messenger_names)) {
486 486
             $query_args[0]['MTP_messenger'] = ['IN', $messenger_names];
487 487
         }
488
-        if (! empty($message_type_names)) {
488
+        if ( ! empty($message_type_names)) {
489 489
             $query_args[0]['MTP_message_type'] = ['IN', $message_type_names];
490 490
         }
491 491
         return $this->update(['MTP_is_active' => false], $query_args);
Please login to merge, or discard this patch.