Completed
Branch BUG/batch-strings-overridden (c36a9a)
by
unknown
10:01 queued 01:18
created
core/libraries/form_sections/inputs/EE_File_Input.input.php 2 patches
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -19,86 +19,86 @@
 block discarded – undo
19 19
  */
20 20
 class EE_File_Input extends EE_Form_Input_Base
21 21
 {
22
-    /**
23
-     * @var array
24
-     */
25
-    protected $allowed_file_extensions;
22
+	/**
23
+	 * @var array
24
+	 */
25
+	protected $allowed_file_extensions;
26 26
 
27
-    /**
28
-     * @var array
29
-     */
30
-    protected $allowed_mime_types;
27
+	/**
28
+	 * @var array
29
+	 */
30
+	protected $allowed_mime_types;
31 31
 
32
-    /**
33
-     * @param array $options
34
-     * @throws InvalidArgumentException
35
-     */
36
-    public function __construct($options = array())
37
-    {
38
-        if (isset($options['allowed_file_extensions'])) {
39
-            $this->allowed_file_extensions = (array) $options['allowed_file_extensions'];
40
-        } else {
41
-            $this->allowed_file_extensions = ['csv'];
42
-        }
43
-        if (isset($options['allowed_mime_types'])) {
44
-            $this->allowed_mime_types = (array) $options['allowed_file_extensions'];
45
-        } else {
46
-            $this->allowed_mime_types = ['text/csv'];
47
-        }
32
+	/**
33
+	 * @param array $options
34
+	 * @throws InvalidArgumentException
35
+	 */
36
+	public function __construct($options = array())
37
+	{
38
+		if (isset($options['allowed_file_extensions'])) {
39
+			$this->allowed_file_extensions = (array) $options['allowed_file_extensions'];
40
+		} else {
41
+			$this->allowed_file_extensions = ['csv'];
42
+		}
43
+		if (isset($options['allowed_mime_types'])) {
44
+			$this->allowed_mime_types = (array) $options['allowed_file_extensions'];
45
+		} else {
46
+			$this->allowed_mime_types = ['text/csv'];
47
+		}
48 48
 
49
-        $this->_set_display_strategy(new EE_File_Input_Display_Strategy());
50
-        $this->_set_normalization_strategy(new EE_File_Normalization());
51
-        $this->add_validation_strategy(
52
-            new EE_Text_Validation_Strategy(
53
-                sprintf(
54
-                    // translators: %1$s is a list of allowed file extensions.
55
-                    esc_html__('Please provide a file of the requested filetype: %1$s', 'event_espresso'),
56
-                    implode(', ', $this->allowed_file_extensions)
57
-                ),
58
-                '~.*\.(' . implode('|', $this->allowed_file_extensions) . ')$~'
59
-            )
60
-        );
61
-        parent::__construct($options);
49
+		$this->_set_display_strategy(new EE_File_Input_Display_Strategy());
50
+		$this->_set_normalization_strategy(new EE_File_Normalization());
51
+		$this->add_validation_strategy(
52
+			new EE_Text_Validation_Strategy(
53
+				sprintf(
54
+					// translators: %1$s is a list of allowed file extensions.
55
+					esc_html__('Please provide a file of the requested filetype: %1$s', 'event_espresso'),
56
+					implode(', ', $this->allowed_file_extensions)
57
+				),
58
+				'~.*\.(' . implode('|', $this->allowed_file_extensions) . ')$~'
59
+			)
60
+		);
61
+		parent::__construct($options);
62 62
 
63 63
 //        It would be great to add this HTML attribute, but jQuery validate chokes on it.
64
-        $this->set_other_html_attributes(
65
-            $this->other_html_attributes()
66
-            . ' extension="'
67
-            . implode(
68
-                ',',
69
-                $this->allowed_file_extensions
70
-            )
71
-            . '"'
72
-        );
73
-    }
64
+		$this->set_other_html_attributes(
65
+			$this->other_html_attributes()
66
+			. ' extension="'
67
+			. implode(
68
+				',',
69
+				$this->allowed_file_extensions
70
+			)
71
+			. '"'
72
+		);
73
+	}
74 74
 
75
-    /**
76
-     * $_FILES has a really weird structure. So we let `FilesDataHandler` take care of finding the file info for
77
-     * this input.
78
-     * @since $VID:$
79
-     * @param array $req_data
80
-     * @return FileSubmissionInterface
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws InvalidInterfaceException
84
-     */
85
-    public function find_form_data_for_this_section($req_data)
86
-    {
87
-        // ignore $req_data. Files are in the files data handler.
88
-        $fileDataHandler = LoaderFactory::getLoader()->getShared(
89
-            'EventEspresso\core\services\request\files\FilesDataHandler'
90
-        );
91
-        return $fileDataHandler->getFileObject($this->html_name());
92
-    }
75
+	/**
76
+	 * $_FILES has a really weird structure. So we let `FilesDataHandler` take care of finding the file info for
77
+	 * this input.
78
+	 * @since $VID:$
79
+	 * @param array $req_data
80
+	 * @return FileSubmissionInterface
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws InvalidInterfaceException
84
+	 */
85
+	public function find_form_data_for_this_section($req_data)
86
+	{
87
+		// ignore $req_data. Files are in the files data handler.
88
+		$fileDataHandler = LoaderFactory::getLoader()->getShared(
89
+			'EventEspresso\core\services\request\files\FilesDataHandler'
90
+		);
91
+		return $fileDataHandler->getFileObject($this->html_name());
92
+	}
93 93
 
94
-    /**
95
-     * Don't transform the file submission object into a string, thanks.
96
-     *
97
-     * @param string $value
98
-     * @return null|string
99
-     */
100
-    protected function _sanitize($value)
101
-    {
102
-        return $value;
103
-    }
94
+	/**
95
+	 * Don't transform the file submission object into a string, thanks.
96
+	 *
97
+	 * @param string $value
98
+	 * @return null|string
99
+	 */
100
+	protected function _sanitize($value)
101
+	{
102
+		return $value;
103
+	}
104 104
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@
 block discarded – undo
55 55
                     esc_html__('Please provide a file of the requested filetype: %1$s', 'event_espresso'),
56 56
                     implode(', ', $this->allowed_file_extensions)
57 57
                 ),
58
-                '~.*\.(' . implode('|', $this->allowed_file_extensions) . ')$~'
58
+                '~.*\.('.implode('|', $this->allowed_file_extensions).')$~'
59 59
             )
60 60
         );
61 61
         parent::__construct($options);
Please login to merge, or discard this patch.
core/libraries/form_sections/form_handlers/FormHandler.php 1 patch
Indentation   +635 added lines, -635 removed lines patch added patch discarded remove patch
@@ -29,639 +29,639 @@
 block discarded – undo
29 29
 abstract class FormHandler implements FormHandlerInterface
30 30
 {
31 31
 
32
-    /**
33
-     * will add opening and closing HTML form tags as well as a submit button
34
-     */
35
-    const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
36
-
37
-    /**
38
-     * will add opening and closing HTML form tags but NOT a submit button
39
-     */
40
-    const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
41
-
42
-    /**
43
-     * will NOT add opening and closing HTML form tags but will add a submit button
44
-     */
45
-    const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
46
-
47
-    /**
48
-     * will NOT add opening and closing HTML form tags NOR a submit button
49
-     */
50
-    const DO_NOT_SETUP_FORM = 'do_not_setup_form';
51
-
52
-    /**
53
-     * if set to false, then this form has no displayable content,
54
-     * and will only be used for processing data sent passed via GET or POST
55
-     * defaults to true ( ie: form has displayable content )
56
-     *
57
-     * @var boolean $displayable
58
-     */
59
-    private $displayable = true;
60
-
61
-    /**
62
-     * @var string $form_name
63
-     */
64
-    private $form_name;
65
-
66
-    /**
67
-     * @var string $admin_name
68
-     */
69
-    private $admin_name;
70
-
71
-    /**
72
-     * @var string $slug
73
-     */
74
-    private $slug;
75
-
76
-    /**
77
-     * @var string $submit_btn_text
78
-     */
79
-    private $submit_btn_text;
80
-
81
-    /**
82
-     * @var string $form_action
83
-     */
84
-    private $form_action;
85
-
86
-    /**
87
-     * form params in key value pairs
88
-     * can be added to form action URL or as hidden inputs
89
-     *
90
-     * @var array $form_args
91
-     */
92
-    private $form_args = array();
93
-
94
-    /**
95
-     * value of one of the string constant above
96
-     *
97
-     * @var string $form_config
98
-     */
99
-    private $form_config;
100
-
101
-    /**
102
-     * whether or not the form was determined to be invalid
103
-     *
104
-     * @var boolean $form_has_errors
105
-     */
106
-    private $form_has_errors;
107
-
108
-    /**
109
-     * the absolute top level form section being used on the page
110
-     *
111
-     * @var EE_Form_Section_Proper $form
112
-     */
113
-    private $form;
114
-
115
-    /**
116
-     * @var EE_Registry $registry
117
-     */
118
-    protected $registry;
119
-
120
-    // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd
121
-    /**
122
-     * Form constructor.
123
-     *
124
-     * @param string      $form_name
125
-     * @param string      $admin_name
126
-     * @param string      $slug
127
-     * @param string      $form_action
128
-     * @param string      $form_config
129
-     * @param EE_Registry $registry
130
-     * @throws InvalidDataTypeException
131
-     * @throws DomainException
132
-     * @throws InvalidArgumentException
133
-     */
134
-    public function __construct(
135
-        $form_name,
136
-        $admin_name,
137
-        $slug,
138
-        $form_action = '',
139
-        $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
140
-        EE_Registry $registry
141
-    ) {
142
-        $this->setFormName($form_name);
143
-        $this->setAdminName($admin_name);
144
-        $this->setSlug($slug);
145
-        $this->setFormAction($form_action);
146
-        $this->setFormConfig($form_config);
147
-        $this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
148
-        $this->registry = $registry;
149
-    }
150
-
151
-
152
-    /**
153
-     * @return array
154
-     */
155
-    public static function getFormConfigConstants()
156
-    {
157
-        return array(
158
-            FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
159
-            FormHandler::ADD_FORM_TAGS_ONLY,
160
-            FormHandler::ADD_FORM_SUBMIT_ONLY,
161
-            FormHandler::DO_NOT_SETUP_FORM,
162
-        );
163
-    }
164
-
165
-
166
-    /**
167
-     * @param bool $for_display
168
-     * @return EE_Form_Section_Proper
169
-     * @throws EE_Error
170
-     * @throws LogicException
171
-     */
172
-    public function form($for_display = false)
173
-    {
174
-        if (! $this->formIsValid()) {
175
-            return null;
176
-        }
177
-        if ($for_display) {
178
-            $form_config = $this->formConfig();
179
-            if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
180
-                || $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
181
-            ) {
182
-                $this->appendSubmitButton();
183
-                $this->clearFormButtonFloats();
184
-            }
185
-        }
186
-        return $this->form;
187
-    }
188
-
189
-
190
-    /**
191
-     * @return boolean
192
-     * @throws LogicException
193
-     */
194
-    public function formIsValid()
195
-    {
196
-        if ($this->form instanceof EE_Form_Section_Proper) {
197
-            return true;
198
-        }
199
-        $form = apply_filters(
200
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
201
-            $this->generate(),
202
-            $this
203
-        );
204
-        if ($this->verifyForm($form)) {
205
-            $this->setForm($form);
206
-        }
207
-        return true;
208
-    }
209
-
210
-
211
-    /**
212
-     * @param EE_Form_Section_Proper|null $form
213
-     * @return bool
214
-     * @throws LogicException
215
-     */
216
-    public function verifyForm(EE_Form_Section_Proper $form = null)
217
-    {
218
-        $form = $form !== null ? $form : $this->form;
219
-        if ($form instanceof EE_Form_Section_Proper) {
220
-            return true;
221
-        }
222
-        throw new LogicException(
223
-            sprintf(
224
-                esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
225
-                $this->form_name,
226
-                var_export($form, true)
227
-            )
228
-        );
229
-    }
230
-
231
-
232
-    /**
233
-     * @param EE_Form_Section_Proper $form
234
-     */
235
-    public function setForm(EE_Form_Section_Proper $form)
236
-    {
237
-        $this->form = $form;
238
-    }
239
-
240
-
241
-    /**
242
-     * @return boolean
243
-     */
244
-    public function displayable()
245
-    {
246
-        return $this->displayable;
247
-    }
248
-
249
-
250
-    /**
251
-     * @param boolean $displayable
252
-     */
253
-    public function setDisplayable($displayable = false)
254
-    {
255
-        $this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
256
-    }
257
-
258
-
259
-    /**
260
-     * a public name for the form that can be displayed on the frontend of a site
261
-     *
262
-     * @return string
263
-     */
264
-    public function formName()
265
-    {
266
-        return $this->form_name;
267
-    }
268
-
269
-
270
-    /**
271
-     * @param string $form_name
272
-     * @throws InvalidDataTypeException
273
-     */
274
-    public function setFormName($form_name)
275
-    {
276
-        if (! is_string($form_name)) {
277
-            throw new InvalidDataTypeException('$form_name', $form_name, 'string');
278
-        }
279
-        $this->form_name = $form_name;
280
-    }
281
-
282
-
283
-    /**
284
-     * a public name for the form that can be displayed, but only in the admin
285
-     *
286
-     * @return string
287
-     */
288
-    public function adminName()
289
-    {
290
-        return $this->admin_name;
291
-    }
292
-
293
-
294
-    /**
295
-     * @param string $admin_name
296
-     * @throws InvalidDataTypeException
297
-     */
298
-    public function setAdminName($admin_name)
299
-    {
300
-        if (! is_string($admin_name)) {
301
-            throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
302
-        }
303
-        $this->admin_name = $admin_name;
304
-    }
305
-
306
-
307
-    /**
308
-     * a URL friendly string that can be used for identifying the form
309
-     *
310
-     * @return string
311
-     */
312
-    public function slug()
313
-    {
314
-        return $this->slug;
315
-    }
316
-
317
-
318
-    /**
319
-     * @param string $slug
320
-     * @throws InvalidDataTypeException
321
-     */
322
-    public function setSlug($slug)
323
-    {
324
-        if (! is_string($slug)) {
325
-            throw new InvalidDataTypeException('$slug', $slug, 'string');
326
-        }
327
-        $this->slug = $slug;
328
-    }
329
-
330
-
331
-    /**
332
-     * @return string
333
-     */
334
-    public function submitBtnText()
335
-    {
336
-        return $this->submit_btn_text;
337
-    }
338
-
339
-
340
-    /**
341
-     * @param string $submit_btn_text
342
-     * @throws InvalidDataTypeException
343
-     * @throws InvalidArgumentException
344
-     */
345
-    public function setSubmitBtnText($submit_btn_text)
346
-    {
347
-        if (! is_string($submit_btn_text)) {
348
-            throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
349
-        }
350
-        if (empty($submit_btn_text)) {
351
-            throw new InvalidArgumentException(
352
-                esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
353
-            );
354
-        }
355
-        $this->submit_btn_text = $submit_btn_text;
356
-    }
357
-
358
-
359
-    /**
360
-     * @return string
361
-     */
362
-    public function formAction()
363
-    {
364
-        return ! empty($this->form_args)
365
-            ? add_query_arg($this->form_args, $this->form_action)
366
-            : $this->form_action;
367
-    }
368
-
369
-
370
-    /**
371
-     * @param string $form_action
372
-     * @throws InvalidDataTypeException
373
-     */
374
-    public function setFormAction($form_action)
375
-    {
376
-        if (! is_string($form_action)) {
377
-            throw new InvalidDataTypeException('$form_action', $form_action, 'string');
378
-        }
379
-        $this->form_action = $form_action;
380
-    }
381
-
382
-
383
-    /**
384
-     * @param array $form_args
385
-     * @throws InvalidDataTypeException
386
-     * @throws InvalidArgumentException
387
-     */
388
-    public function addFormActionArgs($form_args = array())
389
-    {
390
-        if (is_object($form_args)) {
391
-            throw new InvalidDataTypeException(
392
-                '$form_args',
393
-                $form_args,
394
-                'anything other than an object was expected.'
395
-            );
396
-        }
397
-        if (empty($form_args)) {
398
-            throw new InvalidArgumentException(
399
-                esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
400
-            );
401
-        }
402
-        $this->form_args = array_merge($this->form_args, $form_args);
403
-    }
404
-
405
-
406
-    /**
407
-     * @return string
408
-     */
409
-    public function formConfig()
410
-    {
411
-        return $this->form_config;
412
-    }
413
-
414
-
415
-    /**
416
-     * @param string $form_config
417
-     * @throws DomainException
418
-     */
419
-    public function setFormConfig($form_config)
420
-    {
421
-        if (! in_array(
422
-            $form_config,
423
-            array(
424
-                FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
425
-                FormHandler::ADD_FORM_TAGS_ONLY,
426
-                FormHandler::ADD_FORM_SUBMIT_ONLY,
427
-                FormHandler::DO_NOT_SETUP_FORM,
428
-            ),
429
-            true
430
-        )
431
-        ) {
432
-            throw new DomainException(
433
-                sprintf(
434
-                    esc_html__(
435
-                        '"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
436
-                        'event_espresso'
437
-                    ),
438
-                    $form_config
439
-                )
440
-            );
441
-        }
442
-        $this->form_config = $form_config;
443
-    }
444
-
445
-
446
-    /**
447
-     * called after the form is instantiated
448
-     * and used for performing any logic that needs to occur early
449
-     * before any of the other methods are called.
450
-     * returns true if everything is ok to proceed,
451
-     * and false if no further form logic should be implemented
452
-     *
453
-     * @return boolean
454
-     */
455
-    public function initialize()
456
-    {
457
-        $this->form_has_errors = EE_Error::has_error(true);
458
-        return true;
459
-    }
460
-
461
-
462
-    /**
463
-     * used for setting up css and js
464
-     *
465
-     * @return void
466
-     * @throws LogicException
467
-     * @throws EE_Error
468
-     */
469
-    public function enqueueStylesAndScripts()
470
-    {
471
-        $this->form()->enqueue_js();
472
-    }
473
-
474
-
475
-    /**
476
-     * creates and returns the actual form
477
-     *
478
-     * @return EE_Form_Section_Proper
479
-     */
480
-    abstract public function generate();
481
-
482
-
483
-    /**
484
-     * creates and returns an EE_Submit_Input labeled "Submit"
485
-     *
486
-     * @param string $text
487
-     * @return EE_Submit_Input
488
-     */
489
-    public function generateSubmitButton($text = '')
490
-    {
491
-        $text = ! empty($text) ? $text : $this->submitBtnText();
492
-        return new EE_Submit_Input(
493
-            array(
494
-                'html_name'             => 'ee-form-submit-' . $this->slug(),
495
-                'html_id'               => 'ee-form-submit-' . $this->slug(),
496
-                'html_class'            => 'ee-form-submit',
497
-                'html_label'            => ' ',
498
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
499
-                'default'               => $text,
500
-            )
501
-        );
502
-    }
503
-
504
-
505
-    /**
506
-     * calls generateSubmitButton() and appends it onto the form along with a float clearing div
507
-     *
508
-     * @param string $text
509
-     * @return void
510
-     * @throws EE_Error
511
-     */
512
-    public function appendSubmitButton($text = '')
513
-    {
514
-        if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
515
-            return;
516
-        }
517
-        $this->form->add_subsections(
518
-            array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
519
-            null,
520
-            false
521
-        );
522
-    }
523
-
524
-
525
-    /**
526
-     * creates and returns an EE_Submit_Input labeled "Cancel"
527
-     *
528
-     * @param string $text
529
-     * @return EE_Submit_Input
530
-     */
531
-    public function generateCancelButton($text = '')
532
-    {
533
-        $cancel_button = new EE_Submit_Input(
534
-            array(
535
-                'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
536
-                'html_id'               => 'ee-cancel-form-' . $this->slug(),
537
-                'html_class'            => 'ee-cancel-form',
538
-                'html_label'            => ' ',
539
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
540
-                'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
541
-            )
542
-        );
543
-        $cancel_button->set_button_css_attributes(false);
544
-        return $cancel_button;
545
-    }
546
-
547
-
548
-    /**
549
-     * appends a float clearing div onto end of form
550
-     *
551
-     * @return void
552
-     * @throws EE_Error
553
-     */
554
-    public function clearFormButtonFloats()
555
-    {
556
-        $this->form->add_subsections(
557
-            array(
558
-                'clear-submit-btn-float' => new EE_Form_Section_HTML(
559
-                    EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
560
-                ),
561
-            ),
562
-            null,
563
-            false
564
-        );
565
-    }
566
-
567
-
568
-    /**
569
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
570
-     * returns a string of HTML that can be directly echoed in a template
571
-     *
572
-     * @return string
573
-     * @throws \InvalidArgumentException
574
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
575
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
576
-     * @throws LogicException
577
-     * @throws EE_Error
578
-     */
579
-    public function display()
580
-    {
581
-        $form_html = apply_filters(
582
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
583
-            ''
584
-        );
585
-        $form_config = $this->formConfig();
586
-        if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
587
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
588
-        ) {
589
-            $additional_props = $this->requiresMultipartEnctype()
590
-                ? 'enctype="multipart/form-data"'
591
-                : '';
592
-            $form_html .= $this->form()->form_open(
593
-                $this->formAction(),
594
-                'POST',
595
-                $additional_props
596
-            );
597
-        }
598
-        $form_html .= $this->form(true)->get_html();
599
-        if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
600
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
601
-        ) {
602
-            $form_html .= $this->form()->form_close();
603
-        }
604
-        $form_html .= apply_filters(
605
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
606
-            ''
607
-        );
608
-        return $form_html;
609
-    }
610
-
611
-    /**
612
-     * Determines if this form needs "enctype='multipart/form-data'" or not.
613
-     * @since $VID:$
614
-     * @return bool
615
-     * @throws EE_Error
616
-     */
617
-    public function requiresMultipartEnctype()
618
-    {
619
-        foreach ($this->form()->inputs_in_subsections() as $input) {
620
-            if ($input instanceof EE_File_Input) {
621
-                return true;
622
-            }
623
-        }
624
-        return false;
625
-    }
626
-
627
-
628
-    /**
629
-     * handles processing the form submission
630
-     * returns true or false depending on whether the form was processed successfully or not
631
-     *
632
-     * @param array $submitted_form_data
633
-     * @return array
634
-     * @throws \InvalidArgumentException
635
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
636
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
637
-     * @throws EE_Error
638
-     * @throws LogicException
639
-     * @throws InvalidFormSubmissionException
640
-     */
641
-    public function process($submitted_form_data = array())
642
-    {
643
-        if (! $this->form()->was_submitted($submitted_form_data)) {
644
-            throw new InvalidFormSubmissionException($this->form_name);
645
-        }
646
-        $this->form(true)->receive_form_submission($submitted_form_data);
647
-        if (! $this->form()->is_valid()) {
648
-            throw new InvalidFormSubmissionException(
649
-                $this->form_name,
650
-                sprintf(
651
-                    esc_html__(
652
-                        'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
653
-                        'event_espresso'
654
-                    ),
655
-                    $this->form_name,
656
-                    '<br />',
657
-                    implode('<br />', $this->form()->get_validation_errors_accumulated())
658
-                )
659
-            );
660
-        }
661
-        return apply_filters(
662
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
663
-            $this->form()->valid_data(),
664
-            $this
665
-        );
666
-    }
32
+	/**
33
+	 * will add opening and closing HTML form tags as well as a submit button
34
+	 */
35
+	const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
36
+
37
+	/**
38
+	 * will add opening and closing HTML form tags but NOT a submit button
39
+	 */
40
+	const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
41
+
42
+	/**
43
+	 * will NOT add opening and closing HTML form tags but will add a submit button
44
+	 */
45
+	const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
46
+
47
+	/**
48
+	 * will NOT add opening and closing HTML form tags NOR a submit button
49
+	 */
50
+	const DO_NOT_SETUP_FORM = 'do_not_setup_form';
51
+
52
+	/**
53
+	 * if set to false, then this form has no displayable content,
54
+	 * and will only be used for processing data sent passed via GET or POST
55
+	 * defaults to true ( ie: form has displayable content )
56
+	 *
57
+	 * @var boolean $displayable
58
+	 */
59
+	private $displayable = true;
60
+
61
+	/**
62
+	 * @var string $form_name
63
+	 */
64
+	private $form_name;
65
+
66
+	/**
67
+	 * @var string $admin_name
68
+	 */
69
+	private $admin_name;
70
+
71
+	/**
72
+	 * @var string $slug
73
+	 */
74
+	private $slug;
75
+
76
+	/**
77
+	 * @var string $submit_btn_text
78
+	 */
79
+	private $submit_btn_text;
80
+
81
+	/**
82
+	 * @var string $form_action
83
+	 */
84
+	private $form_action;
85
+
86
+	/**
87
+	 * form params in key value pairs
88
+	 * can be added to form action URL or as hidden inputs
89
+	 *
90
+	 * @var array $form_args
91
+	 */
92
+	private $form_args = array();
93
+
94
+	/**
95
+	 * value of one of the string constant above
96
+	 *
97
+	 * @var string $form_config
98
+	 */
99
+	private $form_config;
100
+
101
+	/**
102
+	 * whether or not the form was determined to be invalid
103
+	 *
104
+	 * @var boolean $form_has_errors
105
+	 */
106
+	private $form_has_errors;
107
+
108
+	/**
109
+	 * the absolute top level form section being used on the page
110
+	 *
111
+	 * @var EE_Form_Section_Proper $form
112
+	 */
113
+	private $form;
114
+
115
+	/**
116
+	 * @var EE_Registry $registry
117
+	 */
118
+	protected $registry;
119
+
120
+	// phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd
121
+	/**
122
+	 * Form constructor.
123
+	 *
124
+	 * @param string      $form_name
125
+	 * @param string      $admin_name
126
+	 * @param string      $slug
127
+	 * @param string      $form_action
128
+	 * @param string      $form_config
129
+	 * @param EE_Registry $registry
130
+	 * @throws InvalidDataTypeException
131
+	 * @throws DomainException
132
+	 * @throws InvalidArgumentException
133
+	 */
134
+	public function __construct(
135
+		$form_name,
136
+		$admin_name,
137
+		$slug,
138
+		$form_action = '',
139
+		$form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
140
+		EE_Registry $registry
141
+	) {
142
+		$this->setFormName($form_name);
143
+		$this->setAdminName($admin_name);
144
+		$this->setSlug($slug);
145
+		$this->setFormAction($form_action);
146
+		$this->setFormConfig($form_config);
147
+		$this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
148
+		$this->registry = $registry;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @return array
154
+	 */
155
+	public static function getFormConfigConstants()
156
+	{
157
+		return array(
158
+			FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
159
+			FormHandler::ADD_FORM_TAGS_ONLY,
160
+			FormHandler::ADD_FORM_SUBMIT_ONLY,
161
+			FormHandler::DO_NOT_SETUP_FORM,
162
+		);
163
+	}
164
+
165
+
166
+	/**
167
+	 * @param bool $for_display
168
+	 * @return EE_Form_Section_Proper
169
+	 * @throws EE_Error
170
+	 * @throws LogicException
171
+	 */
172
+	public function form($for_display = false)
173
+	{
174
+		if (! $this->formIsValid()) {
175
+			return null;
176
+		}
177
+		if ($for_display) {
178
+			$form_config = $this->formConfig();
179
+			if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
180
+				|| $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
181
+			) {
182
+				$this->appendSubmitButton();
183
+				$this->clearFormButtonFloats();
184
+			}
185
+		}
186
+		return $this->form;
187
+	}
188
+
189
+
190
+	/**
191
+	 * @return boolean
192
+	 * @throws LogicException
193
+	 */
194
+	public function formIsValid()
195
+	{
196
+		if ($this->form instanceof EE_Form_Section_Proper) {
197
+			return true;
198
+		}
199
+		$form = apply_filters(
200
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
201
+			$this->generate(),
202
+			$this
203
+		);
204
+		if ($this->verifyForm($form)) {
205
+			$this->setForm($form);
206
+		}
207
+		return true;
208
+	}
209
+
210
+
211
+	/**
212
+	 * @param EE_Form_Section_Proper|null $form
213
+	 * @return bool
214
+	 * @throws LogicException
215
+	 */
216
+	public function verifyForm(EE_Form_Section_Proper $form = null)
217
+	{
218
+		$form = $form !== null ? $form : $this->form;
219
+		if ($form instanceof EE_Form_Section_Proper) {
220
+			return true;
221
+		}
222
+		throw new LogicException(
223
+			sprintf(
224
+				esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
225
+				$this->form_name,
226
+				var_export($form, true)
227
+			)
228
+		);
229
+	}
230
+
231
+
232
+	/**
233
+	 * @param EE_Form_Section_Proper $form
234
+	 */
235
+	public function setForm(EE_Form_Section_Proper $form)
236
+	{
237
+		$this->form = $form;
238
+	}
239
+
240
+
241
+	/**
242
+	 * @return boolean
243
+	 */
244
+	public function displayable()
245
+	{
246
+		return $this->displayable;
247
+	}
248
+
249
+
250
+	/**
251
+	 * @param boolean $displayable
252
+	 */
253
+	public function setDisplayable($displayable = false)
254
+	{
255
+		$this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
256
+	}
257
+
258
+
259
+	/**
260
+	 * a public name for the form that can be displayed on the frontend of a site
261
+	 *
262
+	 * @return string
263
+	 */
264
+	public function formName()
265
+	{
266
+		return $this->form_name;
267
+	}
268
+
269
+
270
+	/**
271
+	 * @param string $form_name
272
+	 * @throws InvalidDataTypeException
273
+	 */
274
+	public function setFormName($form_name)
275
+	{
276
+		if (! is_string($form_name)) {
277
+			throw new InvalidDataTypeException('$form_name', $form_name, 'string');
278
+		}
279
+		$this->form_name = $form_name;
280
+	}
281
+
282
+
283
+	/**
284
+	 * a public name for the form that can be displayed, but only in the admin
285
+	 *
286
+	 * @return string
287
+	 */
288
+	public function adminName()
289
+	{
290
+		return $this->admin_name;
291
+	}
292
+
293
+
294
+	/**
295
+	 * @param string $admin_name
296
+	 * @throws InvalidDataTypeException
297
+	 */
298
+	public function setAdminName($admin_name)
299
+	{
300
+		if (! is_string($admin_name)) {
301
+			throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
302
+		}
303
+		$this->admin_name = $admin_name;
304
+	}
305
+
306
+
307
+	/**
308
+	 * a URL friendly string that can be used for identifying the form
309
+	 *
310
+	 * @return string
311
+	 */
312
+	public function slug()
313
+	{
314
+		return $this->slug;
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param string $slug
320
+	 * @throws InvalidDataTypeException
321
+	 */
322
+	public function setSlug($slug)
323
+	{
324
+		if (! is_string($slug)) {
325
+			throw new InvalidDataTypeException('$slug', $slug, 'string');
326
+		}
327
+		$this->slug = $slug;
328
+	}
329
+
330
+
331
+	/**
332
+	 * @return string
333
+	 */
334
+	public function submitBtnText()
335
+	{
336
+		return $this->submit_btn_text;
337
+	}
338
+
339
+
340
+	/**
341
+	 * @param string $submit_btn_text
342
+	 * @throws InvalidDataTypeException
343
+	 * @throws InvalidArgumentException
344
+	 */
345
+	public function setSubmitBtnText($submit_btn_text)
346
+	{
347
+		if (! is_string($submit_btn_text)) {
348
+			throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
349
+		}
350
+		if (empty($submit_btn_text)) {
351
+			throw new InvalidArgumentException(
352
+				esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
353
+			);
354
+		}
355
+		$this->submit_btn_text = $submit_btn_text;
356
+	}
357
+
358
+
359
+	/**
360
+	 * @return string
361
+	 */
362
+	public function formAction()
363
+	{
364
+		return ! empty($this->form_args)
365
+			? add_query_arg($this->form_args, $this->form_action)
366
+			: $this->form_action;
367
+	}
368
+
369
+
370
+	/**
371
+	 * @param string $form_action
372
+	 * @throws InvalidDataTypeException
373
+	 */
374
+	public function setFormAction($form_action)
375
+	{
376
+		if (! is_string($form_action)) {
377
+			throw new InvalidDataTypeException('$form_action', $form_action, 'string');
378
+		}
379
+		$this->form_action = $form_action;
380
+	}
381
+
382
+
383
+	/**
384
+	 * @param array $form_args
385
+	 * @throws InvalidDataTypeException
386
+	 * @throws InvalidArgumentException
387
+	 */
388
+	public function addFormActionArgs($form_args = array())
389
+	{
390
+		if (is_object($form_args)) {
391
+			throw new InvalidDataTypeException(
392
+				'$form_args',
393
+				$form_args,
394
+				'anything other than an object was expected.'
395
+			);
396
+		}
397
+		if (empty($form_args)) {
398
+			throw new InvalidArgumentException(
399
+				esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
400
+			);
401
+		}
402
+		$this->form_args = array_merge($this->form_args, $form_args);
403
+	}
404
+
405
+
406
+	/**
407
+	 * @return string
408
+	 */
409
+	public function formConfig()
410
+	{
411
+		return $this->form_config;
412
+	}
413
+
414
+
415
+	/**
416
+	 * @param string $form_config
417
+	 * @throws DomainException
418
+	 */
419
+	public function setFormConfig($form_config)
420
+	{
421
+		if (! in_array(
422
+			$form_config,
423
+			array(
424
+				FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
425
+				FormHandler::ADD_FORM_TAGS_ONLY,
426
+				FormHandler::ADD_FORM_SUBMIT_ONLY,
427
+				FormHandler::DO_NOT_SETUP_FORM,
428
+			),
429
+			true
430
+		)
431
+		) {
432
+			throw new DomainException(
433
+				sprintf(
434
+					esc_html__(
435
+						'"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
436
+						'event_espresso'
437
+					),
438
+					$form_config
439
+				)
440
+			);
441
+		}
442
+		$this->form_config = $form_config;
443
+	}
444
+
445
+
446
+	/**
447
+	 * called after the form is instantiated
448
+	 * and used for performing any logic that needs to occur early
449
+	 * before any of the other methods are called.
450
+	 * returns true if everything is ok to proceed,
451
+	 * and false if no further form logic should be implemented
452
+	 *
453
+	 * @return boolean
454
+	 */
455
+	public function initialize()
456
+	{
457
+		$this->form_has_errors = EE_Error::has_error(true);
458
+		return true;
459
+	}
460
+
461
+
462
+	/**
463
+	 * used for setting up css and js
464
+	 *
465
+	 * @return void
466
+	 * @throws LogicException
467
+	 * @throws EE_Error
468
+	 */
469
+	public function enqueueStylesAndScripts()
470
+	{
471
+		$this->form()->enqueue_js();
472
+	}
473
+
474
+
475
+	/**
476
+	 * creates and returns the actual form
477
+	 *
478
+	 * @return EE_Form_Section_Proper
479
+	 */
480
+	abstract public function generate();
481
+
482
+
483
+	/**
484
+	 * creates and returns an EE_Submit_Input labeled "Submit"
485
+	 *
486
+	 * @param string $text
487
+	 * @return EE_Submit_Input
488
+	 */
489
+	public function generateSubmitButton($text = '')
490
+	{
491
+		$text = ! empty($text) ? $text : $this->submitBtnText();
492
+		return new EE_Submit_Input(
493
+			array(
494
+				'html_name'             => 'ee-form-submit-' . $this->slug(),
495
+				'html_id'               => 'ee-form-submit-' . $this->slug(),
496
+				'html_class'            => 'ee-form-submit',
497
+				'html_label'            => '&nbsp;',
498
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
499
+				'default'               => $text,
500
+			)
501
+		);
502
+	}
503
+
504
+
505
+	/**
506
+	 * calls generateSubmitButton() and appends it onto the form along with a float clearing div
507
+	 *
508
+	 * @param string $text
509
+	 * @return void
510
+	 * @throws EE_Error
511
+	 */
512
+	public function appendSubmitButton($text = '')
513
+	{
514
+		if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
515
+			return;
516
+		}
517
+		$this->form->add_subsections(
518
+			array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
519
+			null,
520
+			false
521
+		);
522
+	}
523
+
524
+
525
+	/**
526
+	 * creates and returns an EE_Submit_Input labeled "Cancel"
527
+	 *
528
+	 * @param string $text
529
+	 * @return EE_Submit_Input
530
+	 */
531
+	public function generateCancelButton($text = '')
532
+	{
533
+		$cancel_button = new EE_Submit_Input(
534
+			array(
535
+				'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
536
+				'html_id'               => 'ee-cancel-form-' . $this->slug(),
537
+				'html_class'            => 'ee-cancel-form',
538
+				'html_label'            => '&nbsp;',
539
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
540
+				'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
541
+			)
542
+		);
543
+		$cancel_button->set_button_css_attributes(false);
544
+		return $cancel_button;
545
+	}
546
+
547
+
548
+	/**
549
+	 * appends a float clearing div onto end of form
550
+	 *
551
+	 * @return void
552
+	 * @throws EE_Error
553
+	 */
554
+	public function clearFormButtonFloats()
555
+	{
556
+		$this->form->add_subsections(
557
+			array(
558
+				'clear-submit-btn-float' => new EE_Form_Section_HTML(
559
+					EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
560
+				),
561
+			),
562
+			null,
563
+			false
564
+		);
565
+	}
566
+
567
+
568
+	/**
569
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
570
+	 * returns a string of HTML that can be directly echoed in a template
571
+	 *
572
+	 * @return string
573
+	 * @throws \InvalidArgumentException
574
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
575
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
576
+	 * @throws LogicException
577
+	 * @throws EE_Error
578
+	 */
579
+	public function display()
580
+	{
581
+		$form_html = apply_filters(
582
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
583
+			''
584
+		);
585
+		$form_config = $this->formConfig();
586
+		if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
587
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
588
+		) {
589
+			$additional_props = $this->requiresMultipartEnctype()
590
+				? 'enctype="multipart/form-data"'
591
+				: '';
592
+			$form_html .= $this->form()->form_open(
593
+				$this->formAction(),
594
+				'POST',
595
+				$additional_props
596
+			);
597
+		}
598
+		$form_html .= $this->form(true)->get_html();
599
+		if ($form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
600
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
601
+		) {
602
+			$form_html .= $this->form()->form_close();
603
+		}
604
+		$form_html .= apply_filters(
605
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
606
+			''
607
+		);
608
+		return $form_html;
609
+	}
610
+
611
+	/**
612
+	 * Determines if this form needs "enctype='multipart/form-data'" or not.
613
+	 * @since $VID:$
614
+	 * @return bool
615
+	 * @throws EE_Error
616
+	 */
617
+	public function requiresMultipartEnctype()
618
+	{
619
+		foreach ($this->form()->inputs_in_subsections() as $input) {
620
+			if ($input instanceof EE_File_Input) {
621
+				return true;
622
+			}
623
+		}
624
+		return false;
625
+	}
626
+
627
+
628
+	/**
629
+	 * handles processing the form submission
630
+	 * returns true or false depending on whether the form was processed successfully or not
631
+	 *
632
+	 * @param array $submitted_form_data
633
+	 * @return array
634
+	 * @throws \InvalidArgumentException
635
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
636
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
637
+	 * @throws EE_Error
638
+	 * @throws LogicException
639
+	 * @throws InvalidFormSubmissionException
640
+	 */
641
+	public function process($submitted_form_data = array())
642
+	{
643
+		if (! $this->form()->was_submitted($submitted_form_data)) {
644
+			throw new InvalidFormSubmissionException($this->form_name);
645
+		}
646
+		$this->form(true)->receive_form_submission($submitted_form_data);
647
+		if (! $this->form()->is_valid()) {
648
+			throw new InvalidFormSubmissionException(
649
+				$this->form_name,
650
+				sprintf(
651
+					esc_html__(
652
+						'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
653
+						'event_espresso'
654
+					),
655
+					$this->form_name,
656
+					'<br />',
657
+					implode('<br />', $this->form()->get_validation_errors_accumulated())
658
+				)
659
+			);
660
+		}
661
+		return apply_filters(
662
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
663
+			$this->form()->valid_data(),
664
+			$this
665
+		);
666
+	}
667 667
 }
Please login to merge, or discard this patch.
form_sections/strategies/normalization/EE_File_Normalization.strategy.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -13,40 +13,40 @@
 block discarded – undo
13 13
 class EE_File_Normalization extends EE_Normalization_Strategy_Base
14 14
 {
15 15
 
16
-    /**
17
-     * Keep in mind $value_to_normalize should be a FileSubmissionInterface or null, so this shouldn't really do
18
-     * much (other than NOT convert it to a string or something).
19
-     * @param string $value_to_normalize
20
-     * @return FileSubmissionInterface
21
-     */
22
-    public function normalize($value_to_normalize)
23
-    {
24
-        if ($value_to_normalize instanceof FileSubmissionInterface || is_null($value_to_normalize)) {
25
-            return $value_to_normalize;
26
-        } else {
27
-            throw new EE_Validation_Error(
28
-                esc_html__('The file input has an invalid format.', 'event_espresso')
29
-            );
30
-        }
31
-    }
16
+	/**
17
+	 * Keep in mind $value_to_normalize should be a FileSubmissionInterface or null, so this shouldn't really do
18
+	 * much (other than NOT convert it to a string or something).
19
+	 * @param string $value_to_normalize
20
+	 * @return FileSubmissionInterface
21
+	 */
22
+	public function normalize($value_to_normalize)
23
+	{
24
+		if ($value_to_normalize instanceof FileSubmissionInterface || is_null($value_to_normalize)) {
25
+			return $value_to_normalize;
26
+		} else {
27
+			throw new EE_Validation_Error(
28
+				esc_html__('The file input has an invalid format.', 'event_espresso')
29
+			);
30
+		}
31
+	}
32 32
 
33 33
 
34
-    /**
35
-     * This may be called prematurely on submitted data, so we actually don't want to convert it into a string because
36
-     * we'll lose all the FileSubmissionInterface data. So prefer to leave it alone. FileSubmissionInterface
37
-     * can be cast to a string just fine so it's good as-is.
38
-     *
39
-     * @param string $normalized_value
40
-     * @return string
41
-     */
42
-    public function unnormalize($normalized_value)
43
-    {
44
-        if ($normalized_value instanceof FileSubmissionInterface || is_null($normalized_value)) {
45
-            // Leave it as the object, it can be treated like a string because it
46
-            // overrides __toString()
47
-            return $normalized_value;
48
-        } else {
49
-            return (string) $normalized_value;
50
-        }
51
-    }
34
+	/**
35
+	 * This may be called prematurely on submitted data, so we actually don't want to convert it into a string because
36
+	 * we'll lose all the FileSubmissionInterface data. So prefer to leave it alone. FileSubmissionInterface
37
+	 * can be cast to a string just fine so it's good as-is.
38
+	 *
39
+	 * @param string $normalized_value
40
+	 * @return string
41
+	 */
42
+	public function unnormalize($normalized_value)
43
+	{
44
+		if ($normalized_value instanceof FileSubmissionInterface || is_null($normalized_value)) {
45
+			// Leave it as the object, it can be treated like a string because it
46
+			// overrides __toString()
47
+			return $normalized_value;
48
+		} else {
49
+			return (string) $normalized_value;
50
+		}
51
+	}
52 52
 }
Please login to merge, or discard this patch.
core/services/locators/FqcnLocator.php 2 patches
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -18,156 +18,156 @@
 block discarded – undo
18 18
 class FqcnLocator extends Locator
19 19
 {
20 20
 
21
-    /**
22
-     * @var array $FQCNs
23
-     */
24
-    protected $FQCNs = array();
25
-
26
-    /**
27
-     * @var array $namespaces
28
-     */
29
-    protected $namespaces = array();
30
-
31
-
32
-    /**
33
-     * @access protected
34
-     * @param string $namespace
35
-     * @param string $namespace_base_dir
36
-     * @throws InvalidDataTypeException
37
-     */
38
-    protected function setNamespace($namespace, $namespace_base_dir)
39
-    {
40
-        if (! is_string($namespace)) {
41
-            throw new InvalidDataTypeException('$namespace', $namespace, 'string');
42
-        }
43
-        if (! is_string($namespace_base_dir)) {
44
-            throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string');
45
-        }
46
-        $this->namespaces[ $namespace ] = $namespace_base_dir;
47
-    }
48
-
49
-
50
-    /**
51
-     * @access public
52
-     * @return array
53
-     */
54
-    public function getFQCNs()
55
-    {
56
-        return $this->FQCNs;
57
-    }
58
-
59
-
60
-    /**
61
-     * @access public
62
-     * @return int
63
-     */
64
-    public function count()
65
-    {
66
-        return count($this->FQCNs);
67
-    }
68
-
69
-
70
-    /**
71
-     * given a valid namespace, will find all files that match the provided mask
72
-     *
73
-     * @access public
74
-     * @param string|array $namespaces
75
-     * @return array
76
-     * @throws InvalidClassException
77
-     * @throws InvalidDataTypeException
78
-     */
79
-    public function locate($namespaces)
80
-    {
81
-        if (! (is_string($namespaces) || is_array($namespaces))) {
82
-            throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array');
83
-        }
84
-        foreach ((array) $namespaces as $namespace) {
85
-            foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) {
86
-                $this->FQCNs[ $key ] = $file;
87
-            }
88
-        }
89
-        return $this->FQCNs;
90
-    }
91
-
92
-
93
-    /**
94
-     * given a partial namespace, will find all files in that folder
95
-     * ** PLZ NOTE **
96
-     * This assumes that all files within the specified folder should be loaded
97
-     *
98
-     * @access protected
99
-     * @param string $partial_namespace
100
-     * @return array
101
-     * @throws InvalidClassException
102
-     * @throws InvalidDataTypeException
103
-     */
104
-    protected function findFQCNsByNamespace($partial_namespace)
105
-    {
106
-        $iterator = new FilesystemIterator(
107
-            $this->getDirectoryFromPartialNamespace($partial_namespace)
108
-        );
109
-        $iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO);
110
-        $iterator->setFlags(FilesystemIterator::UNIX_PATHS);
111
-        if (iterator_count($iterator) === 0) {
112
-            return array();
113
-        }
114
-        foreach ($iterator as $file) {
115
-            if ($file->isFile() && $file->getExtension() === 'php') {
116
-                $file = $file->getPath() . DS . $file->getBasename('.php');
117
-                foreach ($this->namespaces as $namespace => $base_dir) {
118
-                    $namespace .= Psr4Autoloader::NS;
119
-                    if (strpos($file, $base_dir) === 0) {
120
-                        $this->FQCNs[] = Psr4Autoloader::NS . str_replace(
121
-                            array($base_dir, DS),
122
-                            array($namespace, Psr4Autoloader::NS),
123
-                            $file
124
-                        );
125
-                    }
126
-                }
127
-            }
128
-        }
129
-        return $this->FQCNs;
130
-    }
131
-
132
-
133
-    /**
134
-     * getDirectoryFromPartialNamespace
135
-     *
136
-     * @access protected
137
-     * @param  string $partial_namespace almost fully qualified class name ?
138
-     * @return string
139
-     * @throws InvalidDataTypeException
140
-     * @throws InvalidClassException
141
-     */
142
-    protected function getDirectoryFromPartialNamespace($partial_namespace)
143
-    {
144
-        if (empty($partial_namespace)) {
145
-            throw new InvalidClassException($partial_namespace);
146
-        }
147
-        // load our PSR-4 Autoloader so we can get the list of registered namespaces from it
148
-        $psr4_loader = \EE_Psr4AutoloaderInit::psr4_loader();
149
-        // breakup the incoming namespace into segments so we can loop thru them
150
-        $namespace_segments = explode(Psr4Autoloader::NS, trim($partial_namespace, Psr4Autoloader::NS));
151
-        // we're only interested in the Vendor and secondary base, so pull those from the array
152
-        $vendor_base = array_slice($namespace_segments, 0, 2);
153
-        $namespace = $prefix = null;
154
-        while (! empty($vendor_base)) {
155
-            $namespace = implode(Psr4Autoloader::NS, $vendor_base);
156
-            // check if there's a base directory registered for that namespace
157
-            $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS);
158
-            if (! empty($prefix) && ! empty($prefix[0])) {
159
-                // found one!
160
-                break;
161
-            }
162
-            // remove base and try vendor only portion of namespace
163
-            array_pop($vendor_base);
164
-        }
165
-        // nope? then the incoming namespace is invalid
166
-        if (empty($prefix) || empty($prefix[0])) {
167
-            throw new InvalidClassException($partial_namespace);
168
-        }
169
-        $this->setNamespace($namespace, $prefix[0]);
170
-        // but if it's good, add that base directory to the rest of the path, and return it
171
-        return $prefix[0] . implode(DS, array_diff($namespace_segments, $vendor_base)) . DS;
172
-    }
21
+	/**
22
+	 * @var array $FQCNs
23
+	 */
24
+	protected $FQCNs = array();
25
+
26
+	/**
27
+	 * @var array $namespaces
28
+	 */
29
+	protected $namespaces = array();
30
+
31
+
32
+	/**
33
+	 * @access protected
34
+	 * @param string $namespace
35
+	 * @param string $namespace_base_dir
36
+	 * @throws InvalidDataTypeException
37
+	 */
38
+	protected function setNamespace($namespace, $namespace_base_dir)
39
+	{
40
+		if (! is_string($namespace)) {
41
+			throw new InvalidDataTypeException('$namespace', $namespace, 'string');
42
+		}
43
+		if (! is_string($namespace_base_dir)) {
44
+			throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string');
45
+		}
46
+		$this->namespaces[ $namespace ] = $namespace_base_dir;
47
+	}
48
+
49
+
50
+	/**
51
+	 * @access public
52
+	 * @return array
53
+	 */
54
+	public function getFQCNs()
55
+	{
56
+		return $this->FQCNs;
57
+	}
58
+
59
+
60
+	/**
61
+	 * @access public
62
+	 * @return int
63
+	 */
64
+	public function count()
65
+	{
66
+		return count($this->FQCNs);
67
+	}
68
+
69
+
70
+	/**
71
+	 * given a valid namespace, will find all files that match the provided mask
72
+	 *
73
+	 * @access public
74
+	 * @param string|array $namespaces
75
+	 * @return array
76
+	 * @throws InvalidClassException
77
+	 * @throws InvalidDataTypeException
78
+	 */
79
+	public function locate($namespaces)
80
+	{
81
+		if (! (is_string($namespaces) || is_array($namespaces))) {
82
+			throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array');
83
+		}
84
+		foreach ((array) $namespaces as $namespace) {
85
+			foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) {
86
+				$this->FQCNs[ $key ] = $file;
87
+			}
88
+		}
89
+		return $this->FQCNs;
90
+	}
91
+
92
+
93
+	/**
94
+	 * given a partial namespace, will find all files in that folder
95
+	 * ** PLZ NOTE **
96
+	 * This assumes that all files within the specified folder should be loaded
97
+	 *
98
+	 * @access protected
99
+	 * @param string $partial_namespace
100
+	 * @return array
101
+	 * @throws InvalidClassException
102
+	 * @throws InvalidDataTypeException
103
+	 */
104
+	protected function findFQCNsByNamespace($partial_namespace)
105
+	{
106
+		$iterator = new FilesystemIterator(
107
+			$this->getDirectoryFromPartialNamespace($partial_namespace)
108
+		);
109
+		$iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO);
110
+		$iterator->setFlags(FilesystemIterator::UNIX_PATHS);
111
+		if (iterator_count($iterator) === 0) {
112
+			return array();
113
+		}
114
+		foreach ($iterator as $file) {
115
+			if ($file->isFile() && $file->getExtension() === 'php') {
116
+				$file = $file->getPath() . DS . $file->getBasename('.php');
117
+				foreach ($this->namespaces as $namespace => $base_dir) {
118
+					$namespace .= Psr4Autoloader::NS;
119
+					if (strpos($file, $base_dir) === 0) {
120
+						$this->FQCNs[] = Psr4Autoloader::NS . str_replace(
121
+							array($base_dir, DS),
122
+							array($namespace, Psr4Autoloader::NS),
123
+							$file
124
+						);
125
+					}
126
+				}
127
+			}
128
+		}
129
+		return $this->FQCNs;
130
+	}
131
+
132
+
133
+	/**
134
+	 * getDirectoryFromPartialNamespace
135
+	 *
136
+	 * @access protected
137
+	 * @param  string $partial_namespace almost fully qualified class name ?
138
+	 * @return string
139
+	 * @throws InvalidDataTypeException
140
+	 * @throws InvalidClassException
141
+	 */
142
+	protected function getDirectoryFromPartialNamespace($partial_namespace)
143
+	{
144
+		if (empty($partial_namespace)) {
145
+			throw new InvalidClassException($partial_namespace);
146
+		}
147
+		// load our PSR-4 Autoloader so we can get the list of registered namespaces from it
148
+		$psr4_loader = \EE_Psr4AutoloaderInit::psr4_loader();
149
+		// breakup the incoming namespace into segments so we can loop thru them
150
+		$namespace_segments = explode(Psr4Autoloader::NS, trim($partial_namespace, Psr4Autoloader::NS));
151
+		// we're only interested in the Vendor and secondary base, so pull those from the array
152
+		$vendor_base = array_slice($namespace_segments, 0, 2);
153
+		$namespace = $prefix = null;
154
+		while (! empty($vendor_base)) {
155
+			$namespace = implode(Psr4Autoloader::NS, $vendor_base);
156
+			// check if there's a base directory registered for that namespace
157
+			$prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS);
158
+			if (! empty($prefix) && ! empty($prefix[0])) {
159
+				// found one!
160
+				break;
161
+			}
162
+			// remove base and try vendor only portion of namespace
163
+			array_pop($vendor_base);
164
+		}
165
+		// nope? then the incoming namespace is invalid
166
+		if (empty($prefix) || empty($prefix[0])) {
167
+			throw new InvalidClassException($partial_namespace);
168
+		}
169
+		$this->setNamespace($namespace, $prefix[0]);
170
+		// but if it's good, add that base directory to the rest of the path, and return it
171
+		return $prefix[0] . implode(DS, array_diff($namespace_segments, $vendor_base)) . DS;
172
+	}
173 173
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -37,13 +37,13 @@  discard block
 block discarded – undo
37 37
      */
38 38
     protected function setNamespace($namespace, $namespace_base_dir)
39 39
     {
40
-        if (! is_string($namespace)) {
40
+        if ( ! is_string($namespace)) {
41 41
             throw new InvalidDataTypeException('$namespace', $namespace, 'string');
42 42
         }
43
-        if (! is_string($namespace_base_dir)) {
43
+        if ( ! is_string($namespace_base_dir)) {
44 44
             throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string');
45 45
         }
46
-        $this->namespaces[ $namespace ] = $namespace_base_dir;
46
+        $this->namespaces[$namespace] = $namespace_base_dir;
47 47
     }
48 48
 
49 49
 
@@ -78,12 +78,12 @@  discard block
 block discarded – undo
78 78
      */
79 79
     public function locate($namespaces)
80 80
     {
81
-        if (! (is_string($namespaces) || is_array($namespaces))) {
81
+        if ( ! (is_string($namespaces) || is_array($namespaces))) {
82 82
             throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array');
83 83
         }
84 84
         foreach ((array) $namespaces as $namespace) {
85 85
             foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) {
86
-                $this->FQCNs[ $key ] = $file;
86
+                $this->FQCNs[$key] = $file;
87 87
             }
88 88
         }
89 89
         return $this->FQCNs;
@@ -113,11 +113,11 @@  discard block
 block discarded – undo
113 113
         }
114 114
         foreach ($iterator as $file) {
115 115
             if ($file->isFile() && $file->getExtension() === 'php') {
116
-                $file = $file->getPath() . DS . $file->getBasename('.php');
116
+                $file = $file->getPath().DS.$file->getBasename('.php');
117 117
                 foreach ($this->namespaces as $namespace => $base_dir) {
118 118
                     $namespace .= Psr4Autoloader::NS;
119 119
                     if (strpos($file, $base_dir) === 0) {
120
-                        $this->FQCNs[] = Psr4Autoloader::NS . str_replace(
120
+                        $this->FQCNs[] = Psr4Autoloader::NS.str_replace(
121 121
                             array($base_dir, DS),
122 122
                             array($namespace, Psr4Autoloader::NS),
123 123
                             $file
@@ -151,11 +151,11 @@  discard block
 block discarded – undo
151 151
         // we're only interested in the Vendor and secondary base, so pull those from the array
152 152
         $vendor_base = array_slice($namespace_segments, 0, 2);
153 153
         $namespace = $prefix = null;
154
-        while (! empty($vendor_base)) {
154
+        while ( ! empty($vendor_base)) {
155 155
             $namespace = implode(Psr4Autoloader::NS, $vendor_base);
156 156
             // check if there's a base directory registered for that namespace
157
-            $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS);
158
-            if (! empty($prefix) && ! empty($prefix[0])) {
157
+            $prefix = $psr4_loader->prefixes($namespace.Psr4Autoloader::NS);
158
+            if ( ! empty($prefix) && ! empty($prefix[0])) {
159 159
                 // found one!
160 160
                 break;
161 161
             }
@@ -168,6 +168,6 @@  discard block
 block discarded – undo
168 168
         }
169 169
         $this->setNamespace($namespace, $prefix[0]);
170 170
         // but if it's good, add that base directory to the rest of the path, and return it
171
-        return $prefix[0] . implode(DS, array_diff($namespace_segments, $vendor_base)) . DS;
171
+        return $prefix[0].implode(DS, array_diff($namespace_segments, $vendor_base)).DS;
172 172
     }
173 173
 }
Please login to merge, or discard this patch.
data_migration_scripts/4_1_0_stages/EE_DMS_4_1_0_attendees.dmsstage.php 2 patches
Indentation   +601 added lines, -605 removed lines patch added patch discarded remove patch
@@ -53,10 +53,6 @@  discard block
 block discarded – undo
53 53
 ENGINE=InnoDB
54 54
 AUTO_INCREMENT=3
55 55
 ;
56
-
57
-
58
-
59
-
60 56
  * 4.1 Attendee tables and fields:
61 57
  * $this->_tables = array(
62 58
             'Attendee_CPT'=> new EE_Primary_Table('posts', 'ID'),
@@ -186,637 +182,637 @@  discard block
 block discarded – undo
186 182
  */
187 183
 class EE_DMS_4_1_0_attendees extends EE_Data_Migration_Script_Stage_Table
188 184
 {
189
-    private $_new_attendee_cpt_table;
190
-    private $_new_attendee_meta_table;
191
-    private $_new_reg_table;
192
-    private $_new_transaction_table;
193
-    private $_new_payment_table;
194
-    private $_new_line_table;
195
-    private $_old_mer_table;
196
-    private $_new_ticket_table;
197
-    private $_new_ticket_datetime_table;
198
-    private $_new_datetime_table;
199
-    private $_new_datetime_ticket_table;
200
-    private $_new_price_table;
201
-    private $_new_ticket_price_table;
202
-    /**
203
-     * Rememebrs whether or not the mer table exists
204
-     * @var boolean
205
-     */
206
-    private $_mer_tables_exist = null;
207
-    public function __construct()
208
-    {
209
-        global $wpdb;
210
-        $this->_pretty_name = __("Attendees", "event_espresso");
211
-        $this->_old_table = $wpdb->prefix."events_attendee";
212
-        // Only select the event status column from the event table.
213
-        $this->select_expression = 'att.*, e.event_status';
214
-        // Only select attendees for events that aren't deleted.
215
-        $this->_extra_where_sql = 'AS att
185
+	private $_new_attendee_cpt_table;
186
+	private $_new_attendee_meta_table;
187
+	private $_new_reg_table;
188
+	private $_new_transaction_table;
189
+	private $_new_payment_table;
190
+	private $_new_line_table;
191
+	private $_old_mer_table;
192
+	private $_new_ticket_table;
193
+	private $_new_ticket_datetime_table;
194
+	private $_new_datetime_table;
195
+	private $_new_datetime_ticket_table;
196
+	private $_new_price_table;
197
+	private $_new_ticket_price_table;
198
+	/**
199
+	 * Rememebrs whether or not the mer table exists
200
+	 * @var boolean
201
+	 */
202
+	private $_mer_tables_exist = null;
203
+	public function __construct()
204
+	{
205
+		global $wpdb;
206
+		$this->_pretty_name = __("Attendees", "event_espresso");
207
+		$this->_old_table = $wpdb->prefix."events_attendee";
208
+		// Only select the event status column from the event table.
209
+		$this->select_expression = 'att.*, e.event_status';
210
+		// Only select attendees for events that aren't deleted.
211
+		$this->_extra_where_sql = 'AS att
216 212
             INNER JOIN ' . $wpdb->prefix . 'events_detail AS e ON att.event_id=e.id
217 213
             WHERE e.event_status!="D"';
218
-        $this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
219
-        $this->_new_attendee_cpt_table = $wpdb->posts;
220
-        $this->_new_attendee_meta_table = $wpdb->prefix."esp_attendee_meta";
221
-        $this->_new_reg_table = $wpdb->prefix."esp_registration";
222
-        $this->_new_transaction_table = $wpdb->prefix."esp_transaction";
223
-        $this->_new_payment_table = $wpdb->prefix."esp_payment";
224
-        $this->_new_line_table = $wpdb->prefix."esp_line_item";
225
-        $this->_new_ticket_table = $wpdb->prefix."esp_ticket";
226
-        $this->_new_ticket_datetime_table = $wpdb->prefix."esp_datetime_ticket";
227
-        $this->_new_datetime_table = $wpdb->prefix."esp_datetime";
228
-        $this->_new_datetime_ticket_table = $wpdb->prefix."esp_datetime_ticket";
229
-        $this->_new_price_table = $wpdb->prefix."esp_price";
230
-        $this->_new_ticket_price_table = $wpdb->prefix."esp_ticket_price";
231
-        parent::__construct();
232
-    }
214
+		$this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
215
+		$this->_new_attendee_cpt_table = $wpdb->posts;
216
+		$this->_new_attendee_meta_table = $wpdb->prefix."esp_attendee_meta";
217
+		$this->_new_reg_table = $wpdb->prefix."esp_registration";
218
+		$this->_new_transaction_table = $wpdb->prefix."esp_transaction";
219
+		$this->_new_payment_table = $wpdb->prefix."esp_payment";
220
+		$this->_new_line_table = $wpdb->prefix."esp_line_item";
221
+		$this->_new_ticket_table = $wpdb->prefix."esp_ticket";
222
+		$this->_new_ticket_datetime_table = $wpdb->prefix."esp_datetime_ticket";
223
+		$this->_new_datetime_table = $wpdb->prefix."esp_datetime";
224
+		$this->_new_datetime_ticket_table = $wpdb->prefix."esp_datetime_ticket";
225
+		$this->_new_price_table = $wpdb->prefix."esp_price";
226
+		$this->_new_ticket_price_table = $wpdb->prefix."esp_ticket_price";
227
+		parent::__construct();
228
+	}
233 229
 
234
-    protected function _migrate_old_row($old_row)
235
-    {
236
-        // first check if there's already a new attendee with similar characteristics
237
-        $new_att_id = $this->_find_attendee_cpt_matching($old_row);
238
-        if (! $new_att_id) {
239
-            $new_att_id = $this->_insert_new_attendee_cpt($old_row);
240
-            if (! $new_att_id) {
241
-                // if we couldnt even make an attendee, abandon all hope
242
-                return false;
243
-            }
244
-            $new_att_meta_id = $this->_insert_attendee_meta_row($old_row, $new_att_id);
245
-            if ($new_att_meta_id) {
246
-                $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_meta_table, $new_att_meta_id);
247
-            }
248
-        }
249
-        $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
230
+	protected function _migrate_old_row($old_row)
231
+	{
232
+		// first check if there's already a new attendee with similar characteristics
233
+		$new_att_id = $this->_find_attendee_cpt_matching($old_row);
234
+		if (! $new_att_id) {
235
+			$new_att_id = $this->_insert_new_attendee_cpt($old_row);
236
+			if (! $new_att_id) {
237
+				// if we couldnt even make an attendee, abandon all hope
238
+				return false;
239
+			}
240
+			$new_att_meta_id = $this->_insert_attendee_meta_row($old_row, $new_att_id);
241
+			if ($new_att_meta_id) {
242
+				$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_meta_table, $new_att_meta_id);
243
+			}
244
+		}
245
+		$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
250 246
 
251
-        $txn_id = $this->_insert_new_transaction($old_row);
252
-        if (! $txn_id) {
253
-            // if we couldnt make the transaction, also abandon all hope
254
-            return false;
255
-        }
256
-        $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_transaction_table, $txn_id);
257
-        $pay_id = $this->_insert_new_payment($old_row, $txn_id);
258
-        if ($pay_id) {
259
-            $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_payment_table, $pay_id);
260
-        }
247
+		$txn_id = $this->_insert_new_transaction($old_row);
248
+		if (! $txn_id) {
249
+			// if we couldnt make the transaction, also abandon all hope
250
+			return false;
251
+		}
252
+		$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_transaction_table, $txn_id);
253
+		$pay_id = $this->_insert_new_payment($old_row, $txn_id);
254
+		if ($pay_id) {
255
+			$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_payment_table, $pay_id);
256
+		}
261 257
 
262 258
 
263
-        // even if there was no payment, we can go ahead with adding the reg
264
-        $new_regs = $this->_insert_new_registrations($old_row, $new_att_id, $txn_id);
265
-        if ($new_regs) {
266
-            $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_reg_table, $new_regs);
267
-        }
268
-    }
269
-    /**
270
-     * Checks if there's already an attendee CPT in the db that has the same
271
-     * first and last name, and email. If so, returns its ID as an int.
272
-     * @global type $wpdb
273
-     * @param array $old_attendee
274
-     * @return int
275
-     */
276
-    private function _find_attendee_cpt_matching($old_attendee)
277
-    {
278
-        global $wpdb;
279
-        $existing_attendee_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_new_attendee_cpt_table." AS cpt INNER JOIN ".$this->_new_attendee_meta_table." AS meta ON cpt.ID = meta.ATT_ID WHERE meta.ATT_fname = %s AND meta.ATT_lname = %s AND meta.ATT_email = %s LIMIT 1", $old_attendee['fname'], $old_attendee['lname'], $old_attendee['email']));
280
-        return intval($existing_attendee_id);
281
-    }
282
-    private function _insert_new_attendee_cpt($old_attendee)
283
-    {
284
-        global $wpdb;
285
-        $cols_n_values = array(
286
-            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
287
-            'post_content'=>'',// ATT_bio
288
-            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
289
-            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
290
-            'post_excerpt'=>'',// ATT_short_bio
291
-            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
292
-            'post_author'=>0,// ATT_author
293
-            'post_parent'=>0,// ATT_parent
294
-            'post_type'=>'espresso_attendees',// post_type
295
-            'post_status'=>'publish'// status
296
-        );
297
-        $datatypes = array(
298
-            '%s',// ATT_full_name
299
-            '%s',// ATT_bio
300
-            '%s',// ATT_slug
301
-            '%s',// ATT_created
302
-            '%s',// ATT_short_bio
303
-            '%s',// ATT_modified
304
-            '%d',// ATT_author
305
-            '%d',// ATT_parent
306
-            '%s',// post_type
307
-            '%s',// status
308
-        );
309
-        $success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
310
-        if (! $success) {
311
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
312
-            return 0;
313
-        }
314
-        $new_id = $wpdb->insert_id;
315
-        return $new_id;
316
-    }
259
+		// even if there was no payment, we can go ahead with adding the reg
260
+		$new_regs = $this->_insert_new_registrations($old_row, $new_att_id, $txn_id);
261
+		if ($new_regs) {
262
+			$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_reg_table, $new_regs);
263
+		}
264
+	}
265
+	/**
266
+	 * Checks if there's already an attendee CPT in the db that has the same
267
+	 * first and last name, and email. If so, returns its ID as an int.
268
+	 * @global type $wpdb
269
+	 * @param array $old_attendee
270
+	 * @return int
271
+	 */
272
+	private function _find_attendee_cpt_matching($old_attendee)
273
+	{
274
+		global $wpdb;
275
+		$existing_attendee_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_new_attendee_cpt_table." AS cpt INNER JOIN ".$this->_new_attendee_meta_table." AS meta ON cpt.ID = meta.ATT_ID WHERE meta.ATT_fname = %s AND meta.ATT_lname = %s AND meta.ATT_email = %s LIMIT 1", $old_attendee['fname'], $old_attendee['lname'], $old_attendee['email']));
276
+		return intval($existing_attendee_id);
277
+	}
278
+	private function _insert_new_attendee_cpt($old_attendee)
279
+	{
280
+		global $wpdb;
281
+		$cols_n_values = array(
282
+			'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
283
+			'post_content'=>'',// ATT_bio
284
+			'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
285
+			'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
286
+			'post_excerpt'=>'',// ATT_short_bio
287
+			'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
288
+			'post_author'=>0,// ATT_author
289
+			'post_parent'=>0,// ATT_parent
290
+			'post_type'=>'espresso_attendees',// post_type
291
+			'post_status'=>'publish'// status
292
+		);
293
+		$datatypes = array(
294
+			'%s',// ATT_full_name
295
+			'%s',// ATT_bio
296
+			'%s',// ATT_slug
297
+			'%s',// ATT_created
298
+			'%s',// ATT_short_bio
299
+			'%s',// ATT_modified
300
+			'%d',// ATT_author
301
+			'%d',// ATT_parent
302
+			'%s',// post_type
303
+			'%s',// status
304
+		);
305
+		$success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
306
+		if (! $success) {
307
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
308
+			return 0;
309
+		}
310
+		$new_id = $wpdb->insert_id;
311
+		return $new_id;
312
+	}
317 313
 
318
-    private function _insert_attendee_meta_row($old_attendee, $new_attendee_cpt_id)
319
-    {
320
-        global $wpdb;
321
-        // get the state and country ids from the old row
322
-        try {
323
-            $new_country = $this->get_migration_script()->get_or_create_country(stripslashes($old_attendee['country_id']));
324
-            $new_country_iso = $new_country['CNT_ISO'];
325
-        } catch (EE_Error $exception) {
326
-            $new_country_iso = $this->get_migration_script()->get_default_country_iso();
327
-        }
328
-        try {
329
-            $new_state = $this->get_migration_script()->get_or_create_state(stripslashes($old_attendee['state']), $new_country_iso);
330
-            $new_state_id = $new_state['STA_ID'];
331
-        } catch (EE_Error $exception) {
332
-            $new_state_id = 0;
333
-        }
334
-        $cols_n_values = array(
335
-            'ATT_ID'=>$new_attendee_cpt_id,
336
-            'ATT_fname'=>stripslashes($old_attendee['fname']),
337
-            'ATT_lname'=>stripslashes($old_attendee['lname']),
338
-            'ATT_address'=>stripslashes($old_attendee['address']),
339
-            'ATT_address2'=>stripslashes($old_attendee['address2']),
340
-            'ATT_city'=>stripslashes($old_attendee['city']),
341
-            'STA_ID'=>$new_state_id,
342
-            'CNT_ISO'=>$new_country_iso,
343
-            'ATT_zip'=>stripslashes($old_attendee['zip']),
344
-            'ATT_email'=>stripslashes($old_attendee['email']),
345
-            'ATT_phone'=>stripslashes($old_attendee['phone']),
346
-        );
347
-        $datatypes = array(
348
-            '%d',// ATT_ID
349
-            '%s',// ATT_fname
350
-            '%s',// ATT_lname
351
-            '%s',// ATT_address
352
-            '%s',// ATT_address2
353
-            '%s',// ATT_city
354
-            '%d',// STA_ID
355
-            '%s',// CNT_ISO
356
-            '%s',// ATT_zip
357
-            '%s',// ATT_email
358
-            '%s',// ATT_phone
359
-        );
360
-        $success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
361
-        if (! $success) {
362
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
363
-            return 0;
364
-        }
365
-        $new_id = $wpdb->insert_id;
366
-        return $new_id;
367
-    }
314
+	private function _insert_attendee_meta_row($old_attendee, $new_attendee_cpt_id)
315
+	{
316
+		global $wpdb;
317
+		// get the state and country ids from the old row
318
+		try {
319
+			$new_country = $this->get_migration_script()->get_or_create_country(stripslashes($old_attendee['country_id']));
320
+			$new_country_iso = $new_country['CNT_ISO'];
321
+		} catch (EE_Error $exception) {
322
+			$new_country_iso = $this->get_migration_script()->get_default_country_iso();
323
+		}
324
+		try {
325
+			$new_state = $this->get_migration_script()->get_or_create_state(stripslashes($old_attendee['state']), $new_country_iso);
326
+			$new_state_id = $new_state['STA_ID'];
327
+		} catch (EE_Error $exception) {
328
+			$new_state_id = 0;
329
+		}
330
+		$cols_n_values = array(
331
+			'ATT_ID'=>$new_attendee_cpt_id,
332
+			'ATT_fname'=>stripslashes($old_attendee['fname']),
333
+			'ATT_lname'=>stripslashes($old_attendee['lname']),
334
+			'ATT_address'=>stripslashes($old_attendee['address']),
335
+			'ATT_address2'=>stripslashes($old_attendee['address2']),
336
+			'ATT_city'=>stripslashes($old_attendee['city']),
337
+			'STA_ID'=>$new_state_id,
338
+			'CNT_ISO'=>$new_country_iso,
339
+			'ATT_zip'=>stripslashes($old_attendee['zip']),
340
+			'ATT_email'=>stripslashes($old_attendee['email']),
341
+			'ATT_phone'=>stripslashes($old_attendee['phone']),
342
+		);
343
+		$datatypes = array(
344
+			'%d',// ATT_ID
345
+			'%s',// ATT_fname
346
+			'%s',// ATT_lname
347
+			'%s',// ATT_address
348
+			'%s',// ATT_address2
349
+			'%s',// ATT_city
350
+			'%d',// STA_ID
351
+			'%s',// CNT_ISO
352
+			'%s',// ATT_zip
353
+			'%s',// ATT_email
354
+			'%s',// ATT_phone
355
+		);
356
+		$success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
357
+		if (! $success) {
358
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
359
+			return 0;
360
+		}
361
+		$new_id = $wpdb->insert_id;
362
+		return $new_id;
363
+	}
368 364
 
369
-    /**
370
-     * Note: we don't necessarily create a new transaction for each attendee row.
371
-     * Only if the old attendee 'is_primary' is true; otherwise we find the old attendee row that
372
-     * 'is_primary' and has the same 'txn_id', then we return ITS new transaction id
373
-     * @global type $wpdb
374
-     * @param type $old_attendee
375
-     * @return int new transaction id
376
-     */
377
-    private function _insert_new_transaction($old_attendee)
378
-    {
379
-        global $wpdb;
365
+	/**
366
+	 * Note: we don't necessarily create a new transaction for each attendee row.
367
+	 * Only if the old attendee 'is_primary' is true; otherwise we find the old attendee row that
368
+	 * 'is_primary' and has the same 'txn_id', then we return ITS new transaction id
369
+	 * @global type $wpdb
370
+	 * @param type $old_attendee
371
+	 * @return int new transaction id
372
+	 */
373
+	private function _insert_new_transaction($old_attendee)
374
+	{
375
+		global $wpdb;
380 376
 
381
-        // first: let's check for an existing transaction for this old attendee
382
-        if (intval($old_attendee['is_primary'])) {// primary attendee, so create txn
383
-            $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
384
-        } else { // non-primary attendee, so find its primary attendee's transaction
385
-            $primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
386
-            if (! $primary_attendee_old_id) {
387
-                $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
388
-                $primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
389
-            }
390
-            $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
391
-            if (! $txn_id) {
392
-                $this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
393
-                $txn_id = 0;
394
-            }
395
-        }
396
-        // if there isn't yet a transaction row for this, create one
397
-        // (so even if it was a non-primary attendee with no EE3 primary attendee,
398
-        // it ought to have SOME transaction, so we'll make one)
399
-        if (! $txn_id) {
400
-            // maps 3.1 payment stati onto 4.1 transaction stati
401
-            $txn_status_mapping = array(
402
-                'Completed'=>'TCM',
403
-                'Pending'=>'TIN',
404
-                'Payment Declined'=>'TIN',
405
-                'Incomplete'=>'TIN',
406
-                'Not Completed'=>'TIN',
407
-                'Cancelled'=>'TIN',
408
-                'Declined'=>'TIN'
409
-            );
410
-            $STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
411
-            $cols_n_values = array(
412
-                'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
413
-                'TXN_total'=>floatval($old_attendee['total_cost']),
414
-                'TXN_paid'=>floatval($old_attendee['amount_pd']),
415
-                'STS_ID'=>$STS_ID,
416
-                'TXN_hash_salt'=>$old_attendee['hashSalt']
417
-            );
418
-            $datatypes = array(
419
-                '%s',// TXN_timestamp
420
-                '%f',// TXN_total
421
-                '%f',// TXN_paid
422
-                '%s',// STS_ID
423
-                '%s',// TXN_hash_salt
424
-            );
425
-            $success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
426
-            if (! $success) {
427
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
428
-                return 0;
429
-            }
430
-            $txn_id = $wpdb->insert_id;
431
-        }
377
+		// first: let's check for an existing transaction for this old attendee
378
+		if (intval($old_attendee['is_primary'])) {// primary attendee, so create txn
379
+			$txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
380
+		} else { // non-primary attendee, so find its primary attendee's transaction
381
+			$primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
382
+			if (! $primary_attendee_old_id) {
383
+				$primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
384
+				$primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
385
+			}
386
+			$txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
387
+			if (! $txn_id) {
388
+				$this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
389
+				$txn_id = 0;
390
+			}
391
+		}
392
+		// if there isn't yet a transaction row for this, create one
393
+		// (so even if it was a non-primary attendee with no EE3 primary attendee,
394
+		// it ought to have SOME transaction, so we'll make one)
395
+		if (! $txn_id) {
396
+			// maps 3.1 payment stati onto 4.1 transaction stati
397
+			$txn_status_mapping = array(
398
+				'Completed'=>'TCM',
399
+				'Pending'=>'TIN',
400
+				'Payment Declined'=>'TIN',
401
+				'Incomplete'=>'TIN',
402
+				'Not Completed'=>'TIN',
403
+				'Cancelled'=>'TIN',
404
+				'Declined'=>'TIN'
405
+			);
406
+			$STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
407
+			$cols_n_values = array(
408
+				'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
409
+				'TXN_total'=>floatval($old_attendee['total_cost']),
410
+				'TXN_paid'=>floatval($old_attendee['amount_pd']),
411
+				'STS_ID'=>$STS_ID,
412
+				'TXN_hash_salt'=>$old_attendee['hashSalt']
413
+			);
414
+			$datatypes = array(
415
+				'%s',// TXN_timestamp
416
+				'%f',// TXN_total
417
+				'%f',// TXN_paid
418
+				'%s',// STS_ID
419
+				'%s',// TXN_hash_salt
420
+			);
421
+			$success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
422
+			if (! $success) {
423
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
424
+				return 0;
425
+			}
426
+			$txn_id = $wpdb->insert_id;
427
+		}
432 428
 
433
-        return $txn_id;
434
-    }
435
-    /**
436
-     * Detects if the MER tables exist
437
-     * @global type $wpdb
438
-     * @return boolean
439
-     */
440
-    private function _mer_tables_exist()
441
-    {
442
-        if ($this->_mer_tables_exist === null) {
443
-            global $wpdb;
429
+		return $txn_id;
430
+	}
431
+	/**
432
+	 * Detects if the MER tables exist
433
+	 * @global type $wpdb
434
+	 * @return boolean
435
+	 */
436
+	private function _mer_tables_exist()
437
+	{
438
+		if ($this->_mer_tables_exist === null) {
439
+			global $wpdb;
444 440
 
445
-            if ($wpdb->get_var("SHOW TABLES LIKE '{$this->_old_mer_table}'") != $this->_old_mer_table) {
446
-                $this->_mer_tables_exist = false;
447
-            } else {
448
-                $this->_mer_tables_exist = true;
449
-            }
450
-        }
451
-        return $this->_mer_tables_exist;
452
-    }
441
+			if ($wpdb->get_var("SHOW TABLES LIKE '{$this->_old_mer_table}'") != $this->_old_mer_table) {
442
+				$this->_mer_tables_exist = false;
443
+			} else {
444
+				$this->_mer_tables_exist = true;
445
+			}
446
+		}
447
+		return $this->_mer_tables_exist;
448
+	}
453 449
 
454
-    /**
455
-     * Gets the 4.1 registration's status given the 3.1 attendee row. We consider
456
-     * whether the event required pre-approval or not,a dn the 4.1 payment status.
457
-     * @global type $wpdb
458
-     * @param type $old_attendee_row
459
-     * @return string
460
-     */
461
-    private function _get_reg_status_for_old_payment_status($old_attendee_row)
462
-    {
463
-        // need event default reg status and if pre_approval was required
464
-        global $wpdb;
465
-        $event_required_pre_approval = $wpdb->get_var($wpdb->prepare("SELECT require_pre_approval FROM ".$wpdb->prefix."events_detail WHERE id = %d", $old_attendee_row['event_id']));
466
-        return $this->get_migration_script()->convert_3_1_payment_status_to_4_1_STS_ID(
467
-            $old_attendee_row['payment_status'],
468
-            intval($event_required_pre_approval) && intval($old_attendee_row['pre_approve'])
469
-        );
470
-    }
471
-    /**
472
-     * Adds however many rgistrations are indicated by the old attendee's QUANTITY field,
473
-     * and returns an array of their IDs
474
-     * @global type $wpdb
475
-     * @param array $old_attendee
476
-     * @param int $new_attendee_id
477
-     * @param int $new_txn_id
478
-     * @return array of new registratio ids
479
-     */
480
-    private function _insert_new_registrations($old_attendee, $new_attendee_id, $new_txn_id)
481
-    {
482
-        global $wpdb;
450
+	/**
451
+	 * Gets the 4.1 registration's status given the 3.1 attendee row. We consider
452
+	 * whether the event required pre-approval or not,a dn the 4.1 payment status.
453
+	 * @global type $wpdb
454
+	 * @param type $old_attendee_row
455
+	 * @return string
456
+	 */
457
+	private function _get_reg_status_for_old_payment_status($old_attendee_row)
458
+	{
459
+		// need event default reg status and if pre_approval was required
460
+		global $wpdb;
461
+		$event_required_pre_approval = $wpdb->get_var($wpdb->prepare("SELECT require_pre_approval FROM ".$wpdb->prefix."events_detail WHERE id = %d", $old_attendee_row['event_id']));
462
+		return $this->get_migration_script()->convert_3_1_payment_status_to_4_1_STS_ID(
463
+			$old_attendee_row['payment_status'],
464
+			intval($event_required_pre_approval) && intval($old_attendee_row['pre_approve'])
465
+		);
466
+	}
467
+	/**
468
+	 * Adds however many rgistrations are indicated by the old attendee's QUANTITY field,
469
+	 * and returns an array of their IDs
470
+	 * @global type $wpdb
471
+	 * @param array $old_attendee
472
+	 * @param int $new_attendee_id
473
+	 * @param int $new_txn_id
474
+	 * @return array of new registratio ids
475
+	 */
476
+	private function _insert_new_registrations($old_attendee, $new_attendee_id, $new_txn_id)
477
+	{
478
+		global $wpdb;
483 479
 
484
-        $STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
485
-        $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
486
-        if (! $new_event_id) {
487
-            $this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
488
-        }
480
+		$STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
481
+		$new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
482
+		if (! $new_event_id) {
483
+			$this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
484
+		}
489 485
 
490
-        $ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
491
-        if (! $ticket_id) {
492
-            $ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
493
-            $this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
494
-        }
495
-        $regs_on_this_row = intval($old_attendee['quantity']);
496
-        $new_regs = array();
497
-        // 4 cases we need to account for:
498
-        // 1 old attendee_details row with a quantity of X (no mer)
499
-        // Y old attendee_details rows with a quantity of 1 (no mer) joined by their common registration_id
500
-        // Y old attendee_details rows with a quantity of x (because of mer)
501
-        // Y old attendee_details rows with a quantity of 1 (because of mer) joined by wp_events_multi_event_registration_id_group
502
-        for ($count = 1; $count <= $regs_on_this_row; $count++) {
503
-            // sum regs on older rows
504
-            $regs_on_this_event_and_txn = $this->_sum_old_attendees_on_old_txn($old_attendee, true);
505
-            $cols_n_values = array(
506
-                'EVT_ID'=>$new_event_id,
507
-                'ATT_ID'=>$new_attendee_id,
508
-                'TXN_ID'=>$new_txn_id,
509
-                'TKT_ID'=>$ticket_id,
510
-                'STS_ID'=>$STS_ID,
511
-                'REG_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
512
-                'REG_final_price'=>$old_attendee['final_price'],
513
-                'REG_session'=> substr($old_attendee['attendee_session'], 0, 44),
514
-                'REG_code'=>sanitize_key($old_attendee['registration_id']),
515
-                'REG_url_link'=>  sanitize_key($old_attendee['registration_id'].'-'.$count),
516
-                'REG_count'=>$regs_on_this_event_and_txn + $count,
517
-                'REG_group_size'=>$this->_sum_old_attendees_on_old_txn($old_attendee, false),
518
-                'REG_att_is_going'=>true,
519
-                'REG_deleted'=>false
520
-            );
521
-            $datatypes = array(
522
-                '%d',// EVT_ID
523
-                '%d',// ATT_ID
524
-                '%d',// TXN_ID
525
-                '%d',// TKT_ID
526
-                '%s',// STS_ID
527
-                '%s',// REG_date
528
-                '%f',// REG_final_price
529
-                '%s',// REG_session
530
-                '%s',// REG_code
531
-                '%s',// REG_url_link
532
-                '%d',// REG_count
533
-                '%d',// REG_group_size
534
-                '%d',// REG_att_is_going
535
-                '%d',// REG_deleted
536
-            );
537
-            $success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
538
-            if (! $success) {
539
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
540
-                return 0;
541
-            }
542
-            $cols_n_values['REG_ID'] = $wpdb->insert_id;
543
-            $new_regs[] = $wpdb->insert_id;
544
-        }
545
-        $this->_add_regs_to_ticket_and_datetimes($ticket_id, count($new_regs), $STS_ID);
546
-        return $new_regs;
547
-    }
486
+		$ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
487
+		if (! $ticket_id) {
488
+			$ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
489
+			$this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
490
+		}
491
+		$regs_on_this_row = intval($old_attendee['quantity']);
492
+		$new_regs = array();
493
+		// 4 cases we need to account for:
494
+		// 1 old attendee_details row with a quantity of X (no mer)
495
+		// Y old attendee_details rows with a quantity of 1 (no mer) joined by their common registration_id
496
+		// Y old attendee_details rows with a quantity of x (because of mer)
497
+		// Y old attendee_details rows with a quantity of 1 (because of mer) joined by wp_events_multi_event_registration_id_group
498
+		for ($count = 1; $count <= $regs_on_this_row; $count++) {
499
+			// sum regs on older rows
500
+			$regs_on_this_event_and_txn = $this->_sum_old_attendees_on_old_txn($old_attendee, true);
501
+			$cols_n_values = array(
502
+				'EVT_ID'=>$new_event_id,
503
+				'ATT_ID'=>$new_attendee_id,
504
+				'TXN_ID'=>$new_txn_id,
505
+				'TKT_ID'=>$ticket_id,
506
+				'STS_ID'=>$STS_ID,
507
+				'REG_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
508
+				'REG_final_price'=>$old_attendee['final_price'],
509
+				'REG_session'=> substr($old_attendee['attendee_session'], 0, 44),
510
+				'REG_code'=>sanitize_key($old_attendee['registration_id']),
511
+				'REG_url_link'=>  sanitize_key($old_attendee['registration_id'].'-'.$count),
512
+				'REG_count'=>$regs_on_this_event_and_txn + $count,
513
+				'REG_group_size'=>$this->_sum_old_attendees_on_old_txn($old_attendee, false),
514
+				'REG_att_is_going'=>true,
515
+				'REG_deleted'=>false
516
+			);
517
+			$datatypes = array(
518
+				'%d',// EVT_ID
519
+				'%d',// ATT_ID
520
+				'%d',// TXN_ID
521
+				'%d',// TKT_ID
522
+				'%s',// STS_ID
523
+				'%s',// REG_date
524
+				'%f',// REG_final_price
525
+				'%s',// REG_session
526
+				'%s',// REG_code
527
+				'%s',// REG_url_link
528
+				'%d',// REG_count
529
+				'%d',// REG_group_size
530
+				'%d',// REG_att_is_going
531
+				'%d',// REG_deleted
532
+			);
533
+			$success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
534
+			if (! $success) {
535
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
536
+				return 0;
537
+			}
538
+			$cols_n_values['REG_ID'] = $wpdb->insert_id;
539
+			$new_regs[] = $wpdb->insert_id;
540
+		}
541
+		$this->_add_regs_to_ticket_and_datetimes($ticket_id, count($new_regs), $STS_ID);
542
+		return $new_regs;
543
+	}
548 544
 
549
-    /**
550
-     * Increments the sold values on the ticket and its related datetimes by the amount sold,
551
-     * which should be done directly after adding the rows. Yes this means we're constantly incrementing
552
-     * the sold amounts as we go, and is less efficient than a single big query,
553
-     * but its safer because we KNOW these regs have been added, rather than inferring
554
-     * that they WILL be added (because the attendees stage runs nearly last during
555
-     * the migration script)
556
-     * @param type $new_ticket_id
557
-     * @param type $sold
558
-     * @param type $STS_ID
559
-     * @return boolean whether they were successfully updated or not
560
-     */
561
-    protected function _add_regs_to_ticket_and_datetimes($new_ticket_id, $quantity_sold, $STS_ID)
562
-    {
563
-        if ($STS_ID != 'RAP') {
564
-            return true;
565
-        }
566
-        global $wpdb;
567
-        $success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
568
-        if ($success) {
569
-            // get the ticket's datetimes, and increment them too
570
-            $success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
545
+	/**
546
+	 * Increments the sold values on the ticket and its related datetimes by the amount sold,
547
+	 * which should be done directly after adding the rows. Yes this means we're constantly incrementing
548
+	 * the sold amounts as we go, and is less efficient than a single big query,
549
+	 * but its safer because we KNOW these regs have been added, rather than inferring
550
+	 * that they WILL be added (because the attendees stage runs nearly last during
551
+	 * the migration script)
552
+	 * @param type $new_ticket_id
553
+	 * @param type $sold
554
+	 * @param type $STS_ID
555
+	 * @return boolean whether they were successfully updated or not
556
+	 */
557
+	protected function _add_regs_to_ticket_and_datetimes($new_ticket_id, $quantity_sold, $STS_ID)
558
+	{
559
+		if ($STS_ID != 'RAP') {
560
+			return true;
561
+		}
562
+		global $wpdb;
563
+		$success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
564
+		if ($success) {
565
+			// get the ticket's datetimes, and increment them too
566
+			$success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
571 567
 				INNER JOIN {$this->_new_ticket_datetime_table} as DTK ON TKT.TKT_ID = DTK.TKT_ID
572 568
 				INNER JOIN {$this->_new_datetime_table} as DTT ON DTK.DTT_ID = DTT.DTT_ID
573 569
 				SET DTT.DTT_sold = DTT.DTT_sold + %d WHERE TKT.TKT_ID = %d", $quantity_sold, $new_ticket_id));
574
-            if (! $success_update_dateimtes) {
575
-                $this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
576
-            }
577
-        } else {
578
-            $this->add_error(sprintf(__("Could not update ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
579
-        }
580
-        return true;
581
-    }
582
-    /**
583
-     * Makes a best guess at which ticket is the one the attendee purchased.
584
-     * Obviously, the old attendee's event_id narrows it down quite a bit;
585
-     * then the old attendee's orig_price and event_time, and price_option can uniquely identify the ticket
586
-     * however, if we don't find an exact match, see if any of those conditions match;
587
-     * and lastly if none of that works, just use the first ticket for the event we find
588
-     * @param array $old_attendee
589
-     */
590
-    private function _try_to_find_new_ticket_id($old_attendee, $new_event_id)
591
-    {
592
-        global $wpdb;
593
-        $tickets_table = $this->_new_ticket_table;
594
-        $datetime_tickets_table = $this->_new_ticket_datetime_table;
595
-        $datetime_table = $this->_new_datetime_table;
570
+			if (! $success_update_dateimtes) {
571
+				$this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
572
+			}
573
+		} else {
574
+			$this->add_error(sprintf(__("Could not update ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
575
+		}
576
+		return true;
577
+	}
578
+	/**
579
+	 * Makes a best guess at which ticket is the one the attendee purchased.
580
+	 * Obviously, the old attendee's event_id narrows it down quite a bit;
581
+	 * then the old attendee's orig_price and event_time, and price_option can uniquely identify the ticket
582
+	 * however, if we don't find an exact match, see if any of those conditions match;
583
+	 * and lastly if none of that works, just use the first ticket for the event we find
584
+	 * @param array $old_attendee
585
+	 */
586
+	private function _try_to_find_new_ticket_id($old_attendee, $new_event_id)
587
+	{
588
+		global $wpdb;
589
+		$tickets_table = $this->_new_ticket_table;
590
+		$datetime_tickets_table = $this->_new_ticket_datetime_table;
591
+		$datetime_table = $this->_new_datetime_table;
596 592
 
597
-        $old_att_price_option = $old_attendee['price_option'];
598
-        $old_att_price = floatval($old_attendee['orig_price']);
593
+		$old_att_price_option = $old_attendee['price_option'];
594
+		$old_att_price = floatval($old_attendee['orig_price']);
599 595
 
600
-        $old_att_start_date = $old_attendee['start_date'];
601
-        $old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
602
-        $old_att_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
603
-        // add all conditions to an array from which we can SHIFT conditions off in order to widen our search
604
-        // the most important condition should be last, as it will be array_shift'ed off last
605
-        $conditions = array(
606
-            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
607
-            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
608
-            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
609
-            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
610
-        );
611
-        $select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
596
+		$old_att_start_date = $old_attendee['start_date'];
597
+		$old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
598
+		$old_att_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
599
+		// add all conditions to an array from which we can SHIFT conditions off in order to widen our search
600
+		// the most important condition should be last, as it will be array_shift'ed off last
601
+		$conditions = array(
602
+			$wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
603
+			$wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
604
+			$wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
605
+			$wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
606
+		);
607
+		$select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
612 608
 			$datetime_tickets_table ON $tickets_table.TKT_ID = $datetime_tickets_table.TKT_ID INNER JOIN
613 609
 			$datetime_table ON $datetime_tickets_table.DTT_ID = $datetime_table.DTT_ID";
614
-        // start running queries, widening search each time by removing a condition
615
-        do {
616
-            $full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
617
-            $ticket_id_found = $wpdb->get_var($full_query);
618
-            array_shift($conditions);
619
-        } while (! $ticket_id_found && $conditions);
620
-        return $ticket_id_found;
621
-    }
610
+		// start running queries, widening search each time by removing a condition
611
+		do {
612
+			$full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
613
+			$ticket_id_found = $wpdb->get_var($full_query);
614
+			array_shift($conditions);
615
+		} while (! $ticket_id_found && $conditions);
616
+		return $ticket_id_found;
617
+	}
622 618
 
623
-    /**
624
-     * If we couldn't find a 4.1 ticket for a 3.1 attendee row, this function creates one;
625
-     * and it also tries to find a datetime that works, and a inserts a price, and associates
626
-     * the new ticket to that datetime and price.
627
-     * @return int ticket id
628
-     */
629
-    private function _insert_new_ticket_because_none_found($old_attendee, $new_event_id)
630
-    {
631
-        global $wpdb;
632
-        $old_att_price_option = $old_attendee['price_option'];
633
-        $old_att_price = floatval($old_attendee['orig_price']);
619
+	/**
620
+	 * If we couldn't find a 4.1 ticket for a 3.1 attendee row, this function creates one;
621
+	 * and it also tries to find a datetime that works, and a inserts a price, and associates
622
+	 * the new ticket to that datetime and price.
623
+	 * @return int ticket id
624
+	 */
625
+	private function _insert_new_ticket_because_none_found($old_attendee, $new_event_id)
626
+	{
627
+		global $wpdb;
628
+		$old_att_price_option = $old_attendee['price_option'];
629
+		$old_att_price = floatval($old_attendee['orig_price']);
634 630
 
635
-        $old_att_start_date = $old_attendee['start_date'];
636
-        $old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
637
-        $old_att_start_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
631
+		$old_att_start_date = $old_attendee['start_date'];
632
+		$old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
633
+		$old_att_start_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
638 634
 
639 635
 
640
-        // insert new datetime unless we find one
641
-        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
642
-        if (! $datetime_id) {
643
-            $old_att_end_date = $old_attendee['start_date'];
644
-            $old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
645
-            $old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
646
-            $wpdb->insert(
647
-                $this->_new_datetime_table,
648
-                array(
649
-                        'EVT_ID' => $new_event_id,
650
-                        'DTT_EVT_start' => $old_att_start_datetime,
651
-                        'DTT_EVT_end' => $old_att_end_datetime,
652
-                        'DTT_deleted' => true
653
-                    ),
654
-                array(
655
-                        '%d',// EVT_ID
656
-                        '%s',// DTT_EVT_start
657
-                        '%s',// DTT_EVT_end
658
-                        '%d',// DTT_deleted
659
-                    )
660
-            );
661
-            $datetime_id = $wpdb->insert_id;
662
-        }
636
+		// insert new datetime unless we find one
637
+		$datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
638
+		if (! $datetime_id) {
639
+			$old_att_end_date = $old_attendee['start_date'];
640
+			$old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
641
+			$old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
642
+			$wpdb->insert(
643
+				$this->_new_datetime_table,
644
+				array(
645
+						'EVT_ID' => $new_event_id,
646
+						'DTT_EVT_start' => $old_att_start_datetime,
647
+						'DTT_EVT_end' => $old_att_end_datetime,
648
+						'DTT_deleted' => true
649
+					),
650
+				array(
651
+						'%d',// EVT_ID
652
+						'%s',// DTT_EVT_start
653
+						'%s',// DTT_EVT_end
654
+						'%d',// DTT_deleted
655
+					)
656
+			);
657
+			$datetime_id = $wpdb->insert_id;
658
+		}
663 659
 
664
-        // insert new ticket
665
-        $success = $wpdb->insert(
666
-            $wpdb->prefix . 'esp_ticket',
667
-            array(
668
-                    'TKT_name' => $old_att_price_option,
669
-                    'TKT_qty' => -1,
670
-                    'TKT_price' => $old_att_price,
671
-                    'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
672
-                    'TKT_end_date' => $old_att_end_datetime,
660
+		// insert new ticket
661
+		$success = $wpdb->insert(
662
+			$wpdb->prefix . 'esp_ticket',
663
+			array(
664
+					'TKT_name' => $old_att_price_option,
665
+					'TKT_qty' => -1,
666
+					'TKT_price' => $old_att_price,
667
+					'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
668
+					'TKT_end_date' => $old_att_end_datetime,
673 669
 
674
-                ),
675
-            array(
676
-                    '%s',// name
677
-                    '%d',// qty
678
-                    '%d',// price
679
-                    '%s',// start_date
680
-                    '%s',// end_date
681
-                )
682
-        );
683
-        $ticket_id = $wpdb->insert_id;
684
-        // associate the ticket with the datetime we found earlier
685
-        $wpdb->insert(
686
-            $this->_new_datetime_ticket_table,
687
-            array(
688
-                    'DTT_ID' => $datetime_id,
689
-                    'TKT_ID' => $ticket_id
690
-                ),
691
-            array(
692
-                    '%d',// DTT_ID
693
-                    '%d',// TKT_ID
694
-                )
695
-        );
696
-        // insert new price
697
-        $wpdb->insert(
698
-            $this->_new_price_table,
699
-            array(
700
-                    'PRC_amount' => $old_att_price,
701
-                    'PRT_ID' => EE_DMS_4_1_0_prices::price_type_base,
702
-                    'PRC_name' => $old_att_price_option,
703
-                    'PRC_deleted' => true
704
-                ),
705
-            array(
706
-                    '%d',// PRC_amount
707
-                    '%d',// PRT_ID
708
-                    '%s',// PRC_name
709
-                    '%d',// PRC_deleted
710
-                )
711
-        );
712
-        $price_id = $wpdb->insert_id;
713
-        // associate the price to the ticket
714
-        $wpdb->insert(
715
-            $this->_new_ticket_price_table,
716
-            array(
717
-                    'TKT_ID' => $ticket_id,
718
-                    'PRC_ID' => $price_id
719
-                ),
720
-            array(
721
-                    '%d',// TKT_ID
722
-                    '%d',// PRC_ID
723
-                )
724
-        );
725
-        return $ticket_id;
726
-    }
727
-    /**
728
-     * Counts all the registrations on this transaction. If $count_only_older is TRUE then returns the number added SO FAR (ie,
729
-     * only considers attendee rows with an ID less than this one's), but if $count_only_older is FALSe returns ALL
730
-     * @global type $wpdb
731
-     * @param array $old_attendee_row
732
-     * @param boolean $count_only_older true if you want the running count (ie, the total up to this row), and false if you want ALL
733
-     * @return int
734
-     */
735
-    private function _sum_old_attendees_on_old_txn($old_attendee_row, $count_only_older = false)
736
-    {
737
-        global $wpdb;
738
-        $count_only_older_sql = $count_only_older ? $wpdb->prepare(" AND id<%d", $old_attendee_row['id']) : '';
739
-        $count = intval($wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM ".$this->_old_table." WHERE registration_id=%s $count_only_older_sql", $old_attendee_row['registration_id'])));
670
+				),
671
+			array(
672
+					'%s',// name
673
+					'%d',// qty
674
+					'%d',// price
675
+					'%s',// start_date
676
+					'%s',// end_date
677
+				)
678
+		);
679
+		$ticket_id = $wpdb->insert_id;
680
+		// associate the ticket with the datetime we found earlier
681
+		$wpdb->insert(
682
+			$this->_new_datetime_ticket_table,
683
+			array(
684
+					'DTT_ID' => $datetime_id,
685
+					'TKT_ID' => $ticket_id
686
+				),
687
+			array(
688
+					'%d',// DTT_ID
689
+					'%d',// TKT_ID
690
+				)
691
+		);
692
+		// insert new price
693
+		$wpdb->insert(
694
+			$this->_new_price_table,
695
+			array(
696
+					'PRC_amount' => $old_att_price,
697
+					'PRT_ID' => EE_DMS_4_1_0_prices::price_type_base,
698
+					'PRC_name' => $old_att_price_option,
699
+					'PRC_deleted' => true
700
+				),
701
+			array(
702
+					'%d',// PRC_amount
703
+					'%d',// PRT_ID
704
+					'%s',// PRC_name
705
+					'%d',// PRC_deleted
706
+				)
707
+		);
708
+		$price_id = $wpdb->insert_id;
709
+		// associate the price to the ticket
710
+		$wpdb->insert(
711
+			$this->_new_ticket_price_table,
712
+			array(
713
+					'TKT_ID' => $ticket_id,
714
+					'PRC_ID' => $price_id
715
+				),
716
+			array(
717
+					'%d',// TKT_ID
718
+					'%d',// PRC_ID
719
+				)
720
+		);
721
+		return $ticket_id;
722
+	}
723
+	/**
724
+	 * Counts all the registrations on this transaction. If $count_only_older is TRUE then returns the number added SO FAR (ie,
725
+	 * only considers attendee rows with an ID less than this one's), but if $count_only_older is FALSe returns ALL
726
+	 * @global type $wpdb
727
+	 * @param array $old_attendee_row
728
+	 * @param boolean $count_only_older true if you want the running count (ie, the total up to this row), and false if you want ALL
729
+	 * @return int
730
+	 */
731
+	private function _sum_old_attendees_on_old_txn($old_attendee_row, $count_only_older = false)
732
+	{
733
+		global $wpdb;
734
+		$count_only_older_sql = $count_only_older ? $wpdb->prepare(" AND id<%d", $old_attendee_row['id']) : '';
735
+		$count = intval($wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM ".$this->_old_table." WHERE registration_id=%s $count_only_older_sql", $old_attendee_row['registration_id'])));
740 736
 
741
-        if ($this->_mer_tables_exist()) {
742
-            // if MER exists, then its a little tricky.
743
-            // when users registered by adding items to the cart, and it was a
744
-            // group registration requiring additional attendee INFO, then the attendee rows
745
-            // DO NOT have the same registration_id (although they probably should have)
746
-            // they are related just like MER attendee rows are related, through the MER group table
747
-            // BUT we want to count all the MER attendee rows for the same registration
748
-            $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee_row['registration_id']);
737
+		if ($this->_mer_tables_exist()) {
738
+			// if MER exists, then its a little tricky.
739
+			// when users registered by adding items to the cart, and it was a
740
+			// group registration requiring additional attendee INFO, then the attendee rows
741
+			// DO NOT have the same registration_id (although they probably should have)
742
+			// they are related just like MER attendee rows are related, through the MER group table
743
+			// BUT we want to count all the MER attendee rows for the same registration
744
+			$primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee_row['registration_id']);
749 745
 
750
-            $count_using_mer_table = $wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM {$this->_old_table} att INNER JOIN {$this->_old_mer_table} mer ON att.registration_id = mer.registration_id WHERE att.event_id=%d AND mer.primary_registration_id = %s $count_only_older_sql", $old_attendee_row['event_id'], $primary_attendee['registration_id']));
751
-            $count = max($count_using_mer_table, $count);
752
-        }
753
-        return $count;
754
-    }
755
-    private function _insert_new_payment($old_attendee, $new_txn_id)
756
-    {
757
-        global $wpdb;
758
-        // only add a payment for primary attendees
759
-        $old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
760
-        // if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
761
-        if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
762
-            $pay_status_mapping = array(
763
-                'Completed'=>'PAP',
764
-                'Payment Declined'=>'PDC',
765
-                'Cancelled'=>'PCN',
766
-                'Declined'=>'PDC'
767
-            );
768
-            $by_admin = $old_attendee['payment'] == 'Admin';
769
-            $STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
770
-            $cols_n_values = array(
771
-                'TXN_ID'=>$new_txn_id,
772
-                'STS_ID'=>$STS_ID,
773
-                'PAY_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
774
-                'PAY_method'=>'CART',
775
-                'PAY_amount'=>$old_attendee['amount_pd'],
776
-                'PAY_gateway'=>$old_attendee['txn_type'],
777
-                'PAY_gateway_response'=>'',
778
-                'PAY_txn_id_chq_nmbr'=>substr($old_attendee['txn_id'], 0, 32),
779
-                'PAY_via_admin'=>$by_admin,
780
-                'PAY_details'=>$old_attendee['transaction_details']
746
+			$count_using_mer_table = $wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM {$this->_old_table} att INNER JOIN {$this->_old_mer_table} mer ON att.registration_id = mer.registration_id WHERE att.event_id=%d AND mer.primary_registration_id = %s $count_only_older_sql", $old_attendee_row['event_id'], $primary_attendee['registration_id']));
747
+			$count = max($count_using_mer_table, $count);
748
+		}
749
+		return $count;
750
+	}
751
+	private function _insert_new_payment($old_attendee, $new_txn_id)
752
+	{
753
+		global $wpdb;
754
+		// only add a payment for primary attendees
755
+		$old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
756
+		// if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
757
+		if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
758
+			$pay_status_mapping = array(
759
+				'Completed'=>'PAP',
760
+				'Payment Declined'=>'PDC',
761
+				'Cancelled'=>'PCN',
762
+				'Declined'=>'PDC'
763
+			);
764
+			$by_admin = $old_attendee['payment'] == 'Admin';
765
+			$STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
766
+			$cols_n_values = array(
767
+				'TXN_ID'=>$new_txn_id,
768
+				'STS_ID'=>$STS_ID,
769
+				'PAY_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
770
+				'PAY_method'=>'CART',
771
+				'PAY_amount'=>$old_attendee['amount_pd'],
772
+				'PAY_gateway'=>$old_attendee['txn_type'],
773
+				'PAY_gateway_response'=>'',
774
+				'PAY_txn_id_chq_nmbr'=>substr($old_attendee['txn_id'], 0, 32),
775
+				'PAY_via_admin'=>$by_admin,
776
+				'PAY_details'=>$old_attendee['transaction_details']
781 777
 
782
-            );
783
-            $datatypes = array(
784
-                '%d',// TXN_Id
785
-                '%s',// STS_ID
786
-                '%s',// PAY_timestamp
787
-                '%s',// PAY_method
788
-                '%f',// PAY_amount
789
-                '%s',// PAY_gateway
790
-                '%s',// PAY_gateway_response
791
-                '%s',// PAY_txn_id_chq_nmbr
792
-                '%d',// PAY_via_admin
793
-                '%s',// PAY_details
794
-            );
795
-            $success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
796
-            if (! $success) {
797
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
798
-                return 0;
799
-            }
800
-            $new_id = $wpdb->insert_id;
801
-            return $new_id;
802
-        } else {
803
-            return 0;
804
-        }
805
-    }
778
+			);
779
+			$datatypes = array(
780
+				'%d',// TXN_Id
781
+				'%s',// STS_ID
782
+				'%s',// PAY_timestamp
783
+				'%s',// PAY_method
784
+				'%f',// PAY_amount
785
+				'%s',// PAY_gateway
786
+				'%s',// PAY_gateway_response
787
+				'%s',// PAY_txn_id_chq_nmbr
788
+				'%d',// PAY_via_admin
789
+				'%s',// PAY_details
790
+			);
791
+			$success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
792
+			if (! $success) {
793
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
794
+				return 0;
795
+			}
796
+			$new_id = $wpdb->insert_id;
797
+			return $new_id;
798
+		} else {
799
+			return 0;
800
+		}
801
+	}
806 802
 
807
-    /**
808
-     * If MER is active, if you want ot fin dthe other registrations on that attendee row
809
-     * @global type $wpdb
810
-     * @param type $old_registration_id
811
-     * @return array
812
-     */
813
-    private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
814
-    {
815
-        if (! $this->_mer_tables_exist()) {
816
-            return false;
817
-        }
818
-        global $wpdb;
819
-        $old_att_for_primary_reg = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->_old_mer_table} AS mer INNER JOIN {$this->_old_table} AS att ON mer.primary_registration_id = att.registration_id WHERE mer.registration_id=%s LIMIT 1", $old_registration_id), ARRAY_A);
820
-        return $old_att_for_primary_reg;
821
-    }
803
+	/**
804
+	 * If MER is active, if you want ot fin dthe other registrations on that attendee row
805
+	 * @global type $wpdb
806
+	 * @param type $old_registration_id
807
+	 * @return array
808
+	 */
809
+	private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
810
+	{
811
+		if (! $this->_mer_tables_exist()) {
812
+			return false;
813
+		}
814
+		global $wpdb;
815
+		$old_att_for_primary_reg = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->_old_mer_table} AS mer INNER JOIN {$this->_old_table} AS att ON mer.primary_registration_id = att.registration_id WHERE mer.registration_id=%s LIMIT 1", $old_registration_id), ARRAY_A);
816
+		return $old_att_for_primary_reg;
817
+	}
822 818
 }
Please login to merge, or discard this patch.
Spacing   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
         $this->select_expression = 'att.*, e.event_status';
214 214
         // Only select attendees for events that aren't deleted.
215 215
         $this->_extra_where_sql = 'AS att
216
-            INNER JOIN ' . $wpdb->prefix . 'events_detail AS e ON att.event_id=e.id
216
+            INNER JOIN ' . $wpdb->prefix.'events_detail AS e ON att.event_id=e.id
217 217
             WHERE e.event_status!="D"';
218 218
         $this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
219 219
         $this->_new_attendee_cpt_table = $wpdb->posts;
@@ -235,9 +235,9 @@  discard block
 block discarded – undo
235 235
     {
236 236
         // first check if there's already a new attendee with similar characteristics
237 237
         $new_att_id = $this->_find_attendee_cpt_matching($old_row);
238
-        if (! $new_att_id) {
238
+        if ( ! $new_att_id) {
239 239
             $new_att_id = $this->_insert_new_attendee_cpt($old_row);
240
-            if (! $new_att_id) {
240
+            if ( ! $new_att_id) {
241 241
                 // if we couldnt even make an attendee, abandon all hope
242 242
                 return false;
243 243
             }
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
         $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
250 250
 
251 251
         $txn_id = $this->_insert_new_transaction($old_row);
252
-        if (! $txn_id) {
252
+        if ( ! $txn_id) {
253 253
             // if we couldnt make the transaction, also abandon all hope
254 254
             return false;
255 255
         }
@@ -283,31 +283,31 @@  discard block
 block discarded – undo
283 283
     {
284 284
         global $wpdb;
285 285
         $cols_n_values = array(
286
-            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
287
-            'post_content'=>'',// ATT_bio
288
-            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
289
-            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
290
-            'post_excerpt'=>'',// ATT_short_bio
291
-            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
292
-            'post_author'=>0,// ATT_author
293
-            'post_parent'=>0,// ATT_parent
294
-            'post_type'=>'espresso_attendees',// post_type
286
+            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']), // ATT_full_name
287
+            'post_content'=>'', // ATT_bio
288
+            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']), // ATT_slug
289
+            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']), // ATT_created
290
+            'post_excerpt'=>'', // ATT_short_bio
291
+            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']), // ATT_modified
292
+            'post_author'=>0, // ATT_author
293
+            'post_parent'=>0, // ATT_parent
294
+            'post_type'=>'espresso_attendees', // post_type
295 295
             'post_status'=>'publish'// status
296 296
         );
297 297
         $datatypes = array(
298
-            '%s',// ATT_full_name
299
-            '%s',// ATT_bio
300
-            '%s',// ATT_slug
301
-            '%s',// ATT_created
302
-            '%s',// ATT_short_bio
303
-            '%s',// ATT_modified
304
-            '%d',// ATT_author
305
-            '%d',// ATT_parent
306
-            '%s',// post_type
307
-            '%s',// status
298
+            '%s', // ATT_full_name
299
+            '%s', // ATT_bio
300
+            '%s', // ATT_slug
301
+            '%s', // ATT_created
302
+            '%s', // ATT_short_bio
303
+            '%s', // ATT_modified
304
+            '%d', // ATT_author
305
+            '%d', // ATT_parent
306
+            '%s', // post_type
307
+            '%s', // status
308 308
         );
309 309
         $success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
310
-        if (! $success) {
310
+        if ( ! $success) {
311 311
             $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
312 312
             return 0;
313 313
         }
@@ -345,20 +345,20 @@  discard block
 block discarded – undo
345 345
             'ATT_phone'=>stripslashes($old_attendee['phone']),
346 346
         );
347 347
         $datatypes = array(
348
-            '%d',// ATT_ID
349
-            '%s',// ATT_fname
350
-            '%s',// ATT_lname
351
-            '%s',// ATT_address
352
-            '%s',// ATT_address2
353
-            '%s',// ATT_city
354
-            '%d',// STA_ID
355
-            '%s',// CNT_ISO
356
-            '%s',// ATT_zip
357
-            '%s',// ATT_email
358
-            '%s',// ATT_phone
348
+            '%d', // ATT_ID
349
+            '%s', // ATT_fname
350
+            '%s', // ATT_lname
351
+            '%s', // ATT_address
352
+            '%s', // ATT_address2
353
+            '%s', // ATT_city
354
+            '%d', // STA_ID
355
+            '%s', // CNT_ISO
356
+            '%s', // ATT_zip
357
+            '%s', // ATT_email
358
+            '%s', // ATT_phone
359 359
         );
360 360
         $success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
361
-        if (! $success) {
361
+        if ( ! $success) {
362 362
             $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
363 363
             return 0;
364 364
         }
@@ -383,12 +383,12 @@  discard block
 block discarded – undo
383 383
             $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
384 384
         } else { // non-primary attendee, so find its primary attendee's transaction
385 385
             $primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
386
-            if (! $primary_attendee_old_id) {
386
+            if ( ! $primary_attendee_old_id) {
387 387
                 $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
388 388
                 $primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
389 389
             }
390 390
             $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
391
-            if (! $txn_id) {
391
+            if ( ! $txn_id) {
392 392
                 $this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
393 393
                 $txn_id = 0;
394 394
             }
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
         // if there isn't yet a transaction row for this, create one
397 397
         // (so even if it was a non-primary attendee with no EE3 primary attendee,
398 398
         // it ought to have SOME transaction, so we'll make one)
399
-        if (! $txn_id) {
399
+        if ( ! $txn_id) {
400 400
             // maps 3.1 payment stati onto 4.1 transaction stati
401 401
             $txn_status_mapping = array(
402 402
                 'Completed'=>'TCM',
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
                 'Cancelled'=>'TIN',
408 408
                 'Declined'=>'TIN'
409 409
             );
410
-            $STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
410
+            $STS_ID = isset($txn_status_mapping[$old_attendee['payment_status']]) ? $txn_status_mapping[$old_attendee['payment_status']] : 'TIN';
411 411
             $cols_n_values = array(
412 412
                 'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
413 413
                 'TXN_total'=>floatval($old_attendee['total_cost']),
@@ -416,14 +416,14 @@  discard block
 block discarded – undo
416 416
                 'TXN_hash_salt'=>$old_attendee['hashSalt']
417 417
             );
418 418
             $datatypes = array(
419
-                '%s',// TXN_timestamp
420
-                '%f',// TXN_total
421
-                '%f',// TXN_paid
422
-                '%s',// STS_ID
423
-                '%s',// TXN_hash_salt
419
+                '%s', // TXN_timestamp
420
+                '%f', // TXN_total
421
+                '%f', // TXN_paid
422
+                '%s', // STS_ID
423
+                '%s', // TXN_hash_salt
424 424
             );
425 425
             $success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
426
-            if (! $success) {
426
+            if ( ! $success) {
427 427
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
428 428
                 return 0;
429 429
             }
@@ -483,12 +483,12 @@  discard block
 block discarded – undo
483 483
 
484 484
         $STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
485 485
         $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
486
-        if (! $new_event_id) {
486
+        if ( ! $new_event_id) {
487 487
             $this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
488 488
         }
489 489
 
490 490
         $ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
491
-        if (! $ticket_id) {
491
+        if ( ! $ticket_id) {
492 492
             $ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
493 493
             $this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
494 494
         }
@@ -519,23 +519,23 @@  discard block
 block discarded – undo
519 519
                 'REG_deleted'=>false
520 520
             );
521 521
             $datatypes = array(
522
-                '%d',// EVT_ID
523
-                '%d',// ATT_ID
524
-                '%d',// TXN_ID
525
-                '%d',// TKT_ID
526
-                '%s',// STS_ID
527
-                '%s',// REG_date
528
-                '%f',// REG_final_price
529
-                '%s',// REG_session
530
-                '%s',// REG_code
531
-                '%s',// REG_url_link
532
-                '%d',// REG_count
533
-                '%d',// REG_group_size
534
-                '%d',// REG_att_is_going
535
-                '%d',// REG_deleted
522
+                '%d', // EVT_ID
523
+                '%d', // ATT_ID
524
+                '%d', // TXN_ID
525
+                '%d', // TKT_ID
526
+                '%s', // STS_ID
527
+                '%s', // REG_date
528
+                '%f', // REG_final_price
529
+                '%s', // REG_session
530
+                '%s', // REG_code
531
+                '%s', // REG_url_link
532
+                '%d', // REG_count
533
+                '%d', // REG_group_size
534
+                '%d', // REG_att_is_going
535
+                '%d', // REG_deleted
536 536
             );
537 537
             $success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
538
-            if (! $success) {
538
+            if ( ! $success) {
539 539
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
540 540
                 return 0;
541 541
             }
@@ -567,11 +567,11 @@  discard block
 block discarded – undo
567 567
         $success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
568 568
         if ($success) {
569 569
             // get the ticket's datetimes, and increment them too
570
-            $success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
570
+            $success_update_dateimtes = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
571 571
 				INNER JOIN {$this->_new_ticket_datetime_table} as DTK ON TKT.TKT_ID = DTK.TKT_ID
572 572
 				INNER JOIN {$this->_new_datetime_table} as DTT ON DTK.DTT_ID = DTT.DTT_ID
573 573
 				SET DTT.DTT_sold = DTT.DTT_sold + %d WHERE TKT.TKT_ID = %d", $quantity_sold, $new_ticket_id));
574
-            if (! $success_update_dateimtes) {
574
+            if ( ! $success_update_dateimtes) {
575 575
                 $this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
576 576
             }
577 577
         } else {
@@ -603,10 +603,10 @@  discard block
 block discarded – undo
603 603
         // add all conditions to an array from which we can SHIFT conditions off in order to widen our search
604 604
         // the most important condition should be last, as it will be array_shift'ed off last
605 605
         $conditions = array(
606
-            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
607
-            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
608
-            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
609
-            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
606
+            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime), // times match?
607
+            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price), // prices match?
608
+            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option), // names match?
609
+            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id), // events match?
610 610
         );
611 611
         $select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
612 612
 			$datetime_tickets_table ON $tickets_table.TKT_ID = $datetime_tickets_table.TKT_ID INNER JOIN
@@ -616,7 +616,7 @@  discard block
 block discarded – undo
616 616
             $full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
617 617
             $ticket_id_found = $wpdb->get_var($full_query);
618 618
             array_shift($conditions);
619
-        } while (! $ticket_id_found && $conditions);
619
+        }while ( ! $ticket_id_found && $conditions);
620 620
         return $ticket_id_found;
621 621
     }
622 622
 
@@ -638,8 +638,8 @@  discard block
 block discarded – undo
638 638
 
639 639
 
640 640
         // insert new datetime unless we find one
641
-        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
642
-        if (! $datetime_id) {
641
+        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM ".$this->_new_datetime_table." WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
642
+        if ( ! $datetime_id) {
643 643
             $old_att_end_date = $old_attendee['start_date'];
644 644
             $old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
645 645
             $old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
@@ -652,10 +652,10 @@  discard block
 block discarded – undo
652 652
                         'DTT_deleted' => true
653 653
                     ),
654 654
                 array(
655
-                        '%d',// EVT_ID
656
-                        '%s',// DTT_EVT_start
657
-                        '%s',// DTT_EVT_end
658
-                        '%d',// DTT_deleted
655
+                        '%d', // EVT_ID
656
+                        '%s', // DTT_EVT_start
657
+                        '%s', // DTT_EVT_end
658
+                        '%d', // DTT_deleted
659 659
                     )
660 660
             );
661 661
             $datetime_id = $wpdb->insert_id;
@@ -663,21 +663,21 @@  discard block
 block discarded – undo
663 663
 
664 664
         // insert new ticket
665 665
         $success = $wpdb->insert(
666
-            $wpdb->prefix . 'esp_ticket',
666
+            $wpdb->prefix.'esp_ticket',
667 667
             array(
668 668
                     'TKT_name' => $old_att_price_option,
669 669
                     'TKT_qty' => -1,
670 670
                     'TKT_price' => $old_att_price,
671
-                    'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
671
+                    'TKT_start_date' => $old_att_start_datetime, // we really have no clue what the time should be, but at least it was available when they attended
672 672
                     'TKT_end_date' => $old_att_end_datetime,
673 673
 
674 674
                 ),
675 675
             array(
676
-                    '%s',// name
677
-                    '%d',// qty
678
-                    '%d',// price
679
-                    '%s',// start_date
680
-                    '%s',// end_date
676
+                    '%s', // name
677
+                    '%d', // qty
678
+                    '%d', // price
679
+                    '%s', // start_date
680
+                    '%s', // end_date
681 681
                 )
682 682
         );
683 683
         $ticket_id = $wpdb->insert_id;
@@ -689,8 +689,8 @@  discard block
 block discarded – undo
689 689
                     'TKT_ID' => $ticket_id
690 690
                 ),
691 691
             array(
692
-                    '%d',// DTT_ID
693
-                    '%d',// TKT_ID
692
+                    '%d', // DTT_ID
693
+                    '%d', // TKT_ID
694 694
                 )
695 695
         );
696 696
         // insert new price
@@ -703,10 +703,10 @@  discard block
 block discarded – undo
703 703
                     'PRC_deleted' => true
704 704
                 ),
705 705
             array(
706
-                    '%d',// PRC_amount
707
-                    '%d',// PRT_ID
708
-                    '%s',// PRC_name
709
-                    '%d',// PRC_deleted
706
+                    '%d', // PRC_amount
707
+                    '%d', // PRT_ID
708
+                    '%s', // PRC_name
709
+                    '%d', // PRC_deleted
710 710
                 )
711 711
         );
712 712
         $price_id = $wpdb->insert_id;
@@ -718,8 +718,8 @@  discard block
 block discarded – undo
718 718
                     'PRC_ID' => $price_id
719 719
                 ),
720 720
             array(
721
-                    '%d',// TKT_ID
722
-                    '%d',// PRC_ID
721
+                    '%d', // TKT_ID
722
+                    '%d', // PRC_ID
723 723
                 )
724 724
         );
725 725
         return $ticket_id;
@@ -756,7 +756,7 @@  discard block
 block discarded – undo
756 756
     {
757 757
         global $wpdb;
758 758
         // only add a payment for primary attendees
759
-        $old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
759
+        $old_pay_stati_indicating_no_payment = array('Pending', 'Incomplete', 'Not Completed');
760 760
         // if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
761 761
         if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
762 762
             $pay_status_mapping = array(
@@ -766,7 +766,7 @@  discard block
 block discarded – undo
766 766
                 'Declined'=>'PDC'
767 767
             );
768 768
             $by_admin = $old_attendee['payment'] == 'Admin';
769
-            $STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
769
+            $STS_ID = isset($pay_status_mapping[$old_attendee['payment_status']]) ? $pay_status_mapping[$old_attendee['payment_status']] : 'PFL'; // IE, if we don't recognize the status, assume payment failed
770 770
             $cols_n_values = array(
771 771
                 'TXN_ID'=>$new_txn_id,
772 772
                 'STS_ID'=>$STS_ID,
@@ -781,19 +781,19 @@  discard block
 block discarded – undo
781 781
 
782 782
             );
783 783
             $datatypes = array(
784
-                '%d',// TXN_Id
785
-                '%s',// STS_ID
786
-                '%s',// PAY_timestamp
787
-                '%s',// PAY_method
788
-                '%f',// PAY_amount
789
-                '%s',// PAY_gateway
790
-                '%s',// PAY_gateway_response
791
-                '%s',// PAY_txn_id_chq_nmbr
792
-                '%d',// PAY_via_admin
793
-                '%s',// PAY_details
784
+                '%d', // TXN_Id
785
+                '%s', // STS_ID
786
+                '%s', // PAY_timestamp
787
+                '%s', // PAY_method
788
+                '%f', // PAY_amount
789
+                '%s', // PAY_gateway
790
+                '%s', // PAY_gateway_response
791
+                '%s', // PAY_txn_id_chq_nmbr
792
+                '%d', // PAY_via_admin
793
+                '%s', // PAY_details
794 794
             );
795 795
             $success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
796
-            if (! $success) {
796
+            if ( ! $success) {
797 797
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
798 798
                 return 0;
799 799
             }
@@ -812,7 +812,7 @@  discard block
 block discarded – undo
812 812
      */
813 813
     private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
814 814
     {
815
-        if (! $this->_mer_tables_exist()) {
815
+        if ( ! $this->_mer_tables_exist()) {
816 816
             return false;
817 817
         }
818 818
         global $wpdb;
Please login to merge, or discard this patch.
core/data_migration_scripts/EE_Data_Migration_Script_Stage_Table.core.php 2 patches
Indentation   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -16,89 +16,89 @@
 block discarded – undo
16 16
 abstract class EE_Data_Migration_Script_Stage_Table extends EE_Data_Migration_Script_Stage
17 17
 {
18 18
 
19
-    protected $_old_table;
19
+	protected $_old_table;
20 20
 
21
-    /**
22
-     * @var string The columns to select. May be overridden for children.
23
-     */
24
-    protected $select_expression = '*';
21
+	/**
22
+	 * @var string The columns to select. May be overridden for children.
23
+	 */
24
+	protected $select_expression = '*';
25 25
 
26
-    /**
27
-     * Set in the constructor to add this sql to both the counting query in
28
-     * EE_Data_Migration_Script_Stage_Table::_count_records_to_migrate() and
29
-     * EE_Data_Migration_Script_Stage_Table::_get_rows().
30
-     * Eg "where column_name like '%some_value%'"
31
-     *
32
-     * @var string
33
-     */
34
-    protected $_extra_where_sql;
26
+	/**
27
+	 * Set in the constructor to add this sql to both the counting query in
28
+	 * EE_Data_Migration_Script_Stage_Table::_count_records_to_migrate() and
29
+	 * EE_Data_Migration_Script_Stage_Table::_get_rows().
30
+	 * Eg "where column_name like '%some_value%'"
31
+	 *
32
+	 * @var string
33
+	 */
34
+	protected $_extra_where_sql;
35 35
 
36 36
 
37
-    /**
38
-     * IMPORTANT: if an error is encountered, or everything is finished, this stage should update its status property
39
-     * accordingly. Note: it should not alter the count of items migrated. That is done in the public function that
40
-     * calls this. IMPORTANT: The count of items migrated should ONLY be less than $num_items_to_migrate when it's the
41
-     * last migration step, otherwise it should always return $num_items_to_migrate. (Eg, if we're migrating attendees
42
-     * rows from the database, and $num_items_to_migrate is set to 50, then we SHOULD actually migrate 50 rows,but at
43
-     * very least we MUST report/return 50 items migrated)
44
-     *
45
-     * @param int $num_items
46
-     * @return int number of items ACTUALLY migrated
47
-     */
48
-    public function _migration_step($num_items = 50)
49
-    {
50
-        $rows = $this->_get_rows($num_items);
51
-        $items_actually_migrated = 0;
52
-        foreach ($rows as $old_row) {
53
-            $this->_migrate_old_row($old_row);
54
-            $items_actually_migrated++;
55
-        }
56
-        if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
57
-            $this->set_completed();
58
-        }
59
-        return $items_actually_migrated;
60
-    }
37
+	/**
38
+	 * IMPORTANT: if an error is encountered, or everything is finished, this stage should update its status property
39
+	 * accordingly. Note: it should not alter the count of items migrated. That is done in the public function that
40
+	 * calls this. IMPORTANT: The count of items migrated should ONLY be less than $num_items_to_migrate when it's the
41
+	 * last migration step, otherwise it should always return $num_items_to_migrate. (Eg, if we're migrating attendees
42
+	 * rows from the database, and $num_items_to_migrate is set to 50, then we SHOULD actually migrate 50 rows,but at
43
+	 * very least we MUST report/return 50 items migrated)
44
+	 *
45
+	 * @param int $num_items
46
+	 * @return int number of items ACTUALLY migrated
47
+	 */
48
+	public function _migration_step($num_items = 50)
49
+	{
50
+		$rows = $this->_get_rows($num_items);
51
+		$items_actually_migrated = 0;
52
+		foreach ($rows as $old_row) {
53
+			$this->_migrate_old_row($old_row);
54
+			$items_actually_migrated++;
55
+		}
56
+		if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
57
+			$this->set_completed();
58
+		}
59
+		return $items_actually_migrated;
60
+	}
61 61
 
62
-    /**
63
-     * Gets the rows for each migration stage from the old table
64
-     *
65
-     * @global wpdb $wpdb
66
-     * @param int   $limit
67
-     * @return array of arrays like $wpdb->get_results($sql, ARRAY_A)
68
-     */
69
-    protected function _get_rows($limit)
70
-    {
71
-        global $wpdb;
72
-        $start_at_record = $this->count_records_migrated();
73
-        $query = "SELECT {$this->select_expression} FROM {$this->_old_table} {$this->_extra_where_sql} " . $wpdb->prepare(
74
-            "LIMIT %d, %d",
75
-            $start_at_record,
76
-            $limit
77
-        );
78
-        return $wpdb->get_results($query, ARRAY_A);
79
-    }
62
+	/**
63
+	 * Gets the rows for each migration stage from the old table
64
+	 *
65
+	 * @global wpdb $wpdb
66
+	 * @param int   $limit
67
+	 * @return array of arrays like $wpdb->get_results($sql, ARRAY_A)
68
+	 */
69
+	protected function _get_rows($limit)
70
+	{
71
+		global $wpdb;
72
+		$start_at_record = $this->count_records_migrated();
73
+		$query = "SELECT {$this->select_expression} FROM {$this->_old_table} {$this->_extra_where_sql} " . $wpdb->prepare(
74
+			"LIMIT %d, %d",
75
+			$start_at_record,
76
+			$limit
77
+		);
78
+		return $wpdb->get_results($query, ARRAY_A);
79
+	}
80 80
 
81 81
 
82
-    /**
83
-     * Counts the records to migrate; the public version may cache it
84
-     *
85
-     * @return int
86
-     */
87
-    public function _count_records_to_migrate()
88
-    {
89
-        global $wpdb;
90
-        $query = "SELECT COUNT(*) FROM {$this->_old_table} {$this->_extra_where_sql}";
91
-        $count = $wpdb->get_var($query);
92
-        return $count;
93
-    }
82
+	/**
83
+	 * Counts the records to migrate; the public version may cache it
84
+	 *
85
+	 * @return int
86
+	 */
87
+	public function _count_records_to_migrate()
88
+	{
89
+		global $wpdb;
90
+		$query = "SELECT COUNT(*) FROM {$this->_old_table} {$this->_extra_where_sql}";
91
+		$count = $wpdb->get_var($query);
92
+		return $count;
93
+	}
94 94
 
95
-    /**
96
-     * takes care of migrating this particular row from the OLD table to whatever its
97
-     * representation is in the new database. If there are errors, use $this->add_error to log them. If there is a
98
-     * fatal error which prevents all future migrations, throw an exception describing it
99
-     *
100
-     * @param array $old_row an associative array where keys are column names and values are their values.
101
-     * @return null
102
-     */
103
-    abstract protected function _migrate_old_row($old_row);
95
+	/**
96
+	 * takes care of migrating this particular row from the OLD table to whatever its
97
+	 * representation is in the new database. If there are errors, use $this->add_error to log them. If there is a
98
+	 * fatal error which prevents all future migrations, throw an exception describing it
99
+	 *
100
+	 * @param array $old_row an associative array where keys are column names and values are their values.
101
+	 * @return null
102
+	 */
103
+	abstract protected function _migrate_old_row($old_row);
104 104
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@
 block discarded – undo
70 70
     {
71 71
         global $wpdb;
72 72
         $start_at_record = $this->count_records_migrated();
73
-        $query = "SELECT {$this->select_expression} FROM {$this->_old_table} {$this->_extra_where_sql} " . $wpdb->prepare(
73
+        $query = "SELECT {$this->select_expression} FROM {$this->_old_table} {$this->_extra_where_sql} ".$wpdb->prepare(
74 74
             "LIMIT %d, %d",
75 75
             $start_at_record,
76 76
             $limit
Please login to merge, or discard this patch.
core/helpers/EEH_Line_Item.helper.php 2 patches
Indentation   +2041 added lines, -2041 removed lines patch added patch discarded remove patch
@@ -21,2045 +21,2045 @@
 block discarded – undo
21 21
 class EEH_Line_Item
22 22
 {
23 23
 
24
-    /**
25
-     * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
26
-     * Does NOT automatically re-calculate the line item totals or update the related transaction.
27
-     * You should call recalculate_total_including_taxes() on the grant total line item after this
28
-     * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
29
-     * to keep the registration final prices in-sync with the transaction's total.
30
-     *
31
-     * @param EE_Line_Item $parent_line_item
32
-     * @param string       $name
33
-     * @param float        $unit_price
34
-     * @param string       $description
35
-     * @param int          $quantity
36
-     * @param boolean      $taxable
37
-     * @param boolean      $code if set to a value, ensures there is only one line item with that code
38
-     * @return boolean success
39
-     * @throws EE_Error
40
-     * @throws InvalidArgumentException
41
-     * @throws InvalidDataTypeException
42
-     * @throws InvalidInterfaceException
43
-     * @throws ReflectionException
44
-     */
45
-    public static function add_unrelated_item(
46
-        EE_Line_Item $parent_line_item,
47
-        $name,
48
-        $unit_price,
49
-        $description = '',
50
-        $quantity = 1,
51
-        $taxable = false,
52
-        $code = null
53
-    ) {
54
-        $items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
55
-        $line_item = EE_Line_Item::new_instance(array(
56
-            'LIN_name'       => $name,
57
-            'LIN_desc'       => $description,
58
-            'LIN_unit_price' => $unit_price,
59
-            'LIN_quantity'   => $quantity,
60
-            'LIN_percent'    => null,
61
-            'LIN_is_taxable' => $taxable,
62
-            'LIN_order'      => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
63
-            'LIN_total'      => (float) $unit_price * (int) $quantity,
64
-            'LIN_type'       => EEM_Line_Item::type_line_item,
65
-            'LIN_code'       => $code,
66
-        ));
67
-        $line_item = apply_filters(
68
-            'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
69
-            $line_item,
70
-            $parent_line_item
71
-        );
72
-        return self::add_item($parent_line_item, $line_item);
73
-    }
74
-
75
-
76
-    /**
77
-     * Adds a simple item ( unrelated to any other model object) to the total line item,
78
-     * in the correct spot in the line item tree. Does not automatically
79
-     * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
80
-     * registrations' final prices (which should probably change because of this).
81
-     * You should call recalculate_total_including_taxes() on the grand total line item, then
82
-     * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
83
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
84
-     *
85
-     * @param EE_Line_Item $parent_line_item
86
-     * @param string       $name
87
-     * @param float        $percentage_amount
88
-     * @param string       $description
89
-     * @param boolean      $taxable
90
-     * @return boolean success
91
-     * @throws EE_Error
92
-     */
93
-    public static function add_percentage_based_item(
94
-        EE_Line_Item $parent_line_item,
95
-        $name,
96
-        $percentage_amount,
97
-        $description = '',
98
-        $taxable = false
99
-    ) {
100
-        $line_item = EE_Line_Item::new_instance(array(
101
-            'LIN_name'       => $name,
102
-            'LIN_desc'       => $description,
103
-            'LIN_unit_price' => 0,
104
-            'LIN_percent'    => $percentage_amount,
105
-            'LIN_quantity'   => 1,
106
-            'LIN_is_taxable' => $taxable,
107
-            'LIN_total'      => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
108
-            'LIN_type'       => EEM_Line_Item::type_line_item,
109
-            'LIN_parent'     => $parent_line_item->ID(),
110
-        ));
111
-        $line_item = apply_filters(
112
-            'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
113
-            $line_item
114
-        );
115
-        return $parent_line_item->add_child_line_item($line_item, false);
116
-    }
117
-
118
-
119
-    /**
120
-     * Returns the new line item created by adding a purchase of the ticket
121
-     * ensures that ticket line item is saved, and that cart total has been recalculated.
122
-     * If this ticket has already been purchased, just increments its count.
123
-     * Automatically re-calculates the line item totals and updates the related transaction. But
124
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
125
-     * should probably change because of this).
126
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
127
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
128
-     *
129
-     * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
130
-     * @param EE_Ticket    $ticket
131
-     * @param int          $qty
132
-     * @return EE_Line_Item
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws ReflectionException
138
-     */
139
-    public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140
-    {
141
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142
-            throw new EE_Error(
143
-                sprintf(
144
-                    esc_html__(
145
-                        'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
146
-                        'event_espresso'
147
-                    ),
148
-                    $ticket->ID(),
149
-                    $total_line_item->ID()
150
-                )
151
-            );
152
-        }
153
-        // either increment the qty for an existing ticket
154
-        $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155
-        // or add a new one
156
-        if (! $line_item instanceof EE_Line_Item) {
157
-            $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158
-        }
159
-        $total_line_item->recalculate_total_including_taxes();
160
-        return $line_item;
161
-    }
162
-
163
-
164
-    /**
165
-     * Returns the new line item created by adding a purchase of the ticket
166
-     *
167
-     * @param EE_Line_Item $total_line_item
168
-     * @param EE_Ticket    $ticket
169
-     * @param int          $qty
170
-     * @return EE_Line_Item
171
-     * @throws EE_Error
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     */
177
-    public static function increment_ticket_qty_if_already_in_cart(
178
-        EE_Line_Item $total_line_item,
179
-        EE_Ticket $ticket,
180
-        $qty = 1
181
-    ) {
182
-        $line_item = null;
183
-        if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
184
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
185
-            foreach ((array) $ticket_line_items as $ticket_line_item) {
186
-                if ($ticket_line_item instanceof EE_Line_Item
187
-                    && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
188
-                ) {
189
-                    $line_item = $ticket_line_item;
190
-                    break;
191
-                }
192
-            }
193
-        }
194
-        if ($line_item instanceof EE_Line_Item) {
195
-            EEH_Line_Item::increment_quantity($line_item, $qty);
196
-            return $line_item;
197
-        }
198
-        return null;
199
-    }
200
-
201
-
202
-    /**
203
-     * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
204
-     * Does NOT save or recalculate other line items totals
205
-     *
206
-     * @param EE_Line_Item $line_item
207
-     * @param int          $qty
208
-     * @return void
209
-     * @throws EE_Error
210
-     * @throws InvalidArgumentException
211
-     * @throws InvalidDataTypeException
212
-     * @throws InvalidInterfaceException
213
-     * @throws ReflectionException
214
-     */
215
-    public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
216
-    {
217
-        if (! $line_item->is_percent()) {
218
-            $qty += $line_item->quantity();
219
-            $line_item->set_quantity($qty);
220
-            $line_item->set_total($line_item->unit_price() * $qty);
221
-            $line_item->save();
222
-        }
223
-        foreach ($line_item->children() as $child) {
224
-            if ($child->is_sub_line_item()) {
225
-                EEH_Line_Item::update_quantity($child, $qty);
226
-            }
227
-        }
228
-    }
229
-
230
-
231
-    /**
232
-     * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
233
-     * Does NOT save or recalculate other line items totals
234
-     *
235
-     * @param EE_Line_Item $line_item
236
-     * @param int          $qty
237
-     * @return void
238
-     * @throws EE_Error
239
-     * @throws InvalidArgumentException
240
-     * @throws InvalidDataTypeException
241
-     * @throws InvalidInterfaceException
242
-     * @throws ReflectionException
243
-     */
244
-    public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
245
-    {
246
-        if (! $line_item->is_percent()) {
247
-            $qty = $line_item->quantity() - $qty;
248
-            $qty = max($qty, 0);
249
-            $line_item->set_quantity($qty);
250
-            $line_item->set_total($line_item->unit_price() * $qty);
251
-            $line_item->save();
252
-        }
253
-        foreach ($line_item->children() as $child) {
254
-            if ($child->is_sub_line_item()) {
255
-                EEH_Line_Item::update_quantity($child, $qty);
256
-            }
257
-        }
258
-    }
259
-
260
-
261
-    /**
262
-     * Updates the line item and its children's quantities to the specified number.
263
-     * Does NOT save them or recalculate totals.
264
-     *
265
-     * @param EE_Line_Item $line_item
266
-     * @param int          $new_quantity
267
-     * @throws EE_Error
268
-     * @throws InvalidArgumentException
269
-     * @throws InvalidDataTypeException
270
-     * @throws InvalidInterfaceException
271
-     * @throws ReflectionException
272
-     */
273
-    public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
274
-    {
275
-        if (! $line_item->is_percent()) {
276
-            $line_item->set_quantity($new_quantity);
277
-            $line_item->set_total($line_item->unit_price() * $new_quantity);
278
-            $line_item->save();
279
-        }
280
-        foreach ($line_item->children() as $child) {
281
-            if ($child->is_sub_line_item()) {
282
-                EEH_Line_Item::update_quantity($child, $new_quantity);
283
-            }
284
-        }
285
-    }
286
-
287
-
288
-    /**
289
-     * Returns the new line item created by adding a purchase of the ticket
290
-     *
291
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
292
-     * @param EE_Ticket    $ticket
293
-     * @param int          $qty
294
-     * @return EE_Line_Item
295
-     * @throws EE_Error
296
-     * @throws InvalidArgumentException
297
-     * @throws InvalidDataTypeException
298
-     * @throws InvalidInterfaceException
299
-     * @throws ReflectionException
300
-     */
301
-    public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
302
-    {
303
-        $datetimes = $ticket->datetimes();
304
-        $first_datetime = reset($datetimes);
305
-        $first_datetime_name = esc_html__('Event', 'event_espresso');
306
-        if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
307
-            $first_datetime_name = $first_datetime->event()->name();
308
-        }
309
-        $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
310
-        // get event subtotal line
311
-        $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
312
-        // add $ticket to cart
313
-        $line_item = EE_Line_Item::new_instance(array(
314
-            'LIN_name'       => $ticket->name(),
315
-            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
316
-            'LIN_unit_price' => $ticket->price(),
317
-            'LIN_quantity'   => $qty,
318
-            'LIN_is_taxable' => $ticket->taxable(),
319
-            'LIN_order'      => count($events_sub_total->children()),
320
-            'LIN_total'      => $ticket->price() * $qty,
321
-            'LIN_type'       => EEM_Line_Item::type_line_item,
322
-            'OBJ_ID'         => $ticket->ID(),
323
-            'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
324
-        ));
325
-        $line_item = apply_filters(
326
-            'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
327
-            $line_item
328
-        );
329
-        $events_sub_total->add_child_line_item($line_item);
330
-        // now add the sub-line items
331
-        $running_total_for_ticket = 0;
332
-        foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
333
-            $sign = $price->is_discount() ? -1 : 1;
334
-            $price_total = $price->is_percent()
335
-                ? $running_total_for_ticket * $price->amount() / 100
336
-                : $price->amount() * $qty;
337
-            $sub_line_item = EE_Line_Item::new_instance(array(
338
-                'LIN_name'       => $price->name(),
339
-                'LIN_desc'       => $price->desc(),
340
-                'LIN_quantity'   => $price->is_percent() ? null : $qty,
341
-                'LIN_is_taxable' => false,
342
-                'LIN_order'      => $price->order(),
343
-                'LIN_total'      => $sign * $price_total,
344
-                'LIN_type'       => EEM_Line_Item::type_sub_line_item,
345
-                'OBJ_ID'         => $price->ID(),
346
-                'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
347
-            ));
348
-            $sub_line_item = apply_filters(
349
-                'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
350
-                $sub_line_item
351
-            );
352
-            if ($price->is_percent()) {
353
-                $sub_line_item->set_percent($sign * $price->amount());
354
-            } else {
355
-                $sub_line_item->set_unit_price($sign * $price->amount());
356
-            }
357
-            $running_total_for_ticket += $price_total;
358
-            $line_item->add_child_line_item($sub_line_item);
359
-        }
360
-        return $line_item;
361
-    }
362
-
363
-
364
-    /**
365
-     * Adds the specified item under the pre-tax-sub-total line item. Automatically
366
-     * re-calculates the line item totals and updates the related transaction. But
367
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
368
-     * should probably change because of this).
369
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
370
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
371
-     *
372
-     * @param EE_Line_Item $total_line_item
373
-     * @param EE_Line_Item $item to be added
374
-     * @return boolean
375
-     * @throws EE_Error
376
-     * @throws InvalidArgumentException
377
-     * @throws InvalidDataTypeException
378
-     * @throws InvalidInterfaceException
379
-     * @throws ReflectionException
380
-     */
381
-    public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
382
-    {
383
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
384
-        if ($pre_tax_subtotal instanceof EE_Line_Item) {
385
-            $success = $pre_tax_subtotal->add_child_line_item($item);
386
-        } else {
387
-            return false;
388
-        }
389
-        $total_line_item->recalculate_total_including_taxes();
390
-        return $success;
391
-    }
392
-
393
-
394
-    /**
395
-     * cancels an existing ticket line item,
396
-     * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
397
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
398
-     *
399
-     * @param EE_Line_Item $ticket_line_item
400
-     * @param int          $qty
401
-     * @return bool success
402
-     * @throws EE_Error
403
-     * @throws InvalidArgumentException
404
-     * @throws InvalidDataTypeException
405
-     * @throws InvalidInterfaceException
406
-     * @throws ReflectionException
407
-     */
408
-    public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
409
-    {
410
-        // validate incoming line_item
411
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
412
-            throw new EE_Error(
413
-                sprintf(
414
-                    esc_html__(
415
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
416
-                        'event_espresso'
417
-                    ),
418
-                    $ticket_line_item->type()
419
-                )
420
-            );
421
-        }
422
-        if ($ticket_line_item->quantity() < $qty) {
423
-            throw new EE_Error(
424
-                sprintf(
425
-                    esc_html__(
426
-                        'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
427
-                        'event_espresso'
428
-                    ),
429
-                    $qty,
430
-                    $ticket_line_item->quantity()
431
-                )
432
-            );
433
-        }
434
-        // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
435
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
436
-        foreach ($ticket_line_item->children() as $child_line_item) {
437
-            if ($child_line_item->is_sub_line_item()
438
-                && ! $child_line_item->is_percent()
439
-                && ! $child_line_item->is_cancellation()
440
-            ) {
441
-                $child_line_item->set_quantity($child_line_item->quantity() - $qty);
442
-            }
443
-        }
444
-        // get cancellation sub line item
445
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
446
-            $ticket_line_item,
447
-            EEM_Line_Item::type_cancellation
448
-        );
449
-        $cancellation_line_item = reset($cancellation_line_item);
450
-        // verify that this ticket was indeed previously cancelled
451
-        if ($cancellation_line_item instanceof EE_Line_Item) {
452
-            // increment cancelled quantity
453
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
454
-        } else {
455
-            // create cancellation sub line item
456
-            $cancellation_line_item = EE_Line_Item::new_instance(array(
457
-                'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
458
-                'LIN_desc'       => sprintf(
459
-                    esc_html_x(
460
-                        'Cancelled %1$s : %2$s',
461
-                        'Cancelled Ticket Name : 2015-01-01 11:11',
462
-                        'event_espresso'
463
-                    ),
464
-                    $ticket_line_item->name(),
465
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
466
-                ),
467
-                'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
468
-                'LIN_quantity'   => $qty,
469
-                'LIN_is_taxable' => $ticket_line_item->is_taxable(),
470
-                'LIN_order'      => count($ticket_line_item->children()),
471
-                'LIN_total'      => 0, // $ticket_line_item->unit_price()
472
-                'LIN_type'       => EEM_Line_Item::type_cancellation,
473
-            ));
474
-            $ticket_line_item->add_child_line_item($cancellation_line_item);
475
-        }
476
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
477
-            // decrement parent line item quantity
478
-            $event_line_item = $ticket_line_item->parent();
479
-            if ($event_line_item instanceof EE_Line_Item
480
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
481
-            ) {
482
-                $event_line_item->set_quantity($event_line_item->quantity() - $qty);
483
-                $event_line_item->save();
484
-            }
485
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
486
-            return true;
487
-        }
488
-        return false;
489
-    }
490
-
491
-
492
-    /**
493
-     * reinstates (un-cancels?) a previously canceled ticket line item,
494
-     * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
495
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
496
-     *
497
-     * @param EE_Line_Item $ticket_line_item
498
-     * @param int          $qty
499
-     * @return bool success
500
-     * @throws EE_Error
501
-     * @throws InvalidArgumentException
502
-     * @throws InvalidDataTypeException
503
-     * @throws InvalidInterfaceException
504
-     * @throws ReflectionException
505
-     */
506
-    public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
507
-    {
508
-        // validate incoming line_item
509
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
510
-            throw new EE_Error(
511
-                sprintf(
512
-                    esc_html__(
513
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
514
-                        'event_espresso'
515
-                    ),
516
-                    $ticket_line_item->type()
517
-                )
518
-            );
519
-        }
520
-        // get cancellation sub line item
521
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
522
-            $ticket_line_item,
523
-            EEM_Line_Item::type_cancellation
524
-        );
525
-        $cancellation_line_item = reset($cancellation_line_item);
526
-        // verify that this ticket was indeed previously cancelled
527
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
528
-            return false;
529
-        }
530
-        if ($cancellation_line_item->quantity() > $qty) {
531
-            // decrement cancelled quantity
532
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
533
-        } elseif ($cancellation_line_item->quantity() === $qty) {
534
-            // decrement cancelled quantity in case anyone still has the object kicking around
535
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
536
-            // delete because quantity will end up as 0
537
-            $cancellation_line_item->delete();
538
-            // and attempt to destroy the object,
539
-            // even though PHP won't actually destroy it until it needs the memory
540
-            unset($cancellation_line_item);
541
-        } else {
542
-            // what ?!?! negative quantity ?!?!
543
-            throw new EE_Error(
544
-                sprintf(
545
-                    esc_html__(
546
-                        'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
547
-                        'event_espresso'
548
-                    ),
549
-                    $qty,
550
-                    $cancellation_line_item->quantity()
551
-                )
552
-            );
553
-        }
554
-        // increment ticket quantity
555
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
556
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
557
-            // increment parent line item quantity
558
-            $event_line_item = $ticket_line_item->parent();
559
-            if ($event_line_item instanceof EE_Line_Item
560
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
561
-            ) {
562
-                $event_line_item->set_quantity($event_line_item->quantity() + $qty);
563
-            }
564
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
565
-            return true;
566
-        }
567
-        return false;
568
-    }
569
-
570
-
571
-    /**
572
-     * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
573
-     * then EE_Line_Item::recalculate_total_including_taxes() on the result
574
-     *
575
-     * @param EE_Line_Item $line_item
576
-     * @return float
577
-     * @throws EE_Error
578
-     * @throws InvalidArgumentException
579
-     * @throws InvalidDataTypeException
580
-     * @throws InvalidInterfaceException
581
-     * @throws ReflectionException
582
-     */
583
-    public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
584
-    {
585
-        $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
586
-        return $grand_total_line_item->recalculate_total_including_taxes();
587
-    }
588
-
589
-
590
-    /**
591
-     * Gets the line item which contains the subtotal of all the items
592
-     *
593
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
594
-     * @return EE_Line_Item
595
-     * @throws EE_Error
596
-     * @throws InvalidArgumentException
597
-     * @throws InvalidDataTypeException
598
-     * @throws InvalidInterfaceException
599
-     * @throws ReflectionException
600
-     */
601
-    public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
602
-    {
603
-        $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
604
-        return $pre_tax_subtotal instanceof EE_Line_Item
605
-            ? $pre_tax_subtotal
606
-            : self::create_pre_tax_subtotal($total_line_item);
607
-    }
608
-
609
-
610
-    /**
611
-     * Gets the line item for the taxes subtotal
612
-     *
613
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
614
-     * @return EE_Line_Item
615
-     * @throws EE_Error
616
-     * @throws InvalidArgumentException
617
-     * @throws InvalidDataTypeException
618
-     * @throws InvalidInterfaceException
619
-     * @throws ReflectionException
620
-     */
621
-    public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
622
-    {
623
-        $taxes = $total_line_item->get_child_line_item('taxes');
624
-        return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
625
-    }
626
-
627
-
628
-    /**
629
-     * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
630
-     *
631
-     * @param EE_Line_Item   $line_item
632
-     * @param EE_Transaction $transaction
633
-     * @return void
634
-     * @throws EE_Error
635
-     * @throws InvalidArgumentException
636
-     * @throws InvalidDataTypeException
637
-     * @throws InvalidInterfaceException
638
-     * @throws ReflectionException
639
-     */
640
-    public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
641
-    {
642
-        if ($transaction) {
643
-            /** @type EEM_Transaction $EEM_Transaction */
644
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
645
-            $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
646
-            $line_item->set_TXN_ID($TXN_ID);
647
-        }
648
-    }
649
-
650
-
651
-    /**
652
-     * Creates a new default total line item for the transaction,
653
-     * and its tickets subtotal and taxes subtotal line items (and adds the
654
-     * existing taxes as children of the taxes subtotal line item)
655
-     *
656
-     * @param EE_Transaction $transaction
657
-     * @return EE_Line_Item of type total
658
-     * @throws EE_Error
659
-     * @throws InvalidArgumentException
660
-     * @throws InvalidDataTypeException
661
-     * @throws InvalidInterfaceException
662
-     * @throws ReflectionException
663
-     */
664
-    public static function create_total_line_item($transaction = null)
665
-    {
666
-        $total_line_item = EE_Line_Item::new_instance(array(
667
-            'LIN_code' => 'total',
668
-            'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
669
-            'LIN_type' => EEM_Line_Item::type_total,
670
-            'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
671
-        ));
672
-        $total_line_item = apply_filters(
673
-            'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
674
-            $total_line_item
675
-        );
676
-        self::set_TXN_ID($total_line_item, $transaction);
677
-        self::create_pre_tax_subtotal($total_line_item, $transaction);
678
-        self::create_taxes_subtotal($total_line_item, $transaction);
679
-        return $total_line_item;
680
-    }
681
-
682
-
683
-    /**
684
-     * Creates a default items subtotal line item
685
-     *
686
-     * @param EE_Line_Item   $total_line_item
687
-     * @param EE_Transaction $transaction
688
-     * @return EE_Line_Item
689
-     * @throws EE_Error
690
-     * @throws InvalidArgumentException
691
-     * @throws InvalidDataTypeException
692
-     * @throws InvalidInterfaceException
693
-     * @throws ReflectionException
694
-     */
695
-    protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
696
-    {
697
-        $pre_tax_line_item = EE_Line_Item::new_instance(array(
698
-            'LIN_code' => 'pre-tax-subtotal',
699
-            'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
700
-            'LIN_type' => EEM_Line_Item::type_sub_total,
701
-        ));
702
-        $pre_tax_line_item = apply_filters(
703
-            'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
704
-            $pre_tax_line_item
705
-        );
706
-        self::set_TXN_ID($pre_tax_line_item, $transaction);
707
-        $total_line_item->add_child_line_item($pre_tax_line_item);
708
-        self::create_event_subtotal($pre_tax_line_item, $transaction);
709
-        return $pre_tax_line_item;
710
-    }
711
-
712
-
713
-    /**
714
-     * Creates a line item for the taxes subtotal and finds all the tax prices
715
-     * and applies taxes to it
716
-     *
717
-     * @param EE_Line_Item   $total_line_item of type EEM_Line_Item::type_total
718
-     * @param EE_Transaction $transaction
719
-     * @return EE_Line_Item
720
-     * @throws EE_Error
721
-     * @throws InvalidArgumentException
722
-     * @throws InvalidDataTypeException
723
-     * @throws InvalidInterfaceException
724
-     * @throws ReflectionException
725
-     */
726
-    protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
727
-    {
728
-        $tax_line_item = EE_Line_Item::new_instance(array(
729
-            'LIN_code'  => 'taxes',
730
-            'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
731
-            'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
732
-            'LIN_order' => 1000,// this should always come last
733
-        ));
734
-        $tax_line_item = apply_filters(
735
-            'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
736
-            $tax_line_item
737
-        );
738
-        self::set_TXN_ID($tax_line_item, $transaction);
739
-        $total_line_item->add_child_line_item($tax_line_item);
740
-        // and lastly, add the actual taxes
741
-        self::apply_taxes($total_line_item);
742
-        return $tax_line_item;
743
-    }
744
-
745
-
746
-    /**
747
-     * Creates a default items subtotal line item
748
-     *
749
-     * @param EE_Line_Item   $pre_tax_line_item
750
-     * @param EE_Transaction $transaction
751
-     * @param EE_Event       $event
752
-     * @return EE_Line_Item
753
-     * @throws EE_Error
754
-     * @throws InvalidArgumentException
755
-     * @throws InvalidDataTypeException
756
-     * @throws InvalidInterfaceException
757
-     * @throws ReflectionException
758
-     */
759
-    public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
760
-    {
761
-        $event_line_item = EE_Line_Item::new_instance(array(
762
-            'LIN_code' => self::get_event_code($event),
763
-            'LIN_name' => self::get_event_name($event),
764
-            'LIN_desc' => self::get_event_desc($event),
765
-            'LIN_type' => EEM_Line_Item::type_sub_total,
766
-            'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
767
-            'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
768
-        ));
769
-        $event_line_item = apply_filters(
770
-            'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
771
-            $event_line_item
772
-        );
773
-        self::set_TXN_ID($event_line_item, $transaction);
774
-        $pre_tax_line_item->add_child_line_item($event_line_item);
775
-        return $event_line_item;
776
-    }
777
-
778
-
779
-    /**
780
-     * Gets what the event ticket's code SHOULD be
781
-     *
782
-     * @param EE_Event $event
783
-     * @return string
784
-     * @throws EE_Error
785
-     */
786
-    public static function get_event_code($event)
787
-    {
788
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
789
-    }
790
-
791
-
792
-    /**
793
-     * Gets the event name
794
-     *
795
-     * @param EE_Event $event
796
-     * @return string
797
-     * @throws EE_Error
798
-     */
799
-    public static function get_event_name($event)
800
-    {
801
-        return $event instanceof EE_Event
802
-            ? mb_substr($event->name(), 0, 245)
803
-            : esc_html__('Event', 'event_espresso');
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets the event excerpt
809
-     *
810
-     * @param EE_Event $event
811
-     * @return string
812
-     * @throws EE_Error
813
-     */
814
-    public static function get_event_desc($event)
815
-    {
816
-        return $event instanceof EE_Event ? $event->short_description() : '';
817
-    }
818
-
819
-
820
-    /**
821
-     * Given the grand total line item and a ticket, finds the event sub-total
822
-     * line item the ticket's purchase should be added onto
823
-     *
824
-     * @access public
825
-     * @param EE_Line_Item $grand_total the grand total line item
826
-     * @param EE_Ticket    $ticket
827
-     * @return EE_Line_Item
828
-     * @throws EE_Error
829
-     * @throws InvalidArgumentException
830
-     * @throws InvalidDataTypeException
831
-     * @throws InvalidInterfaceException
832
-     * @throws ReflectionException
833
-     */
834
-    public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
835
-    {
836
-        $first_datetime = $ticket->first_datetime();
837
-        if (! $first_datetime instanceof EE_Datetime) {
838
-            throw new EE_Error(
839
-                sprintf(
840
-                    __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
841
-                    $ticket->ID()
842
-                )
843
-            );
844
-        }
845
-        $event = $first_datetime->event();
846
-        if (! $event instanceof EE_Event) {
847
-            throw new EE_Error(
848
-                sprintf(
849
-                    esc_html__(
850
-                        'The supplied ticket (ID %d) has no event data associated with it.',
851
-                        'event_espresso'
852
-                    ),
853
-                    $ticket->ID()
854
-                )
855
-            );
856
-        }
857
-        $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
858
-        if (! $events_sub_total instanceof EE_Line_Item) {
859
-            throw new EE_Error(
860
-                sprintf(
861
-                    esc_html__(
862
-                        'There is no events sub-total for ticket %s on total line item %d',
863
-                        'event_espresso'
864
-                    ),
865
-                    $ticket->ID(),
866
-                    $grand_total->ID()
867
-                )
868
-            );
869
-        }
870
-        return $events_sub_total;
871
-    }
872
-
873
-
874
-    /**
875
-     * Gets the event line item
876
-     *
877
-     * @param EE_Line_Item $grand_total
878
-     * @param EE_Event     $event
879
-     * @return EE_Line_Item for the event subtotal which is a child of $grand_total
880
-     * @throws EE_Error
881
-     * @throws InvalidArgumentException
882
-     * @throws InvalidDataTypeException
883
-     * @throws InvalidInterfaceException
884
-     * @throws ReflectionException
885
-     */
886
-    public static function get_event_line_item(EE_Line_Item $grand_total, $event)
887
-    {
888
-        /** @type EE_Event $event */
889
-        $event = EEM_Event::instance()->ensure_is_obj($event, true);
890
-        $event_line_item = null;
891
-        $found = false;
892
-        foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
893
-            // default event subtotal, we should only ever find this the first time this method is called
894
-            if (! $event_line_item->OBJ_ID()) {
895
-                // let's use this! but first... set the event details
896
-                EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
897
-                $found = true;
898
-                break;
899
-            }
900
-            if ($event_line_item->OBJ_ID() === $event->ID()) {
901
-                // found existing line item for this event in the cart, so break out of loop and use this one
902
-                $found = true;
903
-                break;
904
-            }
905
-        }
906
-        if (! $found) {
907
-            // there is no event sub-total yet, so add it
908
-            $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
909
-            // create a new "event" subtotal below that
910
-            $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
911
-            // and set the event details
912
-            EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
913
-        }
914
-        return $event_line_item;
915
-    }
916
-
917
-
918
-    /**
919
-     * Creates a default items subtotal line item
920
-     *
921
-     * @param EE_Line_Item   $event_line_item
922
-     * @param EE_Event       $event
923
-     * @param EE_Transaction $transaction
924
-     * @return void
925
-     * @throws EE_Error
926
-     * @throws InvalidArgumentException
927
-     * @throws InvalidDataTypeException
928
-     * @throws InvalidInterfaceException
929
-     * @throws ReflectionException
930
-     */
931
-    public static function set_event_subtotal_details(
932
-        EE_Line_Item $event_line_item,
933
-        EE_Event $event,
934
-        $transaction = null
935
-    ) {
936
-        if ($event instanceof EE_Event) {
937
-            $event_line_item->set_code(self::get_event_code($event));
938
-            $event_line_item->set_name(self::get_event_name($event));
939
-            $event_line_item->set_desc(self::get_event_desc($event));
940
-            $event_line_item->set_OBJ_ID($event->ID());
941
-        }
942
-        self::set_TXN_ID($event_line_item, $transaction);
943
-    }
944
-
945
-
946
-    /**
947
-     * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
948
-     * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
949
-     * any old taxes are removed
950
-     *
951
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
952
-     * @param bool         $update_txn_status
953
-     * @return bool
954
-     * @throws EE_Error
955
-     * @throws InvalidArgumentException
956
-     * @throws InvalidDataTypeException
957
-     * @throws InvalidInterfaceException
958
-     * @throws ReflectionException
959
-     * @throws RuntimeException
960
-     */
961
-    public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false)
962
-    {
963
-        /** @type EEM_Price $EEM_Price */
964
-        $EEM_Price = EE_Registry::instance()->load_model('Price');
965
-        // get array of taxes via Price Model
966
-        $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
967
-        ksort($ordered_taxes);
968
-        $taxes_line_item = self::get_taxes_subtotal($total_line_item);
969
-        // just to be safe, remove its old tax line items
970
-        $deleted = $taxes_line_item->delete_children_line_items();
971
-        $updates = false;
972
-        // loop thru taxes
973
-        foreach ($ordered_taxes as $order => $taxes) {
974
-            foreach ($taxes as $tax) {
975
-                if ($tax instanceof EE_Price) {
976
-                    $tax_line_item = EE_Line_Item::new_instance(
977
-                        array(
978
-                            'LIN_name'       => $tax->name(),
979
-                            'LIN_desc'       => $tax->desc(),
980
-                            'LIN_percent'    => $tax->amount(),
981
-                            'LIN_is_taxable' => false,
982
-                            'LIN_order'      => $order,
983
-                            'LIN_total'      => 0,
984
-                            'LIN_type'       => EEM_Line_Item::type_tax,
985
-                            'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
986
-                            'OBJ_ID'         => $tax->ID(),
987
-                        )
988
-                    );
989
-                    $tax_line_item = apply_filters(
990
-                        'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
991
-                        $tax_line_item
992
-                    );
993
-                    $updates = $taxes_line_item->add_child_line_item($tax_line_item) ?
994
-                        true :
995
-                        $updates;
996
-                }
997
-            }
998
-        }
999
-        // only recalculate totals if something changed
1000
-        if ($deleted || $updates) {
1001
-            $total_line_item->recalculate_total_including_taxes($update_txn_status);
1002
-            return true;
1003
-        }
1004
-        return false;
1005
-    }
1006
-
1007
-
1008
-    /**
1009
-     * Ensures that taxes have been applied to the order, if not applies them.
1010
-     * Returns the total amount of tax
1011
-     *
1012
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1013
-     * @return float
1014
-     * @throws EE_Error
1015
-     * @throws InvalidArgumentException
1016
-     * @throws InvalidDataTypeException
1017
-     * @throws InvalidInterfaceException
1018
-     * @throws ReflectionException
1019
-     */
1020
-    public static function ensure_taxes_applied($total_line_item)
1021
-    {
1022
-        $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1023
-        if (! $taxes_subtotal->children()) {
1024
-            self::apply_taxes($total_line_item);
1025
-        }
1026
-        return $taxes_subtotal->total();
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * Deletes ALL children of the passed line item
1032
-     *
1033
-     * @param EE_Line_Item $parent_line_item
1034
-     * @return bool
1035
-     * @throws EE_Error
1036
-     * @throws InvalidArgumentException
1037
-     * @throws InvalidDataTypeException
1038
-     * @throws InvalidInterfaceException
1039
-     * @throws ReflectionException
1040
-     */
1041
-    public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1042
-    {
1043
-        $deleted = 0;
1044
-        foreach ($parent_line_item->children() as $child_line_item) {
1045
-            if ($child_line_item instanceof EE_Line_Item) {
1046
-                $deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1047
-                if ($child_line_item->ID()) {
1048
-                    $child_line_item->delete();
1049
-                    unset($child_line_item);
1050
-                } else {
1051
-                    $parent_line_item->delete_child_line_item($child_line_item->code());
1052
-                }
1053
-                $deleted++;
1054
-            }
1055
-        }
1056
-        return $deleted;
1057
-    }
1058
-
1059
-
1060
-    /**
1061
-     * Deletes the line items as indicated by the line item code(s) provided,
1062
-     * regardless of where they're found in the line item tree. Automatically
1063
-     * re-calculates the line item totals and updates the related transaction. But
1064
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1065
-     * should probably change because of this).
1066
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1067
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
1068
-     *
1069
-     * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1070
-     * @param array|bool|string $line_item_codes
1071
-     * @return int number of items successfully removed
1072
-     * @throws EE_Error
1073
-     */
1074
-    public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1075
-    {
1076
-
1077
-        if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1078
-            EE_Error::doing_it_wrong(
1079
-                'EEH_Line_Item::delete_items',
1080
-                esc_html__(
1081
-                    'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1082
-                    'event_espresso'
1083
-                ),
1084
-                '4.6.18'
1085
-            );
1086
-        }
1087
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1088
-
1089
-        // check if only a single line_item_id was passed
1090
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1091
-            // place single line_item_id in an array to appear as multiple line_item_ids
1092
-            $line_item_codes = array($line_item_codes);
1093
-        }
1094
-        $removals = 0;
1095
-        // cycle thru line_item_ids
1096
-        foreach ($line_item_codes as $line_item_id) {
1097
-            $removals += $total_line_item->delete_child_line_item($line_item_id);
1098
-        }
1099
-
1100
-        if ($removals > 0) {
1101
-            $total_line_item->recalculate_taxes_and_tax_total();
1102
-            return $removals;
1103
-        } else {
1104
-            return false;
1105
-        }
1106
-    }
1107
-
1108
-
1109
-    /**
1110
-     * Overwrites the previous tax by clearing out the old taxes, and creates a new
1111
-     * tax and updates the total line item accordingly
1112
-     *
1113
-     * @param EE_Line_Item $total_line_item
1114
-     * @param float        $amount
1115
-     * @param string       $name
1116
-     * @param string       $description
1117
-     * @param string       $code
1118
-     * @param boolean      $add_to_existing_line_item
1119
-     *                          if true, and a duplicate line item with the same code is found,
1120
-     *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1121
-     * @return EE_Line_Item the new tax line item created
1122
-     * @throws EE_Error
1123
-     * @throws InvalidArgumentException
1124
-     * @throws InvalidDataTypeException
1125
-     * @throws InvalidInterfaceException
1126
-     * @throws ReflectionException
1127
-     */
1128
-    public static function set_total_tax_to(
1129
-        EE_Line_Item $total_line_item,
1130
-        $amount,
1131
-        $name = null,
1132
-        $description = null,
1133
-        $code = null,
1134
-        $add_to_existing_line_item = false
1135
-    ) {
1136
-        $tax_subtotal = self::get_taxes_subtotal($total_line_item);
1137
-        $taxable_total = $total_line_item->taxable_total();
1138
-
1139
-        if ($add_to_existing_line_item) {
1140
-            $new_tax = $tax_subtotal->get_child_line_item($code);
1141
-            EEM_Line_Item::instance()->delete(
1142
-                array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
1143
-            );
1144
-        } else {
1145
-            $new_tax = null;
1146
-            $tax_subtotal->delete_children_line_items();
1147
-        }
1148
-        if ($new_tax) {
1149
-            $new_tax->set_total($new_tax->total() + $amount);
1150
-            $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1151
-        } else {
1152
-            // no existing tax item. Create it
1153
-            $new_tax = EE_Line_Item::new_instance(array(
1154
-                'TXN_ID'      => $total_line_item->TXN_ID(),
1155
-                'LIN_name'    => $name ? $name : esc_html__('Tax', 'event_espresso'),
1156
-                'LIN_desc'    => $description ? $description : '',
1157
-                'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1158
-                'LIN_total'   => $amount,
1159
-                'LIN_parent'  => $tax_subtotal->ID(),
1160
-                'LIN_type'    => EEM_Line_Item::type_tax,
1161
-                'LIN_code'    => $code,
1162
-            ));
1163
-        }
1164
-
1165
-        $new_tax = apply_filters(
1166
-            'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1167
-            $new_tax,
1168
-            $total_line_item
1169
-        );
1170
-        $new_tax->save();
1171
-        $tax_subtotal->set_total($new_tax->total());
1172
-        $tax_subtotal->save();
1173
-        $total_line_item->recalculate_total_including_taxes();
1174
-        return $new_tax;
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Makes all the line items which are children of $line_item taxable (or not).
1180
-     * Does NOT save the line items
1181
-     *
1182
-     * @param EE_Line_Item $line_item
1183
-     * @param boolean      $taxable
1184
-     * @param string       $code_substring_for_whitelist if this string is part of the line item's code
1185
-     *                                                   it will be whitelisted (ie, except from becoming taxable)
1186
-     * @throws EE_Error
1187
-     */
1188
-    public static function set_line_items_taxable(
1189
-        EE_Line_Item $line_item,
1190
-        $taxable = true,
1191
-        $code_substring_for_whitelist = null
1192
-    ) {
1193
-        $whitelisted = false;
1194
-        if ($code_substring_for_whitelist !== null) {
1195
-            $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1196
-        }
1197
-        if (! $whitelisted && $line_item->is_line_item()) {
1198
-            $line_item->set_is_taxable($taxable);
1199
-        }
1200
-        foreach ($line_item->children() as $child_line_item) {
1201
-            EEH_Line_Item::set_line_items_taxable(
1202
-                $child_line_item,
1203
-                $taxable,
1204
-                $code_substring_for_whitelist
1205
-            );
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Gets all descendants that are event subtotals
1212
-     *
1213
-     * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1214
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1215
-     * @return EE_Line_Item[]
1216
-     * @throws EE_Error
1217
-     */
1218
-    public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1219
-    {
1220
-        return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * Gets all descendants subtotals that match the supplied object type
1226
-     *
1227
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1228
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1229
-     * @param string       $obj_type
1230
-     * @return EE_Line_Item[]
1231
-     * @throws EE_Error
1232
-     */
1233
-    public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1234
-    {
1235
-        return self::_get_descendants_by_type_and_object_type(
1236
-            $parent_line_item,
1237
-            EEM_Line_Item::type_sub_total,
1238
-            $obj_type
1239
-        );
1240
-    }
1241
-
1242
-
1243
-    /**
1244
-     * Gets all descendants that are tickets
1245
-     *
1246
-     * @uses  EEH_Line_Item::get_line_items_of_object_type()
1247
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1248
-     * @return EE_Line_Item[]
1249
-     * @throws EE_Error
1250
-     */
1251
-    public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1252
-    {
1253
-        return self::get_line_items_of_object_type(
1254
-            $parent_line_item,
1255
-            EEM_Line_Item::OBJ_TYPE_TICKET
1256
-        );
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * Gets all descendants subtotals that match the supplied object type
1262
-     *
1263
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1264
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1265
-     * @param string       $obj_type
1266
-     * @return EE_Line_Item[]
1267
-     * @throws EE_Error
1268
-     */
1269
-    public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1270
-    {
1271
-        return self::_get_descendants_by_type_and_object_type(
1272
-            $parent_line_item,
1273
-            EEM_Line_Item::type_line_item,
1274
-            $obj_type
1275
-        );
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1281
-     *
1282
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1283
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1284
-     * @return EE_Line_Item[]
1285
-     * @throws EE_Error
1286
-     */
1287
-    public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1288
-    {
1289
-        return EEH_Line_Item::get_descendants_of_type(
1290
-            $parent_line_item,
1291
-            EEM_Line_Item::type_tax
1292
-        );
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Gets all the real items purchased which are children of this item
1298
-     *
1299
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1300
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1301
-     * @return EE_Line_Item[]
1302
-     * @throws EE_Error
1303
-     */
1304
-    public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1305
-    {
1306
-        return EEH_Line_Item::get_descendants_of_type(
1307
-            $parent_line_item,
1308
-            EEM_Line_Item::type_line_item
1309
-        );
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * Gets all descendants of supplied line item that match the supplied line item type
1315
-     *
1316
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1317
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1318
-     * @param string       $line_item_type   one of the EEM_Line_Item constants
1319
-     * @return EE_Line_Item[]
1320
-     * @throws EE_Error
1321
-     */
1322
-    public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1323
-    {
1324
-        return self::_get_descendants_by_type_and_object_type(
1325
-            $parent_line_item,
1326
-            $line_item_type,
1327
-            null
1328
-        );
1329
-    }
1330
-
1331
-
1332
-    /**
1333
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1334
-     * as well
1335
-     *
1336
-     * @param EE_Line_Item  $parent_line_item - the line item to find descendants of
1337
-     * @param string        $line_item_type   one of the EEM_Line_Item constants
1338
-     * @param string | NULL $obj_type         object model class name (minus prefix) or NULL to ignore object type when
1339
-     *                                        searching
1340
-     * @return EE_Line_Item[]
1341
-     * @throws EE_Error
1342
-     */
1343
-    protected static function _get_descendants_by_type_and_object_type(
1344
-        EE_Line_Item $parent_line_item,
1345
-        $line_item_type,
1346
-        $obj_type = null
1347
-    ) {
1348
-        $objects = array();
1349
-        foreach ($parent_line_item->children() as $child_line_item) {
1350
-            if ($child_line_item instanceof EE_Line_Item) {
1351
-                if ($child_line_item->type() === $line_item_type
1352
-                    && (
1353
-                        $child_line_item->OBJ_type() === $obj_type || $obj_type === null
1354
-                    )
1355
-                ) {
1356
-                    $objects[] = $child_line_item;
1357
-                } else {
1358
-                    // go-through-all-its children looking for more matches
1359
-                    $objects = array_merge(
1360
-                        $objects,
1361
-                        self::_get_descendants_by_type_and_object_type(
1362
-                            $child_line_item,
1363
-                            $line_item_type,
1364
-                            $obj_type
1365
-                        )
1366
-                    );
1367
-                }
1368
-            }
1369
-        }
1370
-        return $objects;
1371
-    }
1372
-
1373
-
1374
-    /**
1375
-     * Gets all descendants subtotals that match the supplied object type
1376
-     *
1377
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1378
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1379
-     * @param string       $OBJ_type         object type (like Event)
1380
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1381
-     * @return EE_Line_Item[]
1382
-     * @throws EE_Error
1383
-     */
1384
-    public static function get_line_items_by_object_type_and_IDs(
1385
-        EE_Line_Item $parent_line_item,
1386
-        $OBJ_type = '',
1387
-        $OBJ_IDs = array()
1388
-    ) {
1389
-        return self::_get_descendants_by_object_type_and_object_ID(
1390
-            $parent_line_item,
1391
-            $OBJ_type,
1392
-            $OBJ_IDs
1393
-        );
1394
-    }
1395
-
1396
-
1397
-    /**
1398
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1399
-     * as well
1400
-     *
1401
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1402
-     * @param string       $OBJ_type         object type (like Event)
1403
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1404
-     * @return EE_Line_Item[]
1405
-     * @throws EE_Error
1406
-     */
1407
-    protected static function _get_descendants_by_object_type_and_object_ID(
1408
-        EE_Line_Item $parent_line_item,
1409
-        $OBJ_type,
1410
-        $OBJ_IDs
1411
-    ) {
1412
-        $objects = array();
1413
-        foreach ($parent_line_item->children() as $child_line_item) {
1414
-            if ($child_line_item instanceof EE_Line_Item) {
1415
-                if ($child_line_item->OBJ_type() === $OBJ_type
1416
-                    && is_array($OBJ_IDs)
1417
-                    && in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1418
-                ) {
1419
-                    $objects[] = $child_line_item;
1420
-                } else {
1421
-                    // go-through-all-its children looking for more matches
1422
-                    $objects = array_merge(
1423
-                        $objects,
1424
-                        self::_get_descendants_by_object_type_and_object_ID(
1425
-                            $child_line_item,
1426
-                            $OBJ_type,
1427
-                            $OBJ_IDs
1428
-                        )
1429
-                    );
1430
-                }
1431
-            }
1432
-        }
1433
-        return $objects;
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * Uses a breadth-first-search in order to find the nearest descendant of
1439
-     * the specified type and returns it, else NULL
1440
-     *
1441
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1442
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1443
-     * @param string       $type             like one of the EEM_Line_Item::type_*
1444
-     * @return EE_Line_Item
1445
-     * @throws EE_Error
1446
-     * @throws InvalidArgumentException
1447
-     * @throws InvalidDataTypeException
1448
-     * @throws InvalidInterfaceException
1449
-     * @throws ReflectionException
1450
-     */
1451
-    public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1452
-    {
1453
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1454
-    }
1455
-
1456
-
1457
-    /**
1458
-     * Uses a breadth-first-search in order to find the nearest descendant
1459
-     * having the specified LIN_code and returns it, else NULL
1460
-     *
1461
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1462
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1463
-     * @param string       $code             any value used for LIN_code
1464
-     * @return EE_Line_Item
1465
-     * @throws EE_Error
1466
-     * @throws InvalidArgumentException
1467
-     * @throws InvalidDataTypeException
1468
-     * @throws InvalidInterfaceException
1469
-     * @throws ReflectionException
1470
-     */
1471
-    public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1472
-    {
1473
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1474
-    }
1475
-
1476
-
1477
-    /**
1478
-     * Uses a breadth-first-search in order to find the nearest descendant
1479
-     * having the specified LIN_code and returns it, else NULL
1480
-     *
1481
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1482
-     * @param string       $search_field     name of EE_Line_Item property
1483
-     * @param string       $value            any value stored in $search_field
1484
-     * @return EE_Line_Item
1485
-     * @throws EE_Error
1486
-     * @throws InvalidArgumentException
1487
-     * @throws InvalidDataTypeException
1488
-     * @throws InvalidInterfaceException
1489
-     * @throws ReflectionException
1490
-     */
1491
-    protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1492
-    {
1493
-        foreach ($parent_line_item->children() as $child) {
1494
-            if ($child->get($search_field) == $value) {
1495
-                return $child;
1496
-            }
1497
-        }
1498
-        foreach ($parent_line_item->children() as $child) {
1499
-            $descendant_found = self::_get_nearest_descendant(
1500
-                $child,
1501
-                $search_field,
1502
-                $value
1503
-            );
1504
-            if ($descendant_found) {
1505
-                return $descendant_found;
1506
-            }
1507
-        }
1508
-        return null;
1509
-    }
1510
-
1511
-
1512
-    /**
1513
-     * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1514
-     * else recursively walks up the line item tree until a parent of type total is found,
1515
-     *
1516
-     * @param EE_Line_Item $line_item
1517
-     * @return EE_Line_Item
1518
-     * @throws EE_Error
1519
-     */
1520
-    public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1521
-    {
1522
-        if ($line_item->TXN_ID()) {
1523
-            $total_line_item = $line_item->transaction()->total_line_item(false);
1524
-            if ($total_line_item instanceof EE_Line_Item) {
1525
-                return $total_line_item;
1526
-            }
1527
-        } else {
1528
-            $line_item_parent = $line_item->parent();
1529
-            if ($line_item_parent instanceof EE_Line_Item) {
1530
-                if ($line_item_parent->is_total()) {
1531
-                    return $line_item_parent;
1532
-                }
1533
-                return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1534
-            }
1535
-        }
1536
-        throw new EE_Error(
1537
-            sprintf(
1538
-                esc_html__(
1539
-                    'A valid grand total for line item %1$d was not found.',
1540
-                    'event_espresso'
1541
-                ),
1542
-                $line_item->ID()
1543
-            )
1544
-        );
1545
-    }
1546
-
1547
-
1548
-    /**
1549
-     * Prints out a representation of the line item tree
1550
-     *
1551
-     * @param EE_Line_Item $line_item
1552
-     * @param int          $indentation
1553
-     * @return void
1554
-     * @throws EE_Error
1555
-     */
1556
-    public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1557
-    {
1558
-        echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1559
-        if (! $indentation) {
1560
-            echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1561
-        }
1562
-        for ($i = 0; $i < $indentation; $i++) {
1563
-            echo '. ';
1564
-        }
1565
-        $breakdown = '';
1566
-        if ($line_item->is_line_item()) {
1567
-            if ($line_item->is_percent()) {
1568
-                $breakdown = "{$line_item->percent()}%";
1569
-            } else {
1570
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1571
-            }
1572
-        }
1573
-        echo $line_item->name();
1574
-        echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1575
-        echo '$' . (string) $line_item->total();
1576
-        if ($breakdown) {
1577
-            echo " ( {$breakdown} )";
1578
-        }
1579
-        if ($line_item->is_taxable()) {
1580
-            echo '  * taxable';
1581
-        }
1582
-        if ($line_item->children()) {
1583
-            foreach ($line_item->children() as $child) {
1584
-                self::visualize($child, $indentation + 1);
1585
-            }
1586
-        }
1587
-    }
1588
-
1589
-
1590
-    /**
1591
-     * Calculates the registration's final price, taking into account that they
1592
-     * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1593
-     * and receive a portion of any transaction-wide discounts.
1594
-     * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1595
-     * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1596
-     * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1597
-     * and brent's final price should be $5.50.
1598
-     * In order to do this, we basically need to traverse the line item tree calculating
1599
-     * the running totals (just as if we were recalculating the total), but when we identify
1600
-     * regular line items, we need to keep track of their share of the grand total.
1601
-     * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1602
-     * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1603
-     * when there are non-taxable items; otherwise they would be the same)
1604
-     *
1605
-     * @param EE_Line_Item $line_item
1606
-     * @param array        $billable_ticket_quantities  array of EE_Ticket IDs and their corresponding quantity that
1607
-     *                                                  can be included in price calculations at this moment
1608
-     * @return array        keys are line items for tickets IDs and values are their share of the running total,
1609
-     *                                                  plus the key 'total', and 'taxable' which also has keys of all
1610
-     *                                                  the ticket IDs.
1611
-     *                                                  Eg array(
1612
-     *                                                      12 => 4.3
1613
-     *                                                      23 => 8.0
1614
-     *                                                      'total' => 16.6,
1615
-     *                                                      'taxable' => array(
1616
-     *                                                          12 => 10,
1617
-     *                                                          23 => 4
1618
-     *                                                      ).
1619
-     *                                                  So to find which registrations have which final price, we need
1620
-     *                                                  to find which line item is theirs, which can be done with
1621
-     *                                                  `EEM_Line_Item::instance()->get_line_item_for_registration(
1622
-     *                                                  $registration );`
1623
-     * @throws EE_Error
1624
-     * @throws InvalidArgumentException
1625
-     * @throws InvalidDataTypeException
1626
-     * @throws InvalidInterfaceException
1627
-     * @throws ReflectionException
1628
-     */
1629
-    public static function calculate_reg_final_prices_per_line_item(
1630
-        EE_Line_Item $line_item,
1631
-        $billable_ticket_quantities = array()
1632
-    ) {
1633
-        $running_totals = [
1634
-            'total'   => 0,
1635
-            'taxable' => ['total' => 0]
1636
-        ];
1637
-        foreach ($line_item->children() as $child_line_item) {
1638
-            switch ($child_line_item->type()) {
1639
-                case EEM_Line_Item::type_sub_total:
1640
-                    $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1641
-                        $child_line_item,
1642
-                        $billable_ticket_quantities
1643
-                    );
1644
-                    // combine arrays but preserve numeric keys
1645
-                    $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1646
-                    $running_totals['total'] += $running_totals_from_subtotal['total'];
1647
-                    $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1648
-                    break;
1649
-
1650
-                case EEM_Line_Item::type_tax_sub_total:
1651
-                    // find how much the taxes percentage is
1652
-                    if ($child_line_item->percent() !== 0) {
1653
-                        $tax_percent_decimal = $child_line_item->percent() / 100;
1654
-                    } else {
1655
-                        $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1656
-                    }
1657
-                    // and apply to all the taxable totals, and add to the pretax totals
1658
-                    foreach ($running_totals as $line_item_id => $this_running_total) {
1659
-                        // "total" and "taxable" array key is an exception
1660
-                        if ($line_item_id === 'taxable') {
1661
-                            continue;
1662
-                        }
1663
-                        $taxable_total = $running_totals['taxable'][ $line_item_id ];
1664
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1665
-                    }
1666
-                    break;
1667
-
1668
-                case EEM_Line_Item::type_line_item:
1669
-                    // ticket line items or ????
1670
-                    if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1671
-                        // kk it's a ticket
1672
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1673
-                            // huh? that shouldn't happen.
1674
-                            $running_totals['total'] += $child_line_item->total();
1675
-                        } else {
1676
-                            // its not in our running totals yet. great.
1677
-                            if ($child_line_item->is_taxable()) {
1678
-                                $taxable_amount = $child_line_item->unit_price();
1679
-                            } else {
1680
-                                $taxable_amount = 0;
1681
-                            }
1682
-                            // are we only calculating totals for some tickets?
1683
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1684
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1685
-                                $running_totals[ $child_line_item->ID() ] = $quantity
1686
-                                    ? $child_line_item->unit_price()
1687
-                                    : 0;
1688
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1689
-                                    ? $taxable_amount
1690
-                                    : 0;
1691
-                            } else {
1692
-                                $quantity = $child_line_item->quantity();
1693
-                                $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1694
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1695
-                            }
1696
-                            $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1697
-                            $running_totals['total'] += $child_line_item->unit_price() * $quantity;
1698
-                        }
1699
-                    } else {
1700
-                        // it's some other type of item added to the cart
1701
-                        // it should affect the running totals
1702
-                        // basically we want to convert it into a PERCENT modifier. Because
1703
-                        // more clearly affect all registration's final price equally
1704
-                        $line_items_percent_of_running_total = $running_totals['total'] > 0
1705
-                            ? ($child_line_item->total() / $running_totals['total']) + 1
1706
-                            : 1;
1707
-                        foreach ($running_totals as $line_item_id => $this_running_total) {
1708
-                            // the "taxable" array key is an exception
1709
-                            if ($line_item_id === 'taxable') {
1710
-                                continue;
1711
-                            }
1712
-                            // update the running totals
1713
-                            // yes this actually even works for the running grand total!
1714
-                            $running_totals[ $line_item_id ] =
1715
-                                $line_items_percent_of_running_total * $this_running_total;
1716
-
1717
-                            if ($child_line_item->is_taxable()) {
1718
-                                $running_totals['taxable'][ $line_item_id ] =
1719
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1720
-                            }
1721
-                        }
1722
-                    }
1723
-                    break;
1724
-            }
1725
-        }
1726
-        return $running_totals;
1727
-    }
1728
-
1729
-
1730
-    /**
1731
-     * @param EE_Line_Item $total_line_item
1732
-     * @param EE_Line_Item $ticket_line_item
1733
-     * @return float | null
1734
-     * @throws EE_Error
1735
-     * @throws InvalidArgumentException
1736
-     * @throws InvalidDataTypeException
1737
-     * @throws InvalidInterfaceException
1738
-     * @throws OutOfRangeException
1739
-     * @throws ReflectionException
1740
-     */
1741
-    public static function calculate_final_price_for_ticket_line_item(
1742
-        EE_Line_Item $total_line_item,
1743
-        EE_Line_Item $ticket_line_item
1744
-    ) {
1745
-        static $final_prices_per_ticket_line_item = array();
1746
-        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1747
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1748
-                $total_line_item
1749
-            );
1750
-        }
1751
-        // ok now find this new registration's final price
1752
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1753
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1754
-        }
1755
-        $message = sprintf(
1756
-            esc_html__(
1757
-                'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1758
-                'event_espresso'
1759
-            ),
1760
-            $ticket_line_item->ID()
1761
-        );
1762
-        if (WP_DEBUG) {
1763
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1764
-            throw new OutOfRangeException($message);
1765
-        }
1766
-        EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1767
-        return null;
1768
-    }
1769
-
1770
-
1771
-    /**
1772
-     * Creates a duplicate of the line item tree, except only includes billable items
1773
-     * and the portion of line items attributed to billable things
1774
-     *
1775
-     * @param EE_Line_Item      $line_item
1776
-     * @param EE_Registration[] $registrations
1777
-     * @return EE_Line_Item
1778
-     * @throws EE_Error
1779
-     * @throws InvalidArgumentException
1780
-     * @throws InvalidDataTypeException
1781
-     * @throws InvalidInterfaceException
1782
-     * @throws ReflectionException
1783
-     */
1784
-    public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1785
-    {
1786
-        $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1787
-        foreach ($line_item->children() as $child_li) {
1788
-            $copy_li->add_child_line_item(
1789
-                EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1790
-            );
1791
-        }
1792
-        // if this is the grand total line item, make sure the totals all add up
1793
-        // (we could have duplicated this logic AS we copied the line items, but
1794
-        // it seems DRYer this way)
1795
-        if ($copy_li->type() === EEM_Line_Item::type_total) {
1796
-            $copy_li->recalculate_total_including_taxes();
1797
-        }
1798
-        return $copy_li;
1799
-    }
1800
-
1801
-
1802
-    /**
1803
-     * Creates a new, unsaved line item from $line_item that factors in the
1804
-     * number of billable registrations on $registrations.
1805
-     *
1806
-     * @param EE_Line_Item      $line_item
1807
-     * @param EE_Registration[] $registrations
1808
-     * @return EE_Line_Item
1809
-     * @throws EE_Error
1810
-     * @throws InvalidArgumentException
1811
-     * @throws InvalidDataTypeException
1812
-     * @throws InvalidInterfaceException
1813
-     * @throws ReflectionException
1814
-     */
1815
-    public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1816
-    {
1817
-        $new_li_fields = $line_item->model_field_array();
1818
-        if ($line_item->type() === EEM_Line_Item::type_line_item &&
1819
-            $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1820
-        ) {
1821
-            $count = 0;
1822
-            foreach ($registrations as $registration) {
1823
-                if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1824
-                    in_array(
1825
-                        $registration->status_ID(),
1826
-                        EEM_Registration::reg_statuses_that_allow_payment(),
1827
-                        true
1828
-                    )
1829
-                ) {
1830
-                    $count++;
1831
-                }
1832
-            }
1833
-            $new_li_fields['LIN_quantity'] = $count;
1834
-        }
1835
-        // don't set the total. We'll leave that up to the code that calculates it
1836
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1837
-        return EE_Line_Item::new_instance($new_li_fields);
1838
-    }
1839
-
1840
-
1841
-    /**
1842
-     * Returns a modified line item tree where all the subtotals which have a total of 0
1843
-     * are removed, and line items with a quantity of 0
1844
-     *
1845
-     * @param EE_Line_Item $line_item |null
1846
-     * @return EE_Line_Item|null
1847
-     * @throws EE_Error
1848
-     * @throws InvalidArgumentException
1849
-     * @throws InvalidDataTypeException
1850
-     * @throws InvalidInterfaceException
1851
-     * @throws ReflectionException
1852
-     */
1853
-    public static function non_empty_line_items(EE_Line_Item $line_item)
1854
-    {
1855
-        $copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1856
-        if ($copied_li === null) {
1857
-            return null;
1858
-        }
1859
-        // if this is an event subtotal, we want to only include it if it
1860
-        // has a non-zero total and at least one ticket line item child
1861
-        $ticket_children = 0;
1862
-        foreach ($line_item->children() as $child_li) {
1863
-            $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1864
-            if ($child_li_copy !== null) {
1865
-                $copied_li->add_child_line_item($child_li_copy);
1866
-                if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1867
-                    $child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1868
-                ) {
1869
-                    $ticket_children++;
1870
-                }
1871
-            }
1872
-        }
1873
-        // if this is an event subtotal with NO ticket children
1874
-        // we basically want to ignore it
1875
-        if ($ticket_children === 0
1876
-            && $line_item->type() === EEM_Line_Item::type_sub_total
1877
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
1878
-            && $line_item->total() === 0
1879
-        ) {
1880
-            return null;
1881
-        }
1882
-        return $copied_li;
1883
-    }
1884
-
1885
-
1886
-    /**
1887
-     * Creates a new, unsaved line item, but if it's a ticket line item
1888
-     * with a total of 0, or a subtotal of 0, returns null instead
1889
-     *
1890
-     * @param EE_Line_Item $line_item
1891
-     * @return EE_Line_Item
1892
-     * @throws EE_Error
1893
-     * @throws InvalidArgumentException
1894
-     * @throws InvalidDataTypeException
1895
-     * @throws InvalidInterfaceException
1896
-     * @throws ReflectionException
1897
-     */
1898
-    public static function non_empty_line_item(EE_Line_Item $line_item)
1899
-    {
1900
-        if ($line_item->type() === EEM_Line_Item::type_line_item
1901
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1902
-            && $line_item->quantity() === 0
1903
-        ) {
1904
-            return null;
1905
-        }
1906
-        $new_li_fields = $line_item->model_field_array();
1907
-        // don't set the total. We'll leave that up to the code that calculates it
1908
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1909
-        return EE_Line_Item::new_instance($new_li_fields);
1910
-    }
1911
-
1912
-
1913
-    /**
1914
-     * Cycles through all of the ticket line items for the supplied total line item
1915
-     * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
1916
-     *
1917
-     * @param EE_Line_Item $total_line_item
1918
-     * @since 4.9.79.p
1919
-     * @throws EE_Error
1920
-     * @throws InvalidArgumentException
1921
-     * @throws InvalidDataTypeException
1922
-     * @throws InvalidInterfaceException
1923
-     * @throws ReflectionException
1924
-     */
1925
-    public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
1926
-    {
1927
-        $ticket_line_items = self::get_ticket_line_items($total_line_item);
1928
-        foreach ($ticket_line_items as $ticket_line_item) {
1929
-            if ($ticket_line_item instanceof EE_Line_Item
1930
-                && $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1931
-            ) {
1932
-                $ticket = $ticket_line_item->ticket();
1933
-                if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
1934
-                    $ticket_line_item->set_is_taxable($ticket->taxable());
1935
-                    $ticket_line_item->save();
1936
-                }
1937
-            }
1938
-        }
1939
-    }
1940
-
1941
-
1942
-
1943
-    /**************************************** @DEPRECATED METHODS *************************************** */
1944
-    /**
1945
-     * @deprecated
1946
-     * @param EE_Line_Item $total_line_item
1947
-     * @return EE_Line_Item
1948
-     * @throws EE_Error
1949
-     * @throws InvalidArgumentException
1950
-     * @throws InvalidDataTypeException
1951
-     * @throws InvalidInterfaceException
1952
-     * @throws ReflectionException
1953
-     */
1954
-    public static function get_items_subtotal(EE_Line_Item $total_line_item)
1955
-    {
1956
-        EE_Error::doing_it_wrong(
1957
-            'EEH_Line_Item::get_items_subtotal()',
1958
-            sprintf(
1959
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1960
-                'EEH_Line_Item::get_pre_tax_subtotal()'
1961
-            ),
1962
-            '4.6.0'
1963
-        );
1964
-        return self::get_pre_tax_subtotal($total_line_item);
1965
-    }
1966
-
1967
-
1968
-    /**
1969
-     * @deprecated
1970
-     * @param EE_Transaction $transaction
1971
-     * @return EE_Line_Item
1972
-     * @throws EE_Error
1973
-     * @throws InvalidArgumentException
1974
-     * @throws InvalidDataTypeException
1975
-     * @throws InvalidInterfaceException
1976
-     * @throws ReflectionException
1977
-     */
1978
-    public static function create_default_total_line_item($transaction = null)
1979
-    {
1980
-        EE_Error::doing_it_wrong(
1981
-            'EEH_Line_Item::create_default_total_line_item()',
1982
-            sprintf(
1983
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1984
-                'EEH_Line_Item::create_total_line_item()'
1985
-            ),
1986
-            '4.6.0'
1987
-        );
1988
-        return self::create_total_line_item($transaction);
1989
-    }
1990
-
1991
-
1992
-    /**
1993
-     * @deprecated
1994
-     * @param EE_Line_Item   $total_line_item
1995
-     * @param EE_Transaction $transaction
1996
-     * @return EE_Line_Item
1997
-     * @throws EE_Error
1998
-     * @throws InvalidArgumentException
1999
-     * @throws InvalidDataTypeException
2000
-     * @throws InvalidInterfaceException
2001
-     * @throws ReflectionException
2002
-     */
2003
-    public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2004
-    {
2005
-        EE_Error::doing_it_wrong(
2006
-            'EEH_Line_Item::create_default_tickets_subtotal()',
2007
-            sprintf(
2008
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2009
-                'EEH_Line_Item::create_pre_tax_subtotal()'
2010
-            ),
2011
-            '4.6.0'
2012
-        );
2013
-        return self::create_pre_tax_subtotal($total_line_item, $transaction);
2014
-    }
2015
-
2016
-
2017
-    /**
2018
-     * @deprecated
2019
-     * @param EE_Line_Item   $total_line_item
2020
-     * @param EE_Transaction $transaction
2021
-     * @return EE_Line_Item
2022
-     * @throws EE_Error
2023
-     * @throws InvalidArgumentException
2024
-     * @throws InvalidDataTypeException
2025
-     * @throws InvalidInterfaceException
2026
-     * @throws ReflectionException
2027
-     */
2028
-    public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2029
-    {
2030
-        EE_Error::doing_it_wrong(
2031
-            'EEH_Line_Item::create_default_taxes_subtotal()',
2032
-            sprintf(
2033
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2034
-                'EEH_Line_Item::create_taxes_subtotal()'
2035
-            ),
2036
-            '4.6.0'
2037
-        );
2038
-        return self::create_taxes_subtotal($total_line_item, $transaction);
2039
-    }
2040
-
2041
-
2042
-    /**
2043
-     * @deprecated
2044
-     * @param EE_Line_Item   $total_line_item
2045
-     * @param EE_Transaction $transaction
2046
-     * @return EE_Line_Item
2047
-     * @throws EE_Error
2048
-     * @throws InvalidArgumentException
2049
-     * @throws InvalidDataTypeException
2050
-     * @throws InvalidInterfaceException
2051
-     * @throws ReflectionException
2052
-     */
2053
-    public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2054
-    {
2055
-        EE_Error::doing_it_wrong(
2056
-            'EEH_Line_Item::create_default_event_subtotal()',
2057
-            sprintf(
2058
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2059
-                'EEH_Line_Item::create_event_subtotal()'
2060
-            ),
2061
-            '4.6.0'
2062
-        );
2063
-        return self::create_event_subtotal($total_line_item, $transaction);
2064
-    }
24
+	/**
25
+	 * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
26
+	 * Does NOT automatically re-calculate the line item totals or update the related transaction.
27
+	 * You should call recalculate_total_including_taxes() on the grant total line item after this
28
+	 * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
29
+	 * to keep the registration final prices in-sync with the transaction's total.
30
+	 *
31
+	 * @param EE_Line_Item $parent_line_item
32
+	 * @param string       $name
33
+	 * @param float        $unit_price
34
+	 * @param string       $description
35
+	 * @param int          $quantity
36
+	 * @param boolean      $taxable
37
+	 * @param boolean      $code if set to a value, ensures there is only one line item with that code
38
+	 * @return boolean success
39
+	 * @throws EE_Error
40
+	 * @throws InvalidArgumentException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws InvalidInterfaceException
43
+	 * @throws ReflectionException
44
+	 */
45
+	public static function add_unrelated_item(
46
+		EE_Line_Item $parent_line_item,
47
+		$name,
48
+		$unit_price,
49
+		$description = '',
50
+		$quantity = 1,
51
+		$taxable = false,
52
+		$code = null
53
+	) {
54
+		$items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
55
+		$line_item = EE_Line_Item::new_instance(array(
56
+			'LIN_name'       => $name,
57
+			'LIN_desc'       => $description,
58
+			'LIN_unit_price' => $unit_price,
59
+			'LIN_quantity'   => $quantity,
60
+			'LIN_percent'    => null,
61
+			'LIN_is_taxable' => $taxable,
62
+			'LIN_order'      => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
63
+			'LIN_total'      => (float) $unit_price * (int) $quantity,
64
+			'LIN_type'       => EEM_Line_Item::type_line_item,
65
+			'LIN_code'       => $code,
66
+		));
67
+		$line_item = apply_filters(
68
+			'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
69
+			$line_item,
70
+			$parent_line_item
71
+		);
72
+		return self::add_item($parent_line_item, $line_item);
73
+	}
74
+
75
+
76
+	/**
77
+	 * Adds a simple item ( unrelated to any other model object) to the total line item,
78
+	 * in the correct spot in the line item tree. Does not automatically
79
+	 * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
80
+	 * registrations' final prices (which should probably change because of this).
81
+	 * You should call recalculate_total_including_taxes() on the grand total line item, then
82
+	 * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
83
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
84
+	 *
85
+	 * @param EE_Line_Item $parent_line_item
86
+	 * @param string       $name
87
+	 * @param float        $percentage_amount
88
+	 * @param string       $description
89
+	 * @param boolean      $taxable
90
+	 * @return boolean success
91
+	 * @throws EE_Error
92
+	 */
93
+	public static function add_percentage_based_item(
94
+		EE_Line_Item $parent_line_item,
95
+		$name,
96
+		$percentage_amount,
97
+		$description = '',
98
+		$taxable = false
99
+	) {
100
+		$line_item = EE_Line_Item::new_instance(array(
101
+			'LIN_name'       => $name,
102
+			'LIN_desc'       => $description,
103
+			'LIN_unit_price' => 0,
104
+			'LIN_percent'    => $percentage_amount,
105
+			'LIN_quantity'   => 1,
106
+			'LIN_is_taxable' => $taxable,
107
+			'LIN_total'      => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
108
+			'LIN_type'       => EEM_Line_Item::type_line_item,
109
+			'LIN_parent'     => $parent_line_item->ID(),
110
+		));
111
+		$line_item = apply_filters(
112
+			'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
113
+			$line_item
114
+		);
115
+		return $parent_line_item->add_child_line_item($line_item, false);
116
+	}
117
+
118
+
119
+	/**
120
+	 * Returns the new line item created by adding a purchase of the ticket
121
+	 * ensures that ticket line item is saved, and that cart total has been recalculated.
122
+	 * If this ticket has already been purchased, just increments its count.
123
+	 * Automatically re-calculates the line item totals and updates the related transaction. But
124
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
125
+	 * should probably change because of this).
126
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
127
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
128
+	 *
129
+	 * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
130
+	 * @param EE_Ticket    $ticket
131
+	 * @param int          $qty
132
+	 * @return EE_Line_Item
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws ReflectionException
138
+	 */
139
+	public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140
+	{
141
+		if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142
+			throw new EE_Error(
143
+				sprintf(
144
+					esc_html__(
145
+						'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
146
+						'event_espresso'
147
+					),
148
+					$ticket->ID(),
149
+					$total_line_item->ID()
150
+				)
151
+			);
152
+		}
153
+		// either increment the qty for an existing ticket
154
+		$line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155
+		// or add a new one
156
+		if (! $line_item instanceof EE_Line_Item) {
157
+			$line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158
+		}
159
+		$total_line_item->recalculate_total_including_taxes();
160
+		return $line_item;
161
+	}
162
+
163
+
164
+	/**
165
+	 * Returns the new line item created by adding a purchase of the ticket
166
+	 *
167
+	 * @param EE_Line_Item $total_line_item
168
+	 * @param EE_Ticket    $ticket
169
+	 * @param int          $qty
170
+	 * @return EE_Line_Item
171
+	 * @throws EE_Error
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 */
177
+	public static function increment_ticket_qty_if_already_in_cart(
178
+		EE_Line_Item $total_line_item,
179
+		EE_Ticket $ticket,
180
+		$qty = 1
181
+	) {
182
+		$line_item = null;
183
+		if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
184
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
185
+			foreach ((array) $ticket_line_items as $ticket_line_item) {
186
+				if ($ticket_line_item instanceof EE_Line_Item
187
+					&& (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
188
+				) {
189
+					$line_item = $ticket_line_item;
190
+					break;
191
+				}
192
+			}
193
+		}
194
+		if ($line_item instanceof EE_Line_Item) {
195
+			EEH_Line_Item::increment_quantity($line_item, $qty);
196
+			return $line_item;
197
+		}
198
+		return null;
199
+	}
200
+
201
+
202
+	/**
203
+	 * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
204
+	 * Does NOT save or recalculate other line items totals
205
+	 *
206
+	 * @param EE_Line_Item $line_item
207
+	 * @param int          $qty
208
+	 * @return void
209
+	 * @throws EE_Error
210
+	 * @throws InvalidArgumentException
211
+	 * @throws InvalidDataTypeException
212
+	 * @throws InvalidInterfaceException
213
+	 * @throws ReflectionException
214
+	 */
215
+	public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
216
+	{
217
+		if (! $line_item->is_percent()) {
218
+			$qty += $line_item->quantity();
219
+			$line_item->set_quantity($qty);
220
+			$line_item->set_total($line_item->unit_price() * $qty);
221
+			$line_item->save();
222
+		}
223
+		foreach ($line_item->children() as $child) {
224
+			if ($child->is_sub_line_item()) {
225
+				EEH_Line_Item::update_quantity($child, $qty);
226
+			}
227
+		}
228
+	}
229
+
230
+
231
+	/**
232
+	 * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
233
+	 * Does NOT save or recalculate other line items totals
234
+	 *
235
+	 * @param EE_Line_Item $line_item
236
+	 * @param int          $qty
237
+	 * @return void
238
+	 * @throws EE_Error
239
+	 * @throws InvalidArgumentException
240
+	 * @throws InvalidDataTypeException
241
+	 * @throws InvalidInterfaceException
242
+	 * @throws ReflectionException
243
+	 */
244
+	public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
245
+	{
246
+		if (! $line_item->is_percent()) {
247
+			$qty = $line_item->quantity() - $qty;
248
+			$qty = max($qty, 0);
249
+			$line_item->set_quantity($qty);
250
+			$line_item->set_total($line_item->unit_price() * $qty);
251
+			$line_item->save();
252
+		}
253
+		foreach ($line_item->children() as $child) {
254
+			if ($child->is_sub_line_item()) {
255
+				EEH_Line_Item::update_quantity($child, $qty);
256
+			}
257
+		}
258
+	}
259
+
260
+
261
+	/**
262
+	 * Updates the line item and its children's quantities to the specified number.
263
+	 * Does NOT save them or recalculate totals.
264
+	 *
265
+	 * @param EE_Line_Item $line_item
266
+	 * @param int          $new_quantity
267
+	 * @throws EE_Error
268
+	 * @throws InvalidArgumentException
269
+	 * @throws InvalidDataTypeException
270
+	 * @throws InvalidInterfaceException
271
+	 * @throws ReflectionException
272
+	 */
273
+	public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
274
+	{
275
+		if (! $line_item->is_percent()) {
276
+			$line_item->set_quantity($new_quantity);
277
+			$line_item->set_total($line_item->unit_price() * $new_quantity);
278
+			$line_item->save();
279
+		}
280
+		foreach ($line_item->children() as $child) {
281
+			if ($child->is_sub_line_item()) {
282
+				EEH_Line_Item::update_quantity($child, $new_quantity);
283
+			}
284
+		}
285
+	}
286
+
287
+
288
+	/**
289
+	 * Returns the new line item created by adding a purchase of the ticket
290
+	 *
291
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
292
+	 * @param EE_Ticket    $ticket
293
+	 * @param int          $qty
294
+	 * @return EE_Line_Item
295
+	 * @throws EE_Error
296
+	 * @throws InvalidArgumentException
297
+	 * @throws InvalidDataTypeException
298
+	 * @throws InvalidInterfaceException
299
+	 * @throws ReflectionException
300
+	 */
301
+	public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
302
+	{
303
+		$datetimes = $ticket->datetimes();
304
+		$first_datetime = reset($datetimes);
305
+		$first_datetime_name = esc_html__('Event', 'event_espresso');
306
+		if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
307
+			$first_datetime_name = $first_datetime->event()->name();
308
+		}
309
+		$event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
310
+		// get event subtotal line
311
+		$events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
312
+		// add $ticket to cart
313
+		$line_item = EE_Line_Item::new_instance(array(
314
+			'LIN_name'       => $ticket->name(),
315
+			'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
316
+			'LIN_unit_price' => $ticket->price(),
317
+			'LIN_quantity'   => $qty,
318
+			'LIN_is_taxable' => $ticket->taxable(),
319
+			'LIN_order'      => count($events_sub_total->children()),
320
+			'LIN_total'      => $ticket->price() * $qty,
321
+			'LIN_type'       => EEM_Line_Item::type_line_item,
322
+			'OBJ_ID'         => $ticket->ID(),
323
+			'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
324
+		));
325
+		$line_item = apply_filters(
326
+			'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
327
+			$line_item
328
+		);
329
+		$events_sub_total->add_child_line_item($line_item);
330
+		// now add the sub-line items
331
+		$running_total_for_ticket = 0;
332
+		foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
333
+			$sign = $price->is_discount() ? -1 : 1;
334
+			$price_total = $price->is_percent()
335
+				? $running_total_for_ticket * $price->amount() / 100
336
+				: $price->amount() * $qty;
337
+			$sub_line_item = EE_Line_Item::new_instance(array(
338
+				'LIN_name'       => $price->name(),
339
+				'LIN_desc'       => $price->desc(),
340
+				'LIN_quantity'   => $price->is_percent() ? null : $qty,
341
+				'LIN_is_taxable' => false,
342
+				'LIN_order'      => $price->order(),
343
+				'LIN_total'      => $sign * $price_total,
344
+				'LIN_type'       => EEM_Line_Item::type_sub_line_item,
345
+				'OBJ_ID'         => $price->ID(),
346
+				'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
347
+			));
348
+			$sub_line_item = apply_filters(
349
+				'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
350
+				$sub_line_item
351
+			);
352
+			if ($price->is_percent()) {
353
+				$sub_line_item->set_percent($sign * $price->amount());
354
+			} else {
355
+				$sub_line_item->set_unit_price($sign * $price->amount());
356
+			}
357
+			$running_total_for_ticket += $price_total;
358
+			$line_item->add_child_line_item($sub_line_item);
359
+		}
360
+		return $line_item;
361
+	}
362
+
363
+
364
+	/**
365
+	 * Adds the specified item under the pre-tax-sub-total line item. Automatically
366
+	 * re-calculates the line item totals and updates the related transaction. But
367
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
368
+	 * should probably change because of this).
369
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
370
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
371
+	 *
372
+	 * @param EE_Line_Item $total_line_item
373
+	 * @param EE_Line_Item $item to be added
374
+	 * @return boolean
375
+	 * @throws EE_Error
376
+	 * @throws InvalidArgumentException
377
+	 * @throws InvalidDataTypeException
378
+	 * @throws InvalidInterfaceException
379
+	 * @throws ReflectionException
380
+	 */
381
+	public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
382
+	{
383
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
384
+		if ($pre_tax_subtotal instanceof EE_Line_Item) {
385
+			$success = $pre_tax_subtotal->add_child_line_item($item);
386
+		} else {
387
+			return false;
388
+		}
389
+		$total_line_item->recalculate_total_including_taxes();
390
+		return $success;
391
+	}
392
+
393
+
394
+	/**
395
+	 * cancels an existing ticket line item,
396
+	 * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
397
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
398
+	 *
399
+	 * @param EE_Line_Item $ticket_line_item
400
+	 * @param int          $qty
401
+	 * @return bool success
402
+	 * @throws EE_Error
403
+	 * @throws InvalidArgumentException
404
+	 * @throws InvalidDataTypeException
405
+	 * @throws InvalidInterfaceException
406
+	 * @throws ReflectionException
407
+	 */
408
+	public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
409
+	{
410
+		// validate incoming line_item
411
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
412
+			throw new EE_Error(
413
+				sprintf(
414
+					esc_html__(
415
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
416
+						'event_espresso'
417
+					),
418
+					$ticket_line_item->type()
419
+				)
420
+			);
421
+		}
422
+		if ($ticket_line_item->quantity() < $qty) {
423
+			throw new EE_Error(
424
+				sprintf(
425
+					esc_html__(
426
+						'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
427
+						'event_espresso'
428
+					),
429
+					$qty,
430
+					$ticket_line_item->quantity()
431
+				)
432
+			);
433
+		}
434
+		// decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
435
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
436
+		foreach ($ticket_line_item->children() as $child_line_item) {
437
+			if ($child_line_item->is_sub_line_item()
438
+				&& ! $child_line_item->is_percent()
439
+				&& ! $child_line_item->is_cancellation()
440
+			) {
441
+				$child_line_item->set_quantity($child_line_item->quantity() - $qty);
442
+			}
443
+		}
444
+		// get cancellation sub line item
445
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
446
+			$ticket_line_item,
447
+			EEM_Line_Item::type_cancellation
448
+		);
449
+		$cancellation_line_item = reset($cancellation_line_item);
450
+		// verify that this ticket was indeed previously cancelled
451
+		if ($cancellation_line_item instanceof EE_Line_Item) {
452
+			// increment cancelled quantity
453
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
454
+		} else {
455
+			// create cancellation sub line item
456
+			$cancellation_line_item = EE_Line_Item::new_instance(array(
457
+				'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
458
+				'LIN_desc'       => sprintf(
459
+					esc_html_x(
460
+						'Cancelled %1$s : %2$s',
461
+						'Cancelled Ticket Name : 2015-01-01 11:11',
462
+						'event_espresso'
463
+					),
464
+					$ticket_line_item->name(),
465
+					current_time(get_option('date_format') . ' ' . get_option('time_format'))
466
+				),
467
+				'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
468
+				'LIN_quantity'   => $qty,
469
+				'LIN_is_taxable' => $ticket_line_item->is_taxable(),
470
+				'LIN_order'      => count($ticket_line_item->children()),
471
+				'LIN_total'      => 0, // $ticket_line_item->unit_price()
472
+				'LIN_type'       => EEM_Line_Item::type_cancellation,
473
+			));
474
+			$ticket_line_item->add_child_line_item($cancellation_line_item);
475
+		}
476
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
477
+			// decrement parent line item quantity
478
+			$event_line_item = $ticket_line_item->parent();
479
+			if ($event_line_item instanceof EE_Line_Item
480
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
481
+			) {
482
+				$event_line_item->set_quantity($event_line_item->quantity() - $qty);
483
+				$event_line_item->save();
484
+			}
485
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
486
+			return true;
487
+		}
488
+		return false;
489
+	}
490
+
491
+
492
+	/**
493
+	 * reinstates (un-cancels?) a previously canceled ticket line item,
494
+	 * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
495
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
496
+	 *
497
+	 * @param EE_Line_Item $ticket_line_item
498
+	 * @param int          $qty
499
+	 * @return bool success
500
+	 * @throws EE_Error
501
+	 * @throws InvalidArgumentException
502
+	 * @throws InvalidDataTypeException
503
+	 * @throws InvalidInterfaceException
504
+	 * @throws ReflectionException
505
+	 */
506
+	public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
507
+	{
508
+		// validate incoming line_item
509
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
510
+			throw new EE_Error(
511
+				sprintf(
512
+					esc_html__(
513
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
514
+						'event_espresso'
515
+					),
516
+					$ticket_line_item->type()
517
+				)
518
+			);
519
+		}
520
+		// get cancellation sub line item
521
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
522
+			$ticket_line_item,
523
+			EEM_Line_Item::type_cancellation
524
+		);
525
+		$cancellation_line_item = reset($cancellation_line_item);
526
+		// verify that this ticket was indeed previously cancelled
527
+		if (! $cancellation_line_item instanceof EE_Line_Item) {
528
+			return false;
529
+		}
530
+		if ($cancellation_line_item->quantity() > $qty) {
531
+			// decrement cancelled quantity
532
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
533
+		} elseif ($cancellation_line_item->quantity() === $qty) {
534
+			// decrement cancelled quantity in case anyone still has the object kicking around
535
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
536
+			// delete because quantity will end up as 0
537
+			$cancellation_line_item->delete();
538
+			// and attempt to destroy the object,
539
+			// even though PHP won't actually destroy it until it needs the memory
540
+			unset($cancellation_line_item);
541
+		} else {
542
+			// what ?!?! negative quantity ?!?!
543
+			throw new EE_Error(
544
+				sprintf(
545
+					esc_html__(
546
+						'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
547
+						'event_espresso'
548
+					),
549
+					$qty,
550
+					$cancellation_line_item->quantity()
551
+				)
552
+			);
553
+		}
554
+		// increment ticket quantity
555
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
556
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
557
+			// increment parent line item quantity
558
+			$event_line_item = $ticket_line_item->parent();
559
+			if ($event_line_item instanceof EE_Line_Item
560
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
561
+			) {
562
+				$event_line_item->set_quantity($event_line_item->quantity() + $qty);
563
+			}
564
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
565
+			return true;
566
+		}
567
+		return false;
568
+	}
569
+
570
+
571
+	/**
572
+	 * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
573
+	 * then EE_Line_Item::recalculate_total_including_taxes() on the result
574
+	 *
575
+	 * @param EE_Line_Item $line_item
576
+	 * @return float
577
+	 * @throws EE_Error
578
+	 * @throws InvalidArgumentException
579
+	 * @throws InvalidDataTypeException
580
+	 * @throws InvalidInterfaceException
581
+	 * @throws ReflectionException
582
+	 */
583
+	public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
584
+	{
585
+		$grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
586
+		return $grand_total_line_item->recalculate_total_including_taxes();
587
+	}
588
+
589
+
590
+	/**
591
+	 * Gets the line item which contains the subtotal of all the items
592
+	 *
593
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
594
+	 * @return EE_Line_Item
595
+	 * @throws EE_Error
596
+	 * @throws InvalidArgumentException
597
+	 * @throws InvalidDataTypeException
598
+	 * @throws InvalidInterfaceException
599
+	 * @throws ReflectionException
600
+	 */
601
+	public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
602
+	{
603
+		$pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
604
+		return $pre_tax_subtotal instanceof EE_Line_Item
605
+			? $pre_tax_subtotal
606
+			: self::create_pre_tax_subtotal($total_line_item);
607
+	}
608
+
609
+
610
+	/**
611
+	 * Gets the line item for the taxes subtotal
612
+	 *
613
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
614
+	 * @return EE_Line_Item
615
+	 * @throws EE_Error
616
+	 * @throws InvalidArgumentException
617
+	 * @throws InvalidDataTypeException
618
+	 * @throws InvalidInterfaceException
619
+	 * @throws ReflectionException
620
+	 */
621
+	public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
622
+	{
623
+		$taxes = $total_line_item->get_child_line_item('taxes');
624
+		return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
625
+	}
626
+
627
+
628
+	/**
629
+	 * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
630
+	 *
631
+	 * @param EE_Line_Item   $line_item
632
+	 * @param EE_Transaction $transaction
633
+	 * @return void
634
+	 * @throws EE_Error
635
+	 * @throws InvalidArgumentException
636
+	 * @throws InvalidDataTypeException
637
+	 * @throws InvalidInterfaceException
638
+	 * @throws ReflectionException
639
+	 */
640
+	public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
641
+	{
642
+		if ($transaction) {
643
+			/** @type EEM_Transaction $EEM_Transaction */
644
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
645
+			$TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
646
+			$line_item->set_TXN_ID($TXN_ID);
647
+		}
648
+	}
649
+
650
+
651
+	/**
652
+	 * Creates a new default total line item for the transaction,
653
+	 * and its tickets subtotal and taxes subtotal line items (and adds the
654
+	 * existing taxes as children of the taxes subtotal line item)
655
+	 *
656
+	 * @param EE_Transaction $transaction
657
+	 * @return EE_Line_Item of type total
658
+	 * @throws EE_Error
659
+	 * @throws InvalidArgumentException
660
+	 * @throws InvalidDataTypeException
661
+	 * @throws InvalidInterfaceException
662
+	 * @throws ReflectionException
663
+	 */
664
+	public static function create_total_line_item($transaction = null)
665
+	{
666
+		$total_line_item = EE_Line_Item::new_instance(array(
667
+			'LIN_code' => 'total',
668
+			'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
669
+			'LIN_type' => EEM_Line_Item::type_total,
670
+			'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
671
+		));
672
+		$total_line_item = apply_filters(
673
+			'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
674
+			$total_line_item
675
+		);
676
+		self::set_TXN_ID($total_line_item, $transaction);
677
+		self::create_pre_tax_subtotal($total_line_item, $transaction);
678
+		self::create_taxes_subtotal($total_line_item, $transaction);
679
+		return $total_line_item;
680
+	}
681
+
682
+
683
+	/**
684
+	 * Creates a default items subtotal line item
685
+	 *
686
+	 * @param EE_Line_Item   $total_line_item
687
+	 * @param EE_Transaction $transaction
688
+	 * @return EE_Line_Item
689
+	 * @throws EE_Error
690
+	 * @throws InvalidArgumentException
691
+	 * @throws InvalidDataTypeException
692
+	 * @throws InvalidInterfaceException
693
+	 * @throws ReflectionException
694
+	 */
695
+	protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
696
+	{
697
+		$pre_tax_line_item = EE_Line_Item::new_instance(array(
698
+			'LIN_code' => 'pre-tax-subtotal',
699
+			'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
700
+			'LIN_type' => EEM_Line_Item::type_sub_total,
701
+		));
702
+		$pre_tax_line_item = apply_filters(
703
+			'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
704
+			$pre_tax_line_item
705
+		);
706
+		self::set_TXN_ID($pre_tax_line_item, $transaction);
707
+		$total_line_item->add_child_line_item($pre_tax_line_item);
708
+		self::create_event_subtotal($pre_tax_line_item, $transaction);
709
+		return $pre_tax_line_item;
710
+	}
711
+
712
+
713
+	/**
714
+	 * Creates a line item for the taxes subtotal and finds all the tax prices
715
+	 * and applies taxes to it
716
+	 *
717
+	 * @param EE_Line_Item   $total_line_item of type EEM_Line_Item::type_total
718
+	 * @param EE_Transaction $transaction
719
+	 * @return EE_Line_Item
720
+	 * @throws EE_Error
721
+	 * @throws InvalidArgumentException
722
+	 * @throws InvalidDataTypeException
723
+	 * @throws InvalidInterfaceException
724
+	 * @throws ReflectionException
725
+	 */
726
+	protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
727
+	{
728
+		$tax_line_item = EE_Line_Item::new_instance(array(
729
+			'LIN_code'  => 'taxes',
730
+			'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
731
+			'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
732
+			'LIN_order' => 1000,// this should always come last
733
+		));
734
+		$tax_line_item = apply_filters(
735
+			'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
736
+			$tax_line_item
737
+		);
738
+		self::set_TXN_ID($tax_line_item, $transaction);
739
+		$total_line_item->add_child_line_item($tax_line_item);
740
+		// and lastly, add the actual taxes
741
+		self::apply_taxes($total_line_item);
742
+		return $tax_line_item;
743
+	}
744
+
745
+
746
+	/**
747
+	 * Creates a default items subtotal line item
748
+	 *
749
+	 * @param EE_Line_Item   $pre_tax_line_item
750
+	 * @param EE_Transaction $transaction
751
+	 * @param EE_Event       $event
752
+	 * @return EE_Line_Item
753
+	 * @throws EE_Error
754
+	 * @throws InvalidArgumentException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws InvalidInterfaceException
757
+	 * @throws ReflectionException
758
+	 */
759
+	public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
760
+	{
761
+		$event_line_item = EE_Line_Item::new_instance(array(
762
+			'LIN_code' => self::get_event_code($event),
763
+			'LIN_name' => self::get_event_name($event),
764
+			'LIN_desc' => self::get_event_desc($event),
765
+			'LIN_type' => EEM_Line_Item::type_sub_total,
766
+			'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
767
+			'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
768
+		));
769
+		$event_line_item = apply_filters(
770
+			'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
771
+			$event_line_item
772
+		);
773
+		self::set_TXN_ID($event_line_item, $transaction);
774
+		$pre_tax_line_item->add_child_line_item($event_line_item);
775
+		return $event_line_item;
776
+	}
777
+
778
+
779
+	/**
780
+	 * Gets what the event ticket's code SHOULD be
781
+	 *
782
+	 * @param EE_Event $event
783
+	 * @return string
784
+	 * @throws EE_Error
785
+	 */
786
+	public static function get_event_code($event)
787
+	{
788
+		return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
789
+	}
790
+
791
+
792
+	/**
793
+	 * Gets the event name
794
+	 *
795
+	 * @param EE_Event $event
796
+	 * @return string
797
+	 * @throws EE_Error
798
+	 */
799
+	public static function get_event_name($event)
800
+	{
801
+		return $event instanceof EE_Event
802
+			? mb_substr($event->name(), 0, 245)
803
+			: esc_html__('Event', 'event_espresso');
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets the event excerpt
809
+	 *
810
+	 * @param EE_Event $event
811
+	 * @return string
812
+	 * @throws EE_Error
813
+	 */
814
+	public static function get_event_desc($event)
815
+	{
816
+		return $event instanceof EE_Event ? $event->short_description() : '';
817
+	}
818
+
819
+
820
+	/**
821
+	 * Given the grand total line item and a ticket, finds the event sub-total
822
+	 * line item the ticket's purchase should be added onto
823
+	 *
824
+	 * @access public
825
+	 * @param EE_Line_Item $grand_total the grand total line item
826
+	 * @param EE_Ticket    $ticket
827
+	 * @return EE_Line_Item
828
+	 * @throws EE_Error
829
+	 * @throws InvalidArgumentException
830
+	 * @throws InvalidDataTypeException
831
+	 * @throws InvalidInterfaceException
832
+	 * @throws ReflectionException
833
+	 */
834
+	public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
835
+	{
836
+		$first_datetime = $ticket->first_datetime();
837
+		if (! $first_datetime instanceof EE_Datetime) {
838
+			throw new EE_Error(
839
+				sprintf(
840
+					__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
841
+					$ticket->ID()
842
+				)
843
+			);
844
+		}
845
+		$event = $first_datetime->event();
846
+		if (! $event instanceof EE_Event) {
847
+			throw new EE_Error(
848
+				sprintf(
849
+					esc_html__(
850
+						'The supplied ticket (ID %d) has no event data associated with it.',
851
+						'event_espresso'
852
+					),
853
+					$ticket->ID()
854
+				)
855
+			);
856
+		}
857
+		$events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
858
+		if (! $events_sub_total instanceof EE_Line_Item) {
859
+			throw new EE_Error(
860
+				sprintf(
861
+					esc_html__(
862
+						'There is no events sub-total for ticket %s on total line item %d',
863
+						'event_espresso'
864
+					),
865
+					$ticket->ID(),
866
+					$grand_total->ID()
867
+				)
868
+			);
869
+		}
870
+		return $events_sub_total;
871
+	}
872
+
873
+
874
+	/**
875
+	 * Gets the event line item
876
+	 *
877
+	 * @param EE_Line_Item $grand_total
878
+	 * @param EE_Event     $event
879
+	 * @return EE_Line_Item for the event subtotal which is a child of $grand_total
880
+	 * @throws EE_Error
881
+	 * @throws InvalidArgumentException
882
+	 * @throws InvalidDataTypeException
883
+	 * @throws InvalidInterfaceException
884
+	 * @throws ReflectionException
885
+	 */
886
+	public static function get_event_line_item(EE_Line_Item $grand_total, $event)
887
+	{
888
+		/** @type EE_Event $event */
889
+		$event = EEM_Event::instance()->ensure_is_obj($event, true);
890
+		$event_line_item = null;
891
+		$found = false;
892
+		foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
893
+			// default event subtotal, we should only ever find this the first time this method is called
894
+			if (! $event_line_item->OBJ_ID()) {
895
+				// let's use this! but first... set the event details
896
+				EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
897
+				$found = true;
898
+				break;
899
+			}
900
+			if ($event_line_item->OBJ_ID() === $event->ID()) {
901
+				// found existing line item for this event in the cart, so break out of loop and use this one
902
+				$found = true;
903
+				break;
904
+			}
905
+		}
906
+		if (! $found) {
907
+			// there is no event sub-total yet, so add it
908
+			$pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
909
+			// create a new "event" subtotal below that
910
+			$event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
911
+			// and set the event details
912
+			EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
913
+		}
914
+		return $event_line_item;
915
+	}
916
+
917
+
918
+	/**
919
+	 * Creates a default items subtotal line item
920
+	 *
921
+	 * @param EE_Line_Item   $event_line_item
922
+	 * @param EE_Event       $event
923
+	 * @param EE_Transaction $transaction
924
+	 * @return void
925
+	 * @throws EE_Error
926
+	 * @throws InvalidArgumentException
927
+	 * @throws InvalidDataTypeException
928
+	 * @throws InvalidInterfaceException
929
+	 * @throws ReflectionException
930
+	 */
931
+	public static function set_event_subtotal_details(
932
+		EE_Line_Item $event_line_item,
933
+		EE_Event $event,
934
+		$transaction = null
935
+	) {
936
+		if ($event instanceof EE_Event) {
937
+			$event_line_item->set_code(self::get_event_code($event));
938
+			$event_line_item->set_name(self::get_event_name($event));
939
+			$event_line_item->set_desc(self::get_event_desc($event));
940
+			$event_line_item->set_OBJ_ID($event->ID());
941
+		}
942
+		self::set_TXN_ID($event_line_item, $transaction);
943
+	}
944
+
945
+
946
+	/**
947
+	 * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
948
+	 * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
949
+	 * any old taxes are removed
950
+	 *
951
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
952
+	 * @param bool         $update_txn_status
953
+	 * @return bool
954
+	 * @throws EE_Error
955
+	 * @throws InvalidArgumentException
956
+	 * @throws InvalidDataTypeException
957
+	 * @throws InvalidInterfaceException
958
+	 * @throws ReflectionException
959
+	 * @throws RuntimeException
960
+	 */
961
+	public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false)
962
+	{
963
+		/** @type EEM_Price $EEM_Price */
964
+		$EEM_Price = EE_Registry::instance()->load_model('Price');
965
+		// get array of taxes via Price Model
966
+		$ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
967
+		ksort($ordered_taxes);
968
+		$taxes_line_item = self::get_taxes_subtotal($total_line_item);
969
+		// just to be safe, remove its old tax line items
970
+		$deleted = $taxes_line_item->delete_children_line_items();
971
+		$updates = false;
972
+		// loop thru taxes
973
+		foreach ($ordered_taxes as $order => $taxes) {
974
+			foreach ($taxes as $tax) {
975
+				if ($tax instanceof EE_Price) {
976
+					$tax_line_item = EE_Line_Item::new_instance(
977
+						array(
978
+							'LIN_name'       => $tax->name(),
979
+							'LIN_desc'       => $tax->desc(),
980
+							'LIN_percent'    => $tax->amount(),
981
+							'LIN_is_taxable' => false,
982
+							'LIN_order'      => $order,
983
+							'LIN_total'      => 0,
984
+							'LIN_type'       => EEM_Line_Item::type_tax,
985
+							'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
986
+							'OBJ_ID'         => $tax->ID(),
987
+						)
988
+					);
989
+					$tax_line_item = apply_filters(
990
+						'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
991
+						$tax_line_item
992
+					);
993
+					$updates = $taxes_line_item->add_child_line_item($tax_line_item) ?
994
+						true :
995
+						$updates;
996
+				}
997
+			}
998
+		}
999
+		// only recalculate totals if something changed
1000
+		if ($deleted || $updates) {
1001
+			$total_line_item->recalculate_total_including_taxes($update_txn_status);
1002
+			return true;
1003
+		}
1004
+		return false;
1005
+	}
1006
+
1007
+
1008
+	/**
1009
+	 * Ensures that taxes have been applied to the order, if not applies them.
1010
+	 * Returns the total amount of tax
1011
+	 *
1012
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1013
+	 * @return float
1014
+	 * @throws EE_Error
1015
+	 * @throws InvalidArgumentException
1016
+	 * @throws InvalidDataTypeException
1017
+	 * @throws InvalidInterfaceException
1018
+	 * @throws ReflectionException
1019
+	 */
1020
+	public static function ensure_taxes_applied($total_line_item)
1021
+	{
1022
+		$taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1023
+		if (! $taxes_subtotal->children()) {
1024
+			self::apply_taxes($total_line_item);
1025
+		}
1026
+		return $taxes_subtotal->total();
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * Deletes ALL children of the passed line item
1032
+	 *
1033
+	 * @param EE_Line_Item $parent_line_item
1034
+	 * @return bool
1035
+	 * @throws EE_Error
1036
+	 * @throws InvalidArgumentException
1037
+	 * @throws InvalidDataTypeException
1038
+	 * @throws InvalidInterfaceException
1039
+	 * @throws ReflectionException
1040
+	 */
1041
+	public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1042
+	{
1043
+		$deleted = 0;
1044
+		foreach ($parent_line_item->children() as $child_line_item) {
1045
+			if ($child_line_item instanceof EE_Line_Item) {
1046
+				$deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1047
+				if ($child_line_item->ID()) {
1048
+					$child_line_item->delete();
1049
+					unset($child_line_item);
1050
+				} else {
1051
+					$parent_line_item->delete_child_line_item($child_line_item->code());
1052
+				}
1053
+				$deleted++;
1054
+			}
1055
+		}
1056
+		return $deleted;
1057
+	}
1058
+
1059
+
1060
+	/**
1061
+	 * Deletes the line items as indicated by the line item code(s) provided,
1062
+	 * regardless of where they're found in the line item tree. Automatically
1063
+	 * re-calculates the line item totals and updates the related transaction. But
1064
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1065
+	 * should probably change because of this).
1066
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1067
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
1068
+	 *
1069
+	 * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1070
+	 * @param array|bool|string $line_item_codes
1071
+	 * @return int number of items successfully removed
1072
+	 * @throws EE_Error
1073
+	 */
1074
+	public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1075
+	{
1076
+
1077
+		if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1078
+			EE_Error::doing_it_wrong(
1079
+				'EEH_Line_Item::delete_items',
1080
+				esc_html__(
1081
+					'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1082
+					'event_espresso'
1083
+				),
1084
+				'4.6.18'
1085
+			);
1086
+		}
1087
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1088
+
1089
+		// check if only a single line_item_id was passed
1090
+		if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1091
+			// place single line_item_id in an array to appear as multiple line_item_ids
1092
+			$line_item_codes = array($line_item_codes);
1093
+		}
1094
+		$removals = 0;
1095
+		// cycle thru line_item_ids
1096
+		foreach ($line_item_codes as $line_item_id) {
1097
+			$removals += $total_line_item->delete_child_line_item($line_item_id);
1098
+		}
1099
+
1100
+		if ($removals > 0) {
1101
+			$total_line_item->recalculate_taxes_and_tax_total();
1102
+			return $removals;
1103
+		} else {
1104
+			return false;
1105
+		}
1106
+	}
1107
+
1108
+
1109
+	/**
1110
+	 * Overwrites the previous tax by clearing out the old taxes, and creates a new
1111
+	 * tax and updates the total line item accordingly
1112
+	 *
1113
+	 * @param EE_Line_Item $total_line_item
1114
+	 * @param float        $amount
1115
+	 * @param string       $name
1116
+	 * @param string       $description
1117
+	 * @param string       $code
1118
+	 * @param boolean      $add_to_existing_line_item
1119
+	 *                          if true, and a duplicate line item with the same code is found,
1120
+	 *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1121
+	 * @return EE_Line_Item the new tax line item created
1122
+	 * @throws EE_Error
1123
+	 * @throws InvalidArgumentException
1124
+	 * @throws InvalidDataTypeException
1125
+	 * @throws InvalidInterfaceException
1126
+	 * @throws ReflectionException
1127
+	 */
1128
+	public static function set_total_tax_to(
1129
+		EE_Line_Item $total_line_item,
1130
+		$amount,
1131
+		$name = null,
1132
+		$description = null,
1133
+		$code = null,
1134
+		$add_to_existing_line_item = false
1135
+	) {
1136
+		$tax_subtotal = self::get_taxes_subtotal($total_line_item);
1137
+		$taxable_total = $total_line_item->taxable_total();
1138
+
1139
+		if ($add_to_existing_line_item) {
1140
+			$new_tax = $tax_subtotal->get_child_line_item($code);
1141
+			EEM_Line_Item::instance()->delete(
1142
+				array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
1143
+			);
1144
+		} else {
1145
+			$new_tax = null;
1146
+			$tax_subtotal->delete_children_line_items();
1147
+		}
1148
+		if ($new_tax) {
1149
+			$new_tax->set_total($new_tax->total() + $amount);
1150
+			$new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1151
+		} else {
1152
+			// no existing tax item. Create it
1153
+			$new_tax = EE_Line_Item::new_instance(array(
1154
+				'TXN_ID'      => $total_line_item->TXN_ID(),
1155
+				'LIN_name'    => $name ? $name : esc_html__('Tax', 'event_espresso'),
1156
+				'LIN_desc'    => $description ? $description : '',
1157
+				'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1158
+				'LIN_total'   => $amount,
1159
+				'LIN_parent'  => $tax_subtotal->ID(),
1160
+				'LIN_type'    => EEM_Line_Item::type_tax,
1161
+				'LIN_code'    => $code,
1162
+			));
1163
+		}
1164
+
1165
+		$new_tax = apply_filters(
1166
+			'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1167
+			$new_tax,
1168
+			$total_line_item
1169
+		);
1170
+		$new_tax->save();
1171
+		$tax_subtotal->set_total($new_tax->total());
1172
+		$tax_subtotal->save();
1173
+		$total_line_item->recalculate_total_including_taxes();
1174
+		return $new_tax;
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Makes all the line items which are children of $line_item taxable (or not).
1180
+	 * Does NOT save the line items
1181
+	 *
1182
+	 * @param EE_Line_Item $line_item
1183
+	 * @param boolean      $taxable
1184
+	 * @param string       $code_substring_for_whitelist if this string is part of the line item's code
1185
+	 *                                                   it will be whitelisted (ie, except from becoming taxable)
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	public static function set_line_items_taxable(
1189
+		EE_Line_Item $line_item,
1190
+		$taxable = true,
1191
+		$code_substring_for_whitelist = null
1192
+	) {
1193
+		$whitelisted = false;
1194
+		if ($code_substring_for_whitelist !== null) {
1195
+			$whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1196
+		}
1197
+		if (! $whitelisted && $line_item->is_line_item()) {
1198
+			$line_item->set_is_taxable($taxable);
1199
+		}
1200
+		foreach ($line_item->children() as $child_line_item) {
1201
+			EEH_Line_Item::set_line_items_taxable(
1202
+				$child_line_item,
1203
+				$taxable,
1204
+				$code_substring_for_whitelist
1205
+			);
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Gets all descendants that are event subtotals
1212
+	 *
1213
+	 * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1214
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1215
+	 * @return EE_Line_Item[]
1216
+	 * @throws EE_Error
1217
+	 */
1218
+	public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1219
+	{
1220
+		return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * Gets all descendants subtotals that match the supplied object type
1226
+	 *
1227
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1228
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1229
+	 * @param string       $obj_type
1230
+	 * @return EE_Line_Item[]
1231
+	 * @throws EE_Error
1232
+	 */
1233
+	public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1234
+	{
1235
+		return self::_get_descendants_by_type_and_object_type(
1236
+			$parent_line_item,
1237
+			EEM_Line_Item::type_sub_total,
1238
+			$obj_type
1239
+		);
1240
+	}
1241
+
1242
+
1243
+	/**
1244
+	 * Gets all descendants that are tickets
1245
+	 *
1246
+	 * @uses  EEH_Line_Item::get_line_items_of_object_type()
1247
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1248
+	 * @return EE_Line_Item[]
1249
+	 * @throws EE_Error
1250
+	 */
1251
+	public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1252
+	{
1253
+		return self::get_line_items_of_object_type(
1254
+			$parent_line_item,
1255
+			EEM_Line_Item::OBJ_TYPE_TICKET
1256
+		);
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * Gets all descendants subtotals that match the supplied object type
1262
+	 *
1263
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1264
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1265
+	 * @param string       $obj_type
1266
+	 * @return EE_Line_Item[]
1267
+	 * @throws EE_Error
1268
+	 */
1269
+	public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1270
+	{
1271
+		return self::_get_descendants_by_type_and_object_type(
1272
+			$parent_line_item,
1273
+			EEM_Line_Item::type_line_item,
1274
+			$obj_type
1275
+		);
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1281
+	 *
1282
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1283
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1284
+	 * @return EE_Line_Item[]
1285
+	 * @throws EE_Error
1286
+	 */
1287
+	public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1288
+	{
1289
+		return EEH_Line_Item::get_descendants_of_type(
1290
+			$parent_line_item,
1291
+			EEM_Line_Item::type_tax
1292
+		);
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Gets all the real items purchased which are children of this item
1298
+	 *
1299
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1300
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1301
+	 * @return EE_Line_Item[]
1302
+	 * @throws EE_Error
1303
+	 */
1304
+	public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1305
+	{
1306
+		return EEH_Line_Item::get_descendants_of_type(
1307
+			$parent_line_item,
1308
+			EEM_Line_Item::type_line_item
1309
+		);
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * Gets all descendants of supplied line item that match the supplied line item type
1315
+	 *
1316
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1317
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1318
+	 * @param string       $line_item_type   one of the EEM_Line_Item constants
1319
+	 * @return EE_Line_Item[]
1320
+	 * @throws EE_Error
1321
+	 */
1322
+	public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1323
+	{
1324
+		return self::_get_descendants_by_type_and_object_type(
1325
+			$parent_line_item,
1326
+			$line_item_type,
1327
+			null
1328
+		);
1329
+	}
1330
+
1331
+
1332
+	/**
1333
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1334
+	 * as well
1335
+	 *
1336
+	 * @param EE_Line_Item  $parent_line_item - the line item to find descendants of
1337
+	 * @param string        $line_item_type   one of the EEM_Line_Item constants
1338
+	 * @param string | NULL $obj_type         object model class name (minus prefix) or NULL to ignore object type when
1339
+	 *                                        searching
1340
+	 * @return EE_Line_Item[]
1341
+	 * @throws EE_Error
1342
+	 */
1343
+	protected static function _get_descendants_by_type_and_object_type(
1344
+		EE_Line_Item $parent_line_item,
1345
+		$line_item_type,
1346
+		$obj_type = null
1347
+	) {
1348
+		$objects = array();
1349
+		foreach ($parent_line_item->children() as $child_line_item) {
1350
+			if ($child_line_item instanceof EE_Line_Item) {
1351
+				if ($child_line_item->type() === $line_item_type
1352
+					&& (
1353
+						$child_line_item->OBJ_type() === $obj_type || $obj_type === null
1354
+					)
1355
+				) {
1356
+					$objects[] = $child_line_item;
1357
+				} else {
1358
+					// go-through-all-its children looking for more matches
1359
+					$objects = array_merge(
1360
+						$objects,
1361
+						self::_get_descendants_by_type_and_object_type(
1362
+							$child_line_item,
1363
+							$line_item_type,
1364
+							$obj_type
1365
+						)
1366
+					);
1367
+				}
1368
+			}
1369
+		}
1370
+		return $objects;
1371
+	}
1372
+
1373
+
1374
+	/**
1375
+	 * Gets all descendants subtotals that match the supplied object type
1376
+	 *
1377
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1378
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1379
+	 * @param string       $OBJ_type         object type (like Event)
1380
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1381
+	 * @return EE_Line_Item[]
1382
+	 * @throws EE_Error
1383
+	 */
1384
+	public static function get_line_items_by_object_type_and_IDs(
1385
+		EE_Line_Item $parent_line_item,
1386
+		$OBJ_type = '',
1387
+		$OBJ_IDs = array()
1388
+	) {
1389
+		return self::_get_descendants_by_object_type_and_object_ID(
1390
+			$parent_line_item,
1391
+			$OBJ_type,
1392
+			$OBJ_IDs
1393
+		);
1394
+	}
1395
+
1396
+
1397
+	/**
1398
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1399
+	 * as well
1400
+	 *
1401
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1402
+	 * @param string       $OBJ_type         object type (like Event)
1403
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1404
+	 * @return EE_Line_Item[]
1405
+	 * @throws EE_Error
1406
+	 */
1407
+	protected static function _get_descendants_by_object_type_and_object_ID(
1408
+		EE_Line_Item $parent_line_item,
1409
+		$OBJ_type,
1410
+		$OBJ_IDs
1411
+	) {
1412
+		$objects = array();
1413
+		foreach ($parent_line_item->children() as $child_line_item) {
1414
+			if ($child_line_item instanceof EE_Line_Item) {
1415
+				if ($child_line_item->OBJ_type() === $OBJ_type
1416
+					&& is_array($OBJ_IDs)
1417
+					&& in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1418
+				) {
1419
+					$objects[] = $child_line_item;
1420
+				} else {
1421
+					// go-through-all-its children looking for more matches
1422
+					$objects = array_merge(
1423
+						$objects,
1424
+						self::_get_descendants_by_object_type_and_object_ID(
1425
+							$child_line_item,
1426
+							$OBJ_type,
1427
+							$OBJ_IDs
1428
+						)
1429
+					);
1430
+				}
1431
+			}
1432
+		}
1433
+		return $objects;
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * Uses a breadth-first-search in order to find the nearest descendant of
1439
+	 * the specified type and returns it, else NULL
1440
+	 *
1441
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1442
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1443
+	 * @param string       $type             like one of the EEM_Line_Item::type_*
1444
+	 * @return EE_Line_Item
1445
+	 * @throws EE_Error
1446
+	 * @throws InvalidArgumentException
1447
+	 * @throws InvalidDataTypeException
1448
+	 * @throws InvalidInterfaceException
1449
+	 * @throws ReflectionException
1450
+	 */
1451
+	public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1452
+	{
1453
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1454
+	}
1455
+
1456
+
1457
+	/**
1458
+	 * Uses a breadth-first-search in order to find the nearest descendant
1459
+	 * having the specified LIN_code and returns it, else NULL
1460
+	 *
1461
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1462
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1463
+	 * @param string       $code             any value used for LIN_code
1464
+	 * @return EE_Line_Item
1465
+	 * @throws EE_Error
1466
+	 * @throws InvalidArgumentException
1467
+	 * @throws InvalidDataTypeException
1468
+	 * @throws InvalidInterfaceException
1469
+	 * @throws ReflectionException
1470
+	 */
1471
+	public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1472
+	{
1473
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1474
+	}
1475
+
1476
+
1477
+	/**
1478
+	 * Uses a breadth-first-search in order to find the nearest descendant
1479
+	 * having the specified LIN_code and returns it, else NULL
1480
+	 *
1481
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1482
+	 * @param string       $search_field     name of EE_Line_Item property
1483
+	 * @param string       $value            any value stored in $search_field
1484
+	 * @return EE_Line_Item
1485
+	 * @throws EE_Error
1486
+	 * @throws InvalidArgumentException
1487
+	 * @throws InvalidDataTypeException
1488
+	 * @throws InvalidInterfaceException
1489
+	 * @throws ReflectionException
1490
+	 */
1491
+	protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1492
+	{
1493
+		foreach ($parent_line_item->children() as $child) {
1494
+			if ($child->get($search_field) == $value) {
1495
+				return $child;
1496
+			}
1497
+		}
1498
+		foreach ($parent_line_item->children() as $child) {
1499
+			$descendant_found = self::_get_nearest_descendant(
1500
+				$child,
1501
+				$search_field,
1502
+				$value
1503
+			);
1504
+			if ($descendant_found) {
1505
+				return $descendant_found;
1506
+			}
1507
+		}
1508
+		return null;
1509
+	}
1510
+
1511
+
1512
+	/**
1513
+	 * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1514
+	 * else recursively walks up the line item tree until a parent of type total is found,
1515
+	 *
1516
+	 * @param EE_Line_Item $line_item
1517
+	 * @return EE_Line_Item
1518
+	 * @throws EE_Error
1519
+	 */
1520
+	public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1521
+	{
1522
+		if ($line_item->TXN_ID()) {
1523
+			$total_line_item = $line_item->transaction()->total_line_item(false);
1524
+			if ($total_line_item instanceof EE_Line_Item) {
1525
+				return $total_line_item;
1526
+			}
1527
+		} else {
1528
+			$line_item_parent = $line_item->parent();
1529
+			if ($line_item_parent instanceof EE_Line_Item) {
1530
+				if ($line_item_parent->is_total()) {
1531
+					return $line_item_parent;
1532
+				}
1533
+				return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1534
+			}
1535
+		}
1536
+		throw new EE_Error(
1537
+			sprintf(
1538
+				esc_html__(
1539
+					'A valid grand total for line item %1$d was not found.',
1540
+					'event_espresso'
1541
+				),
1542
+				$line_item->ID()
1543
+			)
1544
+		);
1545
+	}
1546
+
1547
+
1548
+	/**
1549
+	 * Prints out a representation of the line item tree
1550
+	 *
1551
+	 * @param EE_Line_Item $line_item
1552
+	 * @param int          $indentation
1553
+	 * @return void
1554
+	 * @throws EE_Error
1555
+	 */
1556
+	public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1557
+	{
1558
+		echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1559
+		if (! $indentation) {
1560
+			echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1561
+		}
1562
+		for ($i = 0; $i < $indentation; $i++) {
1563
+			echo '. ';
1564
+		}
1565
+		$breakdown = '';
1566
+		if ($line_item->is_line_item()) {
1567
+			if ($line_item->is_percent()) {
1568
+				$breakdown = "{$line_item->percent()}%";
1569
+			} else {
1570
+				$breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1571
+			}
1572
+		}
1573
+		echo $line_item->name();
1574
+		echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1575
+		echo '$' . (string) $line_item->total();
1576
+		if ($breakdown) {
1577
+			echo " ( {$breakdown} )";
1578
+		}
1579
+		if ($line_item->is_taxable()) {
1580
+			echo '  * taxable';
1581
+		}
1582
+		if ($line_item->children()) {
1583
+			foreach ($line_item->children() as $child) {
1584
+				self::visualize($child, $indentation + 1);
1585
+			}
1586
+		}
1587
+	}
1588
+
1589
+
1590
+	/**
1591
+	 * Calculates the registration's final price, taking into account that they
1592
+	 * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1593
+	 * and receive a portion of any transaction-wide discounts.
1594
+	 * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1595
+	 * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1596
+	 * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1597
+	 * and brent's final price should be $5.50.
1598
+	 * In order to do this, we basically need to traverse the line item tree calculating
1599
+	 * the running totals (just as if we were recalculating the total), but when we identify
1600
+	 * regular line items, we need to keep track of their share of the grand total.
1601
+	 * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1602
+	 * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1603
+	 * when there are non-taxable items; otherwise they would be the same)
1604
+	 *
1605
+	 * @param EE_Line_Item $line_item
1606
+	 * @param array        $billable_ticket_quantities  array of EE_Ticket IDs and their corresponding quantity that
1607
+	 *                                                  can be included in price calculations at this moment
1608
+	 * @return array        keys are line items for tickets IDs and values are their share of the running total,
1609
+	 *                                                  plus the key 'total', and 'taxable' which also has keys of all
1610
+	 *                                                  the ticket IDs.
1611
+	 *                                                  Eg array(
1612
+	 *                                                      12 => 4.3
1613
+	 *                                                      23 => 8.0
1614
+	 *                                                      'total' => 16.6,
1615
+	 *                                                      'taxable' => array(
1616
+	 *                                                          12 => 10,
1617
+	 *                                                          23 => 4
1618
+	 *                                                      ).
1619
+	 *                                                  So to find which registrations have which final price, we need
1620
+	 *                                                  to find which line item is theirs, which can be done with
1621
+	 *                                                  `EEM_Line_Item::instance()->get_line_item_for_registration(
1622
+	 *                                                  $registration );`
1623
+	 * @throws EE_Error
1624
+	 * @throws InvalidArgumentException
1625
+	 * @throws InvalidDataTypeException
1626
+	 * @throws InvalidInterfaceException
1627
+	 * @throws ReflectionException
1628
+	 */
1629
+	public static function calculate_reg_final_prices_per_line_item(
1630
+		EE_Line_Item $line_item,
1631
+		$billable_ticket_quantities = array()
1632
+	) {
1633
+		$running_totals = [
1634
+			'total'   => 0,
1635
+			'taxable' => ['total' => 0]
1636
+		];
1637
+		foreach ($line_item->children() as $child_line_item) {
1638
+			switch ($child_line_item->type()) {
1639
+				case EEM_Line_Item::type_sub_total:
1640
+					$running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1641
+						$child_line_item,
1642
+						$billable_ticket_quantities
1643
+					);
1644
+					// combine arrays but preserve numeric keys
1645
+					$running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1646
+					$running_totals['total'] += $running_totals_from_subtotal['total'];
1647
+					$running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1648
+					break;
1649
+
1650
+				case EEM_Line_Item::type_tax_sub_total:
1651
+					// find how much the taxes percentage is
1652
+					if ($child_line_item->percent() !== 0) {
1653
+						$tax_percent_decimal = $child_line_item->percent() / 100;
1654
+					} else {
1655
+						$tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1656
+					}
1657
+					// and apply to all the taxable totals, and add to the pretax totals
1658
+					foreach ($running_totals as $line_item_id => $this_running_total) {
1659
+						// "total" and "taxable" array key is an exception
1660
+						if ($line_item_id === 'taxable') {
1661
+							continue;
1662
+						}
1663
+						$taxable_total = $running_totals['taxable'][ $line_item_id ];
1664
+						$running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1665
+					}
1666
+					break;
1667
+
1668
+				case EEM_Line_Item::type_line_item:
1669
+					// ticket line items or ????
1670
+					if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1671
+						// kk it's a ticket
1672
+						if (isset($running_totals[ $child_line_item->ID() ])) {
1673
+							// huh? that shouldn't happen.
1674
+							$running_totals['total'] += $child_line_item->total();
1675
+						} else {
1676
+							// its not in our running totals yet. great.
1677
+							if ($child_line_item->is_taxable()) {
1678
+								$taxable_amount = $child_line_item->unit_price();
1679
+							} else {
1680
+								$taxable_amount = 0;
1681
+							}
1682
+							// are we only calculating totals for some tickets?
1683
+							if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1684
+								$quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1685
+								$running_totals[ $child_line_item->ID() ] = $quantity
1686
+									? $child_line_item->unit_price()
1687
+									: 0;
1688
+								$running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1689
+									? $taxable_amount
1690
+									: 0;
1691
+							} else {
1692
+								$quantity = $child_line_item->quantity();
1693
+								$running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1694
+								$running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1695
+							}
1696
+							$running_totals['taxable']['total'] += $taxable_amount * $quantity;
1697
+							$running_totals['total'] += $child_line_item->unit_price() * $quantity;
1698
+						}
1699
+					} else {
1700
+						// it's some other type of item added to the cart
1701
+						// it should affect the running totals
1702
+						// basically we want to convert it into a PERCENT modifier. Because
1703
+						// more clearly affect all registration's final price equally
1704
+						$line_items_percent_of_running_total = $running_totals['total'] > 0
1705
+							? ($child_line_item->total() / $running_totals['total']) + 1
1706
+							: 1;
1707
+						foreach ($running_totals as $line_item_id => $this_running_total) {
1708
+							// the "taxable" array key is an exception
1709
+							if ($line_item_id === 'taxable') {
1710
+								continue;
1711
+							}
1712
+							// update the running totals
1713
+							// yes this actually even works for the running grand total!
1714
+							$running_totals[ $line_item_id ] =
1715
+								$line_items_percent_of_running_total * $this_running_total;
1716
+
1717
+							if ($child_line_item->is_taxable()) {
1718
+								$running_totals['taxable'][ $line_item_id ] =
1719
+									$line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1720
+							}
1721
+						}
1722
+					}
1723
+					break;
1724
+			}
1725
+		}
1726
+		return $running_totals;
1727
+	}
1728
+
1729
+
1730
+	/**
1731
+	 * @param EE_Line_Item $total_line_item
1732
+	 * @param EE_Line_Item $ticket_line_item
1733
+	 * @return float | null
1734
+	 * @throws EE_Error
1735
+	 * @throws InvalidArgumentException
1736
+	 * @throws InvalidDataTypeException
1737
+	 * @throws InvalidInterfaceException
1738
+	 * @throws OutOfRangeException
1739
+	 * @throws ReflectionException
1740
+	 */
1741
+	public static function calculate_final_price_for_ticket_line_item(
1742
+		EE_Line_Item $total_line_item,
1743
+		EE_Line_Item $ticket_line_item
1744
+	) {
1745
+		static $final_prices_per_ticket_line_item = array();
1746
+		if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1747
+			$final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1748
+				$total_line_item
1749
+			);
1750
+		}
1751
+		// ok now find this new registration's final price
1752
+		if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1753
+			return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1754
+		}
1755
+		$message = sprintf(
1756
+			esc_html__(
1757
+				'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1758
+				'event_espresso'
1759
+			),
1760
+			$ticket_line_item->ID()
1761
+		);
1762
+		if (WP_DEBUG) {
1763
+			$message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1764
+			throw new OutOfRangeException($message);
1765
+		}
1766
+		EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1767
+		return null;
1768
+	}
1769
+
1770
+
1771
+	/**
1772
+	 * Creates a duplicate of the line item tree, except only includes billable items
1773
+	 * and the portion of line items attributed to billable things
1774
+	 *
1775
+	 * @param EE_Line_Item      $line_item
1776
+	 * @param EE_Registration[] $registrations
1777
+	 * @return EE_Line_Item
1778
+	 * @throws EE_Error
1779
+	 * @throws InvalidArgumentException
1780
+	 * @throws InvalidDataTypeException
1781
+	 * @throws InvalidInterfaceException
1782
+	 * @throws ReflectionException
1783
+	 */
1784
+	public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1785
+	{
1786
+		$copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1787
+		foreach ($line_item->children() as $child_li) {
1788
+			$copy_li->add_child_line_item(
1789
+				EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1790
+			);
1791
+		}
1792
+		// if this is the grand total line item, make sure the totals all add up
1793
+		// (we could have duplicated this logic AS we copied the line items, but
1794
+		// it seems DRYer this way)
1795
+		if ($copy_li->type() === EEM_Line_Item::type_total) {
1796
+			$copy_li->recalculate_total_including_taxes();
1797
+		}
1798
+		return $copy_li;
1799
+	}
1800
+
1801
+
1802
+	/**
1803
+	 * Creates a new, unsaved line item from $line_item that factors in the
1804
+	 * number of billable registrations on $registrations.
1805
+	 *
1806
+	 * @param EE_Line_Item      $line_item
1807
+	 * @param EE_Registration[] $registrations
1808
+	 * @return EE_Line_Item
1809
+	 * @throws EE_Error
1810
+	 * @throws InvalidArgumentException
1811
+	 * @throws InvalidDataTypeException
1812
+	 * @throws InvalidInterfaceException
1813
+	 * @throws ReflectionException
1814
+	 */
1815
+	public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1816
+	{
1817
+		$new_li_fields = $line_item->model_field_array();
1818
+		if ($line_item->type() === EEM_Line_Item::type_line_item &&
1819
+			$line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1820
+		) {
1821
+			$count = 0;
1822
+			foreach ($registrations as $registration) {
1823
+				if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1824
+					in_array(
1825
+						$registration->status_ID(),
1826
+						EEM_Registration::reg_statuses_that_allow_payment(),
1827
+						true
1828
+					)
1829
+				) {
1830
+					$count++;
1831
+				}
1832
+			}
1833
+			$new_li_fields['LIN_quantity'] = $count;
1834
+		}
1835
+		// don't set the total. We'll leave that up to the code that calculates it
1836
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1837
+		return EE_Line_Item::new_instance($new_li_fields);
1838
+	}
1839
+
1840
+
1841
+	/**
1842
+	 * Returns a modified line item tree where all the subtotals which have a total of 0
1843
+	 * are removed, and line items with a quantity of 0
1844
+	 *
1845
+	 * @param EE_Line_Item $line_item |null
1846
+	 * @return EE_Line_Item|null
1847
+	 * @throws EE_Error
1848
+	 * @throws InvalidArgumentException
1849
+	 * @throws InvalidDataTypeException
1850
+	 * @throws InvalidInterfaceException
1851
+	 * @throws ReflectionException
1852
+	 */
1853
+	public static function non_empty_line_items(EE_Line_Item $line_item)
1854
+	{
1855
+		$copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1856
+		if ($copied_li === null) {
1857
+			return null;
1858
+		}
1859
+		// if this is an event subtotal, we want to only include it if it
1860
+		// has a non-zero total and at least one ticket line item child
1861
+		$ticket_children = 0;
1862
+		foreach ($line_item->children() as $child_li) {
1863
+			$child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1864
+			if ($child_li_copy !== null) {
1865
+				$copied_li->add_child_line_item($child_li_copy);
1866
+				if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1867
+					$child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1868
+				) {
1869
+					$ticket_children++;
1870
+				}
1871
+			}
1872
+		}
1873
+		// if this is an event subtotal with NO ticket children
1874
+		// we basically want to ignore it
1875
+		if ($ticket_children === 0
1876
+			&& $line_item->type() === EEM_Line_Item::type_sub_total
1877
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
1878
+			&& $line_item->total() === 0
1879
+		) {
1880
+			return null;
1881
+		}
1882
+		return $copied_li;
1883
+	}
1884
+
1885
+
1886
+	/**
1887
+	 * Creates a new, unsaved line item, but if it's a ticket line item
1888
+	 * with a total of 0, or a subtotal of 0, returns null instead
1889
+	 *
1890
+	 * @param EE_Line_Item $line_item
1891
+	 * @return EE_Line_Item
1892
+	 * @throws EE_Error
1893
+	 * @throws InvalidArgumentException
1894
+	 * @throws InvalidDataTypeException
1895
+	 * @throws InvalidInterfaceException
1896
+	 * @throws ReflectionException
1897
+	 */
1898
+	public static function non_empty_line_item(EE_Line_Item $line_item)
1899
+	{
1900
+		if ($line_item->type() === EEM_Line_Item::type_line_item
1901
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1902
+			&& $line_item->quantity() === 0
1903
+		) {
1904
+			return null;
1905
+		}
1906
+		$new_li_fields = $line_item->model_field_array();
1907
+		// don't set the total. We'll leave that up to the code that calculates it
1908
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1909
+		return EE_Line_Item::new_instance($new_li_fields);
1910
+	}
1911
+
1912
+
1913
+	/**
1914
+	 * Cycles through all of the ticket line items for the supplied total line item
1915
+	 * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
1916
+	 *
1917
+	 * @param EE_Line_Item $total_line_item
1918
+	 * @since 4.9.79.p
1919
+	 * @throws EE_Error
1920
+	 * @throws InvalidArgumentException
1921
+	 * @throws InvalidDataTypeException
1922
+	 * @throws InvalidInterfaceException
1923
+	 * @throws ReflectionException
1924
+	 */
1925
+	public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
1926
+	{
1927
+		$ticket_line_items = self::get_ticket_line_items($total_line_item);
1928
+		foreach ($ticket_line_items as $ticket_line_item) {
1929
+			if ($ticket_line_item instanceof EE_Line_Item
1930
+				&& $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1931
+			) {
1932
+				$ticket = $ticket_line_item->ticket();
1933
+				if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
1934
+					$ticket_line_item->set_is_taxable($ticket->taxable());
1935
+					$ticket_line_item->save();
1936
+				}
1937
+			}
1938
+		}
1939
+	}
1940
+
1941
+
1942
+
1943
+	/**************************************** @DEPRECATED METHODS *************************************** */
1944
+	/**
1945
+	 * @deprecated
1946
+	 * @param EE_Line_Item $total_line_item
1947
+	 * @return EE_Line_Item
1948
+	 * @throws EE_Error
1949
+	 * @throws InvalidArgumentException
1950
+	 * @throws InvalidDataTypeException
1951
+	 * @throws InvalidInterfaceException
1952
+	 * @throws ReflectionException
1953
+	 */
1954
+	public static function get_items_subtotal(EE_Line_Item $total_line_item)
1955
+	{
1956
+		EE_Error::doing_it_wrong(
1957
+			'EEH_Line_Item::get_items_subtotal()',
1958
+			sprintf(
1959
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1960
+				'EEH_Line_Item::get_pre_tax_subtotal()'
1961
+			),
1962
+			'4.6.0'
1963
+		);
1964
+		return self::get_pre_tax_subtotal($total_line_item);
1965
+	}
1966
+
1967
+
1968
+	/**
1969
+	 * @deprecated
1970
+	 * @param EE_Transaction $transaction
1971
+	 * @return EE_Line_Item
1972
+	 * @throws EE_Error
1973
+	 * @throws InvalidArgumentException
1974
+	 * @throws InvalidDataTypeException
1975
+	 * @throws InvalidInterfaceException
1976
+	 * @throws ReflectionException
1977
+	 */
1978
+	public static function create_default_total_line_item($transaction = null)
1979
+	{
1980
+		EE_Error::doing_it_wrong(
1981
+			'EEH_Line_Item::create_default_total_line_item()',
1982
+			sprintf(
1983
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1984
+				'EEH_Line_Item::create_total_line_item()'
1985
+			),
1986
+			'4.6.0'
1987
+		);
1988
+		return self::create_total_line_item($transaction);
1989
+	}
1990
+
1991
+
1992
+	/**
1993
+	 * @deprecated
1994
+	 * @param EE_Line_Item   $total_line_item
1995
+	 * @param EE_Transaction $transaction
1996
+	 * @return EE_Line_Item
1997
+	 * @throws EE_Error
1998
+	 * @throws InvalidArgumentException
1999
+	 * @throws InvalidDataTypeException
2000
+	 * @throws InvalidInterfaceException
2001
+	 * @throws ReflectionException
2002
+	 */
2003
+	public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2004
+	{
2005
+		EE_Error::doing_it_wrong(
2006
+			'EEH_Line_Item::create_default_tickets_subtotal()',
2007
+			sprintf(
2008
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2009
+				'EEH_Line_Item::create_pre_tax_subtotal()'
2010
+			),
2011
+			'4.6.0'
2012
+		);
2013
+		return self::create_pre_tax_subtotal($total_line_item, $transaction);
2014
+	}
2015
+
2016
+
2017
+	/**
2018
+	 * @deprecated
2019
+	 * @param EE_Line_Item   $total_line_item
2020
+	 * @param EE_Transaction $transaction
2021
+	 * @return EE_Line_Item
2022
+	 * @throws EE_Error
2023
+	 * @throws InvalidArgumentException
2024
+	 * @throws InvalidDataTypeException
2025
+	 * @throws InvalidInterfaceException
2026
+	 * @throws ReflectionException
2027
+	 */
2028
+	public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2029
+	{
2030
+		EE_Error::doing_it_wrong(
2031
+			'EEH_Line_Item::create_default_taxes_subtotal()',
2032
+			sprintf(
2033
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2034
+				'EEH_Line_Item::create_taxes_subtotal()'
2035
+			),
2036
+			'4.6.0'
2037
+		);
2038
+		return self::create_taxes_subtotal($total_line_item, $transaction);
2039
+	}
2040
+
2041
+
2042
+	/**
2043
+	 * @deprecated
2044
+	 * @param EE_Line_Item   $total_line_item
2045
+	 * @param EE_Transaction $transaction
2046
+	 * @return EE_Line_Item
2047
+	 * @throws EE_Error
2048
+	 * @throws InvalidArgumentException
2049
+	 * @throws InvalidDataTypeException
2050
+	 * @throws InvalidInterfaceException
2051
+	 * @throws ReflectionException
2052
+	 */
2053
+	public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2054
+	{
2055
+		EE_Error::doing_it_wrong(
2056
+			'EEH_Line_Item::create_default_event_subtotal()',
2057
+			sprintf(
2058
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2059
+				'EEH_Line_Item::create_event_subtotal()'
2060
+			),
2061
+			'4.6.0'
2062
+		);
2063
+		return self::create_event_subtotal($total_line_item, $transaction);
2064
+	}
2065 2065
 }
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
      */
139 139
     public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140 140
     {
141
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
141
+        if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142 142
             throw new EE_Error(
143 143
                 sprintf(
144 144
                     esc_html__(
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
         // either increment the qty for an existing ticket
154 154
         $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155 155
         // or add a new one
156
-        if (! $line_item instanceof EE_Line_Item) {
156
+        if ( ! $line_item instanceof EE_Line_Item) {
157 157
             $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158 158
         }
159 159
         $total_line_item->recalculate_total_including_taxes();
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
      */
215 215
     public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
216 216
     {
217
-        if (! $line_item->is_percent()) {
217
+        if ( ! $line_item->is_percent()) {
218 218
             $qty += $line_item->quantity();
219 219
             $line_item->set_quantity($qty);
220 220
             $line_item->set_total($line_item->unit_price() * $qty);
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
      */
244 244
     public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
245 245
     {
246
-        if (! $line_item->is_percent()) {
246
+        if ( ! $line_item->is_percent()) {
247 247
             $qty = $line_item->quantity() - $qty;
248 248
             $qty = max($qty, 0);
249 249
             $line_item->set_quantity($qty);
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
      */
273 273
     public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
274 274
     {
275
-        if (! $line_item->is_percent()) {
275
+        if ( ! $line_item->is_percent()) {
276 276
             $line_item->set_quantity($new_quantity);
277 277
             $line_item->set_total($line_item->unit_price() * $new_quantity);
278 278
             $line_item->save();
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
         // add $ticket to cart
313 313
         $line_item = EE_Line_Item::new_instance(array(
314 314
             'LIN_name'       => $ticket->name(),
315
-            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
315
+            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description().' '.$event : $event,
316 316
             'LIN_unit_price' => $ticket->price(),
317 317
             'LIN_quantity'   => $qty,
318 318
             'LIN_is_taxable' => $ticket->taxable(),
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
                         'event_espresso'
463 463
                     ),
464 464
                     $ticket_line_item->name(),
465
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
465
+                    current_time(get_option('date_format').' '.get_option('time_format'))
466 466
                 ),
467 467
                 'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
468 468
                 'LIN_quantity'   => $qty,
@@ -524,7 +524,7 @@  discard block
 block discarded – undo
524 524
         );
525 525
         $cancellation_line_item = reset($cancellation_line_item);
526 526
         // verify that this ticket was indeed previously cancelled
527
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
527
+        if ( ! $cancellation_line_item instanceof EE_Line_Item) {
528 528
             return false;
529 529
         }
530 530
         if ($cancellation_line_item->quantity() > $qty) {
@@ -729,7 +729,7 @@  discard block
 block discarded – undo
729 729
             'LIN_code'  => 'taxes',
730 730
             'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
731 731
             'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
732
-            'LIN_order' => 1000,// this should always come last
732
+            'LIN_order' => 1000, // this should always come last
733 733
         ));
734 734
         $tax_line_item = apply_filters(
735 735
             'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
@@ -785,7 +785,7 @@  discard block
 block discarded – undo
785 785
      */
786 786
     public static function get_event_code($event)
787 787
     {
788
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
788
+        return 'event-'.($event instanceof EE_Event ? $event->ID() : '0');
789 789
     }
790 790
 
791 791
 
@@ -834,7 +834,7 @@  discard block
 block discarded – undo
834 834
     public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
835 835
     {
836 836
         $first_datetime = $ticket->first_datetime();
837
-        if (! $first_datetime instanceof EE_Datetime) {
837
+        if ( ! $first_datetime instanceof EE_Datetime) {
838 838
             throw new EE_Error(
839 839
                 sprintf(
840 840
                     __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
@@ -843,7 +843,7 @@  discard block
 block discarded – undo
843 843
             );
844 844
         }
845 845
         $event = $first_datetime->event();
846
-        if (! $event instanceof EE_Event) {
846
+        if ( ! $event instanceof EE_Event) {
847 847
             throw new EE_Error(
848 848
                 sprintf(
849 849
                     esc_html__(
@@ -855,7 +855,7 @@  discard block
 block discarded – undo
855 855
             );
856 856
         }
857 857
         $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
858
-        if (! $events_sub_total instanceof EE_Line_Item) {
858
+        if ( ! $events_sub_total instanceof EE_Line_Item) {
859 859
             throw new EE_Error(
860 860
                 sprintf(
861 861
                     esc_html__(
@@ -891,7 +891,7 @@  discard block
 block discarded – undo
891 891
         $found = false;
892 892
         foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
893 893
             // default event subtotal, we should only ever find this the first time this method is called
894
-            if (! $event_line_item->OBJ_ID()) {
894
+            if ( ! $event_line_item->OBJ_ID()) {
895 895
                 // let's use this! but first... set the event details
896 896
                 EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
897 897
                 $found = true;
@@ -903,7 +903,7 @@  discard block
 block discarded – undo
903 903
                 break;
904 904
             }
905 905
         }
906
-        if (! $found) {
906
+        if ( ! $found) {
907 907
             // there is no event sub-total yet, so add it
908 908
             $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
909 909
             // create a new "event" subtotal below that
@@ -1020,7 +1020,7 @@  discard block
 block discarded – undo
1020 1020
     public static function ensure_taxes_applied($total_line_item)
1021 1021
     {
1022 1022
         $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1023
-        if (! $taxes_subtotal->children()) {
1023
+        if ( ! $taxes_subtotal->children()) {
1024 1024
             self::apply_taxes($total_line_item);
1025 1025
         }
1026 1026
         return $taxes_subtotal->total();
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1088 1088
 
1089 1089
         // check if only a single line_item_id was passed
1090
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1090
+        if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) {
1091 1091
             // place single line_item_id in an array to appear as multiple line_item_ids
1092 1092
             $line_item_codes = array($line_item_codes);
1093 1093
         }
@@ -1194,7 +1194,7 @@  discard block
 block discarded – undo
1194 1194
         if ($code_substring_for_whitelist !== null) {
1195 1195
             $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1196 1196
         }
1197
-        if (! $whitelisted && $line_item->is_line_item()) {
1197
+        if ( ! $whitelisted && $line_item->is_line_item()) {
1198 1198
             $line_item->set_is_taxable($taxable);
1199 1199
         }
1200 1200
         foreach ($line_item->children() as $child_line_item) {
@@ -1556,7 +1556,7 @@  discard block
 block discarded – undo
1556 1556
     public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1557 1557
     {
1558 1558
         echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1559
-        if (! $indentation) {
1559
+        if ( ! $indentation) {
1560 1560
             echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1561 1561
         }
1562 1562
         for ($i = 0; $i < $indentation; $i++) {
@@ -1567,12 +1567,12 @@  discard block
 block discarded – undo
1567 1567
             if ($line_item->is_percent()) {
1568 1568
                 $breakdown = "{$line_item->percent()}%";
1569 1569
             } else {
1570
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1570
+                $breakdown = '$'."{$line_item->unit_price()} x {$line_item->quantity()}";
1571 1571
             }
1572 1572
         }
1573 1573
         echo $line_item->name();
1574 1574
         echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1575
-        echo '$' . (string) $line_item->total();
1575
+        echo '$'.(string) $line_item->total();
1576 1576
         if ($breakdown) {
1577 1577
             echo " ( {$breakdown} )";
1578 1578
         }
@@ -1660,8 +1660,8 @@  discard block
 block discarded – undo
1660 1660
                         if ($line_item_id === 'taxable') {
1661 1661
                             continue;
1662 1662
                         }
1663
-                        $taxable_total = $running_totals['taxable'][ $line_item_id ];
1664
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1663
+                        $taxable_total = $running_totals['taxable'][$line_item_id];
1664
+                        $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal);
1665 1665
                     }
1666 1666
                     break;
1667 1667
 
@@ -1669,7 +1669,7 @@  discard block
 block discarded – undo
1669 1669
                     // ticket line items or ????
1670 1670
                     if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1671 1671
                         // kk it's a ticket
1672
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1672
+                        if (isset($running_totals[$child_line_item->ID()])) {
1673 1673
                             // huh? that shouldn't happen.
1674 1674
                             $running_totals['total'] += $child_line_item->total();
1675 1675
                         } else {
@@ -1680,18 +1680,18 @@  discard block
 block discarded – undo
1680 1680
                                 $taxable_amount = 0;
1681 1681
                             }
1682 1682
                             // are we only calculating totals for some tickets?
1683
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1684
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1685
-                                $running_totals[ $child_line_item->ID() ] = $quantity
1683
+                            if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
1684
+                                $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
1685
+                                $running_totals[$child_line_item->ID()] = $quantity
1686 1686
                                     ? $child_line_item->unit_price()
1687 1687
                                     : 0;
1688
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1688
+                                $running_totals['taxable'][$child_line_item->ID()] = $quantity
1689 1689
                                     ? $taxable_amount
1690 1690
                                     : 0;
1691 1691
                             } else {
1692 1692
                                 $quantity = $child_line_item->quantity();
1693
-                                $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1694
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1693
+                                $running_totals[$child_line_item->ID()] = $child_line_item->unit_price();
1694
+                                $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
1695 1695
                             }
1696 1696
                             $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1697 1697
                             $running_totals['total'] += $child_line_item->unit_price() * $quantity;
@@ -1711,12 +1711,12 @@  discard block
 block discarded – undo
1711 1711
                             }
1712 1712
                             // update the running totals
1713 1713
                             // yes this actually even works for the running grand total!
1714
-                            $running_totals[ $line_item_id ] =
1714
+                            $running_totals[$line_item_id] =
1715 1715
                                 $line_items_percent_of_running_total * $this_running_total;
1716 1716
 
1717 1717
                             if ($child_line_item->is_taxable()) {
1718
-                                $running_totals['taxable'][ $line_item_id ] =
1719
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1718
+                                $running_totals['taxable'][$line_item_id] =
1719
+                                    $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
1720 1720
                             }
1721 1721
                         }
1722 1722
                     }
@@ -1743,14 +1743,14 @@  discard block
 block discarded – undo
1743 1743
         EE_Line_Item $ticket_line_item
1744 1744
     ) {
1745 1745
         static $final_prices_per_ticket_line_item = array();
1746
-        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1747
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1746
+        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[$total_line_item->ID()])) {
1747
+            $final_prices_per_ticket_line_item[$total_line_item->ID()] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1748 1748
                 $total_line_item
1749 1749
             );
1750 1750
         }
1751 1751
         // ok now find this new registration's final price
1752
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1753
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1752
+        if (isset($final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()])) {
1753
+            return $final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()];
1754 1754
         }
1755 1755
         $message = sprintf(
1756 1756
             esc_html__(
@@ -1760,7 +1760,7 @@  discard block
 block discarded – undo
1760 1760
             $ticket_line_item->ID()
1761 1761
         );
1762 1762
         if (WP_DEBUG) {
1763
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1763
+            $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true);
1764 1764
             throw new OutOfRangeException($message);
1765 1765
         }
1766 1766
         EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
Please login to merge, or discard this patch.
core/services/loaders/ClassInterfaceCache.php 1 patch
Indentation   +161 added lines, -161 removed lines patch added patch discarded remove patch
@@ -17,165 +17,165 @@
 block discarded – undo
17 17
 class ClassInterfaceCache
18 18
 {
19 19
 
20
-    /**
21
-     * array of interfaces indexed by FQCNs where values are arrays of interface FQNs
22
-     *
23
-     * @var string[][] $interfaces
24
-     */
25
-    private $interfaces = array();
26
-
27
-    /**
28
-     * @type string[][] $aliases
29
-     */
30
-    protected $aliases = array();
31
-
32
-
33
-    /**
34
-     * @param string $fqn
35
-     * @return string
36
-     */
37
-    public function getFqn($fqn)
38
-    {
39
-        $fqn = $fqn instanceof FullyQualifiedName ? $fqn->string() : $fqn;
40
-        return ltrim($fqn, '\\');
41
-    }
42
-
43
-
44
-    /**
45
-     * @param string $fqn
46
-     * @return array
47
-     */
48
-    public function getInterfaces($fqn)
49
-    {
50
-        $fqn = $this->getFqn($fqn);
51
-        // have we already seen this FQCN ?
52
-        if (! array_key_exists($fqn, $this->interfaces)) {
53
-            $this->interfaces[ $fqn ] = array();
54
-            if (class_exists($fqn)) {
55
-                $this->interfaces[ $fqn ] = class_implements($fqn, false);
56
-                $this->interfaces[ $fqn ] = $this->interfaces[ $fqn ] !== false
57
-                    ? $this->interfaces[ $fqn ]
58
-                    : array();
59
-            }
60
-        }
61
-        return $this->interfaces[ $fqn ];
62
-    }
63
-
64
-
65
-    /**
66
-     * @param string $fqn
67
-     * @param string $interface
68
-     * @return bool
69
-     */
70
-    public function hasInterface($fqn, $interface)
71
-    {
72
-        $fqn        = $this->getFqn($fqn);
73
-        $interfaces = $this->getInterfaces($fqn);
74
-        return in_array($interface, $interfaces, true);
75
-    }
76
-
77
-
78
-    /**
79
-     * adds an alias for a classname
80
-     *
81
-     * @param string $fqn       the class name that should be used (concrete class to replace interface)
82
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
83
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
84
-     * @throws InvalidAliasException
85
-     */
86
-    public function addAlias($fqn, $alias, $for_class = '')
87
-    {
88
-        $fqn   = $this->getFqn($fqn);
89
-        $alias = $this->getFqn($alias);
90
-        if (strpos($alias, '\\') !== false && ! is_subclass_of($fqn, $alias)) {
91
-            throw new InvalidAliasException($fqn, $alias);
92
-        }
93
-        // are we adding an alias for a specific class?
94
-        if ($for_class !== '') {
95
-            // make sure it's set up as an array
96
-            if (! isset($this->aliases[ $for_class ])) {
97
-                $this->aliases[ $for_class ] = array();
98
-            }
99
-            $this->aliases[ $for_class ][ $alias ] = $fqn;
100
-            return;
101
-        }
102
-        $this->aliases[ $alias ] = $fqn;
103
-    }
104
-
105
-
106
-    /**
107
-     * returns TRUE if the provided FQN is an alias
108
-     *
109
-     * @param string $fqn
110
-     * @param string $for_class
111
-     * @return bool
112
-     */
113
-    public function isAlias($fqn = '', $for_class = '')
114
-    {
115
-        $fqn = $this->getFqn($fqn);
116
-        if ($this->isAliasForClass($fqn, $for_class)) {
117
-            return true;
118
-        }
119
-        if ($this->isDirectAlias($fqn)) {
120
-            return true;
121
-        }
122
-        return false;
123
-    }
124
-
125
-
126
-    /**
127
-     * returns TRUE if the provided FQN is an alias
128
-     *
129
-     * @param string $fqn
130
-     * @return bool
131
-     */
132
-    protected function isDirectAlias($fqn = '')
133
-    {
134
-        return isset($this->aliases[ (string) $fqn ]) && ! is_array($this->aliases[ (string) $fqn ]);
135
-    }
136
-
137
-
138
-    /**
139
-     * returns TRUE if the provided FQN is an alias for the specified class
140
-     *
141
-     * @param string $fqn
142
-     * @param string $for_class
143
-     * @return bool
144
-     */
145
-    protected function isAliasForClass($fqn = '', $for_class = '')
146
-    {
147
-        return (
148
-            $for_class !== ''
149
-            && isset($this->aliases[ (string) $for_class ][ (string) $fqn ])
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     * returns FQN for provided alias if one exists, otherwise returns the original FQN
156
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
157
-     *  for example:
158
-     *      if the following two entries were added to the aliases array:
159
-     *          array(
160
-     *              'interface_alias'           => 'some\namespace\interface'
161
-     *              'some\namespace\interface'  => 'some\namespace\classname'
162
-     *          )
163
-     *      then one could use Loader::getNew( 'interface_alias' )
164
-     *      to load an instance of 'some\namespace\classname'
165
-     *
166
-     * @param string $alias
167
-     * @param string $for_class
168
-     * @return string
169
-     */
170
-    public function getFqnForAlias($alias = '', $for_class = '')
171
-    {
172
-        $alias = $this->getFqn($alias);
173
-        if ($this->isAliasForClass($alias, $for_class)) {
174
-            return $this->getFqnForAlias($this->aliases[ (string) $for_class ][ (string) $alias ], $for_class);
175
-        }
176
-        if ($this->isDirectAlias($alias)) {
177
-            return $this->getFqnForAlias($this->aliases[ (string) $alias ], '');
178
-        }
179
-        return $alias;
180
-    }
20
+	/**
21
+	 * array of interfaces indexed by FQCNs where values are arrays of interface FQNs
22
+	 *
23
+	 * @var string[][] $interfaces
24
+	 */
25
+	private $interfaces = array();
26
+
27
+	/**
28
+	 * @type string[][] $aliases
29
+	 */
30
+	protected $aliases = array();
31
+
32
+
33
+	/**
34
+	 * @param string $fqn
35
+	 * @return string
36
+	 */
37
+	public function getFqn($fqn)
38
+	{
39
+		$fqn = $fqn instanceof FullyQualifiedName ? $fqn->string() : $fqn;
40
+		return ltrim($fqn, '\\');
41
+	}
42
+
43
+
44
+	/**
45
+	 * @param string $fqn
46
+	 * @return array
47
+	 */
48
+	public function getInterfaces($fqn)
49
+	{
50
+		$fqn = $this->getFqn($fqn);
51
+		// have we already seen this FQCN ?
52
+		if (! array_key_exists($fqn, $this->interfaces)) {
53
+			$this->interfaces[ $fqn ] = array();
54
+			if (class_exists($fqn)) {
55
+				$this->interfaces[ $fqn ] = class_implements($fqn, false);
56
+				$this->interfaces[ $fqn ] = $this->interfaces[ $fqn ] !== false
57
+					? $this->interfaces[ $fqn ]
58
+					: array();
59
+			}
60
+		}
61
+		return $this->interfaces[ $fqn ];
62
+	}
63
+
64
+
65
+	/**
66
+	 * @param string $fqn
67
+	 * @param string $interface
68
+	 * @return bool
69
+	 */
70
+	public function hasInterface($fqn, $interface)
71
+	{
72
+		$fqn        = $this->getFqn($fqn);
73
+		$interfaces = $this->getInterfaces($fqn);
74
+		return in_array($interface, $interfaces, true);
75
+	}
76
+
77
+
78
+	/**
79
+	 * adds an alias for a classname
80
+	 *
81
+	 * @param string $fqn       the class name that should be used (concrete class to replace interface)
82
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
83
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
84
+	 * @throws InvalidAliasException
85
+	 */
86
+	public function addAlias($fqn, $alias, $for_class = '')
87
+	{
88
+		$fqn   = $this->getFqn($fqn);
89
+		$alias = $this->getFqn($alias);
90
+		if (strpos($alias, '\\') !== false && ! is_subclass_of($fqn, $alias)) {
91
+			throw new InvalidAliasException($fqn, $alias);
92
+		}
93
+		// are we adding an alias for a specific class?
94
+		if ($for_class !== '') {
95
+			// make sure it's set up as an array
96
+			if (! isset($this->aliases[ $for_class ])) {
97
+				$this->aliases[ $for_class ] = array();
98
+			}
99
+			$this->aliases[ $for_class ][ $alias ] = $fqn;
100
+			return;
101
+		}
102
+		$this->aliases[ $alias ] = $fqn;
103
+	}
104
+
105
+
106
+	/**
107
+	 * returns TRUE if the provided FQN is an alias
108
+	 *
109
+	 * @param string $fqn
110
+	 * @param string $for_class
111
+	 * @return bool
112
+	 */
113
+	public function isAlias($fqn = '', $for_class = '')
114
+	{
115
+		$fqn = $this->getFqn($fqn);
116
+		if ($this->isAliasForClass($fqn, $for_class)) {
117
+			return true;
118
+		}
119
+		if ($this->isDirectAlias($fqn)) {
120
+			return true;
121
+		}
122
+		return false;
123
+	}
124
+
125
+
126
+	/**
127
+	 * returns TRUE if the provided FQN is an alias
128
+	 *
129
+	 * @param string $fqn
130
+	 * @return bool
131
+	 */
132
+	protected function isDirectAlias($fqn = '')
133
+	{
134
+		return isset($this->aliases[ (string) $fqn ]) && ! is_array($this->aliases[ (string) $fqn ]);
135
+	}
136
+
137
+
138
+	/**
139
+	 * returns TRUE if the provided FQN is an alias for the specified class
140
+	 *
141
+	 * @param string $fqn
142
+	 * @param string $for_class
143
+	 * @return bool
144
+	 */
145
+	protected function isAliasForClass($fqn = '', $for_class = '')
146
+	{
147
+		return (
148
+			$for_class !== ''
149
+			&& isset($this->aliases[ (string) $for_class ][ (string) $fqn ])
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 * returns FQN for provided alias if one exists, otherwise returns the original FQN
156
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
157
+	 *  for example:
158
+	 *      if the following two entries were added to the aliases array:
159
+	 *          array(
160
+	 *              'interface_alias'           => 'some\namespace\interface'
161
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
162
+	 *          )
163
+	 *      then one could use Loader::getNew( 'interface_alias' )
164
+	 *      to load an instance of 'some\namespace\classname'
165
+	 *
166
+	 * @param string $alias
167
+	 * @param string $for_class
168
+	 * @return string
169
+	 */
170
+	public function getFqnForAlias($alias = '', $for_class = '')
171
+	{
172
+		$alias = $this->getFqn($alias);
173
+		if ($this->isAliasForClass($alias, $for_class)) {
174
+			return $this->getFqnForAlias($this->aliases[ (string) $for_class ][ (string) $alias ], $for_class);
175
+		}
176
+		if ($this->isDirectAlias($alias)) {
177
+			return $this->getFqnForAlias($this->aliases[ (string) $alias ], '');
178
+		}
179
+		return $alias;
180
+	}
181 181
 }
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 1 patch
Indentation   +1089 added lines, -1089 removed lines patch added patch discarded remove patch
@@ -20,1093 +20,1093 @@
 block discarded – undo
20 20
 class EE_Dependency_Map
21 21
 {
22 22
 
23
-    /**
24
-     * This means that the requested class dependency is not present in the dependency map
25
-     */
26
-    const not_registered = 0;
27
-
28
-    /**
29
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
-     */
31
-    const load_new_object = 1;
32
-
33
-    /**
34
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
-     */
37
-    const load_from_cache = 2;
38
-
39
-    /**
40
-     * When registering a dependency,
41
-     * this indicates to keep any existing dependencies that already exist,
42
-     * and simply discard any new dependencies declared in the incoming data
43
-     */
44
-    const KEEP_EXISTING_DEPENDENCIES = 0;
45
-
46
-    /**
47
-     * When registering a dependency,
48
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
-     */
50
-    const OVERWRITE_DEPENDENCIES = 1;
51
-
52
-
53
-    /**
54
-     * @type EE_Dependency_Map $_instance
55
-     */
56
-    protected static $_instance;
57
-
58
-    /**
59
-     * @var ClassInterfaceCache $class_cache
60
-     */
61
-    private $class_cache;
62
-
63
-    /**
64
-     * @type RequestInterface $request
65
-     */
66
-    protected $request;
67
-
68
-    /**
69
-     * @type LegacyRequestInterface $legacy_request
70
-     */
71
-    protected $legacy_request;
72
-
73
-    /**
74
-     * @type ResponseInterface $response
75
-     */
76
-    protected $response;
77
-
78
-    /**
79
-     * @type LoaderInterface $loader
80
-     */
81
-    protected $loader;
82
-
83
-    /**
84
-     * @type array $_dependency_map
85
-     */
86
-    protected $_dependency_map = array();
87
-
88
-    /**
89
-     * @type array $_class_loaders
90
-     */
91
-    protected $_class_loaders = array();
92
-
93
-
94
-    /**
95
-     * EE_Dependency_Map constructor.
96
-     *
97
-     * @param ClassInterfaceCache $class_cache
98
-     */
99
-    protected function __construct(ClassInterfaceCache $class_cache)
100
-    {
101
-        $this->class_cache = $class_cache;
102
-        do_action('EE_Dependency_Map____construct', $this);
103
-    }
104
-
105
-
106
-    /**
107
-     * @return void
108
-     */
109
-    public function initialize()
110
-    {
111
-        $this->_register_core_dependencies();
112
-        $this->_register_core_class_loaders();
113
-        $this->_register_core_aliases();
114
-    }
115
-
116
-
117
-    /**
118
-     * @singleton method used to instantiate class object
119
-     * @param ClassInterfaceCache|null $class_cache
120
-     * @return EE_Dependency_Map
121
-     */
122
-    public static function instance(ClassInterfaceCache $class_cache = null)
123
-    {
124
-        // check if class object is instantiated, and instantiated properly
125
-        if (! self::$_instance instanceof EE_Dependency_Map
126
-            && $class_cache instanceof ClassInterfaceCache
127
-        ) {
128
-            self::$_instance = new EE_Dependency_Map($class_cache);
129
-        }
130
-        return self::$_instance;
131
-    }
132
-
133
-
134
-    /**
135
-     * @param RequestInterface $request
136
-     */
137
-    public function setRequest(RequestInterface $request)
138
-    {
139
-        $this->request = $request;
140
-    }
141
-
142
-
143
-    /**
144
-     * @param LegacyRequestInterface $legacy_request
145
-     */
146
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
147
-    {
148
-        $this->legacy_request = $legacy_request;
149
-    }
150
-
151
-
152
-    /**
153
-     * @param ResponseInterface $response
154
-     */
155
-    public function setResponse(ResponseInterface $response)
156
-    {
157
-        $this->response = $response;
158
-    }
159
-
160
-
161
-    /**
162
-     * @param LoaderInterface $loader
163
-     */
164
-    public function setLoader(LoaderInterface $loader)
165
-    {
166
-        $this->loader = $loader;
167
-    }
168
-
169
-
170
-    /**
171
-     * @param string $class
172
-     * @param array  $dependencies
173
-     * @param int    $overwrite
174
-     * @return bool
175
-     */
176
-    public static function register_dependencies(
177
-        $class,
178
-        array $dependencies,
179
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
-    ) {
181
-        return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
182
-    }
183
-
184
-
185
-    /**
186
-     * Assigns an array of class names and corresponding load sources (new or cached)
187
-     * to the class specified by the first parameter.
188
-     * IMPORTANT !!!
189
-     * The order of elements in the incoming $dependencies array MUST match
190
-     * the order of the constructor parameters for the class in question.
191
-     * This is especially important when overriding any existing dependencies that are registered.
192
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
193
-     *
194
-     * @param string $class
195
-     * @param array  $dependencies
196
-     * @param int    $overwrite
197
-     * @return bool
198
-     */
199
-    public function registerDependencies(
200
-        $class,
201
-        array $dependencies,
202
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
203
-    ) {
204
-        $class = trim($class, '\\');
205
-        $registered = false;
206
-        if (empty(self::$_instance->_dependency_map[ $class ])) {
207
-            self::$_instance->_dependency_map[ $class ] = array();
208
-        }
209
-        // we need to make sure that any aliases used when registering a dependency
210
-        // get resolved to the correct class name
211
-        foreach ($dependencies as $dependency => $load_source) {
212
-            $alias = self::$_instance->getFqnForAlias($dependency);
213
-            if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
214
-                || ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
215
-            ) {
216
-                unset($dependencies[ $dependency ]);
217
-                $dependencies[ $alias ] = $load_source;
218
-                $registered = true;
219
-            }
220
-        }
221
-        // now add our two lists of dependencies together.
222
-        // using Union (+=) favours the arrays in precedence from left to right,
223
-        // so $dependencies is NOT overwritten because it is listed first
224
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
225
-        // Union is way faster than array_merge() but should be used with caution...
226
-        // especially with numerically indexed arrays
227
-        $dependencies += self::$_instance->_dependency_map[ $class ];
228
-        // now we need to ensure that the resulting dependencies
229
-        // array only has the entries that are required for the class
230
-        // so first count how many dependencies were originally registered for the class
231
-        $dependency_count = count(self::$_instance->_dependency_map[ $class ]);
232
-        // if that count is non-zero (meaning dependencies were already registered)
233
-        self::$_instance->_dependency_map[ $class ] = $dependency_count
234
-            // then truncate the  final array to match that count
235
-            ? array_slice($dependencies, 0, $dependency_count)
236
-            // otherwise just take the incoming array because nothing previously existed
237
-            : $dependencies;
238
-        return $registered;
239
-    }
240
-
241
-
242
-    /**
243
-     * @param string $class_name
244
-     * @param string $loader
245
-     * @return bool
246
-     * @throws DomainException
247
-     */
248
-    public static function register_class_loader($class_name, $loader = 'load_core')
249
-    {
250
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
251
-            throw new DomainException(
252
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
253
-            );
254
-        }
255
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
256
-        if (! is_callable($loader)
257
-            && (
258
-                strpos($loader, 'load_') !== 0
259
-                || ! method_exists('EE_Registry', $loader)
260
-            )
261
-        ) {
262
-            throw new DomainException(
263
-                sprintf(
264
-                    esc_html__(
265
-                        '"%1$s" is not a valid loader method on EE_Registry.',
266
-                        'event_espresso'
267
-                    ),
268
-                    $loader
269
-                )
270
-            );
271
-        }
272
-        $class_name = self::$_instance->getFqnForAlias($class_name);
273
-        if (! isset(self::$_instance->_class_loaders[ $class_name ])) {
274
-            self::$_instance->_class_loaders[ $class_name ] = $loader;
275
-            return true;
276
-        }
277
-        return false;
278
-    }
279
-
280
-
281
-    /**
282
-     * @return array
283
-     */
284
-    public function dependency_map()
285
-    {
286
-        return $this->_dependency_map;
287
-    }
288
-
289
-
290
-    /**
291
-     * returns TRUE if dependency map contains a listing for the provided class name
292
-     *
293
-     * @param string $class_name
294
-     * @return boolean
295
-     */
296
-    public function has($class_name = '')
297
-    {
298
-        // all legacy models have the same dependencies
299
-        if (strpos($class_name, 'EEM_') === 0) {
300
-            $class_name = 'LEGACY_MODELS';
301
-        }
302
-        return isset($this->_dependency_map[ $class_name ]) ? true : false;
303
-    }
304
-
305
-
306
-    /**
307
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
308
-     *
309
-     * @param string $class_name
310
-     * @param string $dependency
311
-     * @return bool
312
-     */
313
-    public function has_dependency_for_class($class_name = '', $dependency = '')
314
-    {
315
-        // all legacy models have the same dependencies
316
-        if (strpos($class_name, 'EEM_') === 0) {
317
-            $class_name = 'LEGACY_MODELS';
318
-        }
319
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
320
-        return isset($this->_dependency_map[ $class_name ][ $dependency ])
321
-            ? true
322
-            : false;
323
-    }
324
-
325
-
326
-    /**
327
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
328
-     *
329
-     * @param string $class_name
330
-     * @param string $dependency
331
-     * @return int
332
-     */
333
-    public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
334
-    {
335
-        // all legacy models have the same dependencies
336
-        if (strpos($class_name, 'EEM_') === 0) {
337
-            $class_name = 'LEGACY_MODELS';
338
-        }
339
-        $dependency = $this->getFqnForAlias($dependency);
340
-        return $this->has_dependency_for_class($class_name, $dependency)
341
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
342
-            : EE_Dependency_Map::not_registered;
343
-    }
344
-
345
-
346
-    /**
347
-     * @param string $class_name
348
-     * @return string | Closure
349
-     */
350
-    public function class_loader($class_name)
351
-    {
352
-        // all legacy models use load_model()
353
-        if (strpos($class_name, 'EEM_') === 0) {
354
-            return 'load_model';
355
-        }
356
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
357
-        // perform strpos() first to avoid loading regex every time we load a class
358
-        if (strpos($class_name, 'EE_CPT_') === 0
359
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
360
-        ) {
361
-            return 'load_core';
362
-        }
363
-        $class_name = $this->getFqnForAlias($class_name);
364
-        return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
365
-    }
366
-
367
-
368
-    /**
369
-     * @return array
370
-     */
371
-    public function class_loaders()
372
-    {
373
-        return $this->_class_loaders;
374
-    }
375
-
376
-
377
-    /**
378
-     * adds an alias for a classname
379
-     *
380
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
381
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
382
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
383
-     */
384
-    public function add_alias($fqcn, $alias, $for_class = '')
385
-    {
386
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
387
-    }
388
-
389
-
390
-    /**
391
-     * Returns TRUE if the provided fully qualified name IS an alias
392
-     * WHY?
393
-     * Because if a class is type hinting for a concretion,
394
-     * then why would we need to find another class to supply it?
395
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
396
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
397
-     * Don't go looking for some substitute.
398
-     * Whereas if a class is type hinting for an interface...
399
-     * then we need to find an actual class to use.
400
-     * So the interface IS the alias for some other FQN,
401
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
402
-     * represents some other class.
403
-     *
404
-     * @param string $fqn
405
-     * @param string $for_class
406
-     * @return bool
407
-     */
408
-    public function isAlias($fqn = '', $for_class = '')
409
-    {
410
-        return $this->class_cache->isAlias($fqn, $for_class);
411
-    }
412
-
413
-
414
-    /**
415
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
416
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
417
-     *  for example:
418
-     *      if the following two entries were added to the _aliases array:
419
-     *          array(
420
-     *              'interface_alias'           => 'some\namespace\interface'
421
-     *              'some\namespace\interface'  => 'some\namespace\classname'
422
-     *          )
423
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
424
-     *      to load an instance of 'some\namespace\classname'
425
-     *
426
-     * @param string $alias
427
-     * @param string $for_class
428
-     * @return string
429
-     */
430
-    public function getFqnForAlias($alias = '', $for_class = '')
431
-    {
432
-        return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
433
-    }
434
-
435
-
436
-    /**
437
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
438
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
439
-     * This is done by using the following class constants:
440
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
441
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
442
-     */
443
-    protected function _register_core_dependencies()
444
-    {
445
-        $this->_dependency_map = array(
446
-            'EE_Request_Handler'                                                                                          => array(
447
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
448
-            ),
449
-            'EE_System'                                                                                                   => array(
450
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
451
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
452
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
453
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
454
-            ),
455
-            'EE_Session'                                                                                                  => array(
456
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
457
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
458
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
459
-                'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
460
-                'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
461
-            ),
462
-            'EE_Cart'                                                                                                     => array(
463
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
464
-            ),
465
-            'EE_Front_Controller'                                                                                         => array(
466
-                'EE_Registry'              => EE_Dependency_Map::load_from_cache,
467
-                'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
468
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
469
-            ),
470
-            'EE_Messenger_Collection_Loader'                                                                              => array(
471
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
472
-            ),
473
-            'EE_Message_Type_Collection_Loader'                                                                           => array(
474
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
475
-            ),
476
-            'EE_Message_Resource_Manager'                                                                                 => array(
477
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
478
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
479
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
480
-            ),
481
-            'EE_Message_Factory'                                                                                          => array(
482
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
483
-            ),
484
-            'EE_messages'                                                                                                 => array(
485
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
486
-            ),
487
-            'EE_Messages_Generator'                                                                                       => array(
488
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
489
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
490
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
491
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
492
-            ),
493
-            'EE_Messages_Processor'                                                                                       => array(
494
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
-            ),
496
-            'EE_Messages_Queue'                                                                                           => array(
497
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
498
-            ),
499
-            'EE_Messages_Template_Defaults'                                                                               => array(
500
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
501
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
502
-            ),
503
-            'EE_Message_To_Generate_From_Request'                                                                         => array(
504
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
505
-                'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
506
-            ),
507
-            'EventEspresso\core\services\commands\CommandBus'                                                             => array(
508
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
509
-            ),
510
-            'EventEspresso\services\commands\CommandHandler'                                                              => array(
511
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
512
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
513
-            ),
514
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
515
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
516
-            ),
517
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
518
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
519
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
520
-            ),
521
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
522
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
523
-            ),
524
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
525
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
526
-            ),
527
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
528
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
529
-            ),
530
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
531
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
532
-            ),
533
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
534
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
535
-            ),
536
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
537
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
538
-            ),
539
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
540
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
541
-            ),
542
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
543
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
544
-            ),
545
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
546
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
-            ),
548
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
549
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
550
-            ),
551
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
552
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
553
-            ),
554
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
555
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
-            ),
557
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
558
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
559
-            ),
560
-            'EventEspresso\core\services\database\TableManager'                                                           => array(
561
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
562
-            ),
563
-            'EE_Data_Migration_Class_Base'                                                                                => array(
564
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
565
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
566
-            ),
567
-            'EE_DMS_Core_4_1_0'                                                                                           => array(
568
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
569
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
570
-            ),
571
-            'EE_DMS_Core_4_2_0'                                                                                           => array(
572
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
573
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
574
-            ),
575
-            'EE_DMS_Core_4_3_0'                                                                                           => array(
576
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
577
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
578
-            ),
579
-            'EE_DMS_Core_4_4_0'                                                                                           => array(
580
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
581
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
582
-            ),
583
-            'EE_DMS_Core_4_5_0'                                                                                           => array(
584
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
586
-            ),
587
-            'EE_DMS_Core_4_6_0'                                                                                           => array(
588
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
589
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
590
-            ),
591
-            'EE_DMS_Core_4_7_0'                                                                                           => array(
592
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
593
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
594
-            ),
595
-            'EE_DMS_Core_4_8_0'                                                                                           => array(
596
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
597
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
598
-            ),
599
-            'EE_DMS_Core_4_9_0'                                                                                           => array(
600
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
601
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
602
-            ),
603
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
604
-                array(),
605
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
606
-            ),
607
-            'EventEspresso\core\services\assets\Registry'                                                                 => array(
608
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
609
-                'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
610
-            ),
611
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
612
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
613
-            ),
614
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
615
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
616
-            ),
617
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
618
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
619
-            ),
620
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
621
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
622
-            ),
623
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
624
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
625
-            ),
626
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
627
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
628
-            ),
629
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
630
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
631
-            ),
632
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
633
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
634
-            ),
635
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
636
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
637
-            ),
638
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
639
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
640
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
641
-            ),
642
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
643
-                null,
644
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
645
-            ),
646
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
647
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
648
-            ),
649
-            'LEGACY_MODELS'                                                                                               => array(
650
-                null,
651
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
652
-            ),
653
-            'EE_Module_Request_Router'                                                                                    => array(
654
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
655
-            ),
656
-            'EE_Registration_Processor'                                                                                   => array(
657
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
658
-            ),
659
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
660
-                null,
661
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
662
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
663
-            ),
664
-            'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
665
-                'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
666
-                'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
667
-            ),
668
-            'EE_Admin_Transactions_List_Table'                                                                            => array(
669
-                null,
670
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
671
-            ),
672
-            'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
673
-                'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
674
-                'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
675
-                'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
676
-            ),
677
-            'EventEspresso\core\domain\services\pue\Config'                                                               => array(
678
-                'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
679
-                'EE_Config'         => EE_Dependency_Map::load_from_cache,
680
-            ),
681
-            'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
682
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
683
-                'EEM_Event'          => EE_Dependency_Map::load_from_cache,
684
-                'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
685
-                'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
686
-                'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
687
-                'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
688
-                'EE_Config'          => EE_Dependency_Map::load_from_cache,
689
-            ),
690
-            'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
691
-                'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
692
-            ),
693
-            'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
694
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
695
-            ),
696
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
697
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
698
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
699
-            ),
700
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
701
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
702
-            ),
703
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
704
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
705
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
706
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
707
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
708
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
709
-            ),
710
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
711
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
712
-            ),
713
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
714
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
715
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
716
-            ),
717
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
718
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
719
-            ),
720
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
721
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
722
-            ),
723
-            'EE_CPT_Strategy'                                                                                             => array(
724
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
725
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
-            ),
727
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
728
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
729
-            ),
730
-            'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
731
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
732
-                'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
733
-                'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
734
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
735
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
736
-            ),
737
-            'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
738
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
740
-            ),
741
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
742
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
743
-            ),
744
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
745
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
746
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
747
-            ),
748
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
749
-                'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
750
-            ),
751
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
752
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache,
753
-            ),
754
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
755
-                'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
756
-            ),
757
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
758
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
759
-            ),
760
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
761
-                'EEM_Answer' => EE_Dependency_Map::load_from_cache,
762
-                'EEM_Question' => EE_Dependency_Map::load_from_cache,
763
-            ),
764
-            'EventEspresso\core\CPTs\CptQueryModifier' => array(
765
-                null,
766
-                null,
767
-                null,
768
-                'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
769
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
770
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
771
-            ),
772
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
773
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
774
-                'EE_Config' => EE_Dependency_Map::load_from_cache
775
-            ),
776
-            'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
777
-                'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
778
-                'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
779
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
780
-                'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
781
-            ),
782
-            'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
783
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
784
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
785
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
786
-            ),
787
-            'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
788
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
789
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
790
-            ),
791
-            'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
792
-                'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
793
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
794
-                'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
795
-            ),
796
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
797
-                'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
798
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
799
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
800
-            ),
801
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
802
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
803
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
804
-            ),
805
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
806
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
807
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
808
-            ),
809
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
810
-                'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
811
-            ),
812
-            'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
813
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
814
-            ),
815
-            'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
816
-                'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
817
-            ),
818
-            'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
819
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
820
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
821
-            ),
822
-            'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
823
-                'EEM_Event' => EE_Dependency_Map::load_from_cache,
824
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
825
-            ),
826
-            'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
827
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
828
-            ),
829
-            'EventEspresso\core\services\session\SessionStartHandler' => array(
830
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
831
-            ),
832
-            'EE_URL_Validation_Strategy' => array(
833
-                null,
834
-                null,
835
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
836
-            ),
837
-            'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
838
-                'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
839
-                'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
840
-                'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
841
-                'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
842
-                'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
843
-            ),
844
-            'EventEspresso\core\services\address\CountrySubRegionDao' => array(
845
-                'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
846
-                'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
847
-            ),
848
-            'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
849
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
850
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
851
-            ),
852
-            'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
853
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
854
-                'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
855
-            ),
856
-            'EventEspresso\core\services\request\files\FilesDataHandler' => array(
857
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
858
-            ),
859
-            'EventEspressoBatchRequest\BatchRequestProcessor' => [
860
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
861
-            ]
862
-        );
863
-    }
864
-
865
-
866
-    /**
867
-     * Registers how core classes are loaded.
868
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
869
-     *        'EE_Request_Handler' => 'load_core'
870
-     *        'EE_Messages_Queue'  => 'load_lib'
871
-     *        'EEH_Debug_Tools'    => 'load_helper'
872
-     * or, if greater control is required, by providing a custom closure. For example:
873
-     *        'Some_Class' => function () {
874
-     *            return new Some_Class();
875
-     *        },
876
-     * This is required for instantiating dependencies
877
-     * where an interface has been type hinted in a class constructor. For example:
878
-     *        'Required_Interface' => function () {
879
-     *            return new A_Class_That_Implements_Required_Interface();
880
-     *        },
881
-     */
882
-    protected function _register_core_class_loaders()
883
-    {
884
-        $this->_class_loaders = array(
885
-            // load_core
886
-            'EE_Dependency_Map'                            => function () {
887
-                return $this;
888
-            },
889
-            'EE_Capabilities'                              => 'load_core',
890
-            'EE_Encryption'                                => 'load_core',
891
-            'EE_Front_Controller'                          => 'load_core',
892
-            'EE_Module_Request_Router'                     => 'load_core',
893
-            'EE_Registry'                                  => 'load_core',
894
-            'EE_Request'                                   => function () {
895
-                return $this->legacy_request;
896
-            },
897
-            'EventEspresso\core\services\request\Request'  => function () {
898
-                return $this->request;
899
-            },
900
-            'EventEspresso\core\services\request\Response' => function () {
901
-                return $this->response;
902
-            },
903
-            'EE_Base'                                      => 'load_core',
904
-            'EE_Request_Handler'                           => 'load_core',
905
-            'EE_Session'                                   => 'load_core',
906
-            'EE_Cron_Tasks'                                => 'load_core',
907
-            'EE_System'                                    => 'load_core',
908
-            'EE_Maintenance_Mode'                          => 'load_core',
909
-            'EE_Register_CPTs'                             => 'load_core',
910
-            'EE_Admin'                                     => 'load_core',
911
-            'EE_CPT_Strategy'                              => 'load_core',
912
-            // load_class
913
-            'EE_Registration_Processor'                    => 'load_class',
914
-            // load_lib
915
-            'EE_Message_Resource_Manager'                  => 'load_lib',
916
-            'EE_Message_Type_Collection'                   => 'load_lib',
917
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
918
-            'EE_Messenger_Collection'                      => 'load_lib',
919
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
920
-            'EE_Messages_Processor'                        => 'load_lib',
921
-            'EE_Message_Repository'                        => 'load_lib',
922
-            'EE_Messages_Queue'                            => 'load_lib',
923
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
924
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
925
-            'EE_Payment_Method_Manager'                    => 'load_lib',
926
-            'EE_Messages_Generator'                        => function () {
927
-                return EE_Registry::instance()->load_lib(
928
-                    'Messages_Generator',
929
-                    array(),
930
-                    false,
931
-                    false
932
-                );
933
-            },
934
-            'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
935
-                return EE_Registry::instance()->load_lib(
936
-                    'Messages_Template_Defaults',
937
-                    $arguments,
938
-                    false,
939
-                    false
940
-                );
941
-            },
942
-            // load_helper
943
-            'EEH_Parse_Shortcodes'                         => function () {
944
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
945
-                    return new EEH_Parse_Shortcodes();
946
-                }
947
-                return null;
948
-            },
949
-            'EE_Template_Config'                           => function () {
950
-                return EE_Config::instance()->template_settings;
951
-            },
952
-            'EE_Currency_Config'                           => function () {
953
-                return EE_Config::instance()->currency;
954
-            },
955
-            'EE_Registration_Config'                       => function () {
956
-                return EE_Config::instance()->registration;
957
-            },
958
-            'EE_Core_Config'                               => function () {
959
-                return EE_Config::instance()->core;
960
-            },
961
-            'EventEspresso\core\services\loaders\Loader'   => function () {
962
-                return LoaderFactory::getLoader();
963
-            },
964
-            'EE_Network_Config'                            => function () {
965
-                return EE_Network_Config::instance();
966
-            },
967
-            'EE_Config'                                    => function () {
968
-                return EE_Config::instance();
969
-            },
970
-            'EventEspresso\core\domain\Domain'             => function () {
971
-                return DomainFactory::getEventEspressoCoreDomain();
972
-            },
973
-            'EE_Admin_Config'                              => function () {
974
-                return EE_Config::instance()->admin;
975
-            },
976
-            'EE_Organization_Config'                       => function () {
977
-                return EE_Config::instance()->organization;
978
-            },
979
-            'EE_Network_Core_Config'                       => function () {
980
-                return EE_Network_Config::instance()->core;
981
-            },
982
-            'EE_Environment_Config'                        => function () {
983
-                return EE_Config::instance()->environment;
984
-            },
985
-        );
986
-    }
987
-
988
-
989
-    /**
990
-     * can be used for supplying alternate names for classes,
991
-     * or for connecting interface names to instantiable classes
992
-     */
993
-    protected function _register_core_aliases()
994
-    {
995
-        $aliases = array(
996
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
997
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
998
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
999
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1000
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1001
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1002
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1003
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1004
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1005
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1006
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1007
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1008
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1009
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1010
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1011
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1012
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1013
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1014
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1015
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1016
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1017
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1018
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1019
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1020
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1021
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1022
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1023
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1024
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1025
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1026
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1027
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1028
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1029
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1030
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1031
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1032
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1033
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1034
-        );
1035
-        foreach ($aliases as $alias => $fqn) {
1036
-            if (is_array($fqn)) {
1037
-                foreach ($fqn as $class => $for_class) {
1038
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1039
-                }
1040
-                continue;
1041
-            }
1042
-            $this->class_cache->addAlias($fqn, $alias);
1043
-        }
1044
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1045
-            $this->class_cache->addAlias(
1046
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1047
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1048
-            );
1049
-        }
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1055
-     * request Primarily used by unit tests.
1056
-     */
1057
-    public function reset()
1058
-    {
1059
-        $this->_register_core_class_loaders();
1060
-        $this->_register_core_dependencies();
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * PLZ NOTE: a better name for this method would be is_alias()
1066
-     * because it returns TRUE if the provided fully qualified name IS an alias
1067
-     * WHY?
1068
-     * Because if a class is type hinting for a concretion,
1069
-     * then why would we need to find another class to supply it?
1070
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1071
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1072
-     * Don't go looking for some substitute.
1073
-     * Whereas if a class is type hinting for an interface...
1074
-     * then we need to find an actual class to use.
1075
-     * So the interface IS the alias for some other FQN,
1076
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1077
-     * represents some other class.
1078
-     *
1079
-     * @deprecated 4.9.62.p
1080
-     * @param string $fqn
1081
-     * @param string $for_class
1082
-     * @return bool
1083
-     */
1084
-    public function has_alias($fqn = '', $for_class = '')
1085
-    {
1086
-        return $this->isAlias($fqn, $for_class);
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1092
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1093
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1094
-     *  for example:
1095
-     *      if the following two entries were added to the _aliases array:
1096
-     *          array(
1097
-     *              'interface_alias'           => 'some\namespace\interface'
1098
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1099
-     *          )
1100
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1101
-     *      to load an instance of 'some\namespace\classname'
1102
-     *
1103
-     * @deprecated 4.9.62.p
1104
-     * @param string $alias
1105
-     * @param string $for_class
1106
-     * @return string
1107
-     */
1108
-    public function get_alias($alias = '', $for_class = '')
1109
-    {
1110
-        return $this->getFqnForAlias($alias, $for_class);
1111
-    }
23
+	/**
24
+	 * This means that the requested class dependency is not present in the dependency map
25
+	 */
26
+	const not_registered = 0;
27
+
28
+	/**
29
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
+	 */
31
+	const load_new_object = 1;
32
+
33
+	/**
34
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
+	 */
37
+	const load_from_cache = 2;
38
+
39
+	/**
40
+	 * When registering a dependency,
41
+	 * this indicates to keep any existing dependencies that already exist,
42
+	 * and simply discard any new dependencies declared in the incoming data
43
+	 */
44
+	const KEEP_EXISTING_DEPENDENCIES = 0;
45
+
46
+	/**
47
+	 * When registering a dependency,
48
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
+	 */
50
+	const OVERWRITE_DEPENDENCIES = 1;
51
+
52
+
53
+	/**
54
+	 * @type EE_Dependency_Map $_instance
55
+	 */
56
+	protected static $_instance;
57
+
58
+	/**
59
+	 * @var ClassInterfaceCache $class_cache
60
+	 */
61
+	private $class_cache;
62
+
63
+	/**
64
+	 * @type RequestInterface $request
65
+	 */
66
+	protected $request;
67
+
68
+	/**
69
+	 * @type LegacyRequestInterface $legacy_request
70
+	 */
71
+	protected $legacy_request;
72
+
73
+	/**
74
+	 * @type ResponseInterface $response
75
+	 */
76
+	protected $response;
77
+
78
+	/**
79
+	 * @type LoaderInterface $loader
80
+	 */
81
+	protected $loader;
82
+
83
+	/**
84
+	 * @type array $_dependency_map
85
+	 */
86
+	protected $_dependency_map = array();
87
+
88
+	/**
89
+	 * @type array $_class_loaders
90
+	 */
91
+	protected $_class_loaders = array();
92
+
93
+
94
+	/**
95
+	 * EE_Dependency_Map constructor.
96
+	 *
97
+	 * @param ClassInterfaceCache $class_cache
98
+	 */
99
+	protected function __construct(ClassInterfaceCache $class_cache)
100
+	{
101
+		$this->class_cache = $class_cache;
102
+		do_action('EE_Dependency_Map____construct', $this);
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return void
108
+	 */
109
+	public function initialize()
110
+	{
111
+		$this->_register_core_dependencies();
112
+		$this->_register_core_class_loaders();
113
+		$this->_register_core_aliases();
114
+	}
115
+
116
+
117
+	/**
118
+	 * @singleton method used to instantiate class object
119
+	 * @param ClassInterfaceCache|null $class_cache
120
+	 * @return EE_Dependency_Map
121
+	 */
122
+	public static function instance(ClassInterfaceCache $class_cache = null)
123
+	{
124
+		// check if class object is instantiated, and instantiated properly
125
+		if (! self::$_instance instanceof EE_Dependency_Map
126
+			&& $class_cache instanceof ClassInterfaceCache
127
+		) {
128
+			self::$_instance = new EE_Dependency_Map($class_cache);
129
+		}
130
+		return self::$_instance;
131
+	}
132
+
133
+
134
+	/**
135
+	 * @param RequestInterface $request
136
+	 */
137
+	public function setRequest(RequestInterface $request)
138
+	{
139
+		$this->request = $request;
140
+	}
141
+
142
+
143
+	/**
144
+	 * @param LegacyRequestInterface $legacy_request
145
+	 */
146
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
147
+	{
148
+		$this->legacy_request = $legacy_request;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @param ResponseInterface $response
154
+	 */
155
+	public function setResponse(ResponseInterface $response)
156
+	{
157
+		$this->response = $response;
158
+	}
159
+
160
+
161
+	/**
162
+	 * @param LoaderInterface $loader
163
+	 */
164
+	public function setLoader(LoaderInterface $loader)
165
+	{
166
+		$this->loader = $loader;
167
+	}
168
+
169
+
170
+	/**
171
+	 * @param string $class
172
+	 * @param array  $dependencies
173
+	 * @param int    $overwrite
174
+	 * @return bool
175
+	 */
176
+	public static function register_dependencies(
177
+		$class,
178
+		array $dependencies,
179
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
+	) {
181
+		return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
182
+	}
183
+
184
+
185
+	/**
186
+	 * Assigns an array of class names and corresponding load sources (new or cached)
187
+	 * to the class specified by the first parameter.
188
+	 * IMPORTANT !!!
189
+	 * The order of elements in the incoming $dependencies array MUST match
190
+	 * the order of the constructor parameters for the class in question.
191
+	 * This is especially important when overriding any existing dependencies that are registered.
192
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
193
+	 *
194
+	 * @param string $class
195
+	 * @param array  $dependencies
196
+	 * @param int    $overwrite
197
+	 * @return bool
198
+	 */
199
+	public function registerDependencies(
200
+		$class,
201
+		array $dependencies,
202
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
203
+	) {
204
+		$class = trim($class, '\\');
205
+		$registered = false;
206
+		if (empty(self::$_instance->_dependency_map[ $class ])) {
207
+			self::$_instance->_dependency_map[ $class ] = array();
208
+		}
209
+		// we need to make sure that any aliases used when registering a dependency
210
+		// get resolved to the correct class name
211
+		foreach ($dependencies as $dependency => $load_source) {
212
+			$alias = self::$_instance->getFqnForAlias($dependency);
213
+			if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
214
+				|| ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
215
+			) {
216
+				unset($dependencies[ $dependency ]);
217
+				$dependencies[ $alias ] = $load_source;
218
+				$registered = true;
219
+			}
220
+		}
221
+		// now add our two lists of dependencies together.
222
+		// using Union (+=) favours the arrays in precedence from left to right,
223
+		// so $dependencies is NOT overwritten because it is listed first
224
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
225
+		// Union is way faster than array_merge() but should be used with caution...
226
+		// especially with numerically indexed arrays
227
+		$dependencies += self::$_instance->_dependency_map[ $class ];
228
+		// now we need to ensure that the resulting dependencies
229
+		// array only has the entries that are required for the class
230
+		// so first count how many dependencies were originally registered for the class
231
+		$dependency_count = count(self::$_instance->_dependency_map[ $class ]);
232
+		// if that count is non-zero (meaning dependencies were already registered)
233
+		self::$_instance->_dependency_map[ $class ] = $dependency_count
234
+			// then truncate the  final array to match that count
235
+			? array_slice($dependencies, 0, $dependency_count)
236
+			// otherwise just take the incoming array because nothing previously existed
237
+			: $dependencies;
238
+		return $registered;
239
+	}
240
+
241
+
242
+	/**
243
+	 * @param string $class_name
244
+	 * @param string $loader
245
+	 * @return bool
246
+	 * @throws DomainException
247
+	 */
248
+	public static function register_class_loader($class_name, $loader = 'load_core')
249
+	{
250
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
251
+			throw new DomainException(
252
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
253
+			);
254
+		}
255
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
256
+		if (! is_callable($loader)
257
+			&& (
258
+				strpos($loader, 'load_') !== 0
259
+				|| ! method_exists('EE_Registry', $loader)
260
+			)
261
+		) {
262
+			throw new DomainException(
263
+				sprintf(
264
+					esc_html__(
265
+						'"%1$s" is not a valid loader method on EE_Registry.',
266
+						'event_espresso'
267
+					),
268
+					$loader
269
+				)
270
+			);
271
+		}
272
+		$class_name = self::$_instance->getFqnForAlias($class_name);
273
+		if (! isset(self::$_instance->_class_loaders[ $class_name ])) {
274
+			self::$_instance->_class_loaders[ $class_name ] = $loader;
275
+			return true;
276
+		}
277
+		return false;
278
+	}
279
+
280
+
281
+	/**
282
+	 * @return array
283
+	 */
284
+	public function dependency_map()
285
+	{
286
+		return $this->_dependency_map;
287
+	}
288
+
289
+
290
+	/**
291
+	 * returns TRUE if dependency map contains a listing for the provided class name
292
+	 *
293
+	 * @param string $class_name
294
+	 * @return boolean
295
+	 */
296
+	public function has($class_name = '')
297
+	{
298
+		// all legacy models have the same dependencies
299
+		if (strpos($class_name, 'EEM_') === 0) {
300
+			$class_name = 'LEGACY_MODELS';
301
+		}
302
+		return isset($this->_dependency_map[ $class_name ]) ? true : false;
303
+	}
304
+
305
+
306
+	/**
307
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
308
+	 *
309
+	 * @param string $class_name
310
+	 * @param string $dependency
311
+	 * @return bool
312
+	 */
313
+	public function has_dependency_for_class($class_name = '', $dependency = '')
314
+	{
315
+		// all legacy models have the same dependencies
316
+		if (strpos($class_name, 'EEM_') === 0) {
317
+			$class_name = 'LEGACY_MODELS';
318
+		}
319
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
320
+		return isset($this->_dependency_map[ $class_name ][ $dependency ])
321
+			? true
322
+			: false;
323
+	}
324
+
325
+
326
+	/**
327
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
328
+	 *
329
+	 * @param string $class_name
330
+	 * @param string $dependency
331
+	 * @return int
332
+	 */
333
+	public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
334
+	{
335
+		// all legacy models have the same dependencies
336
+		if (strpos($class_name, 'EEM_') === 0) {
337
+			$class_name = 'LEGACY_MODELS';
338
+		}
339
+		$dependency = $this->getFqnForAlias($dependency);
340
+		return $this->has_dependency_for_class($class_name, $dependency)
341
+			? $this->_dependency_map[ $class_name ][ $dependency ]
342
+			: EE_Dependency_Map::not_registered;
343
+	}
344
+
345
+
346
+	/**
347
+	 * @param string $class_name
348
+	 * @return string | Closure
349
+	 */
350
+	public function class_loader($class_name)
351
+	{
352
+		// all legacy models use load_model()
353
+		if (strpos($class_name, 'EEM_') === 0) {
354
+			return 'load_model';
355
+		}
356
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
357
+		// perform strpos() first to avoid loading regex every time we load a class
358
+		if (strpos($class_name, 'EE_CPT_') === 0
359
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
360
+		) {
361
+			return 'load_core';
362
+		}
363
+		$class_name = $this->getFqnForAlias($class_name);
364
+		return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
365
+	}
366
+
367
+
368
+	/**
369
+	 * @return array
370
+	 */
371
+	public function class_loaders()
372
+	{
373
+		return $this->_class_loaders;
374
+	}
375
+
376
+
377
+	/**
378
+	 * adds an alias for a classname
379
+	 *
380
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
381
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
382
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
383
+	 */
384
+	public function add_alias($fqcn, $alias, $for_class = '')
385
+	{
386
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
387
+	}
388
+
389
+
390
+	/**
391
+	 * Returns TRUE if the provided fully qualified name IS an alias
392
+	 * WHY?
393
+	 * Because if a class is type hinting for a concretion,
394
+	 * then why would we need to find another class to supply it?
395
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
396
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
397
+	 * Don't go looking for some substitute.
398
+	 * Whereas if a class is type hinting for an interface...
399
+	 * then we need to find an actual class to use.
400
+	 * So the interface IS the alias for some other FQN,
401
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
402
+	 * represents some other class.
403
+	 *
404
+	 * @param string $fqn
405
+	 * @param string $for_class
406
+	 * @return bool
407
+	 */
408
+	public function isAlias($fqn = '', $for_class = '')
409
+	{
410
+		return $this->class_cache->isAlias($fqn, $for_class);
411
+	}
412
+
413
+
414
+	/**
415
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
416
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
417
+	 *  for example:
418
+	 *      if the following two entries were added to the _aliases array:
419
+	 *          array(
420
+	 *              'interface_alias'           => 'some\namespace\interface'
421
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
422
+	 *          )
423
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
424
+	 *      to load an instance of 'some\namespace\classname'
425
+	 *
426
+	 * @param string $alias
427
+	 * @param string $for_class
428
+	 * @return string
429
+	 */
430
+	public function getFqnForAlias($alias = '', $for_class = '')
431
+	{
432
+		return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
433
+	}
434
+
435
+
436
+	/**
437
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
438
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
439
+	 * This is done by using the following class constants:
440
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
441
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
442
+	 */
443
+	protected function _register_core_dependencies()
444
+	{
445
+		$this->_dependency_map = array(
446
+			'EE_Request_Handler'                                                                                          => array(
447
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
448
+			),
449
+			'EE_System'                                                                                                   => array(
450
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
451
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
452
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
453
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
454
+			),
455
+			'EE_Session'                                                                                                  => array(
456
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
457
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
458
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
459
+				'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
460
+				'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
461
+			),
462
+			'EE_Cart'                                                                                                     => array(
463
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
464
+			),
465
+			'EE_Front_Controller'                                                                                         => array(
466
+				'EE_Registry'              => EE_Dependency_Map::load_from_cache,
467
+				'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
468
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
469
+			),
470
+			'EE_Messenger_Collection_Loader'                                                                              => array(
471
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
472
+			),
473
+			'EE_Message_Type_Collection_Loader'                                                                           => array(
474
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
475
+			),
476
+			'EE_Message_Resource_Manager'                                                                                 => array(
477
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
478
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
479
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
480
+			),
481
+			'EE_Message_Factory'                                                                                          => array(
482
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
483
+			),
484
+			'EE_messages'                                                                                                 => array(
485
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
486
+			),
487
+			'EE_Messages_Generator'                                                                                       => array(
488
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
489
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
490
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
491
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
492
+			),
493
+			'EE_Messages_Processor'                                                                                       => array(
494
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
+			),
496
+			'EE_Messages_Queue'                                                                                           => array(
497
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
498
+			),
499
+			'EE_Messages_Template_Defaults'                                                                               => array(
500
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
501
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
502
+			),
503
+			'EE_Message_To_Generate_From_Request'                                                                         => array(
504
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
505
+				'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
506
+			),
507
+			'EventEspresso\core\services\commands\CommandBus'                                                             => array(
508
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
509
+			),
510
+			'EventEspresso\services\commands\CommandHandler'                                                              => array(
511
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
512
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
513
+			),
514
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
515
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
516
+			),
517
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
518
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
519
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
520
+			),
521
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
522
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
523
+			),
524
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
525
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
526
+			),
527
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
528
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
529
+			),
530
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
531
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
532
+			),
533
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
534
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
535
+			),
536
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
537
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
538
+			),
539
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
540
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
541
+			),
542
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
543
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
544
+			),
545
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
546
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
+			),
548
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
549
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
550
+			),
551
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
552
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
553
+			),
554
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
555
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
+			),
557
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
558
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
559
+			),
560
+			'EventEspresso\core\services\database\TableManager'                                                           => array(
561
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
562
+			),
563
+			'EE_Data_Migration_Class_Base'                                                                                => array(
564
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
565
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
566
+			),
567
+			'EE_DMS_Core_4_1_0'                                                                                           => array(
568
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
569
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
570
+			),
571
+			'EE_DMS_Core_4_2_0'                                                                                           => array(
572
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
573
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
574
+			),
575
+			'EE_DMS_Core_4_3_0'                                                                                           => array(
576
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
577
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
578
+			),
579
+			'EE_DMS_Core_4_4_0'                                                                                           => array(
580
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
581
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
582
+			),
583
+			'EE_DMS_Core_4_5_0'                                                                                           => array(
584
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
586
+			),
587
+			'EE_DMS_Core_4_6_0'                                                                                           => array(
588
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
589
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
590
+			),
591
+			'EE_DMS_Core_4_7_0'                                                                                           => array(
592
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
593
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
594
+			),
595
+			'EE_DMS_Core_4_8_0'                                                                                           => array(
596
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
597
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
598
+			),
599
+			'EE_DMS_Core_4_9_0'                                                                                           => array(
600
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
601
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
602
+			),
603
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
604
+				array(),
605
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
606
+			),
607
+			'EventEspresso\core\services\assets\Registry'                                                                 => array(
608
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
609
+				'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
610
+			),
611
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
612
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
613
+			),
614
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
615
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
616
+			),
617
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
618
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
619
+			),
620
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
621
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
622
+			),
623
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
624
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
625
+			),
626
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
627
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
628
+			),
629
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
630
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
631
+			),
632
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
633
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
634
+			),
635
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
636
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
637
+			),
638
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
639
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
640
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
641
+			),
642
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
643
+				null,
644
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
645
+			),
646
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
647
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
648
+			),
649
+			'LEGACY_MODELS'                                                                                               => array(
650
+				null,
651
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
652
+			),
653
+			'EE_Module_Request_Router'                                                                                    => array(
654
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
655
+			),
656
+			'EE_Registration_Processor'                                                                                   => array(
657
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
658
+			),
659
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
660
+				null,
661
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
662
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
663
+			),
664
+			'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
665
+				'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
666
+				'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
667
+			),
668
+			'EE_Admin_Transactions_List_Table'                                                                            => array(
669
+				null,
670
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
671
+			),
672
+			'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
673
+				'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
674
+				'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
675
+				'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
676
+			),
677
+			'EventEspresso\core\domain\services\pue\Config'                                                               => array(
678
+				'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
679
+				'EE_Config'         => EE_Dependency_Map::load_from_cache,
680
+			),
681
+			'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
682
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
683
+				'EEM_Event'          => EE_Dependency_Map::load_from_cache,
684
+				'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
685
+				'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
686
+				'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
687
+				'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
688
+				'EE_Config'          => EE_Dependency_Map::load_from_cache,
689
+			),
690
+			'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
691
+				'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
692
+			),
693
+			'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
694
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
695
+			),
696
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
697
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
698
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
699
+			),
700
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
701
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
702
+			),
703
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
704
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
705
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
706
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
707
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
708
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
709
+			),
710
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
711
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
712
+			),
713
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
714
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
715
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
716
+			),
717
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
718
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
719
+			),
720
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
721
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
722
+			),
723
+			'EE_CPT_Strategy'                                                                                             => array(
724
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
725
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
+			),
727
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
728
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
729
+			),
730
+			'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
731
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
732
+				'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
733
+				'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
734
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
735
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
736
+			),
737
+			'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
738
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
740
+			),
741
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
742
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
743
+			),
744
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
745
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
746
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
747
+			),
748
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
749
+				'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
750
+			),
751
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
752
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache,
753
+			),
754
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
755
+				'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
756
+			),
757
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
758
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
759
+			),
760
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
761
+				'EEM_Answer' => EE_Dependency_Map::load_from_cache,
762
+				'EEM_Question' => EE_Dependency_Map::load_from_cache,
763
+			),
764
+			'EventEspresso\core\CPTs\CptQueryModifier' => array(
765
+				null,
766
+				null,
767
+				null,
768
+				'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
769
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
770
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
771
+			),
772
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
773
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
774
+				'EE_Config' => EE_Dependency_Map::load_from_cache
775
+			),
776
+			'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
777
+				'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
778
+				'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
779
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
780
+				'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
781
+			),
782
+			'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
783
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
784
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
785
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
786
+			),
787
+			'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
788
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
789
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
790
+			),
791
+			'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
792
+				'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
793
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
794
+				'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
795
+			),
796
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
797
+				'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
798
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
799
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
800
+			),
801
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
802
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
803
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
804
+			),
805
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
806
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
807
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
808
+			),
809
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
810
+				'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
811
+			),
812
+			'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
813
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
814
+			),
815
+			'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
816
+				'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
817
+			),
818
+			'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
819
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
820
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
821
+			),
822
+			'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
823
+				'EEM_Event' => EE_Dependency_Map::load_from_cache,
824
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
825
+			),
826
+			'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
827
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
828
+			),
829
+			'EventEspresso\core\services\session\SessionStartHandler' => array(
830
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
831
+			),
832
+			'EE_URL_Validation_Strategy' => array(
833
+				null,
834
+				null,
835
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
836
+			),
837
+			'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
838
+				'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
839
+				'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
840
+				'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
841
+				'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
842
+				'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
843
+			),
844
+			'EventEspresso\core\services\address\CountrySubRegionDao' => array(
845
+				'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
846
+				'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
847
+			),
848
+			'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
849
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
850
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
851
+			),
852
+			'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
853
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
854
+				'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
855
+			),
856
+			'EventEspresso\core\services\request\files\FilesDataHandler' => array(
857
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
858
+			),
859
+			'EventEspressoBatchRequest\BatchRequestProcessor' => [
860
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
861
+			]
862
+		);
863
+	}
864
+
865
+
866
+	/**
867
+	 * Registers how core classes are loaded.
868
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
869
+	 *        'EE_Request_Handler' => 'load_core'
870
+	 *        'EE_Messages_Queue'  => 'load_lib'
871
+	 *        'EEH_Debug_Tools'    => 'load_helper'
872
+	 * or, if greater control is required, by providing a custom closure. For example:
873
+	 *        'Some_Class' => function () {
874
+	 *            return new Some_Class();
875
+	 *        },
876
+	 * This is required for instantiating dependencies
877
+	 * where an interface has been type hinted in a class constructor. For example:
878
+	 *        'Required_Interface' => function () {
879
+	 *            return new A_Class_That_Implements_Required_Interface();
880
+	 *        },
881
+	 */
882
+	protected function _register_core_class_loaders()
883
+	{
884
+		$this->_class_loaders = array(
885
+			// load_core
886
+			'EE_Dependency_Map'                            => function () {
887
+				return $this;
888
+			},
889
+			'EE_Capabilities'                              => 'load_core',
890
+			'EE_Encryption'                                => 'load_core',
891
+			'EE_Front_Controller'                          => 'load_core',
892
+			'EE_Module_Request_Router'                     => 'load_core',
893
+			'EE_Registry'                                  => 'load_core',
894
+			'EE_Request'                                   => function () {
895
+				return $this->legacy_request;
896
+			},
897
+			'EventEspresso\core\services\request\Request'  => function () {
898
+				return $this->request;
899
+			},
900
+			'EventEspresso\core\services\request\Response' => function () {
901
+				return $this->response;
902
+			},
903
+			'EE_Base'                                      => 'load_core',
904
+			'EE_Request_Handler'                           => 'load_core',
905
+			'EE_Session'                                   => 'load_core',
906
+			'EE_Cron_Tasks'                                => 'load_core',
907
+			'EE_System'                                    => 'load_core',
908
+			'EE_Maintenance_Mode'                          => 'load_core',
909
+			'EE_Register_CPTs'                             => 'load_core',
910
+			'EE_Admin'                                     => 'load_core',
911
+			'EE_CPT_Strategy'                              => 'load_core',
912
+			// load_class
913
+			'EE_Registration_Processor'                    => 'load_class',
914
+			// load_lib
915
+			'EE_Message_Resource_Manager'                  => 'load_lib',
916
+			'EE_Message_Type_Collection'                   => 'load_lib',
917
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
918
+			'EE_Messenger_Collection'                      => 'load_lib',
919
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
920
+			'EE_Messages_Processor'                        => 'load_lib',
921
+			'EE_Message_Repository'                        => 'load_lib',
922
+			'EE_Messages_Queue'                            => 'load_lib',
923
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
924
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
925
+			'EE_Payment_Method_Manager'                    => 'load_lib',
926
+			'EE_Messages_Generator'                        => function () {
927
+				return EE_Registry::instance()->load_lib(
928
+					'Messages_Generator',
929
+					array(),
930
+					false,
931
+					false
932
+				);
933
+			},
934
+			'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
935
+				return EE_Registry::instance()->load_lib(
936
+					'Messages_Template_Defaults',
937
+					$arguments,
938
+					false,
939
+					false
940
+				);
941
+			},
942
+			// load_helper
943
+			'EEH_Parse_Shortcodes'                         => function () {
944
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
945
+					return new EEH_Parse_Shortcodes();
946
+				}
947
+				return null;
948
+			},
949
+			'EE_Template_Config'                           => function () {
950
+				return EE_Config::instance()->template_settings;
951
+			},
952
+			'EE_Currency_Config'                           => function () {
953
+				return EE_Config::instance()->currency;
954
+			},
955
+			'EE_Registration_Config'                       => function () {
956
+				return EE_Config::instance()->registration;
957
+			},
958
+			'EE_Core_Config'                               => function () {
959
+				return EE_Config::instance()->core;
960
+			},
961
+			'EventEspresso\core\services\loaders\Loader'   => function () {
962
+				return LoaderFactory::getLoader();
963
+			},
964
+			'EE_Network_Config'                            => function () {
965
+				return EE_Network_Config::instance();
966
+			},
967
+			'EE_Config'                                    => function () {
968
+				return EE_Config::instance();
969
+			},
970
+			'EventEspresso\core\domain\Domain'             => function () {
971
+				return DomainFactory::getEventEspressoCoreDomain();
972
+			},
973
+			'EE_Admin_Config'                              => function () {
974
+				return EE_Config::instance()->admin;
975
+			},
976
+			'EE_Organization_Config'                       => function () {
977
+				return EE_Config::instance()->organization;
978
+			},
979
+			'EE_Network_Core_Config'                       => function () {
980
+				return EE_Network_Config::instance()->core;
981
+			},
982
+			'EE_Environment_Config'                        => function () {
983
+				return EE_Config::instance()->environment;
984
+			},
985
+		);
986
+	}
987
+
988
+
989
+	/**
990
+	 * can be used for supplying alternate names for classes,
991
+	 * or for connecting interface names to instantiable classes
992
+	 */
993
+	protected function _register_core_aliases()
994
+	{
995
+		$aliases = array(
996
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
997
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
998
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
999
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1000
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1001
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1002
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1003
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1004
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1005
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1006
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1007
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1008
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1009
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1010
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1011
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1012
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1013
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1014
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1015
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1016
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1017
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1018
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1019
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1020
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1021
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1022
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1023
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1024
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1025
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1026
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1027
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1028
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1029
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1030
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1031
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1032
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1033
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1034
+		);
1035
+		foreach ($aliases as $alias => $fqn) {
1036
+			if (is_array($fqn)) {
1037
+				foreach ($fqn as $class => $for_class) {
1038
+					$this->class_cache->addAlias($class, $alias, $for_class);
1039
+				}
1040
+				continue;
1041
+			}
1042
+			$this->class_cache->addAlias($fqn, $alias);
1043
+		}
1044
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1045
+			$this->class_cache->addAlias(
1046
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1047
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1048
+			);
1049
+		}
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1055
+	 * request Primarily used by unit tests.
1056
+	 */
1057
+	public function reset()
1058
+	{
1059
+		$this->_register_core_class_loaders();
1060
+		$this->_register_core_dependencies();
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * PLZ NOTE: a better name for this method would be is_alias()
1066
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1067
+	 * WHY?
1068
+	 * Because if a class is type hinting for a concretion,
1069
+	 * then why would we need to find another class to supply it?
1070
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1071
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1072
+	 * Don't go looking for some substitute.
1073
+	 * Whereas if a class is type hinting for an interface...
1074
+	 * then we need to find an actual class to use.
1075
+	 * So the interface IS the alias for some other FQN,
1076
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1077
+	 * represents some other class.
1078
+	 *
1079
+	 * @deprecated 4.9.62.p
1080
+	 * @param string $fqn
1081
+	 * @param string $for_class
1082
+	 * @return bool
1083
+	 */
1084
+	public function has_alias($fqn = '', $for_class = '')
1085
+	{
1086
+		return $this->isAlias($fqn, $for_class);
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1092
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1093
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1094
+	 *  for example:
1095
+	 *      if the following two entries were added to the _aliases array:
1096
+	 *          array(
1097
+	 *              'interface_alias'           => 'some\namespace\interface'
1098
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1099
+	 *          )
1100
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1101
+	 *      to load an instance of 'some\namespace\classname'
1102
+	 *
1103
+	 * @deprecated 4.9.62.p
1104
+	 * @param string $alias
1105
+	 * @param string $for_class
1106
+	 * @return string
1107
+	 */
1108
+	public function get_alias($alias = '', $for_class = '')
1109
+	{
1110
+		return $this->getFqnForAlias($alias, $for_class);
1111
+	}
1112 1112
 }
Please login to merge, or discard this patch.