Completed
Branch master (87d3f3)
by
unknown
03:30
created
core/domain/Domain.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -15,87 +15,87 @@
 block discarded – undo
15 15
  */
16 16
 class Domain extends DomainBase implements CaffeinatedInterface
17 17
 {
18
-    /**
19
-     * URL path component used to denote an API request
20
-     */
21
-    const API_NAMESPACE = 'ee/v';
22
-
23
-    const ASSET_NAMESPACE = 'eventespresso';
24
-
25
-    const TEXT_DOMAIN = 'event_espresso';
26
-
27
-    /**
28
-     * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
-     * Page ui.
30
-     */
31
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
-        = 'manual_registration_status_change_from_registration_admin';
33
-
34
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
-        = 'manual_registration_status_change_from_registration_admin_and_notify';
36
-
37
-
38
-    /**
39
-     * Whether or not EE core is the full premium version.
40
-     * @since 4.9.59.p
41
-     * @var bool
42
-     */
43
-    private $caffeinated;
44
-
45
-    /**
46
-     * @since $VID:$
47
-     * @var bool
48
-     */
49
-    private $multisite;
50
-
51
-
52
-    public function __construct(FilePath $plugin_file, Version $version)
53
-    {
54
-        parent::__construct($plugin_file, $version);
55
-        $this->setCaffeinated();
56
-        $this->multisite = is_multisite();
57
-    }
58
-
59
-    /**
60
-     * Whether or not EE core is the full premium version.
61
-     * @since 4.9.59.p
62
-     * @return bool
63
-     */
64
-    public function isCaffeinated()
65
-    {
66
-        return $this->caffeinated;
67
-    }
68
-
69
-
70
-    /**
71
-     * Setter for $is_caffeinated property.
72
-     * @since 4.9.59.p
73
-     */
74
-    private function setCaffeinated()
75
-    {
76
-        $this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
77
-            && is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
78
-    }
79
-
80
-
81
-    /**
82
-     * This should be used everywhere the Event Espresso brand name is referenced in public facing interfaces
83
-     * to allow for filtering the brand.
84
-     *
85
-     * @return string
86
-     */
87
-    public static function brandName()
88
-    {
89
-        return (string) apply_filters('FHEE__EventEspresso_core_domain_Domain__brandName', 'Event Espresso');
90
-    }
91
-
92
-
93
-    /**
94
-     * @return bool
95
-     * @since $VID:$
96
-     */
97
-    public function isMultiSite(): bool
98
-    {
99
-        return $this->multisite;
100
-    }
18
+	/**
19
+	 * URL path component used to denote an API request
20
+	 */
21
+	const API_NAMESPACE = 'ee/v';
22
+
23
+	const ASSET_NAMESPACE = 'eventespresso';
24
+
25
+	const TEXT_DOMAIN = 'event_espresso';
26
+
27
+	/**
28
+	 * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
+	 * Page ui.
30
+	 */
31
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
+		= 'manual_registration_status_change_from_registration_admin';
33
+
34
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
+		= 'manual_registration_status_change_from_registration_admin_and_notify';
36
+
37
+
38
+	/**
39
+	 * Whether or not EE core is the full premium version.
40
+	 * @since 4.9.59.p
41
+	 * @var bool
42
+	 */
43
+	private $caffeinated;
44
+
45
+	/**
46
+	 * @since $VID:$
47
+	 * @var bool
48
+	 */
49
+	private $multisite;
50
+
51
+
52
+	public function __construct(FilePath $plugin_file, Version $version)
53
+	{
54
+		parent::__construct($plugin_file, $version);
55
+		$this->setCaffeinated();
56
+		$this->multisite = is_multisite();
57
+	}
58
+
59
+	/**
60
+	 * Whether or not EE core is the full premium version.
61
+	 * @since 4.9.59.p
62
+	 * @return bool
63
+	 */
64
+	public function isCaffeinated()
65
+	{
66
+		return $this->caffeinated;
67
+	}
68
+
69
+
70
+	/**
71
+	 * Setter for $is_caffeinated property.
72
+	 * @since 4.9.59.p
73
+	 */
74
+	private function setCaffeinated()
75
+	{
76
+		$this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
77
+			&& is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
78
+	}
79
+
80
+
81
+	/**
82
+	 * This should be used everywhere the Event Espresso brand name is referenced in public facing interfaces
83
+	 * to allow for filtering the brand.
84
+	 *
85
+	 * @return string
86
+	 */
87
+	public static function brandName()
88
+	{
89
+		return (string) apply_filters('FHEE__EventEspresso_core_domain_Domain__brandName', 'Event Espresso');
90
+	}
91
+
92
+
93
+	/**
94
+	 * @return bool
95
+	 * @since $VID:$
96
+	 */
97
+	public function isMultiSite(): bool
98
+	{
99
+		return $this->multisite;
100
+	}
101 101
 }
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 1 patch
Indentation   +858 added lines, -858 removed lines patch added patch discarded remove patch
@@ -22,862 +22,862 @@
 block discarded – undo
22 22
  */
23 23
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
24 24
 {
25
-    /**
26
-     * @var RegForm
27
-     */
28
-    public $reg_form;
29
-
30
-    /**
31
-     * @var int
32
-     */
33
-    protected $reg_form_count = 0;
34
-
35
-
36
-    /**
37
-     *    class constructor
38
-     *
39
-     * @access    public
40
-     * @param EE_Checkout $checkout
41
-     */
42
-    public function __construct(EE_Checkout $checkout)
43
-    {
44
-        $this->_slug    = 'attendee_information';
45
-        $this->_name    = esc_html__('Attendee Information', 'event_espresso');
46
-        $this->checkout = $checkout;
47
-        $this->_reset_success_message();
48
-        $this->set_instructions(
49
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
50
-        );
51
-    }
52
-
53
-
54
-    public function translate_js_strings()
55
-    {
56
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
57
-            ' is a required question.',
58
-            'event_espresso'
59
-        );
60
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
61
-            ' is a required question. Please enter a value for at least one of the options.',
62
-            'event_espresso'
63
-        );
64
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
65
-            'Please answer all required questions correctly before proceeding.',
66
-            'event_espresso'
67
-        );
68
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
69
-            esc_html_x(
70
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
71
-                'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
72
-                'event_espresso'
73
-            ),
74
-            '<br/>'
75
-        );
76
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
77
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
78
-            'event_espresso'
79
-        );
80
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
81
-            'You must enter a valid email address.',
82
-            'event_espresso'
83
-        );
84
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
85
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
86
-            'event_espresso'
87
-        );
88
-    }
89
-
90
-
91
-    public function enqueue_styles_and_scripts()
92
-    {
93
-    }
94
-
95
-
96
-    /**
97
-     * @return boolean
98
-     */
99
-    public function initialize_reg_step(): bool
100
-    {
101
-        return true;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return RegForm
107
-     * @throws DomainException
108
-     * @throws InvalidArgumentException
109
-     * @throws EntityNotFoundException
110
-     * @throws InvalidDataTypeException
111
-     * @throws InvalidInterfaceException
112
-     */
113
-    public function generate_reg_form(): RegForm
114
-    {
115
-        $this->setLegacyFiltersForRegFormGeneration();
116
-        /** @var RegFormDependencyHandler $dependency_handler */
117
-        $dependency_handler = LoaderFactory::getShared(RegFormDependencyHandler::class);
118
-        $dependency_handler->registerDependencies();
119
-        // TODO detect if event has a reg form UUID and swap this out for form generated by new reg form builder
120
-        return LoaderFactory::getShared(RegForm::class, [$this]);
121
-    }
122
-
123
-
124
-    /**
125
-     * @since   $VID:$
126
-     */
127
-    private function setLegacyFiltersForRegFormGeneration()
128
-    {
129
-        add_filter(
130
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_groups_query_parameters',
131
-            [$this, 'registrationQuestionGroupsQueryParameters'],
132
-            1,
133
-            2
134
-        );
135
-        add_filter(
136
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_group_reg_form',
137
-            [$this, 'registrationQuestionGroupsRegForm'],
138
-            1,
139
-            3
140
-        );
141
-        add_filter(
142
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__printCopyInfo',
143
-            [$this, 'registrationRegFormPrintCopyInfo'],
144
-            1,
145
-            2
146
-        );
147
-        add_filter(
148
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__related_questions_query_params',
149
-            [$this, 'registrationRegFormRelatedQuestionsQueryParams'],
150
-            1,
151
-            3
152
-        );
153
-        add_filter(
154
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__before_question_group_questions',
155
-            [$this, 'registrationRegFormBeforeQuestionGroupQuestions'],
156
-            1,
157
-            3
158
-        );
159
-        add_filter(
160
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__subsections_array',
161
-            [$this, 'registrationRegFormSubsections'],
162
-            1,
163
-            3
164
-        );
165
-        add_filter(
166
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__after_question_group_questions',
167
-            [$this, 'registrationRegFormAfterQuestionGroupQuestions'],
168
-            1,
169
-            3
170
-        );
171
-        add_filter(
172
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_AutoCopyAttendeeInfoForm__construct__template_args',
173
-            [$this, 'autoCopyAttendeeInfoTemplateArgs'],
174
-            1
175
-        );
176
-        add_filter(
177
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_CountryOptions__generateLegacyCountryOptions__country_options',
178
-            [$this, 'generateQuestionInputCountryOptions'],
179
-            1,
180
-            4
181
-        );
182
-        add_filter(
183
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_StateOptions__generateLegacyStateOptions__state_options',
184
-            [$this, 'generateQuestionInputStateOptions'],
185
-            1,
186
-            4
187
-        );
188
-    }
189
-
190
-
191
-    /**
192
-     * @param array           $query_params
193
-     * @param EE_Registration $registration
194
-     * @return mixed|void
195
-     * @since   $VID:$
196
-     */
197
-    public function registrationQuestionGroupsQueryParameters(
198
-        array $query_params,
199
-        EE_Registration $registration
200
-    ) {
201
-        return apply_filters(
202
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
203
-            $query_params,
204
-            $registration,
205
-            $this
206
-        );
207
-    }
208
-
209
-
210
-    /**
211
-     * @param RegFormQuestionGroup $question_group_reg_form
212
-     * @param EE_Registration      $registration
213
-     * @param EE_Question_Group    $question_group
214
-     * @return mixed|void
215
-     * @since   $VID:$
216
-     */
217
-    public function registrationQuestionGroupsRegForm(
218
-        RegFormQuestionGroup $question_group_reg_form,
219
-        EE_Registration $registration,
220
-        EE_Question_Group $question_group
221
-    ) {
222
-        return apply_filters(
223
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
224
-            $question_group_reg_form,
225
-            $registration,
226
-            $question_group,
227
-            $this
228
-        );
229
-    }
230
-
231
-
232
-    /**
233
-     * @param int $print_copy_info
234
-     * @param int $attendee_nmbr
235
-     * @return mixed|void
236
-     * @since   $VID:$
237
-     */
238
-    public function registrationRegFormPrintCopyInfo(
239
-        int $print_copy_info,
240
-        int $attendee_nmbr
241
-    ) {
242
-        return apply_filters(
243
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form___printCopyInfo',
244
-            $print_copy_info,
245
-            $attendee_nmbr
246
-        );
247
-    }
248
-
249
-
250
-    /**
251
-     * @param array             $query_params
252
-     * @param EE_Question_Group $question_group
253
-     * @param EE_Registration   $registration
254
-     * @return mixed|void
255
-     * @since   $VID:$
256
-     */
257
-    public function registrationRegFormRelatedQuestionsQueryParams(
258
-        array $query_params,
259
-        EE_Question_Group $question_group,
260
-        EE_Registration $registration
261
-    ) {
262
-        return apply_filters(
263
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
264
-            $query_params,
265
-            $question_group,
266
-            $registration,
267
-            $this
268
-        );
269
-    }
270
-
271
-
272
-    /**
273
-     * @param                   $html
274
-     * @param EE_Registration   $registration
275
-     * @param EE_Question_Group $question_group
276
-     * @return mixed|void
277
-     * @since   $VID:$
278
-     */
279
-    public function registrationRegFormBeforeQuestionGroupQuestions(
280
-        $html,
281
-        EE_Registration $registration,
282
-        EE_Question_Group $question_group
283
-    ) {
284
-        return apply_filters(
285
-            'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
286
-            $html,
287
-            $registration,
288
-            $question_group,
289
-            $this
290
-        );
291
-    }
292
-
293
-
294
-    /**
295
-     * @param array             $form_subsections
296
-     * @param EE_Registration   $registration
297
-     * @param EE_Question_Group $question_group
298
-     * @return mixed|void
299
-     * @since   $VID:$
300
-     */
301
-    public function registrationRegFormSubsections(
302
-        array $form_subsections,
303
-        EE_Registration $registration,
304
-        EE_Question_Group $question_group
305
-    ) {
306
-        return apply_filters(
307
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
308
-            $form_subsections,
309
-            $registration,
310
-            $question_group,
311
-            $this
312
-        );
313
-    }
314
-
315
-
316
-    /**
317
-     * @param                   $html
318
-     * @param EE_Registration   $registration
319
-     * @param EE_Question_Group $question_group
320
-     * @return mixed|void
321
-     * @since   $VID:$
322
-     */
323
-    public function registrationRegFormAfterQuestionGroupQuestions(
324
-        $html,
325
-        EE_Registration $registration,
326
-        EE_Question_Group $question_group
327
-    ) {
328
-        return apply_filters(
329
-            'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
330
-            $html,
331
-            $registration,
332
-            $question_group,
333
-            $this
334
-        );
335
-    }
336
-
337
-
338
-    /**
339
-     * @param array $template_args
340
-     * @return mixed|void
341
-     * @since   $VID:$
342
-     */
343
-    public function autoCopyAttendeeInfoTemplateArgs(array $template_args = [])
344
-    {
345
-        return apply_filters(
346
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
347
-            $template_args
348
-        );
349
-    }
350
-
351
-
352
-    /**
353
-     * @param array           $country_options
354
-     * @param EE_Registration $registration
355
-     * @param EE_Question     $question
356
-     * @param EE_Answer|null  $answer
357
-     * @return mixed|void
358
-     * @since   $VID:$
359
-     */
360
-    public function generateQuestionInputCountryOptions(
361
-        array $country_options,
362
-        EE_Registration $registration,
363
-        EE_Question $question,
364
-        ?EE_Answer $answer
365
-    ) {
366
-        return apply_filters(
367
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
368
-            $country_options,
369
-            $this,
370
-            $registration,
371
-            $question,
372
-            $answer
373
-        );
374
-    }
375
-
376
-
377
-    /**
378
-     * @param array           $state_options
379
-     * @param EE_Registration $registration
380
-     * @param EE_Question     $question
381
-     * @param EE_Answer|null  $answer
382
-     * @return mixed|void
383
-     * @since   $VID:$
384
-     */
385
-    public function generateQuestionInputStateOptions(
386
-        array $state_options,
387
-        EE_Registration $registration,
388
-        EE_Question $question,
389
-        ?EE_Answer $answer
390
-    ) {
391
-        return apply_filters(
392
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
393
-            $state_options,
394
-            $this,
395
-            $registration,
396
-            $question,
397
-            $answer
398
-        );
399
-    }
400
-
401
-
402
-    /**
403
-     * looking for hooks?
404
-     * this method has been replaced by:
405
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::getRegForm()
406
-     *
407
-     * @deprecated   $VID:$
408
-     */
409
-    private function _registrations_reg_form()
410
-    {
411
-    }
412
-
413
-
414
-    /**
415
-     * looking for hooks?
416
-     * this method has been replaced by:
417
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalAttendeeRegInfoInput()
418
-     *
419
-     * @deprecated   $VID:$
420
-     */
421
-    private function _additional_attendee_reg_info_input()
422
-    {
423
-    }
424
-
425
-
426
-    /**
427
-     * looking for hooks?
428
-     * this method has been replaced by:
429
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupRegForm()
430
-     *
431
-     * @deprecated   $VID:$
432
-     */
433
-    private function _question_group_reg_form()
434
-    {
435
-    }
436
-
437
-
438
-    /**
439
-     * looking for hooks?
440
-     * this method has been replaced by:
441
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupHeader()
442
-     *
443
-     * @deprecated   $VID:$
444
-     */
445
-    private function _question_group_header()
446
-    {
447
-    }
448
-
449
-
450
-    /**
451
-     * looking for hooks?
452
-     * this method has been replaced by:
453
-     * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
454
-     *
455
-     * @deprecated   $VID:$
456
-     */
457
-    private function _copy_attendee_info_form()
458
-    {
459
-    }
460
-
461
-
462
-    /**
463
-     * looking for hooks?
464
-     * this method has been replaced by:
465
-     * EventEspresso\core\domain\services\registration\form\v1\AutoCopyAttendeeInfoForm
466
-     *
467
-     * @deprecated   $VID:$
468
-     */
469
-    private function _auto_copy_attendee_info()
470
-    {
471
-    }
472
-
473
-
474
-    /**
475
-     * looking for hooks?
476
-     * this method has been replaced by:
477
-     * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
478
-     *
479
-     * @deprecated   $VID:$
480
-     */
481
-    private function _copy_attendee_info_inputs()
482
-    {
483
-    }
484
-
485
-
486
-    /**
487
-     * looking for hooks?
488
-     * this method has been replaced by:
489
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalPrimaryRegistrantInputs()
490
-     *
491
-     * @deprecated   $VID:$
492
-     */
493
-    private function _additional_primary_registrant_inputs()
494
-    {
495
-    }
496
-
497
-
498
-    /**
499
-     * looking for hooks?
500
-     * this method has been replaced by:
501
-     * EventEspresso\core\domain\services\registration\form\v1\RegFormQuestionFactory::create()
502
-     *
503
-     * @param EE_Registration $registration
504
-     * @param EE_Question     $question
505
-     * @return EE_Form_Input_Base
506
-     * @throws EE_Error
507
-     * @throws ReflectionException
508
-     * @deprecated   $VID:$
509
-     */
510
-    public function reg_form_question(EE_Registration $registration, EE_Question $question): EE_Form_Input_Base
511
-    {
512
-        /** @var RegFormQuestionFactory $reg_form_question_factory */
513
-        $reg_form_question_factory = LoaderFactory::getShared(RegFormQuestionFactory::class);
514
-        return $reg_form_question_factory->create($registration, $question);
515
-    }
516
-
517
-
518
-    /**
519
-     * looking for hooks?
520
-     * this method has been replaced by:
521
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::generateQuestionInput()
522
-     *
523
-     * @deprecated   $VID:$
524
-     */
525
-    private function _generate_question_input()
526
-    {
527
-    }
528
-
529
-
530
-    /**
531
-     * looking for hooks?
532
-     * this method has been replaced by:
533
-     * EventEspresso\core\domain\services\registration\form\v1\CountryOptions::forLegacyFormInput()
534
-     *
535
-     * @param array|null           $countries_list
536
-     * @param EE_Question|null     $question
537
-     * @param EE_Registration|null $registration
538
-     * @param EE_Answer|null       $answer
539
-     * @return array 2d keys are country IDs, values are their names
540
-     * @throws EE_Error
541
-     * @throws ReflectionException
542
-     * @deprecated   $VID:$
543
-     */
544
-    public function use_cached_countries_for_form_input(
545
-        array $countries_list = null,
546
-        EE_Question $question = null,
547
-        EE_Registration $registration = null,
548
-        EE_Answer $answer = null
549
-    ): array {
550
-        /** @var CountryOptions $country_options */
551
-        $country_options = LoaderFactory::getShared(CountryOptions::class, [$this->checkout->action]);
552
-        return $country_options->forLegacyFormInput($countries_list, $question, $registration, $answer);
553
-    }
554
-
555
-
556
-    /**
557
-     * looking for hooks?
558
-     * this method has been replaced by:
559
-     * EventEspresso\core\domain\services\registration\form\v1\StateOptions::forLegacyFormInput()
560
-     *
561
-     * @param array|null           $states_list
562
-     * @param EE_Question|null     $question
563
-     * @param EE_Registration|null $registration
564
-     * @param EE_Answer|null       $answer
565
-     * @return array 2d keys are state IDs, values are their names
566
-     * @throws EE_Error
567
-     * @throws ReflectionException
568
-     * @deprecated   $VID:$
569
-     */
570
-    public function use_cached_states_for_form_input(
571
-        array $states_list = null,
572
-        EE_Question $question = null,
573
-        EE_Registration $registration = null,
574
-        EE_Answer $answer = null
575
-    ): array {
576
-        /** @var StateOptions $state_options */
577
-        $state_options = LoaderFactory::getShared(StateOptions::class, [$this->checkout->action]);
578
-        return $state_options->forLegacyFormInput($states_list, $question, $registration, $answer);
579
-    }
580
-
581
-
582
-    /********************************************************************************************************/
583
-    /****************************************  PROCESS REG STEP  ****************************************/
584
-    /********************************************************************************************************/
585
-
586
-
587
-    /**
588
-     * @return bool
589
-     * @throws EE_Error
590
-     * @throws InvalidArgumentException
591
-     * @throws ReflectionException
592
-     * @throws RuntimeException
593
-     * @throws InvalidDataTypeException
594
-     * @throws InvalidInterfaceException
595
-     */
596
-    public function process_reg_step(): bool
597
-    {
598
-        $this->setLegacyFiltersForRegFormProcessing();
599
-        // grab validated data from form
600
-        $valid_data = $this->checkout->current_step->valid_data();
601
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
602
-        if (empty($valid_data)) {
603
-            return $this->inValidDataError();
604
-        }
605
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
606
-            return $this->inValidTransactionError();
607
-        }
608
-        // get cached registrations
609
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
610
-        // verify we got the goods
611
-        if (empty($registrations)) {
612
-            return $this->noRegistrationsError();
613
-        }
614
-        /** @var RegFormHandler $reg_form_handler */
615
-        $reg_form_handler = LoaderFactory::getNew(RegFormHandler::class, [$this->checkout]);
616
-        // extract attendee info from form data and save to model objects
617
-        if (! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
618
-            // return immediately if the previous step exited early due to errors
619
-            return false;
620
-        }
621
-        // if first pass thru SPCO,
622
-        // then let's check processed registrations against the total number of tickets in the cart
623
-        $registrations_processed = $reg_form_handler->attendeeCount();
624
-        if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
625
-            return $this->registrationProcessingError($registrations_processed);
626
-        }
627
-        // mark this reg step as completed
628
-        $this->set_completed();
629
-        $this->_set_success_message(
630
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
631
-        );
632
-        // do action in case a plugin wants to do something with the data submitted in step 1.
633
-        // passes EE_Single_Page_Checkout, and it's posted data
634
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
635
-        return true;
636
-    }
637
-
638
-
639
-    /**
640
-     * @since   $VID:$
641
-     */
642
-    private function setLegacyFiltersForRegFormProcessing()
643
-    {
644
-        add_filter(
645
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegistrations__bypass',
646
-            [$this, 'preRegistrationProcess'],
647
-            1,
648
-            5
649
-        );
650
-        add_filter(
651
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegFormData__registrant_form_data',
652
-            [$this, 'validDataLineItem'],
653
-            1,
654
-            2
655
-        );
656
-        add_filter(
657
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormInputHandler__saveRegistrationFormInput',
658
-            [$this, 'saveRegistrationFormInput'],
659
-            1,
660
-            4
661
-        );
662
-        add_filter(
663
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantData__ensureCriticalRegistrantDataIsSet',
664
-            [$this, 'mergeAddressDetailsWithCriticalAttendeeDetails'],
665
-            1
666
-        );
667
-    }
668
-
669
-
670
-    /**
671
-     * @param bool            $bypass
672
-     * @param int             $attendee_count
673
-     * @param EE_Registration $registration
674
-     * @param array           $registrations
675
-     * @param array           $reg_form_data
676
-     * @return mixed|void
677
-     * @since   $VID:$
678
-     */
679
-    public function preRegistrationProcess(
680
-        bool $bypass,
681
-        int $attendee_count,
682
-        EE_Registration $registration,
683
-        array $registrations,
684
-        array $reg_form_data
685
-    ) {
686
-        return apply_filters(
687
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
688
-            $bypass,
689
-            $attendee_count,
690
-            $registration,
691
-            $registrations,
692
-            $reg_form_data,
693
-            $this
694
-        );
695
-    }
696
-
697
-
698
-    /**
699
-     * @param array           $reg_form_data
700
-     * @param EE_Registration $registration
701
-     * @return mixed|void
702
-     * @since   $VID:$
703
-     */
704
-    public function validDataLineItem(array $reg_form_data, EE_Registration $registration)
705
-    {
706
-        return apply_filters(
707
-            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
708
-            $reg_form_data,
709
-            $registration
710
-        );
711
-    }
712
-
713
-
714
-    /**
715
-     * @param bool            $save
716
-     * @param EE_Registration $registration
717
-     * @param                 $form_input
718
-     * @param                 $input_value
719
-     * @return mixed|void
720
-     * @since   $VID:$
721
-     */
722
-    public function saveRegistrationFormInput(bool $save, EE_Registration $registration, $form_input, $input_value)
723
-    {
724
-        return apply_filters(
725
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
726
-            $save,
727
-            $registration,
728
-            $form_input,
729
-            $input_value,
730
-            $this
731
-        );
732
-    }
733
-
734
-
735
-    /**
736
-     * @param bool $merge_data
737
-     * @return mixed|void
738
-     * @since   $VID:$
739
-     */
740
-    public function mergeAddressDetailsWithCriticalAttendeeDetails(bool $merge_data)
741
-    {
742
-        return apply_filters(
743
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
744
-            $merge_data
745
-        );
746
-    }
747
-
748
-
749
-    /**
750
-     * @return bool
751
-     * @since   $VID:$
752
-     */
753
-    private function inValidDataError(): bool
754
-    {
755
-        EE_Error::add_error(
756
-            esc_html__('No valid question responses were received.', 'event_espresso'),
757
-            __FILE__,
758
-            __FUNCTION__,
759
-            __LINE__
760
-        );
761
-        return false;
762
-    }
763
-
764
-
765
-    /**
766
-     * @return bool
767
-     * @since   $VID:$
768
-     */
769
-    private function inValidTransactionError(): bool
770
-    {
771
-        EE_Error::add_error(
772
-            esc_html__(
773
-                'A valid transaction could not be initiated for processing your registrations.',
774
-                'event_espresso'
775
-            ),
776
-            __FILE__,
777
-            __FUNCTION__,
778
-            __LINE__
779
-        );
780
-        return false;
781
-    }
782
-
783
-
784
-    /**
785
-     * @return bool
786
-     * @since   $VID:$
787
-     */
788
-    private function noRegistrationsError(): bool
789
-    {
790
-        // combine the old translated string with a new one, in order to not break translations
791
-        $error_message = esc_html__(
792
-            'Your form data could not be applied to any valid registrations.',
793
-            'event_espresso'
794
-        );
795
-        $error_message .= sprintf(
796
-            esc_html_x(
797
-                '%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
798
-                '(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
799
-                'event_espresso'
800
-            ),
801
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
802
-            '</a>',
803
-            '<br />'
804
-        );
805
-        EE_Error::add_error($error_message, __FILE__, __FUNCTION__, __LINE__);
806
-        return false;
807
-    }
808
-
809
-
810
-    /**
811
-     * @param int $registrations_processed
812
-     * @return bool
813
-     * @since   $VID:$
814
-     */
815
-    private function registrationProcessingError(int $registrations_processed): bool
816
-    {
817
-        // generate a correctly translated string for all possible singular/plural combinations
818
-        if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
819
-            $error_msg = sprintf(
820
-                esc_html_x(
821
-                    'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
822
-                    'There was 1 ticket in the Event Queue, but 2 registrations were processed',
823
-                    'event_espresso'
824
-                ),
825
-                $this->checkout->total_ticket_count,
826
-                $registrations_processed
827
-            );
828
-        } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
829
-            $error_msg = sprintf(
830
-                esc_html_x(
831
-                    'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
832
-                    'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
833
-                    'event_espresso'
834
-                ),
835
-                $this->checkout->total_ticket_count,
836
-                $registrations_processed
837
-            );
838
-        } else {
839
-            $error_msg = sprintf(
840
-                esc_html__(
841
-                    'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
842
-                    'event_espresso'
843
-                ),
844
-                $this->checkout->total_ticket_count,
845
-                $registrations_processed
846
-            );
847
-        }
848
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
-        return false;
850
-    }
851
-
852
-
853
-    /**
854
-     *    update_reg_step
855
-     *    this is the final step after a user  revisits the site to edit their attendee information
856
-     *    this gets called AFTER the process_reg_step() method above
857
-     *
858
-     * @return bool
859
-     * @throws EE_Error
860
-     * @throws InvalidArgumentException
861
-     * @throws ReflectionException
862
-     * @throws RuntimeException
863
-     * @throws InvalidDataTypeException
864
-     * @throws InvalidInterfaceException
865
-     */
866
-    public function update_reg_step(): bool
867
-    {
868
-        // save everything
869
-        if ($this->process_reg_step()) {
870
-            $this->checkout->redirect     = true;
871
-            $this->checkout->redirect_url = add_query_arg(
872
-                [
873
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
874
-                    'revisit'        => true,
875
-                ],
876
-                $this->checkout->thank_you_page_url
877
-            );
878
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
879
-            return true;
880
-        }
881
-        return false;
882
-    }
25
+	/**
26
+	 * @var RegForm
27
+	 */
28
+	public $reg_form;
29
+
30
+	/**
31
+	 * @var int
32
+	 */
33
+	protected $reg_form_count = 0;
34
+
35
+
36
+	/**
37
+	 *    class constructor
38
+	 *
39
+	 * @access    public
40
+	 * @param EE_Checkout $checkout
41
+	 */
42
+	public function __construct(EE_Checkout $checkout)
43
+	{
44
+		$this->_slug    = 'attendee_information';
45
+		$this->_name    = esc_html__('Attendee Information', 'event_espresso');
46
+		$this->checkout = $checkout;
47
+		$this->_reset_success_message();
48
+		$this->set_instructions(
49
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
50
+		);
51
+	}
52
+
53
+
54
+	public function translate_js_strings()
55
+	{
56
+		EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
57
+			' is a required question.',
58
+			'event_espresso'
59
+		);
60
+		EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
61
+			' is a required question. Please enter a value for at least one of the options.',
62
+			'event_espresso'
63
+		);
64
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
65
+			'Please answer all required questions correctly before proceeding.',
66
+			'event_espresso'
67
+		);
68
+		EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
69
+			esc_html_x(
70
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
71
+				'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
72
+				'event_espresso'
73
+			),
74
+			'<br/>'
75
+		);
76
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
77
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
78
+			'event_espresso'
79
+		);
80
+		EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
81
+			'You must enter a valid email address.',
82
+			'event_espresso'
83
+		);
84
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
85
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
86
+			'event_espresso'
87
+		);
88
+	}
89
+
90
+
91
+	public function enqueue_styles_and_scripts()
92
+	{
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return boolean
98
+	 */
99
+	public function initialize_reg_step(): bool
100
+	{
101
+		return true;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return RegForm
107
+	 * @throws DomainException
108
+	 * @throws InvalidArgumentException
109
+	 * @throws EntityNotFoundException
110
+	 * @throws InvalidDataTypeException
111
+	 * @throws InvalidInterfaceException
112
+	 */
113
+	public function generate_reg_form(): RegForm
114
+	{
115
+		$this->setLegacyFiltersForRegFormGeneration();
116
+		/** @var RegFormDependencyHandler $dependency_handler */
117
+		$dependency_handler = LoaderFactory::getShared(RegFormDependencyHandler::class);
118
+		$dependency_handler->registerDependencies();
119
+		// TODO detect if event has a reg form UUID and swap this out for form generated by new reg form builder
120
+		return LoaderFactory::getShared(RegForm::class, [$this]);
121
+	}
122
+
123
+
124
+	/**
125
+	 * @since   $VID:$
126
+	 */
127
+	private function setLegacyFiltersForRegFormGeneration()
128
+	{
129
+		add_filter(
130
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_groups_query_parameters',
131
+			[$this, 'registrationQuestionGroupsQueryParameters'],
132
+			1,
133
+			2
134
+		);
135
+		add_filter(
136
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_group_reg_form',
137
+			[$this, 'registrationQuestionGroupsRegForm'],
138
+			1,
139
+			3
140
+		);
141
+		add_filter(
142
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__printCopyInfo',
143
+			[$this, 'registrationRegFormPrintCopyInfo'],
144
+			1,
145
+			2
146
+		);
147
+		add_filter(
148
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__related_questions_query_params',
149
+			[$this, 'registrationRegFormRelatedQuestionsQueryParams'],
150
+			1,
151
+			3
152
+		);
153
+		add_filter(
154
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__before_question_group_questions',
155
+			[$this, 'registrationRegFormBeforeQuestionGroupQuestions'],
156
+			1,
157
+			3
158
+		);
159
+		add_filter(
160
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__subsections_array',
161
+			[$this, 'registrationRegFormSubsections'],
162
+			1,
163
+			3
164
+		);
165
+		add_filter(
166
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__after_question_group_questions',
167
+			[$this, 'registrationRegFormAfterQuestionGroupQuestions'],
168
+			1,
169
+			3
170
+		);
171
+		add_filter(
172
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_AutoCopyAttendeeInfoForm__construct__template_args',
173
+			[$this, 'autoCopyAttendeeInfoTemplateArgs'],
174
+			1
175
+		);
176
+		add_filter(
177
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_CountryOptions__generateLegacyCountryOptions__country_options',
178
+			[$this, 'generateQuestionInputCountryOptions'],
179
+			1,
180
+			4
181
+		);
182
+		add_filter(
183
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_StateOptions__generateLegacyStateOptions__state_options',
184
+			[$this, 'generateQuestionInputStateOptions'],
185
+			1,
186
+			4
187
+		);
188
+	}
189
+
190
+
191
+	/**
192
+	 * @param array           $query_params
193
+	 * @param EE_Registration $registration
194
+	 * @return mixed|void
195
+	 * @since   $VID:$
196
+	 */
197
+	public function registrationQuestionGroupsQueryParameters(
198
+		array $query_params,
199
+		EE_Registration $registration
200
+	) {
201
+		return apply_filters(
202
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
203
+			$query_params,
204
+			$registration,
205
+			$this
206
+		);
207
+	}
208
+
209
+
210
+	/**
211
+	 * @param RegFormQuestionGroup $question_group_reg_form
212
+	 * @param EE_Registration      $registration
213
+	 * @param EE_Question_Group    $question_group
214
+	 * @return mixed|void
215
+	 * @since   $VID:$
216
+	 */
217
+	public function registrationQuestionGroupsRegForm(
218
+		RegFormQuestionGroup $question_group_reg_form,
219
+		EE_Registration $registration,
220
+		EE_Question_Group $question_group
221
+	) {
222
+		return apply_filters(
223
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
224
+			$question_group_reg_form,
225
+			$registration,
226
+			$question_group,
227
+			$this
228
+		);
229
+	}
230
+
231
+
232
+	/**
233
+	 * @param int $print_copy_info
234
+	 * @param int $attendee_nmbr
235
+	 * @return mixed|void
236
+	 * @since   $VID:$
237
+	 */
238
+	public function registrationRegFormPrintCopyInfo(
239
+		int $print_copy_info,
240
+		int $attendee_nmbr
241
+	) {
242
+		return apply_filters(
243
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form___printCopyInfo',
244
+			$print_copy_info,
245
+			$attendee_nmbr
246
+		);
247
+	}
248
+
249
+
250
+	/**
251
+	 * @param array             $query_params
252
+	 * @param EE_Question_Group $question_group
253
+	 * @param EE_Registration   $registration
254
+	 * @return mixed|void
255
+	 * @since   $VID:$
256
+	 */
257
+	public function registrationRegFormRelatedQuestionsQueryParams(
258
+		array $query_params,
259
+		EE_Question_Group $question_group,
260
+		EE_Registration $registration
261
+	) {
262
+		return apply_filters(
263
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
264
+			$query_params,
265
+			$question_group,
266
+			$registration,
267
+			$this
268
+		);
269
+	}
270
+
271
+
272
+	/**
273
+	 * @param                   $html
274
+	 * @param EE_Registration   $registration
275
+	 * @param EE_Question_Group $question_group
276
+	 * @return mixed|void
277
+	 * @since   $VID:$
278
+	 */
279
+	public function registrationRegFormBeforeQuestionGroupQuestions(
280
+		$html,
281
+		EE_Registration $registration,
282
+		EE_Question_Group $question_group
283
+	) {
284
+		return apply_filters(
285
+			'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
286
+			$html,
287
+			$registration,
288
+			$question_group,
289
+			$this
290
+		);
291
+	}
292
+
293
+
294
+	/**
295
+	 * @param array             $form_subsections
296
+	 * @param EE_Registration   $registration
297
+	 * @param EE_Question_Group $question_group
298
+	 * @return mixed|void
299
+	 * @since   $VID:$
300
+	 */
301
+	public function registrationRegFormSubsections(
302
+		array $form_subsections,
303
+		EE_Registration $registration,
304
+		EE_Question_Group $question_group
305
+	) {
306
+		return apply_filters(
307
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
308
+			$form_subsections,
309
+			$registration,
310
+			$question_group,
311
+			$this
312
+		);
313
+	}
314
+
315
+
316
+	/**
317
+	 * @param                   $html
318
+	 * @param EE_Registration   $registration
319
+	 * @param EE_Question_Group $question_group
320
+	 * @return mixed|void
321
+	 * @since   $VID:$
322
+	 */
323
+	public function registrationRegFormAfterQuestionGroupQuestions(
324
+		$html,
325
+		EE_Registration $registration,
326
+		EE_Question_Group $question_group
327
+	) {
328
+		return apply_filters(
329
+			'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
330
+			$html,
331
+			$registration,
332
+			$question_group,
333
+			$this
334
+		);
335
+	}
336
+
337
+
338
+	/**
339
+	 * @param array $template_args
340
+	 * @return mixed|void
341
+	 * @since   $VID:$
342
+	 */
343
+	public function autoCopyAttendeeInfoTemplateArgs(array $template_args = [])
344
+	{
345
+		return apply_filters(
346
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
347
+			$template_args
348
+		);
349
+	}
350
+
351
+
352
+	/**
353
+	 * @param array           $country_options
354
+	 * @param EE_Registration $registration
355
+	 * @param EE_Question     $question
356
+	 * @param EE_Answer|null  $answer
357
+	 * @return mixed|void
358
+	 * @since   $VID:$
359
+	 */
360
+	public function generateQuestionInputCountryOptions(
361
+		array $country_options,
362
+		EE_Registration $registration,
363
+		EE_Question $question,
364
+		?EE_Answer $answer
365
+	) {
366
+		return apply_filters(
367
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
368
+			$country_options,
369
+			$this,
370
+			$registration,
371
+			$question,
372
+			$answer
373
+		);
374
+	}
375
+
376
+
377
+	/**
378
+	 * @param array           $state_options
379
+	 * @param EE_Registration $registration
380
+	 * @param EE_Question     $question
381
+	 * @param EE_Answer|null  $answer
382
+	 * @return mixed|void
383
+	 * @since   $VID:$
384
+	 */
385
+	public function generateQuestionInputStateOptions(
386
+		array $state_options,
387
+		EE_Registration $registration,
388
+		EE_Question $question,
389
+		?EE_Answer $answer
390
+	) {
391
+		return apply_filters(
392
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
393
+			$state_options,
394
+			$this,
395
+			$registration,
396
+			$question,
397
+			$answer
398
+		);
399
+	}
400
+
401
+
402
+	/**
403
+	 * looking for hooks?
404
+	 * this method has been replaced by:
405
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::getRegForm()
406
+	 *
407
+	 * @deprecated   $VID:$
408
+	 */
409
+	private function _registrations_reg_form()
410
+	{
411
+	}
412
+
413
+
414
+	/**
415
+	 * looking for hooks?
416
+	 * this method has been replaced by:
417
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalAttendeeRegInfoInput()
418
+	 *
419
+	 * @deprecated   $VID:$
420
+	 */
421
+	private function _additional_attendee_reg_info_input()
422
+	{
423
+	}
424
+
425
+
426
+	/**
427
+	 * looking for hooks?
428
+	 * this method has been replaced by:
429
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupRegForm()
430
+	 *
431
+	 * @deprecated   $VID:$
432
+	 */
433
+	private function _question_group_reg_form()
434
+	{
435
+	}
436
+
437
+
438
+	/**
439
+	 * looking for hooks?
440
+	 * this method has been replaced by:
441
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupHeader()
442
+	 *
443
+	 * @deprecated   $VID:$
444
+	 */
445
+	private function _question_group_header()
446
+	{
447
+	}
448
+
449
+
450
+	/**
451
+	 * looking for hooks?
452
+	 * this method has been replaced by:
453
+	 * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
454
+	 *
455
+	 * @deprecated   $VID:$
456
+	 */
457
+	private function _copy_attendee_info_form()
458
+	{
459
+	}
460
+
461
+
462
+	/**
463
+	 * looking for hooks?
464
+	 * this method has been replaced by:
465
+	 * EventEspresso\core\domain\services\registration\form\v1\AutoCopyAttendeeInfoForm
466
+	 *
467
+	 * @deprecated   $VID:$
468
+	 */
469
+	private function _auto_copy_attendee_info()
470
+	{
471
+	}
472
+
473
+
474
+	/**
475
+	 * looking for hooks?
476
+	 * this method has been replaced by:
477
+	 * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
478
+	 *
479
+	 * @deprecated   $VID:$
480
+	 */
481
+	private function _copy_attendee_info_inputs()
482
+	{
483
+	}
484
+
485
+
486
+	/**
487
+	 * looking for hooks?
488
+	 * this method has been replaced by:
489
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalPrimaryRegistrantInputs()
490
+	 *
491
+	 * @deprecated   $VID:$
492
+	 */
493
+	private function _additional_primary_registrant_inputs()
494
+	{
495
+	}
496
+
497
+
498
+	/**
499
+	 * looking for hooks?
500
+	 * this method has been replaced by:
501
+	 * EventEspresso\core\domain\services\registration\form\v1\RegFormQuestionFactory::create()
502
+	 *
503
+	 * @param EE_Registration $registration
504
+	 * @param EE_Question     $question
505
+	 * @return EE_Form_Input_Base
506
+	 * @throws EE_Error
507
+	 * @throws ReflectionException
508
+	 * @deprecated   $VID:$
509
+	 */
510
+	public function reg_form_question(EE_Registration $registration, EE_Question $question): EE_Form_Input_Base
511
+	{
512
+		/** @var RegFormQuestionFactory $reg_form_question_factory */
513
+		$reg_form_question_factory = LoaderFactory::getShared(RegFormQuestionFactory::class);
514
+		return $reg_form_question_factory->create($registration, $question);
515
+	}
516
+
517
+
518
+	/**
519
+	 * looking for hooks?
520
+	 * this method has been replaced by:
521
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::generateQuestionInput()
522
+	 *
523
+	 * @deprecated   $VID:$
524
+	 */
525
+	private function _generate_question_input()
526
+	{
527
+	}
528
+
529
+
530
+	/**
531
+	 * looking for hooks?
532
+	 * this method has been replaced by:
533
+	 * EventEspresso\core\domain\services\registration\form\v1\CountryOptions::forLegacyFormInput()
534
+	 *
535
+	 * @param array|null           $countries_list
536
+	 * @param EE_Question|null     $question
537
+	 * @param EE_Registration|null $registration
538
+	 * @param EE_Answer|null       $answer
539
+	 * @return array 2d keys are country IDs, values are their names
540
+	 * @throws EE_Error
541
+	 * @throws ReflectionException
542
+	 * @deprecated   $VID:$
543
+	 */
544
+	public function use_cached_countries_for_form_input(
545
+		array $countries_list = null,
546
+		EE_Question $question = null,
547
+		EE_Registration $registration = null,
548
+		EE_Answer $answer = null
549
+	): array {
550
+		/** @var CountryOptions $country_options */
551
+		$country_options = LoaderFactory::getShared(CountryOptions::class, [$this->checkout->action]);
552
+		return $country_options->forLegacyFormInput($countries_list, $question, $registration, $answer);
553
+	}
554
+
555
+
556
+	/**
557
+	 * looking for hooks?
558
+	 * this method has been replaced by:
559
+	 * EventEspresso\core\domain\services\registration\form\v1\StateOptions::forLegacyFormInput()
560
+	 *
561
+	 * @param array|null           $states_list
562
+	 * @param EE_Question|null     $question
563
+	 * @param EE_Registration|null $registration
564
+	 * @param EE_Answer|null       $answer
565
+	 * @return array 2d keys are state IDs, values are their names
566
+	 * @throws EE_Error
567
+	 * @throws ReflectionException
568
+	 * @deprecated   $VID:$
569
+	 */
570
+	public function use_cached_states_for_form_input(
571
+		array $states_list = null,
572
+		EE_Question $question = null,
573
+		EE_Registration $registration = null,
574
+		EE_Answer $answer = null
575
+	): array {
576
+		/** @var StateOptions $state_options */
577
+		$state_options = LoaderFactory::getShared(StateOptions::class, [$this->checkout->action]);
578
+		return $state_options->forLegacyFormInput($states_list, $question, $registration, $answer);
579
+	}
580
+
581
+
582
+	/********************************************************************************************************/
583
+	/****************************************  PROCESS REG STEP  ****************************************/
584
+	/********************************************************************************************************/
585
+
586
+
587
+	/**
588
+	 * @return bool
589
+	 * @throws EE_Error
590
+	 * @throws InvalidArgumentException
591
+	 * @throws ReflectionException
592
+	 * @throws RuntimeException
593
+	 * @throws InvalidDataTypeException
594
+	 * @throws InvalidInterfaceException
595
+	 */
596
+	public function process_reg_step(): bool
597
+	{
598
+		$this->setLegacyFiltersForRegFormProcessing();
599
+		// grab validated data from form
600
+		$valid_data = $this->checkout->current_step->valid_data();
601
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
602
+		if (empty($valid_data)) {
603
+			return $this->inValidDataError();
604
+		}
605
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
606
+			return $this->inValidTransactionError();
607
+		}
608
+		// get cached registrations
609
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
610
+		// verify we got the goods
611
+		if (empty($registrations)) {
612
+			return $this->noRegistrationsError();
613
+		}
614
+		/** @var RegFormHandler $reg_form_handler */
615
+		$reg_form_handler = LoaderFactory::getNew(RegFormHandler::class, [$this->checkout]);
616
+		// extract attendee info from form data and save to model objects
617
+		if (! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
618
+			// return immediately if the previous step exited early due to errors
619
+			return false;
620
+		}
621
+		// if first pass thru SPCO,
622
+		// then let's check processed registrations against the total number of tickets in the cart
623
+		$registrations_processed = $reg_form_handler->attendeeCount();
624
+		if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
625
+			return $this->registrationProcessingError($registrations_processed);
626
+		}
627
+		// mark this reg step as completed
628
+		$this->set_completed();
629
+		$this->_set_success_message(
630
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
631
+		);
632
+		// do action in case a plugin wants to do something with the data submitted in step 1.
633
+		// passes EE_Single_Page_Checkout, and it's posted data
634
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
635
+		return true;
636
+	}
637
+
638
+
639
+	/**
640
+	 * @since   $VID:$
641
+	 */
642
+	private function setLegacyFiltersForRegFormProcessing()
643
+	{
644
+		add_filter(
645
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegistrations__bypass',
646
+			[$this, 'preRegistrationProcess'],
647
+			1,
648
+			5
649
+		);
650
+		add_filter(
651
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegFormData__registrant_form_data',
652
+			[$this, 'validDataLineItem'],
653
+			1,
654
+			2
655
+		);
656
+		add_filter(
657
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormInputHandler__saveRegistrationFormInput',
658
+			[$this, 'saveRegistrationFormInput'],
659
+			1,
660
+			4
661
+		);
662
+		add_filter(
663
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantData__ensureCriticalRegistrantDataIsSet',
664
+			[$this, 'mergeAddressDetailsWithCriticalAttendeeDetails'],
665
+			1
666
+		);
667
+	}
668
+
669
+
670
+	/**
671
+	 * @param bool            $bypass
672
+	 * @param int             $attendee_count
673
+	 * @param EE_Registration $registration
674
+	 * @param array           $registrations
675
+	 * @param array           $reg_form_data
676
+	 * @return mixed|void
677
+	 * @since   $VID:$
678
+	 */
679
+	public function preRegistrationProcess(
680
+		bool $bypass,
681
+		int $attendee_count,
682
+		EE_Registration $registration,
683
+		array $registrations,
684
+		array $reg_form_data
685
+	) {
686
+		return apply_filters(
687
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
688
+			$bypass,
689
+			$attendee_count,
690
+			$registration,
691
+			$registrations,
692
+			$reg_form_data,
693
+			$this
694
+		);
695
+	}
696
+
697
+
698
+	/**
699
+	 * @param array           $reg_form_data
700
+	 * @param EE_Registration $registration
701
+	 * @return mixed|void
702
+	 * @since   $VID:$
703
+	 */
704
+	public function validDataLineItem(array $reg_form_data, EE_Registration $registration)
705
+	{
706
+		return apply_filters(
707
+			'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
708
+			$reg_form_data,
709
+			$registration
710
+		);
711
+	}
712
+
713
+
714
+	/**
715
+	 * @param bool            $save
716
+	 * @param EE_Registration $registration
717
+	 * @param                 $form_input
718
+	 * @param                 $input_value
719
+	 * @return mixed|void
720
+	 * @since   $VID:$
721
+	 */
722
+	public function saveRegistrationFormInput(bool $save, EE_Registration $registration, $form_input, $input_value)
723
+	{
724
+		return apply_filters(
725
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
726
+			$save,
727
+			$registration,
728
+			$form_input,
729
+			$input_value,
730
+			$this
731
+		);
732
+	}
733
+
734
+
735
+	/**
736
+	 * @param bool $merge_data
737
+	 * @return mixed|void
738
+	 * @since   $VID:$
739
+	 */
740
+	public function mergeAddressDetailsWithCriticalAttendeeDetails(bool $merge_data)
741
+	{
742
+		return apply_filters(
743
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
744
+			$merge_data
745
+		);
746
+	}
747
+
748
+
749
+	/**
750
+	 * @return bool
751
+	 * @since   $VID:$
752
+	 */
753
+	private function inValidDataError(): bool
754
+	{
755
+		EE_Error::add_error(
756
+			esc_html__('No valid question responses were received.', 'event_espresso'),
757
+			__FILE__,
758
+			__FUNCTION__,
759
+			__LINE__
760
+		);
761
+		return false;
762
+	}
763
+
764
+
765
+	/**
766
+	 * @return bool
767
+	 * @since   $VID:$
768
+	 */
769
+	private function inValidTransactionError(): bool
770
+	{
771
+		EE_Error::add_error(
772
+			esc_html__(
773
+				'A valid transaction could not be initiated for processing your registrations.',
774
+				'event_espresso'
775
+			),
776
+			__FILE__,
777
+			__FUNCTION__,
778
+			__LINE__
779
+		);
780
+		return false;
781
+	}
782
+
783
+
784
+	/**
785
+	 * @return bool
786
+	 * @since   $VID:$
787
+	 */
788
+	private function noRegistrationsError(): bool
789
+	{
790
+		// combine the old translated string with a new one, in order to not break translations
791
+		$error_message = esc_html__(
792
+			'Your form data could not be applied to any valid registrations.',
793
+			'event_espresso'
794
+		);
795
+		$error_message .= sprintf(
796
+			esc_html_x(
797
+				'%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
798
+				'(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
799
+				'event_espresso'
800
+			),
801
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" >',
802
+			'</a>',
803
+			'<br />'
804
+		);
805
+		EE_Error::add_error($error_message, __FILE__, __FUNCTION__, __LINE__);
806
+		return false;
807
+	}
808
+
809
+
810
+	/**
811
+	 * @param int $registrations_processed
812
+	 * @return bool
813
+	 * @since   $VID:$
814
+	 */
815
+	private function registrationProcessingError(int $registrations_processed): bool
816
+	{
817
+		// generate a correctly translated string for all possible singular/plural combinations
818
+		if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
819
+			$error_msg = sprintf(
820
+				esc_html_x(
821
+					'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
822
+					'There was 1 ticket in the Event Queue, but 2 registrations were processed',
823
+					'event_espresso'
824
+				),
825
+				$this->checkout->total_ticket_count,
826
+				$registrations_processed
827
+			);
828
+		} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
829
+			$error_msg = sprintf(
830
+				esc_html_x(
831
+					'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
832
+					'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
833
+					'event_espresso'
834
+				),
835
+				$this->checkout->total_ticket_count,
836
+				$registrations_processed
837
+			);
838
+		} else {
839
+			$error_msg = sprintf(
840
+				esc_html__(
841
+					'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
842
+					'event_espresso'
843
+				),
844
+				$this->checkout->total_ticket_count,
845
+				$registrations_processed
846
+			);
847
+		}
848
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
+		return false;
850
+	}
851
+
852
+
853
+	/**
854
+	 *    update_reg_step
855
+	 *    this is the final step after a user  revisits the site to edit their attendee information
856
+	 *    this gets called AFTER the process_reg_step() method above
857
+	 *
858
+	 * @return bool
859
+	 * @throws EE_Error
860
+	 * @throws InvalidArgumentException
861
+	 * @throws ReflectionException
862
+	 * @throws RuntimeException
863
+	 * @throws InvalidDataTypeException
864
+	 * @throws InvalidInterfaceException
865
+	 */
866
+	public function update_reg_step(): bool
867
+	{
868
+		// save everything
869
+		if ($this->process_reg_step()) {
870
+			$this->checkout->redirect     = true;
871
+			$this->checkout->redirect_url = add_query_arg(
872
+				[
873
+					'e_reg_url_link' => $this->checkout->reg_url_link,
874
+					'revisit'        => true,
875
+				],
876
+				$this->checkout->thank_you_page_url
877
+			);
878
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
879
+			return true;
880
+		}
881
+		return false;
882
+	}
883 883
 }
Please login to merge, or discard this patch.
modules/core_rest_api/EED_Core_Rest_Api.module.php 1 patch
Indentation   +1378 added lines, -1378 removed lines patch added patch discarded remove patch
@@ -21,1382 +21,1382 @@
 block discarded – undo
21 21
  */
22 22
 class EED_Core_Rest_Api extends EED_Module
23 23
 {
24
-    const ee_api_namespace = Domain::API_NAMESPACE;
25
-
26
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
27
-
28
-    const saved_routes_option_names = 'ee_core_routes';
29
-
30
-    /**
31
-     * string used in _links response bodies to make them globally unique.
32
-     *
33
-     * @see http://v2.wp-api.org/extending/linking/
34
-     */
35
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
36
-
37
-    /**
38
-     * @var CalculatedModelFields
39
-     */
40
-    protected static $_field_calculator;
41
-
42
-
43
-    /**
44
-     * @return EED_Core_Rest_Api|EED_Module
45
-     */
46
-    public static function instance()
47
-    {
48
-        return parent::get_instance(EED_Core_Rest_Api::class);
49
-    }
50
-
51
-
52
-    /**
53
-     *    set_hooks - for hooking into EE Core, other modules, etc
54
-     *
55
-     * @access    public
56
-     * @return    void
57
-     */
58
-    public static function set_hooks()
59
-    {
60
-    }
61
-
62
-
63
-    /**
64
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
-     *
66
-     * @access    public
67
-     * @return    void
68
-     */
69
-    public static function set_hooks_admin()
70
-    {
71
-    }
72
-
73
-
74
-    public static function set_hooks_both()
75
-    {
76
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
77
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
78
-        add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
79
-        add_filter(
80
-            'rest_index',
81
-            ['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
82
-        );
83
-    }
84
-
85
-
86
-    /**
87
-     * @since   $VID:$
88
-     */
89
-    public static function loadCalculatedModelFields()
90
-    {
91
-        EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
-        );
94
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
95
-    }
96
-
97
-
98
-    /**
99
-     * sets up hooks which only need to be included as part of REST API requests;
100
-     * other requests like to the frontend or admin etc don't need them
101
-     *
102
-     * @throws EE_Error
103
-     */
104
-    public static function set_hooks_rest_api()
105
-    {
106
-        // set hooks which account for changes made to the API
107
-        EED_Core_Rest_Api::_set_hooks_for_changes();
108
-    }
109
-
110
-
111
-    /**
112
-     * public wrapper of _set_hooks_for_changes.
113
-     * Loads all the hooks which make requests to old versions of the API
114
-     * appear the same as they always did
115
-     *
116
-     * @throws EE_Error
117
-     */
118
-    public static function set_hooks_for_changes()
119
-    {
120
-        EED_Core_Rest_Api::_set_hooks_for_changes();
121
-    }
122
-
123
-
124
-    /**
125
-     * Loads all the hooks which make requests to old versions of the API
126
-     * appear the same as they always did
127
-     *
128
-     * @throws EE_Error
129
-     */
130
-    protected static function _set_hooks_for_changes()
131
-    {
132
-        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
-            // ignore the base parent class
135
-            // and legacy named classes
136
-            if (
137
-                $classname_in_namespace === 'ChangesInBase'
138
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
139
-            ) {
140
-                continue;
141
-            }
142
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
-            if (class_exists($full_classname)) {
144
-                $instance_of_class = new $full_classname();
145
-                if ($instance_of_class instanceof ChangesInBase) {
146
-                    $instance_of_class->setHooks();
147
-                }
148
-            }
149
-        }
150
-    }
151
-
152
-
153
-    /**
154
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
155
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
156
-     *
157
-     * @throws EE_Error
158
-     * @throws ReflectionException
159
-     */
160
-    public static function register_routes()
161
-    {
162
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
163
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
164
-                /**
165
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
166
-                 *                                         but can also contain route options like {
167
-                 * @type array    $schema                      {
168
-                 * @type callable $schema_callback
169
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
170
-                 * WP_REST_Request of course
171
-                 * }
172
-                 * }
173
-                 */
174
-                // when registering routes, register all the endpoints' data at the same time
175
-                $multiple_endpoint_args = [];
176
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
177
-                    /**
178
-                     * @var array     $data_for_single_endpoint {
179
-                     * @type callable $callback
180
-                     * @type string methods
181
-                     * @type array args
182
-                     * @type array _links
183
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
184
-                     * WP_REST_Request of course
185
-                     * }
186
-                     */
187
-                    // skip route options
188
-                    if (! is_numeric($endpoint_key)) {
189
-                        continue;
190
-                    }
191
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
-                        throw new EE_Error(
193
-                            esc_html__(
194
-                            // @codingStandardsIgnoreStart
195
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
196
-                                // @codingStandardsIgnoreEnd
197
-                                'event_espresso'
198
-                            )
199
-                        );
200
-                    }
201
-                    $callback = $data_for_single_endpoint['callback'];
202
-                    $single_endpoint_args = [
203
-                        'methods' => $data_for_single_endpoint['methods'],
204
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
-                            : [],
206
-                    ];
207
-                    if (isset($data_for_single_endpoint['_links'])) {
208
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
-                    }
210
-                    if (isset($data_for_single_endpoint['callback_args'])) {
211
-                        $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
213
-                            $callback,
214
-                            $callback_args
215
-                        ) {
216
-                            array_unshift($callback_args, $request);
217
-                            return call_user_func_array(
218
-                                $callback,
219
-                                $callback_args
220
-                            );
221
-                        };
222
-                    } else {
223
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
-                    }
225
-                    // As of WordPress 5.5, if a permission_callback is not provided,
226
-                    // the REST API will issue a _doing_it_wrong notice.
227
-                    // Since the EE REST API defers capabilities to the db model system,
228
-                    // we will just use the generic WP callback for public endpoints
229
-                    if (! isset($single_endpoint_args['permission_callback'])) {
230
-                        $single_endpoint_args['permission_callback'] = '__return_true';
231
-                    }
232
-                    $multiple_endpoint_args[] = $single_endpoint_args;
233
-                }
234
-                if (isset($data_for_multiple_endpoints['schema'])) {
235
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
236
-                    $schema_callback = $schema_route_data['schema_callback'];
237
-                    $callback_args = $schema_route_data['callback_args'];
238
-                    $multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
239
-                        return call_user_func_array(
240
-                            $schema_callback,
241
-                            $callback_args
242
-                        );
243
-                    };
244
-                }
245
-                register_rest_route(
246
-                    $namespace,
247
-                    $relative_route,
248
-                    $multiple_endpoint_args
249
-                );
250
-            }
251
-        }
252
-    }
253
-
254
-
255
-    /**
256
-     * Checks if there was a version change or something that merits invalidating the cached
257
-     * route data. If so, invalidates the cached route data so that it gets refreshed
258
-     * next time the WP API is used
259
-     */
260
-    public static function invalidate_cached_route_data_on_version_change()
261
-    {
262
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
263
-            EED_Core_Rest_Api::invalidate_cached_route_data();
264
-        }
265
-        foreach (EE_Registry::instance()->addons as $addon) {
266
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
267
-                EED_Core_Rest_Api::invalidate_cached_route_data();
268
-            }
269
-        }
270
-    }
271
-
272
-
273
-    /**
274
-     * Removes the cached route data so it will get refreshed next time the WP API is used
275
-     */
276
-    public static function invalidate_cached_route_data()
277
-    {
278
-        // delete the saved EE REST API routes
279
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
280
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
281
-        }
282
-    }
283
-
284
-
285
-    /**
286
-     * Gets the EE route data
287
-     *
288
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
289
-     * @throws EE_Error
290
-     * @throws ReflectionException
291
-     * @type string|array $callback
292
-     * @type string       $methods
293
-     * @type boolean      $hidden_endpoint
294
-     * }
295
-     */
296
-    public static function get_ee_route_data()
297
-    {
298
-        $ee_routes = [];
299
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
300
-            $ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
301
-                $version,
302
-                $hidden_endpoints
303
-            );
304
-        }
305
-        return $ee_routes;
306
-    }
307
-
308
-
309
-    /**
310
-     * Gets the EE route data from the wp options if it exists already,
311
-     * otherwise re-generates it and saves it to the option
312
-     *
313
-     * @param string  $version
314
-     * @param boolean $hidden_endpoints
315
-     * @return array
316
-     * @throws EE_Error
317
-     * @throws ReflectionException
318
-     */
319
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
320
-    {
321
-        $ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
322
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
323
-            $ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
324
-        }
325
-        return $ee_routes;
326
-    }
327
-
328
-
329
-    /**
330
-     * Saves the EE REST API route data to a wp option and returns it
331
-     *
332
-     * @param string  $version
333
-     * @param boolean $hidden_endpoints
334
-     * @return mixed|null
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
339
-    {
340
-        $instance = EED_Core_Rest_Api::instance();
341
-        $routes = apply_filters(
342
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
343
-            array_replace_recursive(
344
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
345
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
346
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
347
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
348
-            )
349
-        );
350
-        $option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
351
-        if (get_option($option_name)) {
352
-            update_option($option_name, $routes, true);
353
-        } else {
354
-            add_option($option_name, $routes, null, 'no');
355
-        }
356
-        return $routes;
357
-    }
358
-
359
-
360
-    /**
361
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
362
-     * need to calculate it on every request
363
-     *
364
-     * @return void
365
-     * @deprecated since version 4.9.1
366
-     */
367
-    public static function save_ee_routes()
368
-    {
369
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
370
-            $instance = EED_Core_Rest_Api::instance();
371
-            $routes = apply_filters(
372
-                'EED_Core_Rest_Api__save_ee_routes__routes',
373
-                array_replace_recursive(
374
-                    $instance->_register_config_routes(),
375
-                    $instance->_register_meta_routes(),
376
-                    $instance->_register_model_routes(),
377
-                    $instance->_register_rpc_routes()
378
-                )
379
-            );
380
-            update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
381
-        }
382
-    }
383
-
384
-
385
-    /**
386
-     * Gets all the route information relating to EE models
387
-     *
388
-     * @return array @see get_ee_route_data
389
-     * @deprecated since version 4.9.1
390
-     */
391
-    protected function _register_model_routes()
392
-    {
393
-        $model_routes = [];
394
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
395
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
396
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
397
-        }
398
-        return $model_routes;
399
-    }
400
-
401
-
402
-    /**
403
-     * Decides whether or not to add write endpoints for this model.
404
-     * Currently, this defaults to exclude all global tables and models
405
-     * which would allow inserting WP core data (we don't want to duplicate
406
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
407
-     *
408
-     * @param EEM_Base $model
409
-     * @return bool
410
-     */
411
-    public static function should_have_write_endpoints(EEM_Base $model)
412
-    {
413
-        if ($model->is_wp_core_model()) {
414
-            return false;
415
-        }
416
-        foreach ($model->get_tables() as $table) {
417
-            if ($table->is_global()) {
418
-                return false;
419
-            }
420
-        }
421
-        return true;
422
-    }
423
-
424
-
425
-    /**
426
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
427
-     * in this versioned namespace of EE4
428
-     *
429
-     * @param $version
430
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
431
-     */
432
-    public static function model_names_with_plural_routes($version)
433
-    {
434
-        $model_version_info = new ModelVersionInfo($version);
435
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
436
-        // let's not bother having endpoints for extra metas
437
-        unset(
438
-            $models_to_register['Extra_Meta'],
439
-            $models_to_register['Extra_Join'],
440
-            $models_to_register['Post_Meta']
441
-        );
442
-        return apply_filters(
443
-            'FHEE__EED_Core_REST_API___register_model_routes',
444
-            $models_to_register
445
-        );
446
-    }
447
-
448
-
449
-    /**
450
-     * Gets the route data for EE models in the specified version
451
-     *
452
-     * @param string  $version
453
-     * @param boolean $hidden_endpoint
454
-     * @return array
455
-     * @throws EE_Error
456
-     * @throws ReflectionException
457
-     */
458
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
459
-    {
460
-        $model_routes = [];
461
-        $model_version_info = new ModelVersionInfo($version);
462
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
463
-            $model = EE_Registry::instance()->load_model($model_name);
464
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
465
-            if (! $model instanceof EEM_Base) {
466
-                continue;
467
-            }
468
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
469
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
470
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
471
-            $model_routes[ $plural_model_route ] = [
472
-                [
473
-                    'callback'        => [
474
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
475
-                        'handleRequestGetAll',
476
-                    ],
477
-                    'callback_args'   => [$version, $model_name],
478
-                    'methods'         => WP_REST_Server::READABLE,
479
-                    'hidden_endpoint' => $hidden_endpoint,
480
-                    'args'            => $this->_get_read_query_params($model, $version),
481
-                    '_links'          => [
482
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
483
-                    ],
484
-                ],
485
-                'schema' => [
486
-                    'schema_callback' => [
487
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
488
-                        'handleSchemaRequest',
489
-                    ],
490
-                    'callback_args'   => [$version, $model_name],
491
-                ],
492
-            ];
493
-            $model_routes[ $singular_model_route ] = [
494
-                [
495
-                    'callback'        => [
496
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
497
-                        'handleRequestGetOne',
498
-                    ],
499
-                    'callback_args'   => [$version, $model_name],
500
-                    'methods'         => WP_REST_Server::READABLE,
501
-                    'hidden_endpoint' => $hidden_endpoint,
502
-                    'args'            => $this->_get_response_selection_query_params($model, $version, true),
503
-                ],
504
-            ];
505
-            if (
506
-                apply_filters(
507
-                    'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
508
-                    EED_Core_Rest_Api::should_have_write_endpoints($model),
509
-                    $model
510
-                )
511
-            ) {
512
-                $model_routes[ $plural_model_route ][] = [
513
-                    'callback'        => [
514
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
515
-                        'handleRequestInsert',
516
-                    ],
517
-                    'callback_args'   => [$version, $model_name],
518
-                    'methods'         => WP_REST_Server::CREATABLE,
519
-                    'hidden_endpoint' => $hidden_endpoint,
520
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
521
-                ];
522
-                $model_routes[ $singular_model_route ] = array_merge(
523
-                    $model_routes[ $singular_model_route ],
524
-                    [
525
-                        [
526
-                            'callback'        => [
527
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
-                                'handleRequestUpdate',
529
-                            ],
530
-                            'callback_args'   => [$version, $model_name],
531
-                            'methods'         => WP_REST_Server::EDITABLE,
532
-                            'hidden_endpoint' => $hidden_endpoint,
533
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
534
-                        ],
535
-                        [
536
-                            'callback'        => [
537
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
538
-                                'handleRequestDelete',
539
-                            ],
540
-                            'callback_args'   => [$version, $model_name],
541
-                            'methods'         => WP_REST_Server::DELETABLE,
542
-                            'hidden_endpoint' => $hidden_endpoint,
543
-                            'args'            => $this->_get_delete_query_params($model, $version),
544
-                        ],
545
-                    ]
546
-                );
547
-            }
548
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
549
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
550
-                    $model,
551
-                    '(?P<id>[^\/]+)',
552
-                    $relation_obj
553
-                );
554
-                $model_routes[ $related_route ] = [
555
-                    [
556
-                        'callback'        => [
557
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
558
-                            'handleRequestGetRelated',
559
-                        ],
560
-                        'callback_args'   => [$version, $model_name, $relation_name],
561
-                        'methods'         => WP_REST_Server::READABLE,
562
-                        'hidden_endpoint' => $hidden_endpoint,
563
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
564
-                    ],
565
-                ];
566
-
567
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
568
-                $model_routes[ $related_write_route ] = [
569
-                    [
570
-                        'callback'        => [
571
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
572
-                            'handleRequestAddRelation',
573
-                        ],
574
-                        'callback_args'   => [$version, $model_name, $relation_name],
575
-                        'methods'         => WP_REST_Server::EDITABLE,
576
-                        'hidden_endpoint' => $hidden_endpoint,
577
-                        'args'            => $this->_get_add_relation_query_params(
578
-                            $model,
579
-                            $relation_obj->get_other_model(),
580
-                            $version
581
-                        ),
582
-                    ],
583
-                    [
584
-                        'callback'        => [
585
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
586
-                            'handleRequestRemoveRelation',
587
-                        ],
588
-                        'callback_args'   => [$version, $model_name, $relation_name],
589
-                        'methods'         => WP_REST_Server::DELETABLE,
590
-                        'hidden_endpoint' => $hidden_endpoint,
591
-                        'args'            => [],
592
-                    ],
593
-                ];
594
-            }
595
-        }
596
-        return $model_routes;
597
-    }
598
-
599
-
600
-    /**
601
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
602
-     * excluding the preceding slash.
603
-     * Eg you pass get_plural_route_to('Event') = 'events'
604
-     *
605
-     * @param EEM_Base $model
606
-     * @return string
607
-     */
608
-    public static function get_collection_route(EEM_Base $model)
609
-    {
610
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
611
-    }
612
-
613
-
614
-    /**
615
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
616
-     * excluding the preceding slash.
617
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
618
-     *
619
-     * @param EEM_Base $model eg Event or Venue
620
-     * @param string   $id
621
-     * @return string
622
-     */
623
-    public static function get_entity_route($model, $id)
624
-    {
625
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
626
-    }
627
-
628
-
629
-    /**
630
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
631
-     * excluding the preceding slash.
632
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
633
-     *
634
-     * @param EEM_Base               $model eg Event or Venue
635
-     * @param string                 $id
636
-     * @param EE_Model_Relation_Base $relation_obj
637
-     * @return string
638
-     */
639
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
640
-    {
641
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
642
-            $relation_obj->get_other_model()->get_this_model_name(),
643
-            $relation_obj
644
-        );
645
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
646
-    }
647
-
648
-
649
-    /**
650
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
651
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
652
-     *
653
-     * @param string $relative_route
654
-     * @param string $version
655
-     * @return string
656
-     */
657
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
658
-    {
659
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
660
-    }
661
-
662
-
663
-    /**
664
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
665
-     * routes that don't conform to the traditional REST CRUD-style).
666
-     *
667
-     * @deprecated since 4.9.1
668
-     */
669
-    protected function _register_rpc_routes()
670
-    {
671
-        $routes = [];
672
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
673
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
674
-                $version,
675
-                $hidden_endpoint
676
-            );
677
-        }
678
-        return $routes;
679
-    }
680
-
681
-
682
-    /**
683
-     * @param string  $version
684
-     * @param boolean $hidden_endpoint
685
-     * @return array
686
-     */
687
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
688
-    {
689
-        $this_versions_routes = [];
690
-        // checkin endpoint
691
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
692
-            [
693
-                'callback'        => [
694
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
695
-                    'handleRequestToggleCheckin',
696
-                ],
697
-                'methods'         => WP_REST_Server::CREATABLE,
698
-                'hidden_endpoint' => $hidden_endpoint,
699
-                'args'            => [
700
-                    'force' => [
701
-                        'required'    => false,
702
-                        'default'     => false,
703
-                        'description' => esc_html__(
704
-                        // @codingStandardsIgnoreStart
705
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
706
-                            // @codingStandardsIgnoreEnd
707
-                            'event_espresso'
708
-                        ),
709
-                    ],
710
-                ],
711
-                'callback_args'   => [$version],
712
-            ],
713
-        ];
714
-        return apply_filters(
715
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
716
-            $this_versions_routes,
717
-            $version,
718
-            $hidden_endpoint
719
-        );
720
-    }
721
-
722
-
723
-    /**
724
-     * Gets the query params that can be used when request one or many
725
-     *
726
-     * @param EEM_Base $model
727
-     * @param string   $version
728
-     * @return array
729
-     */
730
-    protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
731
-    {
732
-        EED_Core_Rest_Api::loadCalculatedModelFields();
733
-        $query_params = [
734
-            'include'   => [
735
-                'required' => false,
736
-                'default'  => '*',
737
-                'type'     => 'string',
738
-            ],
739
-            'calculate' => [
740
-                'required'          => false,
741
-                'default'           => '',
742
-                'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
743
-                'type'              => 'string',
744
-                // because we accept a CSV list of the enumerated strings, WP core validation and sanitization
745
-                // freaks out. We'll just validate this argument while handling the request
746
-                'validate_callback' => null,
747
-                'sanitize_callback' => null,
748
-            ],
749
-            'password'  => [
750
-                'required' => false,
751
-                'default'  => '',
752
-                'type'     => 'string',
753
-            ],
754
-        ];
755
-        return apply_filters(
756
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
757
-            $query_params,
758
-            $model,
759
-            $version
760
-        );
761
-    }
762
-
763
-
764
-    /**
765
-     * Gets the parameters acceptable for delete requests
766
-     *
767
-     * @param EEM_Base $model
768
-     * @param string   $version
769
-     * @return array
770
-     */
771
-    protected function _get_delete_query_params(EEM_Base $model, $version)
772
-    {
773
-        $params_for_delete = [
774
-            'allow_blocking' => [
775
-                'required' => false,
776
-                'default'  => true,
777
-                'type'     => 'boolean',
778
-            ],
779
-        ];
780
-        $params_for_delete['force'] = [
781
-            'required' => false,
782
-            'default'  => false,
783
-            'type'     => 'boolean',
784
-        ];
785
-        return apply_filters(
786
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
787
-            $params_for_delete,
788
-            $model,
789
-            $version
790
-        );
791
-    }
792
-
793
-
794
-    /**
795
-     * @param EEM_Base $source_model
796
-     * @param EEM_Base $related_model
797
-     * @param          $version
798
-     * @return array
799
-     * @throws EE_Error
800
-     * @since $VID:$
801
-     */
802
-    protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
803
-    {
804
-        // if they're related through a HABTM relation, check for any non-FKs
805
-        $all_relation_settings = $source_model->relation_settings();
806
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
807
-        $params = [];
808
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
809
-            foreach ($relation_settings->getNonKeyFields() as $field) {
810
-                /* @var $field EE_Model_Field_Base */
811
-                $params[ $field->get_name() ] = [
812
-                    'required'          => ! $field->is_nullable(),
813
-                    'default'           => ModelDataTranslator::prepareFieldValueForJson(
814
-                        $field,
815
-                        $field->get_default_value(),
816
-                        $version
817
-                    ),
818
-                    'type'              => $field->getSchemaType(),
819
-                    'validate_callback' => null,
820
-                    'sanitize_callback' => null,
821
-                ];
822
-            }
823
-        }
824
-        return $params;
825
-    }
826
-
827
-
828
-    /**
829
-     * Gets info about reading query params that are acceptable
830
-     *
831
-     * @param EEM_Base $model eg 'Event' or 'Venue'
832
-     * @param string   $version
833
-     * @return array    describing the args acceptable when querying this model
834
-     * @throws EE_Error
835
-     */
836
-    protected function _get_read_query_params(EEM_Base $model, $version)
837
-    {
838
-        $default_orderby = [];
839
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
840
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
841
-        }
842
-        return array_merge(
843
-            $this->_get_response_selection_query_params($model, $version),
844
-            [
845
-                'where'    => [
846
-                    'required'          => false,
847
-                    'default'           => [],
848
-                    'type'              => 'object',
849
-                    // because we accept an almost infinite list of possible where conditions, WP
850
-                    // core validation and sanitization freaks out. We'll just validate this argument
851
-                    // while handling the request
852
-                    'validate_callback' => null,
853
-                    'sanitize_callback' => null,
854
-                ],
855
-                'limit'    => [
856
-                    'required'          => false,
857
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
858
-                    'type'              => [
859
-                        'array',
860
-                        'string',
861
-                        'integer',
862
-                    ],
863
-                    // because we accept a variety of types, WP core validation and sanitization
864
-                    // freaks out. We'll just validate this argument while handling the request
865
-                    'validate_callback' => null,
866
-                    'sanitize_callback' => null,
867
-                ],
868
-                'order_by' => [
869
-                    'required'          => false,
870
-                    'default'           => $default_orderby,
871
-                    'type'              => [
872
-                        'object',
873
-                        'string',
874
-                    ],// because we accept a variety of types, WP core validation and sanitization
875
-                    // freaks out. We'll just validate this argument while handling the request
876
-                    'validate_callback' => null,
877
-                    'sanitize_callback' => null,
878
-                ],
879
-                'group_by' => [
880
-                    'required'          => false,
881
-                    'default'           => null,
882
-                    'type'              => [
883
-                        'object',
884
-                        'string',
885
-                    ],
886
-                    // because we accept  an almost infinite list of possible groupings,
887
-                    // WP core validation and sanitization
888
-                    // freaks out. We'll just validate this argument while handling the request
889
-                    'validate_callback' => null,
890
-                    'sanitize_callback' => null,
891
-                ],
892
-                'having'   => [
893
-                    'required'          => false,
894
-                    'default'           => null,
895
-                    'type'              => 'object',
896
-                    // because we accept an almost infinite list of possible where conditions, WP
897
-                    // core validation and sanitization freaks out. We'll just validate this argument
898
-                    // while handling the request
899
-                    'validate_callback' => null,
900
-                    'sanitize_callback' => null,
901
-                ],
902
-                'caps'     => [
903
-                    'required' => false,
904
-                    'default'  => EEM_Base::caps_read,
905
-                    'type'     => 'string',
906
-                    'enum'     => [
907
-                        EEM_Base::caps_read,
908
-                        EEM_Base::caps_read_admin,
909
-                        EEM_Base::caps_edit,
910
-                        EEM_Base::caps_delete,
911
-                    ],
912
-                ],
913
-            ]
914
-        );
915
-    }
916
-
917
-
918
-    /**
919
-     * Gets parameter information for a model regarding writing data
920
-     *
921
-     * @param string           $model_name
922
-     * @param ModelVersionInfo $model_version_info
923
-     * @param boolean          $create                                       whether this is for request to create (in
924
-     *                                                                       which case we need all required params) or
925
-     *                                                                       just to update (in which case we don't
926
-     *                                                                       need those on every request)
927
-     * @return array
928
-     * @throws EE_Error
929
-     * @throws ReflectionException
930
-     */
931
-    protected function _get_write_params(
932
-        $model_name,
933
-        ModelVersionInfo $model_version_info,
934
-        $create = false
935
-    ) {
936
-        $model = EE_Registry::instance()->load_model($model_name);
937
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
938
-
939
-        // we do our own validation and sanitization within the controller
940
-        $sanitize_callback = function_exists('rest_validate_value_from_schema')
941
-            ? ['EED_Core_Rest_Api', 'default_sanitize_callback']
942
-            : null;
943
-        $args_info = [];
944
-        foreach ($fields as $field_name => $field_obj) {
945
-            if ($field_obj->is_auto_increment()) {
946
-                // totally ignore auto increment IDs
947
-                continue;
948
-            }
949
-            $arg_info = $field_obj->getSchema();
950
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
951
-            $arg_info['required'] = $required;
952
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
953
-            unset($arg_info['readonly']);
954
-            $schema_properties = $field_obj->getSchemaProperties();
955
-            if (
956
-                isset($schema_properties['raw'])
957
-                && $field_obj->getSchemaType() === 'object'
958
-            ) {
959
-                // if there's a "raw" form of this argument, use those properties instead
960
-                $arg_info = array_replace(
961
-                    $arg_info,
962
-                    $schema_properties['raw']
963
-                );
964
-            }
965
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
966
-                $field_obj,
967
-                $field_obj->get_default_value(),
968
-                $model_version_info->requestedVersion()
969
-            );
970
-            $arg_info['sanitize_callback'] = $sanitize_callback;
971
-            $args_info[ $field_name ] = $arg_info;
972
-            if ($field_obj instanceof EE_Datetime_Field) {
973
-                $gmt_arg_info = $arg_info;
974
-                $gmt_arg_info['description'] = sprintf(
975
-                    esc_html__(
976
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
977
-                        'event_espresso'
978
-                    ),
979
-                    $field_obj->get_nicename(),
980
-                    $field_name
981
-                );
982
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
983
-            }
984
-        }
985
-        return $args_info;
986
-    }
987
-
988
-
989
-    /**
990
-     * Replacement for WP API's 'rest_parse_request_arg'.
991
-     * If the value is blank but not required, don't bother validating it.
992
-     * Also, it uses our email validation instead of WP API's default.
993
-     *
994
-     * @param                 $value
995
-     * @param WP_REST_Request $request
996
-     * @param                 $param
997
-     * @return bool|true|WP_Error
998
-     * @throws InvalidArgumentException
999
-     * @throws InvalidInterfaceException
1000
-     * @throws InvalidDataTypeException
1001
-     */
1002
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
1003
-    {
1004
-        $attributes = $request->get_attributes();
1005
-        if (
1006
-            ! isset($attributes['args'][ $param ])
1007
-            || ! is_array($attributes['args'][ $param ])
1008
-        ) {
1009
-            $validation_result = true;
1010
-        } else {
1011
-            $args = $attributes['args'][ $param ];
1012
-            if (
1013
-                (
1014
-                    $value === ''
1015
-                    || $value === null
1016
-                )
1017
-                && (! isset($args['required'])
1018
-                    || $args['required'] === false
1019
-                )
1020
-            ) {
1021
-                // not required and not provided? that's cool
1022
-                $validation_result = true;
1023
-            } elseif (
1024
-                isset($args['format'])
1025
-                      && $args['format'] === 'email'
1026
-            ) {
1027
-                $validation_result = true;
1028
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1029
-                    $validation_result = new WP_Error(
1030
-                        'rest_invalid_param',
1031
-                        esc_html__(
1032
-                            'The email address is not valid or does not exist.',
1033
-                            'event_espresso'
1034
-                        )
1035
-                    );
1036
-                }
1037
-            } else {
1038
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
1039
-            }
1040
-        }
1041
-        if (is_wp_error($validation_result)) {
1042
-            return $validation_result;
1043
-        }
1044
-        return rest_sanitize_request_arg($value, $request, $param);
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1050
-     *
1051
-     * @param $email
1052
-     * @return bool
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidInterfaceException
1055
-     * @throws InvalidDataTypeException
1056
-     */
1057
-    protected static function _validate_email($email)
1058
-    {
1059
-        try {
1060
-            EmailAddressFactory::create($email);
1061
-            return true;
1062
-        } catch (EmailValidationException $e) {
1063
-            return false;
1064
-        }
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * Gets routes for the config
1070
-     *
1071
-     * @return array @see _register_model_routes
1072
-     * @deprecated since version 4.9.1
1073
-     */
1074
-    protected function _register_config_routes()
1075
-    {
1076
-        $config_routes = [];
1077
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1078
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1079
-                $version,
1080
-                $hidden_endpoint
1081
-            );
1082
-        }
1083
-        return $config_routes;
1084
-    }
1085
-
1086
-
1087
-    /**
1088
-     * Gets routes for the config for the specified version
1089
-     *
1090
-     * @param string  $version
1091
-     * @param boolean $hidden_endpoint
1092
-     * @return array
1093
-     */
1094
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1095
-    {
1096
-        return [
1097
-            'config'    => [
1098
-                [
1099
-                    'callback'        => [
1100
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1101
-                        'handleRequest',
1102
-                    ],
1103
-                    'methods'         => WP_REST_Server::READABLE,
1104
-                    'hidden_endpoint' => $hidden_endpoint,
1105
-                    'callback_args'   => [$version],
1106
-                ],
1107
-            ],
1108
-            'site_info' => [
1109
-                [
1110
-                    'callback'        => [
1111
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1112
-                        'handleRequestSiteInfo',
1113
-                    ],
1114
-                    'methods'         => WP_REST_Server::READABLE,
1115
-                    'hidden_endpoint' => $hidden_endpoint,
1116
-                    'callback_args'   => [$version],
1117
-                ],
1118
-            ],
1119
-        ];
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     * Gets the meta info routes
1125
-     *
1126
-     * @return array @see _register_model_routes
1127
-     * @deprecated since version 4.9.1
1128
-     */
1129
-    protected function _register_meta_routes()
1130
-    {
1131
-        $meta_routes = [];
1132
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1133
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1134
-                $version,
1135
-                $hidden_endpoint
1136
-            );
1137
-        }
1138
-        return $meta_routes;
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * @param string  $version
1144
-     * @param boolean $hidden_endpoint
1145
-     * @return array
1146
-     */
1147
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1148
-    {
1149
-        return [
1150
-            'resources' => [
1151
-                [
1152
-                    'callback'        => [
1153
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1154
-                        'handleRequestModelsMeta',
1155
-                    ],
1156
-                    'methods'         => WP_REST_Server::READABLE,
1157
-                    'hidden_endpoint' => $hidden_endpoint,
1158
-                    'callback_args'   => [$version],
1159
-                ],
1160
-            ],
1161
-        ];
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Tries to hide old 4.6 endpoints from the
1167
-     *
1168
-     * @param array $route_data
1169
-     * @return array
1170
-     * @throws EE_Error
1171
-     * @throws ReflectionException
1172
-     */
1173
-    public static function hide_old_endpoints($route_data)
1174
-    {
1175
-        // allow API clients to override which endpoints get hidden, in case
1176
-        // they want to discover particular endpoints
1177
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1178
-        $force_show_ee_namespace = ltrim(
1179
-            EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1180
-            '/'
1181
-        );
1182
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1183
-            foreach ($relative_urls as $resource_name => $endpoints) {
1184
-                foreach ($endpoints as $key => $endpoint) {
1185
-                    // skip schema and other route options
1186
-                    if (! is_numeric($key)) {
1187
-                        continue;
1188
-                    }
1189
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1190
-                    // to $force_show_ee_namespace, in which case only show that one
1191
-                    // namespace's endpoints (and hide all others)
1192
-                    if (
1193
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1194
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1195
-                    ) {
1196
-                        $full_route = '/' . ltrim($namespace, '/');
1197
-                        $full_route .= '/' . ltrim($resource_name, '/');
1198
-                        unset($route_data[ $full_route ]);
1199
-                    }
1200
-                }
1201
-            }
1202
-        }
1203
-        return $route_data;
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * Returns an array describing which versions of core support serving requests for.
1209
-     * Keys are core versions' major and minor version, and values are the
1210
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1211
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1212
-     * the answers table entirely, in which case it would be very difficult for
1213
-     * it to serve 4.6-style responses.
1214
-     * Versions of core that are missing from this array are unknowns.
1215
-     * previous ver
1216
-     *
1217
-     * @return array
1218
-     */
1219
-    public static function version_compatibilities()
1220
-    {
1221
-        return apply_filters(
1222
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1223
-            [
1224
-                '4.8.29' => '4.8.29',
1225
-                '4.8.33' => '4.8.29',
1226
-                '4.8.34' => '4.8.29',
1227
-                '4.8.36' => '4.8.29',
1228
-            ]
1229
-        );
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Gets the latest API version served. Eg if there
1235
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1236
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1237
-     *
1238
-     * @return string
1239
-     */
1240
-    public static function latest_rest_api_version()
1241
-    {
1242
-        $versions_served = EED_Core_Rest_Api::versions_served();
1243
-        $versions_served_keys = array_keys($versions_served);
1244
-        return end($versions_served_keys);
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1250
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1251
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1252
-     * We also indicate whether or not this version should be put in the index or not
1253
-     *
1254
-     * @return array keys are API version numbers (just major and minor numbers), and values
1255
-     * are whether or not they should be hidden
1256
-     */
1257
-    public static function versions_served()
1258
-    {
1259
-        $versions_served = [];
1260
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1261
-        $lowest_compatible_version = end($possibly_served_versions);
1262
-        reset($possibly_served_versions);
1263
-        $versions_served_historically = array_keys($possibly_served_versions);
1264
-        $latest_version = end($versions_served_historically);
1265
-        reset($versions_served_historically);
1266
-        // for each version of core we have ever served:
1267
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1268
-            // if it's not above the current core version, and it's compatible with the current version of core
1269
-
1270
-            if ($key_versioned_endpoint === $latest_version) {
1271
-                // don't hide the latest version in the index
1272
-                $versions_served[ $key_versioned_endpoint ] = false;
1273
-            } elseif (
1274
-                version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1275
-                && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1276
-            ) {
1277
-                // include, but hide, previous versions which are still supported
1278
-                $versions_served[ $key_versioned_endpoint ] = true;
1279
-            } elseif (
1280
-                apply_filters(
1281
-                    'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1282
-                    false,
1283
-                    $possibly_served_versions
1284
-                )
1285
-            ) {
1286
-                // if a version is no longer supported, don't include it in index or list of versions served
1287
-                $versions_served[ $key_versioned_endpoint ] = true;
1288
-            }
1289
-        }
1290
-        return $versions_served;
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * Gets the major and minor version of EE core's version string
1296
-     *
1297
-     * @return string
1298
-     */
1299
-    public static function core_version()
1300
-    {
1301
-        return apply_filters(
1302
-            'FHEE__EED_Core_REST_API__core_version',
1303
-            implode(
1304
-                '.',
1305
-                array_slice(
1306
-                    explode(
1307
-                        '.',
1308
-                        espresso_version()
1309
-                    ),
1310
-                    0,
1311
-                    3
1312
-                )
1313
-            )
1314
-        );
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * Gets the default limit that should be used when querying for resources
1320
-     *
1321
-     * @return int
1322
-     */
1323
-    public static function get_default_query_limit()
1324
-    {
1325
-        // we actually don't use a const because we want folks to always use
1326
-        // this method, not the const directly
1327
-        return apply_filters(
1328
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1329
-            50
1330
-        );
1331
-    }
1332
-
1333
-
1334
-    /**
1335
-     * @param string $version api version string (i.e. '4.8.36')
1336
-     * @return array
1337
-     */
1338
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1339
-    {
1340
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1341
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1342
-        $collection_routes = [];
1343
-        foreach ($model_names as $model_name => $model_class_name) {
1344
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1345
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1346
-        }
1347
-        return $collection_routes;
1348
-    }
1349
-
1350
-
1351
-    /**
1352
-     * Returns an array of primary key names indexed by model names.
1353
-     *
1354
-     * @param string $version
1355
-     * @return array
1356
-     */
1357
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1358
-    {
1359
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1360
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1361
-        $primary_key_items = [];
1362
-        foreach ($model_names as $model_name => $model_class_name) {
1363
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1364
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1365
-                if (count($primary_keys) > 1) {
1366
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1367
-                } else {
1368
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1369
-                }
1370
-            }
1371
-        }
1372
-        return $primary_key_items;
1373
-    }
1374
-
1375
-
1376
-    /**
1377
-     * Determines the EE REST API debug mode is activated, or not.
1378
-     *
1379
-     * @return bool
1380
-     * @since 4.9.76.p
1381
-     */
1382
-    public static function debugMode()
1383
-    {
1384
-        static $debug_mode = null; // could be class prop
1385
-        if ($debug_mode === null) {
1386
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1387
-        }
1388
-        return $debug_mode;
1389
-    }
1390
-
1391
-
1392
-    /**
1393
-     *    run - initial module setup
1394
-     *
1395
-     * @access    public
1396
-     * @param WP $WP
1397
-     * @return    void
1398
-     */
1399
-    public function run($WP)
1400
-    {
1401
-    }
24
+	const ee_api_namespace = Domain::API_NAMESPACE;
25
+
26
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
27
+
28
+	const saved_routes_option_names = 'ee_core_routes';
29
+
30
+	/**
31
+	 * string used in _links response bodies to make them globally unique.
32
+	 *
33
+	 * @see http://v2.wp-api.org/extending/linking/
34
+	 */
35
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
36
+
37
+	/**
38
+	 * @var CalculatedModelFields
39
+	 */
40
+	protected static $_field_calculator;
41
+
42
+
43
+	/**
44
+	 * @return EED_Core_Rest_Api|EED_Module
45
+	 */
46
+	public static function instance()
47
+	{
48
+		return parent::get_instance(EED_Core_Rest_Api::class);
49
+	}
50
+
51
+
52
+	/**
53
+	 *    set_hooks - for hooking into EE Core, other modules, etc
54
+	 *
55
+	 * @access    public
56
+	 * @return    void
57
+	 */
58
+	public static function set_hooks()
59
+	{
60
+	}
61
+
62
+
63
+	/**
64
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
+	 *
66
+	 * @access    public
67
+	 * @return    void
68
+	 */
69
+	public static function set_hooks_admin()
70
+	{
71
+	}
72
+
73
+
74
+	public static function set_hooks_both()
75
+	{
76
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
77
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
78
+		add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
79
+		add_filter(
80
+			'rest_index',
81
+			['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
82
+		);
83
+	}
84
+
85
+
86
+	/**
87
+	 * @since   $VID:$
88
+	 */
89
+	public static function loadCalculatedModelFields()
90
+	{
91
+		EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
+		);
94
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
95
+	}
96
+
97
+
98
+	/**
99
+	 * sets up hooks which only need to be included as part of REST API requests;
100
+	 * other requests like to the frontend or admin etc don't need them
101
+	 *
102
+	 * @throws EE_Error
103
+	 */
104
+	public static function set_hooks_rest_api()
105
+	{
106
+		// set hooks which account for changes made to the API
107
+		EED_Core_Rest_Api::_set_hooks_for_changes();
108
+	}
109
+
110
+
111
+	/**
112
+	 * public wrapper of _set_hooks_for_changes.
113
+	 * Loads all the hooks which make requests to old versions of the API
114
+	 * appear the same as they always did
115
+	 *
116
+	 * @throws EE_Error
117
+	 */
118
+	public static function set_hooks_for_changes()
119
+	{
120
+		EED_Core_Rest_Api::_set_hooks_for_changes();
121
+	}
122
+
123
+
124
+	/**
125
+	 * Loads all the hooks which make requests to old versions of the API
126
+	 * appear the same as they always did
127
+	 *
128
+	 * @throws EE_Error
129
+	 */
130
+	protected static function _set_hooks_for_changes()
131
+	{
132
+		$folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
+			// ignore the base parent class
135
+			// and legacy named classes
136
+			if (
137
+				$classname_in_namespace === 'ChangesInBase'
138
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
139
+			) {
140
+				continue;
141
+			}
142
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
+			if (class_exists($full_classname)) {
144
+				$instance_of_class = new $full_classname();
145
+				if ($instance_of_class instanceof ChangesInBase) {
146
+					$instance_of_class->setHooks();
147
+				}
148
+			}
149
+		}
150
+	}
151
+
152
+
153
+	/**
154
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
155
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
156
+	 *
157
+	 * @throws EE_Error
158
+	 * @throws ReflectionException
159
+	 */
160
+	public static function register_routes()
161
+	{
162
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
163
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
164
+				/**
165
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
166
+				 *                                         but can also contain route options like {
167
+				 * @type array    $schema                      {
168
+				 * @type callable $schema_callback
169
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
170
+				 * WP_REST_Request of course
171
+				 * }
172
+				 * }
173
+				 */
174
+				// when registering routes, register all the endpoints' data at the same time
175
+				$multiple_endpoint_args = [];
176
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
177
+					/**
178
+					 * @var array     $data_for_single_endpoint {
179
+					 * @type callable $callback
180
+					 * @type string methods
181
+					 * @type array args
182
+					 * @type array _links
183
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
184
+					 * WP_REST_Request of course
185
+					 * }
186
+					 */
187
+					// skip route options
188
+					if (! is_numeric($endpoint_key)) {
189
+						continue;
190
+					}
191
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
+						throw new EE_Error(
193
+							esc_html__(
194
+							// @codingStandardsIgnoreStart
195
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
196
+								// @codingStandardsIgnoreEnd
197
+								'event_espresso'
198
+							)
199
+						);
200
+					}
201
+					$callback = $data_for_single_endpoint['callback'];
202
+					$single_endpoint_args = [
203
+						'methods' => $data_for_single_endpoint['methods'],
204
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
+							: [],
206
+					];
207
+					if (isset($data_for_single_endpoint['_links'])) {
208
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
+					}
210
+					if (isset($data_for_single_endpoint['callback_args'])) {
211
+						$callback_args = $data_for_single_endpoint['callback_args'];
212
+						$single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
213
+							$callback,
214
+							$callback_args
215
+						) {
216
+							array_unshift($callback_args, $request);
217
+							return call_user_func_array(
218
+								$callback,
219
+								$callback_args
220
+							);
221
+						};
222
+					} else {
223
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
+					}
225
+					// As of WordPress 5.5, if a permission_callback is not provided,
226
+					// the REST API will issue a _doing_it_wrong notice.
227
+					// Since the EE REST API defers capabilities to the db model system,
228
+					// we will just use the generic WP callback for public endpoints
229
+					if (! isset($single_endpoint_args['permission_callback'])) {
230
+						$single_endpoint_args['permission_callback'] = '__return_true';
231
+					}
232
+					$multiple_endpoint_args[] = $single_endpoint_args;
233
+				}
234
+				if (isset($data_for_multiple_endpoints['schema'])) {
235
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
236
+					$schema_callback = $schema_route_data['schema_callback'];
237
+					$callback_args = $schema_route_data['callback_args'];
238
+					$multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
239
+						return call_user_func_array(
240
+							$schema_callback,
241
+							$callback_args
242
+						);
243
+					};
244
+				}
245
+				register_rest_route(
246
+					$namespace,
247
+					$relative_route,
248
+					$multiple_endpoint_args
249
+				);
250
+			}
251
+		}
252
+	}
253
+
254
+
255
+	/**
256
+	 * Checks if there was a version change or something that merits invalidating the cached
257
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
258
+	 * next time the WP API is used
259
+	 */
260
+	public static function invalidate_cached_route_data_on_version_change()
261
+	{
262
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
263
+			EED_Core_Rest_Api::invalidate_cached_route_data();
264
+		}
265
+		foreach (EE_Registry::instance()->addons as $addon) {
266
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
267
+				EED_Core_Rest_Api::invalidate_cached_route_data();
268
+			}
269
+		}
270
+	}
271
+
272
+
273
+	/**
274
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
275
+	 */
276
+	public static function invalidate_cached_route_data()
277
+	{
278
+		// delete the saved EE REST API routes
279
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
280
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
281
+		}
282
+	}
283
+
284
+
285
+	/**
286
+	 * Gets the EE route data
287
+	 *
288
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
289
+	 * @throws EE_Error
290
+	 * @throws ReflectionException
291
+	 * @type string|array $callback
292
+	 * @type string       $methods
293
+	 * @type boolean      $hidden_endpoint
294
+	 * }
295
+	 */
296
+	public static function get_ee_route_data()
297
+	{
298
+		$ee_routes = [];
299
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
300
+			$ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
301
+				$version,
302
+				$hidden_endpoints
303
+			);
304
+		}
305
+		return $ee_routes;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Gets the EE route data from the wp options if it exists already,
311
+	 * otherwise re-generates it and saves it to the option
312
+	 *
313
+	 * @param string  $version
314
+	 * @param boolean $hidden_endpoints
315
+	 * @return array
316
+	 * @throws EE_Error
317
+	 * @throws ReflectionException
318
+	 */
319
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
320
+	{
321
+		$ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
322
+		if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
323
+			$ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
324
+		}
325
+		return $ee_routes;
326
+	}
327
+
328
+
329
+	/**
330
+	 * Saves the EE REST API route data to a wp option and returns it
331
+	 *
332
+	 * @param string  $version
333
+	 * @param boolean $hidden_endpoints
334
+	 * @return mixed|null
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
339
+	{
340
+		$instance = EED_Core_Rest_Api::instance();
341
+		$routes = apply_filters(
342
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
343
+			array_replace_recursive(
344
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
345
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
346
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
347
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
348
+			)
349
+		);
350
+		$option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
351
+		if (get_option($option_name)) {
352
+			update_option($option_name, $routes, true);
353
+		} else {
354
+			add_option($option_name, $routes, null, 'no');
355
+		}
356
+		return $routes;
357
+	}
358
+
359
+
360
+	/**
361
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
362
+	 * need to calculate it on every request
363
+	 *
364
+	 * @return void
365
+	 * @deprecated since version 4.9.1
366
+	 */
367
+	public static function save_ee_routes()
368
+	{
369
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
370
+			$instance = EED_Core_Rest_Api::instance();
371
+			$routes = apply_filters(
372
+				'EED_Core_Rest_Api__save_ee_routes__routes',
373
+				array_replace_recursive(
374
+					$instance->_register_config_routes(),
375
+					$instance->_register_meta_routes(),
376
+					$instance->_register_model_routes(),
377
+					$instance->_register_rpc_routes()
378
+				)
379
+			);
380
+			update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
381
+		}
382
+	}
383
+
384
+
385
+	/**
386
+	 * Gets all the route information relating to EE models
387
+	 *
388
+	 * @return array @see get_ee_route_data
389
+	 * @deprecated since version 4.9.1
390
+	 */
391
+	protected function _register_model_routes()
392
+	{
393
+		$model_routes = [];
394
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
395
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
396
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
397
+		}
398
+		return $model_routes;
399
+	}
400
+
401
+
402
+	/**
403
+	 * Decides whether or not to add write endpoints for this model.
404
+	 * Currently, this defaults to exclude all global tables and models
405
+	 * which would allow inserting WP core data (we don't want to duplicate
406
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
407
+	 *
408
+	 * @param EEM_Base $model
409
+	 * @return bool
410
+	 */
411
+	public static function should_have_write_endpoints(EEM_Base $model)
412
+	{
413
+		if ($model->is_wp_core_model()) {
414
+			return false;
415
+		}
416
+		foreach ($model->get_tables() as $table) {
417
+			if ($table->is_global()) {
418
+				return false;
419
+			}
420
+		}
421
+		return true;
422
+	}
423
+
424
+
425
+	/**
426
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
427
+	 * in this versioned namespace of EE4
428
+	 *
429
+	 * @param $version
430
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
431
+	 */
432
+	public static function model_names_with_plural_routes($version)
433
+	{
434
+		$model_version_info = new ModelVersionInfo($version);
435
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
436
+		// let's not bother having endpoints for extra metas
437
+		unset(
438
+			$models_to_register['Extra_Meta'],
439
+			$models_to_register['Extra_Join'],
440
+			$models_to_register['Post_Meta']
441
+		);
442
+		return apply_filters(
443
+			'FHEE__EED_Core_REST_API___register_model_routes',
444
+			$models_to_register
445
+		);
446
+	}
447
+
448
+
449
+	/**
450
+	 * Gets the route data for EE models in the specified version
451
+	 *
452
+	 * @param string  $version
453
+	 * @param boolean $hidden_endpoint
454
+	 * @return array
455
+	 * @throws EE_Error
456
+	 * @throws ReflectionException
457
+	 */
458
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
459
+	{
460
+		$model_routes = [];
461
+		$model_version_info = new ModelVersionInfo($version);
462
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
463
+			$model = EE_Registry::instance()->load_model($model_name);
464
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
465
+			if (! $model instanceof EEM_Base) {
466
+				continue;
467
+			}
468
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
469
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
470
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
471
+			$model_routes[ $plural_model_route ] = [
472
+				[
473
+					'callback'        => [
474
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
475
+						'handleRequestGetAll',
476
+					],
477
+					'callback_args'   => [$version, $model_name],
478
+					'methods'         => WP_REST_Server::READABLE,
479
+					'hidden_endpoint' => $hidden_endpoint,
480
+					'args'            => $this->_get_read_query_params($model, $version),
481
+					'_links'          => [
482
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
483
+					],
484
+				],
485
+				'schema' => [
486
+					'schema_callback' => [
487
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
488
+						'handleSchemaRequest',
489
+					],
490
+					'callback_args'   => [$version, $model_name],
491
+				],
492
+			];
493
+			$model_routes[ $singular_model_route ] = [
494
+				[
495
+					'callback'        => [
496
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
497
+						'handleRequestGetOne',
498
+					],
499
+					'callback_args'   => [$version, $model_name],
500
+					'methods'         => WP_REST_Server::READABLE,
501
+					'hidden_endpoint' => $hidden_endpoint,
502
+					'args'            => $this->_get_response_selection_query_params($model, $version, true),
503
+				],
504
+			];
505
+			if (
506
+				apply_filters(
507
+					'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
508
+					EED_Core_Rest_Api::should_have_write_endpoints($model),
509
+					$model
510
+				)
511
+			) {
512
+				$model_routes[ $plural_model_route ][] = [
513
+					'callback'        => [
514
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
515
+						'handleRequestInsert',
516
+					],
517
+					'callback_args'   => [$version, $model_name],
518
+					'methods'         => WP_REST_Server::CREATABLE,
519
+					'hidden_endpoint' => $hidden_endpoint,
520
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
521
+				];
522
+				$model_routes[ $singular_model_route ] = array_merge(
523
+					$model_routes[ $singular_model_route ],
524
+					[
525
+						[
526
+							'callback'        => [
527
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
+								'handleRequestUpdate',
529
+							],
530
+							'callback_args'   => [$version, $model_name],
531
+							'methods'         => WP_REST_Server::EDITABLE,
532
+							'hidden_endpoint' => $hidden_endpoint,
533
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
534
+						],
535
+						[
536
+							'callback'        => [
537
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
538
+								'handleRequestDelete',
539
+							],
540
+							'callback_args'   => [$version, $model_name],
541
+							'methods'         => WP_REST_Server::DELETABLE,
542
+							'hidden_endpoint' => $hidden_endpoint,
543
+							'args'            => $this->_get_delete_query_params($model, $version),
544
+						],
545
+					]
546
+				);
547
+			}
548
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
549
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
550
+					$model,
551
+					'(?P<id>[^\/]+)',
552
+					$relation_obj
553
+				);
554
+				$model_routes[ $related_route ] = [
555
+					[
556
+						'callback'        => [
557
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
558
+							'handleRequestGetRelated',
559
+						],
560
+						'callback_args'   => [$version, $model_name, $relation_name],
561
+						'methods'         => WP_REST_Server::READABLE,
562
+						'hidden_endpoint' => $hidden_endpoint,
563
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
564
+					],
565
+				];
566
+
567
+				$related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
568
+				$model_routes[ $related_write_route ] = [
569
+					[
570
+						'callback'        => [
571
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
572
+							'handleRequestAddRelation',
573
+						],
574
+						'callback_args'   => [$version, $model_name, $relation_name],
575
+						'methods'         => WP_REST_Server::EDITABLE,
576
+						'hidden_endpoint' => $hidden_endpoint,
577
+						'args'            => $this->_get_add_relation_query_params(
578
+							$model,
579
+							$relation_obj->get_other_model(),
580
+							$version
581
+						),
582
+					],
583
+					[
584
+						'callback'        => [
585
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
586
+							'handleRequestRemoveRelation',
587
+						],
588
+						'callback_args'   => [$version, $model_name, $relation_name],
589
+						'methods'         => WP_REST_Server::DELETABLE,
590
+						'hidden_endpoint' => $hidden_endpoint,
591
+						'args'            => [],
592
+					],
593
+				];
594
+			}
595
+		}
596
+		return $model_routes;
597
+	}
598
+
599
+
600
+	/**
601
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
602
+	 * excluding the preceding slash.
603
+	 * Eg you pass get_plural_route_to('Event') = 'events'
604
+	 *
605
+	 * @param EEM_Base $model
606
+	 * @return string
607
+	 */
608
+	public static function get_collection_route(EEM_Base $model)
609
+	{
610
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
611
+	}
612
+
613
+
614
+	/**
615
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
616
+	 * excluding the preceding slash.
617
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
618
+	 *
619
+	 * @param EEM_Base $model eg Event or Venue
620
+	 * @param string   $id
621
+	 * @return string
622
+	 */
623
+	public static function get_entity_route($model, $id)
624
+	{
625
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
626
+	}
627
+
628
+
629
+	/**
630
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
631
+	 * excluding the preceding slash.
632
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
633
+	 *
634
+	 * @param EEM_Base               $model eg Event or Venue
635
+	 * @param string                 $id
636
+	 * @param EE_Model_Relation_Base $relation_obj
637
+	 * @return string
638
+	 */
639
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
640
+	{
641
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
642
+			$relation_obj->get_other_model()->get_this_model_name(),
643
+			$relation_obj
644
+		);
645
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
646
+	}
647
+
648
+
649
+	/**
650
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
651
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
652
+	 *
653
+	 * @param string $relative_route
654
+	 * @param string $version
655
+	 * @return string
656
+	 */
657
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
658
+	{
659
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
660
+	}
661
+
662
+
663
+	/**
664
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
665
+	 * routes that don't conform to the traditional REST CRUD-style).
666
+	 *
667
+	 * @deprecated since 4.9.1
668
+	 */
669
+	protected function _register_rpc_routes()
670
+	{
671
+		$routes = [];
672
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
673
+			$routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
674
+				$version,
675
+				$hidden_endpoint
676
+			);
677
+		}
678
+		return $routes;
679
+	}
680
+
681
+
682
+	/**
683
+	 * @param string  $version
684
+	 * @param boolean $hidden_endpoint
685
+	 * @return array
686
+	 */
687
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
688
+	{
689
+		$this_versions_routes = [];
690
+		// checkin endpoint
691
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
692
+			[
693
+				'callback'        => [
694
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
695
+					'handleRequestToggleCheckin',
696
+				],
697
+				'methods'         => WP_REST_Server::CREATABLE,
698
+				'hidden_endpoint' => $hidden_endpoint,
699
+				'args'            => [
700
+					'force' => [
701
+						'required'    => false,
702
+						'default'     => false,
703
+						'description' => esc_html__(
704
+						// @codingStandardsIgnoreStart
705
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
706
+							// @codingStandardsIgnoreEnd
707
+							'event_espresso'
708
+						),
709
+					],
710
+				],
711
+				'callback_args'   => [$version],
712
+			],
713
+		];
714
+		return apply_filters(
715
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
716
+			$this_versions_routes,
717
+			$version,
718
+			$hidden_endpoint
719
+		);
720
+	}
721
+
722
+
723
+	/**
724
+	 * Gets the query params that can be used when request one or many
725
+	 *
726
+	 * @param EEM_Base $model
727
+	 * @param string   $version
728
+	 * @return array
729
+	 */
730
+	protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
731
+	{
732
+		EED_Core_Rest_Api::loadCalculatedModelFields();
733
+		$query_params = [
734
+			'include'   => [
735
+				'required' => false,
736
+				'default'  => '*',
737
+				'type'     => 'string',
738
+			],
739
+			'calculate' => [
740
+				'required'          => false,
741
+				'default'           => '',
742
+				'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
743
+				'type'              => 'string',
744
+				// because we accept a CSV list of the enumerated strings, WP core validation and sanitization
745
+				// freaks out. We'll just validate this argument while handling the request
746
+				'validate_callback' => null,
747
+				'sanitize_callback' => null,
748
+			],
749
+			'password'  => [
750
+				'required' => false,
751
+				'default'  => '',
752
+				'type'     => 'string',
753
+			],
754
+		];
755
+		return apply_filters(
756
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
757
+			$query_params,
758
+			$model,
759
+			$version
760
+		);
761
+	}
762
+
763
+
764
+	/**
765
+	 * Gets the parameters acceptable for delete requests
766
+	 *
767
+	 * @param EEM_Base $model
768
+	 * @param string   $version
769
+	 * @return array
770
+	 */
771
+	protected function _get_delete_query_params(EEM_Base $model, $version)
772
+	{
773
+		$params_for_delete = [
774
+			'allow_blocking' => [
775
+				'required' => false,
776
+				'default'  => true,
777
+				'type'     => 'boolean',
778
+			],
779
+		];
780
+		$params_for_delete['force'] = [
781
+			'required' => false,
782
+			'default'  => false,
783
+			'type'     => 'boolean',
784
+		];
785
+		return apply_filters(
786
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
787
+			$params_for_delete,
788
+			$model,
789
+			$version
790
+		);
791
+	}
792
+
793
+
794
+	/**
795
+	 * @param EEM_Base $source_model
796
+	 * @param EEM_Base $related_model
797
+	 * @param          $version
798
+	 * @return array
799
+	 * @throws EE_Error
800
+	 * @since $VID:$
801
+	 */
802
+	protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
803
+	{
804
+		// if they're related through a HABTM relation, check for any non-FKs
805
+		$all_relation_settings = $source_model->relation_settings();
806
+		$relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
807
+		$params = [];
808
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
809
+			foreach ($relation_settings->getNonKeyFields() as $field) {
810
+				/* @var $field EE_Model_Field_Base */
811
+				$params[ $field->get_name() ] = [
812
+					'required'          => ! $field->is_nullable(),
813
+					'default'           => ModelDataTranslator::prepareFieldValueForJson(
814
+						$field,
815
+						$field->get_default_value(),
816
+						$version
817
+					),
818
+					'type'              => $field->getSchemaType(),
819
+					'validate_callback' => null,
820
+					'sanitize_callback' => null,
821
+				];
822
+			}
823
+		}
824
+		return $params;
825
+	}
826
+
827
+
828
+	/**
829
+	 * Gets info about reading query params that are acceptable
830
+	 *
831
+	 * @param EEM_Base $model eg 'Event' or 'Venue'
832
+	 * @param string   $version
833
+	 * @return array    describing the args acceptable when querying this model
834
+	 * @throws EE_Error
835
+	 */
836
+	protected function _get_read_query_params(EEM_Base $model, $version)
837
+	{
838
+		$default_orderby = [];
839
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
840
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
841
+		}
842
+		return array_merge(
843
+			$this->_get_response_selection_query_params($model, $version),
844
+			[
845
+				'where'    => [
846
+					'required'          => false,
847
+					'default'           => [],
848
+					'type'              => 'object',
849
+					// because we accept an almost infinite list of possible where conditions, WP
850
+					// core validation and sanitization freaks out. We'll just validate this argument
851
+					// while handling the request
852
+					'validate_callback' => null,
853
+					'sanitize_callback' => null,
854
+				],
855
+				'limit'    => [
856
+					'required'          => false,
857
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
858
+					'type'              => [
859
+						'array',
860
+						'string',
861
+						'integer',
862
+					],
863
+					// because we accept a variety of types, WP core validation and sanitization
864
+					// freaks out. We'll just validate this argument while handling the request
865
+					'validate_callback' => null,
866
+					'sanitize_callback' => null,
867
+				],
868
+				'order_by' => [
869
+					'required'          => false,
870
+					'default'           => $default_orderby,
871
+					'type'              => [
872
+						'object',
873
+						'string',
874
+					],// because we accept a variety of types, WP core validation and sanitization
875
+					// freaks out. We'll just validate this argument while handling the request
876
+					'validate_callback' => null,
877
+					'sanitize_callback' => null,
878
+				],
879
+				'group_by' => [
880
+					'required'          => false,
881
+					'default'           => null,
882
+					'type'              => [
883
+						'object',
884
+						'string',
885
+					],
886
+					// because we accept  an almost infinite list of possible groupings,
887
+					// WP core validation and sanitization
888
+					// freaks out. We'll just validate this argument while handling the request
889
+					'validate_callback' => null,
890
+					'sanitize_callback' => null,
891
+				],
892
+				'having'   => [
893
+					'required'          => false,
894
+					'default'           => null,
895
+					'type'              => 'object',
896
+					// because we accept an almost infinite list of possible where conditions, WP
897
+					// core validation and sanitization freaks out. We'll just validate this argument
898
+					// while handling the request
899
+					'validate_callback' => null,
900
+					'sanitize_callback' => null,
901
+				],
902
+				'caps'     => [
903
+					'required' => false,
904
+					'default'  => EEM_Base::caps_read,
905
+					'type'     => 'string',
906
+					'enum'     => [
907
+						EEM_Base::caps_read,
908
+						EEM_Base::caps_read_admin,
909
+						EEM_Base::caps_edit,
910
+						EEM_Base::caps_delete,
911
+					],
912
+				],
913
+			]
914
+		);
915
+	}
916
+
917
+
918
+	/**
919
+	 * Gets parameter information for a model regarding writing data
920
+	 *
921
+	 * @param string           $model_name
922
+	 * @param ModelVersionInfo $model_version_info
923
+	 * @param boolean          $create                                       whether this is for request to create (in
924
+	 *                                                                       which case we need all required params) or
925
+	 *                                                                       just to update (in which case we don't
926
+	 *                                                                       need those on every request)
927
+	 * @return array
928
+	 * @throws EE_Error
929
+	 * @throws ReflectionException
930
+	 */
931
+	protected function _get_write_params(
932
+		$model_name,
933
+		ModelVersionInfo $model_version_info,
934
+		$create = false
935
+	) {
936
+		$model = EE_Registry::instance()->load_model($model_name);
937
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
938
+
939
+		// we do our own validation and sanitization within the controller
940
+		$sanitize_callback = function_exists('rest_validate_value_from_schema')
941
+			? ['EED_Core_Rest_Api', 'default_sanitize_callback']
942
+			: null;
943
+		$args_info = [];
944
+		foreach ($fields as $field_name => $field_obj) {
945
+			if ($field_obj->is_auto_increment()) {
946
+				// totally ignore auto increment IDs
947
+				continue;
948
+			}
949
+			$arg_info = $field_obj->getSchema();
950
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
951
+			$arg_info['required'] = $required;
952
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
953
+			unset($arg_info['readonly']);
954
+			$schema_properties = $field_obj->getSchemaProperties();
955
+			if (
956
+				isset($schema_properties['raw'])
957
+				&& $field_obj->getSchemaType() === 'object'
958
+			) {
959
+				// if there's a "raw" form of this argument, use those properties instead
960
+				$arg_info = array_replace(
961
+					$arg_info,
962
+					$schema_properties['raw']
963
+				);
964
+			}
965
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
966
+				$field_obj,
967
+				$field_obj->get_default_value(),
968
+				$model_version_info->requestedVersion()
969
+			);
970
+			$arg_info['sanitize_callback'] = $sanitize_callback;
971
+			$args_info[ $field_name ] = $arg_info;
972
+			if ($field_obj instanceof EE_Datetime_Field) {
973
+				$gmt_arg_info = $arg_info;
974
+				$gmt_arg_info['description'] = sprintf(
975
+					esc_html__(
976
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
977
+						'event_espresso'
978
+					),
979
+					$field_obj->get_nicename(),
980
+					$field_name
981
+				);
982
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
983
+			}
984
+		}
985
+		return $args_info;
986
+	}
987
+
988
+
989
+	/**
990
+	 * Replacement for WP API's 'rest_parse_request_arg'.
991
+	 * If the value is blank but not required, don't bother validating it.
992
+	 * Also, it uses our email validation instead of WP API's default.
993
+	 *
994
+	 * @param                 $value
995
+	 * @param WP_REST_Request $request
996
+	 * @param                 $param
997
+	 * @return bool|true|WP_Error
998
+	 * @throws InvalidArgumentException
999
+	 * @throws InvalidInterfaceException
1000
+	 * @throws InvalidDataTypeException
1001
+	 */
1002
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
1003
+	{
1004
+		$attributes = $request->get_attributes();
1005
+		if (
1006
+			! isset($attributes['args'][ $param ])
1007
+			|| ! is_array($attributes['args'][ $param ])
1008
+		) {
1009
+			$validation_result = true;
1010
+		} else {
1011
+			$args = $attributes['args'][ $param ];
1012
+			if (
1013
+				(
1014
+					$value === ''
1015
+					|| $value === null
1016
+				)
1017
+				&& (! isset($args['required'])
1018
+					|| $args['required'] === false
1019
+				)
1020
+			) {
1021
+				// not required and not provided? that's cool
1022
+				$validation_result = true;
1023
+			} elseif (
1024
+				isset($args['format'])
1025
+					  && $args['format'] === 'email'
1026
+			) {
1027
+				$validation_result = true;
1028
+				if (! EED_Core_Rest_Api::_validate_email($value)) {
1029
+					$validation_result = new WP_Error(
1030
+						'rest_invalid_param',
1031
+						esc_html__(
1032
+							'The email address is not valid or does not exist.',
1033
+							'event_espresso'
1034
+						)
1035
+					);
1036
+				}
1037
+			} else {
1038
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
1039
+			}
1040
+		}
1041
+		if (is_wp_error($validation_result)) {
1042
+			return $validation_result;
1043
+		}
1044
+		return rest_sanitize_request_arg($value, $request, $param);
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1050
+	 *
1051
+	 * @param $email
1052
+	 * @return bool
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidInterfaceException
1055
+	 * @throws InvalidDataTypeException
1056
+	 */
1057
+	protected static function _validate_email($email)
1058
+	{
1059
+		try {
1060
+			EmailAddressFactory::create($email);
1061
+			return true;
1062
+		} catch (EmailValidationException $e) {
1063
+			return false;
1064
+		}
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * Gets routes for the config
1070
+	 *
1071
+	 * @return array @see _register_model_routes
1072
+	 * @deprecated since version 4.9.1
1073
+	 */
1074
+	protected function _register_config_routes()
1075
+	{
1076
+		$config_routes = [];
1077
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1078
+			$config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1079
+				$version,
1080
+				$hidden_endpoint
1081
+			);
1082
+		}
1083
+		return $config_routes;
1084
+	}
1085
+
1086
+
1087
+	/**
1088
+	 * Gets routes for the config for the specified version
1089
+	 *
1090
+	 * @param string  $version
1091
+	 * @param boolean $hidden_endpoint
1092
+	 * @return array
1093
+	 */
1094
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1095
+	{
1096
+		return [
1097
+			'config'    => [
1098
+				[
1099
+					'callback'        => [
1100
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1101
+						'handleRequest',
1102
+					],
1103
+					'methods'         => WP_REST_Server::READABLE,
1104
+					'hidden_endpoint' => $hidden_endpoint,
1105
+					'callback_args'   => [$version],
1106
+				],
1107
+			],
1108
+			'site_info' => [
1109
+				[
1110
+					'callback'        => [
1111
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1112
+						'handleRequestSiteInfo',
1113
+					],
1114
+					'methods'         => WP_REST_Server::READABLE,
1115
+					'hidden_endpoint' => $hidden_endpoint,
1116
+					'callback_args'   => [$version],
1117
+				],
1118
+			],
1119
+		];
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 * Gets the meta info routes
1125
+	 *
1126
+	 * @return array @see _register_model_routes
1127
+	 * @deprecated since version 4.9.1
1128
+	 */
1129
+	protected function _register_meta_routes()
1130
+	{
1131
+		$meta_routes = [];
1132
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1133
+			$meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1134
+				$version,
1135
+				$hidden_endpoint
1136
+			);
1137
+		}
1138
+		return $meta_routes;
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * @param string  $version
1144
+	 * @param boolean $hidden_endpoint
1145
+	 * @return array
1146
+	 */
1147
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1148
+	{
1149
+		return [
1150
+			'resources' => [
1151
+				[
1152
+					'callback'        => [
1153
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1154
+						'handleRequestModelsMeta',
1155
+					],
1156
+					'methods'         => WP_REST_Server::READABLE,
1157
+					'hidden_endpoint' => $hidden_endpoint,
1158
+					'callback_args'   => [$version],
1159
+				],
1160
+			],
1161
+		];
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Tries to hide old 4.6 endpoints from the
1167
+	 *
1168
+	 * @param array $route_data
1169
+	 * @return array
1170
+	 * @throws EE_Error
1171
+	 * @throws ReflectionException
1172
+	 */
1173
+	public static function hide_old_endpoints($route_data)
1174
+	{
1175
+		// allow API clients to override which endpoints get hidden, in case
1176
+		// they want to discover particular endpoints
1177
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1178
+		$force_show_ee_namespace = ltrim(
1179
+			EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1180
+			'/'
1181
+		);
1182
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1183
+			foreach ($relative_urls as $resource_name => $endpoints) {
1184
+				foreach ($endpoints as $key => $endpoint) {
1185
+					// skip schema and other route options
1186
+					if (! is_numeric($key)) {
1187
+						continue;
1188
+					}
1189
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1190
+					// to $force_show_ee_namespace, in which case only show that one
1191
+					// namespace's endpoints (and hide all others)
1192
+					if (
1193
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1194
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1195
+					) {
1196
+						$full_route = '/' . ltrim($namespace, '/');
1197
+						$full_route .= '/' . ltrim($resource_name, '/');
1198
+						unset($route_data[ $full_route ]);
1199
+					}
1200
+				}
1201
+			}
1202
+		}
1203
+		return $route_data;
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * Returns an array describing which versions of core support serving requests for.
1209
+	 * Keys are core versions' major and minor version, and values are the
1210
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1211
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1212
+	 * the answers table entirely, in which case it would be very difficult for
1213
+	 * it to serve 4.6-style responses.
1214
+	 * Versions of core that are missing from this array are unknowns.
1215
+	 * previous ver
1216
+	 *
1217
+	 * @return array
1218
+	 */
1219
+	public static function version_compatibilities()
1220
+	{
1221
+		return apply_filters(
1222
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1223
+			[
1224
+				'4.8.29' => '4.8.29',
1225
+				'4.8.33' => '4.8.29',
1226
+				'4.8.34' => '4.8.29',
1227
+				'4.8.36' => '4.8.29',
1228
+			]
1229
+		);
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Gets the latest API version served. Eg if there
1235
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1236
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1237
+	 *
1238
+	 * @return string
1239
+	 */
1240
+	public static function latest_rest_api_version()
1241
+	{
1242
+		$versions_served = EED_Core_Rest_Api::versions_served();
1243
+		$versions_served_keys = array_keys($versions_served);
1244
+		return end($versions_served_keys);
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1250
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1251
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1252
+	 * We also indicate whether or not this version should be put in the index or not
1253
+	 *
1254
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1255
+	 * are whether or not they should be hidden
1256
+	 */
1257
+	public static function versions_served()
1258
+	{
1259
+		$versions_served = [];
1260
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1261
+		$lowest_compatible_version = end($possibly_served_versions);
1262
+		reset($possibly_served_versions);
1263
+		$versions_served_historically = array_keys($possibly_served_versions);
1264
+		$latest_version = end($versions_served_historically);
1265
+		reset($versions_served_historically);
1266
+		// for each version of core we have ever served:
1267
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1268
+			// if it's not above the current core version, and it's compatible with the current version of core
1269
+
1270
+			if ($key_versioned_endpoint === $latest_version) {
1271
+				// don't hide the latest version in the index
1272
+				$versions_served[ $key_versioned_endpoint ] = false;
1273
+			} elseif (
1274
+				version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1275
+				&& version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1276
+			) {
1277
+				// include, but hide, previous versions which are still supported
1278
+				$versions_served[ $key_versioned_endpoint ] = true;
1279
+			} elseif (
1280
+				apply_filters(
1281
+					'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1282
+					false,
1283
+					$possibly_served_versions
1284
+				)
1285
+			) {
1286
+				// if a version is no longer supported, don't include it in index or list of versions served
1287
+				$versions_served[ $key_versioned_endpoint ] = true;
1288
+			}
1289
+		}
1290
+		return $versions_served;
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * Gets the major and minor version of EE core's version string
1296
+	 *
1297
+	 * @return string
1298
+	 */
1299
+	public static function core_version()
1300
+	{
1301
+		return apply_filters(
1302
+			'FHEE__EED_Core_REST_API__core_version',
1303
+			implode(
1304
+				'.',
1305
+				array_slice(
1306
+					explode(
1307
+						'.',
1308
+						espresso_version()
1309
+					),
1310
+					0,
1311
+					3
1312
+				)
1313
+			)
1314
+		);
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * Gets the default limit that should be used when querying for resources
1320
+	 *
1321
+	 * @return int
1322
+	 */
1323
+	public static function get_default_query_limit()
1324
+	{
1325
+		// we actually don't use a const because we want folks to always use
1326
+		// this method, not the const directly
1327
+		return apply_filters(
1328
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1329
+			50
1330
+		);
1331
+	}
1332
+
1333
+
1334
+	/**
1335
+	 * @param string $version api version string (i.e. '4.8.36')
1336
+	 * @return array
1337
+	 */
1338
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1339
+	{
1340
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1341
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1342
+		$collection_routes = [];
1343
+		foreach ($model_names as $model_name => $model_class_name) {
1344
+			$collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1345
+															. EEH_Inflector::pluralize_and_lower($model_name);
1346
+		}
1347
+		return $collection_routes;
1348
+	}
1349
+
1350
+
1351
+	/**
1352
+	 * Returns an array of primary key names indexed by model names.
1353
+	 *
1354
+	 * @param string $version
1355
+	 * @return array
1356
+	 */
1357
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1358
+	{
1359
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1360
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1361
+		$primary_key_items = [];
1362
+		foreach ($model_names as $model_name => $model_class_name) {
1363
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1364
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1365
+				if (count($primary_keys) > 1) {
1366
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1367
+				} else {
1368
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1369
+				}
1370
+			}
1371
+		}
1372
+		return $primary_key_items;
1373
+	}
1374
+
1375
+
1376
+	/**
1377
+	 * Determines the EE REST API debug mode is activated, or not.
1378
+	 *
1379
+	 * @return bool
1380
+	 * @since 4.9.76.p
1381
+	 */
1382
+	public static function debugMode()
1383
+	{
1384
+		static $debug_mode = null; // could be class prop
1385
+		if ($debug_mode === null) {
1386
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1387
+		}
1388
+		return $debug_mode;
1389
+	}
1390
+
1391
+
1392
+	/**
1393
+	 *    run - initial module setup
1394
+	 *
1395
+	 * @access    public
1396
+	 * @param WP $WP
1397
+	 * @return    void
1398
+	 */
1399
+	public function run($WP)
1400
+	{
1401
+	}
1402 1402
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Money.helper.php 1 patch
Indentation   +220 added lines, -220 removed lines patch added patch discarded remove patch
@@ -10,236 +10,236 @@
 block discarded – undo
10 10
  */
11 11
 class EEH_Money extends EEH_Base
12 12
 {
13
-    /**
14
-     * This removes all localized money formatting from the incoming value
15
-     * Note: uses this site's currency settings for deciding what is considered a
16
-     * "thousands separator" (usually the character "," )
17
-     * and what is a "decimal mark" (usually the character ".")
18
-     *
19
-     * @param int|float|string $money_value
20
-     * @param string|null      $CNT_ISO
21
-     * @return float
22
-     * @throws EE_Error
23
-     * @throws ReflectionException
24
-     */
25
-    public static function strip_localized_money_formatting($money_value, ?string $CNT_ISO = ''): float
26
-    {
27
-        $currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
28
-        $money_value     = str_replace(
29
-            [
30
-                $currency_config->thsnds,
31
-                $currency_config->dec_mrk,
32
-            ],
33
-            [
34
-                '', // remove thousands separator
35
-                '.', // convert decimal mark to what PHP expects
36
-            ],
37
-            $money_value
38
-        );
39
-        return (float) filter_var(
40
-            $money_value,
41
-            FILTER_SANITIZE_NUMBER_FLOAT,
42
-            FILTER_FLAG_ALLOW_FRACTION
43
-        );
44
-    }
13
+	/**
14
+	 * This removes all localized money formatting from the incoming value
15
+	 * Note: uses this site's currency settings for deciding what is considered a
16
+	 * "thousands separator" (usually the character "," )
17
+	 * and what is a "decimal mark" (usually the character ".")
18
+	 *
19
+	 * @param int|float|string $money_value
20
+	 * @param string|null      $CNT_ISO
21
+	 * @return float
22
+	 * @throws EE_Error
23
+	 * @throws ReflectionException
24
+	 */
25
+	public static function strip_localized_money_formatting($money_value, ?string $CNT_ISO = ''): float
26
+	{
27
+		$currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
28
+		$money_value     = str_replace(
29
+			[
30
+				$currency_config->thsnds,
31
+				$currency_config->dec_mrk,
32
+			],
33
+			[
34
+				'', // remove thousands separator
35
+				'.', // convert decimal mark to what PHP expects
36
+			],
37
+			$money_value
38
+		);
39
+		return (float) filter_var(
40
+			$money_value,
41
+			FILTER_SANITIZE_NUMBER_FLOAT,
42
+			FILTER_FLAG_ALLOW_FRACTION
43
+		);
44
+	}
45 45
 
46 46
 
47
-    /**
48
-     * This converts an incoming localized money value into a standard float item (to three decimal places)
49
-     * Only use this if you know the $money_value follows your currency configuration's
50
-     * settings. Note: this uses this site's currency settings for deciding what is considered a
51
-     * "thousands separator" (usually the character "," )
52
-     * and what is a "decimal mark" (usually the character ".")
53
-     *
54
-     * @param int|float|string $money_value
55
-     * @return float
56
-     * @throws EE_Error
57
-     * @throws ReflectionException
58
-     */
59
-    public static function convert_to_float_from_localized_money($money_value): float
60
-    {
61
-        // float it! and round to three decimal places
62
-        return round(EEH_Money::strip_localized_money_formatting($money_value), 3);
63
-    }
47
+	/**
48
+	 * This converts an incoming localized money value into a standard float item (to three decimal places)
49
+	 * Only use this if you know the $money_value follows your currency configuration's
50
+	 * settings. Note: this uses this site's currency settings for deciding what is considered a
51
+	 * "thousands separator" (usually the character "," )
52
+	 * and what is a "decimal mark" (usually the character ".")
53
+	 *
54
+	 * @param int|float|string $money_value
55
+	 * @return float
56
+	 * @throws EE_Error
57
+	 * @throws ReflectionException
58
+	 */
59
+	public static function convert_to_float_from_localized_money($money_value): float
60
+	{
61
+		// float it! and round to three decimal places
62
+		return round(EEH_Money::strip_localized_money_formatting($money_value), 3);
63
+	}
64 64
 
65 65
 
66
-    /**
67
-     * For comparing floats. Default operator is '=', but see the $operator below for all options.
68
-     * This should be used to compare floats instead of normal '==' because floats
69
-     * are inherently imprecise, and so you can sometimes have two floats that appear to be identical
70
-     * but actually differ by 0.00000001.
71
-     *
72
-     * @see http://biostall.com/php-function-to-compare-floating-point-numbers
73
-     * @param int|float|string $float1
74
-     * @param int|float|string $float2
75
-     * @param string|null      $operator The operator. Valid options are =, <=, <, >=, >, <>, eq, lt, lte, gt, gte, ne
76
-     * @return bool whether the equation is true or false
77
-     * @throws EE_Error
78
-     */
79
-    public static function compare_floats($float1, $float2, ?string $operator = '='): bool
80
-    {
81
-        // Check numbers to 5 digits of precision
82
-        $epsilon = 0.00001;
83
-        $float1  = (float) $float1;
84
-        $float2  = (float) $float2;
85
-        switch ($operator) {
86
-            // equal
87
-            case '=':
88
-            case '==':
89
-            case '===':
90
-            case 'eq':
91
-                if (abs($float1 - $float2) < $epsilon) {
92
-                    return true;
93
-                }
94
-                break;
95
-            // less than
96
-            case '<':
97
-            case 'lt':
98
-                if (abs($float1 - $float2) < $epsilon) {
99
-                    return false;
100
-                }
101
-                if ($float1 < $float2) {
102
-                    return true;
103
-                }
104
-                break;
105
-            // less than or equal
106
-            case '<=':
107
-            case 'lte':
108
-                if (
109
-                    self::compare_floats($float1, $float2, '<')
110
-                    || self::compare_floats($float1, $float2)
111
-                ) {
112
-                    return true;
113
-                }
114
-                break;
115
-            // greater than
116
-            case '>':
117
-            case 'gt':
118
-                if (abs($float1 - $float2) < $epsilon) {
119
-                    return false;
120
-                }
121
-                if ($float1 > $float2) {
122
-                    return true;
123
-                }
124
-                break;
125
-            // greater than or equal
126
-            case '>=':
127
-            case 'gte':
128
-                if (
129
-                    self::compare_floats($float1, $float2, '>')
130
-                    || self::compare_floats($float1, $float2)
131
-                ) {
132
-                    return true;
133
-                }
134
-                break;
135
-            case '<>':
136
-            case '!=':
137
-            case '!==':
138
-            case 'ne':
139
-                if (abs($float1 - $float2) > $epsilon) {
140
-                    return true;
141
-                }
142
-                break;
143
-            default:
144
-                throw new EE_Error(
145
-                    sprintf(
146
-                        esc_html__(
147
-                            "Unknown operator %s in EEH_Money::compare_floats()",
148
-                            'event_espresso'
149
-                        ),
150
-                        $operator
151
-                    )
152
-                );
153
-        }
154
-        return false;
155
-    }
66
+	/**
67
+	 * For comparing floats. Default operator is '=', but see the $operator below for all options.
68
+	 * This should be used to compare floats instead of normal '==' because floats
69
+	 * are inherently imprecise, and so you can sometimes have two floats that appear to be identical
70
+	 * but actually differ by 0.00000001.
71
+	 *
72
+	 * @see http://biostall.com/php-function-to-compare-floating-point-numbers
73
+	 * @param int|float|string $float1
74
+	 * @param int|float|string $float2
75
+	 * @param string|null      $operator The operator. Valid options are =, <=, <, >=, >, <>, eq, lt, lte, gt, gte, ne
76
+	 * @return bool whether the equation is true or false
77
+	 * @throws EE_Error
78
+	 */
79
+	public static function compare_floats($float1, $float2, ?string $operator = '='): bool
80
+	{
81
+		// Check numbers to 5 digits of precision
82
+		$epsilon = 0.00001;
83
+		$float1  = (float) $float1;
84
+		$float2  = (float) $float2;
85
+		switch ($operator) {
86
+			// equal
87
+			case '=':
88
+			case '==':
89
+			case '===':
90
+			case 'eq':
91
+				if (abs($float1 - $float2) < $epsilon) {
92
+					return true;
93
+				}
94
+				break;
95
+			// less than
96
+			case '<':
97
+			case 'lt':
98
+				if (abs($float1 - $float2) < $epsilon) {
99
+					return false;
100
+				}
101
+				if ($float1 < $float2) {
102
+					return true;
103
+				}
104
+				break;
105
+			// less than or equal
106
+			case '<=':
107
+			case 'lte':
108
+				if (
109
+					self::compare_floats($float1, $float2, '<')
110
+					|| self::compare_floats($float1, $float2)
111
+				) {
112
+					return true;
113
+				}
114
+				break;
115
+			// greater than
116
+			case '>':
117
+			case 'gt':
118
+				if (abs($float1 - $float2) < $epsilon) {
119
+					return false;
120
+				}
121
+				if ($float1 > $float2) {
122
+					return true;
123
+				}
124
+				break;
125
+			// greater than or equal
126
+			case '>=':
127
+			case 'gte':
128
+				if (
129
+					self::compare_floats($float1, $float2, '>')
130
+					|| self::compare_floats($float1, $float2)
131
+				) {
132
+					return true;
133
+				}
134
+				break;
135
+			case '<>':
136
+			case '!=':
137
+			case '!==':
138
+			case 'ne':
139
+				if (abs($float1 - $float2) > $epsilon) {
140
+					return true;
141
+				}
142
+				break;
143
+			default:
144
+				throw new EE_Error(
145
+					sprintf(
146
+						esc_html__(
147
+							"Unknown operator %s in EEH_Money::compare_floats()",
148
+							'event_espresso'
149
+						),
150
+						$operator
151
+					)
152
+				);
153
+		}
154
+		return false;
155
+	}
156 156
 
157 157
 
158
-    /**
159
-     * This returns a localized format string suitable for jQplot.
160
-     *
161
-     * @param string|null $CNT_ISO If this is provided, then will attempt to get the currency settings for the country.
162
-     *                             Otherwise will use currency settings for current active country on site.
163
-     * @return string
164
-     * @throws EE_Error
165
-     * @throws ReflectionException
166
-     */
167
-    public static function get_format_for_jqplot(?string $CNT_ISO = ''): string
168
-    {
169
-        // default format
170
-        $format          = 'f';
171
-        $currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
172
-        // first get the decimal place and number of places
173
-        $format = "%'." . $currency_config->dec_plc . $format;
174
-        // currency symbol on right side.
175
-        return $currency_config->sign_b4 ? $currency_config->sign . $format : $format . $currency_config->sign;
176
-    }
158
+	/**
159
+	 * This returns a localized format string suitable for jQplot.
160
+	 *
161
+	 * @param string|null $CNT_ISO If this is provided, then will attempt to get the currency settings for the country.
162
+	 *                             Otherwise will use currency settings for current active country on site.
163
+	 * @return string
164
+	 * @throws EE_Error
165
+	 * @throws ReflectionException
166
+	 */
167
+	public static function get_format_for_jqplot(?string $CNT_ISO = ''): string
168
+	{
169
+		// default format
170
+		$format          = 'f';
171
+		$currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
172
+		// first get the decimal place and number of places
173
+		$format = "%'." . $currency_config->dec_plc . $format;
174
+		// currency symbol on right side.
175
+		return $currency_config->sign_b4 ? $currency_config->sign . $format : $format . $currency_config->sign;
176
+	}
177 177
 
178 178
 
179
-    /**
180
-     * This returns a localized format string suitable for usage with the Google Charts API format param.
181
-     *
182
-     * @param string|null $CNT_ISO If this is provided, then will attempt to get the currency settings for the country.
183
-     *                             Otherwise will use currency settings for current active country on site.
184
-     *                             Note: GoogleCharts uses ICU pattern set
185
-     *                             (@return array
186
-     * @return array
187
-     * @throws EE_Error
188
-     * @throws ReflectionException
189
-     * @see http://icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
190
-     */
191
-    public static function get_format_for_google_charts(?string $CNT_ISO = ''): array
192
-    {
193
-        $currency_config            = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
194
-        $decimal_places_placeholder = str_pad('', $currency_config->dec_plc, '0');
195
-        // first get the decimal place and number of places
196
-        $format = '#,##0.' . $decimal_places_placeholder;
197
-        // currency symbol on right side.
198
-        $format          = $currency_config->sign_b4
199
-            ? $currency_config->sign . $format
200
-            : $format
201
-              . $currency_config->sign;
202
-        $formatterObject = [
203
-            'decimalSymbol'  => $currency_config->dec_mrk,
204
-            'groupingSymbol' => $currency_config->thsnds,
205
-            'fractionDigits' => $currency_config->dec_plc,
206
-        ];
207
-        if ($currency_config->sign_b4) {
208
-            $formatterObject['prefix'] = $currency_config->sign;
209
-        } else {
210
-            $formatterObject['suffix'] = $currency_config->sign;
211
-        }
212
-        return [
213
-            'format'          => $format,
214
-            'formatterObject' => $formatterObject,
215
-        ];
216
-    }
179
+	/**
180
+	 * This returns a localized format string suitable for usage with the Google Charts API format param.
181
+	 *
182
+	 * @param string|null $CNT_ISO If this is provided, then will attempt to get the currency settings for the country.
183
+	 *                             Otherwise will use currency settings for current active country on site.
184
+	 *                             Note: GoogleCharts uses ICU pattern set
185
+	 *                             (@return array
186
+	 * @return array
187
+	 * @throws EE_Error
188
+	 * @throws ReflectionException
189
+	 * @see http://icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
190
+	 */
191
+	public static function get_format_for_google_charts(?string $CNT_ISO = ''): array
192
+	{
193
+		$currency_config            = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
194
+		$decimal_places_placeholder = str_pad('', $currency_config->dec_plc, '0');
195
+		// first get the decimal place and number of places
196
+		$format = '#,##0.' . $decimal_places_placeholder;
197
+		// currency symbol on right side.
198
+		$format          = $currency_config->sign_b4
199
+			? $currency_config->sign . $format
200
+			: $format
201
+			  . $currency_config->sign;
202
+		$formatterObject = [
203
+			'decimalSymbol'  => $currency_config->dec_mrk,
204
+			'groupingSymbol' => $currency_config->thsnds,
205
+			'fractionDigits' => $currency_config->dec_plc,
206
+		];
207
+		if ($currency_config->sign_b4) {
208
+			$formatterObject['prefix'] = $currency_config->sign;
209
+		} else {
210
+			$formatterObject['suffix'] = $currency_config->sign;
211
+		}
212
+		return [
213
+			'format'          => $format,
214
+			'formatterObject' => $formatterObject,
215
+		];
216
+	}
217 217
 
218 218
 
219
-    /**
220
-     * @param string|null $CNT_ISO
221
-     * @return EE_Currency_Config
222
-     * @throws EE_Error
223
-     * @throws ReflectionException
224
-     */
225
-    public static function get_currency_config(?string $CNT_ISO = ''): EE_Currency_Config
226
-    {
227
-        return EE_Currency_Config::getCurrencyConfig($CNT_ISO);
228
-    }
219
+	/**
220
+	 * @param string|null $CNT_ISO
221
+	 * @return EE_Currency_Config
222
+	 * @throws EE_Error
223
+	 * @throws ReflectionException
224
+	 */
225
+	public static function get_currency_config(?string $CNT_ISO = ''): EE_Currency_Config
226
+	{
227
+		return EE_Currency_Config::getCurrencyConfig($CNT_ISO);
228
+	}
229 229
 
230 230
 
231
-    /**
232
-     * @param string|null $CNT_ISO
233
-     * @param bool        $as_decimal if false [default] will return the number of decimal places ex: 1, 2, 3
234
-     *                                if true, will return the subunits as a decimal fraction ex: .1, .01, .001
235
-     * @return float
236
-     * @throws EE_Error
237
-     * @throws ReflectionException
238
-     * @since $VID:$
239
-     */
240
-    public static function getCurrencySubUnits(?string $CNT_ISO = '', bool $as_decimal = false): float
241
-    {
242
-        $currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
243
-        return $as_decimal ? pow(10, ($currency_config->dec_plc * -1)) : $currency_config->dec_plc;
244
-    }
231
+	/**
232
+	 * @param string|null $CNT_ISO
233
+	 * @param bool        $as_decimal if false [default] will return the number of decimal places ex: 1, 2, 3
234
+	 *                                if true, will return the subunits as a decimal fraction ex: .1, .01, .001
235
+	 * @return float
236
+	 * @throws EE_Error
237
+	 * @throws ReflectionException
238
+	 * @since $VID:$
239
+	 */
240
+	public static function getCurrencySubUnits(?string $CNT_ISO = '', bool $as_decimal = false): float
241
+	{
242
+		$currency_config = EE_Currency_Config::getCurrencyConfig($CNT_ISO);
243
+		return $as_decimal ? pow(10, ($currency_config->dec_plc * -1)) : $currency_config->dec_plc;
244
+	}
245 245
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +838 added lines, -838 removed lines patch added patch discarded remove patch
@@ -12,842 +12,842 @@
 block discarded – undo
12 12
  */
13 13
 class EEM_Datetime extends EEM_Soft_Delete_Base
14 14
 {
15
-    /**
16
-     * @var EEM_Datetime $_instance
17
-     */
18
-    protected static $_instance;
19
-
20
-
21
-    /**
22
-     * private constructor to prevent direct creation
23
-     *
24
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
25
-     *                         (and any incoming timezone data that gets saved).
26
-     *                         Note this just sends the timezone info to the date time model field objects.
27
-     *                         Default is NULL
28
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
29
-     * @throws EE_Error
30
-     * @throws InvalidArgumentException
31
-     * @throws InvalidArgumentException
32
-     */
33
-    protected function __construct($timezone)
34
-    {
35
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
36
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
37
-        $this->_tables                 = [
38
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
39
-        ];
40
-        $this->_fields                 = [
41
-            'Datetime' => [
42
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
43
-                    'DTT_ID',
44
-                    esc_html__('Datetime ID', 'event_espresso')
45
-                ),
46
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
47
-                    'EVT_ID',
48
-                    esc_html__('Event ID', 'event_espresso'),
49
-                    false,
50
-                    0,
51
-                    'Event'
52
-                ),
53
-                'VNU_ID' => new EE_Foreign_Key_Int_Field(
54
-                    'VNU_ID',
55
-                    __('Venue ID', 'event_espresso'),
56
-                    false,
57
-                    0,
58
-                    'Venue'
59
-                ),
60
-                'DTT_name'        => new EE_Plain_Text_Field(
61
-                    'DTT_name',
62
-                    esc_html__('Datetime Name', 'event_espresso'),
63
-                    false,
64
-                    ''
65
-                ),
66
-                'DTT_description' => new EE_Post_Content_Field(
67
-                    'DTT_description',
68
-                    esc_html__('Description for Datetime', 'event_espresso'),
69
-                    false,
70
-                    ''
71
-                ),
72
-                'DTT_EVT_start'   => new EE_Datetime_Field(
73
-                    'DTT_EVT_start',
74
-                    esc_html__('Start time/date of Event', 'event_espresso'),
75
-                    false,
76
-                    EE_Datetime_Field::now,
77
-                    $timezone
78
-                ),
79
-                'DTT_EVT_end'     => new EE_Datetime_Field(
80
-                    'DTT_EVT_end',
81
-                    esc_html__('End time/date of Event', 'event_espresso'),
82
-                    false,
83
-                    EE_Datetime_Field::now,
84
-                    $timezone
85
-                ),
86
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
87
-                    'DTT_reg_limit',
88
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
89
-                    true,
90
-                    EE_INF
91
-                ),
92
-                'DTT_sold'        => new EE_Integer_Field(
93
-                    'DTT_sold',
94
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
95
-                    true,
96
-                    0
97
-                ),
98
-                'DTT_reserved'    => new EE_Integer_Field(
99
-                    'DTT_reserved',
100
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
101
-                    false,
102
-                    0
103
-                ),
104
-                'DTT_is_primary'  => new EE_Boolean_Field(
105
-                    'DTT_is_primary',
106
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
107
-                    false,
108
-                    false
109
-                ),
110
-                'DTT_order'       => new EE_Integer_Field(
111
-                    'DTT_order',
112
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
113
-                    false,
114
-                    0
115
-                ),
116
-                'DTT_parent'      => new EE_Integer_Field(
117
-                    'DTT_parent',
118
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
119
-                    true,
120
-                    0
121
-                ),
122
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
123
-                    'DTT_deleted',
124
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
125
-                    false,
126
-                    false
127
-                ),
128
-            ],
129
-        ];
130
-        $this->_model_relations        = [
131
-            'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
132
-            'Event'           => new EE_Belongs_To_Relation(),
133
-            'Checkin'         => new EE_Has_Many_Relation(),
134
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
135
-            'Venue'           => new EE_Belongs_To_Relation(),
136
-        ];
137
-        $path_to_event_model           = 'Event';
138
-        $this->model_chain_to_password = $path_to_event_model;
139
-        $this->_model_chain_to_wp_user = $path_to_event_model;
140
-        // this model is generally available for reading
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
142
-            new EE_Restriction_Generator_Event_Related_Public(
143
-                $path_to_event_model
144
-            );
145
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
146
-            new EE_Restriction_Generator_Event_Related_Protected(
147
-                $path_to_event_model
148
-            );
149
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
150
-            new EE_Restriction_Generator_Event_Related_Protected(
151
-                $path_to_event_model
152
-            );
153
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
154
-            new EE_Restriction_Generator_Event_Related_Protected(
155
-                $path_to_event_model,
156
-                EEM_Base::caps_edit
157
-            );
158
-        parent::__construct($timezone);
159
-    }
160
-
161
-
162
-    /**
163
-     * create new blank datetime
164
-     *
165
-     * @access public
166
-     * @return EE_Datetime[] array on success, FALSE on fail
167
-     * @throws EE_Error
168
-     * @throws InvalidArgumentException
169
-     * @throws InvalidDataTypeException
170
-     * @throws ReflectionException
171
-     * @throws InvalidInterfaceException
172
-     */
173
-    public function create_new_blank_datetime()
174
-    {
175
-        // makes sure timezone is always set.
176
-        $timezone_string = $this->get_timezone();
177
-        /**
178
-         * Filters the initial start date for the new datetime.
179
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
180
-         *
181
-         * @param int $start_date Unix timestamp representing now + 30 days in seconds.
182
-         * @return int Unix timestamp
183
-         */
184
-        $start_date = apply_filters(
185
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
186
-            $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
187
-        );
188
-        /**
189
-         * Filters the initial end date for the new datetime.
190
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
191
-         *
192
-         * @param int $end_data Unix timestamp representing now + 30 days in seconds.
193
-         * @return int Unix timestamp
194
-         */
195
-        $end_date       = apply_filters(
196
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
197
-            $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
198
-        );
199
-        $blank_datetime = EE_Datetime::new_instance(
200
-            [
201
-                'DTT_EVT_start' => $start_date,
202
-                'DTT_EVT_end'   => $end_date,
203
-                'DTT_order'     => 1,
204
-                'DTT_reg_limit' => EE_INF,
205
-            ],
206
-            $timezone_string
207
-        );
208
-        /**
209
-         * Filters the initial start time and format for the new EE_Datetime instance.
210
-         *
211
-         * @param array $start_time An array having size 2.  First element is the time, second element is the time
212
-         *                          format.
213
-         * @return array
214
-         */
215
-        $start_time = apply_filters(
216
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
217
-            ['8am', 'ga']
218
-        );
219
-        /**
220
-         * Filters the initial end time and format for the new EE_Datetime instance.
221
-         *
222
-         * @param array $end_time An array having size 2.  First element is the time, second element is the time
223
-         *                        format
224
-         * @return array
225
-         */
226
-        $end_time = apply_filters(
227
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
228
-            ['5pm', 'ga']
229
-        );
230
-        $this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
231
-        $blank_datetime->set_start_time(
232
-            $this->convert_datetime_for_query(
233
-                'DTT_EVT_start',
234
-                $start_time[0],
235
-                $start_time[1],
236
-                $timezone_string
237
-            )
238
-        );
239
-        $blank_datetime->set_end_time(
240
-            $this->convert_datetime_for_query(
241
-                'DTT_EVT_end',
242
-                $end_time[0],
243
-                $end_time[1],
244
-                $timezone_string
245
-            )
246
-        );
247
-        return [$blank_datetime];
248
-    }
249
-
250
-
251
-    /**
252
-     * Validates whether the start_time and end_time are in the expected format.
253
-     *
254
-     * @param array $start_time
255
-     * @param array $end_time
256
-     * @throws InvalidArgumentException
257
-     * @throws InvalidDataTypeException
258
-     */
259
-    private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
260
-    {
261
-        if (! is_array($start_time)) {
262
-            throw new InvalidDataTypeException('start_time', $start_time, 'array');
263
-        }
264
-        if (! is_array($end_time)) {
265
-            throw new InvalidDataTypeException('end_time', $end_time, 'array');
266
-        }
267
-        if (count($start_time) !== 2) {
268
-            throw new InvalidArgumentException(
269
-                sprintf(
270
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
271
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
272
-                    '$start_time'
273
-                )
274
-            );
275
-        }
276
-        if (count($end_time) !== 2) {
277
-            throw new InvalidArgumentException(
278
-                sprintf(
279
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
280
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
281
-                    '$end_time'
282
-                )
283
-            );
284
-        }
285
-    }
286
-
287
-
288
-    /**
289
-     * get event start date from db
290
-     *
291
-     * @access public
292
-     * @param int $EVT_ID
293
-     * @return EE_Datetime[] array on success, FALSE on fail
294
-     * @throws EE_Error
295
-     * @throws ReflectionException
296
-     */
297
-    public function get_all_event_dates($EVT_ID = 0)
298
-    {
299
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
300
-            return $this->create_new_blank_datetime();
301
-        }
302
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
303
-        if (empty($results)) {
304
-            return $this->create_new_blank_datetime();
305
-        }
306
-        return $results;
307
-    }
308
-
309
-
310
-    /**
311
-     * get all datetimes attached to an event ordered by the DTT_order field
312
-     *
313
-     * @public
314
-     * @param int     $EVT_ID     event id
315
-     * @param boolean $include_expired
316
-     * @param boolean $include_deleted
317
-     * @param int     $limit      If included then limit the count of results by
318
-     *                            the given number
319
-     * @return EE_Datetime[]
320
-     * @throws EE_Error
321
-     */
322
-    public function get_datetimes_for_event_ordered_by_DTT_order(
323
-        int $EVT_ID,
324
-        bool $include_expired = true,
325
-        bool $include_deleted = true,
326
-        $limit = 0
327
-    ) {
328
-        $prev_data_prep_value = $this->prepModelForQuery();
329
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
330
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
331
-        $query_params         = $this->addDefaultWhereConditions($query_params);
332
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
333
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
334
-    }
335
-
336
-
337
-    /**
338
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
339
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
340
-     * and then the earlier datetimes are the most important.
341
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
342
-     *
343
-     * @param int $EVT_ID
344
-     * @param int $limit
345
-     * @return EE_Datetime[]|EE_Base_Class[]
346
-     * @throws EE_Error
347
-     */
348
-    public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, $limit = 0)
349
-    {
350
-        $query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
351
-        $query_params    = $this->addDefaultWhereConditions($query_params);
352
-        $query_params    = $this->addDefaultQueryParams($query_params, $limit);
353
-        return $this->get_all($query_params);
354
-    }
355
-
356
-
357
-    /**
358
-     * @param int     $EVT_ID
359
-     * @param boolean $include_expired
360
-     * @param boolean $include_deleted
361
-     * @return EE_Datetime
362
-     * @throws EE_Error
363
-     */
364
-    public function get_oldest_datetime_for_event(
365
-        int $EVT_ID,
366
-        bool $include_expired = false,
367
-        bool $include_deleted = false
368
-    ) {
369
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
370
-            $EVT_ID,
371
-            $include_expired,
372
-            $include_deleted,
373
-            1
374
-        );
375
-        if ($results) {
376
-            return array_shift($results);
377
-        }
378
-        return null;
379
-    }
380
-
381
-
382
-    /**
383
-     * Gets the 'primary' datetime for an event.
384
-     *
385
-     * @param int  $EVT_ID
386
-     * @param bool $try_to_exclude_expired
387
-     * @param bool $try_to_exclude_deleted
388
-     * @return EE_Datetime
389
-     * @throws EE_Error
390
-     */
391
-    public function get_primary_datetime_for_event(
392
-        int $EVT_ID,
393
-        bool $try_to_exclude_expired = true,
394
-        bool $try_to_exclude_deleted = true
395
-    ) {
396
-        if ($try_to_exclude_expired) {
397
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
398
-            if ($non_expired) {
399
-                return $non_expired;
400
-            }
401
-        }
402
-        if ($try_to_exclude_deleted) {
403
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
404
-            if ($expired_even) {
405
-                return $expired_even;
406
-            }
407
-        }
408
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
409
-    }
410
-
411
-
412
-    /**
413
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
414
-     * only by start date
415
-     *
416
-     * @param int     $EVT_ID
417
-     * @param boolean $include_expired
418
-     * @param boolean $include_deleted
419
-     * @param int     $limit
420
-     * @return EE_Datetime[]
421
-     * @throws EE_Error
422
-     */
423
-    public function get_datetimes_for_event_ordered_by_start_time(
424
-        int $EVT_ID,
425
-        bool $include_expired = true,
426
-        bool $include_deleted = true,
427
-        $limit = 0
428
-    ) {
429
-        $prev_data_prep_value = $this->prepModelForQuery();
430
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
431
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
432
-        $query_params         = $this->addDefaultWhereConditions(
433
-            $query_params,
434
-            EEM_Base::default_where_conditions_this_only
435
-        );
436
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
437
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
438
-    }
439
-
440
-
441
-    /**
442
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
443
-     * only by start date
444
-     *
445
-     * @param int     $TKT_ID
446
-     * @param boolean $include_expired
447
-     * @param boolean $include_deleted
448
-     * @param int     $limit
449
-     * @return EE_Datetime[]
450
-     * @throws EE_Error
451
-     */
452
-    public function get_datetimes_for_ticket_ordered_by_start_time(
453
-        int $TKT_ID,
454
-        bool $include_expired = true,
455
-        bool $include_deleted = true,
456
-        $limit = 0
457
-    ) {
458
-        $prev_data_prep_value = $this->prepModelForQuery();
459
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
460
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
461
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit);
462
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
463
-    }
464
-
465
-
466
-    /**
467
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
468
-     * datetimes.
469
-     *
470
-     * @param int      $TKT_ID           ID of ticket to retrieve the datetimes for
471
-     * @param boolean  $include_expired  whether to include expired datetimes or not
472
-     * @param boolean  $include_deleted  whether to include trashed datetimes or not.
473
-     * @param int|null $limit            if null, no limit, if int then limit results by
474
-     *                                   that number
475
-     * @return EE_Datetime[]
476
-     * @throws EE_Error
477
-     */
478
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
479
-        int $TKT_ID,
480
-        bool $include_expired = true,
481
-        bool $include_deleted = true,
482
-        $limit = 0
483
-    ) {
484
-        $prev_data_prep_value = $this->prepModelForQuery();
485
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
486
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
487
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
488
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
494
-     * reason it doesn't exist, we consider the earliest event the most important)
495
-     *
496
-     * @param int $EVT_ID
497
-     * @return EE_Datetime
498
-     * @throws EE_Error
499
-     */
500
-    public function get_most_important_datetime_for_event(int $EVT_ID)
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 stdClass[]
525
-     * @throws EE_Error
526
-     * @throws InvalidArgumentException
527
-     * @throws InvalidArgumentException
528
-     */
529
-    public function get_dtt_months_and_years(array $where_params, $evt_active_status = '')
530
-    {
531
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
532
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
533
-        switch ($evt_active_status) {
534
-            case 'upcoming':
535
-                $where_params['Event.status'] = 'publish';
536
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
537
-                if (isset($where_params['DTT_EVT_start'])) {
538
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
539
-                }
540
-                $where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
541
-                break;
542
-            case 'expired':
543
-                if (isset($where_params['Event.status'])) {
544
-                    unset($where_params['Event.status']);
545
-                }
546
-                // get events to exclude
547
-                $exclude_query[0] = array_merge(
548
-                    $where_params,
549
-                    ['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
550
-                );
551
-                // first get all events that have datetimes where its not expired.
552
-                $event_ids = $this->_get_all_wpdb_results(
553
-                    $exclude_query,
554
-                    OBJECT_K,
555
-                    'Datetime.EVT_ID'
556
-                );
557
-                $event_ids = array_keys($event_ids);
558
-                if (isset($where_params['DTT_EVT_end'])) {
559
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
560
-                }
561
-                $where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
562
-                $where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
563
-                break;
564
-            case 'active':
565
-                $where_params['Event.status'] = 'publish';
566
-                if (isset($where_params['DTT_EVT_start'])) {
567
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
568
-                }
569
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
570
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
571
-                }
572
-                $where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
573
-                $where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
574
-                break;
575
-            case 'inactive':
576
-                if (isset($where_params['Event.status'])) {
577
-                    unset($where_params['Event.status']);
578
-                }
579
-                if (isset($where_params['OR'])) {
580
-                    $where_params['AND']['OR'] = $where_params['OR'];
581
-                }
582
-                if (isset($where_params['DTT_EVT_end'])) {
583
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
584
-                    unset($where_params['DTT_EVT_end']);
585
-                }
586
-                if (isset($where_params['DTT_EVT_start'])) {
587
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
588
-                    unset($where_params['DTT_EVT_start']);
589
-                }
590
-                $where_params['AND']['Event.status'] = ['!=', 'publish'];
591
-                break;
592
-        }
593
-        $query_params[0]          = $where_params;
594
-        $query_params['group_by'] = ['dtt_year', 'dtt_month'];
595
-        $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
596
-
597
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
598
-            $this->get_timezone(),
599
-            'DTT_EVT_start'
600
-        );
601
-        $columns_to_select = [
602
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
603
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
604
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
605
-        ];
606
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
607
-    }
608
-
609
-
610
-    /**
611
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
612
-     * for the tickets for each datetime)
613
-     *
614
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
615
-     * @throws EE_Error
616
-     * @throws ReflectionException
617
-     */
618
-    public function update_sold(array $datetimes)
619
-    {
620
-        EE_Error::doing_it_wrong(
621
-            __FUNCTION__,
622
-            esc_html__(
623
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
624
-                'event_espresso'
625
-            ),
626
-            '4.9.32.rc.005'
627
-        );
628
-        foreach ($datetimes as $datetime) {
629
-            $datetime->update_sold();
630
-        }
631
-    }
632
-
633
-
634
-    /**
635
-     *    Gets the total number of tickets available at a particular datetime
636
-     *    (does NOT take into account the datetime's spaces available)
637
-     *
638
-     * @param int   $DTT_ID
639
-     * @param array $query_params
640
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
641
-     *             tickets attached to datetime then FALSE is returned.
642
-     * @throws EE_Error
643
-     * @throws ReflectionException
644
-     */
645
-    public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = [])
646
-    {
647
-        $datetime = $this->get_one_by_ID($DTT_ID);
648
-        if ($datetime instanceof EE_Datetime) {
649
-            return $datetime->tickets_remaining($query_params);
650
-        }
651
-        return 0;
652
-    }
653
-
654
-
655
-    /**
656
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
657
-     *
658
-     * @param array $stati_to_include  If included you can restrict the statuses we return counts for by including the
659
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
660
-     *                                 for all valid stati.
661
-     * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
662
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
663
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
664
-     * @throws EE_Error
665
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
666
-     *                                 EE_Datetime::expired
667
-     */
668
-    public function get_datetime_counts_by_status(array $stati_to_include = [], array $query_params = [])
669
-    {
670
-        // only accept where conditions for this query.
671
-        $_where            = isset($query_params[0]) ? $query_params[0] : [];
672
-        $status_query_args = [
673
-            EE_Datetime::active   => array_merge(
674
-                $_where,
675
-                ['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
676
-            ),
677
-            EE_Datetime::upcoming => array_merge(
678
-                $_where,
679
-                ['DTT_EVT_start' => ['>', time()]]
680
-            ),
681
-            EE_Datetime::expired  => array_merge(
682
-                $_where,
683
-                ['DTT_EVT_end' => ['<', time()]]
684
-            ),
685
-        ];
686
-        if (! empty($stati_to_include)) {
687
-            foreach (array_keys($status_query_args) as $status) {
688
-                if (! in_array($status, $stati_to_include, true)) {
689
-                    unset($status_query_args[ $status ]);
690
-                }
691
-            }
692
-        }
693
-        // loop through and query counts for each stati.
694
-        $status_query_results = [];
695
-        foreach ($status_query_args as $status => $status_where_conditions) {
696
-            $status_query_results[ $status ] = EEM_Datetime::count(
697
-                [$status_where_conditions],
698
-                'DTT_ID',
699
-                true
700
-            );
701
-        }
702
-        return $status_query_results;
703
-    }
704
-
705
-
706
-    /**
707
-     * Returns the specific count for a given Datetime status matching any given query_params.
708
-     *
709
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
710
-     * @param array  $query_params
711
-     * @return int
712
-     * @throws EE_Error
713
-     */
714
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = [])
715
-    {
716
-        $count = $this->get_datetime_counts_by_status([$status], $query_params);
717
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
718
-    }
719
-
720
-
721
-    /**
722
-     * @return bool|int
723
-     * @since   $VID:$
724
-     */
725
-    private function prepModelForQuery()
726
-    {
727
-        $prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
728
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
729
-        return $prev_data_prep_value;
730
-    }
731
-
732
-
733
-    /**
734
-     * @param array    $query_params
735
-     * @param bool|int $prev_data_prep_value
736
-     * @return EE_Base_Class[]|EE_Datetime[]
737
-     * @throws EE_Error
738
-     * @since   $VID:$
739
-     */
740
-    private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value)
741
-    {
742
-        $result = $this->get_all($query_params);
743
-        $this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
744
-        return $result;
745
-    }
746
-
747
-
748
-    /**
749
-     * @param array  $query_params
750
-     * @param int    $limit
751
-     * @param string $order_by
752
-     * @param string $order
753
-     * @return array
754
-     * @since   $VID:$
755
-     */
756
-    private function addDefaultQueryParams(array $query_params, $limit = 0, $order_by = 'DTT_EVT_start', $order = 'ASC')
757
-    {
758
-        $query_params = $this->addOrderByQueryParams($query_params, $order_by, $order);
759
-        $query_params = $this->addLimitQueryParams($query_params, $limit);
760
-        return $query_params;
761
-    }
762
-
763
-
764
-    /**
765
-     * @param array  $query_params
766
-     * @param string $default_where_conditions
767
-     * @return array
768
-     * @since   $VID:$
769
-     */
770
-    private function addDefaultWhereConditions(
771
-        array $query_params,
772
-        $default_where_conditions = EEM_Base::default_where_conditions_none
773
-    ) {
774
-        $query_params['default_where_conditions'] = $default_where_conditions;
775
-        return $query_params;
776
-    }
777
-
778
-
779
-    /**
780
-     * @param array $where_params
781
-     * @param bool  $include_deleted
782
-     * @param bool  $include_expired
783
-     * @return array
784
-     * @since   $VID:$
785
-     */
786
-    private function addDefaultWhereParams(array $where_params, bool $include_deleted = true, bool $include_expired = true)
787
-    {
788
-        $where_params = $this->addExpiredWhereParams($where_params, $include_expired);
789
-        $where_params = $this->addDeletedWhereParams($where_params, $include_deleted);
790
-        return $where_params;
791
-    }
792
-
793
-
794
-    /**
795
-     * @param array $where_params
796
-     * @param bool  $include_deleted
797
-     * @return array
798
-     * @since   $VID:$
799
-     */
800
-    private function addDeletedWhereParams(array $where_params, bool $include_deleted = true)
801
-    {
802
-        $deleted                     = $include_deleted ? [true, false] : [false];
803
-        $where_params['DTT_deleted'] = ['IN', $deleted];
804
-        return $where_params;
805
-    }
806
-
807
-
808
-    /**
809
-     * @param array $where_params
810
-     * @param bool  $include_expired
811
-     * @return array
812
-     * @since   $VID:$
813
-     */
814
-    private function addExpiredWhereParams(array $where_params, bool $include_expired = true)
815
-    {
816
-        if (! $include_expired) {
817
-            $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
818
-        }
819
-        return $where_params;
820
-    }
821
-
822
-
823
-    /**
824
-     * @param array $query_params
825
-     * @param int   $limit
826
-     * @return array
827
-     * @since   $VID:$
828
-     */
829
-    private function addLimitQueryParams(array $query_params, $limit = 0)
830
-    {
831
-        if ($limit) {
832
-            $query_params['limit'] = $limit;
833
-        }
834
-        return $query_params;
835
-    }
836
-
837
-
838
-    /**
839
-     * @param array  $query_params
840
-     * @param string $order_by
841
-     * @param string $order
842
-     * @return array
843
-     * @since   $VID:$
844
-     */
845
-    private function addOrderByQueryParams(array $query_params, $order_by = 'DTT_EVT_start', $order = 'ASC')
846
-    {
847
-        $order                    = $order === 'ASC' ? 'ASC' : 'DESC';
848
-        $valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
849
-        $order_by                 = in_array($order_by, $valid_order_columns, true) ? $order_by : 'DTT_EVT_start';
850
-        $query_params['order_by'] = [$order_by => $order];
851
-        return $query_params;
852
-    }
15
+	/**
16
+	 * @var EEM_Datetime $_instance
17
+	 */
18
+	protected static $_instance;
19
+
20
+
21
+	/**
22
+	 * private constructor to prevent direct creation
23
+	 *
24
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
25
+	 *                         (and any incoming timezone data that gets saved).
26
+	 *                         Note this just sends the timezone info to the date time model field objects.
27
+	 *                         Default is NULL
28
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
29
+	 * @throws EE_Error
30
+	 * @throws InvalidArgumentException
31
+	 * @throws InvalidArgumentException
32
+	 */
33
+	protected function __construct($timezone)
34
+	{
35
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
36
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
37
+		$this->_tables                 = [
38
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
39
+		];
40
+		$this->_fields                 = [
41
+			'Datetime' => [
42
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
43
+					'DTT_ID',
44
+					esc_html__('Datetime ID', 'event_espresso')
45
+				),
46
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
47
+					'EVT_ID',
48
+					esc_html__('Event ID', 'event_espresso'),
49
+					false,
50
+					0,
51
+					'Event'
52
+				),
53
+				'VNU_ID' => new EE_Foreign_Key_Int_Field(
54
+					'VNU_ID',
55
+					__('Venue ID', 'event_espresso'),
56
+					false,
57
+					0,
58
+					'Venue'
59
+				),
60
+				'DTT_name'        => new EE_Plain_Text_Field(
61
+					'DTT_name',
62
+					esc_html__('Datetime Name', 'event_espresso'),
63
+					false,
64
+					''
65
+				),
66
+				'DTT_description' => new EE_Post_Content_Field(
67
+					'DTT_description',
68
+					esc_html__('Description for Datetime', 'event_espresso'),
69
+					false,
70
+					''
71
+				),
72
+				'DTT_EVT_start'   => new EE_Datetime_Field(
73
+					'DTT_EVT_start',
74
+					esc_html__('Start time/date of Event', 'event_espresso'),
75
+					false,
76
+					EE_Datetime_Field::now,
77
+					$timezone
78
+				),
79
+				'DTT_EVT_end'     => new EE_Datetime_Field(
80
+					'DTT_EVT_end',
81
+					esc_html__('End time/date of Event', 'event_espresso'),
82
+					false,
83
+					EE_Datetime_Field::now,
84
+					$timezone
85
+				),
86
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
87
+					'DTT_reg_limit',
88
+					esc_html__('Registration Limit for this time', 'event_espresso'),
89
+					true,
90
+					EE_INF
91
+				),
92
+				'DTT_sold'        => new EE_Integer_Field(
93
+					'DTT_sold',
94
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
95
+					true,
96
+					0
97
+				),
98
+				'DTT_reserved'    => new EE_Integer_Field(
99
+					'DTT_reserved',
100
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
101
+					false,
102
+					0
103
+				),
104
+				'DTT_is_primary'  => new EE_Boolean_Field(
105
+					'DTT_is_primary',
106
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
107
+					false,
108
+					false
109
+				),
110
+				'DTT_order'       => new EE_Integer_Field(
111
+					'DTT_order',
112
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
113
+					false,
114
+					0
115
+				),
116
+				'DTT_parent'      => new EE_Integer_Field(
117
+					'DTT_parent',
118
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
119
+					true,
120
+					0
121
+				),
122
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
123
+					'DTT_deleted',
124
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
125
+					false,
126
+					false
127
+				),
128
+			],
129
+		];
130
+		$this->_model_relations        = [
131
+			'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
132
+			'Event'           => new EE_Belongs_To_Relation(),
133
+			'Checkin'         => new EE_Has_Many_Relation(),
134
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
135
+			'Venue'           => new EE_Belongs_To_Relation(),
136
+		];
137
+		$path_to_event_model           = 'Event';
138
+		$this->model_chain_to_password = $path_to_event_model;
139
+		$this->_model_chain_to_wp_user = $path_to_event_model;
140
+		// this model is generally available for reading
141
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
142
+			new EE_Restriction_Generator_Event_Related_Public(
143
+				$path_to_event_model
144
+			);
145
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
146
+			new EE_Restriction_Generator_Event_Related_Protected(
147
+				$path_to_event_model
148
+			);
149
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
150
+			new EE_Restriction_Generator_Event_Related_Protected(
151
+				$path_to_event_model
152
+			);
153
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
154
+			new EE_Restriction_Generator_Event_Related_Protected(
155
+				$path_to_event_model,
156
+				EEM_Base::caps_edit
157
+			);
158
+		parent::__construct($timezone);
159
+	}
160
+
161
+
162
+	/**
163
+	 * create new blank datetime
164
+	 *
165
+	 * @access public
166
+	 * @return EE_Datetime[] array on success, FALSE on fail
167
+	 * @throws EE_Error
168
+	 * @throws InvalidArgumentException
169
+	 * @throws InvalidDataTypeException
170
+	 * @throws ReflectionException
171
+	 * @throws InvalidInterfaceException
172
+	 */
173
+	public function create_new_blank_datetime()
174
+	{
175
+		// makes sure timezone is always set.
176
+		$timezone_string = $this->get_timezone();
177
+		/**
178
+		 * Filters the initial start date for the new datetime.
179
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
180
+		 *
181
+		 * @param int $start_date Unix timestamp representing now + 30 days in seconds.
182
+		 * @return int Unix timestamp
183
+		 */
184
+		$start_date = apply_filters(
185
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
186
+			$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
187
+		);
188
+		/**
189
+		 * Filters the initial end date for the new datetime.
190
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
191
+		 *
192
+		 * @param int $end_data Unix timestamp representing now + 30 days in seconds.
193
+		 * @return int Unix timestamp
194
+		 */
195
+		$end_date       = apply_filters(
196
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
197
+			$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
198
+		);
199
+		$blank_datetime = EE_Datetime::new_instance(
200
+			[
201
+				'DTT_EVT_start' => $start_date,
202
+				'DTT_EVT_end'   => $end_date,
203
+				'DTT_order'     => 1,
204
+				'DTT_reg_limit' => EE_INF,
205
+			],
206
+			$timezone_string
207
+		);
208
+		/**
209
+		 * Filters the initial start time and format for the new EE_Datetime instance.
210
+		 *
211
+		 * @param array $start_time An array having size 2.  First element is the time, second element is the time
212
+		 *                          format.
213
+		 * @return array
214
+		 */
215
+		$start_time = apply_filters(
216
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
217
+			['8am', 'ga']
218
+		);
219
+		/**
220
+		 * Filters the initial end time and format for the new EE_Datetime instance.
221
+		 *
222
+		 * @param array $end_time An array having size 2.  First element is the time, second element is the time
223
+		 *                        format
224
+		 * @return array
225
+		 */
226
+		$end_time = apply_filters(
227
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
228
+			['5pm', 'ga']
229
+		);
230
+		$this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
231
+		$blank_datetime->set_start_time(
232
+			$this->convert_datetime_for_query(
233
+				'DTT_EVT_start',
234
+				$start_time[0],
235
+				$start_time[1],
236
+				$timezone_string
237
+			)
238
+		);
239
+		$blank_datetime->set_end_time(
240
+			$this->convert_datetime_for_query(
241
+				'DTT_EVT_end',
242
+				$end_time[0],
243
+				$end_time[1],
244
+				$timezone_string
245
+			)
246
+		);
247
+		return [$blank_datetime];
248
+	}
249
+
250
+
251
+	/**
252
+	 * Validates whether the start_time and end_time are in the expected format.
253
+	 *
254
+	 * @param array $start_time
255
+	 * @param array $end_time
256
+	 * @throws InvalidArgumentException
257
+	 * @throws InvalidDataTypeException
258
+	 */
259
+	private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
260
+	{
261
+		if (! is_array($start_time)) {
262
+			throw new InvalidDataTypeException('start_time', $start_time, 'array');
263
+		}
264
+		if (! is_array($end_time)) {
265
+			throw new InvalidDataTypeException('end_time', $end_time, 'array');
266
+		}
267
+		if (count($start_time) !== 2) {
268
+			throw new InvalidArgumentException(
269
+				sprintf(
270
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
271
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
272
+					'$start_time'
273
+				)
274
+			);
275
+		}
276
+		if (count($end_time) !== 2) {
277
+			throw new InvalidArgumentException(
278
+				sprintf(
279
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
280
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
281
+					'$end_time'
282
+				)
283
+			);
284
+		}
285
+	}
286
+
287
+
288
+	/**
289
+	 * get event start date from db
290
+	 *
291
+	 * @access public
292
+	 * @param int $EVT_ID
293
+	 * @return EE_Datetime[] array on success, FALSE on fail
294
+	 * @throws EE_Error
295
+	 * @throws ReflectionException
296
+	 */
297
+	public function get_all_event_dates($EVT_ID = 0)
298
+	{
299
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
300
+			return $this->create_new_blank_datetime();
301
+		}
302
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
303
+		if (empty($results)) {
304
+			return $this->create_new_blank_datetime();
305
+		}
306
+		return $results;
307
+	}
308
+
309
+
310
+	/**
311
+	 * get all datetimes attached to an event ordered by the DTT_order field
312
+	 *
313
+	 * @public
314
+	 * @param int     $EVT_ID     event id
315
+	 * @param boolean $include_expired
316
+	 * @param boolean $include_deleted
317
+	 * @param int     $limit      If included then limit the count of results by
318
+	 *                            the given number
319
+	 * @return EE_Datetime[]
320
+	 * @throws EE_Error
321
+	 */
322
+	public function get_datetimes_for_event_ordered_by_DTT_order(
323
+		int $EVT_ID,
324
+		bool $include_expired = true,
325
+		bool $include_deleted = true,
326
+		$limit = 0
327
+	) {
328
+		$prev_data_prep_value = $this->prepModelForQuery();
329
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
330
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
331
+		$query_params         = $this->addDefaultWhereConditions($query_params);
332
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
333
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
334
+	}
335
+
336
+
337
+	/**
338
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
339
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
340
+	 * and then the earlier datetimes are the most important.
341
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
342
+	 *
343
+	 * @param int $EVT_ID
344
+	 * @param int $limit
345
+	 * @return EE_Datetime[]|EE_Base_Class[]
346
+	 * @throws EE_Error
347
+	 */
348
+	public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, $limit = 0)
349
+	{
350
+		$query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
351
+		$query_params    = $this->addDefaultWhereConditions($query_params);
352
+		$query_params    = $this->addDefaultQueryParams($query_params, $limit);
353
+		return $this->get_all($query_params);
354
+	}
355
+
356
+
357
+	/**
358
+	 * @param int     $EVT_ID
359
+	 * @param boolean $include_expired
360
+	 * @param boolean $include_deleted
361
+	 * @return EE_Datetime
362
+	 * @throws EE_Error
363
+	 */
364
+	public function get_oldest_datetime_for_event(
365
+		int $EVT_ID,
366
+		bool $include_expired = false,
367
+		bool $include_deleted = false
368
+	) {
369
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
370
+			$EVT_ID,
371
+			$include_expired,
372
+			$include_deleted,
373
+			1
374
+		);
375
+		if ($results) {
376
+			return array_shift($results);
377
+		}
378
+		return null;
379
+	}
380
+
381
+
382
+	/**
383
+	 * Gets the 'primary' datetime for an event.
384
+	 *
385
+	 * @param int  $EVT_ID
386
+	 * @param bool $try_to_exclude_expired
387
+	 * @param bool $try_to_exclude_deleted
388
+	 * @return EE_Datetime
389
+	 * @throws EE_Error
390
+	 */
391
+	public function get_primary_datetime_for_event(
392
+		int $EVT_ID,
393
+		bool $try_to_exclude_expired = true,
394
+		bool $try_to_exclude_deleted = true
395
+	) {
396
+		if ($try_to_exclude_expired) {
397
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
398
+			if ($non_expired) {
399
+				return $non_expired;
400
+			}
401
+		}
402
+		if ($try_to_exclude_deleted) {
403
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
404
+			if ($expired_even) {
405
+				return $expired_even;
406
+			}
407
+		}
408
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
409
+	}
410
+
411
+
412
+	/**
413
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
414
+	 * only by start date
415
+	 *
416
+	 * @param int     $EVT_ID
417
+	 * @param boolean $include_expired
418
+	 * @param boolean $include_deleted
419
+	 * @param int     $limit
420
+	 * @return EE_Datetime[]
421
+	 * @throws EE_Error
422
+	 */
423
+	public function get_datetimes_for_event_ordered_by_start_time(
424
+		int $EVT_ID,
425
+		bool $include_expired = true,
426
+		bool $include_deleted = true,
427
+		$limit = 0
428
+	) {
429
+		$prev_data_prep_value = $this->prepModelForQuery();
430
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
431
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
432
+		$query_params         = $this->addDefaultWhereConditions(
433
+			$query_params,
434
+			EEM_Base::default_where_conditions_this_only
435
+		);
436
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
437
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
438
+	}
439
+
440
+
441
+	/**
442
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
443
+	 * only by start date
444
+	 *
445
+	 * @param int     $TKT_ID
446
+	 * @param boolean $include_expired
447
+	 * @param boolean $include_deleted
448
+	 * @param int     $limit
449
+	 * @return EE_Datetime[]
450
+	 * @throws EE_Error
451
+	 */
452
+	public function get_datetimes_for_ticket_ordered_by_start_time(
453
+		int $TKT_ID,
454
+		bool $include_expired = true,
455
+		bool $include_deleted = true,
456
+		$limit = 0
457
+	) {
458
+		$prev_data_prep_value = $this->prepModelForQuery();
459
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
460
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
461
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit);
462
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
463
+	}
464
+
465
+
466
+	/**
467
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
468
+	 * datetimes.
469
+	 *
470
+	 * @param int      $TKT_ID           ID of ticket to retrieve the datetimes for
471
+	 * @param boolean  $include_expired  whether to include expired datetimes or not
472
+	 * @param boolean  $include_deleted  whether to include trashed datetimes or not.
473
+	 * @param int|null $limit            if null, no limit, if int then limit results by
474
+	 *                                   that number
475
+	 * @return EE_Datetime[]
476
+	 * @throws EE_Error
477
+	 */
478
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
479
+		int $TKT_ID,
480
+		bool $include_expired = true,
481
+		bool $include_deleted = true,
482
+		$limit = 0
483
+	) {
484
+		$prev_data_prep_value = $this->prepModelForQuery();
485
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
486
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
487
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
488
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
494
+	 * reason it doesn't exist, we consider the earliest event the most important)
495
+	 *
496
+	 * @param int $EVT_ID
497
+	 * @return EE_Datetime
498
+	 * @throws EE_Error
499
+	 */
500
+	public function get_most_important_datetime_for_event(int $EVT_ID)
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 stdClass[]
525
+	 * @throws EE_Error
526
+	 * @throws InvalidArgumentException
527
+	 * @throws InvalidArgumentException
528
+	 */
529
+	public function get_dtt_months_and_years(array $where_params, $evt_active_status = '')
530
+	{
531
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
532
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
533
+		switch ($evt_active_status) {
534
+			case 'upcoming':
535
+				$where_params['Event.status'] = 'publish';
536
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
537
+				if (isset($where_params['DTT_EVT_start'])) {
538
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
539
+				}
540
+				$where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
541
+				break;
542
+			case 'expired':
543
+				if (isset($where_params['Event.status'])) {
544
+					unset($where_params['Event.status']);
545
+				}
546
+				// get events to exclude
547
+				$exclude_query[0] = array_merge(
548
+					$where_params,
549
+					['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
550
+				);
551
+				// first get all events that have datetimes where its not expired.
552
+				$event_ids = $this->_get_all_wpdb_results(
553
+					$exclude_query,
554
+					OBJECT_K,
555
+					'Datetime.EVT_ID'
556
+				);
557
+				$event_ids = array_keys($event_ids);
558
+				if (isset($where_params['DTT_EVT_end'])) {
559
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
560
+				}
561
+				$where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
562
+				$where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
563
+				break;
564
+			case 'active':
565
+				$where_params['Event.status'] = 'publish';
566
+				if (isset($where_params['DTT_EVT_start'])) {
567
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
568
+				}
569
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
570
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
571
+				}
572
+				$where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
573
+				$where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
574
+				break;
575
+			case 'inactive':
576
+				if (isset($where_params['Event.status'])) {
577
+					unset($where_params['Event.status']);
578
+				}
579
+				if (isset($where_params['OR'])) {
580
+					$where_params['AND']['OR'] = $where_params['OR'];
581
+				}
582
+				if (isset($where_params['DTT_EVT_end'])) {
583
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
584
+					unset($where_params['DTT_EVT_end']);
585
+				}
586
+				if (isset($where_params['DTT_EVT_start'])) {
587
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
588
+					unset($where_params['DTT_EVT_start']);
589
+				}
590
+				$where_params['AND']['Event.status'] = ['!=', 'publish'];
591
+				break;
592
+		}
593
+		$query_params[0]          = $where_params;
594
+		$query_params['group_by'] = ['dtt_year', 'dtt_month'];
595
+		$query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
596
+
597
+		$query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
598
+			$this->get_timezone(),
599
+			'DTT_EVT_start'
600
+		);
601
+		$columns_to_select = [
602
+			'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
603
+			'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
604
+			'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
605
+		];
606
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
607
+	}
608
+
609
+
610
+	/**
611
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
612
+	 * for the tickets for each datetime)
613
+	 *
614
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
615
+	 * @throws EE_Error
616
+	 * @throws ReflectionException
617
+	 */
618
+	public function update_sold(array $datetimes)
619
+	{
620
+		EE_Error::doing_it_wrong(
621
+			__FUNCTION__,
622
+			esc_html__(
623
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
624
+				'event_espresso'
625
+			),
626
+			'4.9.32.rc.005'
627
+		);
628
+		foreach ($datetimes as $datetime) {
629
+			$datetime->update_sold();
630
+		}
631
+	}
632
+
633
+
634
+	/**
635
+	 *    Gets the total number of tickets available at a particular datetime
636
+	 *    (does NOT take into account the datetime's spaces available)
637
+	 *
638
+	 * @param int   $DTT_ID
639
+	 * @param array $query_params
640
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
641
+	 *             tickets attached to datetime then FALSE is returned.
642
+	 * @throws EE_Error
643
+	 * @throws ReflectionException
644
+	 */
645
+	public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = [])
646
+	{
647
+		$datetime = $this->get_one_by_ID($DTT_ID);
648
+		if ($datetime instanceof EE_Datetime) {
649
+			return $datetime->tickets_remaining($query_params);
650
+		}
651
+		return 0;
652
+	}
653
+
654
+
655
+	/**
656
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
657
+	 *
658
+	 * @param array $stati_to_include  If included you can restrict the statuses we return counts for by including the
659
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
660
+	 *                                 for all valid stati.
661
+	 * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
662
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
663
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
664
+	 * @throws EE_Error
665
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
666
+	 *                                 EE_Datetime::expired
667
+	 */
668
+	public function get_datetime_counts_by_status(array $stati_to_include = [], array $query_params = [])
669
+	{
670
+		// only accept where conditions for this query.
671
+		$_where            = isset($query_params[0]) ? $query_params[0] : [];
672
+		$status_query_args = [
673
+			EE_Datetime::active   => array_merge(
674
+				$_where,
675
+				['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
676
+			),
677
+			EE_Datetime::upcoming => array_merge(
678
+				$_where,
679
+				['DTT_EVT_start' => ['>', time()]]
680
+			),
681
+			EE_Datetime::expired  => array_merge(
682
+				$_where,
683
+				['DTT_EVT_end' => ['<', time()]]
684
+			),
685
+		];
686
+		if (! empty($stati_to_include)) {
687
+			foreach (array_keys($status_query_args) as $status) {
688
+				if (! in_array($status, $stati_to_include, true)) {
689
+					unset($status_query_args[ $status ]);
690
+				}
691
+			}
692
+		}
693
+		// loop through and query counts for each stati.
694
+		$status_query_results = [];
695
+		foreach ($status_query_args as $status => $status_where_conditions) {
696
+			$status_query_results[ $status ] = EEM_Datetime::count(
697
+				[$status_where_conditions],
698
+				'DTT_ID',
699
+				true
700
+			);
701
+		}
702
+		return $status_query_results;
703
+	}
704
+
705
+
706
+	/**
707
+	 * Returns the specific count for a given Datetime status matching any given query_params.
708
+	 *
709
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
710
+	 * @param array  $query_params
711
+	 * @return int
712
+	 * @throws EE_Error
713
+	 */
714
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = [])
715
+	{
716
+		$count = $this->get_datetime_counts_by_status([$status], $query_params);
717
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
718
+	}
719
+
720
+
721
+	/**
722
+	 * @return bool|int
723
+	 * @since   $VID:$
724
+	 */
725
+	private function prepModelForQuery()
726
+	{
727
+		$prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
728
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
729
+		return $prev_data_prep_value;
730
+	}
731
+
732
+
733
+	/**
734
+	 * @param array    $query_params
735
+	 * @param bool|int $prev_data_prep_value
736
+	 * @return EE_Base_Class[]|EE_Datetime[]
737
+	 * @throws EE_Error
738
+	 * @since   $VID:$
739
+	 */
740
+	private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value)
741
+	{
742
+		$result = $this->get_all($query_params);
743
+		$this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
744
+		return $result;
745
+	}
746
+
747
+
748
+	/**
749
+	 * @param array  $query_params
750
+	 * @param int    $limit
751
+	 * @param string $order_by
752
+	 * @param string $order
753
+	 * @return array
754
+	 * @since   $VID:$
755
+	 */
756
+	private function addDefaultQueryParams(array $query_params, $limit = 0, $order_by = 'DTT_EVT_start', $order = 'ASC')
757
+	{
758
+		$query_params = $this->addOrderByQueryParams($query_params, $order_by, $order);
759
+		$query_params = $this->addLimitQueryParams($query_params, $limit);
760
+		return $query_params;
761
+	}
762
+
763
+
764
+	/**
765
+	 * @param array  $query_params
766
+	 * @param string $default_where_conditions
767
+	 * @return array
768
+	 * @since   $VID:$
769
+	 */
770
+	private function addDefaultWhereConditions(
771
+		array $query_params,
772
+		$default_where_conditions = EEM_Base::default_where_conditions_none
773
+	) {
774
+		$query_params['default_where_conditions'] = $default_where_conditions;
775
+		return $query_params;
776
+	}
777
+
778
+
779
+	/**
780
+	 * @param array $where_params
781
+	 * @param bool  $include_deleted
782
+	 * @param bool  $include_expired
783
+	 * @return array
784
+	 * @since   $VID:$
785
+	 */
786
+	private function addDefaultWhereParams(array $where_params, bool $include_deleted = true, bool $include_expired = true)
787
+	{
788
+		$where_params = $this->addExpiredWhereParams($where_params, $include_expired);
789
+		$where_params = $this->addDeletedWhereParams($where_params, $include_deleted);
790
+		return $where_params;
791
+	}
792
+
793
+
794
+	/**
795
+	 * @param array $where_params
796
+	 * @param bool  $include_deleted
797
+	 * @return array
798
+	 * @since   $VID:$
799
+	 */
800
+	private function addDeletedWhereParams(array $where_params, bool $include_deleted = true)
801
+	{
802
+		$deleted                     = $include_deleted ? [true, false] : [false];
803
+		$where_params['DTT_deleted'] = ['IN', $deleted];
804
+		return $where_params;
805
+	}
806
+
807
+
808
+	/**
809
+	 * @param array $where_params
810
+	 * @param bool  $include_expired
811
+	 * @return array
812
+	 * @since   $VID:$
813
+	 */
814
+	private function addExpiredWhereParams(array $where_params, bool $include_expired = true)
815
+	{
816
+		if (! $include_expired) {
817
+			$where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
818
+		}
819
+		return $where_params;
820
+	}
821
+
822
+
823
+	/**
824
+	 * @param array $query_params
825
+	 * @param int   $limit
826
+	 * @return array
827
+	 * @since   $VID:$
828
+	 */
829
+	private function addLimitQueryParams(array $query_params, $limit = 0)
830
+	{
831
+		if ($limit) {
832
+			$query_params['limit'] = $limit;
833
+		}
834
+		return $query_params;
835
+	}
836
+
837
+
838
+	/**
839
+	 * @param array  $query_params
840
+	 * @param string $order_by
841
+	 * @param string $order
842
+	 * @return array
843
+	 * @since   $VID:$
844
+	 */
845
+	private function addOrderByQueryParams(array $query_params, $order_by = 'DTT_EVT_start', $order = 'ASC')
846
+	{
847
+		$order                    = $order === 'ASC' ? 'ASC' : 'DESC';
848
+		$valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
849
+		$order_by                 = in_array($order_by, $valid_order_columns, true) ? $order_by : 'DTT_EVT_start';
850
+		$query_params['order_by'] = [$order_by => $order];
851
+		return $query_params;
852
+	}
853 853
 }
Please login to merge, or discard this patch.
strategies/EE_Restriction_Generator_Default_Protected.strategy.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -14,164 +14,164 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Restriction_Generator_Default_Protected extends EE_Restriction_Generator_Base
16 16
 {
17
-    /**
18
-     * Name of the field on this model (or a related model, including the model chain to it)
19
-     * that is a boolean indicating whether or not a model object is considered "Default" or not
20
-     *
21
-     * @var string
22
-     */
23
-    protected $_default_field_name;
24
-
25
-    /**
26
-     * The model chain to follow to get to the event model, including the event model itself.
27
-     * Eg 'Ticket.Datetime.Event'
28
-     *
29
-     * @var string
30
-     */
31
-    protected $_path_to_event_model;
32
-
33
-
34
-    /**
35
-     * @param string $default_field_name  the name of the field Name of the field on this model
36
-     *                                    (or a related model, including the model chain to it)
37
-     *                                    that is a boolean indicating whether or not a model object
38
-     *                                    is considered "Default" or not
39
-     * @param string $path_to_event_model The model chain to follow to get to the event model,
40
-     *                                    including the event model itself. Eg 'Ticket.Datetime.Event'
41
-     */
42
-    public function __construct(string $default_field_name, string $path_to_event_model)
43
-    {
44
-        $this->_default_field_name  = $default_field_name;
45
-        $this->_path_to_event_model = rtrim($path_to_event_model, '.') . '.';
46
-    }
47
-
48
-
49
-    /**
50
-     * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
51
-     * @throws EE_Error
52
-     */
53
-    protected function _generate_restrictions(): array
54
-    {
55
-        // if there are no standard caps for this model, then for now
56
-        // all we know is if they need the default cap to access this
57
-        if (! $this->model()->cap_slug()) {
58
-            return [
59
-                self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions(),
60
-            ];
61
-        }
62
-
63
-        $action         = $this->action();
64
-        $others         = "{$action}_others";
65
-        $private        = "{$action}_private";
66
-        $default        = "{$action}_default";
67
-        $others_default = "{$action}_others_default";
68
-        $event_model    = EEM_Event::instance();
69
-
70
-        $restrictions = [
71
-            // first: access to non-defaults is essentially controlled by which events are accessible
72
-            // if they don't have the basic event cap, they can't access ANY non-default items
73
-            $this->getCapKey($event_model, $action)    => $this->nonDefaultRestrictions(true),
74
-            // if they don't have the others event cap, they can't access others' non-default items
75
-            $this->getCapKey($event_model, $others)    => $this->othersNonDefaultRestrictions($event_model, $others),
76
-            // if they have basic and others, but not private, they can't access others' private non-default items
77
-            $this->getCapKey($event_model, $private)   => $this->privateRestrictions($event_model, $private),
78
-            // second: access to defaults is controlled by the default capabilities
79
-            // if they don't have the default capability, restrict access to only non-default items
80
-            $this->getCapKey($this->model(), $default) => $this->nonDefaultRestrictions(false),
81
-        ];
82
-        // if they don't have the "others" default capability,
83
-        // restrict access to only their default ones, and non-default ones
84
-        if (EE_Restriction_Generator_Base::is_cap($this->model(), $others_default)) {
85
-            $restrictions[ $this->getCapKey($this->model(), $others_default) ] = $this->othersDefaultRestrictions(
86
-                $others_default
87
-            );
88
-        }
89
-        return $restrictions;
90
-    }
91
-
92
-
93
-    /**
94
-     * @param EEM_Base $model
95
-     * @param string   $action
96
-     * @return string
97
-     * @since   $VID:$
98
-     */
99
-    private function getCapKey(EEM_Base $model, string $action): string
100
-    {
101
-        return EE_Restriction_Generator_Base::get_cap_name($model, $action);
102
-    }
103
-
104
-
105
-    /**
106
-     * @param bool $use_default_field_name
107
-     * @return EE_Default_Where_Conditions
108
-     * @since   $VID:$
109
-     */
110
-    private function nonDefaultRestrictions(bool $use_default_field_name): EE_Default_Where_Conditions
111
-    {
112
-        return new EE_Default_Where_Conditions([$this->_default_field_name => $use_default_field_name]);
113
-    }
114
-
115
-
116
-    /**
117
-     * @param string $action
118
-     * @return EE_Default_Where_Conditions
119
-     * @throws EE_Error
120
-     * @since   $VID:$
121
-     */
122
-    private function othersDefaultRestrictions(string $action): EE_Default_Where_Conditions
123
-    {
124
-        return new EE_Default_Where_Conditions(
125
-            [
126
-                // if they don't have the others default cap, they can't access others default items
127
-                // (but they can access their own default items, and non-default items)
128
-                'OR*no_' . $this->getCapKey($this->model(), $action) => [
129
-                    'AND'                      => [
130
-                        $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
131
-                        $this->_default_field_name                  => true,
132
-                    ],
133
-                    $this->_default_field_name => false,
134
-                ],
135
-            ]
136
-        );
137
-    }
138
-
139
-
140
-    /**
141
-     * @param EEM_Event $event_model
142
-     * @param string    $action
143
-     * @return EE_Default_Where_Conditions
144
-     * @since   $VID:$
145
-     */
146
-    private function othersNonDefaultRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
147
-    {
148
-        return new EE_Default_Where_Conditions(
149
-            [
150
-                'OR*no_' . $this->getCapKey($event_model, $action) => [
151
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
152
-                ],
153
-                $this->_default_field_name                         => true,
154
-            ]
155
-        );
156
-    }
157
-
158
-
159
-    /**
160
-     * @param EEM_Event $event_model
161
-     * @param string    $action
162
-     * @return EE_Default_Where_Conditions
163
-     * @since   $VID:$
164
-     */
165
-    private function privateRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
166
-    {
167
-        return new EE_Default_Where_Conditions(
168
-            [
169
-                'OR*no_' . $this->getCapKey($event_model, $action) => [
170
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
171
-                    $this->_path_to_event_model . 'status'      => ['!=', 'private'],
172
-                    $this->_default_field_name                  => true,
173
-                ],
174
-            ]
175
-        );
176
-    }
17
+	/**
18
+	 * Name of the field on this model (or a related model, including the model chain to it)
19
+	 * that is a boolean indicating whether or not a model object is considered "Default" or not
20
+	 *
21
+	 * @var string
22
+	 */
23
+	protected $_default_field_name;
24
+
25
+	/**
26
+	 * The model chain to follow to get to the event model, including the event model itself.
27
+	 * Eg 'Ticket.Datetime.Event'
28
+	 *
29
+	 * @var string
30
+	 */
31
+	protected $_path_to_event_model;
32
+
33
+
34
+	/**
35
+	 * @param string $default_field_name  the name of the field Name of the field on this model
36
+	 *                                    (or a related model, including the model chain to it)
37
+	 *                                    that is a boolean indicating whether or not a model object
38
+	 *                                    is considered "Default" or not
39
+	 * @param string $path_to_event_model The model chain to follow to get to the event model,
40
+	 *                                    including the event model itself. Eg 'Ticket.Datetime.Event'
41
+	 */
42
+	public function __construct(string $default_field_name, string $path_to_event_model)
43
+	{
44
+		$this->_default_field_name  = $default_field_name;
45
+		$this->_path_to_event_model = rtrim($path_to_event_model, '.') . '.';
46
+	}
47
+
48
+
49
+	/**
50
+	 * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
51
+	 * @throws EE_Error
52
+	 */
53
+	protected function _generate_restrictions(): array
54
+	{
55
+		// if there are no standard caps for this model, then for now
56
+		// all we know is if they need the default cap to access this
57
+		if (! $this->model()->cap_slug()) {
58
+			return [
59
+				self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions(),
60
+			];
61
+		}
62
+
63
+		$action         = $this->action();
64
+		$others         = "{$action}_others";
65
+		$private        = "{$action}_private";
66
+		$default        = "{$action}_default";
67
+		$others_default = "{$action}_others_default";
68
+		$event_model    = EEM_Event::instance();
69
+
70
+		$restrictions = [
71
+			// first: access to non-defaults is essentially controlled by which events are accessible
72
+			// if they don't have the basic event cap, they can't access ANY non-default items
73
+			$this->getCapKey($event_model, $action)    => $this->nonDefaultRestrictions(true),
74
+			// if they don't have the others event cap, they can't access others' non-default items
75
+			$this->getCapKey($event_model, $others)    => $this->othersNonDefaultRestrictions($event_model, $others),
76
+			// if they have basic and others, but not private, they can't access others' private non-default items
77
+			$this->getCapKey($event_model, $private)   => $this->privateRestrictions($event_model, $private),
78
+			// second: access to defaults is controlled by the default capabilities
79
+			// if they don't have the default capability, restrict access to only non-default items
80
+			$this->getCapKey($this->model(), $default) => $this->nonDefaultRestrictions(false),
81
+		];
82
+		// if they don't have the "others" default capability,
83
+		// restrict access to only their default ones, and non-default ones
84
+		if (EE_Restriction_Generator_Base::is_cap($this->model(), $others_default)) {
85
+			$restrictions[ $this->getCapKey($this->model(), $others_default) ] = $this->othersDefaultRestrictions(
86
+				$others_default
87
+			);
88
+		}
89
+		return $restrictions;
90
+	}
91
+
92
+
93
+	/**
94
+	 * @param EEM_Base $model
95
+	 * @param string   $action
96
+	 * @return string
97
+	 * @since   $VID:$
98
+	 */
99
+	private function getCapKey(EEM_Base $model, string $action): string
100
+	{
101
+		return EE_Restriction_Generator_Base::get_cap_name($model, $action);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @param bool $use_default_field_name
107
+	 * @return EE_Default_Where_Conditions
108
+	 * @since   $VID:$
109
+	 */
110
+	private function nonDefaultRestrictions(bool $use_default_field_name): EE_Default_Where_Conditions
111
+	{
112
+		return new EE_Default_Where_Conditions([$this->_default_field_name => $use_default_field_name]);
113
+	}
114
+
115
+
116
+	/**
117
+	 * @param string $action
118
+	 * @return EE_Default_Where_Conditions
119
+	 * @throws EE_Error
120
+	 * @since   $VID:$
121
+	 */
122
+	private function othersDefaultRestrictions(string $action): EE_Default_Where_Conditions
123
+	{
124
+		return new EE_Default_Where_Conditions(
125
+			[
126
+				// if they don't have the others default cap, they can't access others default items
127
+				// (but they can access their own default items, and non-default items)
128
+				'OR*no_' . $this->getCapKey($this->model(), $action) => [
129
+					'AND'                      => [
130
+						$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
131
+						$this->_default_field_name                  => true,
132
+					],
133
+					$this->_default_field_name => false,
134
+				],
135
+			]
136
+		);
137
+	}
138
+
139
+
140
+	/**
141
+	 * @param EEM_Event $event_model
142
+	 * @param string    $action
143
+	 * @return EE_Default_Where_Conditions
144
+	 * @since   $VID:$
145
+	 */
146
+	private function othersNonDefaultRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
147
+	{
148
+		return new EE_Default_Where_Conditions(
149
+			[
150
+				'OR*no_' . $this->getCapKey($event_model, $action) => [
151
+					$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
152
+				],
153
+				$this->_default_field_name                         => true,
154
+			]
155
+		);
156
+	}
157
+
158
+
159
+	/**
160
+	 * @param EEM_Event $event_model
161
+	 * @param string    $action
162
+	 * @return EE_Default_Where_Conditions
163
+	 * @since   $VID:$
164
+	 */
165
+	private function privateRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
166
+	{
167
+		return new EE_Default_Where_Conditions(
168
+			[
169
+				'OR*no_' . $this->getCapKey($event_model, $action) => [
170
+					$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
171
+					$this->_path_to_event_model . 'status'      => ['!=', 'private'],
172
+					$this->_default_field_name                  => true,
173
+				],
174
+			]
175
+		);
176
+	}
177 177
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Price.model.php 1 patch
Indentation   +337 added lines, -337 removed lines patch added patch discarded remove patch
@@ -12,368 +12,368 @@
 block discarded – undo
12 12
  */
13 13
 class EEM_Price extends EEM_Soft_Delete_Base
14 14
 {
15
-    // private instance of the EEM_Price object
16
-    protected static $_instance;
15
+	// private instance of the EEM_Price object
16
+	protected static $_instance;
17 17
 
18 18
 
19
-    /**
20
-     * private constructor to prevent direct creation
21
-     *
22
-     * @Constructor
23
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
24
-     *                         (and any incoming timezone data that gets saved).
25
-     *                         Note this just sends the timezone info to the date time model field objects.
26
-     *                         Default is NULL
27
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
28
-     */
29
-    protected function __construct($timezone)
30
-    {
31
-        $this->singular_item = __('Price', 'event_espresso');
32
-        $this->plural_item   = __('Prices', 'event_espresso');
19
+	/**
20
+	 * private constructor to prevent direct creation
21
+	 *
22
+	 * @Constructor
23
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
24
+	 *                         (and any incoming timezone data that gets saved).
25
+	 *                         Note this just sends the timezone info to the date time model field objects.
26
+	 *                         Default is NULL
27
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
28
+	 */
29
+	protected function __construct($timezone)
30
+	{
31
+		$this->singular_item = __('Price', 'event_espresso');
32
+		$this->plural_item   = __('Prices', 'event_espresso');
33 33
 
34
-        $this->_tables          = [
35
-            'Price' => new EE_Primary_Table('esp_price', 'PRC_ID'),
36
-        ];
37
-        $this->_fields          = [
38
-            'Price' => [
39
-                'PRC_ID'         => new EE_Primary_Key_Int_Field(
40
-                    'PRC_ID',
41
-                    'Price ID'
42
-                ),
43
-                'PRT_ID'         => new EE_Foreign_Key_Int_Field(
44
-                    'PRT_ID',
45
-                    esc_html__('Price type Id', 'event_espresso'),
46
-                    false,
47
-                    null,
48
-                    'Price_Type'
49
-                ),
50
-                'PRC_amount'     => new EE_Money_Field(
51
-                    'PRC_amount',
52
-                    esc_html__('Price Amount', 'event_espresso'),
53
-                    false,
54
-                    0
55
-                ),
56
-                'PRC_name'       => new EE_Plain_Text_Field(
57
-                    'PRC_name',
58
-                    esc_html__('Name of Price', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'PRC_desc'       => new EE_Post_Content_Field(
63
-                    'PRC_desc',
64
-                    esc_html__('Price Description', 'event_espresso'),
65
-                    false,
66
-                    ''
67
-                ),
68
-                'PRC_is_default' => new EE_Boolean_Field(
69
-                    'PRC_is_default',
70
-                    esc_html__('Flag indicating whether price is a default price', 'event_espresso'),
71
-                    false,
72
-                    false
73
-                ),
74
-                'PRC_overrides'  => new EE_Integer_Field(
75
-                    'PRC_overrides',
76
-                    esc_html__(
77
-                        'Price ID for a global Price that will be overridden by this Price  ( for replacing default prices )',
78
-                        'event_espresso'
79
-                    ),
80
-                    true,
81
-                    0
82
-                ),
83
-                'PRC_order'      => new EE_Integer_Field(
84
-                    'PRC_order',
85
-                    esc_html__(
86
-                        'Order of Application of Price (lower numbers apply first?)',
87
-                        'event_espresso'
88
-                    ),
89
-                    false,
90
-                    1
91
-                ),
92
-                'PRC_deleted'    => new EE_Trashed_Flag_Field(
93
-                    'PRC_deleted',
94
-                    esc_html__('Flag Indicating if this has been deleted or not', 'event_espresso'),
95
-                    false,
96
-                    false
97
-                ),
98
-                'PRC_parent'     => new EE_Integer_Field(
99
-                    'PRC_parent',
100
-                    esc_html__('Indicates what PRC_ID is the parent of this PRC_ID', 'event_espresso'),
101
-                    true,
102
-                    0
103
-                ),
104
-                'PRC_wp_user'    => new EE_WP_User_Field(
105
-                    'PRC_wp_user',
106
-                    esc_html__('Price Creator ID', 'event_espresso'),
107
-                    false
108
-                ),
109
-            ],
110
-        ];
111
-        $this->_model_relations = [
112
-            'Ticket'     => new EE_HABTM_Relation('Ticket_Price'),
113
-            'Price_Type' => new EE_Belongs_To_Relation(),
114
-            'WP_User'    => new EE_Belongs_To_Relation(),
115
-        ];
116
-        // this model is generally available for reading
117
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] =
118
-            new EE_Restriction_Generator_Default_Public(
119
-                'PRC_is_default',
120
-                'Ticket.Datetime.Event'
121
-            );
122
-        // account for default tickets in the caps
123
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
124
-            new EE_Restriction_Generator_Default_Protected(
125
-                'PRC_is_default',
126
-                'Ticket.Datetime.Event'
127
-            );
128
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
129
-            new EE_Restriction_Generator_Default_Protected(
130
-                'PRC_is_default',
131
-                'Ticket.Datetime.Event'
132
-            );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
134
-            new EE_Restriction_Generator_Default_Protected(
135
-                'PRC_is_default',
136
-                'Ticket.Datetime.Event'
137
-            );
138
-        parent::__construct($timezone);
139
-    }
34
+		$this->_tables          = [
35
+			'Price' => new EE_Primary_Table('esp_price', 'PRC_ID'),
36
+		];
37
+		$this->_fields          = [
38
+			'Price' => [
39
+				'PRC_ID'         => new EE_Primary_Key_Int_Field(
40
+					'PRC_ID',
41
+					'Price ID'
42
+				),
43
+				'PRT_ID'         => new EE_Foreign_Key_Int_Field(
44
+					'PRT_ID',
45
+					esc_html__('Price type Id', 'event_espresso'),
46
+					false,
47
+					null,
48
+					'Price_Type'
49
+				),
50
+				'PRC_amount'     => new EE_Money_Field(
51
+					'PRC_amount',
52
+					esc_html__('Price Amount', 'event_espresso'),
53
+					false,
54
+					0
55
+				),
56
+				'PRC_name'       => new EE_Plain_Text_Field(
57
+					'PRC_name',
58
+					esc_html__('Name of Price', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'PRC_desc'       => new EE_Post_Content_Field(
63
+					'PRC_desc',
64
+					esc_html__('Price Description', 'event_espresso'),
65
+					false,
66
+					''
67
+				),
68
+				'PRC_is_default' => new EE_Boolean_Field(
69
+					'PRC_is_default',
70
+					esc_html__('Flag indicating whether price is a default price', 'event_espresso'),
71
+					false,
72
+					false
73
+				),
74
+				'PRC_overrides'  => new EE_Integer_Field(
75
+					'PRC_overrides',
76
+					esc_html__(
77
+						'Price ID for a global Price that will be overridden by this Price  ( for replacing default prices )',
78
+						'event_espresso'
79
+					),
80
+					true,
81
+					0
82
+				),
83
+				'PRC_order'      => new EE_Integer_Field(
84
+					'PRC_order',
85
+					esc_html__(
86
+						'Order of Application of Price (lower numbers apply first?)',
87
+						'event_espresso'
88
+					),
89
+					false,
90
+					1
91
+				),
92
+				'PRC_deleted'    => new EE_Trashed_Flag_Field(
93
+					'PRC_deleted',
94
+					esc_html__('Flag Indicating if this has been deleted or not', 'event_espresso'),
95
+					false,
96
+					false
97
+				),
98
+				'PRC_parent'     => new EE_Integer_Field(
99
+					'PRC_parent',
100
+					esc_html__('Indicates what PRC_ID is the parent of this PRC_ID', 'event_espresso'),
101
+					true,
102
+					0
103
+				),
104
+				'PRC_wp_user'    => new EE_WP_User_Field(
105
+					'PRC_wp_user',
106
+					esc_html__('Price Creator ID', 'event_espresso'),
107
+					false
108
+				),
109
+			],
110
+		];
111
+		$this->_model_relations = [
112
+			'Ticket'     => new EE_HABTM_Relation('Ticket_Price'),
113
+			'Price_Type' => new EE_Belongs_To_Relation(),
114
+			'WP_User'    => new EE_Belongs_To_Relation(),
115
+		];
116
+		// this model is generally available for reading
117
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] =
118
+			new EE_Restriction_Generator_Default_Public(
119
+				'PRC_is_default',
120
+				'Ticket.Datetime.Event'
121
+			);
122
+		// account for default tickets in the caps
123
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
124
+			new EE_Restriction_Generator_Default_Protected(
125
+				'PRC_is_default',
126
+				'Ticket.Datetime.Event'
127
+			);
128
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
129
+			new EE_Restriction_Generator_Default_Protected(
130
+				'PRC_is_default',
131
+				'Ticket.Datetime.Event'
132
+			);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
134
+			new EE_Restriction_Generator_Default_Protected(
135
+				'PRC_is_default',
136
+				'Ticket.Datetime.Event'
137
+			);
138
+		parent::__construct($timezone);
139
+	}
140 140
 
141 141
 
142
-    /**
143
-     * instantiate a new price object with blank/empty properties
144
-     *
145
-     * @return mixed array on success, FALSE on fail
146
-     */
147
-    public function get_new_price()
148
-    {
149
-        return $this->create_default_object();
150
-    }
142
+	/**
143
+	 * instantiate a new price object with blank/empty properties
144
+	 *
145
+	 * @return mixed array on success, FALSE on fail
146
+	 */
147
+	public function get_new_price()
148
+	{
149
+		return $this->create_default_object();
150
+	}
151 151
 
152 152
 
153
-    /**
154
-     * retrieve  ALL prices from db
155
-     *
156
-     * @return EE_Base_Class[]|EE_PRice[]
157
-     * @throws EE_Error
158
-     */
159
-    public function get_all_prices()
160
-    {
161
-        // retrieve all prices
162
-        return $this->get_all(['order_by' => ['PRC_amount' => 'ASC']]);
163
-    }
153
+	/**
154
+	 * retrieve  ALL prices from db
155
+	 *
156
+	 * @return EE_Base_Class[]|EE_PRice[]
157
+	 * @throws EE_Error
158
+	 */
159
+	public function get_all_prices()
160
+	{
161
+		// retrieve all prices
162
+		return $this->get_all(['order_by' => ['PRC_amount' => 'ASC']]);
163
+	}
164 164
 
165 165
 
166
-    /**
167
-     * retrieve all active prices for a particular event
168
-     *
169
-     * @param int $EVT_ID
170
-     * @return array on success
171
-     * @throws EE_Error
172
-     */
173
-    public function get_all_event_prices($EVT_ID = 0)
174
-    {
175
-        return $this->get_all(
176
-            [
177
-                [
178
-                    'EVT_ID'            => $EVT_ID,
179
-                    'Price_Type.PBT_ID' => ['!=', EEM_Price_Type::base_type_tax],
180
-                ],
181
-                'order_by' => $this->_order_by_array_for_get_all_method(),
182
-            ]
183
-        );
184
-    }
166
+	/**
167
+	 * retrieve all active prices for a particular event
168
+	 *
169
+	 * @param int $EVT_ID
170
+	 * @return array on success
171
+	 * @throws EE_Error
172
+	 */
173
+	public function get_all_event_prices($EVT_ID = 0)
174
+	{
175
+		return $this->get_all(
176
+			[
177
+				[
178
+					'EVT_ID'            => $EVT_ID,
179
+					'Price_Type.PBT_ID' => ['!=', EEM_Price_Type::base_type_tax],
180
+				],
181
+				'order_by' => $this->_order_by_array_for_get_all_method(),
182
+			]
183
+		);
184
+	}
185 185
 
186 186
 
187
-    /**
188
-     * retrieve all active global prices (that are not taxes (PBT_ID=4)) for a particular event
189
-     *
190
-     * @param boolean $count return count
191
-     * @param bool    $include_taxes
192
-     * @return bool|EE_Base_Class[]|EE_PRice[]
193
-     * @throws EE_Error
194
-     */
195
-    public function get_all_default_prices($count = false, $include_taxes = false)
196
-    {
197
-        $_where = [
198
-            'PRC_deleted'    => 0,
199
-            'PRC_is_default' => 1,
200
-        ];
201
-        if (! $include_taxes) {
202
-            $_where['Price_Type.PBT_ID'] = ['!=', 4];
203
-        }
204
-        $_query_params = [
205
-            $_where,
206
-            'order_by' => $this->_order_by_array_for_get_all_method(),
207
-        ];
208
-        return $count ? $this->count([$_where]) : $this->get_all($_query_params);
209
-    }
187
+	/**
188
+	 * retrieve all active global prices (that are not taxes (PBT_ID=4)) for a particular event
189
+	 *
190
+	 * @param boolean $count return count
191
+	 * @param bool    $include_taxes
192
+	 * @return bool|EE_Base_Class[]|EE_PRice[]
193
+	 * @throws EE_Error
194
+	 */
195
+	public function get_all_default_prices($count = false, $include_taxes = false)
196
+	{
197
+		$_where = [
198
+			'PRC_deleted'    => 0,
199
+			'PRC_is_default' => 1,
200
+		];
201
+		if (! $include_taxes) {
202
+			$_where['Price_Type.PBT_ID'] = ['!=', 4];
203
+		}
204
+		$_query_params = [
205
+			$_where,
206
+			'order_by' => $this->_order_by_array_for_get_all_method(),
207
+		];
208
+		return $count ? $this->count([$_where]) : $this->get_all($_query_params);
209
+	}
210 210
 
211 211
 
212
-    /**
213
-     * retrieve all active global prices that are taxes
214
-     *
215
-     * @return bool|EE_Base_Class[]|EE_PRice[]
216
-     * @throws EE_Error
217
-     * @since   $VID:$
218
-     */
219
-    public function getAllDefaultTaxes()
220
-    {
221
-        return $this->get_all(
222
-            [
223
-                [
224
-                    'PRC_deleted'    => 0,
225
-                    'PRC_is_default' => 1,
226
-                    'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax
227
-                ],
228
-                'order_by' => [
229
-                    'Price_Type.PRT_order' => 'ASC',
230
-                    'PRC_order' => 'ASC'
231
-                ],
232
-            ]
233
-        );
234
-    }
212
+	/**
213
+	 * retrieve all active global prices that are taxes
214
+	 *
215
+	 * @return bool|EE_Base_Class[]|EE_PRice[]
216
+	 * @throws EE_Error
217
+	 * @since   $VID:$
218
+	 */
219
+	public function getAllDefaultTaxes()
220
+	{
221
+		return $this->get_all(
222
+			[
223
+				[
224
+					'PRC_deleted'    => 0,
225
+					'PRC_is_default' => 1,
226
+					'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax
227
+				],
228
+				'order_by' => [
229
+					'Price_Type.PRT_order' => 'ASC',
230
+					'PRC_order' => 'ASC'
231
+				],
232
+			]
233
+		);
234
+	}
235 235
 
236 236
 
237
-    /**
238
-     * retrieve all prices that are taxes
239
-     *
240
-     * @return EE_Base_Class[]|EE_PRice[]
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws ReflectionException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     */
247
-    public function get_all_prices_that_are_taxes()
248
-    {
249
-        $taxes     = [];
250
-        $all_taxes = $this->get_all(
251
-            [
252
-                ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, 'PRC_is_default' => 1],
253
-                'order_by' => ['Price_Type.PRT_order' => 'ASC', 'PRC_order' => 'ASC'],
254
-            ]
255
-        );
256
-        foreach ($all_taxes as $tax) {
257
-            if ($tax instanceof EE_Price) {
258
-                $taxes[ $tax->order() ][ $tax->ID() ] = $tax;
259
-            }
260
-        }
261
-        return $taxes;
262
-    }
237
+	/**
238
+	 * retrieve all prices that are taxes
239
+	 *
240
+	 * @return EE_Base_Class[]|EE_PRice[]
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws ReflectionException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 */
247
+	public function get_all_prices_that_are_taxes()
248
+	{
249
+		$taxes     = [];
250
+		$all_taxes = $this->get_all(
251
+			[
252
+				['Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, 'PRC_is_default' => 1],
253
+				'order_by' => ['Price_Type.PRT_order' => 'ASC', 'PRC_order' => 'ASC'],
254
+			]
255
+		);
256
+		foreach ($all_taxes as $tax) {
257
+			if ($tax instanceof EE_Price) {
258
+				$taxes[ $tax->order() ][ $tax->ID() ] = $tax;
259
+			}
260
+		}
261
+		return $taxes;
262
+	}
263 263
 
264 264
 
265
-    /**
266
-     * retrieve all prices for an ticket plus default global prices, but not taxes
267
-     *
268
-     * @param int $TKT_ID the id of the event.  If not included then we assume that this is a new ticket.
269
-     * @return EE_Base_Class[]|EE_PRice[]|boolean
270
-     * @throws EE_Error
271
-     */
272
-    public function get_all_ticket_prices_for_admin($TKT_ID = 0)
273
-    {
274
-        $array_of_price_objects = [];
275
-        if (empty($TKT_ID)) {
276
-            // if there is no tkt, get prices with no tkt ID, are global, are not a tax, and are active
277
-            // return that list
278
-            $default_prices = $this->get_all_default_prices();
265
+	/**
266
+	 * retrieve all prices for an ticket plus default global prices, but not taxes
267
+	 *
268
+	 * @param int $TKT_ID the id of the event.  If not included then we assume that this is a new ticket.
269
+	 * @return EE_Base_Class[]|EE_PRice[]|boolean
270
+	 * @throws EE_Error
271
+	 */
272
+	public function get_all_ticket_prices_for_admin($TKT_ID = 0)
273
+	{
274
+		$array_of_price_objects = [];
275
+		if (empty($TKT_ID)) {
276
+			// if there is no tkt, get prices with no tkt ID, are global, are not a tax, and are active
277
+			// return that list
278
+			$default_prices = $this->get_all_default_prices();
279 279
 
280
-            if ($default_prices) {
281
-                foreach ($default_prices as $price) {
282
-                    if ($price instanceof EE_Price) {
283
-                        $array_of_price_objects[ $price->type() ][] = $price;
284
-                    }
285
-                }
286
-                return $array_of_price_objects;
287
-            }
288
-            return [];
289
-        }
290
-        $ticket_prices = $this->get_all(
291
-            [
292
-                [
293
-                    'TKT_ID'      => $TKT_ID,
294
-                    'PRC_deleted' => 0,
295
-                ],
296
-                'order_by' => ['PRC_order' => 'ASC'],
297
-            ]
298
-        );
280
+			if ($default_prices) {
281
+				foreach ($default_prices as $price) {
282
+					if ($price instanceof EE_Price) {
283
+						$array_of_price_objects[ $price->type() ][] = $price;
284
+					}
285
+				}
286
+				return $array_of_price_objects;
287
+			}
288
+			return [];
289
+		}
290
+		$ticket_prices = $this->get_all(
291
+			[
292
+				[
293
+					'TKT_ID'      => $TKT_ID,
294
+					'PRC_deleted' => 0,
295
+				],
296
+				'order_by' => ['PRC_order' => 'ASC'],
297
+			]
298
+		);
299 299
 
300
-        if (! empty($ticket_prices)) {
301
-            foreach ($ticket_prices as $price) {
302
-                if ($price instanceof EE_Price) {
303
-                    $array_of_price_objects[ $price->type() ][] = $price;
304
-                }
305
-            }
306
-            return $array_of_price_objects;
307
-        }
308
-        return false;
309
-    }
300
+		if (! empty($ticket_prices)) {
301
+			foreach ($ticket_prices as $price) {
302
+				if ($price instanceof EE_Price) {
303
+					$array_of_price_objects[ $price->type() ][] = $price;
304
+				}
305
+			}
306
+			return $array_of_price_objects;
307
+		}
308
+		return false;
309
+	}
310 310
 
311 311
 
312
-    /**
313
-     * _sort_event_prices_by_type
314
-     *
315
-     * @param EE_Price $price_a
316
-     * @param EE_Price $price_b
317
-     * @return bool false on fail
318
-     */
319
-    public function _sort_event_prices_by_type(EE_Price $price_a, EE_Price $price_b)
320
-    {
321
-        if ($price_a->type_obj()->order() === $price_b->type_obj()->order()) {
322
-            return $this->_sort_event_prices_by_order($price_a, $price_b);
323
-        }
324
-        return $price_a->type_obj()->order() < $price_b->type_obj()->order() ? -1 : 1;
325
-    }
312
+	/**
313
+	 * _sort_event_prices_by_type
314
+	 *
315
+	 * @param EE_Price $price_a
316
+	 * @param EE_Price $price_b
317
+	 * @return bool false on fail
318
+	 */
319
+	public function _sort_event_prices_by_type(EE_Price $price_a, EE_Price $price_b)
320
+	{
321
+		if ($price_a->type_obj()->order() === $price_b->type_obj()->order()) {
322
+			return $this->_sort_event_prices_by_order($price_a, $price_b);
323
+		}
324
+		return $price_a->type_obj()->order() < $price_b->type_obj()->order() ? -1 : 1;
325
+	}
326 326
 
327 327
 
328
-    /**
329
-     *        _sort_event_prices_by_order
330
-     *
331
-     * @param EE_Price $price_a
332
-     * @param EE_Price $price_b
333
-     * @return bool false on fail
334
-     */
335
-    public function _sort_event_prices_by_order(EE_Price $price_a, EE_Price $price_b)
336
-    {
337
-        if ($price_a->order() === $price_b->order()) {
338
-            return 0;
339
-        }
340
-        return $price_a->order() < $price_b->order() ? -1 : 1;
341
-    }
328
+	/**
329
+	 *        _sort_event_prices_by_order
330
+	 *
331
+	 * @param EE_Price $price_a
332
+	 * @param EE_Price $price_b
333
+	 * @return bool false on fail
334
+	 */
335
+	public function _sort_event_prices_by_order(EE_Price $price_a, EE_Price $price_b)
336
+	{
337
+		if ($price_a->order() === $price_b->order()) {
338
+			return 0;
339
+		}
340
+		return $price_a->order() < $price_b->order() ? -1 : 1;
341
+	}
342 342
 
343 343
 
344
-    /**
345
-     * get all prices of a specific type
346
-     *
347
-     * @param int $type - PRT_ID
348
-     * @return EE_Base_Class[]|EE_PRice[]
349
-     * @throws EE_Error
350
-     */
351
-    public function get_all_prices_that_are_type($type = 0)
352
-    {
353
-        return $this->get_all(
354
-            [
355
-                [
356
-                    'PRT_ID' => $type,
357
-                ],
358
-                'order_by' => $this->_order_by_array_for_get_all_method(),
359
-            ]
360
-        );
361
-    }
344
+	/**
345
+	 * get all prices of a specific type
346
+	 *
347
+	 * @param int $type - PRT_ID
348
+	 * @return EE_Base_Class[]|EE_PRice[]
349
+	 * @throws EE_Error
350
+	 */
351
+	public function get_all_prices_that_are_type($type = 0)
352
+	{
353
+		return $this->get_all(
354
+			[
355
+				[
356
+					'PRT_ID' => $type,
357
+				],
358
+				'order_by' => $this->_order_by_array_for_get_all_method(),
359
+			]
360
+		);
361
+	}
362 362
 
363 363
 
364
-    /**
365
-     * Returns an array of the normal 'order_by' query parameter provided to the get_all query.
366
-     * Of course you don't have to use it, but this is the order we usually want to sort prices by
367
-     *
368
-     * @return array which can be used like so: $this->get_all(array(array(...where
369
-     *               stuff...),'order_by'=>$this->_order_by_array_for_get_all_method()));
370
-     */
371
-    public function _order_by_array_for_get_all_method()
372
-    {
373
-        return [
374
-            'PRC_order'            => 'ASC',
375
-            'Price_Type.PRT_order' => 'ASC',
376
-            'PRC_ID'               => 'ASC',
377
-        ];
378
-    }
364
+	/**
365
+	 * Returns an array of the normal 'order_by' query parameter provided to the get_all query.
366
+	 * Of course you don't have to use it, but this is the order we usually want to sort prices by
367
+	 *
368
+	 * @return array which can be used like so: $this->get_all(array(array(...where
369
+	 *               stuff...),'order_by'=>$this->_order_by_array_for_get_all_method()));
370
+	 */
371
+	public function _order_by_array_for_get_all_method()
372
+	{
373
+		return [
374
+			'PRC_order'            => 'ASC',
375
+			'Price_Type.PRT_order' => 'ASC',
376
+			'PRC_ID'               => 'ASC',
377
+		];
378
+	}
379 379
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event_Message_Template.model.php 1 patch
Indentation   +119 added lines, -119 removed lines patch added patch discarded remove patch
@@ -11,134 +11,134 @@
 block discarded – undo
11 11
  */
12 12
 class EEM_Event_Message_Template extends EEM_Base
13 13
 {
14
-    // private instance of the EEM_Event_Message_Template object
15
-    protected static $_instance = null;
14
+	// private instance of the EEM_Event_Message_Template object
15
+	protected static $_instance = null;
16 16
 
17 17
 
18
-    /**
19
-     * protected constructor to prevent direct creation
20
-     *
21
-     * @param null $timezone
22
-     * @throws EE_Error
23
-     */
24
-    protected function __construct($timezone = null)
25
-    {
26
-        $this->singular_item = esc_html__('Event Message Template', 'event_espresso');
27
-        $this->plural_item = esc_html__('Event Message Templates', 'event_espresso');
18
+	/**
19
+	 * protected constructor to prevent direct creation
20
+	 *
21
+	 * @param null $timezone
22
+	 * @throws EE_Error
23
+	 */
24
+	protected function __construct($timezone = null)
25
+	{
26
+		$this->singular_item = esc_html__('Event Message Template', 'event_espresso');
27
+		$this->plural_item = esc_html__('Event Message Templates', 'event_espresso');
28 28
 
29
-        $this->_tables = [
30
-            'Event_Message_Template' => new EE_Primary_Table('esp_event_message_template', 'EMT_ID'),
31
-        ];
32
-        $this->_fields = [
33
-            'Event_Message_Template' => [
34
-                'EMT_ID' => new EE_Primary_Key_Int_Field(
35
-                    'EMT_ID',
36
-                    esc_html__('Event Message Template ID', 'event_espresso')
37
-                ),
38
-                'EVT_ID' => new EE_Foreign_Key_Int_Field(
39
-                    'EVT_ID',
40
-                    esc_html__('The ID to the Event', 'event_espresso'),
41
-                    false,
42
-                    0,
43
-                    'Event'
44
-                ),
45
-                'GRP_ID' => new EE_Foreign_Key_Int_Field(
46
-                    'GRP_ID',
47
-                    esc_html__('The ID to the Message Template Group', 'event_espresso'),
48
-                    false,
49
-                    0,
50
-                    'Message_Template_Group'
51
-                ),
52
-            ],
53
-        ];
54
-        $this->_model_relations = [
55
-            'Event'                  => new EE_Belongs_To_Relation(),
56
-            'Message_Template_Group' => new EE_Belongs_To_Relation(),
57
-        ];
58
-        $path_to_event = 'Event';
59
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
60
-            $path_to_event
61
-        );
62
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
63
-            $path_to_event
64
-        );
65
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
66
-            $path_to_event
67
-        );
68
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected(
69
-            $path_to_event,
70
-            EEM_Base::caps_edit
71
-        );
72
-        parent::__construct($timezone);
73
-    }
29
+		$this->_tables = [
30
+			'Event_Message_Template' => new EE_Primary_Table('esp_event_message_template', 'EMT_ID'),
31
+		];
32
+		$this->_fields = [
33
+			'Event_Message_Template' => [
34
+				'EMT_ID' => new EE_Primary_Key_Int_Field(
35
+					'EMT_ID',
36
+					esc_html__('Event Message Template ID', 'event_espresso')
37
+				),
38
+				'EVT_ID' => new EE_Foreign_Key_Int_Field(
39
+					'EVT_ID',
40
+					esc_html__('The ID to the Event', 'event_espresso'),
41
+					false,
42
+					0,
43
+					'Event'
44
+				),
45
+				'GRP_ID' => new EE_Foreign_Key_Int_Field(
46
+					'GRP_ID',
47
+					esc_html__('The ID to the Message Template Group', 'event_espresso'),
48
+					false,
49
+					0,
50
+					'Message_Template_Group'
51
+				),
52
+			],
53
+		];
54
+		$this->_model_relations = [
55
+			'Event'                  => new EE_Belongs_To_Relation(),
56
+			'Message_Template_Group' => new EE_Belongs_To_Relation(),
57
+		];
58
+		$path_to_event = 'Event';
59
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
60
+			$path_to_event
61
+		);
62
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
63
+			$path_to_event
64
+		);
65
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
66
+			$path_to_event
67
+		);
68
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected(
69
+			$path_to_event,
70
+			EEM_Base::caps_edit
71
+		);
72
+		parent::__construct($timezone);
73
+	}
74 74
 
75 75
 
76
-    /**
77
-     * helper method to simply return an array of event ids for events attached to the given
78
-     * message template group.
79
-     *
80
-     * @param int $GRP_ID The MTP group we want attached events for.
81
-     * @return  array               An array of event ids.
82
-     * @throws EE_Error
83
-     * @since 4.3.0
84
-     */
85
-    public function get_attached_event_ids($GRP_ID)
86
-    {
87
-        $event_ids = $this->_get_all_wpdb_results([['GRP_ID' => $GRP_ID]], ARRAY_N, 'EVT_ID');
88
-        $event_ids = call_user_func_array('array_merge', $event_ids);
89
-        return $event_ids;
90
-    }
76
+	/**
77
+	 * helper method to simply return an array of event ids for events attached to the given
78
+	 * message template group.
79
+	 *
80
+	 * @param int $GRP_ID The MTP group we want attached events for.
81
+	 * @return  array               An array of event ids.
82
+	 * @throws EE_Error
83
+	 * @since 4.3.0
84
+	 */
85
+	public function get_attached_event_ids($GRP_ID)
86
+	{
87
+		$event_ids = $this->_get_all_wpdb_results([['GRP_ID' => $GRP_ID]], ARRAY_N, 'EVT_ID');
88
+		$event_ids = call_user_func_array('array_merge', $event_ids);
89
+		return $event_ids;
90
+	}
91 91
 
92 92
 
93
-    /**
94
-     * helper method for clearing event/group relations for the given event ids and grp ids.
95
-     *
96
-     * @param array $GRP_IDs An array of GRP_IDs. Optional. If empty then there must be EVT IDs.
97
-     * @param array $EVT_IDs An array of EVT_IDs.  Optional. If empty then there must be GRP IDs.
98
-     * @return int             How many rows were deleted.
99
-     * @throws EE_Error
100
-     * @throws EE_Error
101
-     */
102
-    public function delete_event_group_relations($GRP_IDs = [], $EVT_IDs = [])
103
-    {
104
-        if (empty($GRP_IDs) && empty($EVT_IDs)) {
105
-            throw new EE_Error(
106
-                sprintf(
107
-                    esc_html__(
108
-                        '%s requires either an array of GRP_IDs or EVT_IDs or both, but both cannot be empty.',
109
-                        'event_espresso'
110
-                    ),
111
-                    __METHOD__
112
-                )
113
-            );
114
-        }
93
+	/**
94
+	 * helper method for clearing event/group relations for the given event ids and grp ids.
95
+	 *
96
+	 * @param array $GRP_IDs An array of GRP_IDs. Optional. If empty then there must be EVT IDs.
97
+	 * @param array $EVT_IDs An array of EVT_IDs.  Optional. If empty then there must be GRP IDs.
98
+	 * @return int             How many rows were deleted.
99
+	 * @throws EE_Error
100
+	 * @throws EE_Error
101
+	 */
102
+	public function delete_event_group_relations($GRP_IDs = [], $EVT_IDs = [])
103
+	{
104
+		if (empty($GRP_IDs) && empty($EVT_IDs)) {
105
+			throw new EE_Error(
106
+				sprintf(
107
+					esc_html__(
108
+						'%s requires either an array of GRP_IDs or EVT_IDs or both, but both cannot be empty.',
109
+						'event_espresso'
110
+					),
111
+					__METHOD__
112
+				)
113
+			);
114
+		}
115 115
 
116
-        $where = [];
117
-        if (! empty($GRP_IDs)) {
118
-            $where['GRP_ID'] = ['IN', (array) $GRP_IDs];
119
-        }
120
-        if (! empty($EVT_IDs)) {
121
-            $where['EVT_ID'] = ['IN', (array) $EVT_IDs];
122
-        }
116
+		$where = [];
117
+		if (! empty($GRP_IDs)) {
118
+			$where['GRP_ID'] = ['IN', (array) $GRP_IDs];
119
+		}
120
+		if (! empty($EVT_IDs)) {
121
+			$where['EVT_ID'] = ['IN', (array) $EVT_IDs];
122
+		}
123 123
 
124
-        return $this->delete([$where], false);
125
-    }
124
+		return $this->delete([$where], false);
125
+	}
126 126
 
127 127
 
128
-    /**
129
-     * returns a numerically indexed array
130
-     * with values that correspond to the 'GRP_ID' column
131
-     * where the 'EVT_ID' column matches that of the supplied event
132
-     *
133
-     * @param EE_Event $event
134
-     * @return array
135
-     * @throws EE_Error
136
-     * @throws ReflectionException
137
-     * @since   $VID:$
138
-     */
139
-    public function messageTemplateGroupIDsForEvent(EE_Event $event): array
140
-    {
141
-        $results = $this->get_col([['EVT_ID' => $event->ID()]], 'GRP_ID');
142
-        return $results !== false ? $results : [];
143
-    }
128
+	/**
129
+	 * returns a numerically indexed array
130
+	 * with values that correspond to the 'GRP_ID' column
131
+	 * where the 'EVT_ID' column matches that of the supplied event
132
+	 *
133
+	 * @param EE_Event $event
134
+	 * @return array
135
+	 * @throws EE_Error
136
+	 * @throws ReflectionException
137
+	 * @since   $VID:$
138
+	 */
139
+	public function messageTemplateGroupIDsForEvent(EE_Event $event): array
140
+	{
141
+		$results = $this->get_col([['EVT_ID' => $event->ID()]], 'GRP_ID');
142
+		return $results !== false ? $results : [];
143
+	}
144 144
 }
Please login to merge, or discard this patch.
core/domain/entities/admin/GraphQLData/GraphQLData.php 1 patch
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -14,74 +14,74 @@
 block discarded – undo
14 14
  */
15 15
 abstract class GraphQLData implements GraphQLDataInterface
16 16
 {
17
-    /**
18
-     * @var string $namespace The graphql namespace/prefix.
19
-     */
20
-    protected $namespace = 'Espresso';
17
+	/**
18
+	 * @var string $namespace The graphql namespace/prefix.
19
+	 */
20
+	protected $namespace = 'Espresso';
21 21
 
22
-    /**
23
-     * @var array $params
24
-     */
25
-    private $params = [];
22
+	/**
23
+	 * @var array $params
24
+	 */
25
+	private $params = [];
26 26
 
27 27
 
28
-    /**
29
-     * @param array $params
30
-     */
31
-    public function setParams(array $params)
32
-    {
33
-        $this->params = $params;
34
-    }
28
+	/**
29
+	 * @param array $params
30
+	 */
31
+	public function setParams(array $params)
32
+	{
33
+		$this->params = $params;
34
+	}
35 35
 
36 36
 
37 37
 
38
-    /**
39
-     * @param string $field_key
40
-     * @param array  $where_params
41
-     * @return mixed|null
42
-     * @since $VID:$
43
-     */
44
-    protected function getQueryResponse(string $field_key, array $where_params = [])
45
-    {
46
-        if (! empty($where_params)) {
47
-            if (! array_key_exists('variables', $this->params)) {
48
-                $this->params['variables'] = [];
49
-            }
50
-            $this->params['variables']['where'] = $where_params;
51
-        }
38
+	/**
39
+	 * @param string $field_key
40
+	 * @param array  $where_params
41
+	 * @return mixed|null
42
+	 * @since $VID:$
43
+	 */
44
+	protected function getQueryResponse(string $field_key, array $where_params = [])
45
+	{
46
+		if (! empty($where_params)) {
47
+			if (! array_key_exists('variables', $this->params)) {
48
+				$this->params['variables'] = [];
49
+			}
50
+			$this->params['variables']['where'] = $where_params;
51
+		}
52 52
 
53
-        $responseData = $this->makeGraphQLRequest($this->params);
54
-        return ! empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
55
-    }
53
+		$responseData = $this->makeGraphQLRequest($this->params);
54
+		return ! empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
55
+	}
56 56
 
57 57
 
58
-    /**
59
-     * @param array $data
60
-     * @return array|null
61
-     * @since $VID:$
62
-     */
63
-    protected function makeGraphQLRequest(array $data)
64
-    {
65
-        $error = '';
66
-        try {
67
-            $response = graphql($data);
68
-            if (! empty($response['data'])) {
69
-                return $response['data'];
70
-            }
71
-            $error = ! empty($response['errors'])
72
-                ? print_r($response['errors'], true)
73
-                : esc_html__(
74
-                    'An unknown error has occurred during the GraphQL request and no data was found to return.',
75
-                    'event_espresso'
76
-                );
77
-        } catch (Exception $e) {
78
-            if (defined('GRAPHQL_DEBUG') && GRAPHQL_DEBUG) {
79
-                $error = $e->getMessage();
80
-            }
81
-        }
82
-        if ($error !== '') {
83
-            error_log($error);
84
-        }
85
-        return null;
86
-    }
58
+	/**
59
+	 * @param array $data
60
+	 * @return array|null
61
+	 * @since $VID:$
62
+	 */
63
+	protected function makeGraphQLRequest(array $data)
64
+	{
65
+		$error = '';
66
+		try {
67
+			$response = graphql($data);
68
+			if (! empty($response['data'])) {
69
+				return $response['data'];
70
+			}
71
+			$error = ! empty($response['errors'])
72
+				? print_r($response['errors'], true)
73
+				: esc_html__(
74
+					'An unknown error has occurred during the GraphQL request and no data was found to return.',
75
+					'event_espresso'
76
+				);
77
+		} catch (Exception $e) {
78
+			if (defined('GRAPHQL_DEBUG') && GRAPHQL_DEBUG) {
79
+				$error = $e->getMessage();
80
+			}
81
+		}
82
+		if ($error !== '') {
83
+			error_log($error);
84
+		}
85
+		return null;
86
+	}
87 87
 }
Please login to merge, or discard this patch.