Completed
Branch master (8d9631)
by
unknown
56:07 queued 43:57
created
core/EE_Dependency_Map.core.php 1 patch
Indentation   +1139 added lines, -1139 removed lines patch added patch discarded remove patch
@@ -20,1143 +20,1143 @@
 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
-            'EE_DMS_Core_4_10_0' => array(
604
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
605
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
606
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
607
-            ),
608
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
609
-                array(),
610
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
611
-            ),
612
-            'EventEspresso\core\services\assets\Registry'                                                                 => array(
613
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
614
-                'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
615
-            ),
616
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
617
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
618
-            ),
619
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
620
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
621
-            ),
622
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
623
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
624
-            ),
625
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
626
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
627
-            ),
628
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
629
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
630
-            ),
631
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
632
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
633
-            ),
634
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
635
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
636
-            ),
637
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
638
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
639
-            ),
640
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
641
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
642
-            ),
643
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
644
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
645
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
646
-            ),
647
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
648
-                null,
649
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
650
-            ),
651
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
652
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
653
-            ),
654
-            'LEGACY_MODELS'                                                                                               => array(
655
-                null,
656
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
657
-            ),
658
-            'EE_Module_Request_Router'                                                                                    => array(
659
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
660
-            ),
661
-            'EE_Registration_Processor'                                                                                   => array(
662
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
663
-            ),
664
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
665
-                null,
666
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
667
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
668
-            ),
669
-            'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
670
-                'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
671
-                'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
672
-            ),
673
-            'EE_Admin_Transactions_List_Table'                                                                            => array(
674
-                null,
675
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
676
-            ),
677
-            'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
678
-                'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
679
-                'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
680
-                'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
681
-            ),
682
-            'EventEspresso\core\domain\services\pue\Config'                                                               => array(
683
-                'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
684
-                'EE_Config'         => EE_Dependency_Map::load_from_cache,
685
-            ),
686
-            'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
687
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
688
-                'EEM_Event'          => EE_Dependency_Map::load_from_cache,
689
-                'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
690
-                'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
691
-                'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
692
-                'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
693
-                'EE_Config'          => EE_Dependency_Map::load_from_cache,
694
-            ),
695
-            'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
696
-                'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
697
-            ),
698
-            'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
699
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
700
-            ),
701
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
702
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
703
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
704
-            ),
705
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
706
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
707
-            ),
708
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
709
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
710
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
711
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
712
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
713
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
714
-            ),
715
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
716
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
717
-            ),
718
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
719
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
720
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
-            ),
722
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
723
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
724
-            ),
725
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
726
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
727
-            ),
728
-            'EE_CPT_Strategy'                                                                                             => array(
729
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
730
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
731
-            ),
732
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
733
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
734
-            ),
735
-            'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
736
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
737
-                'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
738
-                'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
740
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
-            ),
742
-            'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
743
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
744
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
745
-            ),
746
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
747
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
748
-            ),
749
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
750
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
751
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
752
-            ),
753
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
754
-                'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
755
-            ),
756
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
757
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache,
758
-            ),
759
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
760
-                'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
761
-            ),
762
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
763
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
764
-            ),
765
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
766
-                'EEM_Answer' => EE_Dependency_Map::load_from_cache,
767
-                'EEM_Question' => EE_Dependency_Map::load_from_cache,
768
-            ),
769
-            'EventEspresso\core\CPTs\CptQueryModifier' => array(
770
-                null,
771
-                null,
772
-                null,
773
-                'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
774
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
775
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
776
-            ),
777
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
778
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
779
-                'EE_Config' => EE_Dependency_Map::load_from_cache
780
-            ),
781
-            'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
782
-                'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
783
-                'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
784
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
785
-                'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
786
-            ),
787
-            'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
788
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
789
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
790
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
791
-            ),
792
-            'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
793
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
795
-            ),
796
-            'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
797
-                'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
798
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
799
-                'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
800
-            ),
801
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
802
-                'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
803
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
804
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
805
-            ),
806
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
807
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
808
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
809
-            ),
810
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
811
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
812
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
813
-            ),
814
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
815
-                'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
816
-            ),
817
-            'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
818
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
819
-            ),
820
-            'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
821
-                'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
822
-            ),
823
-            'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
824
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
825
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
826
-            ),
827
-            'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
828
-                'EEM_Event' => EE_Dependency_Map::load_from_cache,
829
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
830
-            ),
831
-            'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
832
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
833
-            ),
834
-            'EventEspresso\core\services\session\SessionStartHandler' => array(
835
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
-            ),
837
-            'EE_URL_Validation_Strategy' => array(
838
-                null,
839
-                null,
840
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
841
-            ),
842
-            'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
843
-                'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
844
-                'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
845
-                'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
846
-                'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
847
-                'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
848
-            ),
849
-            'EventEspresso\core\services\address\CountrySubRegionDao' => array(
850
-                'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
851
-                'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
852
-            ),
853
-            'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
854
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
855
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
856
-            ),
857
-            'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
858
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
859
-                'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
860
-            ),
861
-            'EventEspresso\core\services\request\files\FilesDataHandler' => array(
862
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
863
-            ),
864
-            'EventEspressoBatchRequest\BatchRequestProcessor' => [
865
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
866
-            ],
867
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder' => [
868
-                null,
869
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
870
-                'EEM_Registration'  => EE_Dependency_Map::load_from_cache,
871
-            ],
872
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader' => [
873
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
874
-                'EEM_Attendee'  => EE_Dependency_Map::load_from_cache,
875
-            ],
876
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader' => [
877
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
878
-                'EEM_Datetime'  => EE_Dependency_Map::load_from_cache,
879
-            ],
880
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader' => [
881
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
882
-                'EEM_Event'  => EE_Dependency_Map::load_from_cache,
883
-            ],
884
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader' => [
885
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
886
-                'EEM_Ticket'  => EE_Dependency_Map::load_from_cache,
887
-            ],
888
-            'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion' => [
889
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache
890
-            ],
891
-            'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion' => [
892
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache
893
-            ],
894
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion' => [
895
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
896
-                'EEM_Event' => EE_Dependency_Map::load_from_cache,
897
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
898
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
899
-            ],
900
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion' => [
901
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
902
-            ]
903
-        );
904
-    }
905
-
906
-
907
-    /**
908
-     * Registers how core classes are loaded.
909
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
910
-     *        'EE_Request_Handler' => 'load_core'
911
-     *        'EE_Messages_Queue'  => 'load_lib'
912
-     *        'EEH_Debug_Tools'    => 'load_helper'
913
-     * or, if greater control is required, by providing a custom closure. For example:
914
-     *        'Some_Class' => function () {
915
-     *            return new Some_Class();
916
-     *        },
917
-     * This is required for instantiating dependencies
918
-     * where an interface has been type hinted in a class constructor. For example:
919
-     *        'Required_Interface' => function () {
920
-     *            return new A_Class_That_Implements_Required_Interface();
921
-     *        },
922
-     */
923
-    protected function _register_core_class_loaders()
924
-    {
925
-        $this->_class_loaders = array(
926
-            // load_core
927
-            'EE_Dependency_Map'                            => function () {
928
-                return $this;
929
-            },
930
-            'EE_Capabilities'                              => 'load_core',
931
-            'EE_Encryption'                                => 'load_core',
932
-            'EE_Front_Controller'                          => 'load_core',
933
-            'EE_Module_Request_Router'                     => 'load_core',
934
-            'EE_Registry'                                  => 'load_core',
935
-            'EE_Request'                                   => function () {
936
-                return $this->legacy_request;
937
-            },
938
-            'EventEspresso\core\services\request\Request'  => function () {
939
-                return $this->request;
940
-            },
941
-            'EventEspresso\core\services\request\Response' => function () {
942
-                return $this->response;
943
-            },
944
-            'EE_Base'                                      => 'load_core',
945
-            'EE_Request_Handler'                           => 'load_core',
946
-            'EE_Session'                                   => 'load_core',
947
-            'EE_Cron_Tasks'                                => 'load_core',
948
-            'EE_System'                                    => 'load_core',
949
-            'EE_Maintenance_Mode'                          => 'load_core',
950
-            'EE_Register_CPTs'                             => 'load_core',
951
-            'EE_Admin'                                     => 'load_core',
952
-            'EE_CPT_Strategy'                              => 'load_core',
953
-            // load_class
954
-            'EE_Registration_Processor'                    => 'load_class',
955
-            // load_lib
956
-            'EE_Message_Resource_Manager'                  => 'load_lib',
957
-            'EE_Message_Type_Collection'                   => 'load_lib',
958
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
959
-            'EE_Messenger_Collection'                      => 'load_lib',
960
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
961
-            'EE_Messages_Processor'                        => 'load_lib',
962
-            'EE_Message_Repository'                        => 'load_lib',
963
-            'EE_Messages_Queue'                            => 'load_lib',
964
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
965
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
966
-            'EE_Payment_Method_Manager'                    => 'load_lib',
967
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
968
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
969
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
970
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
971
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
972
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
973
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
974
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
975
-            'EE_DMS_Core_4_10_0'                            => 'load_dms',
976
-            'EE_Messages_Generator'                        => function () {
977
-                return EE_Registry::instance()->load_lib(
978
-                    'Messages_Generator',
979
-                    array(),
980
-                    false,
981
-                    false
982
-                );
983
-            },
984
-            'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
985
-                return EE_Registry::instance()->load_lib(
986
-                    'Messages_Template_Defaults',
987
-                    $arguments,
988
-                    false,
989
-                    false
990
-                );
991
-            },
992
-            // load_helper
993
-            'EEH_Parse_Shortcodes'                         => function () {
994
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
995
-                    return new EEH_Parse_Shortcodes();
996
-                }
997
-                return null;
998
-            },
999
-            'EE_Template_Config'                           => function () {
1000
-                return EE_Config::instance()->template_settings;
1001
-            },
1002
-            'EE_Currency_Config'                           => function () {
1003
-                return EE_Config::instance()->currency;
1004
-            },
1005
-            'EE_Registration_Config'                       => function () {
1006
-                return EE_Config::instance()->registration;
1007
-            },
1008
-            'EE_Core_Config'                               => function () {
1009
-                return EE_Config::instance()->core;
1010
-            },
1011
-            'EventEspresso\core\services\loaders\Loader'   => function () {
1012
-                return LoaderFactory::getLoader();
1013
-            },
1014
-            'EE_Network_Config'                            => function () {
1015
-                return EE_Network_Config::instance();
1016
-            },
1017
-            'EE_Config'                                    => function () {
1018
-                return EE_Config::instance();
1019
-            },
1020
-            'EventEspresso\core\domain\Domain'             => function () {
1021
-                return DomainFactory::getEventEspressoCoreDomain();
1022
-            },
1023
-            'EE_Admin_Config'                              => function () {
1024
-                return EE_Config::instance()->admin;
1025
-            },
1026
-            'EE_Organization_Config'                       => function () {
1027
-                return EE_Config::instance()->organization;
1028
-            },
1029
-            'EE_Network_Core_Config'                       => function () {
1030
-                return EE_Network_Config::instance()->core;
1031
-            },
1032
-            'EE_Environment_Config'                        => function () {
1033
-                return EE_Config::instance()->environment;
1034
-            },
1035
-        );
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * can be used for supplying alternate names for classes,
1041
-     * or for connecting interface names to instantiable classes
1042
-     */
1043
-    protected function _register_core_aliases()
1044
-    {
1045
-        $aliases = array(
1046
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1047
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1048
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1049
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1050
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1051
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1052
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1053
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1054
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1055
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1056
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1057
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1058
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1059
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1060
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1061
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1062
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1063
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1064
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1065
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1066
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1067
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1068
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1069
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1070
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1071
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1072
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1073
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1074
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1075
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1076
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1077
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1078
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1079
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1080
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1081
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1082
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1083
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1084
-        );
1085
-        foreach ($aliases as $alias => $fqn) {
1086
-            if (is_array($fqn)) {
1087
-                foreach ($fqn as $class => $for_class) {
1088
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1089
-                }
1090
-                continue;
1091
-            }
1092
-            $this->class_cache->addAlias($fqn, $alias);
1093
-        }
1094
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1095
-            $this->class_cache->addAlias(
1096
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1097
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1098
-            );
1099
-        }
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1105
-     * request Primarily used by unit tests.
1106
-     */
1107
-    public function reset()
1108
-    {
1109
-        $this->_register_core_class_loaders();
1110
-        $this->_register_core_dependencies();
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * PLZ NOTE: a better name for this method would be is_alias()
1116
-     * because it returns TRUE if the provided fully qualified name IS an alias
1117
-     * WHY?
1118
-     * Because if a class is type hinting for a concretion,
1119
-     * then why would we need to find another class to supply it?
1120
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1121
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1122
-     * Don't go looking for some substitute.
1123
-     * Whereas if a class is type hinting for an interface...
1124
-     * then we need to find an actual class to use.
1125
-     * So the interface IS the alias for some other FQN,
1126
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1127
-     * represents some other class.
1128
-     *
1129
-     * @deprecated 4.9.62.p
1130
-     * @param string $fqn
1131
-     * @param string $for_class
1132
-     * @return bool
1133
-     */
1134
-    public function has_alias($fqn = '', $for_class = '')
1135
-    {
1136
-        return $this->isAlias($fqn, $for_class);
1137
-    }
1138
-
1139
-
1140
-    /**
1141
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1142
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1143
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1144
-     *  for example:
1145
-     *      if the following two entries were added to the _aliases array:
1146
-     *          array(
1147
-     *              'interface_alias'           => 'some\namespace\interface'
1148
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1149
-     *          )
1150
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1151
-     *      to load an instance of 'some\namespace\classname'
1152
-     *
1153
-     * @deprecated 4.9.62.p
1154
-     * @param string $alias
1155
-     * @param string $for_class
1156
-     * @return string
1157
-     */
1158
-    public function get_alias($alias = '', $for_class = '')
1159
-    {
1160
-        return $this->getFqnForAlias($alias, $for_class);
1161
-    }
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
+			'EE_DMS_Core_4_10_0' => array(
604
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
605
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
606
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
607
+			),
608
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
609
+				array(),
610
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
611
+			),
612
+			'EventEspresso\core\services\assets\Registry'                                                                 => array(
613
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
614
+				'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
615
+			),
616
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
617
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
618
+			),
619
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
620
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
621
+			),
622
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
623
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
624
+			),
625
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
626
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
627
+			),
628
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
629
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
630
+			),
631
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
632
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
633
+			),
634
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
635
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
636
+			),
637
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
638
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
639
+			),
640
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
641
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
642
+			),
643
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
644
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
645
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
646
+			),
647
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
648
+				null,
649
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
650
+			),
651
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
652
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
653
+			),
654
+			'LEGACY_MODELS'                                                                                               => array(
655
+				null,
656
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
657
+			),
658
+			'EE_Module_Request_Router'                                                                                    => array(
659
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
660
+			),
661
+			'EE_Registration_Processor'                                                                                   => array(
662
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
663
+			),
664
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
665
+				null,
666
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
667
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
668
+			),
669
+			'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
670
+				'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
671
+				'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
672
+			),
673
+			'EE_Admin_Transactions_List_Table'                                                                            => array(
674
+				null,
675
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
676
+			),
677
+			'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
678
+				'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
679
+				'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
680
+				'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
681
+			),
682
+			'EventEspresso\core\domain\services\pue\Config'                                                               => array(
683
+				'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
684
+				'EE_Config'         => EE_Dependency_Map::load_from_cache,
685
+			),
686
+			'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
687
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
688
+				'EEM_Event'          => EE_Dependency_Map::load_from_cache,
689
+				'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
690
+				'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
691
+				'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
692
+				'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
693
+				'EE_Config'          => EE_Dependency_Map::load_from_cache,
694
+			),
695
+			'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
696
+				'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
697
+			),
698
+			'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
699
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
700
+			),
701
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
702
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
703
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
704
+			),
705
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
706
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
707
+			),
708
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
709
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
710
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
711
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
712
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
713
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
714
+			),
715
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
716
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
717
+			),
718
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
719
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
720
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
+			),
722
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
723
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
724
+			),
725
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
726
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
727
+			),
728
+			'EE_CPT_Strategy'                                                                                             => array(
729
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
730
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
731
+			),
732
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
733
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
734
+			),
735
+			'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
736
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
737
+				'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
738
+				'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
740
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
+			),
742
+			'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
743
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
744
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
745
+			),
746
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
747
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
748
+			),
749
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
750
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
751
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
752
+			),
753
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
754
+				'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
755
+			),
756
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
757
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache,
758
+			),
759
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
760
+				'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
761
+			),
762
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
763
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
764
+			),
765
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
766
+				'EEM_Answer' => EE_Dependency_Map::load_from_cache,
767
+				'EEM_Question' => EE_Dependency_Map::load_from_cache,
768
+			),
769
+			'EventEspresso\core\CPTs\CptQueryModifier' => array(
770
+				null,
771
+				null,
772
+				null,
773
+				'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
774
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
775
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
776
+			),
777
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
778
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
779
+				'EE_Config' => EE_Dependency_Map::load_from_cache
780
+			),
781
+			'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
782
+				'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
783
+				'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
784
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
785
+				'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
786
+			),
787
+			'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
788
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
789
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
790
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
791
+			),
792
+			'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
793
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
795
+			),
796
+			'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
797
+				'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
798
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
799
+				'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
800
+			),
801
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
802
+				'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
803
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
804
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
805
+			),
806
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
807
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
808
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
809
+			),
810
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
811
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
812
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
813
+			),
814
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
815
+				'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
816
+			),
817
+			'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
818
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
819
+			),
820
+			'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
821
+				'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
822
+			),
823
+			'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
824
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
825
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
826
+			),
827
+			'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
828
+				'EEM_Event' => EE_Dependency_Map::load_from_cache,
829
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
830
+			),
831
+			'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
832
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
833
+			),
834
+			'EventEspresso\core\services\session\SessionStartHandler' => array(
835
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
+			),
837
+			'EE_URL_Validation_Strategy' => array(
838
+				null,
839
+				null,
840
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
841
+			),
842
+			'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
843
+				'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
844
+				'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
845
+				'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
846
+				'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
847
+				'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
848
+			),
849
+			'EventEspresso\core\services\address\CountrySubRegionDao' => array(
850
+				'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
851
+				'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
852
+			),
853
+			'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
854
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
855
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
856
+			),
857
+			'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
858
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
859
+				'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
860
+			),
861
+			'EventEspresso\core\services\request\files\FilesDataHandler' => array(
862
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
863
+			),
864
+			'EventEspressoBatchRequest\BatchRequestProcessor' => [
865
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
866
+			],
867
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder' => [
868
+				null,
869
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
870
+				'EEM_Registration'  => EE_Dependency_Map::load_from_cache,
871
+			],
872
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader' => [
873
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
874
+				'EEM_Attendee'  => EE_Dependency_Map::load_from_cache,
875
+			],
876
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader' => [
877
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
878
+				'EEM_Datetime'  => EE_Dependency_Map::load_from_cache,
879
+			],
880
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader' => [
881
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
882
+				'EEM_Event'  => EE_Dependency_Map::load_from_cache,
883
+			],
884
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader' => [
885
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
886
+				'EEM_Ticket'  => EE_Dependency_Map::load_from_cache,
887
+			],
888
+			'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion' => [
889
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache
890
+			],
891
+			'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion' => [
892
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache
893
+			],
894
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion' => [
895
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
896
+				'EEM_Event' => EE_Dependency_Map::load_from_cache,
897
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
898
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
899
+			],
900
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion' => [
901
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
902
+			]
903
+		);
904
+	}
905
+
906
+
907
+	/**
908
+	 * Registers how core classes are loaded.
909
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
910
+	 *        'EE_Request_Handler' => 'load_core'
911
+	 *        'EE_Messages_Queue'  => 'load_lib'
912
+	 *        'EEH_Debug_Tools'    => 'load_helper'
913
+	 * or, if greater control is required, by providing a custom closure. For example:
914
+	 *        'Some_Class' => function () {
915
+	 *            return new Some_Class();
916
+	 *        },
917
+	 * This is required for instantiating dependencies
918
+	 * where an interface has been type hinted in a class constructor. For example:
919
+	 *        'Required_Interface' => function () {
920
+	 *            return new A_Class_That_Implements_Required_Interface();
921
+	 *        },
922
+	 */
923
+	protected function _register_core_class_loaders()
924
+	{
925
+		$this->_class_loaders = array(
926
+			// load_core
927
+			'EE_Dependency_Map'                            => function () {
928
+				return $this;
929
+			},
930
+			'EE_Capabilities'                              => 'load_core',
931
+			'EE_Encryption'                                => 'load_core',
932
+			'EE_Front_Controller'                          => 'load_core',
933
+			'EE_Module_Request_Router'                     => 'load_core',
934
+			'EE_Registry'                                  => 'load_core',
935
+			'EE_Request'                                   => function () {
936
+				return $this->legacy_request;
937
+			},
938
+			'EventEspresso\core\services\request\Request'  => function () {
939
+				return $this->request;
940
+			},
941
+			'EventEspresso\core\services\request\Response' => function () {
942
+				return $this->response;
943
+			},
944
+			'EE_Base'                                      => 'load_core',
945
+			'EE_Request_Handler'                           => 'load_core',
946
+			'EE_Session'                                   => 'load_core',
947
+			'EE_Cron_Tasks'                                => 'load_core',
948
+			'EE_System'                                    => 'load_core',
949
+			'EE_Maintenance_Mode'                          => 'load_core',
950
+			'EE_Register_CPTs'                             => 'load_core',
951
+			'EE_Admin'                                     => 'load_core',
952
+			'EE_CPT_Strategy'                              => 'load_core',
953
+			// load_class
954
+			'EE_Registration_Processor'                    => 'load_class',
955
+			// load_lib
956
+			'EE_Message_Resource_Manager'                  => 'load_lib',
957
+			'EE_Message_Type_Collection'                   => 'load_lib',
958
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
959
+			'EE_Messenger_Collection'                      => 'load_lib',
960
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
961
+			'EE_Messages_Processor'                        => 'load_lib',
962
+			'EE_Message_Repository'                        => 'load_lib',
963
+			'EE_Messages_Queue'                            => 'load_lib',
964
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
965
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
966
+			'EE_Payment_Method_Manager'                    => 'load_lib',
967
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
968
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
969
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
970
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
971
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
972
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
973
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
974
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
975
+			'EE_DMS_Core_4_10_0'                            => 'load_dms',
976
+			'EE_Messages_Generator'                        => function () {
977
+				return EE_Registry::instance()->load_lib(
978
+					'Messages_Generator',
979
+					array(),
980
+					false,
981
+					false
982
+				);
983
+			},
984
+			'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
985
+				return EE_Registry::instance()->load_lib(
986
+					'Messages_Template_Defaults',
987
+					$arguments,
988
+					false,
989
+					false
990
+				);
991
+			},
992
+			// load_helper
993
+			'EEH_Parse_Shortcodes'                         => function () {
994
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
995
+					return new EEH_Parse_Shortcodes();
996
+				}
997
+				return null;
998
+			},
999
+			'EE_Template_Config'                           => function () {
1000
+				return EE_Config::instance()->template_settings;
1001
+			},
1002
+			'EE_Currency_Config'                           => function () {
1003
+				return EE_Config::instance()->currency;
1004
+			},
1005
+			'EE_Registration_Config'                       => function () {
1006
+				return EE_Config::instance()->registration;
1007
+			},
1008
+			'EE_Core_Config'                               => function () {
1009
+				return EE_Config::instance()->core;
1010
+			},
1011
+			'EventEspresso\core\services\loaders\Loader'   => function () {
1012
+				return LoaderFactory::getLoader();
1013
+			},
1014
+			'EE_Network_Config'                            => function () {
1015
+				return EE_Network_Config::instance();
1016
+			},
1017
+			'EE_Config'                                    => function () {
1018
+				return EE_Config::instance();
1019
+			},
1020
+			'EventEspresso\core\domain\Domain'             => function () {
1021
+				return DomainFactory::getEventEspressoCoreDomain();
1022
+			},
1023
+			'EE_Admin_Config'                              => function () {
1024
+				return EE_Config::instance()->admin;
1025
+			},
1026
+			'EE_Organization_Config'                       => function () {
1027
+				return EE_Config::instance()->organization;
1028
+			},
1029
+			'EE_Network_Core_Config'                       => function () {
1030
+				return EE_Network_Config::instance()->core;
1031
+			},
1032
+			'EE_Environment_Config'                        => function () {
1033
+				return EE_Config::instance()->environment;
1034
+			},
1035
+		);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * can be used for supplying alternate names for classes,
1041
+	 * or for connecting interface names to instantiable classes
1042
+	 */
1043
+	protected function _register_core_aliases()
1044
+	{
1045
+		$aliases = array(
1046
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1047
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1048
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1049
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1050
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1051
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1052
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1053
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1054
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1055
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1056
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1057
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1058
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1059
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1060
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1061
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1062
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1063
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1064
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1065
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1066
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1067
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1068
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1069
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1070
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1071
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1072
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1073
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1074
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1075
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1076
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1077
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1078
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1079
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1080
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1081
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1082
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1083
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1084
+		);
1085
+		foreach ($aliases as $alias => $fqn) {
1086
+			if (is_array($fqn)) {
1087
+				foreach ($fqn as $class => $for_class) {
1088
+					$this->class_cache->addAlias($class, $alias, $for_class);
1089
+				}
1090
+				continue;
1091
+			}
1092
+			$this->class_cache->addAlias($fqn, $alias);
1093
+		}
1094
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1095
+			$this->class_cache->addAlias(
1096
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1097
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1098
+			);
1099
+		}
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1105
+	 * request Primarily used by unit tests.
1106
+	 */
1107
+	public function reset()
1108
+	{
1109
+		$this->_register_core_class_loaders();
1110
+		$this->_register_core_dependencies();
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * PLZ NOTE: a better name for this method would be is_alias()
1116
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1117
+	 * WHY?
1118
+	 * Because if a class is type hinting for a concretion,
1119
+	 * then why would we need to find another class to supply it?
1120
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1121
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1122
+	 * Don't go looking for some substitute.
1123
+	 * Whereas if a class is type hinting for an interface...
1124
+	 * then we need to find an actual class to use.
1125
+	 * So the interface IS the alias for some other FQN,
1126
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1127
+	 * represents some other class.
1128
+	 *
1129
+	 * @deprecated 4.9.62.p
1130
+	 * @param string $fqn
1131
+	 * @param string $for_class
1132
+	 * @return bool
1133
+	 */
1134
+	public function has_alias($fqn = '', $for_class = '')
1135
+	{
1136
+		return $this->isAlias($fqn, $for_class);
1137
+	}
1138
+
1139
+
1140
+	/**
1141
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1142
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1143
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1144
+	 *  for example:
1145
+	 *      if the following two entries were added to the _aliases array:
1146
+	 *          array(
1147
+	 *              'interface_alias'           => 'some\namespace\interface'
1148
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1149
+	 *          )
1150
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1151
+	 *      to load an instance of 'some\namespace\classname'
1152
+	 *
1153
+	 * @deprecated 4.9.62.p
1154
+	 * @param string $alias
1155
+	 * @param string $for_class
1156
+	 * @return string
1157
+	 */
1158
+	public function get_alias($alias = '', $for_class = '')
1159
+	{
1160
+		return $this->getFqnForAlias($alias, $for_class);
1161
+	}
1162 1162
 }
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/PreviewEventDeletion.php 3 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -199,7 +199,7 @@
 block discarded – undo
199 199
             if ($units_processed >= $batch_size) {
200 200
                 break;
201 201
             }
202
-            if (!$root_node instanceof ModelObjNode) {
202
+            if ( ! $root_node instanceof ModelObjNode) {
203 203
                 throw new InvalidClassException('ModelObjNode');
204 204
             }
205 205
             if ($root_node->isComplete()) {
Please login to merge, or discard this patch.
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -36,149 +36,149 @@  discard block
 block discarded – undo
36 36
 class PreviewEventDeletion extends JobHandler
37 37
 {
38 38
 
39
-    /**
40
-     * @var NodeGroupDao
41
-     */
42
-    protected $model_obj_node_group_persister;
39
+	/**
40
+	 * @var NodeGroupDao
41
+	 */
42
+	protected $model_obj_node_group_persister;
43 43
 
44
-    public function __construct(NodeGroupDao $model_obj_node_group_persister)
45
-    {
46
-        $this->model_obj_node_group_persister = $model_obj_node_group_persister;
47
-    }
44
+	public function __construct(NodeGroupDao $model_obj_node_group_persister)
45
+	{
46
+		$this->model_obj_node_group_persister = $model_obj_node_group_persister;
47
+	}
48 48
 
49
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
49
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
50 50
 
51
-    /**
52
-     *
53
-     * @param JobParameters $job_parameters
54
-     * @return JobStepResponse
55
-     * @throws EE_Error
56
-     * @throws InvalidDataTypeException
57
-     * @throws InvalidInterfaceException
58
-     * @throws InvalidArgumentException
59
-     * @throws ReflectionException
60
-     */
61
-    public function create_job(JobParameters $job_parameters)
62
-    {
63
-        // Set the "root" model objects we will want to delete (record their ID and model)
64
-        $event_ids = $job_parameters->request_datum('EVT_IDs', array());
65
-        // Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
66
-        // prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
67
-        // we have no UI to access them independent of events, so they may as well get deleted too.)
68
-        $roots = [];
69
-        foreach ($event_ids as $event_id) {
70
-            $roots[] = new ModelObjNode(
71
-                $event_id,
72
-                EEM_Event::instance()
73
-            );
74
-            // Also, we want to delete their related, non-global, tickets, prices and message templates
75
-            $related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
76
-                [
77
-                    [
78
-                        'TKT_is_default' => false,
79
-                        'Datetime.EVT_ID' => $event_id
80
-                    ]
81
-                ]
82
-            );
83
-            foreach ($related_non_global_tickets as $ticket) {
84
-                $roots[] = new ModelObjNode(
85
-                    $ticket->ID(),
86
-                    $ticket->get_model(),
87
-                    ['Registration']
88
-                );
89
-            }
90
-            $related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
91
-                [
92
-                    [
93
-                        'PRC_is_default' => false,
94
-                        'Ticket.Datetime.EVT_ID' => $event_id
95
-                    ]
96
-                ]
97
-            );
98
-            foreach ($related_non_global_prices as $price) {
99
-                $roots[] = new ModelObjNode(
100
-                    $price->ID(),
101
-                    $price->get_model()
102
-                );
103
-            }
104
-        }
105
-        $transactions_ids = $this->getTransactionsToDelete($event_ids);
106
-        foreach ($transactions_ids as $transaction_id) {
107
-            $roots[] = new ModelObjNode(
108
-                $transaction_id,
109
-                EEM_Transaction::instance(),
110
-                ['Registration']
111
-            );
112
-        }
113
-        $job_parameters->add_extra_data('roots', $roots);
114
-        // Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
115
-        // an accurate count.)
116
-        $estimated_work_per_model_obj = 10;
117
-        $count_regs = EEM_Registration::instance()->count(
118
-            [
119
-                [
120
-                    'EVT_ID' => ['IN', $event_ids]
121
-                ]
122
-            ]
123
-        );
124
-        $job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
125
-        return new JobStepResponse(
126
-            $job_parameters,
127
-            esc_html__('Generating preview of data to be deleted...', 'event_espresso')
128
-        );
129
-    }
51
+	/**
52
+	 *
53
+	 * @param JobParameters $job_parameters
54
+	 * @return JobStepResponse
55
+	 * @throws EE_Error
56
+	 * @throws InvalidDataTypeException
57
+	 * @throws InvalidInterfaceException
58
+	 * @throws InvalidArgumentException
59
+	 * @throws ReflectionException
60
+	 */
61
+	public function create_job(JobParameters $job_parameters)
62
+	{
63
+		// Set the "root" model objects we will want to delete (record their ID and model)
64
+		$event_ids = $job_parameters->request_datum('EVT_IDs', array());
65
+		// Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
66
+		// prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
67
+		// we have no UI to access them independent of events, so they may as well get deleted too.)
68
+		$roots = [];
69
+		foreach ($event_ids as $event_id) {
70
+			$roots[] = new ModelObjNode(
71
+				$event_id,
72
+				EEM_Event::instance()
73
+			);
74
+			// Also, we want to delete their related, non-global, tickets, prices and message templates
75
+			$related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
76
+				[
77
+					[
78
+						'TKT_is_default' => false,
79
+						'Datetime.EVT_ID' => $event_id
80
+					]
81
+				]
82
+			);
83
+			foreach ($related_non_global_tickets as $ticket) {
84
+				$roots[] = new ModelObjNode(
85
+					$ticket->ID(),
86
+					$ticket->get_model(),
87
+					['Registration']
88
+				);
89
+			}
90
+			$related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
91
+				[
92
+					[
93
+						'PRC_is_default' => false,
94
+						'Ticket.Datetime.EVT_ID' => $event_id
95
+					]
96
+				]
97
+			);
98
+			foreach ($related_non_global_prices as $price) {
99
+				$roots[] = new ModelObjNode(
100
+					$price->ID(),
101
+					$price->get_model()
102
+				);
103
+			}
104
+		}
105
+		$transactions_ids = $this->getTransactionsToDelete($event_ids);
106
+		foreach ($transactions_ids as $transaction_id) {
107
+			$roots[] = new ModelObjNode(
108
+				$transaction_id,
109
+				EEM_Transaction::instance(),
110
+				['Registration']
111
+			);
112
+		}
113
+		$job_parameters->add_extra_data('roots', $roots);
114
+		// Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
115
+		// an accurate count.)
116
+		$estimated_work_per_model_obj = 10;
117
+		$count_regs = EEM_Registration::instance()->count(
118
+			[
119
+				[
120
+					'EVT_ID' => ['IN', $event_ids]
121
+				]
122
+			]
123
+		);
124
+		$job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
125
+		return new JobStepResponse(
126
+			$job_parameters,
127
+			esc_html__('Generating preview of data to be deleted...', 'event_espresso')
128
+		);
129
+	}
130 130
 
131
-    /**
132
-     * @since $VID:$
133
-     * @param EE_Base_Class[] $model_objs
134
-     * @param array $dont_traverse_models
135
-     * @return array
136
-     * @throws EE_Error
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @throws ReflectionException
141
-     */
142
-    protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
143
-    {
144
-        $nodes = [];
145
-        foreach ($model_objs as $model_obj) {
146
-            $nodes[] = new ModelObjNode(
147
-                $model_obj->ID(),
148
-                $model_obj->get_model(),
149
-                $dont_traverse_models
150
-            );
151
-        }
152
-        return $nodes;
153
-    }
131
+	/**
132
+	 * @since $VID:$
133
+	 * @param EE_Base_Class[] $model_objs
134
+	 * @param array $dont_traverse_models
135
+	 * @return array
136
+	 * @throws EE_Error
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @throws ReflectionException
141
+	 */
142
+	protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
143
+	{
144
+		$nodes = [];
145
+		foreach ($model_objs as $model_obj) {
146
+			$nodes[] = new ModelObjNode(
147
+				$model_obj->ID(),
148
+				$model_obj->get_model(),
149
+				$dont_traverse_models
150
+			);
151
+		}
152
+		return $nodes;
153
+	}
154 154
 
155
-    /**
156
-     * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
157
-     * (Ones that are related to other events can stay around until those other events are deleted too.)
158
-     * @since $VID:$
159
-     * @param $event_ids
160
-     * @return array of transaction IDs
161
-     */
162
-    protected function getTransactionsToDelete($event_ids)
163
-    {
164
-        if (empty($event_ids)) {
165
-            return [];
166
-        }
167
-        global $wpdb;
168
-        $event_ids = array_map(
169
-            'intval',
170
-            $event_ids
171
-        );
172
-        $imploded_sanitized_event_ids = implode(',', $event_ids);
173
-        // Select transactions with registrations for the events $event_ids which also don't have registrations
174
-        // for any events NOT in $event_ids.
175
-        // Notice the outer query searched for transactions whose registrations ARE in $event_ids,
176
-        // whereas the inner query checks if the outer query's transaction has any registrations that are
177
-        // NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
178
-        return array_map(
179
-            'intval',
180
-            $wpdb->get_col(
181
-                "SELECT 
155
+	/**
156
+	 * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
157
+	 * (Ones that are related to other events can stay around until those other events are deleted too.)
158
+	 * @since $VID:$
159
+	 * @param $event_ids
160
+	 * @return array of transaction IDs
161
+	 */
162
+	protected function getTransactionsToDelete($event_ids)
163
+	{
164
+		if (empty($event_ids)) {
165
+			return [];
166
+		}
167
+		global $wpdb;
168
+		$event_ids = array_map(
169
+			'intval',
170
+			$event_ids
171
+		);
172
+		$imploded_sanitized_event_ids = implode(',', $event_ids);
173
+		// Select transactions with registrations for the events $event_ids which also don't have registrations
174
+		// for any events NOT in $event_ids.
175
+		// Notice the outer query searched for transactions whose registrations ARE in $event_ids,
176
+		// whereas the inner query checks if the outer query's transaction has any registrations that are
177
+		// NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
178
+		return array_map(
179
+			'intval',
180
+			$wpdb->get_col(
181
+				"SELECT 
182 182
                       DISTINCT t.TXN_ID
183 183
                     FROM 
184 184
                       {$wpdb->prefix}esp_transaction t INNER JOIN 
@@ -196,84 +196,84 @@  discard block
 block discarded – undo
196 196
                            tsub.TXN_ID=t.TXN_ID AND
197 197
                            rsub.EVT_ID NOT IN ({$imploded_sanitized_event_ids})
198 198
                        )"
199
-            )
200
-        );
201
-    }
199
+			)
200
+		);
201
+	}
202 202
 
203
-    /**
204
-     * Performs another step of the job
205
-     * @param JobParameters $job_parameters
206
-     * @param int $batch_size
207
-     * @return JobStepResponse
208
-     * @throws BatchRequestException
209
-     */
210
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
211
-    {
212
-        // Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
213
-        // about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
214
-        // 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
215
-        $batch_size *= 3;
216
-        $units_processed = 0;
217
-        foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
218
-            if ($units_processed >= $batch_size) {
219
-                break;
220
-            }
221
-            if (!$root_node instanceof ModelObjNode) {
222
-                throw new InvalidClassException('ModelObjNode');
223
-            }
224
-            if ($root_node->isComplete()) {
225
-                continue;
226
-            }
227
-            $units_processed += $root_node->visit($batch_size - $units_processed);
228
-        }
229
-        $job_parameters->mark_processed($units_processed);
230
-        // If the most-recently processed root node is complete, we must be all done because we're doing them
231
-        // sequentially.
232
-        if (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete()) {
233
-            $job_parameters->set_status(JobParameters::status_complete);
234
-            // Show a full progress bar.
235
-            $job_parameters->set_units_processed($job_parameters->job_size());
236
-            $deletion_job_code = $job_parameters->request_datum('deletion_job_code');
237
-            $this->model_obj_node_group_persister->persistModelObjNodesGroup(
238
-                $job_parameters->extra_datum('roots'),
239
-                $deletion_job_code
240
-            );
241
-            return new JobStepResponse(
242
-                $job_parameters,
243
-                esc_html__('Finished identifying items for deletion.', 'event_espresso'),
244
-                [
245
-                    'deletion_job_code' => $deletion_job_code
246
-                ]
247
-            );
248
-        } else {
249
-            // Because the job size was a guess, it may have likely been provden wrong. We don't want to show more work
250
-            // done than we originally said there would be. So adjust the estimate.
251
-            if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
252
-                $job_parameters->set_job_size($job_parameters->job_size() * 2);
253
-            }
254
-            return new JobStepResponse(
255
-                $job_parameters,
256
-                sprintf(
257
-                    esc_html__('Identified %d items for deletion.', 'event_espresso'),
258
-                    $units_processed
259
-                )
260
-            );
261
-        }
262
-    }
203
+	/**
204
+	 * Performs another step of the job
205
+	 * @param JobParameters $job_parameters
206
+	 * @param int $batch_size
207
+	 * @return JobStepResponse
208
+	 * @throws BatchRequestException
209
+	 */
210
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
211
+	{
212
+		// Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
213
+		// about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
214
+		// 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
215
+		$batch_size *= 3;
216
+		$units_processed = 0;
217
+		foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
218
+			if ($units_processed >= $batch_size) {
219
+				break;
220
+			}
221
+			if (!$root_node instanceof ModelObjNode) {
222
+				throw new InvalidClassException('ModelObjNode');
223
+			}
224
+			if ($root_node->isComplete()) {
225
+				continue;
226
+			}
227
+			$units_processed += $root_node->visit($batch_size - $units_processed);
228
+		}
229
+		$job_parameters->mark_processed($units_processed);
230
+		// If the most-recently processed root node is complete, we must be all done because we're doing them
231
+		// sequentially.
232
+		if (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete()) {
233
+			$job_parameters->set_status(JobParameters::status_complete);
234
+			// Show a full progress bar.
235
+			$job_parameters->set_units_processed($job_parameters->job_size());
236
+			$deletion_job_code = $job_parameters->request_datum('deletion_job_code');
237
+			$this->model_obj_node_group_persister->persistModelObjNodesGroup(
238
+				$job_parameters->extra_datum('roots'),
239
+				$deletion_job_code
240
+			);
241
+			return new JobStepResponse(
242
+				$job_parameters,
243
+				esc_html__('Finished identifying items for deletion.', 'event_espresso'),
244
+				[
245
+					'deletion_job_code' => $deletion_job_code
246
+				]
247
+			);
248
+		} else {
249
+			// Because the job size was a guess, it may have likely been provden wrong. We don't want to show more work
250
+			// done than we originally said there would be. So adjust the estimate.
251
+			if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
252
+				$job_parameters->set_job_size($job_parameters->job_size() * 2);
253
+			}
254
+			return new JobStepResponse(
255
+				$job_parameters,
256
+				sprintf(
257
+					esc_html__('Identified %d items for deletion.', 'event_espresso'),
258
+					$units_processed
259
+				)
260
+			);
261
+		}
262
+	}
263 263
 
264
-    /**
265
-     * Performs any clean-up logic when we know the job is completed
266
-     * @param JobParameters $job_parameters
267
-     * @return JobStepResponse
268
-     */
269
-    public function cleanup_job(JobParameters $job_parameters)
270
-    {
271
-        // Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
272
-        return new JobStepResponse(
273
-            $job_parameters,
274
-            esc_html__('All done', 'event_espresso')
275
-        );
276
-    }
264
+	/**
265
+	 * Performs any clean-up logic when we know the job is completed
266
+	 * @param JobParameters $job_parameters
267
+	 * @return JobStepResponse
268
+	 */
269
+	public function cleanup_job(JobParameters $job_parameters)
270
+	{
271
+		// Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
272
+		return new JobStepResponse(
273
+			$job_parameters,
274
+			esc_html__('All done', 'event_espresso')
275
+		);
276
+	}
277 277
 }
278 278
 // End of file EventDeletion.php
279 279
 // Location: EventEspressoBatchRequest\JobHandlers/EventDeletion.php
Please login to merge, or discard this patch.
Unused Use Statements   -2 removed lines patch added patch discarded remove patch
@@ -9,11 +9,9 @@
 block discarded – undo
9 9
 use EEM_Registration;
10 10
 use EEM_Ticket;
11 11
 use EEM_Transaction;
12
-use EETests\bootstrap\CoreLoader;
13 12
 use EventEspresso\core\exceptions\InvalidClassException;
14 13
 use EventEspresso\core\exceptions\InvalidDataTypeException;
15 14
 use EventEspresso\core\exceptions\InvalidInterfaceException;
16
-use EventEspresso\core\services\loaders\LoaderFactory;
17 15
 use EventEspresso\core\services\orm\tree_traversal\ModelObjNode;
18 16
 use EventEspresso\core\services\orm\tree_traversal\NodeGroupDao;
19 17
 use EventEspressoBatchRequest\Helpers\BatchRequestException;
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/ModelObjNode.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
                 continue;
69 69
             }
70 70
             if ($relation instanceof EE_Has_Many_Relation) {
71
-                $this->nodes[ $relationName ] = new RelationNode(
71
+                $this->nodes[$relationName] = new RelationNode(
72 72
                     $this->id,
73 73
                     $this->model,
74 74
                     $relation->get_other_model(),
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
                     $relation->get_join_model()->get_this_model_name(),
80 80
                     $this->dont_traverse_models
81 81
                 )) {
82
-                $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
82
+                $this->nodes[$relation->get_join_model()->get_this_model_name()] = new RelationNode(
83 83
                     $this->id,
84 84
                     $this->model,
85 85
                     $relation->get_join_model(),
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
             // To save on space when serializing, only bother keeping a record of relation nodes that actually found
128 128
             // related model objects.
129 129
             if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
130
-                unset($this->nodes[ $model_name ]);
130
+                unset($this->nodes[$model_name]);
131 131
             }
132 132
             if ($num_identified >= $model_objects_to_identify) {
133 133
                 // ...but admit we're wrong if the work exceeded the budget.
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
             $tree['rels'] = null;
159 159
         } else {
160 160
             foreach ($this->nodes as $relation_name => $relation_node) {
161
-                $tree['rels'][ $relation_name ] = $relation_node->toArray();
161
+                $tree['rels'][$relation_name] = $relation_node->toArray();
162 162
             }
163 163
         }
164 164
         return $tree;
Please login to merge, or discard this patch.
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -22,204 +22,204 @@
 block discarded – undo
22 22
  */
23 23
 class ModelObjNode extends BaseNode
24 24
 {
25
-    /**
26
-     * @var int|string
27
-     */
28
-    protected $id;
25
+	/**
26
+	 * @var int|string
27
+	 */
28
+	protected $id;
29 29
 
30
-    /**
31
-     * @var EEM_Base
32
-     */
33
-    protected $model;
30
+	/**
31
+	 * @var EEM_Base
32
+	 */
33
+	protected $model;
34 34
 
35
-    /**
36
-     * @var RelationNode[]
37
-     */
38
-    protected $nodes;
35
+	/**
36
+	 * @var RelationNode[]
37
+	 */
38
+	protected $nodes;
39 39
 
40
-    /**
41
-     * We don't pass the model objects because this needs to serialize to something tiny for effiency.
42
-     * @param $model_obj_id
43
-     * @param EEM_Base $model
44
-     * @param array $dont_traverse_models array of model names we DON'T want to traverse.
45
-     */
46
-    public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
47
-    {
48
-        $this->id = $model_obj_id;
49
-        $this->model = $model;
50
-        $this->dont_traverse_models = $dont_traverse_models;
51
-    }
40
+	/**
41
+	 * We don't pass the model objects because this needs to serialize to something tiny for effiency.
42
+	 * @param $model_obj_id
43
+	 * @param EEM_Base $model
44
+	 * @param array $dont_traverse_models array of model names we DON'T want to traverse.
45
+	 */
46
+	public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
47
+	{
48
+		$this->id = $model_obj_id;
49
+		$this->model = $model;
50
+		$this->dont_traverse_models = $dont_traverse_models;
51
+	}
52 52
 
53
-    /**
54
-     * Creates a relation node for each relation of this model's relations.
55
-     * Does NOT call `discover` on them yet though.
56
-     * @since $VID:$
57
-     * @throws \EE_Error
58
-     * @throws InvalidDataTypeException
59
-     * @throws InvalidInterfaceException
60
-     * @throws InvalidArgumentException
61
-     * @throws ReflectionException
62
-     */
63
-    protected function discover()
64
-    {
65
-        $this->nodes = [];
66
-        foreach ($this->model->relation_settings() as $relationName => $relation) {
67
-            // Make sure this isn't one of the models we were told to not traverse into.
68
-            if (in_array($relationName, $this->dont_traverse_models)) {
69
-                continue;
70
-            }
71
-            if ($relation instanceof EE_Has_Many_Relation) {
72
-                $this->nodes[ $relationName ] = new RelationNode(
73
-                    $this->id,
74
-                    $this->model,
75
-                    $relation->get_other_model(),
76
-                    $this->dont_traverse_models
77
-                );
78
-            } elseif ($relation instanceof EE_HABTM_Relation &&
79
-                ! in_array(
80
-                    $relation->get_join_model()->get_this_model_name(),
81
-                    $this->dont_traverse_models
82
-                )) {
83
-                $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
84
-                    $this->id,
85
-                    $this->model,
86
-                    $relation->get_join_model(),
87
-                    $this->dont_traverse_models
88
-                );
89
-            }
90
-        }
91
-        ksort($this->nodes);
92
-    }
53
+	/**
54
+	 * Creates a relation node for each relation of this model's relations.
55
+	 * Does NOT call `discover` on them yet though.
56
+	 * @since $VID:$
57
+	 * @throws \EE_Error
58
+	 * @throws InvalidDataTypeException
59
+	 * @throws InvalidInterfaceException
60
+	 * @throws InvalidArgumentException
61
+	 * @throws ReflectionException
62
+	 */
63
+	protected function discover()
64
+	{
65
+		$this->nodes = [];
66
+		foreach ($this->model->relation_settings() as $relationName => $relation) {
67
+			// Make sure this isn't one of the models we were told to not traverse into.
68
+			if (in_array($relationName, $this->dont_traverse_models)) {
69
+				continue;
70
+			}
71
+			if ($relation instanceof EE_Has_Many_Relation) {
72
+				$this->nodes[ $relationName ] = new RelationNode(
73
+					$this->id,
74
+					$this->model,
75
+					$relation->get_other_model(),
76
+					$this->dont_traverse_models
77
+				);
78
+			} elseif ($relation instanceof EE_HABTM_Relation &&
79
+				! in_array(
80
+					$relation->get_join_model()->get_this_model_name(),
81
+					$this->dont_traverse_models
82
+				)) {
83
+				$this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
84
+					$this->id,
85
+					$this->model,
86
+					$relation->get_join_model(),
87
+					$this->dont_traverse_models
88
+				);
89
+			}
90
+		}
91
+		ksort($this->nodes);
92
+	}
93 93
 
94 94
 
95
-    /**
96
-     * Whether this item has already been initialized
97
-     */
98
-    protected function isDiscovered()
99
-    {
100
-        return $this->nodes !== null && is_array($this->nodes);
101
-    }
95
+	/**
96
+	 * Whether this item has already been initialized
97
+	 */
98
+	protected function isDiscovered()
99
+	{
100
+		return $this->nodes !== null && is_array($this->nodes);
101
+	}
102 102
 
103
-    /**
104
-     * @since $VID:$
105
-     * @return boolean
106
-     */
107
-    public function isComplete()
108
-    {
109
-        if ($this->complete === null) {
110
-            $this->complete = false;
111
-        }
112
-        return $this->complete;
113
-    }
103
+	/**
104
+	 * @since $VID:$
105
+	 * @return boolean
106
+	 */
107
+	public function isComplete()
108
+	{
109
+		if ($this->complete === null) {
110
+			$this->complete = false;
111
+		}
112
+		return $this->complete;
113
+	}
114 114
 
115
-    /**
116
-     * Triggers working on each child relation node that has work to do.
117
-     * @since $VID:$
118
-     * @param $model_objects_to_identify
119
-     * @return int units of work done
120
-     */
121
-    protected function work($model_objects_to_identify)
122
-    {
123
-        $num_identified = 0;
124
-        // Begin assuming we'll finish all the work on this node and its children...
125
-        $this->complete = true;
126
-        foreach ($this->nodes as $model_name => $relation_node) {
127
-            $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
128
-            // To save on space when serializing, only bother keeping a record of relation nodes that actually found
129
-            // related model objects.
130
-            if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
131
-                unset($this->nodes[ $model_name ]);
132
-            }
133
-            if ($num_identified >= $model_objects_to_identify) {
134
-                // ...but admit we're wrong if the work exceeded the budget.
135
-                $this->complete = false;
136
-                break;
137
-            }
138
-        }
139
-        return $num_identified;
140
-    }
115
+	/**
116
+	 * Triggers working on each child relation node that has work to do.
117
+	 * @since $VID:$
118
+	 * @param $model_objects_to_identify
119
+	 * @return int units of work done
120
+	 */
121
+	protected function work($model_objects_to_identify)
122
+	{
123
+		$num_identified = 0;
124
+		// Begin assuming we'll finish all the work on this node and its children...
125
+		$this->complete = true;
126
+		foreach ($this->nodes as $model_name => $relation_node) {
127
+			$num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
128
+			// To save on space when serializing, only bother keeping a record of relation nodes that actually found
129
+			// related model objects.
130
+			if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
131
+				unset($this->nodes[ $model_name ]);
132
+			}
133
+			if ($num_identified >= $model_objects_to_identify) {
134
+				// ...but admit we're wrong if the work exceeded the budget.
135
+				$this->complete = false;
136
+				break;
137
+			}
138
+		}
139
+		return $num_identified;
140
+	}
141 141
 
142
-    /**
143
-     * @since $VID:$
144
-     * @return array
145
-     * @throws \EE_Error
146
-     * @throws InvalidDataTypeException
147
-     * @throws InvalidInterfaceException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     */
151
-    public function toArray()
152
-    {
153
-        $tree = [
154
-            'id' => $this->id,
155
-            'complete' => $this->isComplete(),
156
-            'rels' => []
157
-        ];
158
-        if ($this->nodes === null) {
159
-            $tree['rels'] = null;
160
-        } else {
161
-            foreach ($this->nodes as $relation_name => $relation_node) {
162
-                $tree['rels'][ $relation_name ] = $relation_node->toArray();
163
-            }
164
-        }
165
-        return $tree;
166
-    }
142
+	/**
143
+	 * @since $VID:$
144
+	 * @return array
145
+	 * @throws \EE_Error
146
+	 * @throws InvalidDataTypeException
147
+	 * @throws InvalidInterfaceException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function toArray()
152
+	{
153
+		$tree = [
154
+			'id' => $this->id,
155
+			'complete' => $this->isComplete(),
156
+			'rels' => []
157
+		];
158
+		if ($this->nodes === null) {
159
+			$tree['rels'] = null;
160
+		} else {
161
+			foreach ($this->nodes as $relation_name => $relation_node) {
162
+				$tree['rels'][ $relation_name ] = $relation_node->toArray();
163
+			}
164
+		}
165
+		return $tree;
166
+	}
167 167
 
168
-    /**
169
-     * @since $VID:$
170
-     * @return array|mixed
171
-     * @throws InvalidArgumentException
172
-     * @throws InvalidDataTypeException
173
-     * @throws InvalidInterfaceException
174
-     * @throws ReflectionException
175
-     * @throws \EE_Error
176
-     */
177
-    public function getIds()
178
-    {
179
-        $ids = [
180
-            $this->model->get_this_model_name() => [
181
-                $this->id => $this->id
182
-            ]
183
-        ];
184
-        if ($this->nodes && is_array($this->nodes)) {
185
-            foreach ($this->nodes as $relation_node) {
186
-                $ids = array_replace_recursive($ids, $relation_node->getIds());
187
-            }
188
-        }
189
-        return $ids;
190
-    }
168
+	/**
169
+	 * @since $VID:$
170
+	 * @return array|mixed
171
+	 * @throws InvalidArgumentException
172
+	 * @throws InvalidDataTypeException
173
+	 * @throws InvalidInterfaceException
174
+	 * @throws ReflectionException
175
+	 * @throws \EE_Error
176
+	 */
177
+	public function getIds()
178
+	{
179
+		$ids = [
180
+			$this->model->get_this_model_name() => [
181
+				$this->id => $this->id
182
+			]
183
+		];
184
+		if ($this->nodes && is_array($this->nodes)) {
185
+			foreach ($this->nodes as $relation_node) {
186
+				$ids = array_replace_recursive($ids, $relation_node->getIds());
187
+			}
188
+		}
189
+		return $ids;
190
+	}
191 191
 
192
-    /**
193
-     * Don't serialize the models. Just record their names on some dynamic properties.
194
-     * @since $VID:$
195
-     */
196
-    public function __sleep()
197
-    {
198
-        $this->m = $this->model->get_this_model_name();
199
-        return array_merge(
200
-            [
201
-                'm',
202
-                'id',
203
-                'nodes',
204
-            ],
205
-            parent::__sleep()
206
-        );
207
-    }
192
+	/**
193
+	 * Don't serialize the models. Just record their names on some dynamic properties.
194
+	 * @since $VID:$
195
+	 */
196
+	public function __sleep()
197
+	{
198
+		$this->m = $this->model->get_this_model_name();
199
+		return array_merge(
200
+			[
201
+				'm',
202
+				'id',
203
+				'nodes',
204
+			],
205
+			parent::__sleep()
206
+		);
207
+	}
208 208
 
209
-    /**
210
-     * Use the dynamic properties to instantiate the models we use.
211
-     * @since $VID:$
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidInterfaceException
216
-     * @throws ReflectionException
217
-     */
218
-    public function __wakeup()
219
-    {
220
-        $this->model = EE_Registry::instance()->load_model($this->m);
221
-        parent::__wakeup();
222
-    }
209
+	/**
210
+	 * Use the dynamic properties to instantiate the models we use.
211
+	 * @since $VID:$
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function __wakeup()
219
+	{
220
+		$this->model = EE_Registry::instance()->load_model($this->m);
221
+		parent::__wakeup();
222
+	}
223 223
 }
224 224
 // End of file Visitor.php
225 225
 // Location: EventEspresso\core\services\orm\tree_traversal/Visitor.php
Please login to merge, or discard this patch.
admin_pages/events/form_sections/ConfirmEventDeletionForm.php 3 patches
Unused Use Statements   -2 removed lines patch added patch discarded remove patch
@@ -4,8 +4,6 @@
 block discarded – undo
4 4
 
5 5
 use EE_Checkbox_Multi_Input;
6 6
 use EE_Event;
7
-use EE_Form_Section_HTML;
8
-use EEH_HTML;
9 7
 use EEM_Event;
10 8
 use EventEspresso\core\exceptions\UnexpectedEntityException;
11 9
 
Please login to merge, or discard this patch.
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -22,55 +22,55 @@
 block discarded – undo
22 22
  */
23 23
 class ConfirmEventDeletionForm extends \EE_Form_Section_Proper
24 24
 {
25
-    /**
26
-     * @var EE_Event[]
27
-     */
28
-    protected $events;
29
-    public function __construct($event_ids, $options_array = array())
30
-    {
31
-        if (! isset($options_array['subsections'])) {
32
-            $options_array['subsections'] = [];
33
-        }
34
-        if (! isset($options_array['subsections']['events'])) {
35
-            $events_subsection = new \EE_Form_Section_Proper();
36
-            $options_array['subsections']['events'] = $events_subsection;
37
-        }
38
-        $events = EEM_Event::instance()->get_all_deleted_and_undeleted(
39
-            [
40
-                [
41
-                    'EVT_ID' => ['IN',$event_ids]
42
-                ]
43
-            ]
44
-        );
45
-        if (! is_array($events)) {
46
-            throw new UnexpectedEntityException($event_ids, 'array');
47
-        }
48
-        $this->events = $events;
49
-        $events_inputs = [
50
-        ];
51
-        foreach ($events as $event) {
52
-            $events_inputs[ $event->ID() ] = new EE_Checkbox_Multi_Input(
53
-                [
54
-                    'yes' => $event->name(),
55
-                ],
56
-                [
57
-                    'html_label_text' => esc_html__('Please confirm you wish to delete:', 'event_espresso'),
58
-                    'required' => true
59
-                ]
60
-            );
61
-        }
62
-        $events_subsection->add_subsections($events_inputs);
63
-        $options_array['subsections']['backup'] = new EE_Checkbox_Multi_Input(
64
-            [
65
-                'yes' => esc_html__('I have backed up my database.', 'event_espresso')
66
-            ],
67
-            [
68
-                'html_label_text' => esc_html__('Deleting this data cannot be undone. Please confirm you have a usable database backup.', 'event_espresso'),
69
-                'required' => true
70
-            ]
71
-        );
72
-        parent::__construct($options_array);
73
-    }
25
+	/**
26
+	 * @var EE_Event[]
27
+	 */
28
+	protected $events;
29
+	public function __construct($event_ids, $options_array = array())
30
+	{
31
+		if (! isset($options_array['subsections'])) {
32
+			$options_array['subsections'] = [];
33
+		}
34
+		if (! isset($options_array['subsections']['events'])) {
35
+			$events_subsection = new \EE_Form_Section_Proper();
36
+			$options_array['subsections']['events'] = $events_subsection;
37
+		}
38
+		$events = EEM_Event::instance()->get_all_deleted_and_undeleted(
39
+			[
40
+				[
41
+					'EVT_ID' => ['IN',$event_ids]
42
+				]
43
+			]
44
+		);
45
+		if (! is_array($events)) {
46
+			throw new UnexpectedEntityException($event_ids, 'array');
47
+		}
48
+		$this->events = $events;
49
+		$events_inputs = [
50
+		];
51
+		foreach ($events as $event) {
52
+			$events_inputs[ $event->ID() ] = new EE_Checkbox_Multi_Input(
53
+				[
54
+					'yes' => $event->name(),
55
+				],
56
+				[
57
+					'html_label_text' => esc_html__('Please confirm you wish to delete:', 'event_espresso'),
58
+					'required' => true
59
+				]
60
+			);
61
+		}
62
+		$events_subsection->add_subsections($events_inputs);
63
+		$options_array['subsections']['backup'] = new EE_Checkbox_Multi_Input(
64
+			[
65
+				'yes' => esc_html__('I have backed up my database.', 'event_espresso')
66
+			],
67
+			[
68
+				'html_label_text' => esc_html__('Deleting this data cannot be undone. Please confirm you have a usable database backup.', 'event_espresso'),
69
+				'required' => true
70
+			]
71
+		);
72
+		parent::__construct($options_array);
73
+	}
74 74
 }
75 75
 // End of file ConfirmEventDeletionForm.php
76 76
 // Location: EventEspresso\admin_pages\events\form_sections/ConfirmEventDeletionForm.php
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -28,28 +28,28 @@
 block discarded – undo
28 28
     protected $events;
29 29
     public function __construct($event_ids, $options_array = array())
30 30
     {
31
-        if (! isset($options_array['subsections'])) {
31
+        if ( ! isset($options_array['subsections'])) {
32 32
             $options_array['subsections'] = [];
33 33
         }
34
-        if (! isset($options_array['subsections']['events'])) {
34
+        if ( ! isset($options_array['subsections']['events'])) {
35 35
             $events_subsection = new \EE_Form_Section_Proper();
36 36
             $options_array['subsections']['events'] = $events_subsection;
37 37
         }
38 38
         $events = EEM_Event::instance()->get_all_deleted_and_undeleted(
39 39
             [
40 40
                 [
41
-                    'EVT_ID' => ['IN',$event_ids]
41
+                    'EVT_ID' => ['IN', $event_ids]
42 42
                 ]
43 43
             ]
44 44
         );
45
-        if (! is_array($events)) {
45
+        if ( ! is_array($events)) {
46 46
             throw new UnexpectedEntityException($event_ids, 'array');
47 47
         }
48 48
         $this->events = $events;
49 49
         $events_inputs = [
50 50
         ];
51 51
         foreach ($events as $event) {
52
-            $events_inputs[ $event->ID() ] = new EE_Checkbox_Multi_Input(
52
+            $events_inputs[$event->ID()] = new EE_Checkbox_Multi_Input(
53 53
                 [
54 54
                     'yes' => $event->name(),
55 55
                 ],
Please login to merge, or discard this patch.
admin_pages/events/templates/event_preview_deletion.template.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -1,97 +1,97 @@
 block discarded – undo
1 1
 <h2><?php esc_html_e('Please Confirm You Want to Permanently Delete the Following Data', 'event_espresso'); ?></h2>
2 2
 <h3>
3 3
     <?php
4
-    printf(
5
-        esc_html(
6
-            // translators: 1: number of events
7
-            _n('%1$d Event', '%1$d Events', count($events), 'event_espresso')
8
-        ),
9
-        count($events)
10
-    );
11
-    ?>
4
+	printf(
5
+		esc_html(
6
+			// translators: 1: number of events
7
+			_n('%1$d Event', '%1$d Events', count($events), 'event_espresso')
8
+		),
9
+		count($events)
10
+	);
11
+	?>
12 12
 </h3>
13 13
 <ul>
14 14
     <?php
15
-    foreach ($events as $event) {
16
-        ?>
15
+	foreach ($events as $event) {
16
+		?>
17 17
         <li>
18 18
             <?php echo $event->name(); ?>
19 19
         </li>
20 20
         <?php
21
-    }
22
-    ?>
21
+	}
22
+	?>
23 23
 </ul>
24 24
 <h3>
25 25
     <?php
26
-    printf(
27
-        esc_html(
28
-            // translators: 1: number of datetimes
29
-            _n('%1$d Datetime', '%1$d Datetimes', count($datetimes), 'event_espresso')
30
-        ),
31
-        count($datetimes)
32
-    );
33
-    ?>
26
+	printf(
27
+		esc_html(
28
+			// translators: 1: number of datetimes
29
+			_n('%1$d Datetime', '%1$d Datetimes', count($datetimes), 'event_espresso')
30
+		),
31
+		count($datetimes)
32
+	);
33
+	?>
34 34
 </h3>
35 35
 <ul>
36 36
     <?php
37
-    foreach ($datetimes as $datetime) {
38
-        ?>
37
+	foreach ($datetimes as $datetime) {
38
+		?>
39 39
         <li>
40 40
             <?php echo $datetime->get_dtt_display_name(true); ?>
41 41
         </li>
42 42
         <?php
43
-    }
44
-    ?>
43
+	}
44
+	?>
45 45
 </ul>
46 46
 <h3>
47 47
     <?php
48
-    printf(
49
-        esc_html(
50
-            _n('%1$d Registration', '%1$d Registrations', $reg_count, 'event_espresso')
51
-        ),
52
-        $reg_count
53
-    );
54
-    ?>
48
+	printf(
49
+		esc_html(
50
+			_n('%1$d Registration', '%1$d Registrations', $reg_count, 'event_espresso')
51
+		),
52
+		$reg_count
53
+	);
54
+	?>
55 55
 </h3>
56 56
 <?php
57 57
 if ($reg_count > count($registrations)) {
58
-    ?>
58
+	?>
59 59
     <p class="notice">
60 60
         <?php
61
-        printf(
62
-            esc_html__('Only showing first %1$d.', 'event_espresso'),
63
-            count($registrations)
64
-        );
65
-        ?>
61
+		printf(
62
+			esc_html__('Only showing first %1$d.', 'event_espresso'),
63
+			count($registrations)
64
+		);
65
+		?>
66 66
     </p>
67 67
     <?php
68 68
 }
69 69
 ?>
70 70
 <?php
71 71
 if ($reg_count > 0) {
72
-    ?>
72
+	?>
73 73
     <p><?php esc_html_e('Note: contacts will not be deleted, only their registrations for the enumerated events.', 'event_espresso'); ?></p>
74 74
     <?php
75 75
 }
76 76
 ?>
77 77
 <ul>
78 78
     <?php
79
-    foreach ($registrations as $registration) {
80
-        ?>
79
+	foreach ($registrations as $registration) {
80
+		?>
81 81
         <li>
82 82
             <?php
83
-            printf(
84
-                esc_html(
85
-                    _x('%1$s (%2$d of %3$d)', 'Registration name (number of count)', 'event_espresso')
86
-                ),
87
-                $registration->attendeeName(true),
88
-                $registration->count(),
89
-                $registration->group_size()
90
-            ); ?>
83
+			printf(
84
+				esc_html(
85
+					_x('%1$s (%2$d of %3$d)', 'Registration name (number of count)', 'event_espresso')
86
+				),
87
+				$registration->attendeeName(true),
88
+				$registration->count(),
89
+				$registration->group_size()
90
+			); ?>
91 91
         </li>
92 92
         <?php
93
-    }
94
-    ?>
93
+	}
94
+	?>
95 95
 </ul>
96 96
 <form action="<?php echo $form_url; ?>" method="POST">
97 97
     <?php echo $form->get_html_and_js(); ?>
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2558 added lines, -2558 removed lines patch added patch discarded remove patch
@@ -13,2562 +13,2562 @@
 block discarded – undo
13 13
 class Transactions_Admin_Page extends EE_Admin_Page
14 14
 {
15 15
 
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug = TXN_PG_SLUG;
50
-        $this->page_label = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels = array(
78
-            'buttons' => array(
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ),
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     */
97
-    public function _set_page_routes()
98
-    {
99
-
100
-        $this->_set_transaction_status_array();
101
-
102
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
103
-                  && ! is_array($this->_req_data['TXN_ID'])
104
-            ? $this->_req_data['TXN_ID']
105
-            : 0;
106
-
107
-        $this->_page_routes = array(
108
-
109
-            'default' => array(
110
-                'func'       => '_transactions_overview_list_table',
111
-                'capability' => 'ee_read_transactions',
112
-            ),
113
-
114
-            'view_transaction' => array(
115
-                'func'       => '_transaction_details',
116
-                'capability' => 'ee_read_transaction',
117
-                'obj_id'     => $txn_id,
118
-            ),
119
-
120
-            'send_payment_reminder' => array(
121
-                'func'       => '_send_payment_reminder',
122
-                'noheader'   => true,
123
-                'capability' => 'ee_send_message',
124
-            ),
125
-
126
-            'espresso_apply_payment' => array(
127
-                'func'       => 'apply_payments_or_refunds',
128
-                'noheader'   => true,
129
-                'capability' => 'ee_edit_payments',
130
-            ),
131
-
132
-            'espresso_apply_refund' => array(
133
-                'func'       => 'apply_payments_or_refunds',
134
-                'noheader'   => true,
135
-                'capability' => 'ee_edit_payments',
136
-            ),
137
-
138
-            'espresso_delete_payment' => array(
139
-                'func'       => 'delete_payment',
140
-                'noheader'   => true,
141
-                'capability' => 'ee_delete_payments',
142
-            ),
143
-
144
-            'espresso_recalculate_line_items' => array(
145
-                'func'       => 'recalculateLineItems',
146
-                'noheader'   => true,
147
-                'capability' => 'ee_edit_payments',
148
-            ),
149
-
150
-        );
151
-    }
152
-
153
-
154
-    protected function _set_page_config()
155
-    {
156
-        $this->_page_config = array(
157
-            'default'          => array(
158
-                'nav'           => array(
159
-                    'label' => esc_html__('Overview', 'event_espresso'),
160
-                    'order' => 10,
161
-                ),
162
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
163
-                'help_tabs'     => array(
164
-                    'transactions_overview_help_tab'                       => array(
165
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
-                        'filename' => 'transactions_overview',
167
-                    ),
168
-                    'transactions_overview_table_column_headings_help_tab' => array(
169
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
-                        'filename' => 'transactions_overview_table_column_headings',
171
-                    ),
172
-                    'transactions_overview_views_filters_help_tab'         => array(
173
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
-                        'filename' => 'transactions_overview_views_filters_search',
175
-                    ),
176
-                ),
177
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
-                // 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
-                /**
180
-                 * commented out because currently we are not displaying tips for transaction list table status but this
181
-                 * may change in a later iteration so want to keep the code for then.
182
-                 */
183
-                // 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
-                'require_nonce' => false,
185
-            ),
186
-            'view_transaction' => array(
187
-                'nav'       => array(
188
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
189
-                    'order'      => 5,
190
-                    'url'        => isset($this->_req_data['TXN_ID'])
191
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
-                        : $this->_admin_base_url,
193
-                    'persistent' => false,
194
-                ),
195
-                'help_tabs' => array(
196
-                    'transactions_view_transaction_help_tab'                                              => array(
197
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction',
199
-                    ),
200
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
203
-                    ),
204
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
-                        'filename' => 'transactions_view_transaction_attendees_registered',
207
-                    ),
208
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
-                    ),
212
-                ),
213
-                'qtips'     => array('Transaction_Details_Tips'),
214
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
-                // 'help_tour' => array('Transaction_Details_Help_Tour'),
216
-                'metaboxes' => array('_transaction_details_metaboxes'),
217
-
218
-                'require_nonce' => false,
219
-            ),
220
-        );
221
-    }
222
-
223
-
224
-    /**
225
-     * The below methods aren't used by this class currently
226
-     */
227
-    protected function _add_screen_options()
228
-    {
229
-        // noop
230
-    }
231
-
232
-
233
-    protected function _add_feature_pointers()
234
-    {
235
-        // noop
236
-    }
237
-
238
-
239
-    public function admin_init()
240
-    {
241
-        // IF a registration was JUST added via the admin...
242
-        if (isset(
243
-            $this->_req_data['redirect_from'],
244
-            $this->_req_data['EVT_ID'],
245
-            $this->_req_data['event_name']
246
-        )) {
247
-            // then set a cookie so that we can block any attempts to use
248
-            // the back button as a way to enter another registration.
249
-            setcookie(
250
-                'ee_registration_added',
251
-                $this->_req_data['EVT_ID'],
252
-                time() + WEEK_IN_SECONDS,
253
-                '/'
254
-            );
255
-            // and update the global
256
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
257
-        }
258
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
259
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
260
-            'event_espresso'
261
-        );
262
-        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
263
-            'An error occurred! Please refresh the page and try again.',
264
-            'event_espresso'
265
-        );
266
-        EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
267
-        EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
268
-        EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
269
-        EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
270
-            'This transaction has been overpaid ! Payments Total',
271
-            'event_espresso'
272
-        );
273
-    }
274
-
275
-
276
-    public function admin_notices()
277
-    {
278
-        // noop
279
-    }
280
-
281
-
282
-    public function admin_footer_scripts()
283
-    {
284
-        // noop
285
-    }
286
-
287
-
288
-    /**
289
-     * _set_transaction_status_array
290
-     * sets list of transaction statuses
291
-     *
292
-     * @access private
293
-     * @return void
294
-     * @throws EE_Error
295
-     * @throws InvalidArgumentException
296
-     * @throws InvalidDataTypeException
297
-     * @throws InvalidInterfaceException
298
-     */
299
-    private function _set_transaction_status_array()
300
-    {
301
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
302
-    }
303
-
304
-
305
-    /**
306
-     * get_transaction_status_array
307
-     * return the transaction status array for wp_list_table
308
-     *
309
-     * @access public
310
-     * @return array
311
-     */
312
-    public function get_transaction_status_array()
313
-    {
314
-        return self::$_txn_status;
315
-    }
316
-
317
-
318
-    /**
319
-     *    get list of payment statuses
320
-     *
321
-     * @access private
322
-     * @return void
323
-     * @throws EE_Error
324
-     * @throws InvalidArgumentException
325
-     * @throws InvalidDataTypeException
326
-     * @throws InvalidInterfaceException
327
-     */
328
-    private function _get_payment_status_array()
329
-    {
330
-        self::$_pay_status = EEM_Payment::instance()->status_array(true);
331
-        $this->_template_args['payment_status'] = self::$_pay_status;
332
-    }
333
-
334
-
335
-    /**
336
-     *    _add_screen_options_default
337
-     *
338
-     * @access protected
339
-     * @return void
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     */
344
-    protected function _add_screen_options_default()
345
-    {
346
-        $this->_per_page_screen_option();
347
-    }
348
-
349
-
350
-    /**
351
-     * load_scripts_styles
352
-     *
353
-     * @access public
354
-     * @return void
355
-     */
356
-    public function load_scripts_styles()
357
-    {
358
-        // enqueue style
359
-        wp_register_style(
360
-            'espresso_txn',
361
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
362
-            array(),
363
-            EVENT_ESPRESSO_VERSION
364
-        );
365
-        wp_enqueue_style('espresso_txn');
366
-        // scripts
367
-        wp_register_script(
368
-            'espresso_txn',
369
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
370
-            array(
371
-                'ee_admin_js',
372
-                'ee-datepicker',
373
-                'jquery-ui-datepicker',
374
-                'jquery-ui-draggable',
375
-                'ee-dialog',
376
-                'ee-accounting',
377
-                'ee-serialize-full-array',
378
-            ),
379
-            EVENT_ESPRESSO_VERSION,
380
-            true
381
-        );
382
-        wp_enqueue_script('espresso_txn');
383
-    }
384
-
385
-
386
-    /**
387
-     *    load_scripts_styles_view_transaction
388
-     *
389
-     * @access public
390
-     * @return void
391
-     */
392
-    public function load_scripts_styles_view_transaction()
393
-    {
394
-        // styles
395
-        wp_enqueue_style('espresso-ui-theme');
396
-    }
397
-
398
-
399
-    /**
400
-     *    load_scripts_styles_default
401
-     *
402
-     * @access public
403
-     * @return void
404
-     */
405
-    public function load_scripts_styles_default()
406
-    {
407
-        // styles
408
-        wp_enqueue_style('espresso-ui-theme');
409
-    }
410
-
411
-
412
-    /**
413
-     *    _set_list_table_views_default
414
-     *
415
-     * @access protected
416
-     * @return void
417
-     */
418
-    protected function _set_list_table_views_default()
419
-    {
420
-        $this->_views = array(
421
-            'all'        => array(
422
-                'slug'  => 'all',
423
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
424
-                'count' => 0,
425
-            ),
426
-            'abandoned'  => array(
427
-                'slug'  => 'abandoned',
428
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
-                'count' => 0,
430
-            ),
431
-            'incomplete' => array(
432
-                'slug'  => 'incomplete',
433
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
434
-                'count' => 0,
435
-            ),
436
-        );
437
-        if (/**
438
-         * Filters whether a link to the "Failed Transactions" list table
439
-         * appears on the Transactions Admin Page list table.
440
-         * List display can be turned back on via the following:
441
-         * add_filter(
442
-         *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
443
-         *     '__return_true'
444
-         * );
445
-         *
446
-         * @since 4.9.70.p
447
-         * @param boolean                 $display_failed_txns_list
448
-         * @param Transactions_Admin_Page $this
449
-         */
450
-        apply_filters(
451
-            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
452
-            false,
453
-            $this
454
-        )
455
-        ) {
456
-            $this->_views['failed'] = array(
457
-                'slug'  => 'failed',
458
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
459
-                'count' => 0,
460
-            );
461
-        }
462
-    }
463
-
464
-
465
-    /**
466
-     * _set_transaction_object
467
-     * This sets the _transaction property for the transaction details screen
468
-     *
469
-     * @access private
470
-     * @return void
471
-     * @throws EE_Error
472
-     * @throws InvalidArgumentException
473
-     * @throws RuntimeException
474
-     * @throws InvalidDataTypeException
475
-     * @throws InvalidInterfaceException
476
-     * @throws ReflectionException
477
-     */
478
-    private function _set_transaction_object()
479
-    {
480
-        if ($this->_transaction instanceof EE_Transaction) {
481
-            return;
482
-        } //get out we've already set the object
483
-
484
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
485
-            ? absint($this->_req_data['TXN_ID'])
486
-            : false;
487
-
488
-        // get transaction object
489
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
490
-        $this->_session = $this->_transaction instanceof EE_Transaction
491
-            ? $this->_transaction->session_data()
492
-            : null;
493
-        if ($this->_transaction instanceof EE_Transaction) {
494
-            $this->_transaction->verify_abandoned_transaction_status();
495
-        }
496
-
497
-        if (! $this->_transaction instanceof EE_Transaction) {
498
-            $error_msg = sprintf(
499
-                esc_html__(
500
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
501
-                    'event_espresso'
502
-                ),
503
-                $TXN_ID
504
-            );
505
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
506
-        }
507
-    }
508
-
509
-
510
-    /**
511
-     *    _transaction_legend_items
512
-     *
513
-     * @access protected
514
-     * @return array
515
-     * @throws EE_Error
516
-     * @throws InvalidArgumentException
517
-     * @throws ReflectionException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     */
521
-    protected function _transaction_legend_items()
522
-    {
523
-        EE_Registry::instance()->load_helper('MSG_Template');
524
-        $items = array();
525
-
526
-        if (EE_Registry::instance()->CAP->current_user_can(
527
-            'ee_read_global_messages',
528
-            'view_filtered_messages'
529
-        )) {
530
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
531
-            if (is_array($related_for_icon)
532
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
533
-            ) {
534
-                $items['view_related_messages'] = array(
535
-                    'class' => $related_for_icon['css_class'],
536
-                    'desc'  => $related_for_icon['label'],
537
-                );
538
-            }
539
-        }
540
-
541
-        $items = apply_filters(
542
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
543
-            array_merge(
544
-                $items,
545
-                array(
546
-                    'view_details'          => array(
547
-                        'class' => 'dashicons dashicons-cart',
548
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
549
-                    ),
550
-                    'view_invoice'          => array(
551
-                        'class' => 'dashicons dashicons-media-spreadsheet',
552
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
553
-                    ),
554
-                    'view_receipt'          => array(
555
-                        'class' => 'dashicons dashicons-media-default',
556
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
557
-                    ),
558
-                    'view_registration'     => array(
559
-                        'class' => 'dashicons dashicons-clipboard',
560
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
561
-                    ),
562
-                    'payment_overview_link' => array(
563
-                        'class' => 'dashicons dashicons-money',
564
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
565
-                    ),
566
-                )
567
-            )
568
-        );
569
-
570
-        if (EEH_MSG_Template::is_mt_active('payment_reminder')
571
-            && EE_Registry::instance()->CAP->current_user_can(
572
-                'ee_send_message',
573
-                'espresso_transactions_send_payment_reminder'
574
-            )
575
-        ) {
576
-            $items['send_payment_reminder'] = array(
577
-                'class' => 'dashicons dashicons-email-alt',
578
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
579
-            );
580
-        } else {
581
-            $items['blank*'] = array(
582
-                'class' => '',
583
-                'desc'  => '',
584
-            );
585
-        }
586
-        $more_items = apply_filters(
587
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
588
-            array(
589
-                'overpaid'   => array(
590
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
591
-                    'desc'  => EEH_Template::pretty_status(
592
-                        EEM_Transaction::overpaid_status_code,
593
-                        false,
594
-                        'sentence'
595
-                    ),
596
-                ),
597
-                'complete'   => array(
598
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
599
-                    'desc'  => EEH_Template::pretty_status(
600
-                        EEM_Transaction::complete_status_code,
601
-                        false,
602
-                        'sentence'
603
-                    ),
604
-                ),
605
-                'incomplete' => array(
606
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
607
-                    'desc'  => EEH_Template::pretty_status(
608
-                        EEM_Transaction::incomplete_status_code,
609
-                        false,
610
-                        'sentence'
611
-                    ),
612
-                ),
613
-                'abandoned'  => array(
614
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
615
-                    'desc'  => EEH_Template::pretty_status(
616
-                        EEM_Transaction::abandoned_status_code,
617
-                        false,
618
-                        'sentence'
619
-                    ),
620
-                ),
621
-                'failed'     => array(
622
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
623
-                    'desc'  => EEH_Template::pretty_status(
624
-                        EEM_Transaction::failed_status_code,
625
-                        false,
626
-                        'sentence'
627
-                    ),
628
-                ),
629
-            )
630
-        );
631
-
632
-        return array_merge($items, $more_items);
633
-    }
634
-
635
-
636
-    /**
637
-     *    _transactions_overview_list_table
638
-     *
639
-     * @access protected
640
-     * @return void
641
-     * @throws DomainException
642
-     * @throws EE_Error
643
-     * @throws InvalidArgumentException
644
-     * @throws InvalidDataTypeException
645
-     * @throws InvalidInterfaceException
646
-     * @throws ReflectionException
647
-     */
648
-    protected function _transactions_overview_list_table()
649
-    {
650
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
651
-        $event = isset($this->_req_data['EVT_ID'])
652
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
653
-            : null;
654
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
655
-            ? sprintf(
656
-                esc_html__(
657
-                    '%sViewing Transactions for the Event: %s%s',
658
-                    'event_espresso'
659
-                ),
660
-                '<h3>',
661
-                '<a href="'
662
-                . EE_Admin_Page::add_query_args_and_nonce(
663
-                    array('action' => 'edit', 'post' => $event->ID()),
664
-                    EVENTS_ADMIN_URL
665
-                )
666
-                . '" title="'
667
-                . esc_attr__(
668
-                    'Click to Edit event',
669
-                    'event_espresso'
670
-                )
671
-                . '">' . $event->name() . '</a>',
672
-                '</h3>'
673
-            )
674
-            : '';
675
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
676
-        $this->display_admin_list_table_page_with_no_sidebar();
677
-    }
678
-
679
-
680
-    /**
681
-     *    _transaction_details
682
-     * generates HTML for the View Transaction Details Admin page
683
-     *
684
-     * @access protected
685
-     * @return void
686
-     * @throws DomainException
687
-     * @throws EE_Error
688
-     * @throws InvalidArgumentException
689
-     * @throws InvalidDataTypeException
690
-     * @throws InvalidInterfaceException
691
-     * @throws RuntimeException
692
-     * @throws ReflectionException
693
-     */
694
-    protected function _transaction_details()
695
-    {
696
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
697
-
698
-        $this->_set_transaction_status_array();
699
-
700
-        $this->_template_args = array();
701
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
702
-
703
-        $this->_set_transaction_object();
704
-
705
-        if (! $this->_transaction instanceof EE_Transaction) {
706
-            return;
707
-        }
708
-        $primary_registration = $this->_transaction->primary_registration();
709
-        $attendee = $primary_registration instanceof EE_Registration
710
-            ? $primary_registration->attendee()
711
-            : null;
712
-
713
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
714
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
715
-
716
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
717
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
718
-
719
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
720
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
721
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
722
-
723
-        $this->_template_args['grand_total'] = $this->_transaction->total();
724
-        $this->_template_args['total_paid'] = $this->_transaction->paid();
725
-
726
-        $amount_due = $this->_transaction->total() - $this->_transaction->paid();
727
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
728
-            $amount_due,
729
-            true
730
-        );
731
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
732
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
733
-                                                  . $this->_template_args['amount_due'];
734
-        } else {
735
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
736
-        }
737
-        $this->_template_args['amount_due_class'] = '';
738
-
739
-        if ($this->_transaction->paid() === $this->_transaction->total()) {
740
-            // paid in full
741
-            $this->_template_args['amount_due'] = false;
742
-        } elseif ($this->_transaction->paid() > $this->_transaction->total()) {
743
-            // overpaid
744
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
745
-        } elseif ($this->_transaction->total() > (float) 0) {
746
-            if ($this->_transaction->paid() > (float) 0) {
747
-                // monies owing
748
-                $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
749
-            } elseif ($this->_transaction->paid() === (float) 0) {
750
-                // no payments made yet
751
-                $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
752
-            }
753
-        } elseif ($this->_transaction->total() === (float) 0) {
754
-            // free event
755
-            $this->_template_args['amount_due'] = false;
756
-        }
757
-
758
-        $payment_method = $this->_transaction->payment_method();
759
-
760
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
761
-            ? $payment_method->admin_name()
762
-            : esc_html__('Unknown', 'event_espresso');
763
-
764
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
765
-        // link back to overview
766
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
767
-            ? $_SERVER['HTTP_REFERER']
768
-            : TXN_ADMIN_URL;
769
-
770
-
771
-        // next link
772
-        $next_txn = $this->_transaction->next(
773
-            null,
774
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
775
-            'TXN_ID'
776
-        );
777
-        $this->_template_args['next_transaction'] = $next_txn
778
-            ? $this->_next_link(
779
-                EE_Admin_Page::add_query_args_and_nonce(
780
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
781
-                    TXN_ADMIN_URL
782
-                ),
783
-                'dashicons dashicons-arrow-right ee-icon-size-22'
784
-            )
785
-            : '';
786
-        // previous link
787
-        $previous_txn = $this->_transaction->previous(
788
-            null,
789
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
790
-            'TXN_ID'
791
-        );
792
-        $this->_template_args['previous_transaction'] = $previous_txn
793
-            ? $this->_previous_link(
794
-                EE_Admin_Page::add_query_args_and_nonce(
795
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
796
-                    TXN_ADMIN_URL
797
-                ),
798
-                'dashicons dashicons-arrow-left ee-icon-size-22'
799
-            )
800
-            : '';
801
-
802
-        // were we just redirected here after adding a new registration ???
803
-        if (isset(
804
-            $this->_req_data['redirect_from'],
805
-            $this->_req_data['EVT_ID'],
806
-            $this->_req_data['event_name']
807
-        )) {
808
-            if (EE_Registry::instance()->CAP->current_user_can(
809
-                'ee_edit_registrations',
810
-                'espresso_registrations_new_registration',
811
-                $this->_req_data['EVT_ID']
812
-            )) {
813
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
814
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
815
-                    array(
816
-                        'page'     => 'espresso_registrations',
817
-                        'action'   => 'new_registration',
818
-                        'return'   => 'default',
819
-                        'TXN_ID'   => $this->_transaction->ID(),
820
-                        'event_id' => $this->_req_data['EVT_ID'],
821
-                    ),
822
-                    REG_ADMIN_URL
823
-                );
824
-                $this->_admin_page_title .= '">';
825
-
826
-                $this->_admin_page_title .= sprintf(
827
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
828
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
829
-                );
830
-                $this->_admin_page_title .= '</a>';
831
-            }
832
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
833
-        }
834
-        // grab messages at the last second
835
-        $this->_template_args['notices'] = EE_Error::get_notices();
836
-        // path to template
837
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
838
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
839
-            $template_path,
840
-            $this->_template_args,
841
-            true
842
-        );
843
-
844
-        // the details template wrapper
845
-        $this->display_admin_page_with_sidebar();
846
-    }
847
-
848
-
849
-    /**
850
-     *        _transaction_details_metaboxes
851
-     *
852
-     * @access protected
853
-     * @return void
854
-     * @throws EE_Error
855
-     * @throws InvalidArgumentException
856
-     * @throws InvalidDataTypeException
857
-     * @throws InvalidInterfaceException
858
-     * @throws RuntimeException
859
-     * @throws ReflectionException
860
-     */
861
-    protected function _transaction_details_metaboxes()
862
-    {
863
-
864
-        $this->_set_transaction_object();
865
-
866
-        if (! $this->_transaction instanceof EE_Transaction) {
867
-            return;
868
-        }
869
-        add_meta_box(
870
-            'edit-txn-details-mbox',
871
-            esc_html__('Transaction Details', 'event_espresso'),
872
-            array($this, 'txn_details_meta_box'),
873
-            $this->_wp_page_slug,
874
-            'normal',
875
-            'high'
876
-        );
877
-        add_meta_box(
878
-            'edit-txn-attendees-mbox',
879
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
-            array($this, 'txn_attendees_meta_box'),
881
-            $this->_wp_page_slug,
882
-            'normal',
883
-            'high',
884
-            array('TXN_ID' => $this->_transaction->ID())
885
-        );
886
-        add_meta_box(
887
-            'edit-txn-registrant-mbox',
888
-            esc_html__('Primary Contact', 'event_espresso'),
889
-            array($this, 'txn_registrant_side_meta_box'),
890
-            $this->_wp_page_slug,
891
-            'side',
892
-            'high'
893
-        );
894
-        add_meta_box(
895
-            'edit-txn-billing-info-mbox',
896
-            esc_html__('Billing Information', 'event_espresso'),
897
-            array($this, 'txn_billing_info_side_meta_box'),
898
-            $this->_wp_page_slug,
899
-            'side',
900
-            'high'
901
-        );
902
-    }
903
-
904
-
905
-    /**
906
-     * Callback for transaction actions metabox.
907
-     *
908
-     * @param EE_Transaction|null $transaction
909
-     * @return string
910
-     * @throws DomainException
911
-     * @throws EE_Error
912
-     * @throws InvalidArgumentException
913
-     * @throws InvalidDataTypeException
914
-     * @throws InvalidInterfaceException
915
-     * @throws ReflectionException
916
-     * @throws RuntimeException
917
-     */
918
-    public function getActionButtons(EE_Transaction $transaction = null)
919
-    {
920
-        $content = '';
921
-        $actions = array();
922
-        if (! $transaction instanceof EE_Transaction) {
923
-            return $content;
924
-        }
925
-        /** @var EE_Registration $primary_registration */
926
-        $primary_registration = $transaction->primary_registration();
927
-        $attendee = $primary_registration instanceof EE_Registration
928
-            ? $primary_registration->attendee()
929
-            : null;
930
-
931
-        if ($attendee instanceof EE_Attendee
932
-            && EE_Registry::instance()->CAP->current_user_can(
933
-                'ee_send_message',
934
-                'espresso_transactions_send_payment_reminder'
935
-            )
936
-        ) {
937
-            $actions['payment_reminder'] =
938
-                EEH_MSG_Template::is_mt_active('payment_reminder')
939
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
940
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
941
-                    ? EEH_Template::get_button_or_link(
942
-                        EE_Admin_Page::add_query_args_and_nonce(
943
-                            array(
944
-                                'action'      => 'send_payment_reminder',
945
-                                'TXN_ID'      => $this->_transaction->ID(),
946
-                                'redirect_to' => 'view_transaction',
947
-                            ),
948
-                            TXN_ADMIN_URL
949
-                        ),
950
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
951
-                        'button secondary-button',
952
-                        'dashicons dashicons-email-alt'
953
-                    )
954
-                    : '';
955
-        }
956
-
957
-        if (EE_Registry::instance()->CAP->current_user_can(
958
-            'ee_edit_payments',
959
-            'espresso_transactions_recalculate_line_items'
960
-        )
961
-        ) {
962
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
963
-                EE_Admin_Page::add_query_args_and_nonce(
964
-                    array(
965
-                        'action'      => 'espresso_recalculate_line_items',
966
-                        'TXN_ID'      => $this->_transaction->ID(),
967
-                        'redirect_to' => 'view_transaction',
968
-                    ),
969
-                    TXN_ADMIN_URL
970
-                ),
971
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
972
-                'button secondary-button',
973
-                'dashicons dashicons-update'
974
-            );
975
-        }
976
-
977
-        if ($primary_registration instanceof EE_Registration
978
-            && EEH_MSG_Template::is_mt_active('receipt')
979
-        ) {
980
-            $actions['receipt'] = EEH_Template::get_button_or_link(
981
-                $primary_registration->receipt_url(),
982
-                esc_html__('View Receipt', 'event_espresso'),
983
-                'button secondary-button',
984
-                'dashicons dashicons-media-default'
985
-            );
986
-        }
987
-
988
-        if ($primary_registration instanceof EE_Registration
989
-            && EEH_MSG_Template::is_mt_active('invoice')
990
-        ) {
991
-            $actions['invoice'] = EEH_Template::get_button_or_link(
992
-                $primary_registration->invoice_url(),
993
-                esc_html__('View Invoice', 'event_espresso'),
994
-                'button secondary-button',
995
-                'dashicons dashicons-media-spreadsheet'
996
-            );
997
-        }
998
-        $actions = array_filter(
999
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1000
-        );
1001
-        if ($actions) {
1002
-            $content = '<ul>';
1003
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1004
-            $content .= '</uL>';
1005
-        }
1006
-        return $content;
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * txn_details_meta_box
1012
-     * generates HTML for the Transaction main meta box
1013
-     *
1014
-     * @return void
1015
-     * @throws DomainException
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     * @throws RuntimeException
1021
-     * @throws ReflectionException
1022
-     */
1023
-    public function txn_details_meta_box()
1024
-    {
1025
-        $this->_set_transaction_object();
1026
-        $this->_template_args['TXN_ID'] = $this->_transaction->ID();
1027
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1028
-            ? $this->_transaction->primary_registration()->attendee()
1029
-            : null;
1030
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1031
-            'ee_edit_payments',
1032
-            'apply_payment_or_refund_from_registration_details'
1033
-        );
1034
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1035
-            'ee_delete_payments',
1036
-            'delete_payment_from_registration_details'
1037
-        );
1038
-
1039
-        // get line table
1040
-        EEH_Autoloader::register_line_item_display_autoloaders();
1041
-        $Line_Item_Display = new EE_Line_Item_Display(
1042
-            'admin_table',
1043
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1044
-        );
1045
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1046
-            $this->_transaction->total_line_item()
1047
-        );
1048
-        $this->_template_args['REG_code'] = $this->_transaction->primary_registration() instanceof EE_Registration
1049
-            ? $this->_transaction->primary_registration()->reg_code()
1050
-            : null;
1051
-        // process taxes
1052
-        $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1053
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1054
-
1055
-        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1056
-            $this->_transaction->total(),
1057
-            false,
1058
-            false
1059
-        );
1060
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1061
-        $this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1062
-
1063
-        // process payment details
1064
-        $payments = $this->_transaction->payments();
1065
-        if (! empty($payments)) {
1066
-            $this->_template_args['payments'] = $payments;
1067
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1068
-        } else {
1069
-            $this->_template_args['payments'] = false;
1070
-            $this->_template_args['existing_reg_payments'] = array();
1071
-        }
1072
-
1073
-        $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1074
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1075
-            array('action' => 'espresso_delete_payment'),
1076
-            TXN_ADMIN_URL
1077
-        );
1078
-
1079
-        if (isset($txn_details['invoice_number'])) {
1080
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1081
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1082
-                'Invoice Number',
1083
-                'event_espresso'
1084
-            );
1085
-        }
1086
-
1087
-        $this->_template_args['txn_details']['registration_session']['value']
1088
-            = $this->_transaction->primary_registration() instanceof EE_Registration
1089
-            ? $this->_transaction->primary_registration()->session_ID()
1090
-            : null;
1091
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1092
-            'Registration Session',
1093
-            'event_espresso'
1094
-        );
1095
-
1096
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1097
-            ? $this->_session['ip_address']
1098
-            : '';
1099
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1100
-            'Transaction placed from IP',
1101
-            'event_espresso'
1102
-        );
1103
-
1104
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1105
-            ? $this->_session['user_agent']
1106
-            : '';
1107
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1108
-            'Registrant User Agent',
1109
-            'event_espresso'
1110
-        );
1111
-
1112
-        $reg_steps = '<ul>';
1113
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1114
-            if ($reg_step_status === true) {
1115
-                $reg_steps .= '<li style="color:#70cc50">'
1116
-                              . sprintf(
1117
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1118
-                                  ucwords(str_replace('_', ' ', $reg_step))
1119
-                              )
1120
-                              . '</li>';
1121
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1122
-                $reg_steps .= '<li style="color:#2EA2CC">'
1123
-                              . sprintf(
1124
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1125
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1126
-                                  date(
1127
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1128
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1129
-                                  )
1130
-                              )
1131
-                              . '</li>';
1132
-            } else {
1133
-                $reg_steps .= '<li style="color:#E76700">'
1134
-                              . sprintf(
1135
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1136
-                                  ucwords(str_replace('_', ' ', $reg_step))
1137
-                              )
1138
-                              . '</li>';
1139
-            }
1140
-        }
1141
-        $reg_steps .= '</ul>';
1142
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1143
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1144
-            'Registration Step Progress',
1145
-            'event_espresso'
1146
-        );
1147
-
1148
-
1149
-        $this->_get_registrations_to_apply_payment_to();
1150
-        $this->_get_payment_methods($payments);
1151
-        $this->_get_payment_status_array();
1152
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1153
-
1154
-        $this->_template_args['transaction_form_url'] = add_query_arg(
1155
-            array(
1156
-                'action'  => 'edit_transaction',
1157
-                'process' => 'transaction',
1158
-            ),
1159
-            TXN_ADMIN_URL
1160
-        );
1161
-        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1162
-            array(
1163
-                'page'   => 'espresso_transactions',
1164
-                'action' => 'espresso_apply_payment',
1165
-            ),
1166
-            WP_AJAX_URL
1167
-        );
1168
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1169
-            array(
1170
-                'page'   => 'espresso_transactions',
1171
-                'action' => 'espresso_delete_payment',
1172
-            ),
1173
-            WP_AJAX_URL
1174
-        );
1175
-
1176
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1177
-
1178
-        // 'espresso_delete_payment_nonce'
1179
-
1180
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1181
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1182
-    }
1183
-
1184
-
1185
-    /**
1186
-     * _get_registration_payment_IDs
1187
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1188
-     *
1189
-     * @access protected
1190
-     * @param EE_Payment[] $payments
1191
-     * @return array
1192
-     * @throws EE_Error
1193
-     * @throws InvalidArgumentException
1194
-     * @throws InvalidDataTypeException
1195
-     * @throws InvalidInterfaceException
1196
-     * @throws ReflectionException
1197
-     */
1198
-    protected function _get_registration_payment_IDs($payments = array())
1199
-    {
1200
-        $existing_reg_payments = array();
1201
-        // get all reg payments for these payments
1202
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1203
-            array(
1204
-                array(
1205
-                    'PAY_ID' => array(
1206
-                        'IN',
1207
-                        array_keys($payments),
1208
-                    ),
1209
-                ),
1210
-            )
1211
-        );
1212
-        if (! empty($reg_payments)) {
1213
-            foreach ($payments as $payment) {
1214
-                if (! $payment instanceof EE_Payment) {
1215
-                    continue;
1216
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1217
-                    $existing_reg_payments[ $payment->ID() ] = array();
1218
-                }
1219
-                foreach ($reg_payments as $reg_payment) {
1220
-                    if ($reg_payment instanceof EE_Registration_Payment
1221
-                        && $reg_payment->payment_ID() === $payment->ID()
1222
-                    ) {
1223
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1224
-                    }
1225
-                }
1226
-            }
1227
-        }
1228
-
1229
-        return $existing_reg_payments;
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * _get_registrations_to_apply_payment_to
1235
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1236
-     * which allows the admin to only apply the payment to the specific registrations
1237
-     *
1238
-     * @access protected
1239
-     * @return void
1240
-     * @throws EE_Error
1241
-     * @throws InvalidArgumentException
1242
-     * @throws InvalidDataTypeException
1243
-     * @throws InvalidInterfaceException
1244
-     * @throws ReflectionException
1245
-     */
1246
-    protected function _get_registrations_to_apply_payment_to()
1247
-    {
1248
-        // we want any registration with an active status (ie: not deleted or cancelled)
1249
-        $query_params = array(
1250
-            array(
1251
-                'STS_ID' => array(
1252
-                    'IN',
1253
-                    array(
1254
-                        EEM_Registration::status_id_approved,
1255
-                        EEM_Registration::status_id_pending_payment,
1256
-                        EEM_Registration::status_id_not_approved,
1257
-                    ),
1258
-                ),
1259
-            ),
1260
-        );
1261
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1262
-            '',
1263
-            'txn-admin-apply-payment-to-registrations-dv',
1264
-            '',
1265
-            'clear: both; margin: 1.5em 0 0; display: none;'
1266
-        );
1267
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1268
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1269
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1270
-            EEH_HTML::tr(
1271
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1272
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1273
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1274
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1275
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1276
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1277
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1278
-            )
1279
-        );
1280
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1281
-        // get registrations for TXN
1282
-        $registrations = $this->_transaction->registrations($query_params);
1283
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1284
-        foreach ($registrations as $registration) {
1285
-            if ($registration instanceof EE_Registration) {
1286
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
1287
-                    ? $registration->attendee()->full_name()
1288
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1289
-                $owing = $registration->final_price() - $registration->paid();
1290
-                $taxable = $registration->ticket()->taxable()
1291
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1292
-                    : '';
1293
-                $checked = empty($existing_reg_payments)
1294
-                           || in_array($registration->ID(), $existing_reg_payments, true)
1295
-                    ? ' checked="checked"'
1296
-                    : '';
1297
-                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1298
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1299
-                    EEH_HTML::td($registration->ID()) .
1300
-                    EEH_HTML::td($attendee_name) .
1301
-                    EEH_HTML::td(
1302
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1303
-                    ) .
1304
-                    EEH_HTML::td($registration->event_name()) .
1305
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1306
-                    EEH_HTML::td(
1307
-                        EEH_Template::format_currency($owing),
1308
-                        '',
1309
-                        'txn-admin-payment-owing-td jst-cntr'
1310
-                    ) .
1311
-                    EEH_HTML::td(
1312
-                        '<input type="checkbox" value="' . $registration->ID()
1313
-                        . '" name="txn_admin_payment[registrations]"'
1314
-                        . $checked . $disabled . '>',
1315
-                        '',
1316
-                        'jst-cntr'
1317
-                    ),
1318
-                    'apply-payment-registration-row-' . $registration->ID()
1319
-                );
1320
-            }
1321
-        }
1322
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1323
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1324
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1325
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1326
-            esc_html__(
1327
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1328
-                'event_espresso'
1329
-            ),
1330
-            '',
1331
-            'clear description'
1332
-        );
1333
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1334
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * _get_reg_status_selection
1340
-     *
1341
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1342
-     *         instead of events.
1343
-     * @access protected
1344
-     * @return void
1345
-     * @throws EE_Error
1346
-     */
1347
-    protected function _get_reg_status_selection()
1348
-    {
1349
-        // first get all possible statuses
1350
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1351
-        // let's add a "don't change" option.
1352
-        $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1353
-        $status_array = array_merge($status_array, $statuses);
1354
-        $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1355
-            'txn_reg_status_change[reg_status]',
1356
-            $status_array,
1357
-            'NAN',
1358
-            'id="txn-admin-payment-reg-status-inp"',
1359
-            'txn-reg-status-change-reg-status'
1360
-        );
1361
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1362
-            'delete_txn_reg_status_change[reg_status]',
1363
-            $status_array,
1364
-            'NAN',
1365
-            'delete-txn-admin-payment-reg-status-inp',
1366
-            'delete-txn-reg-status-change-reg-status'
1367
-        );
1368
-    }
1369
-
1370
-
1371
-    /**
1372
-     *    _get_payment_methods
1373
-     * Gets all the payment methods available generally, or the ones that are already
1374
-     * selected on these payments (in case their payment methods are no longer active).
1375
-     * Has the side-effect of updating the template args' payment_methods item
1376
-     *
1377
-     * @access private
1378
-     * @param EE_Payment[] to show on this page
1379
-     * @return void
1380
-     * @throws EE_Error
1381
-     * @throws InvalidArgumentException
1382
-     * @throws InvalidDataTypeException
1383
-     * @throws InvalidInterfaceException
1384
-     * @throws ReflectionException
1385
-     */
1386
-    private function _get_payment_methods($payments = array())
1387
-    {
1388
-        $payment_methods_of_payments = array();
1389
-        foreach ($payments as $payment) {
1390
-            if ($payment instanceof EE_Payment) {
1391
-                $payment_methods_of_payments[] = $payment->ID();
1392
-            }
1393
-        }
1394
-        if ($payment_methods_of_payments) {
1395
-            $query_args = array(
1396
-                array(
1397
-                    'OR*payment_method_for_payment' => array(
1398
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1399
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1400
-                    ),
1401
-                ),
1402
-            );
1403
-        } else {
1404
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1405
-        }
1406
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * txn_attendees_meta_box
1412
-     *    generates HTML for the Attendees Transaction main meta box
1413
-     *
1414
-     * @access public
1415
-     * @param WP_Post $post
1416
-     * @param array   $metabox
1417
-     * @return void
1418
-     * @throws DomainException
1419
-     * @throws EE_Error
1420
-     * @throws InvalidArgumentException
1421
-     * @throws InvalidDataTypeException
1422
-     * @throws InvalidInterfaceException
1423
-     * @throws ReflectionException
1424
-     */
1425
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1426
-    {
1427
-
1428
-        /** @noinspection NonSecureExtractUsageInspection */
1429
-        extract($metabox['args']);
1430
-        $this->_template_args['post'] = $post;
1431
-        $this->_template_args['event_attendees'] = array();
1432
-        // process items in cart
1433
-        $line_items = $this->_transaction->get_many_related(
1434
-            'Line_Item',
1435
-            array(array('LIN_type' => 'line-item'))
1436
-        );
1437
-        if (! empty($line_items)) {
1438
-            foreach ($line_items as $item) {
1439
-                if ($item instanceof EE_Line_Item) {
1440
-                    switch ($item->OBJ_type()) {
1441
-                        case 'Event':
1442
-                            break;
1443
-                        case 'Ticket':
1444
-                            $ticket = $item->ticket();
1445
-                            // right now we're only handling tickets here.
1446
-                            // Cause its expected that only tickets will have attendees right?
1447
-                            if (! $ticket instanceof EE_Ticket) {
1448
-                                break;
1449
-                            }
1450
-                            try {
1451
-                                $event_name = $ticket->get_event_name();
1452
-                            } catch (Exception $e) {
1453
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1454
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1455
-                            }
1456
-                            $event_name .= ' - ' . $item->name();
1457
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1458
-                            // now get all of the registrations for this transaction that use this ticket
1459
-                            $registrations = $ticket->registrations(
1460
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1461
-                            );
1462
-                            foreach ($registrations as $registration) {
1463
-                                if (! $registration instanceof EE_Registration) {
1464
-                                    break;
1465
-                                }
1466
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1467
-                                    = $registration->status_ID();
1468
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1469
-                                    = $registration->count();
1470
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1471
-                                    = $event_name;
1472
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1473
-                                    = $ticket_price;
1474
-                                // attendee info
1475
-                                $attendee = $registration->get_first_related('Attendee');
1476
-                                if ($attendee instanceof EE_Attendee) {
1477
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1478
-                                        = $attendee->ID();
1479
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1480
-                                        = $attendee->full_name();
1481
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1482
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1483
-                                          . esc_html__(
1484
-                                              ' Event',
1485
-                                              'event_espresso'
1486
-                                          )
1487
-                                          . '">' . $attendee->email() . '</a>';
1488
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1489
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1490
-                                } else {
1491
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1492
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1493
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1494
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1495
-                                }
1496
-                            }
1497
-                            break;
1498
-                    }
1499
-                }
1500
-            }
1501
-
1502
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1503
-                array(
1504
-                    'action'  => 'edit_transaction',
1505
-                    'process' => 'attendees',
1506
-                ),
1507
-                TXN_ADMIN_URL
1508
-            );
1509
-            echo EEH_Template::display_template(
1510
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1511
-                $this->_template_args,
1512
-                true
1513
-            );
1514
-        } else {
1515
-            echo sprintf(
1516
-                esc_html__(
1517
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1518
-                    'event_espresso'
1519
-                ),
1520
-                '<p class="important-notice">',
1521
-                '</p>'
1522
-            );
1523
-        }
1524
-    }
1525
-
1526
-
1527
-    /**
1528
-     * txn_registrant_side_meta_box
1529
-     * generates HTML for the Edit Transaction side meta box
1530
-     *
1531
-     * @access public
1532
-     * @return void
1533
-     * @throws DomainException
1534
-     * @throws EE_Error
1535
-     * @throws InvalidArgumentException
1536
-     * @throws InvalidDataTypeException
1537
-     * @throws InvalidInterfaceException
1538
-     * @throws ReflectionException
1539
-     */
1540
-    public function txn_registrant_side_meta_box()
1541
-    {
1542
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1543
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1544
-            : null;
1545
-        if (! $primary_att instanceof EE_Attendee) {
1546
-            $this->_template_args['no_attendee_message'] = esc_html__(
1547
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1548
-                'event_espresso'
1549
-            );
1550
-            $primary_att = EEM_Attendee::instance()->create_default_object();
1551
-        }
1552
-        $this->_template_args['ATT_ID'] = $primary_att->ID();
1553
-        $this->_template_args['prime_reg_fname'] = $primary_att->fname();
1554
-        $this->_template_args['prime_reg_lname'] = $primary_att->lname();
1555
-        $this->_template_args['prime_reg_email'] = $primary_att->email();
1556
-        $this->_template_args['prime_reg_phone'] = $primary_att->phone();
1557
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1558
-            array(
1559
-                'action' => 'edit_attendee',
1560
-                'post'   => $primary_att->ID(),
1561
-            ),
1562
-            REG_ADMIN_URL
1563
-        );
1564
-        // get formatted address for registrant
1565
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1566
-        echo EEH_Template::display_template(
1567
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1568
-            $this->_template_args,
1569
-            true
1570
-        );
1571
-    }
1572
-
1573
-
1574
-    /**
1575
-     * txn_billing_info_side_meta_box
1576
-     *    generates HTML for the Edit Transaction side meta box
1577
-     *
1578
-     * @access public
1579
-     * @return void
1580
-     * @throws DomainException
1581
-     * @throws EE_Error
1582
-     */
1583
-    public function txn_billing_info_side_meta_box()
1584
-    {
1585
-
1586
-        $this->_template_args['billing_form'] = $this->_transaction->billing_info();
1587
-        $this->_template_args['billing_form_url'] = add_query_arg(
1588
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1589
-            TXN_ADMIN_URL
1590
-        );
1591
-
1592
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1593
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1594
-    }
1595
-
1596
-
1597
-    /**
1598
-     * apply_payments_or_refunds
1599
-     *    registers a payment or refund made towards a transaction
1600
-     *
1601
-     * @access public
1602
-     * @return void
1603
-     * @throws EE_Error
1604
-     * @throws InvalidArgumentException
1605
-     * @throws ReflectionException
1606
-     * @throws RuntimeException
1607
-     * @throws InvalidDataTypeException
1608
-     * @throws InvalidInterfaceException
1609
-     */
1610
-    public function apply_payments_or_refunds()
1611
-    {
1612
-        $json_response_data = array('return_data' => false);
1613
-        $valid_data = $this->_validate_payment_request_data();
1614
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1615
-            'ee_edit_payments',
1616
-            'apply_payment_or_refund_from_registration_details'
1617
-        );
1618
-        if (! empty($valid_data) && $has_access) {
1619
-            $PAY_ID = $valid_data['PAY_ID'];
1620
-            // save  the new payment
1621
-            $payment = $this->_create_payment_from_request_data($valid_data);
1622
-            // get the TXN for this payment
1623
-            $transaction = $payment->transaction();
1624
-            // verify transaction
1625
-            if ($transaction instanceof EE_Transaction) {
1626
-                // calculate_total_payments_and_update_status
1627
-                $this->_process_transaction_payments($transaction);
1628
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1629
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1630
-                // apply payment to registrations (if applicable)
1631
-                if (! empty($REG_IDs)) {
1632
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1633
-                    $this->_maybe_send_notifications();
1634
-                    // now process status changes for the same registrations
1635
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1636
-                }
1637
-                $this->_maybe_send_notifications($payment);
1638
-                // prepare to render page
1639
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1640
-                do_action(
1641
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1642
-                    $transaction,
1643
-                    $payment
1644
-                );
1645
-            } else {
1646
-                EE_Error::add_error(
1647
-                    esc_html__(
1648
-                        'A valid Transaction for this payment could not be retrieved.',
1649
-                        'event_espresso'
1650
-                    ),
1651
-                    __FILE__,
1652
-                    __FUNCTION__,
1653
-                    __LINE__
1654
-                );
1655
-            }
1656
-        } elseif ($has_access) {
1657
-            EE_Error::add_error(
1658
-                esc_html__(
1659
-                    'The payment form data could not be processed. Please try again.',
1660
-                    'event_espresso'
1661
-                ),
1662
-                __FILE__,
1663
-                __FUNCTION__,
1664
-                __LINE__
1665
-            );
1666
-        } else {
1667
-            EE_Error::add_error(
1668
-                esc_html__(
1669
-                    'You do not have access to apply payments or refunds to a registration.',
1670
-                    'event_espresso'
1671
-                ),
1672
-                __FILE__,
1673
-                __FUNCTION__,
1674
-                __LINE__
1675
-            );
1676
-        }
1677
-        $notices = EE_Error::get_notices(
1678
-            false,
1679
-            false,
1680
-            false
1681
-        );
1682
-        $this->_template_args = array(
1683
-            'data'    => $json_response_data,
1684
-            'error'   => $notices['errors'],
1685
-            'success' => $notices['success'],
1686
-        );
1687
-        $this->_return_json();
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * _validate_payment_request_data
1693
-     *
1694
-     * @return array
1695
-     * @throws EE_Error
1696
-     * @throws InvalidArgumentException
1697
-     * @throws InvalidDataTypeException
1698
-     * @throws InvalidInterfaceException
1699
-     */
1700
-    protected function _validate_payment_request_data()
1701
-    {
1702
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1703
-            return array();
1704
-        }
1705
-        $payment_form = $this->_generate_payment_form_section();
1706
-        try {
1707
-            if ($payment_form->was_submitted()) {
1708
-                $payment_form->receive_form_submission();
1709
-                if (! $payment_form->is_valid()) {
1710
-                    $submission_error_messages = array();
1711
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1712
-                        if ($validation_error instanceof EE_Validation_Error) {
1713
-                            $submission_error_messages[] = sprintf(
1714
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1715
-                                $validation_error->get_form_section()->html_label_text(),
1716
-                                $validation_error->getMessage()
1717
-                            );
1718
-                        }
1719
-                    }
1720
-                    EE_Error::add_error(
1721
-                        implode('<br />', $submission_error_messages),
1722
-                        __FILE__,
1723
-                        __FUNCTION__,
1724
-                        __LINE__
1725
-                    );
1726
-                    return array();
1727
-                }
1728
-            }
1729
-        } catch (EE_Error $e) {
1730
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1731
-            return array();
1732
-        }
1733
-
1734
-        return $payment_form->valid_data();
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * _generate_payment_form_section
1740
-     *
1741
-     * @return EE_Form_Section_Proper
1742
-     * @throws EE_Error
1743
-     */
1744
-    protected function _generate_payment_form_section()
1745
-    {
1746
-        return new EE_Form_Section_Proper(
1747
-            array(
1748
-                'name'        => 'txn_admin_payment',
1749
-                'subsections' => array(
1750
-                    'PAY_ID'          => new EE_Text_Input(
1751
-                        array(
1752
-                            'default'               => 0,
1753
-                            'required'              => false,
1754
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1755
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1756
-                        )
1757
-                    ),
1758
-                    'TXN_ID'          => new EE_Text_Input(
1759
-                        array(
1760
-                            'default'               => 0,
1761
-                            'required'              => true,
1762
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1763
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1764
-                        )
1765
-                    ),
1766
-                    'type'            => new EE_Text_Input(
1767
-                        array(
1768
-                            'default'               => 1,
1769
-                            'required'              => true,
1770
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1771
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1772
-                        )
1773
-                    ),
1774
-                    'amount'          => new EE_Text_Input(
1775
-                        array(
1776
-                            'default'               => 0,
1777
-                            'required'              => true,
1778
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1779
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1780
-                        )
1781
-                    ),
1782
-                    'status'          => new EE_Text_Input(
1783
-                        array(
1784
-                            'default'         => EEM_Payment::status_id_approved,
1785
-                            'required'        => true,
1786
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1787
-                        )
1788
-                    ),
1789
-                    'PMD_ID'          => new EE_Text_Input(
1790
-                        array(
1791
-                            'default'               => 2,
1792
-                            'required'              => true,
1793
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1794
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1795
-                        )
1796
-                    ),
1797
-                    'date'            => new EE_Text_Input(
1798
-                        array(
1799
-                            'default'         => time(),
1800
-                            'required'        => true,
1801
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1802
-                        )
1803
-                    ),
1804
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1805
-                        array(
1806
-                            'default'               => '',
1807
-                            'required'              => false,
1808
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1809
-                            'validation_strategies' => array(
1810
-                                new EE_Max_Length_Validation_Strategy(
1811
-                                    esc_html__('Input too long', 'event_espresso'),
1812
-                                    100
1813
-                                ),
1814
-                            ),
1815
-                        )
1816
-                    ),
1817
-                    'po_number'       => new EE_Text_Input(
1818
-                        array(
1819
-                            'default'               => '',
1820
-                            'required'              => false,
1821
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1822
-                            'validation_strategies' => array(
1823
-                                new EE_Max_Length_Validation_Strategy(
1824
-                                    esc_html__('Input too long', 'event_espresso'),
1825
-                                    100
1826
-                                ),
1827
-                            ),
1828
-                        )
1829
-                    ),
1830
-                    'accounting'      => new EE_Text_Input(
1831
-                        array(
1832
-                            'default'               => '',
1833
-                            'required'              => false,
1834
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1835
-                            'validation_strategies' => array(
1836
-                                new EE_Max_Length_Validation_Strategy(
1837
-                                    esc_html__('Input too long', 'event_espresso'),
1838
-                                    100
1839
-                                ),
1840
-                            ),
1841
-                        )
1842
-                    ),
1843
-                ),
1844
-            )
1845
-        );
1846
-    }
1847
-
1848
-
1849
-    /**
1850
-     * _create_payment_from_request_data
1851
-     *
1852
-     * @param array $valid_data
1853
-     * @return EE_Payment
1854
-     * @throws EE_Error
1855
-     * @throws InvalidArgumentException
1856
-     * @throws InvalidDataTypeException
1857
-     * @throws InvalidInterfaceException
1858
-     * @throws ReflectionException
1859
-     */
1860
-    protected function _create_payment_from_request_data($valid_data)
1861
-    {
1862
-        $PAY_ID = $valid_data['PAY_ID'];
1863
-        // get payment amount
1864
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1865
-        // payments have a type value of 1 and refunds have a type value of -1
1866
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1867
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1868
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1869
-        $date = $valid_data['date']
1870
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1871
-            : date('Y-m-d g:i a', current_time('timestamp'));
1872
-        $payment = EE_Payment::new_instance(
1873
-            array(
1874
-                'TXN_ID'              => $valid_data['TXN_ID'],
1875
-                'STS_ID'              => $valid_data['status'],
1876
-                'PAY_timestamp'       => $date,
1877
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1878
-                'PMD_ID'              => $valid_data['PMD_ID'],
1879
-                'PAY_amount'          => $amount,
1880
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1881
-                'PAY_po_number'       => $valid_data['po_number'],
1882
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1883
-                'PAY_details'         => $valid_data,
1884
-                'PAY_ID'              => $PAY_ID,
1885
-            ),
1886
-            '',
1887
-            array('Y-m-d', 'g:i a')
1888
-        );
1889
-
1890
-        if (! $payment->save()) {
1891
-            EE_Error::add_error(
1892
-                sprintf(
1893
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1894
-                    $payment->ID()
1895
-                ),
1896
-                __FILE__,
1897
-                __FUNCTION__,
1898
-                __LINE__
1899
-            );
1900
-        }
1901
-
1902
-        return $payment;
1903
-    }
1904
-
1905
-
1906
-    /**
1907
-     * _process_transaction_payments
1908
-     *
1909
-     * @param \EE_Transaction $transaction
1910
-     * @return void
1911
-     * @throws EE_Error
1912
-     * @throws InvalidArgumentException
1913
-     * @throws ReflectionException
1914
-     * @throws InvalidDataTypeException
1915
-     * @throws InvalidInterfaceException
1916
-     */
1917
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1918
-    {
1919
-        /** @type EE_Transaction_Payments $transaction_payments */
1920
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1921
-        // update the transaction with this payment
1922
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1923
-            EE_Error::add_success(
1924
-                esc_html__(
1925
-                    'The payment has been processed successfully.',
1926
-                    'event_espresso'
1927
-                ),
1928
-                __FILE__,
1929
-                __FUNCTION__,
1930
-                __LINE__
1931
-            );
1932
-        } else {
1933
-            EE_Error::add_error(
1934
-                esc_html__(
1935
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1936
-                    'event_espresso'
1937
-                ),
1938
-                __FILE__,
1939
-                __FUNCTION__,
1940
-                __LINE__
1941
-            );
1942
-        }
1943
-    }
1944
-
1945
-
1946
-    /**
1947
-     * _get_REG_IDs_to_apply_payment_to
1948
-     * returns a list of registration IDs that the payment will apply to
1949
-     *
1950
-     * @param \EE_Payment $payment
1951
-     * @return array
1952
-     * @throws EE_Error
1953
-     * @throws InvalidArgumentException
1954
-     * @throws InvalidDataTypeException
1955
-     * @throws InvalidInterfaceException
1956
-     * @throws ReflectionException
1957
-     */
1958
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1959
-    {
1960
-        $REG_IDs = array();
1961
-        // grab array of IDs for specific registrations to apply changes to
1962
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1963
-            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1964
-        }
1965
-        // nothing specified ? then get all reg IDs
1966
-        if (empty($REG_IDs)) {
1967
-            $registrations = $payment->transaction()->registrations();
1968
-            $REG_IDs = ! empty($registrations)
1969
-                ? array_keys($registrations)
1970
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1971
-        }
1972
-
1973
-        // ensure that REG_IDs are integers and NOT strings
1974
-        return array_map('intval', $REG_IDs);
1975
-    }
1976
-
1977
-
1978
-    /**
1979
-     * @return array
1980
-     */
1981
-    public function existing_reg_payment_REG_IDs()
1982
-    {
1983
-        return $this->_existing_reg_payment_REG_IDs;
1984
-    }
1985
-
1986
-
1987
-    /**
1988
-     * @param array $existing_reg_payment_REG_IDs
1989
-     */
1990
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1991
-    {
1992
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1993
-    }
1994
-
1995
-
1996
-    /**
1997
-     * _get_existing_reg_payment_REG_IDs
1998
-     * returns a list of registration IDs that the payment is currently related to
1999
-     * as recorded in the database
2000
-     *
2001
-     * @param \EE_Payment $payment
2002
-     * @return array
2003
-     * @throws EE_Error
2004
-     * @throws InvalidArgumentException
2005
-     * @throws InvalidDataTypeException
2006
-     * @throws InvalidInterfaceException
2007
-     * @throws ReflectionException
2008
-     */
2009
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2010
-    {
2011
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2012
-            // let's get any existing reg payment records for this payment
2013
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2014
-            // but we only want the REG IDs, so grab the array keys
2015
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2016
-                ? array_keys($existing_reg_payment_REG_IDs)
2017
-                : array();
2018
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2019
-        }
2020
-
2021
-        return $this->existing_reg_payment_REG_IDs();
2022
-    }
2023
-
2024
-
2025
-    /**
2026
-     * _remove_existing_registration_payments
2027
-     * this calculates the difference between existing relations
2028
-     * to the supplied payment and the new list registration IDs,
2029
-     * removes any related registrations that no longer apply,
2030
-     * and then updates the registration paid fields
2031
-     *
2032
-     * @param \EE_Payment $payment
2033
-     * @param int         $PAY_ID
2034
-     * @return bool;
2035
-     * @throws EE_Error
2036
-     * @throws InvalidArgumentException
2037
-     * @throws ReflectionException
2038
-     * @throws InvalidDataTypeException
2039
-     * @throws InvalidInterfaceException
2040
-     */
2041
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2042
-    {
2043
-        // newly created payments will have nothing recorded for $PAY_ID
2044
-        if (absint($PAY_ID) === 0) {
2045
-            return false;
2046
-        }
2047
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2048
-        if (empty($existing_reg_payment_REG_IDs)) {
2049
-            return false;
2050
-        }
2051
-        /** @type EE_Transaction_Payments $transaction_payments */
2052
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2053
-
2054
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2055
-            $payment,
2056
-            array(
2057
-                array(
2058
-                    'PAY_ID' => $payment->ID(),
2059
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2060
-                ),
2061
-            )
2062
-        );
2063
-    }
2064
-
2065
-
2066
-    /**
2067
-     * _update_registration_payments
2068
-     * this applies the payments to the selected registrations
2069
-     * but only if they have not already been paid for
2070
-     *
2071
-     * @param  EE_Transaction $transaction
2072
-     * @param \EE_Payment     $payment
2073
-     * @param array           $REG_IDs
2074
-     * @return void
2075
-     * @throws EE_Error
2076
-     * @throws InvalidArgumentException
2077
-     * @throws ReflectionException
2078
-     * @throws RuntimeException
2079
-     * @throws InvalidDataTypeException
2080
-     * @throws InvalidInterfaceException
2081
-     */
2082
-    protected function _update_registration_payments(
2083
-        EE_Transaction $transaction,
2084
-        EE_Payment $payment,
2085
-        $REG_IDs = array()
2086
-    ) {
2087
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2088
-        // so let's do that using our set of REG_IDs from the form
2089
-        $registration_query_where_params = array(
2090
-            'REG_ID' => array('IN', $REG_IDs),
2091
-        );
2092
-        // but add in some conditions regarding payment,
2093
-        // so that we don't apply payments to registrations that are free or have already been paid for
2094
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2095
-        if (! $payment->is_a_refund()) {
2096
-            $registration_query_where_params['REG_final_price'] = array('!=', 0);
2097
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2098
-        }
2099
-        $registrations = $transaction->registrations(array($registration_query_where_params));
2100
-        if (! empty($registrations)) {
2101
-            /** @type EE_Payment_Processor $payment_processor */
2102
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2103
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2104
-        }
2105
-    }
2106
-
2107
-
2108
-    /**
2109
-     * _process_registration_status_change
2110
-     * This processes requested registration status changes for all the registrations
2111
-     * on a given transaction and (optionally) sends out notifications for the changes.
2112
-     *
2113
-     * @param  EE_Transaction $transaction
2114
-     * @param array           $REG_IDs
2115
-     * @return bool
2116
-     * @throws EE_Error
2117
-     * @throws InvalidArgumentException
2118
-     * @throws ReflectionException
2119
-     * @throws InvalidDataTypeException
2120
-     * @throws InvalidInterfaceException
2121
-     */
2122
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2123
-    {
2124
-        // first if there is no change in status then we get out.
2125
-        if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2126
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2127
-        ) {
2128
-            // no error message, no change requested, just nothing to do man.
2129
-            return false;
2130
-        }
2131
-        /** @type EE_Transaction_Processor $transaction_processor */
2132
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2133
-
2134
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2135
-        return $transaction_processor->manually_update_registration_statuses(
2136
-            $transaction,
2137
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2138
-            array(array('REG_ID' => array('IN', $REG_IDs)))
2139
-        );
2140
-    }
2141
-
2142
-
2143
-    /**
2144
-     * _build_payment_json_response
2145
-     *
2146
-     * @access public
2147
-     * @param \EE_Payment $payment
2148
-     * @param array       $REG_IDs
2149
-     * @param bool | null $delete_txn_reg_status_change
2150
-     * @return array
2151
-     * @throws EE_Error
2152
-     * @throws InvalidArgumentException
2153
-     * @throws InvalidDataTypeException
2154
-     * @throws InvalidInterfaceException
2155
-     * @throws ReflectionException
2156
-     */
2157
-    protected function _build_payment_json_response(
2158
-        EE_Payment $payment,
2159
-        $REG_IDs = array(),
2160
-        $delete_txn_reg_status_change = null
2161
-    ) {
2162
-        // was the payment deleted ?
2163
-        if (is_bool($delete_txn_reg_status_change)) {
2164
-            return array(
2165
-                'PAY_ID'                       => $payment->ID(),
2166
-                'amount'                       => $payment->amount(),
2167
-                'total_paid'                   => $payment->transaction()->paid(),
2168
-                'txn_status'                   => $payment->transaction()->status_ID(),
2169
-                'pay_status'                   => $payment->STS_ID(),
2170
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2171
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2172
-            );
2173
-        } else {
2174
-            $this->_get_payment_status_array();
2175
-
2176
-            return array(
2177
-                'amount'           => $payment->amount(),
2178
-                'total_paid'       => $payment->transaction()->paid(),
2179
-                'txn_status'       => $payment->transaction()->status_ID(),
2180
-                'pay_status'       => $payment->STS_ID(),
2181
-                'PAY_ID'           => $payment->ID(),
2182
-                'STS_ID'           => $payment->STS_ID(),
2183
-                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2184
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2185
-                'method'           => strtoupper($payment->source()),
2186
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2187
-                'gateway'          => $payment->payment_method()
2188
-                    ? $payment->payment_method()->admin_name()
2189
-                    : esc_html__('Unknown', 'event_espresso'),
2190
-                'gateway_response' => $payment->gateway_response(),
2191
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2192
-                'po_number'        => $payment->po_number(),
2193
-                'extra_accntng'    => $payment->extra_accntng(),
2194
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2195
-            );
2196
-        }
2197
-    }
2198
-
2199
-
2200
-    /**
2201
-     * delete_payment
2202
-     *    delete a payment or refund made towards a transaction
2203
-     *
2204
-     * @access public
2205
-     * @return void
2206
-     * @throws EE_Error
2207
-     * @throws InvalidArgumentException
2208
-     * @throws ReflectionException
2209
-     * @throws InvalidDataTypeException
2210
-     * @throws InvalidInterfaceException
2211
-     */
2212
-    public function delete_payment()
2213
-    {
2214
-        $json_response_data = array('return_data' => false);
2215
-        $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2216
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2217
-            : 0;
2218
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2219
-            'ee_delete_payments',
2220
-            'delete_payment_from_registration_details'
2221
-        );
2222
-        if ($PAY_ID && $can_delete) {
2223
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2224
-                ? $this->_req_data['delete_txn_reg_status_change']
2225
-                : false;
2226
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2227
-            if ($payment instanceof EE_Payment) {
2228
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2229
-                /** @type EE_Transaction_Payments $transaction_payments */
2230
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2231
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2232
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2233
-                        $payment,
2234
-                        $REG_IDs,
2235
-                        $delete_txn_reg_status_change
2236
-                    );
2237
-                    if ($delete_txn_reg_status_change) {
2238
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2239
-                        // MAKE sure we also add the delete_txn_req_status_change to the
2240
-                        // $_REQUEST global because that's how messages will be looking for it.
2241
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2242
-                        $this->_maybe_send_notifications();
2243
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2244
-                    }
2245
-                }
2246
-            } else {
2247
-                EE_Error::add_error(
2248
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2249
-                    __FILE__,
2250
-                    __FUNCTION__,
2251
-                    __LINE__
2252
-                );
2253
-            }
2254
-        } elseif ($can_delete) {
2255
-            EE_Error::add_error(
2256
-                esc_html__(
2257
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2258
-                    'event_espresso'
2259
-                ),
2260
-                __FILE__,
2261
-                __FUNCTION__,
2262
-                __LINE__
2263
-            );
2264
-        } else {
2265
-            EE_Error::add_error(
2266
-                esc_html__(
2267
-                    'You do not have access to delete a payment.',
2268
-                    'event_espresso'
2269
-                ),
2270
-                __FILE__,
2271
-                __FUNCTION__,
2272
-                __LINE__
2273
-            );
2274
-        }
2275
-        $notices = EE_Error::get_notices(false, false, false);
2276
-        $this->_template_args = array(
2277
-            'data'      => $json_response_data,
2278
-            'success'   => $notices['success'],
2279
-            'error'     => $notices['errors'],
2280
-            'attention' => $notices['attention'],
2281
-        );
2282
-        $this->_return_json();
2283
-    }
2284
-
2285
-
2286
-    /**
2287
-     * _registration_payment_data_array
2288
-     * adds info for 'owing' and 'paid' for each registration to the json response
2289
-     *
2290
-     * @access protected
2291
-     * @param array $REG_IDs
2292
-     * @return array
2293
-     * @throws EE_Error
2294
-     * @throws InvalidArgumentException
2295
-     * @throws InvalidDataTypeException
2296
-     * @throws InvalidInterfaceException
2297
-     * @throws ReflectionException
2298
-     */
2299
-    protected function _registration_payment_data_array($REG_IDs)
2300
-    {
2301
-        $registration_payment_data = array();
2302
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2303
-        if (! empty($REG_IDs)) {
2304
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2305
-            foreach ($registrations as $registration) {
2306
-                if ($registration instanceof EE_Registration) {
2307
-                    $registration_payment_data[ $registration->ID() ] = array(
2308
-                        'paid'  => $registration->pretty_paid(),
2309
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2310
-                    );
2311
-                }
2312
-            }
2313
-        }
2314
-
2315
-        return $registration_payment_data;
2316
-    }
2317
-
2318
-
2319
-    /**
2320
-     * _maybe_send_notifications
2321
-     * determines whether or not the admin has indicated that notifications should be sent.
2322
-     * If so, will toggle a filter switch for delivering registration notices.
2323
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2324
-     *
2325
-     * @access protected
2326
-     * @param \EE_Payment | null $payment
2327
-     */
2328
-    protected function _maybe_send_notifications($payment = null)
2329
-    {
2330
-        switch ($payment instanceof EE_Payment) {
2331
-            // payment notifications
2332
-            case true:
2333
-                if (isset($this->_req_data['txn_payments']['send_notifications'])
2334
-                    && filter_var(
2335
-                        $this->_req_data['txn_payments']['send_notifications'],
2336
-                        FILTER_VALIDATE_BOOLEAN
2337
-                    )
2338
-                ) {
2339
-                    $this->_process_payment_notification($payment);
2340
-                }
2341
-                break;
2342
-            // registration notifications
2343
-            case false:
2344
-                if (isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2345
-                    && filter_var(
2346
-                        $this->_req_data['txn_reg_status_change']['send_notifications'],
2347
-                        FILTER_VALIDATE_BOOLEAN
2348
-                    )
2349
-                ) {
2350
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2351
-                }
2352
-                break;
2353
-        }
2354
-    }
2355
-
2356
-
2357
-    /**
2358
-     * _send_payment_reminder
2359
-     *    generates HTML for the View Transaction Details Admin page
2360
-     *
2361
-     * @access protected
2362
-     * @return void
2363
-     * @throws EE_Error
2364
-     * @throws InvalidArgumentException
2365
-     * @throws InvalidDataTypeException
2366
-     * @throws InvalidInterfaceException
2367
-     */
2368
-    protected function _send_payment_reminder()
2369
-    {
2370
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2371
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2372
-        $query_args = isset($this->_req_data['redirect_to']) ? array(
2373
-            'action' => $this->_req_data['redirect_to'],
2374
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2375
-        ) : array();
2376
-        do_action(
2377
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2378
-            $transaction
2379
-        );
2380
-        $this->_redirect_after_action(
2381
-            false,
2382
-            esc_html__('payment reminder', 'event_espresso'),
2383
-            esc_html__('sent', 'event_espresso'),
2384
-            $query_args,
2385
-            true
2386
-        );
2387
-    }
2388
-
2389
-
2390
-    /**
2391
-     *  get_transactions
2392
-     *    get transactions for given parameters (used by list table)
2393
-     *
2394
-     * @param  int     $perpage how many transactions displayed per page
2395
-     * @param  boolean $count   return the count or objects
2396
-     * @param string   $view
2397
-     * @return mixed int = count || array of transaction objects
2398
-     * @throws EE_Error
2399
-     * @throws InvalidArgumentException
2400
-     * @throws InvalidDataTypeException
2401
-     * @throws InvalidInterfaceException
2402
-     */
2403
-    public function get_transactions($perpage, $count = false, $view = '')
2404
-    {
2405
-
2406
-        $TXN = EEM_Transaction::instance();
2407
-
2408
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2409
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2410
-            : date(
2411
-                'm/d/Y',
2412
-                strtotime('-10 year')
2413
-            );
2414
-        $end_date = isset($this->_req_data['txn-filter-end-date'])
2415
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2416
-            : date('m/d/Y');
2417
-
2418
-        // make sure our timestamps start and end right at the boundaries for each day
2419
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2420
-        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2421
-
2422
-
2423
-        // convert to timestamps
2424
-        $start_date = strtotime($start_date);
2425
-        $end_date = strtotime($end_date);
2426
-
2427
-        // makes sure start date is the lowest value and vice versa
2428
-        $start_date = min($start_date, $end_date);
2429
-        $end_date = max($start_date, $end_date);
2430
-
2431
-        // convert to correct format for query
2432
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2433
-            'TXN_timestamp',
2434
-            date('Y-m-d H:i:s', $start_date),
2435
-            'Y-m-d H:i:s'
2436
-        );
2437
-        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2438
-            'TXN_timestamp',
2439
-            date('Y-m-d H:i:s', $end_date),
2440
-            'Y-m-d H:i:s'
2441
-        );
2442
-
2443
-
2444
-        // set orderby
2445
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2446
-
2447
-        switch ($this->_req_data['orderby']) {
2448
-            case 'TXN_ID':
2449
-                $orderby = 'TXN_ID';
2450
-                break;
2451
-            case 'ATT_fname':
2452
-                $orderby = 'Registration.Attendee.ATT_fname';
2453
-                break;
2454
-            case 'event_name':
2455
-                $orderby = 'Registration.Event.EVT_name';
2456
-                break;
2457
-            default: // 'TXN_timestamp'
2458
-                $orderby = 'TXN_timestamp';
2459
-        }
2460
-
2461
-        $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2462
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2463
-        $per_page = ! empty($perpage) ? $perpage : 10;
2464
-        $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2465
-
2466
-        $offset = ($current_page - 1) * $per_page;
2467
-        $limit = array($offset, $per_page);
2468
-
2469
-        $_where = array(
2470
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2471
-            'Registration.REG_count' => 1,
2472
-        );
2473
-
2474
-        if (isset($this->_req_data['EVT_ID'])) {
2475
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2476
-        }
2477
-
2478
-        if (isset($this->_req_data['s'])) {
2479
-            $search_string = '%' . $this->_req_data['s'] . '%';
2480
-            $_where['OR'] = array(
2481
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2482
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2483
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2484
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2485
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2486
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2487
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2488
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2489
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2490
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2491
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2492
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2493
-                'Registration.REG_code'               => array('LIKE', $search_string),
2494
-                'Registration.REG_count'              => array('LIKE', $search_string),
2495
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2496
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2497
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2498
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2499
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2500
-                'TXN_session_data'                    => array('LIKE', $search_string),
2501
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2502
-            );
2503
-        }
2504
-
2505
-        // failed transactions
2506
-        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2507
-                  || ($count && $view === 'failed');
2508
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2509
-                     || ($count && $view === 'abandoned');
2510
-        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2511
-                      || ($count && $view === 'incomplete');
2512
-
2513
-        if ($failed) {
2514
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2515
-        } elseif ($abandoned) {
2516
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2517
-        } elseif ($incomplete) {
2518
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2519
-        } else {
2520
-            $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2521
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2522
-        }
2523
-
2524
-        $query_params = apply_filters(
2525
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2526
-            array(
2527
-                $_where,
2528
-                'order_by'                 => array($orderby => $sort),
2529
-                'limit'                    => $limit,
2530
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2531
-            ),
2532
-            $this->_req_data,
2533
-            $view,
2534
-            $count
2535
-        );
2536
-
2537
-        $transactions = $count
2538
-            ? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2539
-            : $TXN->get_all($query_params);
2540
-
2541
-        return $transactions;
2542
-    }
2543
-
2544
-
2545
-    /**
2546
-     * @since 4.9.79.p
2547
-     * @throws EE_Error
2548
-     * @throws InvalidArgumentException
2549
-     * @throws InvalidDataTypeException
2550
-     * @throws InvalidInterfaceException
2551
-     * @throws ReflectionException
2552
-     * @throws RuntimeException
2553
-     */
2554
-    public function recalculateLineItems()
2555
-    {
2556
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2557
-        /** @var EE_Transaction $transaction */
2558
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2559
-        $total_line_item = $transaction->total_line_item(false);
2560
-        $success = $transaction->recalculateLineItems();
2561
-        $this->_redirect_after_action(
2562
-            (bool) $success,
2563
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2564
-            esc_html__('recalculated', 'event_espresso'),
2565
-            isset($this->_req_data['redirect_to'])
2566
-                ? array(
2567
-                'action' => $this->_req_data['redirect_to'],
2568
-                'TXN_ID' => $this->_req_data['TXN_ID'],
2569
-            )
2570
-                : array(),
2571
-            true
2572
-        );
2573
-    }
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug = TXN_PG_SLUG;
50
+		$this->page_label = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels = array(
78
+			'buttons' => array(
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			),
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 */
97
+	public function _set_page_routes()
98
+	{
99
+
100
+		$this->_set_transaction_status_array();
101
+
102
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
103
+				  && ! is_array($this->_req_data['TXN_ID'])
104
+			? $this->_req_data['TXN_ID']
105
+			: 0;
106
+
107
+		$this->_page_routes = array(
108
+
109
+			'default' => array(
110
+				'func'       => '_transactions_overview_list_table',
111
+				'capability' => 'ee_read_transactions',
112
+			),
113
+
114
+			'view_transaction' => array(
115
+				'func'       => '_transaction_details',
116
+				'capability' => 'ee_read_transaction',
117
+				'obj_id'     => $txn_id,
118
+			),
119
+
120
+			'send_payment_reminder' => array(
121
+				'func'       => '_send_payment_reminder',
122
+				'noheader'   => true,
123
+				'capability' => 'ee_send_message',
124
+			),
125
+
126
+			'espresso_apply_payment' => array(
127
+				'func'       => 'apply_payments_or_refunds',
128
+				'noheader'   => true,
129
+				'capability' => 'ee_edit_payments',
130
+			),
131
+
132
+			'espresso_apply_refund' => array(
133
+				'func'       => 'apply_payments_or_refunds',
134
+				'noheader'   => true,
135
+				'capability' => 'ee_edit_payments',
136
+			),
137
+
138
+			'espresso_delete_payment' => array(
139
+				'func'       => 'delete_payment',
140
+				'noheader'   => true,
141
+				'capability' => 'ee_delete_payments',
142
+			),
143
+
144
+			'espresso_recalculate_line_items' => array(
145
+				'func'       => 'recalculateLineItems',
146
+				'noheader'   => true,
147
+				'capability' => 'ee_edit_payments',
148
+			),
149
+
150
+		);
151
+	}
152
+
153
+
154
+	protected function _set_page_config()
155
+	{
156
+		$this->_page_config = array(
157
+			'default'          => array(
158
+				'nav'           => array(
159
+					'label' => esc_html__('Overview', 'event_espresso'),
160
+					'order' => 10,
161
+				),
162
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
163
+				'help_tabs'     => array(
164
+					'transactions_overview_help_tab'                       => array(
165
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
+						'filename' => 'transactions_overview',
167
+					),
168
+					'transactions_overview_table_column_headings_help_tab' => array(
169
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
+						'filename' => 'transactions_overview_table_column_headings',
171
+					),
172
+					'transactions_overview_views_filters_help_tab'         => array(
173
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
+						'filename' => 'transactions_overview_views_filters_search',
175
+					),
176
+				),
177
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
+				// 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
+				/**
180
+				 * commented out because currently we are not displaying tips for transaction list table status but this
181
+				 * may change in a later iteration so want to keep the code for then.
182
+				 */
183
+				// 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
+				'require_nonce' => false,
185
+			),
186
+			'view_transaction' => array(
187
+				'nav'       => array(
188
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
189
+					'order'      => 5,
190
+					'url'        => isset($this->_req_data['TXN_ID'])
191
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
+						: $this->_admin_base_url,
193
+					'persistent' => false,
194
+				),
195
+				'help_tabs' => array(
196
+					'transactions_view_transaction_help_tab'                                              => array(
197
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction',
199
+					),
200
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_transaction_details_table',
203
+					),
204
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
+						'filename' => 'transactions_view_transaction_attendees_registered',
207
+					),
208
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
+					),
212
+				),
213
+				'qtips'     => array('Transaction_Details_Tips'),
214
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
+				// 'help_tour' => array('Transaction_Details_Help_Tour'),
216
+				'metaboxes' => array('_transaction_details_metaboxes'),
217
+
218
+				'require_nonce' => false,
219
+			),
220
+		);
221
+	}
222
+
223
+
224
+	/**
225
+	 * The below methods aren't used by this class currently
226
+	 */
227
+	protected function _add_screen_options()
228
+	{
229
+		// noop
230
+	}
231
+
232
+
233
+	protected function _add_feature_pointers()
234
+	{
235
+		// noop
236
+	}
237
+
238
+
239
+	public function admin_init()
240
+	{
241
+		// IF a registration was JUST added via the admin...
242
+		if (isset(
243
+			$this->_req_data['redirect_from'],
244
+			$this->_req_data['EVT_ID'],
245
+			$this->_req_data['event_name']
246
+		)) {
247
+			// then set a cookie so that we can block any attempts to use
248
+			// the back button as a way to enter another registration.
249
+			setcookie(
250
+				'ee_registration_added',
251
+				$this->_req_data['EVT_ID'],
252
+				time() + WEEK_IN_SECONDS,
253
+				'/'
254
+			);
255
+			// and update the global
256
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
257
+		}
258
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
259
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
260
+			'event_espresso'
261
+		);
262
+		EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
263
+			'An error occurred! Please refresh the page and try again.',
264
+			'event_espresso'
265
+		);
266
+		EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
267
+		EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
268
+		EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
269
+		EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
270
+			'This transaction has been overpaid ! Payments Total',
271
+			'event_espresso'
272
+		);
273
+	}
274
+
275
+
276
+	public function admin_notices()
277
+	{
278
+		// noop
279
+	}
280
+
281
+
282
+	public function admin_footer_scripts()
283
+	{
284
+		// noop
285
+	}
286
+
287
+
288
+	/**
289
+	 * _set_transaction_status_array
290
+	 * sets list of transaction statuses
291
+	 *
292
+	 * @access private
293
+	 * @return void
294
+	 * @throws EE_Error
295
+	 * @throws InvalidArgumentException
296
+	 * @throws InvalidDataTypeException
297
+	 * @throws InvalidInterfaceException
298
+	 */
299
+	private function _set_transaction_status_array()
300
+	{
301
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
302
+	}
303
+
304
+
305
+	/**
306
+	 * get_transaction_status_array
307
+	 * return the transaction status array for wp_list_table
308
+	 *
309
+	 * @access public
310
+	 * @return array
311
+	 */
312
+	public function get_transaction_status_array()
313
+	{
314
+		return self::$_txn_status;
315
+	}
316
+
317
+
318
+	/**
319
+	 *    get list of payment statuses
320
+	 *
321
+	 * @access private
322
+	 * @return void
323
+	 * @throws EE_Error
324
+	 * @throws InvalidArgumentException
325
+	 * @throws InvalidDataTypeException
326
+	 * @throws InvalidInterfaceException
327
+	 */
328
+	private function _get_payment_status_array()
329
+	{
330
+		self::$_pay_status = EEM_Payment::instance()->status_array(true);
331
+		$this->_template_args['payment_status'] = self::$_pay_status;
332
+	}
333
+
334
+
335
+	/**
336
+	 *    _add_screen_options_default
337
+	 *
338
+	 * @access protected
339
+	 * @return void
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 */
344
+	protected function _add_screen_options_default()
345
+	{
346
+		$this->_per_page_screen_option();
347
+	}
348
+
349
+
350
+	/**
351
+	 * load_scripts_styles
352
+	 *
353
+	 * @access public
354
+	 * @return void
355
+	 */
356
+	public function load_scripts_styles()
357
+	{
358
+		// enqueue style
359
+		wp_register_style(
360
+			'espresso_txn',
361
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
362
+			array(),
363
+			EVENT_ESPRESSO_VERSION
364
+		);
365
+		wp_enqueue_style('espresso_txn');
366
+		// scripts
367
+		wp_register_script(
368
+			'espresso_txn',
369
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
370
+			array(
371
+				'ee_admin_js',
372
+				'ee-datepicker',
373
+				'jquery-ui-datepicker',
374
+				'jquery-ui-draggable',
375
+				'ee-dialog',
376
+				'ee-accounting',
377
+				'ee-serialize-full-array',
378
+			),
379
+			EVENT_ESPRESSO_VERSION,
380
+			true
381
+		);
382
+		wp_enqueue_script('espresso_txn');
383
+	}
384
+
385
+
386
+	/**
387
+	 *    load_scripts_styles_view_transaction
388
+	 *
389
+	 * @access public
390
+	 * @return void
391
+	 */
392
+	public function load_scripts_styles_view_transaction()
393
+	{
394
+		// styles
395
+		wp_enqueue_style('espresso-ui-theme');
396
+	}
397
+
398
+
399
+	/**
400
+	 *    load_scripts_styles_default
401
+	 *
402
+	 * @access public
403
+	 * @return void
404
+	 */
405
+	public function load_scripts_styles_default()
406
+	{
407
+		// styles
408
+		wp_enqueue_style('espresso-ui-theme');
409
+	}
410
+
411
+
412
+	/**
413
+	 *    _set_list_table_views_default
414
+	 *
415
+	 * @access protected
416
+	 * @return void
417
+	 */
418
+	protected function _set_list_table_views_default()
419
+	{
420
+		$this->_views = array(
421
+			'all'        => array(
422
+				'slug'  => 'all',
423
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
424
+				'count' => 0,
425
+			),
426
+			'abandoned'  => array(
427
+				'slug'  => 'abandoned',
428
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
+				'count' => 0,
430
+			),
431
+			'incomplete' => array(
432
+				'slug'  => 'incomplete',
433
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
434
+				'count' => 0,
435
+			),
436
+		);
437
+		if (/**
438
+		 * Filters whether a link to the "Failed Transactions" list table
439
+		 * appears on the Transactions Admin Page list table.
440
+		 * List display can be turned back on via the following:
441
+		 * add_filter(
442
+		 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
443
+		 *     '__return_true'
444
+		 * );
445
+		 *
446
+		 * @since 4.9.70.p
447
+		 * @param boolean                 $display_failed_txns_list
448
+		 * @param Transactions_Admin_Page $this
449
+		 */
450
+		apply_filters(
451
+			'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
452
+			false,
453
+			$this
454
+		)
455
+		) {
456
+			$this->_views['failed'] = array(
457
+				'slug'  => 'failed',
458
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
459
+				'count' => 0,
460
+			);
461
+		}
462
+	}
463
+
464
+
465
+	/**
466
+	 * _set_transaction_object
467
+	 * This sets the _transaction property for the transaction details screen
468
+	 *
469
+	 * @access private
470
+	 * @return void
471
+	 * @throws EE_Error
472
+	 * @throws InvalidArgumentException
473
+	 * @throws RuntimeException
474
+	 * @throws InvalidDataTypeException
475
+	 * @throws InvalidInterfaceException
476
+	 * @throws ReflectionException
477
+	 */
478
+	private function _set_transaction_object()
479
+	{
480
+		if ($this->_transaction instanceof EE_Transaction) {
481
+			return;
482
+		} //get out we've already set the object
483
+
484
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
485
+			? absint($this->_req_data['TXN_ID'])
486
+			: false;
487
+
488
+		// get transaction object
489
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
490
+		$this->_session = $this->_transaction instanceof EE_Transaction
491
+			? $this->_transaction->session_data()
492
+			: null;
493
+		if ($this->_transaction instanceof EE_Transaction) {
494
+			$this->_transaction->verify_abandoned_transaction_status();
495
+		}
496
+
497
+		if (! $this->_transaction instanceof EE_Transaction) {
498
+			$error_msg = sprintf(
499
+				esc_html__(
500
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
501
+					'event_espresso'
502
+				),
503
+				$TXN_ID
504
+			);
505
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
506
+		}
507
+	}
508
+
509
+
510
+	/**
511
+	 *    _transaction_legend_items
512
+	 *
513
+	 * @access protected
514
+	 * @return array
515
+	 * @throws EE_Error
516
+	 * @throws InvalidArgumentException
517
+	 * @throws ReflectionException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 */
521
+	protected function _transaction_legend_items()
522
+	{
523
+		EE_Registry::instance()->load_helper('MSG_Template');
524
+		$items = array();
525
+
526
+		if (EE_Registry::instance()->CAP->current_user_can(
527
+			'ee_read_global_messages',
528
+			'view_filtered_messages'
529
+		)) {
530
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
531
+			if (is_array($related_for_icon)
532
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
533
+			) {
534
+				$items['view_related_messages'] = array(
535
+					'class' => $related_for_icon['css_class'],
536
+					'desc'  => $related_for_icon['label'],
537
+				);
538
+			}
539
+		}
540
+
541
+		$items = apply_filters(
542
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
543
+			array_merge(
544
+				$items,
545
+				array(
546
+					'view_details'          => array(
547
+						'class' => 'dashicons dashicons-cart',
548
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
549
+					),
550
+					'view_invoice'          => array(
551
+						'class' => 'dashicons dashicons-media-spreadsheet',
552
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
553
+					),
554
+					'view_receipt'          => array(
555
+						'class' => 'dashicons dashicons-media-default',
556
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
557
+					),
558
+					'view_registration'     => array(
559
+						'class' => 'dashicons dashicons-clipboard',
560
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
561
+					),
562
+					'payment_overview_link' => array(
563
+						'class' => 'dashicons dashicons-money',
564
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
565
+					),
566
+				)
567
+			)
568
+		);
569
+
570
+		if (EEH_MSG_Template::is_mt_active('payment_reminder')
571
+			&& EE_Registry::instance()->CAP->current_user_can(
572
+				'ee_send_message',
573
+				'espresso_transactions_send_payment_reminder'
574
+			)
575
+		) {
576
+			$items['send_payment_reminder'] = array(
577
+				'class' => 'dashicons dashicons-email-alt',
578
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
579
+			);
580
+		} else {
581
+			$items['blank*'] = array(
582
+				'class' => '',
583
+				'desc'  => '',
584
+			);
585
+		}
586
+		$more_items = apply_filters(
587
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
588
+			array(
589
+				'overpaid'   => array(
590
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
591
+					'desc'  => EEH_Template::pretty_status(
592
+						EEM_Transaction::overpaid_status_code,
593
+						false,
594
+						'sentence'
595
+					),
596
+				),
597
+				'complete'   => array(
598
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
599
+					'desc'  => EEH_Template::pretty_status(
600
+						EEM_Transaction::complete_status_code,
601
+						false,
602
+						'sentence'
603
+					),
604
+				),
605
+				'incomplete' => array(
606
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
607
+					'desc'  => EEH_Template::pretty_status(
608
+						EEM_Transaction::incomplete_status_code,
609
+						false,
610
+						'sentence'
611
+					),
612
+				),
613
+				'abandoned'  => array(
614
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
615
+					'desc'  => EEH_Template::pretty_status(
616
+						EEM_Transaction::abandoned_status_code,
617
+						false,
618
+						'sentence'
619
+					),
620
+				),
621
+				'failed'     => array(
622
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
623
+					'desc'  => EEH_Template::pretty_status(
624
+						EEM_Transaction::failed_status_code,
625
+						false,
626
+						'sentence'
627
+					),
628
+				),
629
+			)
630
+		);
631
+
632
+		return array_merge($items, $more_items);
633
+	}
634
+
635
+
636
+	/**
637
+	 *    _transactions_overview_list_table
638
+	 *
639
+	 * @access protected
640
+	 * @return void
641
+	 * @throws DomainException
642
+	 * @throws EE_Error
643
+	 * @throws InvalidArgumentException
644
+	 * @throws InvalidDataTypeException
645
+	 * @throws InvalidInterfaceException
646
+	 * @throws ReflectionException
647
+	 */
648
+	protected function _transactions_overview_list_table()
649
+	{
650
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
651
+		$event = isset($this->_req_data['EVT_ID'])
652
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
653
+			: null;
654
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
655
+			? sprintf(
656
+				esc_html__(
657
+					'%sViewing Transactions for the Event: %s%s',
658
+					'event_espresso'
659
+				),
660
+				'<h3>',
661
+				'<a href="'
662
+				. EE_Admin_Page::add_query_args_and_nonce(
663
+					array('action' => 'edit', 'post' => $event->ID()),
664
+					EVENTS_ADMIN_URL
665
+				)
666
+				. '" title="'
667
+				. esc_attr__(
668
+					'Click to Edit event',
669
+					'event_espresso'
670
+				)
671
+				. '">' . $event->name() . '</a>',
672
+				'</h3>'
673
+			)
674
+			: '';
675
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
676
+		$this->display_admin_list_table_page_with_no_sidebar();
677
+	}
678
+
679
+
680
+	/**
681
+	 *    _transaction_details
682
+	 * generates HTML for the View Transaction Details Admin page
683
+	 *
684
+	 * @access protected
685
+	 * @return void
686
+	 * @throws DomainException
687
+	 * @throws EE_Error
688
+	 * @throws InvalidArgumentException
689
+	 * @throws InvalidDataTypeException
690
+	 * @throws InvalidInterfaceException
691
+	 * @throws RuntimeException
692
+	 * @throws ReflectionException
693
+	 */
694
+	protected function _transaction_details()
695
+	{
696
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
697
+
698
+		$this->_set_transaction_status_array();
699
+
700
+		$this->_template_args = array();
701
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
702
+
703
+		$this->_set_transaction_object();
704
+
705
+		if (! $this->_transaction instanceof EE_Transaction) {
706
+			return;
707
+		}
708
+		$primary_registration = $this->_transaction->primary_registration();
709
+		$attendee = $primary_registration instanceof EE_Registration
710
+			? $primary_registration->attendee()
711
+			: null;
712
+
713
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
714
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
715
+
716
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
717
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
718
+
719
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
720
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
721
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
722
+
723
+		$this->_template_args['grand_total'] = $this->_transaction->total();
724
+		$this->_template_args['total_paid'] = $this->_transaction->paid();
725
+
726
+		$amount_due = $this->_transaction->total() - $this->_transaction->paid();
727
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
728
+			$amount_due,
729
+			true
730
+		);
731
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
732
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
733
+												  . $this->_template_args['amount_due'];
734
+		} else {
735
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
736
+		}
737
+		$this->_template_args['amount_due_class'] = '';
738
+
739
+		if ($this->_transaction->paid() === $this->_transaction->total()) {
740
+			// paid in full
741
+			$this->_template_args['amount_due'] = false;
742
+		} elseif ($this->_transaction->paid() > $this->_transaction->total()) {
743
+			// overpaid
744
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
745
+		} elseif ($this->_transaction->total() > (float) 0) {
746
+			if ($this->_transaction->paid() > (float) 0) {
747
+				// monies owing
748
+				$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
749
+			} elseif ($this->_transaction->paid() === (float) 0) {
750
+				// no payments made yet
751
+				$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
752
+			}
753
+		} elseif ($this->_transaction->total() === (float) 0) {
754
+			// free event
755
+			$this->_template_args['amount_due'] = false;
756
+		}
757
+
758
+		$payment_method = $this->_transaction->payment_method();
759
+
760
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
761
+			? $payment_method->admin_name()
762
+			: esc_html__('Unknown', 'event_espresso');
763
+
764
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
765
+		// link back to overview
766
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
767
+			? $_SERVER['HTTP_REFERER']
768
+			: TXN_ADMIN_URL;
769
+
770
+
771
+		// next link
772
+		$next_txn = $this->_transaction->next(
773
+			null,
774
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
775
+			'TXN_ID'
776
+		);
777
+		$this->_template_args['next_transaction'] = $next_txn
778
+			? $this->_next_link(
779
+				EE_Admin_Page::add_query_args_and_nonce(
780
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
781
+					TXN_ADMIN_URL
782
+				),
783
+				'dashicons dashicons-arrow-right ee-icon-size-22'
784
+			)
785
+			: '';
786
+		// previous link
787
+		$previous_txn = $this->_transaction->previous(
788
+			null,
789
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
790
+			'TXN_ID'
791
+		);
792
+		$this->_template_args['previous_transaction'] = $previous_txn
793
+			? $this->_previous_link(
794
+				EE_Admin_Page::add_query_args_and_nonce(
795
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
796
+					TXN_ADMIN_URL
797
+				),
798
+				'dashicons dashicons-arrow-left ee-icon-size-22'
799
+			)
800
+			: '';
801
+
802
+		// were we just redirected here after adding a new registration ???
803
+		if (isset(
804
+			$this->_req_data['redirect_from'],
805
+			$this->_req_data['EVT_ID'],
806
+			$this->_req_data['event_name']
807
+		)) {
808
+			if (EE_Registry::instance()->CAP->current_user_can(
809
+				'ee_edit_registrations',
810
+				'espresso_registrations_new_registration',
811
+				$this->_req_data['EVT_ID']
812
+			)) {
813
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
814
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
815
+					array(
816
+						'page'     => 'espresso_registrations',
817
+						'action'   => 'new_registration',
818
+						'return'   => 'default',
819
+						'TXN_ID'   => $this->_transaction->ID(),
820
+						'event_id' => $this->_req_data['EVT_ID'],
821
+					),
822
+					REG_ADMIN_URL
823
+				);
824
+				$this->_admin_page_title .= '">';
825
+
826
+				$this->_admin_page_title .= sprintf(
827
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
828
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
829
+				);
830
+				$this->_admin_page_title .= '</a>';
831
+			}
832
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
833
+		}
834
+		// grab messages at the last second
835
+		$this->_template_args['notices'] = EE_Error::get_notices();
836
+		// path to template
837
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
838
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
839
+			$template_path,
840
+			$this->_template_args,
841
+			true
842
+		);
843
+
844
+		// the details template wrapper
845
+		$this->display_admin_page_with_sidebar();
846
+	}
847
+
848
+
849
+	/**
850
+	 *        _transaction_details_metaboxes
851
+	 *
852
+	 * @access protected
853
+	 * @return void
854
+	 * @throws EE_Error
855
+	 * @throws InvalidArgumentException
856
+	 * @throws InvalidDataTypeException
857
+	 * @throws InvalidInterfaceException
858
+	 * @throws RuntimeException
859
+	 * @throws ReflectionException
860
+	 */
861
+	protected function _transaction_details_metaboxes()
862
+	{
863
+
864
+		$this->_set_transaction_object();
865
+
866
+		if (! $this->_transaction instanceof EE_Transaction) {
867
+			return;
868
+		}
869
+		add_meta_box(
870
+			'edit-txn-details-mbox',
871
+			esc_html__('Transaction Details', 'event_espresso'),
872
+			array($this, 'txn_details_meta_box'),
873
+			$this->_wp_page_slug,
874
+			'normal',
875
+			'high'
876
+		);
877
+		add_meta_box(
878
+			'edit-txn-attendees-mbox',
879
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
+			array($this, 'txn_attendees_meta_box'),
881
+			$this->_wp_page_slug,
882
+			'normal',
883
+			'high',
884
+			array('TXN_ID' => $this->_transaction->ID())
885
+		);
886
+		add_meta_box(
887
+			'edit-txn-registrant-mbox',
888
+			esc_html__('Primary Contact', 'event_espresso'),
889
+			array($this, 'txn_registrant_side_meta_box'),
890
+			$this->_wp_page_slug,
891
+			'side',
892
+			'high'
893
+		);
894
+		add_meta_box(
895
+			'edit-txn-billing-info-mbox',
896
+			esc_html__('Billing Information', 'event_espresso'),
897
+			array($this, 'txn_billing_info_side_meta_box'),
898
+			$this->_wp_page_slug,
899
+			'side',
900
+			'high'
901
+		);
902
+	}
903
+
904
+
905
+	/**
906
+	 * Callback for transaction actions metabox.
907
+	 *
908
+	 * @param EE_Transaction|null $transaction
909
+	 * @return string
910
+	 * @throws DomainException
911
+	 * @throws EE_Error
912
+	 * @throws InvalidArgumentException
913
+	 * @throws InvalidDataTypeException
914
+	 * @throws InvalidInterfaceException
915
+	 * @throws ReflectionException
916
+	 * @throws RuntimeException
917
+	 */
918
+	public function getActionButtons(EE_Transaction $transaction = null)
919
+	{
920
+		$content = '';
921
+		$actions = array();
922
+		if (! $transaction instanceof EE_Transaction) {
923
+			return $content;
924
+		}
925
+		/** @var EE_Registration $primary_registration */
926
+		$primary_registration = $transaction->primary_registration();
927
+		$attendee = $primary_registration instanceof EE_Registration
928
+			? $primary_registration->attendee()
929
+			: null;
930
+
931
+		if ($attendee instanceof EE_Attendee
932
+			&& EE_Registry::instance()->CAP->current_user_can(
933
+				'ee_send_message',
934
+				'espresso_transactions_send_payment_reminder'
935
+			)
936
+		) {
937
+			$actions['payment_reminder'] =
938
+				EEH_MSG_Template::is_mt_active('payment_reminder')
939
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
940
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
941
+					? EEH_Template::get_button_or_link(
942
+						EE_Admin_Page::add_query_args_and_nonce(
943
+							array(
944
+								'action'      => 'send_payment_reminder',
945
+								'TXN_ID'      => $this->_transaction->ID(),
946
+								'redirect_to' => 'view_transaction',
947
+							),
948
+							TXN_ADMIN_URL
949
+						),
950
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
951
+						'button secondary-button',
952
+						'dashicons dashicons-email-alt'
953
+					)
954
+					: '';
955
+		}
956
+
957
+		if (EE_Registry::instance()->CAP->current_user_can(
958
+			'ee_edit_payments',
959
+			'espresso_transactions_recalculate_line_items'
960
+		)
961
+		) {
962
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
963
+				EE_Admin_Page::add_query_args_and_nonce(
964
+					array(
965
+						'action'      => 'espresso_recalculate_line_items',
966
+						'TXN_ID'      => $this->_transaction->ID(),
967
+						'redirect_to' => 'view_transaction',
968
+					),
969
+					TXN_ADMIN_URL
970
+				),
971
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
972
+				'button secondary-button',
973
+				'dashicons dashicons-update'
974
+			);
975
+		}
976
+
977
+		if ($primary_registration instanceof EE_Registration
978
+			&& EEH_MSG_Template::is_mt_active('receipt')
979
+		) {
980
+			$actions['receipt'] = EEH_Template::get_button_or_link(
981
+				$primary_registration->receipt_url(),
982
+				esc_html__('View Receipt', 'event_espresso'),
983
+				'button secondary-button',
984
+				'dashicons dashicons-media-default'
985
+			);
986
+		}
987
+
988
+		if ($primary_registration instanceof EE_Registration
989
+			&& EEH_MSG_Template::is_mt_active('invoice')
990
+		) {
991
+			$actions['invoice'] = EEH_Template::get_button_or_link(
992
+				$primary_registration->invoice_url(),
993
+				esc_html__('View Invoice', 'event_espresso'),
994
+				'button secondary-button',
995
+				'dashicons dashicons-media-spreadsheet'
996
+			);
997
+		}
998
+		$actions = array_filter(
999
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1000
+		);
1001
+		if ($actions) {
1002
+			$content = '<ul>';
1003
+			$content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1004
+			$content .= '</uL>';
1005
+		}
1006
+		return $content;
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * txn_details_meta_box
1012
+	 * generates HTML for the Transaction main meta box
1013
+	 *
1014
+	 * @return void
1015
+	 * @throws DomainException
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 * @throws RuntimeException
1021
+	 * @throws ReflectionException
1022
+	 */
1023
+	public function txn_details_meta_box()
1024
+	{
1025
+		$this->_set_transaction_object();
1026
+		$this->_template_args['TXN_ID'] = $this->_transaction->ID();
1027
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1028
+			? $this->_transaction->primary_registration()->attendee()
1029
+			: null;
1030
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1031
+			'ee_edit_payments',
1032
+			'apply_payment_or_refund_from_registration_details'
1033
+		);
1034
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1035
+			'ee_delete_payments',
1036
+			'delete_payment_from_registration_details'
1037
+		);
1038
+
1039
+		// get line table
1040
+		EEH_Autoloader::register_line_item_display_autoloaders();
1041
+		$Line_Item_Display = new EE_Line_Item_Display(
1042
+			'admin_table',
1043
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1044
+		);
1045
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1046
+			$this->_transaction->total_line_item()
1047
+		);
1048
+		$this->_template_args['REG_code'] = $this->_transaction->primary_registration() instanceof EE_Registration
1049
+			? $this->_transaction->primary_registration()->reg_code()
1050
+			: null;
1051
+		// process taxes
1052
+		$taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1053
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1054
+
1055
+		$this->_template_args['grand_total'] = EEH_Template::format_currency(
1056
+			$this->_transaction->total(),
1057
+			false,
1058
+			false
1059
+		);
1060
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1061
+		$this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1062
+
1063
+		// process payment details
1064
+		$payments = $this->_transaction->payments();
1065
+		if (! empty($payments)) {
1066
+			$this->_template_args['payments'] = $payments;
1067
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1068
+		} else {
1069
+			$this->_template_args['payments'] = false;
1070
+			$this->_template_args['existing_reg_payments'] = array();
1071
+		}
1072
+
1073
+		$this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1074
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1075
+			array('action' => 'espresso_delete_payment'),
1076
+			TXN_ADMIN_URL
1077
+		);
1078
+
1079
+		if (isset($txn_details['invoice_number'])) {
1080
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1081
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1082
+				'Invoice Number',
1083
+				'event_espresso'
1084
+			);
1085
+		}
1086
+
1087
+		$this->_template_args['txn_details']['registration_session']['value']
1088
+			= $this->_transaction->primary_registration() instanceof EE_Registration
1089
+			? $this->_transaction->primary_registration()->session_ID()
1090
+			: null;
1091
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1092
+			'Registration Session',
1093
+			'event_espresso'
1094
+		);
1095
+
1096
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1097
+			? $this->_session['ip_address']
1098
+			: '';
1099
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1100
+			'Transaction placed from IP',
1101
+			'event_espresso'
1102
+		);
1103
+
1104
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1105
+			? $this->_session['user_agent']
1106
+			: '';
1107
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1108
+			'Registrant User Agent',
1109
+			'event_espresso'
1110
+		);
1111
+
1112
+		$reg_steps = '<ul>';
1113
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1114
+			if ($reg_step_status === true) {
1115
+				$reg_steps .= '<li style="color:#70cc50">'
1116
+							  . sprintf(
1117
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1118
+								  ucwords(str_replace('_', ' ', $reg_step))
1119
+							  )
1120
+							  . '</li>';
1121
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1122
+				$reg_steps .= '<li style="color:#2EA2CC">'
1123
+							  . sprintf(
1124
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1125
+								  ucwords(str_replace('_', ' ', $reg_step)),
1126
+								  date(
1127
+									  get_option('date_format') . ' ' . get_option('time_format'),
1128
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1129
+								  )
1130
+							  )
1131
+							  . '</li>';
1132
+			} else {
1133
+				$reg_steps .= '<li style="color:#E76700">'
1134
+							  . sprintf(
1135
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1136
+								  ucwords(str_replace('_', ' ', $reg_step))
1137
+							  )
1138
+							  . '</li>';
1139
+			}
1140
+		}
1141
+		$reg_steps .= '</ul>';
1142
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1143
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1144
+			'Registration Step Progress',
1145
+			'event_espresso'
1146
+		);
1147
+
1148
+
1149
+		$this->_get_registrations_to_apply_payment_to();
1150
+		$this->_get_payment_methods($payments);
1151
+		$this->_get_payment_status_array();
1152
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1153
+
1154
+		$this->_template_args['transaction_form_url'] = add_query_arg(
1155
+			array(
1156
+				'action'  => 'edit_transaction',
1157
+				'process' => 'transaction',
1158
+			),
1159
+			TXN_ADMIN_URL
1160
+		);
1161
+		$this->_template_args['apply_payment_form_url'] = add_query_arg(
1162
+			array(
1163
+				'page'   => 'espresso_transactions',
1164
+				'action' => 'espresso_apply_payment',
1165
+			),
1166
+			WP_AJAX_URL
1167
+		);
1168
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1169
+			array(
1170
+				'page'   => 'espresso_transactions',
1171
+				'action' => 'espresso_delete_payment',
1172
+			),
1173
+			WP_AJAX_URL
1174
+		);
1175
+
1176
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1177
+
1178
+		// 'espresso_delete_payment_nonce'
1179
+
1180
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1181
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1182
+	}
1183
+
1184
+
1185
+	/**
1186
+	 * _get_registration_payment_IDs
1187
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1188
+	 *
1189
+	 * @access protected
1190
+	 * @param EE_Payment[] $payments
1191
+	 * @return array
1192
+	 * @throws EE_Error
1193
+	 * @throws InvalidArgumentException
1194
+	 * @throws InvalidDataTypeException
1195
+	 * @throws InvalidInterfaceException
1196
+	 * @throws ReflectionException
1197
+	 */
1198
+	protected function _get_registration_payment_IDs($payments = array())
1199
+	{
1200
+		$existing_reg_payments = array();
1201
+		// get all reg payments for these payments
1202
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1203
+			array(
1204
+				array(
1205
+					'PAY_ID' => array(
1206
+						'IN',
1207
+						array_keys($payments),
1208
+					),
1209
+				),
1210
+			)
1211
+		);
1212
+		if (! empty($reg_payments)) {
1213
+			foreach ($payments as $payment) {
1214
+				if (! $payment instanceof EE_Payment) {
1215
+					continue;
1216
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1217
+					$existing_reg_payments[ $payment->ID() ] = array();
1218
+				}
1219
+				foreach ($reg_payments as $reg_payment) {
1220
+					if ($reg_payment instanceof EE_Registration_Payment
1221
+						&& $reg_payment->payment_ID() === $payment->ID()
1222
+					) {
1223
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1224
+					}
1225
+				}
1226
+			}
1227
+		}
1228
+
1229
+		return $existing_reg_payments;
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * _get_registrations_to_apply_payment_to
1235
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1236
+	 * which allows the admin to only apply the payment to the specific registrations
1237
+	 *
1238
+	 * @access protected
1239
+	 * @return void
1240
+	 * @throws EE_Error
1241
+	 * @throws InvalidArgumentException
1242
+	 * @throws InvalidDataTypeException
1243
+	 * @throws InvalidInterfaceException
1244
+	 * @throws ReflectionException
1245
+	 */
1246
+	protected function _get_registrations_to_apply_payment_to()
1247
+	{
1248
+		// we want any registration with an active status (ie: not deleted or cancelled)
1249
+		$query_params = array(
1250
+			array(
1251
+				'STS_ID' => array(
1252
+					'IN',
1253
+					array(
1254
+						EEM_Registration::status_id_approved,
1255
+						EEM_Registration::status_id_pending_payment,
1256
+						EEM_Registration::status_id_not_approved,
1257
+					),
1258
+				),
1259
+			),
1260
+		);
1261
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1262
+			'',
1263
+			'txn-admin-apply-payment-to-registrations-dv',
1264
+			'',
1265
+			'clear: both; margin: 1.5em 0 0; display: none;'
1266
+		);
1267
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1268
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1269
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1270
+			EEH_HTML::tr(
1271
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1272
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1273
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1274
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1275
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1276
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1277
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1278
+			)
1279
+		);
1280
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1281
+		// get registrations for TXN
1282
+		$registrations = $this->_transaction->registrations($query_params);
1283
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1284
+		foreach ($registrations as $registration) {
1285
+			if ($registration instanceof EE_Registration) {
1286
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
1287
+					? $registration->attendee()->full_name()
1288
+					: esc_html__('Unknown Attendee', 'event_espresso');
1289
+				$owing = $registration->final_price() - $registration->paid();
1290
+				$taxable = $registration->ticket()->taxable()
1291
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1292
+					: '';
1293
+				$checked = empty($existing_reg_payments)
1294
+						   || in_array($registration->ID(), $existing_reg_payments, true)
1295
+					? ' checked="checked"'
1296
+					: '';
1297
+				$disabled = $registration->final_price() > 0 ? '' : ' disabled';
1298
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1299
+					EEH_HTML::td($registration->ID()) .
1300
+					EEH_HTML::td($attendee_name) .
1301
+					EEH_HTML::td(
1302
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1303
+					) .
1304
+					EEH_HTML::td($registration->event_name()) .
1305
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1306
+					EEH_HTML::td(
1307
+						EEH_Template::format_currency($owing),
1308
+						'',
1309
+						'txn-admin-payment-owing-td jst-cntr'
1310
+					) .
1311
+					EEH_HTML::td(
1312
+						'<input type="checkbox" value="' . $registration->ID()
1313
+						. '" name="txn_admin_payment[registrations]"'
1314
+						. $checked . $disabled . '>',
1315
+						'',
1316
+						'jst-cntr'
1317
+					),
1318
+					'apply-payment-registration-row-' . $registration->ID()
1319
+				);
1320
+			}
1321
+		}
1322
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1323
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1324
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1325
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1326
+			esc_html__(
1327
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1328
+				'event_espresso'
1329
+			),
1330
+			'',
1331
+			'clear description'
1332
+		);
1333
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1334
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * _get_reg_status_selection
1340
+	 *
1341
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1342
+	 *         instead of events.
1343
+	 * @access protected
1344
+	 * @return void
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	protected function _get_reg_status_selection()
1348
+	{
1349
+		// first get all possible statuses
1350
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1351
+		// let's add a "don't change" option.
1352
+		$status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1353
+		$status_array = array_merge($status_array, $statuses);
1354
+		$this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1355
+			'txn_reg_status_change[reg_status]',
1356
+			$status_array,
1357
+			'NAN',
1358
+			'id="txn-admin-payment-reg-status-inp"',
1359
+			'txn-reg-status-change-reg-status'
1360
+		);
1361
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1362
+			'delete_txn_reg_status_change[reg_status]',
1363
+			$status_array,
1364
+			'NAN',
1365
+			'delete-txn-admin-payment-reg-status-inp',
1366
+			'delete-txn-reg-status-change-reg-status'
1367
+		);
1368
+	}
1369
+
1370
+
1371
+	/**
1372
+	 *    _get_payment_methods
1373
+	 * Gets all the payment methods available generally, or the ones that are already
1374
+	 * selected on these payments (in case their payment methods are no longer active).
1375
+	 * Has the side-effect of updating the template args' payment_methods item
1376
+	 *
1377
+	 * @access private
1378
+	 * @param EE_Payment[] to show on this page
1379
+	 * @return void
1380
+	 * @throws EE_Error
1381
+	 * @throws InvalidArgumentException
1382
+	 * @throws InvalidDataTypeException
1383
+	 * @throws InvalidInterfaceException
1384
+	 * @throws ReflectionException
1385
+	 */
1386
+	private function _get_payment_methods($payments = array())
1387
+	{
1388
+		$payment_methods_of_payments = array();
1389
+		foreach ($payments as $payment) {
1390
+			if ($payment instanceof EE_Payment) {
1391
+				$payment_methods_of_payments[] = $payment->ID();
1392
+			}
1393
+		}
1394
+		if ($payment_methods_of_payments) {
1395
+			$query_args = array(
1396
+				array(
1397
+					'OR*payment_method_for_payment' => array(
1398
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1399
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1400
+					),
1401
+				),
1402
+			);
1403
+		} else {
1404
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1405
+		}
1406
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * txn_attendees_meta_box
1412
+	 *    generates HTML for the Attendees Transaction main meta box
1413
+	 *
1414
+	 * @access public
1415
+	 * @param WP_Post $post
1416
+	 * @param array   $metabox
1417
+	 * @return void
1418
+	 * @throws DomainException
1419
+	 * @throws EE_Error
1420
+	 * @throws InvalidArgumentException
1421
+	 * @throws InvalidDataTypeException
1422
+	 * @throws InvalidInterfaceException
1423
+	 * @throws ReflectionException
1424
+	 */
1425
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1426
+	{
1427
+
1428
+		/** @noinspection NonSecureExtractUsageInspection */
1429
+		extract($metabox['args']);
1430
+		$this->_template_args['post'] = $post;
1431
+		$this->_template_args['event_attendees'] = array();
1432
+		// process items in cart
1433
+		$line_items = $this->_transaction->get_many_related(
1434
+			'Line_Item',
1435
+			array(array('LIN_type' => 'line-item'))
1436
+		);
1437
+		if (! empty($line_items)) {
1438
+			foreach ($line_items as $item) {
1439
+				if ($item instanceof EE_Line_Item) {
1440
+					switch ($item->OBJ_type()) {
1441
+						case 'Event':
1442
+							break;
1443
+						case 'Ticket':
1444
+							$ticket = $item->ticket();
1445
+							// right now we're only handling tickets here.
1446
+							// Cause its expected that only tickets will have attendees right?
1447
+							if (! $ticket instanceof EE_Ticket) {
1448
+								break;
1449
+							}
1450
+							try {
1451
+								$event_name = $ticket->get_event_name();
1452
+							} catch (Exception $e) {
1453
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1454
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1455
+							}
1456
+							$event_name .= ' - ' . $item->name();
1457
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1458
+							// now get all of the registrations for this transaction that use this ticket
1459
+							$registrations = $ticket->registrations(
1460
+								array(array('TXN_ID' => $this->_transaction->ID()))
1461
+							);
1462
+							foreach ($registrations as $registration) {
1463
+								if (! $registration instanceof EE_Registration) {
1464
+									break;
1465
+								}
1466
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1467
+									= $registration->status_ID();
1468
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1469
+									= $registration->count();
1470
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1471
+									= $event_name;
1472
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1473
+									= $ticket_price;
1474
+								// attendee info
1475
+								$attendee = $registration->get_first_related('Attendee');
1476
+								if ($attendee instanceof EE_Attendee) {
1477
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1478
+										= $attendee->ID();
1479
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1480
+										= $attendee->full_name();
1481
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1482
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1483
+										  . esc_html__(
1484
+											  ' Event',
1485
+											  'event_espresso'
1486
+										  )
1487
+										  . '">' . $attendee->email() . '</a>';
1488
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1489
+										= EEH_Address::format($attendee, 'inline', false, false);
1490
+								} else {
1491
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1492
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1493
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1494
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1495
+								}
1496
+							}
1497
+							break;
1498
+					}
1499
+				}
1500
+			}
1501
+
1502
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1503
+				array(
1504
+					'action'  => 'edit_transaction',
1505
+					'process' => 'attendees',
1506
+				),
1507
+				TXN_ADMIN_URL
1508
+			);
1509
+			echo EEH_Template::display_template(
1510
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1511
+				$this->_template_args,
1512
+				true
1513
+			);
1514
+		} else {
1515
+			echo sprintf(
1516
+				esc_html__(
1517
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1518
+					'event_espresso'
1519
+				),
1520
+				'<p class="important-notice">',
1521
+				'</p>'
1522
+			);
1523
+		}
1524
+	}
1525
+
1526
+
1527
+	/**
1528
+	 * txn_registrant_side_meta_box
1529
+	 * generates HTML for the Edit Transaction side meta box
1530
+	 *
1531
+	 * @access public
1532
+	 * @return void
1533
+	 * @throws DomainException
1534
+	 * @throws EE_Error
1535
+	 * @throws InvalidArgumentException
1536
+	 * @throws InvalidDataTypeException
1537
+	 * @throws InvalidInterfaceException
1538
+	 * @throws ReflectionException
1539
+	 */
1540
+	public function txn_registrant_side_meta_box()
1541
+	{
1542
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1543
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1544
+			: null;
1545
+		if (! $primary_att instanceof EE_Attendee) {
1546
+			$this->_template_args['no_attendee_message'] = esc_html__(
1547
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1548
+				'event_espresso'
1549
+			);
1550
+			$primary_att = EEM_Attendee::instance()->create_default_object();
1551
+		}
1552
+		$this->_template_args['ATT_ID'] = $primary_att->ID();
1553
+		$this->_template_args['prime_reg_fname'] = $primary_att->fname();
1554
+		$this->_template_args['prime_reg_lname'] = $primary_att->lname();
1555
+		$this->_template_args['prime_reg_email'] = $primary_att->email();
1556
+		$this->_template_args['prime_reg_phone'] = $primary_att->phone();
1557
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1558
+			array(
1559
+				'action' => 'edit_attendee',
1560
+				'post'   => $primary_att->ID(),
1561
+			),
1562
+			REG_ADMIN_URL
1563
+		);
1564
+		// get formatted address for registrant
1565
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1566
+		echo EEH_Template::display_template(
1567
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1568
+			$this->_template_args,
1569
+			true
1570
+		);
1571
+	}
1572
+
1573
+
1574
+	/**
1575
+	 * txn_billing_info_side_meta_box
1576
+	 *    generates HTML for the Edit Transaction side meta box
1577
+	 *
1578
+	 * @access public
1579
+	 * @return void
1580
+	 * @throws DomainException
1581
+	 * @throws EE_Error
1582
+	 */
1583
+	public function txn_billing_info_side_meta_box()
1584
+	{
1585
+
1586
+		$this->_template_args['billing_form'] = $this->_transaction->billing_info();
1587
+		$this->_template_args['billing_form_url'] = add_query_arg(
1588
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1589
+			TXN_ADMIN_URL
1590
+		);
1591
+
1592
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1593
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1594
+	}
1595
+
1596
+
1597
+	/**
1598
+	 * apply_payments_or_refunds
1599
+	 *    registers a payment or refund made towards a transaction
1600
+	 *
1601
+	 * @access public
1602
+	 * @return void
1603
+	 * @throws EE_Error
1604
+	 * @throws InvalidArgumentException
1605
+	 * @throws ReflectionException
1606
+	 * @throws RuntimeException
1607
+	 * @throws InvalidDataTypeException
1608
+	 * @throws InvalidInterfaceException
1609
+	 */
1610
+	public function apply_payments_or_refunds()
1611
+	{
1612
+		$json_response_data = array('return_data' => false);
1613
+		$valid_data = $this->_validate_payment_request_data();
1614
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1615
+			'ee_edit_payments',
1616
+			'apply_payment_or_refund_from_registration_details'
1617
+		);
1618
+		if (! empty($valid_data) && $has_access) {
1619
+			$PAY_ID = $valid_data['PAY_ID'];
1620
+			// save  the new payment
1621
+			$payment = $this->_create_payment_from_request_data($valid_data);
1622
+			// get the TXN for this payment
1623
+			$transaction = $payment->transaction();
1624
+			// verify transaction
1625
+			if ($transaction instanceof EE_Transaction) {
1626
+				// calculate_total_payments_and_update_status
1627
+				$this->_process_transaction_payments($transaction);
1628
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1629
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1630
+				// apply payment to registrations (if applicable)
1631
+				if (! empty($REG_IDs)) {
1632
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1633
+					$this->_maybe_send_notifications();
1634
+					// now process status changes for the same registrations
1635
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1636
+				}
1637
+				$this->_maybe_send_notifications($payment);
1638
+				// prepare to render page
1639
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1640
+				do_action(
1641
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1642
+					$transaction,
1643
+					$payment
1644
+				);
1645
+			} else {
1646
+				EE_Error::add_error(
1647
+					esc_html__(
1648
+						'A valid Transaction for this payment could not be retrieved.',
1649
+						'event_espresso'
1650
+					),
1651
+					__FILE__,
1652
+					__FUNCTION__,
1653
+					__LINE__
1654
+				);
1655
+			}
1656
+		} elseif ($has_access) {
1657
+			EE_Error::add_error(
1658
+				esc_html__(
1659
+					'The payment form data could not be processed. Please try again.',
1660
+					'event_espresso'
1661
+				),
1662
+				__FILE__,
1663
+				__FUNCTION__,
1664
+				__LINE__
1665
+			);
1666
+		} else {
1667
+			EE_Error::add_error(
1668
+				esc_html__(
1669
+					'You do not have access to apply payments or refunds to a registration.',
1670
+					'event_espresso'
1671
+				),
1672
+				__FILE__,
1673
+				__FUNCTION__,
1674
+				__LINE__
1675
+			);
1676
+		}
1677
+		$notices = EE_Error::get_notices(
1678
+			false,
1679
+			false,
1680
+			false
1681
+		);
1682
+		$this->_template_args = array(
1683
+			'data'    => $json_response_data,
1684
+			'error'   => $notices['errors'],
1685
+			'success' => $notices['success'],
1686
+		);
1687
+		$this->_return_json();
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * _validate_payment_request_data
1693
+	 *
1694
+	 * @return array
1695
+	 * @throws EE_Error
1696
+	 * @throws InvalidArgumentException
1697
+	 * @throws InvalidDataTypeException
1698
+	 * @throws InvalidInterfaceException
1699
+	 */
1700
+	protected function _validate_payment_request_data()
1701
+	{
1702
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1703
+			return array();
1704
+		}
1705
+		$payment_form = $this->_generate_payment_form_section();
1706
+		try {
1707
+			if ($payment_form->was_submitted()) {
1708
+				$payment_form->receive_form_submission();
1709
+				if (! $payment_form->is_valid()) {
1710
+					$submission_error_messages = array();
1711
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1712
+						if ($validation_error instanceof EE_Validation_Error) {
1713
+							$submission_error_messages[] = sprintf(
1714
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1715
+								$validation_error->get_form_section()->html_label_text(),
1716
+								$validation_error->getMessage()
1717
+							);
1718
+						}
1719
+					}
1720
+					EE_Error::add_error(
1721
+						implode('<br />', $submission_error_messages),
1722
+						__FILE__,
1723
+						__FUNCTION__,
1724
+						__LINE__
1725
+					);
1726
+					return array();
1727
+				}
1728
+			}
1729
+		} catch (EE_Error $e) {
1730
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1731
+			return array();
1732
+		}
1733
+
1734
+		return $payment_form->valid_data();
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * _generate_payment_form_section
1740
+	 *
1741
+	 * @return EE_Form_Section_Proper
1742
+	 * @throws EE_Error
1743
+	 */
1744
+	protected function _generate_payment_form_section()
1745
+	{
1746
+		return new EE_Form_Section_Proper(
1747
+			array(
1748
+				'name'        => 'txn_admin_payment',
1749
+				'subsections' => array(
1750
+					'PAY_ID'          => new EE_Text_Input(
1751
+						array(
1752
+							'default'               => 0,
1753
+							'required'              => false,
1754
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1755
+							'validation_strategies' => array(new EE_Int_Normalization()),
1756
+						)
1757
+					),
1758
+					'TXN_ID'          => new EE_Text_Input(
1759
+						array(
1760
+							'default'               => 0,
1761
+							'required'              => true,
1762
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1763
+							'validation_strategies' => array(new EE_Int_Normalization()),
1764
+						)
1765
+					),
1766
+					'type'            => new EE_Text_Input(
1767
+						array(
1768
+							'default'               => 1,
1769
+							'required'              => true,
1770
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1771
+							'validation_strategies' => array(new EE_Int_Normalization()),
1772
+						)
1773
+					),
1774
+					'amount'          => new EE_Text_Input(
1775
+						array(
1776
+							'default'               => 0,
1777
+							'required'              => true,
1778
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1779
+							'validation_strategies' => array(new EE_Float_Normalization()),
1780
+						)
1781
+					),
1782
+					'status'          => new EE_Text_Input(
1783
+						array(
1784
+							'default'         => EEM_Payment::status_id_approved,
1785
+							'required'        => true,
1786
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1787
+						)
1788
+					),
1789
+					'PMD_ID'          => new EE_Text_Input(
1790
+						array(
1791
+							'default'               => 2,
1792
+							'required'              => true,
1793
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1794
+							'validation_strategies' => array(new EE_Int_Normalization()),
1795
+						)
1796
+					),
1797
+					'date'            => new EE_Text_Input(
1798
+						array(
1799
+							'default'         => time(),
1800
+							'required'        => true,
1801
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1802
+						)
1803
+					),
1804
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1805
+						array(
1806
+							'default'               => '',
1807
+							'required'              => false,
1808
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1809
+							'validation_strategies' => array(
1810
+								new EE_Max_Length_Validation_Strategy(
1811
+									esc_html__('Input too long', 'event_espresso'),
1812
+									100
1813
+								),
1814
+							),
1815
+						)
1816
+					),
1817
+					'po_number'       => new EE_Text_Input(
1818
+						array(
1819
+							'default'               => '',
1820
+							'required'              => false,
1821
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1822
+							'validation_strategies' => array(
1823
+								new EE_Max_Length_Validation_Strategy(
1824
+									esc_html__('Input too long', 'event_espresso'),
1825
+									100
1826
+								),
1827
+							),
1828
+						)
1829
+					),
1830
+					'accounting'      => new EE_Text_Input(
1831
+						array(
1832
+							'default'               => '',
1833
+							'required'              => false,
1834
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1835
+							'validation_strategies' => array(
1836
+								new EE_Max_Length_Validation_Strategy(
1837
+									esc_html__('Input too long', 'event_espresso'),
1838
+									100
1839
+								),
1840
+							),
1841
+						)
1842
+					),
1843
+				),
1844
+			)
1845
+		);
1846
+	}
1847
+
1848
+
1849
+	/**
1850
+	 * _create_payment_from_request_data
1851
+	 *
1852
+	 * @param array $valid_data
1853
+	 * @return EE_Payment
1854
+	 * @throws EE_Error
1855
+	 * @throws InvalidArgumentException
1856
+	 * @throws InvalidDataTypeException
1857
+	 * @throws InvalidInterfaceException
1858
+	 * @throws ReflectionException
1859
+	 */
1860
+	protected function _create_payment_from_request_data($valid_data)
1861
+	{
1862
+		$PAY_ID = $valid_data['PAY_ID'];
1863
+		// get payment amount
1864
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1865
+		// payments have a type value of 1 and refunds have a type value of -1
1866
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1867
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1868
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1869
+		$date = $valid_data['date']
1870
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1871
+			: date('Y-m-d g:i a', current_time('timestamp'));
1872
+		$payment = EE_Payment::new_instance(
1873
+			array(
1874
+				'TXN_ID'              => $valid_data['TXN_ID'],
1875
+				'STS_ID'              => $valid_data['status'],
1876
+				'PAY_timestamp'       => $date,
1877
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1878
+				'PMD_ID'              => $valid_data['PMD_ID'],
1879
+				'PAY_amount'          => $amount,
1880
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1881
+				'PAY_po_number'       => $valid_data['po_number'],
1882
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1883
+				'PAY_details'         => $valid_data,
1884
+				'PAY_ID'              => $PAY_ID,
1885
+			),
1886
+			'',
1887
+			array('Y-m-d', 'g:i a')
1888
+		);
1889
+
1890
+		if (! $payment->save()) {
1891
+			EE_Error::add_error(
1892
+				sprintf(
1893
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1894
+					$payment->ID()
1895
+				),
1896
+				__FILE__,
1897
+				__FUNCTION__,
1898
+				__LINE__
1899
+			);
1900
+		}
1901
+
1902
+		return $payment;
1903
+	}
1904
+
1905
+
1906
+	/**
1907
+	 * _process_transaction_payments
1908
+	 *
1909
+	 * @param \EE_Transaction $transaction
1910
+	 * @return void
1911
+	 * @throws EE_Error
1912
+	 * @throws InvalidArgumentException
1913
+	 * @throws ReflectionException
1914
+	 * @throws InvalidDataTypeException
1915
+	 * @throws InvalidInterfaceException
1916
+	 */
1917
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1918
+	{
1919
+		/** @type EE_Transaction_Payments $transaction_payments */
1920
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1921
+		// update the transaction with this payment
1922
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1923
+			EE_Error::add_success(
1924
+				esc_html__(
1925
+					'The payment has been processed successfully.',
1926
+					'event_espresso'
1927
+				),
1928
+				__FILE__,
1929
+				__FUNCTION__,
1930
+				__LINE__
1931
+			);
1932
+		} else {
1933
+			EE_Error::add_error(
1934
+				esc_html__(
1935
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1936
+					'event_espresso'
1937
+				),
1938
+				__FILE__,
1939
+				__FUNCTION__,
1940
+				__LINE__
1941
+			);
1942
+		}
1943
+	}
1944
+
1945
+
1946
+	/**
1947
+	 * _get_REG_IDs_to_apply_payment_to
1948
+	 * returns a list of registration IDs that the payment will apply to
1949
+	 *
1950
+	 * @param \EE_Payment $payment
1951
+	 * @return array
1952
+	 * @throws EE_Error
1953
+	 * @throws InvalidArgumentException
1954
+	 * @throws InvalidDataTypeException
1955
+	 * @throws InvalidInterfaceException
1956
+	 * @throws ReflectionException
1957
+	 */
1958
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1959
+	{
1960
+		$REG_IDs = array();
1961
+		// grab array of IDs for specific registrations to apply changes to
1962
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1963
+			$REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1964
+		}
1965
+		// nothing specified ? then get all reg IDs
1966
+		if (empty($REG_IDs)) {
1967
+			$registrations = $payment->transaction()->registrations();
1968
+			$REG_IDs = ! empty($registrations)
1969
+				? array_keys($registrations)
1970
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1971
+		}
1972
+
1973
+		// ensure that REG_IDs are integers and NOT strings
1974
+		return array_map('intval', $REG_IDs);
1975
+	}
1976
+
1977
+
1978
+	/**
1979
+	 * @return array
1980
+	 */
1981
+	public function existing_reg_payment_REG_IDs()
1982
+	{
1983
+		return $this->_existing_reg_payment_REG_IDs;
1984
+	}
1985
+
1986
+
1987
+	/**
1988
+	 * @param array $existing_reg_payment_REG_IDs
1989
+	 */
1990
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1991
+	{
1992
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1993
+	}
1994
+
1995
+
1996
+	/**
1997
+	 * _get_existing_reg_payment_REG_IDs
1998
+	 * returns a list of registration IDs that the payment is currently related to
1999
+	 * as recorded in the database
2000
+	 *
2001
+	 * @param \EE_Payment $payment
2002
+	 * @return array
2003
+	 * @throws EE_Error
2004
+	 * @throws InvalidArgumentException
2005
+	 * @throws InvalidDataTypeException
2006
+	 * @throws InvalidInterfaceException
2007
+	 * @throws ReflectionException
2008
+	 */
2009
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2010
+	{
2011
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2012
+			// let's get any existing reg payment records for this payment
2013
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2014
+			// but we only want the REG IDs, so grab the array keys
2015
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2016
+				? array_keys($existing_reg_payment_REG_IDs)
2017
+				: array();
2018
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2019
+		}
2020
+
2021
+		return $this->existing_reg_payment_REG_IDs();
2022
+	}
2023
+
2024
+
2025
+	/**
2026
+	 * _remove_existing_registration_payments
2027
+	 * this calculates the difference between existing relations
2028
+	 * to the supplied payment and the new list registration IDs,
2029
+	 * removes any related registrations that no longer apply,
2030
+	 * and then updates the registration paid fields
2031
+	 *
2032
+	 * @param \EE_Payment $payment
2033
+	 * @param int         $PAY_ID
2034
+	 * @return bool;
2035
+	 * @throws EE_Error
2036
+	 * @throws InvalidArgumentException
2037
+	 * @throws ReflectionException
2038
+	 * @throws InvalidDataTypeException
2039
+	 * @throws InvalidInterfaceException
2040
+	 */
2041
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2042
+	{
2043
+		// newly created payments will have nothing recorded for $PAY_ID
2044
+		if (absint($PAY_ID) === 0) {
2045
+			return false;
2046
+		}
2047
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2048
+		if (empty($existing_reg_payment_REG_IDs)) {
2049
+			return false;
2050
+		}
2051
+		/** @type EE_Transaction_Payments $transaction_payments */
2052
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2053
+
2054
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2055
+			$payment,
2056
+			array(
2057
+				array(
2058
+					'PAY_ID' => $payment->ID(),
2059
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2060
+				),
2061
+			)
2062
+		);
2063
+	}
2064
+
2065
+
2066
+	/**
2067
+	 * _update_registration_payments
2068
+	 * this applies the payments to the selected registrations
2069
+	 * but only if they have not already been paid for
2070
+	 *
2071
+	 * @param  EE_Transaction $transaction
2072
+	 * @param \EE_Payment     $payment
2073
+	 * @param array           $REG_IDs
2074
+	 * @return void
2075
+	 * @throws EE_Error
2076
+	 * @throws InvalidArgumentException
2077
+	 * @throws ReflectionException
2078
+	 * @throws RuntimeException
2079
+	 * @throws InvalidDataTypeException
2080
+	 * @throws InvalidInterfaceException
2081
+	 */
2082
+	protected function _update_registration_payments(
2083
+		EE_Transaction $transaction,
2084
+		EE_Payment $payment,
2085
+		$REG_IDs = array()
2086
+	) {
2087
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2088
+		// so let's do that using our set of REG_IDs from the form
2089
+		$registration_query_where_params = array(
2090
+			'REG_ID' => array('IN', $REG_IDs),
2091
+		);
2092
+		// but add in some conditions regarding payment,
2093
+		// so that we don't apply payments to registrations that are free or have already been paid for
2094
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2095
+		if (! $payment->is_a_refund()) {
2096
+			$registration_query_where_params['REG_final_price'] = array('!=', 0);
2097
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2098
+		}
2099
+		$registrations = $transaction->registrations(array($registration_query_where_params));
2100
+		if (! empty($registrations)) {
2101
+			/** @type EE_Payment_Processor $payment_processor */
2102
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2103
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2104
+		}
2105
+	}
2106
+
2107
+
2108
+	/**
2109
+	 * _process_registration_status_change
2110
+	 * This processes requested registration status changes for all the registrations
2111
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2112
+	 *
2113
+	 * @param  EE_Transaction $transaction
2114
+	 * @param array           $REG_IDs
2115
+	 * @return bool
2116
+	 * @throws EE_Error
2117
+	 * @throws InvalidArgumentException
2118
+	 * @throws ReflectionException
2119
+	 * @throws InvalidDataTypeException
2120
+	 * @throws InvalidInterfaceException
2121
+	 */
2122
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2123
+	{
2124
+		// first if there is no change in status then we get out.
2125
+		if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2126
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2127
+		) {
2128
+			// no error message, no change requested, just nothing to do man.
2129
+			return false;
2130
+		}
2131
+		/** @type EE_Transaction_Processor $transaction_processor */
2132
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2133
+
2134
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2135
+		return $transaction_processor->manually_update_registration_statuses(
2136
+			$transaction,
2137
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2138
+			array(array('REG_ID' => array('IN', $REG_IDs)))
2139
+		);
2140
+	}
2141
+
2142
+
2143
+	/**
2144
+	 * _build_payment_json_response
2145
+	 *
2146
+	 * @access public
2147
+	 * @param \EE_Payment $payment
2148
+	 * @param array       $REG_IDs
2149
+	 * @param bool | null $delete_txn_reg_status_change
2150
+	 * @return array
2151
+	 * @throws EE_Error
2152
+	 * @throws InvalidArgumentException
2153
+	 * @throws InvalidDataTypeException
2154
+	 * @throws InvalidInterfaceException
2155
+	 * @throws ReflectionException
2156
+	 */
2157
+	protected function _build_payment_json_response(
2158
+		EE_Payment $payment,
2159
+		$REG_IDs = array(),
2160
+		$delete_txn_reg_status_change = null
2161
+	) {
2162
+		// was the payment deleted ?
2163
+		if (is_bool($delete_txn_reg_status_change)) {
2164
+			return array(
2165
+				'PAY_ID'                       => $payment->ID(),
2166
+				'amount'                       => $payment->amount(),
2167
+				'total_paid'                   => $payment->transaction()->paid(),
2168
+				'txn_status'                   => $payment->transaction()->status_ID(),
2169
+				'pay_status'                   => $payment->STS_ID(),
2170
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2171
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2172
+			);
2173
+		} else {
2174
+			$this->_get_payment_status_array();
2175
+
2176
+			return array(
2177
+				'amount'           => $payment->amount(),
2178
+				'total_paid'       => $payment->transaction()->paid(),
2179
+				'txn_status'       => $payment->transaction()->status_ID(),
2180
+				'pay_status'       => $payment->STS_ID(),
2181
+				'PAY_ID'           => $payment->ID(),
2182
+				'STS_ID'           => $payment->STS_ID(),
2183
+				'status'           => self::$_pay_status[ $payment->STS_ID() ],
2184
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2185
+				'method'           => strtoupper($payment->source()),
2186
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2187
+				'gateway'          => $payment->payment_method()
2188
+					? $payment->payment_method()->admin_name()
2189
+					: esc_html__('Unknown', 'event_espresso'),
2190
+				'gateway_response' => $payment->gateway_response(),
2191
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2192
+				'po_number'        => $payment->po_number(),
2193
+				'extra_accntng'    => $payment->extra_accntng(),
2194
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2195
+			);
2196
+		}
2197
+	}
2198
+
2199
+
2200
+	/**
2201
+	 * delete_payment
2202
+	 *    delete a payment or refund made towards a transaction
2203
+	 *
2204
+	 * @access public
2205
+	 * @return void
2206
+	 * @throws EE_Error
2207
+	 * @throws InvalidArgumentException
2208
+	 * @throws ReflectionException
2209
+	 * @throws InvalidDataTypeException
2210
+	 * @throws InvalidInterfaceException
2211
+	 */
2212
+	public function delete_payment()
2213
+	{
2214
+		$json_response_data = array('return_data' => false);
2215
+		$PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2216
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2217
+			: 0;
2218
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2219
+			'ee_delete_payments',
2220
+			'delete_payment_from_registration_details'
2221
+		);
2222
+		if ($PAY_ID && $can_delete) {
2223
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2224
+				? $this->_req_data['delete_txn_reg_status_change']
2225
+				: false;
2226
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2227
+			if ($payment instanceof EE_Payment) {
2228
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2229
+				/** @type EE_Transaction_Payments $transaction_payments */
2230
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2231
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2232
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2233
+						$payment,
2234
+						$REG_IDs,
2235
+						$delete_txn_reg_status_change
2236
+					);
2237
+					if ($delete_txn_reg_status_change) {
2238
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2239
+						// MAKE sure we also add the delete_txn_req_status_change to the
2240
+						// $_REQUEST global because that's how messages will be looking for it.
2241
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2242
+						$this->_maybe_send_notifications();
2243
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2244
+					}
2245
+				}
2246
+			} else {
2247
+				EE_Error::add_error(
2248
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2249
+					__FILE__,
2250
+					__FUNCTION__,
2251
+					__LINE__
2252
+				);
2253
+			}
2254
+		} elseif ($can_delete) {
2255
+			EE_Error::add_error(
2256
+				esc_html__(
2257
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2258
+					'event_espresso'
2259
+				),
2260
+				__FILE__,
2261
+				__FUNCTION__,
2262
+				__LINE__
2263
+			);
2264
+		} else {
2265
+			EE_Error::add_error(
2266
+				esc_html__(
2267
+					'You do not have access to delete a payment.',
2268
+					'event_espresso'
2269
+				),
2270
+				__FILE__,
2271
+				__FUNCTION__,
2272
+				__LINE__
2273
+			);
2274
+		}
2275
+		$notices = EE_Error::get_notices(false, false, false);
2276
+		$this->_template_args = array(
2277
+			'data'      => $json_response_data,
2278
+			'success'   => $notices['success'],
2279
+			'error'     => $notices['errors'],
2280
+			'attention' => $notices['attention'],
2281
+		);
2282
+		$this->_return_json();
2283
+	}
2284
+
2285
+
2286
+	/**
2287
+	 * _registration_payment_data_array
2288
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2289
+	 *
2290
+	 * @access protected
2291
+	 * @param array $REG_IDs
2292
+	 * @return array
2293
+	 * @throws EE_Error
2294
+	 * @throws InvalidArgumentException
2295
+	 * @throws InvalidDataTypeException
2296
+	 * @throws InvalidInterfaceException
2297
+	 * @throws ReflectionException
2298
+	 */
2299
+	protected function _registration_payment_data_array($REG_IDs)
2300
+	{
2301
+		$registration_payment_data = array();
2302
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2303
+		if (! empty($REG_IDs)) {
2304
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2305
+			foreach ($registrations as $registration) {
2306
+				if ($registration instanceof EE_Registration) {
2307
+					$registration_payment_data[ $registration->ID() ] = array(
2308
+						'paid'  => $registration->pretty_paid(),
2309
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2310
+					);
2311
+				}
2312
+			}
2313
+		}
2314
+
2315
+		return $registration_payment_data;
2316
+	}
2317
+
2318
+
2319
+	/**
2320
+	 * _maybe_send_notifications
2321
+	 * determines whether or not the admin has indicated that notifications should be sent.
2322
+	 * If so, will toggle a filter switch for delivering registration notices.
2323
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2324
+	 *
2325
+	 * @access protected
2326
+	 * @param \EE_Payment | null $payment
2327
+	 */
2328
+	protected function _maybe_send_notifications($payment = null)
2329
+	{
2330
+		switch ($payment instanceof EE_Payment) {
2331
+			// payment notifications
2332
+			case true:
2333
+				if (isset($this->_req_data['txn_payments']['send_notifications'])
2334
+					&& filter_var(
2335
+						$this->_req_data['txn_payments']['send_notifications'],
2336
+						FILTER_VALIDATE_BOOLEAN
2337
+					)
2338
+				) {
2339
+					$this->_process_payment_notification($payment);
2340
+				}
2341
+				break;
2342
+			// registration notifications
2343
+			case false:
2344
+				if (isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2345
+					&& filter_var(
2346
+						$this->_req_data['txn_reg_status_change']['send_notifications'],
2347
+						FILTER_VALIDATE_BOOLEAN
2348
+					)
2349
+				) {
2350
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2351
+				}
2352
+				break;
2353
+		}
2354
+	}
2355
+
2356
+
2357
+	/**
2358
+	 * _send_payment_reminder
2359
+	 *    generates HTML for the View Transaction Details Admin page
2360
+	 *
2361
+	 * @access protected
2362
+	 * @return void
2363
+	 * @throws EE_Error
2364
+	 * @throws InvalidArgumentException
2365
+	 * @throws InvalidDataTypeException
2366
+	 * @throws InvalidInterfaceException
2367
+	 */
2368
+	protected function _send_payment_reminder()
2369
+	{
2370
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2371
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2372
+		$query_args = isset($this->_req_data['redirect_to']) ? array(
2373
+			'action' => $this->_req_data['redirect_to'],
2374
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2375
+		) : array();
2376
+		do_action(
2377
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2378
+			$transaction
2379
+		);
2380
+		$this->_redirect_after_action(
2381
+			false,
2382
+			esc_html__('payment reminder', 'event_espresso'),
2383
+			esc_html__('sent', 'event_espresso'),
2384
+			$query_args,
2385
+			true
2386
+		);
2387
+	}
2388
+
2389
+
2390
+	/**
2391
+	 *  get_transactions
2392
+	 *    get transactions for given parameters (used by list table)
2393
+	 *
2394
+	 * @param  int     $perpage how many transactions displayed per page
2395
+	 * @param  boolean $count   return the count or objects
2396
+	 * @param string   $view
2397
+	 * @return mixed int = count || array of transaction objects
2398
+	 * @throws EE_Error
2399
+	 * @throws InvalidArgumentException
2400
+	 * @throws InvalidDataTypeException
2401
+	 * @throws InvalidInterfaceException
2402
+	 */
2403
+	public function get_transactions($perpage, $count = false, $view = '')
2404
+	{
2405
+
2406
+		$TXN = EEM_Transaction::instance();
2407
+
2408
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2409
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2410
+			: date(
2411
+				'm/d/Y',
2412
+				strtotime('-10 year')
2413
+			);
2414
+		$end_date = isset($this->_req_data['txn-filter-end-date'])
2415
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2416
+			: date('m/d/Y');
2417
+
2418
+		// make sure our timestamps start and end right at the boundaries for each day
2419
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2420
+		$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2421
+
2422
+
2423
+		// convert to timestamps
2424
+		$start_date = strtotime($start_date);
2425
+		$end_date = strtotime($end_date);
2426
+
2427
+		// makes sure start date is the lowest value and vice versa
2428
+		$start_date = min($start_date, $end_date);
2429
+		$end_date = max($start_date, $end_date);
2430
+
2431
+		// convert to correct format for query
2432
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2433
+			'TXN_timestamp',
2434
+			date('Y-m-d H:i:s', $start_date),
2435
+			'Y-m-d H:i:s'
2436
+		);
2437
+		$end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2438
+			'TXN_timestamp',
2439
+			date('Y-m-d H:i:s', $end_date),
2440
+			'Y-m-d H:i:s'
2441
+		);
2442
+
2443
+
2444
+		// set orderby
2445
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2446
+
2447
+		switch ($this->_req_data['orderby']) {
2448
+			case 'TXN_ID':
2449
+				$orderby = 'TXN_ID';
2450
+				break;
2451
+			case 'ATT_fname':
2452
+				$orderby = 'Registration.Attendee.ATT_fname';
2453
+				break;
2454
+			case 'event_name':
2455
+				$orderby = 'Registration.Event.EVT_name';
2456
+				break;
2457
+			default: // 'TXN_timestamp'
2458
+				$orderby = 'TXN_timestamp';
2459
+		}
2460
+
2461
+		$sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2462
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2463
+		$per_page = ! empty($perpage) ? $perpage : 10;
2464
+		$per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2465
+
2466
+		$offset = ($current_page - 1) * $per_page;
2467
+		$limit = array($offset, $per_page);
2468
+
2469
+		$_where = array(
2470
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2471
+			'Registration.REG_count' => 1,
2472
+		);
2473
+
2474
+		if (isset($this->_req_data['EVT_ID'])) {
2475
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2476
+		}
2477
+
2478
+		if (isset($this->_req_data['s'])) {
2479
+			$search_string = '%' . $this->_req_data['s'] . '%';
2480
+			$_where['OR'] = array(
2481
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2482
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2483
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2484
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2485
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2486
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2487
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2488
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2489
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2490
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2491
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2492
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2493
+				'Registration.REG_code'               => array('LIKE', $search_string),
2494
+				'Registration.REG_count'              => array('LIKE', $search_string),
2495
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2496
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2497
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2498
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2499
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2500
+				'TXN_session_data'                    => array('LIKE', $search_string),
2501
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2502
+			);
2503
+		}
2504
+
2505
+		// failed transactions
2506
+		$failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2507
+				  || ($count && $view === 'failed');
2508
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2509
+					 || ($count && $view === 'abandoned');
2510
+		$incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2511
+					  || ($count && $view === 'incomplete');
2512
+
2513
+		if ($failed) {
2514
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2515
+		} elseif ($abandoned) {
2516
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2517
+		} elseif ($incomplete) {
2518
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2519
+		} else {
2520
+			$_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2521
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2522
+		}
2523
+
2524
+		$query_params = apply_filters(
2525
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2526
+			array(
2527
+				$_where,
2528
+				'order_by'                 => array($orderby => $sort),
2529
+				'limit'                    => $limit,
2530
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2531
+			),
2532
+			$this->_req_data,
2533
+			$view,
2534
+			$count
2535
+		);
2536
+
2537
+		$transactions = $count
2538
+			? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2539
+			: $TXN->get_all($query_params);
2540
+
2541
+		return $transactions;
2542
+	}
2543
+
2544
+
2545
+	/**
2546
+	 * @since 4.9.79.p
2547
+	 * @throws EE_Error
2548
+	 * @throws InvalidArgumentException
2549
+	 * @throws InvalidDataTypeException
2550
+	 * @throws InvalidInterfaceException
2551
+	 * @throws ReflectionException
2552
+	 * @throws RuntimeException
2553
+	 */
2554
+	public function recalculateLineItems()
2555
+	{
2556
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2557
+		/** @var EE_Transaction $transaction */
2558
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2559
+		$total_line_item = $transaction->total_line_item(false);
2560
+		$success = $transaction->recalculateLineItems();
2561
+		$this->_redirect_after_action(
2562
+			(bool) $success,
2563
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2564
+			esc_html__('recalculated', 'event_espresso'),
2565
+			isset($this->_req_data['redirect_to'])
2566
+				? array(
2567
+				'action' => $this->_req_data['redirect_to'],
2568
+				'TXN_ID' => $this->_req_data['TXN_ID'],
2569
+			)
2570
+				: array(),
2571
+			true
2572
+		);
2573
+	}
2574 2574
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 1 patch
Indentation   +2105 added lines, -2105 removed lines patch added patch discarded remove patch
@@ -17,2109 +17,2109 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * Used to reference when a registration has never been checked in.
22
-     *
23
-     * @deprecated use \EE_Checkin::status_checked_never instead
24
-     * @type int
25
-     */
26
-    const checkin_status_never = 2;
27
-
28
-    /**
29
-     * Used to reference when a registration has been checked in.
30
-     *
31
-     * @deprecated use \EE_Checkin::status_checked_in instead
32
-     * @type int
33
-     */
34
-    const checkin_status_in = 1;
35
-
36
-
37
-    /**
38
-     * Used to reference when a registration has been checked out.
39
-     *
40
-     * @deprecated use \EE_Checkin::status_checked_out instead
41
-     * @type int
42
-     */
43
-    const checkin_status_out = 0;
44
-
45
-
46
-    /**
47
-     * extra meta key for tracking reg status os trashed registrations
48
-     *
49
-     * @type string
50
-     */
51
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
-
53
-
54
-    /**
55
-     * extra meta key for tracking if registration has reserved ticket
56
-     *
57
-     * @type string
58
-     */
59
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values          incoming values
64
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
-     *                                        used.)
66
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
-     *                                        date_format and the second value is the time format
68
-     * @return EE_Registration
69
-     * @throws EE_Error
70
-     */
71
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
-    {
73
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Registration
83
-     */
84
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
-    {
86
-        return new self($props_n_values, true, $timezone);
87
-    }
88
-
89
-
90
-    /**
91
-     *        Set Event ID
92
-     *
93
-     * @param        int $EVT_ID Event ID
94
-     * @throws EE_Error
95
-     * @throws RuntimeException
96
-     */
97
-    public function set_event($EVT_ID = 0)
98
-    {
99
-        $this->set('EVT_ID', $EVT_ID);
100
-    }
101
-
102
-
103
-    /**
104
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
-     * be routed to internal methods
106
-     *
107
-     * @param string $field_name
108
-     * @param mixed  $field_value
109
-     * @param bool   $use_default
110
-     * @throws EE_Error
111
-     * @throws EntityNotFoundException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     * @throws ReflectionException
116
-     * @throws RuntimeException
117
-     */
118
-    public function set($field_name, $field_value, $use_default = false)
119
-    {
120
-        switch ($field_name) {
121
-            case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
123
-                    $this->set_reg_code($field_value, $use_default);
124
-                }
125
-                break;
126
-            case 'STS_ID':
127
-                $this->set_status($field_value, $use_default);
128
-                break;
129
-            default:
130
-                parent::set($field_name, $field_value, $use_default);
131
-        }
132
-    }
133
-
134
-
135
-    /**
136
-     * Set Status ID
137
-     * updates the registration status and ALSO...
138
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
-     *
141
-     * @param string                $new_STS_ID
142
-     * @param boolean               $use_default
143
-     * @param ContextInterface|null $context
144
-     * @return bool
145
-     * @throws DomainException
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidInterfaceException
151
-     * @throws ReflectionException
152
-     * @throws RuntimeException
153
-     * @throws UnexpectedEntityException
154
-     */
155
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
-    {
157
-        // get current REG_Status
158
-        $old_STS_ID = $this->status_ID();
159
-        // if status has changed
160
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
-            && ! empty($old_STS_ID) // and that old status is actually set
162
-            && ! empty($new_STS_ID) // as well as the new status
163
-            && $this->ID() // ensure registration is in the db
164
-        ) {
165
-            // update internal status first
166
-            parent::set('STS_ID', $new_STS_ID, $use_default);
167
-            // THEN handle other changes that occur when reg status changes
168
-            // TO approved
169
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
-                // reserve a space by incrementing ticket and datetime sold values
171
-                $this->reserveRegistrationSpace();
172
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
-                // OR FROM  approved
174
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
-                // release a space by decrementing ticket and datetime sold values
176
-                $this->releaseRegistrationSpace();
177
-                do_action(
178
-                    'AHEE__EE_Registration__set_status__from_approved',
179
-                    $this,
180
-                    $old_STS_ID,
181
-                    $new_STS_ID,
182
-                    $context
183
-                );
184
-            }
185
-            // update status
186
-            parent::set('STS_ID', $new_STS_ID, $use_default);
187
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
-            if ($this->statusChangeUpdatesTransaction($context)) {
189
-                $this->updateTransactionAfterStatusChange();
190
-            }
191
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
-            return true;
193
-        }
194
-        // even though the old value matches the new value, it's still good to
195
-        // allow the parent set method to have a say
196
-        parent::set('STS_ID', $new_STS_ID, $use_default);
197
-        return true;
198
-    }
199
-
200
-
201
-    /**
202
-     * update REGs and TXN when cancelled or declined registrations involved
203
-     *
204
-     * @param string                $new_STS_ID
205
-     * @param string                $old_STS_ID
206
-     * @param ContextInterface|null $context
207
-     * @throws EE_Error
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     * @throws ReflectionException
212
-     * @throws RuntimeException
213
-     */
214
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
-    {
216
-        // these reg statuses should not be considered in any calculations involving monies owing
217
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
-        // true if registration has been cancelled or declined
219
-        $this->updateIfCanceled(
220
-            $closed_reg_statuses,
221
-            $new_STS_ID,
222
-            $old_STS_ID,
223
-            $context
224
-        );
225
-        $this->updateIfReinstated(
226
-            $closed_reg_statuses,
227
-            $new_STS_ID,
228
-            $old_STS_ID,
229
-            $context
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     * update REGs and TXN when cancelled or declined registrations involved
236
-     *
237
-     * @param array                 $closed_reg_statuses
238
-     * @param string                $new_STS_ID
239
-     * @param string                $old_STS_ID
240
-     * @param ContextInterface|null $context
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws InvalidDataTypeException
244
-     * @throws InvalidInterfaceException
245
-     * @throws ReflectionException
246
-     * @throws RuntimeException
247
-     */
248
-    private function updateIfCanceled(
249
-        array $closed_reg_statuses,
250
-        $new_STS_ID,
251
-        $old_STS_ID,
252
-        ContextInterface $context = null
253
-    ) {
254
-        // true if registration has been cancelled or declined
255
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
-        ) {
258
-            /** @type EE_Registration_Processor $registration_processor */
259
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
-            /** @type EE_Transaction_Processor $transaction_processor */
261
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
-            // cancelled or declined registration
263
-            $registration_processor->update_registration_after_being_canceled_or_declined(
264
-                $this,
265
-                $closed_reg_statuses
266
-            );
267
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
-                $this,
269
-                $closed_reg_statuses,
270
-                false
271
-            );
272
-            do_action(
273
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
274
-                $this,
275
-                $old_STS_ID,
276
-                $new_STS_ID,
277
-                $context
278
-            );
279
-            return;
280
-        }
281
-    }
282
-
283
-
284
-    /**
285
-     * update REGs and TXN when cancelled or declined registrations involved
286
-     *
287
-     * @param array                 $closed_reg_statuses
288
-     * @param string                $new_STS_ID
289
-     * @param string                $old_STS_ID
290
-     * @param ContextInterface|null $context
291
-     * @throws EE_Error
292
-     * @throws InvalidArgumentException
293
-     * @throws InvalidDataTypeException
294
-     * @throws InvalidInterfaceException
295
-     * @throws ReflectionException
296
-     */
297
-    private function updateIfReinstated(
298
-        array $closed_reg_statuses,
299
-        $new_STS_ID,
300
-        $old_STS_ID,
301
-        ContextInterface $context = null
302
-    ) {
303
-        // true if reinstating cancelled or declined registration
304
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
-        ) {
307
-            /** @type EE_Registration_Processor $registration_processor */
308
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
-            /** @type EE_Transaction_Processor $transaction_processor */
310
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
-            // reinstating cancelled or declined registration
312
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
-                $this,
314
-                $closed_reg_statuses
315
-            );
316
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
-                $this,
318
-                $closed_reg_statuses,
319
-                false
320
-            );
321
-            do_action(
322
-                'AHEE__EE_Registration__set_status__after_reinstated',
323
-                $this,
324
-                $old_STS_ID,
325
-                $new_STS_ID,
326
-                $context
327
-            );
328
-        }
329
-    }
330
-
331
-
332
-    /**
333
-     * @param ContextInterface|null $context
334
-     * @return bool
335
-     */
336
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
-    {
338
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
339
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
-            array('spco_reg_step_attendee_information_process_registrations'),
341
-            $context,
342
-            $this
343
-        );
344
-        return ! (
345
-            $context instanceof ContextInterface
346
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
-        );
348
-    }
349
-
350
-
351
-    /**
352
-     * @throws EE_Error
353
-     * @throws EntityNotFoundException
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidDataTypeException
356
-     * @throws InvalidInterfaceException
357
-     * @throws ReflectionException
358
-     * @throws RuntimeException
359
-     */
360
-    private function updateTransactionAfterStatusChange()
361
-    {
362
-        /** @type EE_Transaction_Payments $transaction_payments */
363
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
-        $this->transaction()->update_status_based_on_total_paid(true);
366
-    }
367
-
368
-
369
-    /**
370
-     *        get Status ID
371
-     */
372
-    public function status_ID()
373
-    {
374
-        return $this->get('STS_ID');
375
-    }
376
-
377
-
378
-    /**
379
-     * Gets the ticket this registration is for
380
-     *
381
-     * @param boolean $include_archived whether to include archived tickets or not.
382
-     *
383
-     * @return EE_Ticket|EE_Base_Class
384
-     * @throws EE_Error
385
-     */
386
-    public function ticket($include_archived = true)
387
-    {
388
-        $query_params = array();
389
-        if ($include_archived) {
390
-            $query_params['default_where_conditions'] = 'none';
391
-        }
392
-        return $this->get_first_related('Ticket', $query_params);
393
-    }
394
-
395
-
396
-    /**
397
-     * Gets the event this registration is for
398
-     *
399
-     * @return EE_Event
400
-     * @throws EE_Error
401
-     * @throws EntityNotFoundException
402
-     */
403
-    public function event()
404
-    {
405
-        $event = $this->get_first_related('Event');
406
-        if (! $event instanceof \EE_Event) {
407
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
408
-        }
409
-        return $event;
410
-    }
411
-
412
-
413
-    /**
414
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
-     * with the author of the event this registration is for.
416
-     *
417
-     * @since 4.5.0
418
-     * @return int
419
-     * @throws EE_Error
420
-     * @throws EntityNotFoundException
421
-     */
422
-    public function wp_user()
423
-    {
424
-        $event = $this->event();
425
-        if ($event instanceof EE_Event) {
426
-            return $event->wp_user();
427
-        }
428
-        return 0;
429
-    }
430
-
431
-
432
-    /**
433
-     * increments this registration's related ticket sold and corresponding datetime sold values
434
-     *
435
-     * @return void
436
-     * @throws DomainException
437
-     * @throws EE_Error
438
-     * @throws EntityNotFoundException
439
-     * @throws InvalidArgumentException
440
-     * @throws InvalidDataTypeException
441
-     * @throws InvalidInterfaceException
442
-     * @throws ReflectionException
443
-     * @throws UnexpectedEntityException
444
-     */
445
-    private function reserveRegistrationSpace()
446
-    {
447
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
448
-        // so stop tracking that this reg has a ticket reserved
449
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
-        $ticket = $this->ticket();
451
-        $ticket->increaseSold();
452
-        // possibly set event status to sold out
453
-        $this->event()->perform_sold_out_status_check();
454
-    }
455
-
456
-
457
-    /**
458
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
-     *
460
-     * @return void
461
-     * @throws DomainException
462
-     * @throws EE_Error
463
-     * @throws EntityNotFoundException
464
-     * @throws InvalidArgumentException
465
-     * @throws InvalidDataTypeException
466
-     * @throws InvalidInterfaceException
467
-     * @throws ReflectionException
468
-     * @throws UnexpectedEntityException
469
-     */
470
-    private function releaseRegistrationSpace()
471
-    {
472
-        $ticket = $this->ticket();
473
-        $ticket->decreaseSold();
474
-        // possibly change event status from sold out back to previous status
475
-        $this->event()->perform_sold_out_status_check();
476
-    }
477
-
478
-
479
-    /**
480
-     * tracks this registration's ticket reservation in extra meta
481
-     * and can increment related ticket reserved and corresponding datetime reserved values
482
-     *
483
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
-    {
493
-        // only reserve ticket if space is not currently reserved
494
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
-            // IMPORTANT !!!
497
-            // although checking $update_ticket first would be more efficient,
498
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
-                && $update_ticket
501
-            ) {
502
-                $ticket = $this->ticket();
503
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
-                $ticket->save();
505
-            }
506
-        }
507
-    }
508
-
509
-
510
-    /**
511
-     * stops tracking this registration's ticket reservation in extra meta
512
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
-     *
514
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
-     * @return void
516
-     * @throws EE_Error
517
-     * @throws InvalidArgumentException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     * @throws ReflectionException
521
-     */
522
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
-    {
524
-        // only release ticket if space is currently reserved
525
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
-            // IMPORTANT !!!
528
-            // although checking $update_ticket first would be more efficient,
529
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
-                && $update_ticket
532
-            ) {
533
-                $ticket = $this->ticket();
534
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
-            }
536
-        }
537
-    }
538
-
539
-
540
-    /**
541
-     * Set Attendee ID
542
-     *
543
-     * @param        int $ATT_ID Attendee ID
544
-     * @throws EE_Error
545
-     * @throws RuntimeException
546
-     */
547
-    public function set_attendee_id($ATT_ID = 0)
548
-    {
549
-        $this->set('ATT_ID', $ATT_ID);
550
-    }
551
-
552
-
553
-    /**
554
-     *        Set Transaction ID
555
-     *
556
-     * @param        int $TXN_ID Transaction ID
557
-     * @throws EE_Error
558
-     * @throws RuntimeException
559
-     */
560
-    public function set_transaction_id($TXN_ID = 0)
561
-    {
562
-        $this->set('TXN_ID', $TXN_ID);
563
-    }
564
-
565
-
566
-    /**
567
-     *        Set Session
568
-     *
569
-     * @param    string $REG_session PHP Session ID
570
-     * @throws EE_Error
571
-     * @throws RuntimeException
572
-     */
573
-    public function set_session($REG_session = '')
574
-    {
575
-        $this->set('REG_session', $REG_session);
576
-    }
577
-
578
-
579
-    /**
580
-     *        Set Registration URL Link
581
-     *
582
-     * @param    string $REG_url_link Registration URL Link
583
-     * @throws EE_Error
584
-     * @throws RuntimeException
585
-     */
586
-    public function set_reg_url_link($REG_url_link = '')
587
-    {
588
-        $this->set('REG_url_link', $REG_url_link);
589
-    }
590
-
591
-
592
-    /**
593
-     *        Set Attendee Counter
594
-     *
595
-     * @param        int $REG_count Primary Attendee
596
-     * @throws EE_Error
597
-     * @throws RuntimeException
598
-     */
599
-    public function set_count($REG_count = 1)
600
-    {
601
-        $this->set('REG_count', $REG_count);
602
-    }
603
-
604
-
605
-    /**
606
-     *        Set Group Size
607
-     *
608
-     * @param        boolean $REG_group_size Group Registration
609
-     * @throws EE_Error
610
-     * @throws RuntimeException
611
-     */
612
-    public function set_group_size($REG_group_size = false)
613
-    {
614
-        $this->set('REG_group_size', $REG_group_size);
615
-    }
616
-
617
-
618
-    /**
619
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
-     *    EEM_Registration::status_id_not_approved
621
-     *
622
-     * @return        boolean
623
-     */
624
-    public function is_not_approved()
625
-    {
626
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
-    }
628
-
629
-
630
-    /**
631
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
-     *    EEM_Registration::status_id_pending_payment
633
-     *
634
-     * @return        boolean
635
-     */
636
-    public function is_pending_payment()
637
-    {
638
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
-    }
640
-
641
-
642
-    /**
643
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
-     *
645
-     * @return        boolean
646
-     */
647
-    public function is_approved()
648
-    {
649
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
-    }
651
-
652
-
653
-    /**
654
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
-     *
656
-     * @return        boolean
657
-     */
658
-    public function is_cancelled()
659
-    {
660
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
-    }
662
-
663
-
664
-    /**
665
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
-     *
667
-     * @return        boolean
668
-     */
669
-    public function is_declined()
670
-    {
671
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
-    }
673
-
674
-
675
-    /**
676
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
-     *    EEM_Registration::status_id_incomplete
678
-     *
679
-     * @return        boolean
680
-     */
681
-    public function is_incomplete()
682
-    {
683
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
-    }
685
-
686
-
687
-    /**
688
-     *        Set Registration Date
689
-     *
690
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
-     *                                                 Date
692
-     * @throws EE_Error
693
-     * @throws RuntimeException
694
-     */
695
-    public function set_reg_date($REG_date = false)
696
-    {
697
-        $this->set('REG_date', $REG_date);
698
-    }
699
-
700
-
701
-    /**
702
-     *    Set final price owing for this registration after all ticket/price modifications
703
-     *
704
-     * @access    public
705
-     * @param    float $REG_final_price
706
-     * @throws EE_Error
707
-     * @throws RuntimeException
708
-     */
709
-    public function set_final_price($REG_final_price = 0.00)
710
-    {
711
-        $this->set('REG_final_price', $REG_final_price);
712
-    }
713
-
714
-
715
-    /**
716
-     *    Set amount paid towards this registration's final price
717
-     *
718
-     * @access    public
719
-     * @param    float $REG_paid
720
-     * @throws EE_Error
721
-     * @throws RuntimeException
722
-     */
723
-    public function set_paid($REG_paid = 0.00)
724
-    {
725
-        $this->set('REG_paid', $REG_paid);
726
-    }
727
-
728
-
729
-    /**
730
-     *        Attendee Is Going
731
-     *
732
-     * @param        boolean $REG_att_is_going Attendee Is Going
733
-     * @throws EE_Error
734
-     * @throws RuntimeException
735
-     */
736
-    public function set_att_is_going($REG_att_is_going = false)
737
-    {
738
-        $this->set('REG_att_is_going', $REG_att_is_going);
739
-    }
740
-
741
-
742
-    /**
743
-     * Gets the related attendee
744
-     *
745
-     * @return EE_Attendee
746
-     * @throws EE_Error
747
-     */
748
-    public function attendee()
749
-    {
750
-        return $this->get_first_related('Attendee');
751
-    }
752
-
753
-    /**
754
-     * Gets the name of the attendee.
755
-     * @since $VID:$
756
-     * @param bool $apply_html_entities set to true if you want to use HTML entities.
757
-     * @return string
758
-     * @throws EE_Error
759
-     * @throws InvalidArgumentException
760
-     * @throws InvalidDataTypeException
761
-     * @throws InvalidInterfaceException
762
-     * @throws ReflectionException
763
-     */
764
-    public function attendeeName($apply_html_entities = false)
765
-    {
766
-        $attendee = $this->get_first_related('Attendee');
767
-        if ($attendee instanceof EE_Attendee) {
768
-            $attendee_name = $attendee->full_name($apply_html_entities);
769
-        } else {
770
-            $attendee_name = esc_html__('Unknown', 'event_espresso');
771
-        }
772
-        return $attendee_name;
773
-    }
774
-
775
-
776
-    /**
777
-     *        get Event ID
778
-     */
779
-    public function event_ID()
780
-    {
781
-        return $this->get('EVT_ID');
782
-    }
783
-
784
-
785
-    /**
786
-     *        get Event ID
787
-     */
788
-    public function event_name()
789
-    {
790
-        $event = $this->event_obj();
791
-        if ($event) {
792
-            return $event->name();
793
-        } else {
794
-            return null;
795
-        }
796
-    }
797
-
798
-
799
-    /**
800
-     * Fetches the event this registration is for
801
-     *
802
-     * @return EE_Event
803
-     * @throws EE_Error
804
-     */
805
-    public function event_obj()
806
-    {
807
-        return $this->get_first_related('Event');
808
-    }
809
-
810
-
811
-    /**
812
-     *        get Attendee ID
813
-     */
814
-    public function attendee_ID()
815
-    {
816
-        return $this->get('ATT_ID');
817
-    }
818
-
819
-
820
-    /**
821
-     *        get PHP Session ID
822
-     */
823
-    public function session_ID()
824
-    {
825
-        return $this->get('REG_session');
826
-    }
827
-
828
-
829
-    /**
830
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
831
-     *
832
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
833
-     * @return string
834
-     */
835
-    public function receipt_url($messenger = 'html')
836
-    {
837
-
838
-        /**
839
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
840
-         * already in use on old system.  If there is then we just return the standard url for it.
841
-         *
842
-         * @since 4.5.0
843
-         */
844
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
845
-        $has_custom = EEH_Template::locate_template(
846
-            $template_relative_path,
847
-            array(),
848
-            true,
849
-            true,
850
-            true
851
-        );
852
-
853
-        if ($has_custom) {
854
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
855
-        }
856
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
857
-    }
858
-
859
-
860
-    /**
861
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
862
-     *
863
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
864
-     * @return string
865
-     * @throws EE_Error
866
-     */
867
-    public function invoice_url($messenger = 'html')
868
-    {
869
-        /**
870
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
871
-         * already in use on old system.  If there is then we just return the standard url for it.
872
-         *
873
-         * @since 4.5.0
874
-         */
875
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
876
-        $has_custom = EEH_Template::locate_template(
877
-            $template_relative_path,
878
-            array(),
879
-            true,
880
-            true,
881
-            true
882
-        );
883
-
884
-        if ($has_custom) {
885
-            if ($messenger == 'html') {
886
-                return $this->invoice_url('launch');
887
-            }
888
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
889
-
890
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
891
-            if ($messenger == 'html') {
892
-                $query_args['html'] = true;
893
-            }
894
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
895
-        }
896
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
897
-    }
898
-
899
-
900
-    /**
901
-     * get Registration URL Link
902
-     *
903
-     * @access public
904
-     * @return string
905
-     * @throws EE_Error
906
-     */
907
-    public function reg_url_link()
908
-    {
909
-        return (string) $this->get('REG_url_link');
910
-    }
911
-
912
-
913
-    /**
914
-     * Echoes out invoice_url()
915
-     *
916
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
917
-     * @return void
918
-     * @throws EE_Error
919
-     */
920
-    public function e_invoice_url($type = 'launch')
921
-    {
922
-        echo $this->invoice_url($type);
923
-    }
924
-
925
-
926
-    /**
927
-     * Echoes out payment_overview_url
928
-     */
929
-    public function e_payment_overview_url()
930
-    {
931
-        echo $this->payment_overview_url();
932
-    }
933
-
934
-
935
-    /**
936
-     * Gets the URL for the checkout payment options reg step
937
-     * with this registration's REG_url_link added as a query parameter
938
-     *
939
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
940
-     *                            payment overview url.
941
-     * @return string
942
-     * @throws InvalidInterfaceException
943
-     * @throws InvalidDataTypeException
944
-     * @throws EE_Error
945
-     * @throws InvalidArgumentException
946
-     */
947
-    public function payment_overview_url($clear_session = false)
948
-    {
949
-        return add_query_arg(
950
-            (array) apply_filters(
951
-                'FHEE__EE_Registration__payment_overview_url__query_args',
952
-                array(
953
-                    'e_reg_url_link' => $this->reg_url_link(),
954
-                    'step'           => 'payment_options',
955
-                    'revisit'        => true,
956
-                    'clear_session'  => (bool) $clear_session,
957
-                ),
958
-                $this
959
-            ),
960
-            EE_Registry::instance()->CFG->core->reg_page_url()
961
-        );
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets the URL for the checkout attendee information reg step
967
-     * with this registration's REG_url_link added as a query parameter
968
-     *
969
-     * @return string
970
-     * @throws InvalidInterfaceException
971
-     * @throws InvalidDataTypeException
972
-     * @throws EE_Error
973
-     * @throws InvalidArgumentException
974
-     */
975
-    public function edit_attendee_information_url()
976
-    {
977
-        return add_query_arg(
978
-            (array) apply_filters(
979
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
980
-                array(
981
-                    'e_reg_url_link' => $this->reg_url_link(),
982
-                    'step'           => 'attendee_information',
983
-                    'revisit'        => true,
984
-                ),
985
-                $this
986
-            ),
987
-            EE_Registry::instance()->CFG->core->reg_page_url()
988
-        );
989
-    }
990
-
991
-
992
-    /**
993
-     * Simply generates and returns the appropriate admin_url link to edit this registration
994
-     *
995
-     * @return string
996
-     * @throws EE_Error
997
-     */
998
-    public function get_admin_edit_url()
999
-    {
1000
-        return EEH_URL::add_query_args_and_nonce(
1001
-            array(
1002
-                'page'    => 'espresso_registrations',
1003
-                'action'  => 'view_registration',
1004
-                '_REG_ID' => $this->ID(),
1005
-            ),
1006
-            admin_url('admin.php')
1007
-        );
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     *    is_primary_registrant?
1013
-     */
1014
-    public function is_primary_registrant()
1015
-    {
1016
-        return $this->get('REG_count') === 1 ? true : false;
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * This returns the primary registration object for this registration group (which may be this object).
1022
-     *
1023
-     * @return EE_Registration
1024
-     * @throws EE_Error
1025
-     */
1026
-    public function get_primary_registration()
1027
-    {
1028
-        if ($this->is_primary_registrant()) {
1029
-            return $this;
1030
-        }
1031
-
1032
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1033
-        /** @var EE_Registration $primary_registrant */
1034
-        $primary_registrant = EEM_Registration::instance()->get_one(
1035
-            array(
1036
-                array(
1037
-                    'TXN_ID'    => $this->transaction_ID(),
1038
-                    'REG_count' => 1,
1039
-                ),
1040
-            )
1041
-        );
1042
-        return $primary_registrant;
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     *        get  Attendee Number
1048
-     *
1049
-     * @access        public
1050
-     */
1051
-    public function count()
1052
-    {
1053
-        return $this->get('REG_count');
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     *        get Group Size
1059
-     */
1060
-    public function group_size()
1061
-    {
1062
-        return $this->get('REG_group_size');
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     *        get Registration Date
1068
-     */
1069
-    public function date()
1070
-    {
1071
-        return $this->get('REG_date');
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * gets a pretty date
1077
-     *
1078
-     * @param string $date_format
1079
-     * @param string $time_format
1080
-     * @return string
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function pretty_date($date_format = null, $time_format = null)
1084
-    {
1085
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * final_price
1091
-     * the registration's share of the transaction total, so that the
1092
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1093
-     *
1094
-     * @return float
1095
-     * @throws EE_Error
1096
-     */
1097
-    public function final_price()
1098
-    {
1099
-        return $this->get('REG_final_price');
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * pretty_final_price
1105
-     *  final price as formatted string, with correct decimal places and currency symbol
1106
-     *
1107
-     * @return string
1108
-     * @throws EE_Error
1109
-     */
1110
-    public function pretty_final_price()
1111
-    {
1112
-        return $this->get_pretty('REG_final_price');
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * get paid (yeah)
1118
-     *
1119
-     * @return float
1120
-     * @throws EE_Error
1121
-     */
1122
-    public function paid()
1123
-    {
1124
-        return $this->get('REG_paid');
1125
-    }
1126
-
1127
-
1128
-    /**
1129
-     * pretty_paid
1130
-     *
1131
-     * @return float
1132
-     * @throws EE_Error
1133
-     */
1134
-    public function pretty_paid()
1135
-    {
1136
-        return $this->get_pretty('REG_paid');
1137
-    }
1138
-
1139
-
1140
-    /**
1141
-     * owes_monies_and_can_pay
1142
-     * whether or not this registration has monies owing and it's' status allows payment
1143
-     *
1144
-     * @param array $requires_payment
1145
-     * @return bool
1146
-     * @throws EE_Error
1147
-     */
1148
-    public function owes_monies_and_can_pay($requires_payment = array())
1149
-    {
1150
-        // these reg statuses require payment (if event is not free)
1151
-        $requires_payment = ! empty($requires_payment)
1152
-            ? $requires_payment
1153
-            : EEM_Registration::reg_statuses_that_allow_payment();
1154
-        if (in_array($this->status_ID(), $requires_payment) &&
1155
-            $this->final_price() != 0 &&
1156
-            $this->final_price() != $this->paid()
1157
-        ) {
1158
-            return true;
1159
-        } else {
1160
-            return false;
1161
-        }
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Prints out the return value of $this->pretty_status()
1167
-     *
1168
-     * @param bool $show_icons
1169
-     * @return void
1170
-     * @throws EE_Error
1171
-     */
1172
-    public function e_pretty_status($show_icons = false)
1173
-    {
1174
-        echo $this->pretty_status($show_icons);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Returns a nice version of the status for displaying to customers
1180
-     *
1181
-     * @param bool $show_icons
1182
-     * @return string
1183
-     * @throws EE_Error
1184
-     */
1185
-    public function pretty_status($show_icons = false)
1186
-    {
1187
-        $status = EEM_Status::instance()->localized_status(
1188
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1189
-            false,
1190
-            'sentence'
1191
-        );
1192
-        $icon = '';
1193
-        switch ($this->status_ID()) {
1194
-            case EEM_Registration::status_id_approved:
1195
-                $icon = $show_icons
1196
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1197
-                    : '';
1198
-                break;
1199
-            case EEM_Registration::status_id_pending_payment:
1200
-                $icon = $show_icons
1201
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1202
-                    : '';
1203
-                break;
1204
-            case EEM_Registration::status_id_not_approved:
1205
-                $icon = $show_icons
1206
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1207
-                    : '';
1208
-                break;
1209
-            case EEM_Registration::status_id_cancelled:
1210
-                $icon = $show_icons
1211
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1212
-                    : '';
1213
-                break;
1214
-            case EEM_Registration::status_id_incomplete:
1215
-                $icon = $show_icons
1216
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1217
-                    : '';
1218
-                break;
1219
-            case EEM_Registration::status_id_declined:
1220
-                $icon = $show_icons
1221
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1222
-                    : '';
1223
-                break;
1224
-            case EEM_Registration::status_id_wait_list:
1225
-                $icon = $show_icons
1226
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1227
-                    : '';
1228
-                break;
1229
-        }
1230
-        return $icon . $status[ $this->status_ID() ];
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     *        get Attendee Is Going
1236
-     */
1237
-    public function att_is_going()
1238
-    {
1239
-        return $this->get('REG_att_is_going');
1240
-    }
1241
-
1242
-
1243
-    /**
1244
-     * Gets related answers
1245
-     *
1246
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1247
-     * @return EE_Answer[]
1248
-     * @throws EE_Error
1249
-     */
1250
-    public function answers($query_params = null)
1251
-    {
1252
-        return $this->get_many_related('Answer', $query_params);
1253
-    }
1254
-
1255
-
1256
-    /**
1257
-     * Gets the registration's answer value to the specified question
1258
-     * (either the question's ID or a question object)
1259
-     *
1260
-     * @param EE_Question|int $question
1261
-     * @param bool            $pretty_value
1262
-     * @return array|string if pretty_value= true, the result will always be a string
1263
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1264
-     * will convert it into some kind of string)
1265
-     * @throws EE_Error
1266
-     */
1267
-    public function answer_value_to_question($question, $pretty_value = true)
1268
-    {
1269
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1270
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * question_groups
1276
-     * returns an array of EE_Question_Group objects for this registration
1277
-     *
1278
-     * @return EE_Question_Group[]
1279
-     * @throws EE_Error
1280
-     * @throws InvalidArgumentException
1281
-     * @throws InvalidDataTypeException
1282
-     * @throws InvalidInterfaceException
1283
-     * @throws ReflectionException
1284
-     */
1285
-    public function question_groups()
1286
-    {
1287
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * count_question_groups
1293
-     * returns a count of the number of EE_Question_Group objects for this registration
1294
-     *
1295
-     * @return int
1296
-     * @throws EE_Error
1297
-     * @throws EntityNotFoundException
1298
-     * @throws InvalidArgumentException
1299
-     * @throws InvalidDataTypeException
1300
-     * @throws InvalidInterfaceException
1301
-     * @throws ReflectionException
1302
-     */
1303
-    public function count_question_groups()
1304
-    {
1305
-        return EEM_Event::instance()->count_related(
1306
-            $this->event_ID(),
1307
-            'Question_Group',
1308
-            [
1309
-                [
1310
-                    'Event_Question_Group.'
1311
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1312
-                ]
1313
-            ]
1314
-        );
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * Returns the registration date in the 'standard' string format
1320
-     * (function may be improved in the future to allow for different formats and timezones)
1321
-     *
1322
-     * @return string
1323
-     * @throws EE_Error
1324
-     */
1325
-    public function reg_date()
1326
-    {
1327
-        return $this->get_datetime('REG_date');
1328
-    }
1329
-
1330
-
1331
-    /**
1332
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1333
-     * the ticket this registration purchased, or the datetime they have registered
1334
-     * to attend)
1335
-     *
1336
-     * @return EE_Datetime_Ticket
1337
-     * @throws EE_Error
1338
-     */
1339
-    public function datetime_ticket()
1340
-    {
1341
-        return $this->get_first_related('Datetime_Ticket');
1342
-    }
1343
-
1344
-
1345
-    /**
1346
-     * Sets the registration's datetime_ticket.
1347
-     *
1348
-     * @param EE_Datetime_Ticket $datetime_ticket
1349
-     * @return EE_Datetime_Ticket
1350
-     * @throws EE_Error
1351
-     */
1352
-    public function set_datetime_ticket($datetime_ticket)
1353
-    {
1354
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1355
-    }
1356
-
1357
-    /**
1358
-     * Gets deleted
1359
-     *
1360
-     * @return bool
1361
-     * @throws EE_Error
1362
-     */
1363
-    public function deleted()
1364
-    {
1365
-        return $this->get('REG_deleted');
1366
-    }
1367
-
1368
-    /**
1369
-     * Sets deleted
1370
-     *
1371
-     * @param boolean $deleted
1372
-     * @return bool
1373
-     * @throws EE_Error
1374
-     * @throws RuntimeException
1375
-     */
1376
-    public function set_deleted($deleted)
1377
-    {
1378
-        if ($deleted) {
1379
-            $this->delete();
1380
-        } else {
1381
-            $this->restore();
1382
-        }
1383
-    }
1384
-
1385
-
1386
-    /**
1387
-     * Get the status object of this object
1388
-     *
1389
-     * @return EE_Status
1390
-     * @throws EE_Error
1391
-     */
1392
-    public function status_obj()
1393
-    {
1394
-        return $this->get_first_related('Status');
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * Returns the number of times this registration has checked into any of the datetimes
1400
-     * its available for
1401
-     *
1402
-     * @return int
1403
-     * @throws EE_Error
1404
-     */
1405
-    public function count_checkins()
1406
-    {
1407
-        return $this->get_model()->count_related($this, 'Checkin');
1408
-    }
1409
-
1410
-
1411
-    /**
1412
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1413
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1414
-     *
1415
-     * @return int
1416
-     * @throws EE_Error
1417
-     */
1418
-    public function count_checkins_not_checkedout()
1419
-    {
1420
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1426
-     *
1427
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1428
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1429
-     *                                          consider registration status as well as datetime access.
1430
-     * @return bool
1431
-     * @throws EE_Error
1432
-     */
1433
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1434
-    {
1435
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1436
-
1437
-        // first check registration status
1438
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1439
-            return false;
1440
-        }
1441
-        // is there a datetime ticket that matches this dtt_ID?
1442
-        if (! (EEM_Datetime_Ticket::instance()->exists(
1443
-            array(
1444
-                array(
1445
-                    'TKT_ID' => $this->get('TKT_ID'),
1446
-                    'DTT_ID' => $DTT_ID,
1447
-                ),
1448
-            )
1449
-        ))
1450
-        ) {
1451
-            return false;
1452
-        }
1453
-
1454
-        // final check is against TKT_uses
1455
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1461
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1462
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1463
-     * then return false.  Otherwise return true.
1464
-     *
1465
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1466
-     * @return bool true means can checkin.  false means cannot checkin.
1467
-     * @throws EE_Error
1468
-     */
1469
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1470
-    {
1471
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1472
-
1473
-        if (! $DTT_ID) {
1474
-            return false;
1475
-        }
1476
-
1477
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1478
-
1479
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1480
-        // check-in or not.
1481
-        if (! $max_uses || $max_uses === EE_INF) {
1482
-            return true;
1483
-        }
1484
-
1485
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1486
-        // go ahead and toggle.
1487
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1488
-            return true;
1489
-        }
1490
-
1491
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1492
-        // disallows further check-ins.
1493
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1494
-            array(
1495
-                array(
1496
-                    'REG_ID' => $this->ID(),
1497
-                    'CHK_in' => true,
1498
-                ),
1499
-            ),
1500
-            'DTT_ID',
1501
-            true
1502
-        );
1503
-        // checkins have already reached their max number of uses
1504
-        // so registrant can NOT checkin
1505
-        if ($count_unique_dtt_checkins >= $max_uses) {
1506
-            EE_Error::add_error(
1507
-                esc_html__(
1508
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1509
-                    'event_espresso'
1510
-                ),
1511
-                __FILE__,
1512
-                __FUNCTION__,
1513
-                __LINE__
1514
-            );
1515
-            return false;
1516
-        }
1517
-        return true;
1518
-    }
1519
-
1520
-
1521
-    /**
1522
-     * toggle Check-in status for this registration
1523
-     * Check-ins are toggled in the following order:
1524
-     * never checked in -> checked in
1525
-     * checked in -> checked out
1526
-     * checked out -> checked in
1527
-     *
1528
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1529
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1530
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1531
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1532
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1533
-     * @throws EE_Error
1534
-     */
1535
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1536
-    {
1537
-        if (empty($DTT_ID)) {
1538
-            $datetime = $this->get_latest_related_datetime();
1539
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1540
-            // verify the registration can checkin for the given DTT_ID
1541
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1542
-            EE_Error::add_error(
1543
-                sprintf(
1544
-                    esc_html__(
1545
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1546
-                        'event_espresso'
1547
-                    ),
1548
-                    $this->ID(),
1549
-                    $DTT_ID
1550
-                ),
1551
-                __FILE__,
1552
-                __FUNCTION__,
1553
-                __LINE__
1554
-            );
1555
-            return false;
1556
-        }
1557
-        $status_paths = array(
1558
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1559
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1560
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1561
-        );
1562
-        // start by getting the current status so we know what status we'll be changing to.
1563
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1564
-        $status_to = $status_paths[ $cur_status ];
1565
-        // database only records true for checked IN or false for checked OUT
1566
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1567
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1568
-        // add relation - note Check-ins are always creating new rows
1569
-        // because we are keeping track of Check-ins over time.
1570
-        // Eventually we'll probably want to show a list table
1571
-        // for the individual Check-ins so that they can be managed.
1572
-        $checkin = EE_Checkin::new_instance(
1573
-            array(
1574
-                'REG_ID' => $this->ID(),
1575
-                'DTT_ID' => $DTT_ID,
1576
-                'CHK_in' => $new_status,
1577
-            )
1578
-        );
1579
-        // if the record could not be saved then return false
1580
-        if ($checkin->save() === 0) {
1581
-            if (WP_DEBUG) {
1582
-                global $wpdb;
1583
-                $error = sprintf(
1584
-                    esc_html__(
1585
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1586
-                        'event_espresso'
1587
-                    ),
1588
-                    '<br />',
1589
-                    $wpdb->last_error
1590
-                );
1591
-            } else {
1592
-                $error = esc_html__(
1593
-                    'Registration check in update failed because of an unknown database error',
1594
-                    'event_espresso'
1595
-                );
1596
-            }
1597
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1598
-            return false;
1599
-        }
1600
-        // Fire a checked_in and checkout_out action.
1601
-        $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1602
-        do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1603
-        return $status_to;
1604
-    }
1605
-
1606
-
1607
-    /**
1608
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1609
-     * "Latest" is defined by the `DTT_EVT_start` column.
1610
-     *
1611
-     * @return EE_Datetime|null
1612
-     * @throws EE_Error
1613
-     */
1614
-    public function get_latest_related_datetime()
1615
-    {
1616
-        return EEM_Datetime::instance()->get_one(
1617
-            array(
1618
-                array(
1619
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1620
-                ),
1621
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1622
-            )
1623
-        );
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1629
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1630
-     *
1631
-     * @throws EE_Error
1632
-     */
1633
-    public function get_earliest_related_datetime()
1634
-    {
1635
-        return EEM_Datetime::instance()->get_one(
1636
-            array(
1637
-                array(
1638
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1639
-                ),
1640
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1641
-            )
1642
-        );
1643
-    }
1644
-
1645
-
1646
-    /**
1647
-     * This method simply returns the check-in status for this registration and the given datetime.
1648
-     * If neither the datetime nor the checkin values are provided as arguments,
1649
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1650
-     *
1651
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1652
-     *                            (if empty we'll get the primary datetime for
1653
-     *                            this registration (via event) and use it's ID);
1654
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1655
-     *
1656
-     * @return int                Integer representing Check-in status.
1657
-     * @throws EE_Error
1658
-     */
1659
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1660
-    {
1661
-        $checkin_query_params = array(
1662
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1663
-        );
1664
-
1665
-        if ($DTT_ID > 0) {
1666
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1667
-        }
1668
-
1669
-        // get checkin object (if exists)
1670
-        $checkin = $checkin instanceof EE_Checkin
1671
-            ? $checkin
1672
-            : $this->get_first_related('Checkin', $checkin_query_params);
1673
-        if ($checkin instanceof EE_Checkin) {
1674
-            if ($checkin->get('CHK_in')) {
1675
-                return EE_Checkin::status_checked_in; // checked in
1676
-            }
1677
-            return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1678
-        }
1679
-        return EE_Checkin::status_checked_never; // never been checked in
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * This method returns a localized message for the toggled Check-in message.
1685
-     *
1686
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1687
-     *                     then it is assumed Check-in for primary datetime was toggled.
1688
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1689
-     *                     message can be customized with the attendee name.
1690
-     * @return string internationalized message
1691
-     * @throws EE_Error
1692
-     */
1693
-    public function get_checkin_msg($DTT_ID, $error = false)
1694
-    {
1695
-        // let's get the attendee first so we can include the name of the attendee
1696
-        $attendee = $this->get_first_related('Attendee');
1697
-        if ($attendee instanceof EE_Attendee) {
1698
-            if ($error) {
1699
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1700
-            }
1701
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1702
-            // what is the status message going to be?
1703
-            switch ($cur_status) {
1704
-                case EE_Checkin::status_checked_never:
1705
-                    return sprintf(
1706
-                        __("%s has been removed from Check-in records", "event_espresso"),
1707
-                        $attendee->full_name()
1708
-                    );
1709
-                    break;
1710
-                case EE_Checkin::status_checked_in:
1711
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1712
-                    break;
1713
-                case EE_Checkin::status_checked_out:
1714
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1715
-                    break;
1716
-            }
1717
-        }
1718
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * Returns the related EE_Transaction to this registration
1724
-     *
1725
-     * @return EE_Transaction
1726
-     * @throws EE_Error
1727
-     * @throws EntityNotFoundException
1728
-     */
1729
-    public function transaction()
1730
-    {
1731
-        $transaction = $this->get_first_related('Transaction');
1732
-        if (! $transaction instanceof \EE_Transaction) {
1733
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1734
-        }
1735
-        return $transaction;
1736
-    }
1737
-
1738
-
1739
-    /**
1740
-     *        get Registration Code
1741
-     */
1742
-    public function reg_code()
1743
-    {
1744
-        return $this->get('REG_code');
1745
-    }
1746
-
1747
-
1748
-    /**
1749
-     *        get Transaction ID
1750
-     */
1751
-    public function transaction_ID()
1752
-    {
1753
-        return $this->get('TXN_ID');
1754
-    }
1755
-
1756
-
1757
-    /**
1758
-     * @return int
1759
-     * @throws EE_Error
1760
-     */
1761
-    public function ticket_ID()
1762
-    {
1763
-        return $this->get('TKT_ID');
1764
-    }
1765
-
1766
-
1767
-    /**
1768
-     *        Set Registration Code
1769
-     *
1770
-     * @access    public
1771
-     * @param    string  $REG_code Registration Code
1772
-     * @param    boolean $use_default
1773
-     * @throws EE_Error
1774
-     */
1775
-    public function set_reg_code($REG_code, $use_default = false)
1776
-    {
1777
-        if (empty($REG_code)) {
1778
-            EE_Error::add_error(
1779
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1780
-                __FILE__,
1781
-                __FUNCTION__,
1782
-                __LINE__
1783
-            );
1784
-            return;
1785
-        }
1786
-        if (! $this->reg_code()) {
1787
-            parent::set('REG_code', $REG_code, $use_default);
1788
-        } else {
1789
-            EE_Error::doing_it_wrong(
1790
-                __CLASS__ . '::' . __FUNCTION__,
1791
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1792
-                '4.6.0'
1793
-            );
1794
-        }
1795
-    }
1796
-
1797
-
1798
-    /**
1799
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1800
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1801
-     *    $registration->transaction()->registrations();
1802
-     *
1803
-     * @since 4.5.0
1804
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1805
-     * @throws EE_Error
1806
-     */
1807
-    public function get_all_other_registrations_in_group()
1808
-    {
1809
-        if ($this->group_size() < 2) {
1810
-            return array();
1811
-        }
1812
-
1813
-        $query[0] = array(
1814
-            'TXN_ID' => $this->transaction_ID(),
1815
-            'REG_ID' => array('!=', $this->ID()),
1816
-            'TKT_ID' => $this->ticket_ID(),
1817
-        );
1818
-        /** @var EE_Registration[] $registrations */
1819
-        $registrations = $this->get_model()->get_all($query);
1820
-        return $registrations;
1821
-    }
1822
-
1823
-    /**
1824
-     * Return the link to the admin details for the object.
1825
-     *
1826
-     * @return string
1827
-     * @throws EE_Error
1828
-     */
1829
-    public function get_admin_details_link()
1830
-    {
1831
-        EE_Registry::instance()->load_helper('URL');
1832
-        return EEH_URL::add_query_args_and_nonce(
1833
-            array(
1834
-                'page'    => 'espresso_registrations',
1835
-                'action'  => 'view_registration',
1836
-                '_REG_ID' => $this->ID(),
1837
-            ),
1838
-            admin_url('admin.php')
1839
-        );
1840
-    }
1841
-
1842
-    /**
1843
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1844
-     *
1845
-     * @return string
1846
-     * @throws EE_Error
1847
-     */
1848
-    public function get_admin_edit_link()
1849
-    {
1850
-        return $this->get_admin_details_link();
1851
-    }
1852
-
1853
-    /**
1854
-     * Returns the link to a settings page for the object.
1855
-     *
1856
-     * @return string
1857
-     * @throws EE_Error
1858
-     */
1859
-    public function get_admin_settings_link()
1860
-    {
1861
-        return $this->get_admin_details_link();
1862
-    }
1863
-
1864
-    /**
1865
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1866
-     *
1867
-     * @return string
1868
-     */
1869
-    public function get_admin_overview_link()
1870
-    {
1871
-        EE_Registry::instance()->load_helper('URL');
1872
-        return EEH_URL::add_query_args_and_nonce(
1873
-            array(
1874
-                'page' => 'espresso_registrations',
1875
-            ),
1876
-            admin_url('admin.php')
1877
-        );
1878
-    }
1879
-
1880
-
1881
-    /**
1882
-     * @param array $query_params
1883
-     *
1884
-     * @return \EE_Registration[]
1885
-     * @throws EE_Error
1886
-     */
1887
-    public function payments($query_params = array())
1888
-    {
1889
-        return $this->get_many_related('Payment', $query_params);
1890
-    }
1891
-
1892
-
1893
-    /**
1894
-     * @param array $query_params
1895
-     *
1896
-     * @return \EE_Registration_Payment[]
1897
-     * @throws EE_Error
1898
-     */
1899
-    public function registration_payments($query_params = array())
1900
-    {
1901
-        return $this->get_many_related('Registration_Payment', $query_params);
1902
-    }
1903
-
1904
-
1905
-    /**
1906
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1907
-     * Note: if there are no payments on the registration there will be no payment method returned.
1908
-     *
1909
-     * @return EE_Payment_Method|null
1910
-     */
1911
-    public function payment_method()
1912
-    {
1913
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1914
-    }
1915
-
1916
-
1917
-    /**
1918
-     * @return \EE_Line_Item
1919
-     * @throws EntityNotFoundException
1920
-     * @throws EE_Error
1921
-     */
1922
-    public function ticket_line_item()
1923
-    {
1924
-        $ticket = $this->ticket();
1925
-        $transaction = $this->transaction();
1926
-        $line_item = null;
1927
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1928
-            $transaction->total_line_item(),
1929
-            'Ticket',
1930
-            array($ticket->ID())
1931
-        );
1932
-        foreach ($ticket_line_items as $ticket_line_item) {
1933
-            if ($ticket_line_item instanceof \EE_Line_Item
1934
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1935
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1936
-            ) {
1937
-                $line_item = $ticket_line_item;
1938
-                break;
1939
-            }
1940
-        }
1941
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1942
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1943
-        }
1944
-        return $line_item;
1945
-    }
1946
-
1947
-
1948
-    /**
1949
-     * Soft Deletes this model object.
1950
-     *
1951
-     * @return boolean | int
1952
-     * @throws RuntimeException
1953
-     * @throws EE_Error
1954
-     */
1955
-    public function delete()
1956
-    {
1957
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1958
-            $this->set_status(EEM_Registration::status_id_cancelled);
1959
-        }
1960
-        return parent::delete();
1961
-    }
1962
-
1963
-
1964
-    /**
1965
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1966
-     *
1967
-     * @throws EE_Error
1968
-     * @throws RuntimeException
1969
-     */
1970
-    public function restore()
1971
-    {
1972
-        $previous_status = $this->get_extra_meta(
1973
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1974
-            true,
1975
-            EEM_Registration::status_id_cancelled
1976
-        );
1977
-        if ($previous_status) {
1978
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1979
-            $this->set_status($previous_status);
1980
-        }
1981
-        return parent::restore();
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1987
-     *
1988
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1989
-     *                                           depending on whether the reg status changes to or from "Approved"
1990
-     * @return boolean whether the Registration status was updated
1991
-     * @throws EE_Error
1992
-     * @throws RuntimeException
1993
-     */
1994
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1995
-    {
1996
-        $paid = $this->paid();
1997
-        $price = $this->final_price();
1998
-        switch (true) {
1999
-            // overpaid or paid
2000
-            case EEH_Money::compare_floats($paid, $price, '>'):
2001
-            case EEH_Money::compare_floats($paid, $price):
2002
-                $new_status = EEM_Registration::status_id_approved;
2003
-                break;
2004
-            //  underpaid
2005
-            case EEH_Money::compare_floats($paid, $price, '<'):
2006
-                $new_status = EEM_Registration::status_id_pending_payment;
2007
-                break;
2008
-            // uhhh Houston...
2009
-            default:
2010
-                throw new RuntimeException(
2011
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2012
-                );
2013
-        }
2014
-        if ($new_status !== $this->status_ID()) {
2015
-            if ($trigger_set_status_logic) {
2016
-                return $this->set_status($new_status);
2017
-            }
2018
-            parent::set('STS_ID', $new_status);
2019
-            return true;
2020
-        }
2021
-        return false;
2022
-    }
2023
-
2024
-
2025
-    /*************************** DEPRECATED ***************************/
2026
-
2027
-
2028
-    /**
2029
-     * @deprecated
2030
-     * @since     4.7.0
2031
-     * @access    public
2032
-     */
2033
-    public function price_paid()
2034
-    {
2035
-        EE_Error::doing_it_wrong(
2036
-            'EE_Registration::price_paid()',
2037
-            esc_html__(
2038
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2039
-                'event_espresso'
2040
-            ),
2041
-            '4.7.0'
2042
-        );
2043
-        return $this->final_price();
2044
-    }
2045
-
2046
-
2047
-    /**
2048
-     * @deprecated
2049
-     * @since     4.7.0
2050
-     * @access    public
2051
-     * @param    float $REG_final_price
2052
-     * @throws EE_Error
2053
-     * @throws RuntimeException
2054
-     */
2055
-    public function set_price_paid($REG_final_price = 0.00)
2056
-    {
2057
-        EE_Error::doing_it_wrong(
2058
-            'EE_Registration::set_price_paid()',
2059
-            esc_html__(
2060
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2061
-                'event_espresso'
2062
-            ),
2063
-            '4.7.0'
2064
-        );
2065
-        $this->set_final_price($REG_final_price);
2066
-    }
2067
-
2068
-
2069
-    /**
2070
-     * @deprecated
2071
-     * @since 4.7.0
2072
-     * @return string
2073
-     * @throws EE_Error
2074
-     */
2075
-    public function pretty_price_paid()
2076
-    {
2077
-        EE_Error::doing_it_wrong(
2078
-            'EE_Registration::pretty_price_paid()',
2079
-            esc_html__(
2080
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2081
-                'event_espresso'
2082
-            ),
2083
-            '4.7.0'
2084
-        );
2085
-        return $this->pretty_final_price();
2086
-    }
2087
-
2088
-
2089
-    /**
2090
-     * Gets the primary datetime related to this registration via the related Event to this registration
2091
-     *
2092
-     * @deprecated 4.9.17
2093
-     * @return EE_Datetime
2094
-     * @throws EE_Error
2095
-     * @throws EntityNotFoundException
2096
-     */
2097
-    public function get_related_primary_datetime()
2098
-    {
2099
-        EE_Error::doing_it_wrong(
2100
-            __METHOD__,
2101
-            esc_html__(
2102
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2103
-                'event_espresso'
2104
-            ),
2105
-            '4.9.17',
2106
-            '5.0.0'
2107
-        );
2108
-        return $this->event()->primary_datetime();
2109
-    }
2110
-
2111
-    /**
2112
-     * Returns the contact's name (or "Unknown" if there is no contact.)
2113
-     * @since $VID:$
2114
-     * @return string
2115
-     * @throws EE_Error
2116
-     * @throws InvalidArgumentException
2117
-     * @throws InvalidDataTypeException
2118
-     * @throws InvalidInterfaceException
2119
-     * @throws ReflectionException
2120
-     */
2121
-    public function name()
2122
-    {
2123
-        return $this->attendeeName();
2124
-    }
20
+	/**
21
+	 * Used to reference when a registration has never been checked in.
22
+	 *
23
+	 * @deprecated use \EE_Checkin::status_checked_never instead
24
+	 * @type int
25
+	 */
26
+	const checkin_status_never = 2;
27
+
28
+	/**
29
+	 * Used to reference when a registration has been checked in.
30
+	 *
31
+	 * @deprecated use \EE_Checkin::status_checked_in instead
32
+	 * @type int
33
+	 */
34
+	const checkin_status_in = 1;
35
+
36
+
37
+	/**
38
+	 * Used to reference when a registration has been checked out.
39
+	 *
40
+	 * @deprecated use \EE_Checkin::status_checked_out instead
41
+	 * @type int
42
+	 */
43
+	const checkin_status_out = 0;
44
+
45
+
46
+	/**
47
+	 * extra meta key for tracking reg status os trashed registrations
48
+	 *
49
+	 * @type string
50
+	 */
51
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
+
53
+
54
+	/**
55
+	 * extra meta key for tracking if registration has reserved ticket
56
+	 *
57
+	 * @type string
58
+	 */
59
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values          incoming values
64
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
+	 *                                        used.)
66
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
+	 *                                        date_format and the second value is the time format
68
+	 * @return EE_Registration
69
+	 * @throws EE_Error
70
+	 */
71
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
+	{
73
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Registration
83
+	 */
84
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
+	{
86
+		return new self($props_n_values, true, $timezone);
87
+	}
88
+
89
+
90
+	/**
91
+	 *        Set Event ID
92
+	 *
93
+	 * @param        int $EVT_ID Event ID
94
+	 * @throws EE_Error
95
+	 * @throws RuntimeException
96
+	 */
97
+	public function set_event($EVT_ID = 0)
98
+	{
99
+		$this->set('EVT_ID', $EVT_ID);
100
+	}
101
+
102
+
103
+	/**
104
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
+	 * be routed to internal methods
106
+	 *
107
+	 * @param string $field_name
108
+	 * @param mixed  $field_value
109
+	 * @param bool   $use_default
110
+	 * @throws EE_Error
111
+	 * @throws EntityNotFoundException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws ReflectionException
116
+	 * @throws RuntimeException
117
+	 */
118
+	public function set($field_name, $field_value, $use_default = false)
119
+	{
120
+		switch ($field_name) {
121
+			case 'REG_code':
122
+				if (! empty($field_value) && $this->reg_code() === null) {
123
+					$this->set_reg_code($field_value, $use_default);
124
+				}
125
+				break;
126
+			case 'STS_ID':
127
+				$this->set_status($field_value, $use_default);
128
+				break;
129
+			default:
130
+				parent::set($field_name, $field_value, $use_default);
131
+		}
132
+	}
133
+
134
+
135
+	/**
136
+	 * Set Status ID
137
+	 * updates the registration status and ALSO...
138
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
+	 *
141
+	 * @param string                $new_STS_ID
142
+	 * @param boolean               $use_default
143
+	 * @param ContextInterface|null $context
144
+	 * @return bool
145
+	 * @throws DomainException
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidInterfaceException
151
+	 * @throws ReflectionException
152
+	 * @throws RuntimeException
153
+	 * @throws UnexpectedEntityException
154
+	 */
155
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
+	{
157
+		// get current REG_Status
158
+		$old_STS_ID = $this->status_ID();
159
+		// if status has changed
160
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
+			&& ! empty($old_STS_ID) // and that old status is actually set
162
+			&& ! empty($new_STS_ID) // as well as the new status
163
+			&& $this->ID() // ensure registration is in the db
164
+		) {
165
+			// update internal status first
166
+			parent::set('STS_ID', $new_STS_ID, $use_default);
167
+			// THEN handle other changes that occur when reg status changes
168
+			// TO approved
169
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
+				// reserve a space by incrementing ticket and datetime sold values
171
+				$this->reserveRegistrationSpace();
172
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
+				// OR FROM  approved
174
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
+				// release a space by decrementing ticket and datetime sold values
176
+				$this->releaseRegistrationSpace();
177
+				do_action(
178
+					'AHEE__EE_Registration__set_status__from_approved',
179
+					$this,
180
+					$old_STS_ID,
181
+					$new_STS_ID,
182
+					$context
183
+				);
184
+			}
185
+			// update status
186
+			parent::set('STS_ID', $new_STS_ID, $use_default);
187
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
+			if ($this->statusChangeUpdatesTransaction($context)) {
189
+				$this->updateTransactionAfterStatusChange();
190
+			}
191
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
+			return true;
193
+		}
194
+		// even though the old value matches the new value, it's still good to
195
+		// allow the parent set method to have a say
196
+		parent::set('STS_ID', $new_STS_ID, $use_default);
197
+		return true;
198
+	}
199
+
200
+
201
+	/**
202
+	 * update REGs and TXN when cancelled or declined registrations involved
203
+	 *
204
+	 * @param string                $new_STS_ID
205
+	 * @param string                $old_STS_ID
206
+	 * @param ContextInterface|null $context
207
+	 * @throws EE_Error
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 * @throws ReflectionException
212
+	 * @throws RuntimeException
213
+	 */
214
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
+	{
216
+		// these reg statuses should not be considered in any calculations involving monies owing
217
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
+		// true if registration has been cancelled or declined
219
+		$this->updateIfCanceled(
220
+			$closed_reg_statuses,
221
+			$new_STS_ID,
222
+			$old_STS_ID,
223
+			$context
224
+		);
225
+		$this->updateIfReinstated(
226
+			$closed_reg_statuses,
227
+			$new_STS_ID,
228
+			$old_STS_ID,
229
+			$context
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 * update REGs and TXN when cancelled or declined registrations involved
236
+	 *
237
+	 * @param array                 $closed_reg_statuses
238
+	 * @param string                $new_STS_ID
239
+	 * @param string                $old_STS_ID
240
+	 * @param ContextInterface|null $context
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws InvalidDataTypeException
244
+	 * @throws InvalidInterfaceException
245
+	 * @throws ReflectionException
246
+	 * @throws RuntimeException
247
+	 */
248
+	private function updateIfCanceled(
249
+		array $closed_reg_statuses,
250
+		$new_STS_ID,
251
+		$old_STS_ID,
252
+		ContextInterface $context = null
253
+	) {
254
+		// true if registration has been cancelled or declined
255
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
+		) {
258
+			/** @type EE_Registration_Processor $registration_processor */
259
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
+			/** @type EE_Transaction_Processor $transaction_processor */
261
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
+			// cancelled or declined registration
263
+			$registration_processor->update_registration_after_being_canceled_or_declined(
264
+				$this,
265
+				$closed_reg_statuses
266
+			);
267
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
+				$this,
269
+				$closed_reg_statuses,
270
+				false
271
+			);
272
+			do_action(
273
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
274
+				$this,
275
+				$old_STS_ID,
276
+				$new_STS_ID,
277
+				$context
278
+			);
279
+			return;
280
+		}
281
+	}
282
+
283
+
284
+	/**
285
+	 * update REGs and TXN when cancelled or declined registrations involved
286
+	 *
287
+	 * @param array                 $closed_reg_statuses
288
+	 * @param string                $new_STS_ID
289
+	 * @param string                $old_STS_ID
290
+	 * @param ContextInterface|null $context
291
+	 * @throws EE_Error
292
+	 * @throws InvalidArgumentException
293
+	 * @throws InvalidDataTypeException
294
+	 * @throws InvalidInterfaceException
295
+	 * @throws ReflectionException
296
+	 */
297
+	private function updateIfReinstated(
298
+		array $closed_reg_statuses,
299
+		$new_STS_ID,
300
+		$old_STS_ID,
301
+		ContextInterface $context = null
302
+	) {
303
+		// true if reinstating cancelled or declined registration
304
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
+		) {
307
+			/** @type EE_Registration_Processor $registration_processor */
308
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
+			/** @type EE_Transaction_Processor $transaction_processor */
310
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
+			// reinstating cancelled or declined registration
312
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
+				$this,
314
+				$closed_reg_statuses
315
+			);
316
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
+				$this,
318
+				$closed_reg_statuses,
319
+				false
320
+			);
321
+			do_action(
322
+				'AHEE__EE_Registration__set_status__after_reinstated',
323
+				$this,
324
+				$old_STS_ID,
325
+				$new_STS_ID,
326
+				$context
327
+			);
328
+		}
329
+	}
330
+
331
+
332
+	/**
333
+	 * @param ContextInterface|null $context
334
+	 * @return bool
335
+	 */
336
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
+	{
338
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
339
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
+			array('spco_reg_step_attendee_information_process_registrations'),
341
+			$context,
342
+			$this
343
+		);
344
+		return ! (
345
+			$context instanceof ContextInterface
346
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
+		);
348
+	}
349
+
350
+
351
+	/**
352
+	 * @throws EE_Error
353
+	 * @throws EntityNotFoundException
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws InvalidInterfaceException
357
+	 * @throws ReflectionException
358
+	 * @throws RuntimeException
359
+	 */
360
+	private function updateTransactionAfterStatusChange()
361
+	{
362
+		/** @type EE_Transaction_Payments $transaction_payments */
363
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
+		$this->transaction()->update_status_based_on_total_paid(true);
366
+	}
367
+
368
+
369
+	/**
370
+	 *        get Status ID
371
+	 */
372
+	public function status_ID()
373
+	{
374
+		return $this->get('STS_ID');
375
+	}
376
+
377
+
378
+	/**
379
+	 * Gets the ticket this registration is for
380
+	 *
381
+	 * @param boolean $include_archived whether to include archived tickets or not.
382
+	 *
383
+	 * @return EE_Ticket|EE_Base_Class
384
+	 * @throws EE_Error
385
+	 */
386
+	public function ticket($include_archived = true)
387
+	{
388
+		$query_params = array();
389
+		if ($include_archived) {
390
+			$query_params['default_where_conditions'] = 'none';
391
+		}
392
+		return $this->get_first_related('Ticket', $query_params);
393
+	}
394
+
395
+
396
+	/**
397
+	 * Gets the event this registration is for
398
+	 *
399
+	 * @return EE_Event
400
+	 * @throws EE_Error
401
+	 * @throws EntityNotFoundException
402
+	 */
403
+	public function event()
404
+	{
405
+		$event = $this->get_first_related('Event');
406
+		if (! $event instanceof \EE_Event) {
407
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
408
+		}
409
+		return $event;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
+	 * with the author of the event this registration is for.
416
+	 *
417
+	 * @since 4.5.0
418
+	 * @return int
419
+	 * @throws EE_Error
420
+	 * @throws EntityNotFoundException
421
+	 */
422
+	public function wp_user()
423
+	{
424
+		$event = $this->event();
425
+		if ($event instanceof EE_Event) {
426
+			return $event->wp_user();
427
+		}
428
+		return 0;
429
+	}
430
+
431
+
432
+	/**
433
+	 * increments this registration's related ticket sold and corresponding datetime sold values
434
+	 *
435
+	 * @return void
436
+	 * @throws DomainException
437
+	 * @throws EE_Error
438
+	 * @throws EntityNotFoundException
439
+	 * @throws InvalidArgumentException
440
+	 * @throws InvalidDataTypeException
441
+	 * @throws InvalidInterfaceException
442
+	 * @throws ReflectionException
443
+	 * @throws UnexpectedEntityException
444
+	 */
445
+	private function reserveRegistrationSpace()
446
+	{
447
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
448
+		// so stop tracking that this reg has a ticket reserved
449
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
+		$ticket = $this->ticket();
451
+		$ticket->increaseSold();
452
+		// possibly set event status to sold out
453
+		$this->event()->perform_sold_out_status_check();
454
+	}
455
+
456
+
457
+	/**
458
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
+	 *
460
+	 * @return void
461
+	 * @throws DomainException
462
+	 * @throws EE_Error
463
+	 * @throws EntityNotFoundException
464
+	 * @throws InvalidArgumentException
465
+	 * @throws InvalidDataTypeException
466
+	 * @throws InvalidInterfaceException
467
+	 * @throws ReflectionException
468
+	 * @throws UnexpectedEntityException
469
+	 */
470
+	private function releaseRegistrationSpace()
471
+	{
472
+		$ticket = $this->ticket();
473
+		$ticket->decreaseSold();
474
+		// possibly change event status from sold out back to previous status
475
+		$this->event()->perform_sold_out_status_check();
476
+	}
477
+
478
+
479
+	/**
480
+	 * tracks this registration's ticket reservation in extra meta
481
+	 * and can increment related ticket reserved and corresponding datetime reserved values
482
+	 *
483
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
+	{
493
+		// only reserve ticket if space is not currently reserved
494
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
+			// IMPORTANT !!!
497
+			// although checking $update_ticket first would be more efficient,
498
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
+				&& $update_ticket
501
+			) {
502
+				$ticket = $this->ticket();
503
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
+				$ticket->save();
505
+			}
506
+		}
507
+	}
508
+
509
+
510
+	/**
511
+	 * stops tracking this registration's ticket reservation in extra meta
512
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
+	 *
514
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
+	 * @return void
516
+	 * @throws EE_Error
517
+	 * @throws InvalidArgumentException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 * @throws ReflectionException
521
+	 */
522
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
+	{
524
+		// only release ticket if space is currently reserved
525
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
+			// IMPORTANT !!!
528
+			// although checking $update_ticket first would be more efficient,
529
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
+				&& $update_ticket
532
+			) {
533
+				$ticket = $this->ticket();
534
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
+			}
536
+		}
537
+	}
538
+
539
+
540
+	/**
541
+	 * Set Attendee ID
542
+	 *
543
+	 * @param        int $ATT_ID Attendee ID
544
+	 * @throws EE_Error
545
+	 * @throws RuntimeException
546
+	 */
547
+	public function set_attendee_id($ATT_ID = 0)
548
+	{
549
+		$this->set('ATT_ID', $ATT_ID);
550
+	}
551
+
552
+
553
+	/**
554
+	 *        Set Transaction ID
555
+	 *
556
+	 * @param        int $TXN_ID Transaction ID
557
+	 * @throws EE_Error
558
+	 * @throws RuntimeException
559
+	 */
560
+	public function set_transaction_id($TXN_ID = 0)
561
+	{
562
+		$this->set('TXN_ID', $TXN_ID);
563
+	}
564
+
565
+
566
+	/**
567
+	 *        Set Session
568
+	 *
569
+	 * @param    string $REG_session PHP Session ID
570
+	 * @throws EE_Error
571
+	 * @throws RuntimeException
572
+	 */
573
+	public function set_session($REG_session = '')
574
+	{
575
+		$this->set('REG_session', $REG_session);
576
+	}
577
+
578
+
579
+	/**
580
+	 *        Set Registration URL Link
581
+	 *
582
+	 * @param    string $REG_url_link Registration URL Link
583
+	 * @throws EE_Error
584
+	 * @throws RuntimeException
585
+	 */
586
+	public function set_reg_url_link($REG_url_link = '')
587
+	{
588
+		$this->set('REG_url_link', $REG_url_link);
589
+	}
590
+
591
+
592
+	/**
593
+	 *        Set Attendee Counter
594
+	 *
595
+	 * @param        int $REG_count Primary Attendee
596
+	 * @throws EE_Error
597
+	 * @throws RuntimeException
598
+	 */
599
+	public function set_count($REG_count = 1)
600
+	{
601
+		$this->set('REG_count', $REG_count);
602
+	}
603
+
604
+
605
+	/**
606
+	 *        Set Group Size
607
+	 *
608
+	 * @param        boolean $REG_group_size Group Registration
609
+	 * @throws EE_Error
610
+	 * @throws RuntimeException
611
+	 */
612
+	public function set_group_size($REG_group_size = false)
613
+	{
614
+		$this->set('REG_group_size', $REG_group_size);
615
+	}
616
+
617
+
618
+	/**
619
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
+	 *    EEM_Registration::status_id_not_approved
621
+	 *
622
+	 * @return        boolean
623
+	 */
624
+	public function is_not_approved()
625
+	{
626
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
+	}
628
+
629
+
630
+	/**
631
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
+	 *    EEM_Registration::status_id_pending_payment
633
+	 *
634
+	 * @return        boolean
635
+	 */
636
+	public function is_pending_payment()
637
+	{
638
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
+	}
640
+
641
+
642
+	/**
643
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
+	 *
645
+	 * @return        boolean
646
+	 */
647
+	public function is_approved()
648
+	{
649
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
+	}
651
+
652
+
653
+	/**
654
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
+	 *
656
+	 * @return        boolean
657
+	 */
658
+	public function is_cancelled()
659
+	{
660
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
+	}
662
+
663
+
664
+	/**
665
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
+	 *
667
+	 * @return        boolean
668
+	 */
669
+	public function is_declined()
670
+	{
671
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
+	}
673
+
674
+
675
+	/**
676
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
+	 *    EEM_Registration::status_id_incomplete
678
+	 *
679
+	 * @return        boolean
680
+	 */
681
+	public function is_incomplete()
682
+	{
683
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
+	}
685
+
686
+
687
+	/**
688
+	 *        Set Registration Date
689
+	 *
690
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
+	 *                                                 Date
692
+	 * @throws EE_Error
693
+	 * @throws RuntimeException
694
+	 */
695
+	public function set_reg_date($REG_date = false)
696
+	{
697
+		$this->set('REG_date', $REG_date);
698
+	}
699
+
700
+
701
+	/**
702
+	 *    Set final price owing for this registration after all ticket/price modifications
703
+	 *
704
+	 * @access    public
705
+	 * @param    float $REG_final_price
706
+	 * @throws EE_Error
707
+	 * @throws RuntimeException
708
+	 */
709
+	public function set_final_price($REG_final_price = 0.00)
710
+	{
711
+		$this->set('REG_final_price', $REG_final_price);
712
+	}
713
+
714
+
715
+	/**
716
+	 *    Set amount paid towards this registration's final price
717
+	 *
718
+	 * @access    public
719
+	 * @param    float $REG_paid
720
+	 * @throws EE_Error
721
+	 * @throws RuntimeException
722
+	 */
723
+	public function set_paid($REG_paid = 0.00)
724
+	{
725
+		$this->set('REG_paid', $REG_paid);
726
+	}
727
+
728
+
729
+	/**
730
+	 *        Attendee Is Going
731
+	 *
732
+	 * @param        boolean $REG_att_is_going Attendee Is Going
733
+	 * @throws EE_Error
734
+	 * @throws RuntimeException
735
+	 */
736
+	public function set_att_is_going($REG_att_is_going = false)
737
+	{
738
+		$this->set('REG_att_is_going', $REG_att_is_going);
739
+	}
740
+
741
+
742
+	/**
743
+	 * Gets the related attendee
744
+	 *
745
+	 * @return EE_Attendee
746
+	 * @throws EE_Error
747
+	 */
748
+	public function attendee()
749
+	{
750
+		return $this->get_first_related('Attendee');
751
+	}
752
+
753
+	/**
754
+	 * Gets the name of the attendee.
755
+	 * @since $VID:$
756
+	 * @param bool $apply_html_entities set to true if you want to use HTML entities.
757
+	 * @return string
758
+	 * @throws EE_Error
759
+	 * @throws InvalidArgumentException
760
+	 * @throws InvalidDataTypeException
761
+	 * @throws InvalidInterfaceException
762
+	 * @throws ReflectionException
763
+	 */
764
+	public function attendeeName($apply_html_entities = false)
765
+	{
766
+		$attendee = $this->get_first_related('Attendee');
767
+		if ($attendee instanceof EE_Attendee) {
768
+			$attendee_name = $attendee->full_name($apply_html_entities);
769
+		} else {
770
+			$attendee_name = esc_html__('Unknown', 'event_espresso');
771
+		}
772
+		return $attendee_name;
773
+	}
774
+
775
+
776
+	/**
777
+	 *        get Event ID
778
+	 */
779
+	public function event_ID()
780
+	{
781
+		return $this->get('EVT_ID');
782
+	}
783
+
784
+
785
+	/**
786
+	 *        get Event ID
787
+	 */
788
+	public function event_name()
789
+	{
790
+		$event = $this->event_obj();
791
+		if ($event) {
792
+			return $event->name();
793
+		} else {
794
+			return null;
795
+		}
796
+	}
797
+
798
+
799
+	/**
800
+	 * Fetches the event this registration is for
801
+	 *
802
+	 * @return EE_Event
803
+	 * @throws EE_Error
804
+	 */
805
+	public function event_obj()
806
+	{
807
+		return $this->get_first_related('Event');
808
+	}
809
+
810
+
811
+	/**
812
+	 *        get Attendee ID
813
+	 */
814
+	public function attendee_ID()
815
+	{
816
+		return $this->get('ATT_ID');
817
+	}
818
+
819
+
820
+	/**
821
+	 *        get PHP Session ID
822
+	 */
823
+	public function session_ID()
824
+	{
825
+		return $this->get('REG_session');
826
+	}
827
+
828
+
829
+	/**
830
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
831
+	 *
832
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
833
+	 * @return string
834
+	 */
835
+	public function receipt_url($messenger = 'html')
836
+	{
837
+
838
+		/**
839
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
840
+		 * already in use on old system.  If there is then we just return the standard url for it.
841
+		 *
842
+		 * @since 4.5.0
843
+		 */
844
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
845
+		$has_custom = EEH_Template::locate_template(
846
+			$template_relative_path,
847
+			array(),
848
+			true,
849
+			true,
850
+			true
851
+		);
852
+
853
+		if ($has_custom) {
854
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
855
+		}
856
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
857
+	}
858
+
859
+
860
+	/**
861
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
862
+	 *
863
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
864
+	 * @return string
865
+	 * @throws EE_Error
866
+	 */
867
+	public function invoice_url($messenger = 'html')
868
+	{
869
+		/**
870
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
871
+		 * already in use on old system.  If there is then we just return the standard url for it.
872
+		 *
873
+		 * @since 4.5.0
874
+		 */
875
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
876
+		$has_custom = EEH_Template::locate_template(
877
+			$template_relative_path,
878
+			array(),
879
+			true,
880
+			true,
881
+			true
882
+		);
883
+
884
+		if ($has_custom) {
885
+			if ($messenger == 'html') {
886
+				return $this->invoice_url('launch');
887
+			}
888
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
889
+
890
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
891
+			if ($messenger == 'html') {
892
+				$query_args['html'] = true;
893
+			}
894
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
895
+		}
896
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
897
+	}
898
+
899
+
900
+	/**
901
+	 * get Registration URL Link
902
+	 *
903
+	 * @access public
904
+	 * @return string
905
+	 * @throws EE_Error
906
+	 */
907
+	public function reg_url_link()
908
+	{
909
+		return (string) $this->get('REG_url_link');
910
+	}
911
+
912
+
913
+	/**
914
+	 * Echoes out invoice_url()
915
+	 *
916
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
917
+	 * @return void
918
+	 * @throws EE_Error
919
+	 */
920
+	public function e_invoice_url($type = 'launch')
921
+	{
922
+		echo $this->invoice_url($type);
923
+	}
924
+
925
+
926
+	/**
927
+	 * Echoes out payment_overview_url
928
+	 */
929
+	public function e_payment_overview_url()
930
+	{
931
+		echo $this->payment_overview_url();
932
+	}
933
+
934
+
935
+	/**
936
+	 * Gets the URL for the checkout payment options reg step
937
+	 * with this registration's REG_url_link added as a query parameter
938
+	 *
939
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
940
+	 *                            payment overview url.
941
+	 * @return string
942
+	 * @throws InvalidInterfaceException
943
+	 * @throws InvalidDataTypeException
944
+	 * @throws EE_Error
945
+	 * @throws InvalidArgumentException
946
+	 */
947
+	public function payment_overview_url($clear_session = false)
948
+	{
949
+		return add_query_arg(
950
+			(array) apply_filters(
951
+				'FHEE__EE_Registration__payment_overview_url__query_args',
952
+				array(
953
+					'e_reg_url_link' => $this->reg_url_link(),
954
+					'step'           => 'payment_options',
955
+					'revisit'        => true,
956
+					'clear_session'  => (bool) $clear_session,
957
+				),
958
+				$this
959
+			),
960
+			EE_Registry::instance()->CFG->core->reg_page_url()
961
+		);
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets the URL for the checkout attendee information reg step
967
+	 * with this registration's REG_url_link added as a query parameter
968
+	 *
969
+	 * @return string
970
+	 * @throws InvalidInterfaceException
971
+	 * @throws InvalidDataTypeException
972
+	 * @throws EE_Error
973
+	 * @throws InvalidArgumentException
974
+	 */
975
+	public function edit_attendee_information_url()
976
+	{
977
+		return add_query_arg(
978
+			(array) apply_filters(
979
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
980
+				array(
981
+					'e_reg_url_link' => $this->reg_url_link(),
982
+					'step'           => 'attendee_information',
983
+					'revisit'        => true,
984
+				),
985
+				$this
986
+			),
987
+			EE_Registry::instance()->CFG->core->reg_page_url()
988
+		);
989
+	}
990
+
991
+
992
+	/**
993
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
994
+	 *
995
+	 * @return string
996
+	 * @throws EE_Error
997
+	 */
998
+	public function get_admin_edit_url()
999
+	{
1000
+		return EEH_URL::add_query_args_and_nonce(
1001
+			array(
1002
+				'page'    => 'espresso_registrations',
1003
+				'action'  => 'view_registration',
1004
+				'_REG_ID' => $this->ID(),
1005
+			),
1006
+			admin_url('admin.php')
1007
+		);
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 *    is_primary_registrant?
1013
+	 */
1014
+	public function is_primary_registrant()
1015
+	{
1016
+		return $this->get('REG_count') === 1 ? true : false;
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * This returns the primary registration object for this registration group (which may be this object).
1022
+	 *
1023
+	 * @return EE_Registration
1024
+	 * @throws EE_Error
1025
+	 */
1026
+	public function get_primary_registration()
1027
+	{
1028
+		if ($this->is_primary_registrant()) {
1029
+			return $this;
1030
+		}
1031
+
1032
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1033
+		/** @var EE_Registration $primary_registrant */
1034
+		$primary_registrant = EEM_Registration::instance()->get_one(
1035
+			array(
1036
+				array(
1037
+					'TXN_ID'    => $this->transaction_ID(),
1038
+					'REG_count' => 1,
1039
+				),
1040
+			)
1041
+		);
1042
+		return $primary_registrant;
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 *        get  Attendee Number
1048
+	 *
1049
+	 * @access        public
1050
+	 */
1051
+	public function count()
1052
+	{
1053
+		return $this->get('REG_count');
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 *        get Group Size
1059
+	 */
1060
+	public function group_size()
1061
+	{
1062
+		return $this->get('REG_group_size');
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 *        get Registration Date
1068
+	 */
1069
+	public function date()
1070
+	{
1071
+		return $this->get('REG_date');
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * gets a pretty date
1077
+	 *
1078
+	 * @param string $date_format
1079
+	 * @param string $time_format
1080
+	 * @return string
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function pretty_date($date_format = null, $time_format = null)
1084
+	{
1085
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * final_price
1091
+	 * the registration's share of the transaction total, so that the
1092
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1093
+	 *
1094
+	 * @return float
1095
+	 * @throws EE_Error
1096
+	 */
1097
+	public function final_price()
1098
+	{
1099
+		return $this->get('REG_final_price');
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * pretty_final_price
1105
+	 *  final price as formatted string, with correct decimal places and currency symbol
1106
+	 *
1107
+	 * @return string
1108
+	 * @throws EE_Error
1109
+	 */
1110
+	public function pretty_final_price()
1111
+	{
1112
+		return $this->get_pretty('REG_final_price');
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * get paid (yeah)
1118
+	 *
1119
+	 * @return float
1120
+	 * @throws EE_Error
1121
+	 */
1122
+	public function paid()
1123
+	{
1124
+		return $this->get('REG_paid');
1125
+	}
1126
+
1127
+
1128
+	/**
1129
+	 * pretty_paid
1130
+	 *
1131
+	 * @return float
1132
+	 * @throws EE_Error
1133
+	 */
1134
+	public function pretty_paid()
1135
+	{
1136
+		return $this->get_pretty('REG_paid');
1137
+	}
1138
+
1139
+
1140
+	/**
1141
+	 * owes_monies_and_can_pay
1142
+	 * whether or not this registration has monies owing and it's' status allows payment
1143
+	 *
1144
+	 * @param array $requires_payment
1145
+	 * @return bool
1146
+	 * @throws EE_Error
1147
+	 */
1148
+	public function owes_monies_and_can_pay($requires_payment = array())
1149
+	{
1150
+		// these reg statuses require payment (if event is not free)
1151
+		$requires_payment = ! empty($requires_payment)
1152
+			? $requires_payment
1153
+			: EEM_Registration::reg_statuses_that_allow_payment();
1154
+		if (in_array($this->status_ID(), $requires_payment) &&
1155
+			$this->final_price() != 0 &&
1156
+			$this->final_price() != $this->paid()
1157
+		) {
1158
+			return true;
1159
+		} else {
1160
+			return false;
1161
+		}
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Prints out the return value of $this->pretty_status()
1167
+	 *
1168
+	 * @param bool $show_icons
1169
+	 * @return void
1170
+	 * @throws EE_Error
1171
+	 */
1172
+	public function e_pretty_status($show_icons = false)
1173
+	{
1174
+		echo $this->pretty_status($show_icons);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Returns a nice version of the status for displaying to customers
1180
+	 *
1181
+	 * @param bool $show_icons
1182
+	 * @return string
1183
+	 * @throws EE_Error
1184
+	 */
1185
+	public function pretty_status($show_icons = false)
1186
+	{
1187
+		$status = EEM_Status::instance()->localized_status(
1188
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1189
+			false,
1190
+			'sentence'
1191
+		);
1192
+		$icon = '';
1193
+		switch ($this->status_ID()) {
1194
+			case EEM_Registration::status_id_approved:
1195
+				$icon = $show_icons
1196
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1197
+					: '';
1198
+				break;
1199
+			case EEM_Registration::status_id_pending_payment:
1200
+				$icon = $show_icons
1201
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1202
+					: '';
1203
+				break;
1204
+			case EEM_Registration::status_id_not_approved:
1205
+				$icon = $show_icons
1206
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1207
+					: '';
1208
+				break;
1209
+			case EEM_Registration::status_id_cancelled:
1210
+				$icon = $show_icons
1211
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1212
+					: '';
1213
+				break;
1214
+			case EEM_Registration::status_id_incomplete:
1215
+				$icon = $show_icons
1216
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1217
+					: '';
1218
+				break;
1219
+			case EEM_Registration::status_id_declined:
1220
+				$icon = $show_icons
1221
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1222
+					: '';
1223
+				break;
1224
+			case EEM_Registration::status_id_wait_list:
1225
+				$icon = $show_icons
1226
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1227
+					: '';
1228
+				break;
1229
+		}
1230
+		return $icon . $status[ $this->status_ID() ];
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 *        get Attendee Is Going
1236
+	 */
1237
+	public function att_is_going()
1238
+	{
1239
+		return $this->get('REG_att_is_going');
1240
+	}
1241
+
1242
+
1243
+	/**
1244
+	 * Gets related answers
1245
+	 *
1246
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1247
+	 * @return EE_Answer[]
1248
+	 * @throws EE_Error
1249
+	 */
1250
+	public function answers($query_params = null)
1251
+	{
1252
+		return $this->get_many_related('Answer', $query_params);
1253
+	}
1254
+
1255
+
1256
+	/**
1257
+	 * Gets the registration's answer value to the specified question
1258
+	 * (either the question's ID or a question object)
1259
+	 *
1260
+	 * @param EE_Question|int $question
1261
+	 * @param bool            $pretty_value
1262
+	 * @return array|string if pretty_value= true, the result will always be a string
1263
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1264
+	 * will convert it into some kind of string)
1265
+	 * @throws EE_Error
1266
+	 */
1267
+	public function answer_value_to_question($question, $pretty_value = true)
1268
+	{
1269
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1270
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * question_groups
1276
+	 * returns an array of EE_Question_Group objects for this registration
1277
+	 *
1278
+	 * @return EE_Question_Group[]
1279
+	 * @throws EE_Error
1280
+	 * @throws InvalidArgumentException
1281
+	 * @throws InvalidDataTypeException
1282
+	 * @throws InvalidInterfaceException
1283
+	 * @throws ReflectionException
1284
+	 */
1285
+	public function question_groups()
1286
+	{
1287
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * count_question_groups
1293
+	 * returns a count of the number of EE_Question_Group objects for this registration
1294
+	 *
1295
+	 * @return int
1296
+	 * @throws EE_Error
1297
+	 * @throws EntityNotFoundException
1298
+	 * @throws InvalidArgumentException
1299
+	 * @throws InvalidDataTypeException
1300
+	 * @throws InvalidInterfaceException
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	public function count_question_groups()
1304
+	{
1305
+		return EEM_Event::instance()->count_related(
1306
+			$this->event_ID(),
1307
+			'Question_Group',
1308
+			[
1309
+				[
1310
+					'Event_Question_Group.'
1311
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1312
+				]
1313
+			]
1314
+		);
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * Returns the registration date in the 'standard' string format
1320
+	 * (function may be improved in the future to allow for different formats and timezones)
1321
+	 *
1322
+	 * @return string
1323
+	 * @throws EE_Error
1324
+	 */
1325
+	public function reg_date()
1326
+	{
1327
+		return $this->get_datetime('REG_date');
1328
+	}
1329
+
1330
+
1331
+	/**
1332
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1333
+	 * the ticket this registration purchased, or the datetime they have registered
1334
+	 * to attend)
1335
+	 *
1336
+	 * @return EE_Datetime_Ticket
1337
+	 * @throws EE_Error
1338
+	 */
1339
+	public function datetime_ticket()
1340
+	{
1341
+		return $this->get_first_related('Datetime_Ticket');
1342
+	}
1343
+
1344
+
1345
+	/**
1346
+	 * Sets the registration's datetime_ticket.
1347
+	 *
1348
+	 * @param EE_Datetime_Ticket $datetime_ticket
1349
+	 * @return EE_Datetime_Ticket
1350
+	 * @throws EE_Error
1351
+	 */
1352
+	public function set_datetime_ticket($datetime_ticket)
1353
+	{
1354
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1355
+	}
1356
+
1357
+	/**
1358
+	 * Gets deleted
1359
+	 *
1360
+	 * @return bool
1361
+	 * @throws EE_Error
1362
+	 */
1363
+	public function deleted()
1364
+	{
1365
+		return $this->get('REG_deleted');
1366
+	}
1367
+
1368
+	/**
1369
+	 * Sets deleted
1370
+	 *
1371
+	 * @param boolean $deleted
1372
+	 * @return bool
1373
+	 * @throws EE_Error
1374
+	 * @throws RuntimeException
1375
+	 */
1376
+	public function set_deleted($deleted)
1377
+	{
1378
+		if ($deleted) {
1379
+			$this->delete();
1380
+		} else {
1381
+			$this->restore();
1382
+		}
1383
+	}
1384
+
1385
+
1386
+	/**
1387
+	 * Get the status object of this object
1388
+	 *
1389
+	 * @return EE_Status
1390
+	 * @throws EE_Error
1391
+	 */
1392
+	public function status_obj()
1393
+	{
1394
+		return $this->get_first_related('Status');
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * Returns the number of times this registration has checked into any of the datetimes
1400
+	 * its available for
1401
+	 *
1402
+	 * @return int
1403
+	 * @throws EE_Error
1404
+	 */
1405
+	public function count_checkins()
1406
+	{
1407
+		return $this->get_model()->count_related($this, 'Checkin');
1408
+	}
1409
+
1410
+
1411
+	/**
1412
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1413
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1414
+	 *
1415
+	 * @return int
1416
+	 * @throws EE_Error
1417
+	 */
1418
+	public function count_checkins_not_checkedout()
1419
+	{
1420
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1426
+	 *
1427
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1428
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1429
+	 *                                          consider registration status as well as datetime access.
1430
+	 * @return bool
1431
+	 * @throws EE_Error
1432
+	 */
1433
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1434
+	{
1435
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1436
+
1437
+		// first check registration status
1438
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1439
+			return false;
1440
+		}
1441
+		// is there a datetime ticket that matches this dtt_ID?
1442
+		if (! (EEM_Datetime_Ticket::instance()->exists(
1443
+			array(
1444
+				array(
1445
+					'TKT_ID' => $this->get('TKT_ID'),
1446
+					'DTT_ID' => $DTT_ID,
1447
+				),
1448
+			)
1449
+		))
1450
+		) {
1451
+			return false;
1452
+		}
1453
+
1454
+		// final check is against TKT_uses
1455
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1461
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1462
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1463
+	 * then return false.  Otherwise return true.
1464
+	 *
1465
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1466
+	 * @return bool true means can checkin.  false means cannot checkin.
1467
+	 * @throws EE_Error
1468
+	 */
1469
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1470
+	{
1471
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1472
+
1473
+		if (! $DTT_ID) {
1474
+			return false;
1475
+		}
1476
+
1477
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1478
+
1479
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1480
+		// check-in or not.
1481
+		if (! $max_uses || $max_uses === EE_INF) {
1482
+			return true;
1483
+		}
1484
+
1485
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1486
+		// go ahead and toggle.
1487
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1488
+			return true;
1489
+		}
1490
+
1491
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1492
+		// disallows further check-ins.
1493
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1494
+			array(
1495
+				array(
1496
+					'REG_ID' => $this->ID(),
1497
+					'CHK_in' => true,
1498
+				),
1499
+			),
1500
+			'DTT_ID',
1501
+			true
1502
+		);
1503
+		// checkins have already reached their max number of uses
1504
+		// so registrant can NOT checkin
1505
+		if ($count_unique_dtt_checkins >= $max_uses) {
1506
+			EE_Error::add_error(
1507
+				esc_html__(
1508
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1509
+					'event_espresso'
1510
+				),
1511
+				__FILE__,
1512
+				__FUNCTION__,
1513
+				__LINE__
1514
+			);
1515
+			return false;
1516
+		}
1517
+		return true;
1518
+	}
1519
+
1520
+
1521
+	/**
1522
+	 * toggle Check-in status for this registration
1523
+	 * Check-ins are toggled in the following order:
1524
+	 * never checked in -> checked in
1525
+	 * checked in -> checked out
1526
+	 * checked out -> checked in
1527
+	 *
1528
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1529
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1530
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1531
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1532
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1533
+	 * @throws EE_Error
1534
+	 */
1535
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1536
+	{
1537
+		if (empty($DTT_ID)) {
1538
+			$datetime = $this->get_latest_related_datetime();
1539
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1540
+			// verify the registration can checkin for the given DTT_ID
1541
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1542
+			EE_Error::add_error(
1543
+				sprintf(
1544
+					esc_html__(
1545
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1546
+						'event_espresso'
1547
+					),
1548
+					$this->ID(),
1549
+					$DTT_ID
1550
+				),
1551
+				__FILE__,
1552
+				__FUNCTION__,
1553
+				__LINE__
1554
+			);
1555
+			return false;
1556
+		}
1557
+		$status_paths = array(
1558
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1559
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1560
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1561
+		);
1562
+		// start by getting the current status so we know what status we'll be changing to.
1563
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1564
+		$status_to = $status_paths[ $cur_status ];
1565
+		// database only records true for checked IN or false for checked OUT
1566
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1567
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1568
+		// add relation - note Check-ins are always creating new rows
1569
+		// because we are keeping track of Check-ins over time.
1570
+		// Eventually we'll probably want to show a list table
1571
+		// for the individual Check-ins so that they can be managed.
1572
+		$checkin = EE_Checkin::new_instance(
1573
+			array(
1574
+				'REG_ID' => $this->ID(),
1575
+				'DTT_ID' => $DTT_ID,
1576
+				'CHK_in' => $new_status,
1577
+			)
1578
+		);
1579
+		// if the record could not be saved then return false
1580
+		if ($checkin->save() === 0) {
1581
+			if (WP_DEBUG) {
1582
+				global $wpdb;
1583
+				$error = sprintf(
1584
+					esc_html__(
1585
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1586
+						'event_espresso'
1587
+					),
1588
+					'<br />',
1589
+					$wpdb->last_error
1590
+				);
1591
+			} else {
1592
+				$error = esc_html__(
1593
+					'Registration check in update failed because of an unknown database error',
1594
+					'event_espresso'
1595
+				);
1596
+			}
1597
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1598
+			return false;
1599
+		}
1600
+		// Fire a checked_in and checkout_out action.
1601
+		$checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1602
+		do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1603
+		return $status_to;
1604
+	}
1605
+
1606
+
1607
+	/**
1608
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1609
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1610
+	 *
1611
+	 * @return EE_Datetime|null
1612
+	 * @throws EE_Error
1613
+	 */
1614
+	public function get_latest_related_datetime()
1615
+	{
1616
+		return EEM_Datetime::instance()->get_one(
1617
+			array(
1618
+				array(
1619
+					'Ticket.Registration.REG_ID' => $this->ID(),
1620
+				),
1621
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1622
+			)
1623
+		);
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1629
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1630
+	 *
1631
+	 * @throws EE_Error
1632
+	 */
1633
+	public function get_earliest_related_datetime()
1634
+	{
1635
+		return EEM_Datetime::instance()->get_one(
1636
+			array(
1637
+				array(
1638
+					'Ticket.Registration.REG_ID' => $this->ID(),
1639
+				),
1640
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1641
+			)
1642
+		);
1643
+	}
1644
+
1645
+
1646
+	/**
1647
+	 * This method simply returns the check-in status for this registration and the given datetime.
1648
+	 * If neither the datetime nor the checkin values are provided as arguments,
1649
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1650
+	 *
1651
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1652
+	 *                            (if empty we'll get the primary datetime for
1653
+	 *                            this registration (via event) and use it's ID);
1654
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1655
+	 *
1656
+	 * @return int                Integer representing Check-in status.
1657
+	 * @throws EE_Error
1658
+	 */
1659
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1660
+	{
1661
+		$checkin_query_params = array(
1662
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1663
+		);
1664
+
1665
+		if ($DTT_ID > 0) {
1666
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1667
+		}
1668
+
1669
+		// get checkin object (if exists)
1670
+		$checkin = $checkin instanceof EE_Checkin
1671
+			? $checkin
1672
+			: $this->get_first_related('Checkin', $checkin_query_params);
1673
+		if ($checkin instanceof EE_Checkin) {
1674
+			if ($checkin->get('CHK_in')) {
1675
+				return EE_Checkin::status_checked_in; // checked in
1676
+			}
1677
+			return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1678
+		}
1679
+		return EE_Checkin::status_checked_never; // never been checked in
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * This method returns a localized message for the toggled Check-in message.
1685
+	 *
1686
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1687
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1688
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1689
+	 *                     message can be customized with the attendee name.
1690
+	 * @return string internationalized message
1691
+	 * @throws EE_Error
1692
+	 */
1693
+	public function get_checkin_msg($DTT_ID, $error = false)
1694
+	{
1695
+		// let's get the attendee first so we can include the name of the attendee
1696
+		$attendee = $this->get_first_related('Attendee');
1697
+		if ($attendee instanceof EE_Attendee) {
1698
+			if ($error) {
1699
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1700
+			}
1701
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1702
+			// what is the status message going to be?
1703
+			switch ($cur_status) {
1704
+				case EE_Checkin::status_checked_never:
1705
+					return sprintf(
1706
+						__("%s has been removed from Check-in records", "event_espresso"),
1707
+						$attendee->full_name()
1708
+					);
1709
+					break;
1710
+				case EE_Checkin::status_checked_in:
1711
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1712
+					break;
1713
+				case EE_Checkin::status_checked_out:
1714
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1715
+					break;
1716
+			}
1717
+		}
1718
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * Returns the related EE_Transaction to this registration
1724
+	 *
1725
+	 * @return EE_Transaction
1726
+	 * @throws EE_Error
1727
+	 * @throws EntityNotFoundException
1728
+	 */
1729
+	public function transaction()
1730
+	{
1731
+		$transaction = $this->get_first_related('Transaction');
1732
+		if (! $transaction instanceof \EE_Transaction) {
1733
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1734
+		}
1735
+		return $transaction;
1736
+	}
1737
+
1738
+
1739
+	/**
1740
+	 *        get Registration Code
1741
+	 */
1742
+	public function reg_code()
1743
+	{
1744
+		return $this->get('REG_code');
1745
+	}
1746
+
1747
+
1748
+	/**
1749
+	 *        get Transaction ID
1750
+	 */
1751
+	public function transaction_ID()
1752
+	{
1753
+		return $this->get('TXN_ID');
1754
+	}
1755
+
1756
+
1757
+	/**
1758
+	 * @return int
1759
+	 * @throws EE_Error
1760
+	 */
1761
+	public function ticket_ID()
1762
+	{
1763
+		return $this->get('TKT_ID');
1764
+	}
1765
+
1766
+
1767
+	/**
1768
+	 *        Set Registration Code
1769
+	 *
1770
+	 * @access    public
1771
+	 * @param    string  $REG_code Registration Code
1772
+	 * @param    boolean $use_default
1773
+	 * @throws EE_Error
1774
+	 */
1775
+	public function set_reg_code($REG_code, $use_default = false)
1776
+	{
1777
+		if (empty($REG_code)) {
1778
+			EE_Error::add_error(
1779
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1780
+				__FILE__,
1781
+				__FUNCTION__,
1782
+				__LINE__
1783
+			);
1784
+			return;
1785
+		}
1786
+		if (! $this->reg_code()) {
1787
+			parent::set('REG_code', $REG_code, $use_default);
1788
+		} else {
1789
+			EE_Error::doing_it_wrong(
1790
+				__CLASS__ . '::' . __FUNCTION__,
1791
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1792
+				'4.6.0'
1793
+			);
1794
+		}
1795
+	}
1796
+
1797
+
1798
+	/**
1799
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1800
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1801
+	 *    $registration->transaction()->registrations();
1802
+	 *
1803
+	 * @since 4.5.0
1804
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1805
+	 * @throws EE_Error
1806
+	 */
1807
+	public function get_all_other_registrations_in_group()
1808
+	{
1809
+		if ($this->group_size() < 2) {
1810
+			return array();
1811
+		}
1812
+
1813
+		$query[0] = array(
1814
+			'TXN_ID' => $this->transaction_ID(),
1815
+			'REG_ID' => array('!=', $this->ID()),
1816
+			'TKT_ID' => $this->ticket_ID(),
1817
+		);
1818
+		/** @var EE_Registration[] $registrations */
1819
+		$registrations = $this->get_model()->get_all($query);
1820
+		return $registrations;
1821
+	}
1822
+
1823
+	/**
1824
+	 * Return the link to the admin details for the object.
1825
+	 *
1826
+	 * @return string
1827
+	 * @throws EE_Error
1828
+	 */
1829
+	public function get_admin_details_link()
1830
+	{
1831
+		EE_Registry::instance()->load_helper('URL');
1832
+		return EEH_URL::add_query_args_and_nonce(
1833
+			array(
1834
+				'page'    => 'espresso_registrations',
1835
+				'action'  => 'view_registration',
1836
+				'_REG_ID' => $this->ID(),
1837
+			),
1838
+			admin_url('admin.php')
1839
+		);
1840
+	}
1841
+
1842
+	/**
1843
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1844
+	 *
1845
+	 * @return string
1846
+	 * @throws EE_Error
1847
+	 */
1848
+	public function get_admin_edit_link()
1849
+	{
1850
+		return $this->get_admin_details_link();
1851
+	}
1852
+
1853
+	/**
1854
+	 * Returns the link to a settings page for the object.
1855
+	 *
1856
+	 * @return string
1857
+	 * @throws EE_Error
1858
+	 */
1859
+	public function get_admin_settings_link()
1860
+	{
1861
+		return $this->get_admin_details_link();
1862
+	}
1863
+
1864
+	/**
1865
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1866
+	 *
1867
+	 * @return string
1868
+	 */
1869
+	public function get_admin_overview_link()
1870
+	{
1871
+		EE_Registry::instance()->load_helper('URL');
1872
+		return EEH_URL::add_query_args_and_nonce(
1873
+			array(
1874
+				'page' => 'espresso_registrations',
1875
+			),
1876
+			admin_url('admin.php')
1877
+		);
1878
+	}
1879
+
1880
+
1881
+	/**
1882
+	 * @param array $query_params
1883
+	 *
1884
+	 * @return \EE_Registration[]
1885
+	 * @throws EE_Error
1886
+	 */
1887
+	public function payments($query_params = array())
1888
+	{
1889
+		return $this->get_many_related('Payment', $query_params);
1890
+	}
1891
+
1892
+
1893
+	/**
1894
+	 * @param array $query_params
1895
+	 *
1896
+	 * @return \EE_Registration_Payment[]
1897
+	 * @throws EE_Error
1898
+	 */
1899
+	public function registration_payments($query_params = array())
1900
+	{
1901
+		return $this->get_many_related('Registration_Payment', $query_params);
1902
+	}
1903
+
1904
+
1905
+	/**
1906
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1907
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1908
+	 *
1909
+	 * @return EE_Payment_Method|null
1910
+	 */
1911
+	public function payment_method()
1912
+	{
1913
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1914
+	}
1915
+
1916
+
1917
+	/**
1918
+	 * @return \EE_Line_Item
1919
+	 * @throws EntityNotFoundException
1920
+	 * @throws EE_Error
1921
+	 */
1922
+	public function ticket_line_item()
1923
+	{
1924
+		$ticket = $this->ticket();
1925
+		$transaction = $this->transaction();
1926
+		$line_item = null;
1927
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1928
+			$transaction->total_line_item(),
1929
+			'Ticket',
1930
+			array($ticket->ID())
1931
+		);
1932
+		foreach ($ticket_line_items as $ticket_line_item) {
1933
+			if ($ticket_line_item instanceof \EE_Line_Item
1934
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1935
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1936
+			) {
1937
+				$line_item = $ticket_line_item;
1938
+				break;
1939
+			}
1940
+		}
1941
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1942
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1943
+		}
1944
+		return $line_item;
1945
+	}
1946
+
1947
+
1948
+	/**
1949
+	 * Soft Deletes this model object.
1950
+	 *
1951
+	 * @return boolean | int
1952
+	 * @throws RuntimeException
1953
+	 * @throws EE_Error
1954
+	 */
1955
+	public function delete()
1956
+	{
1957
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1958
+			$this->set_status(EEM_Registration::status_id_cancelled);
1959
+		}
1960
+		return parent::delete();
1961
+	}
1962
+
1963
+
1964
+	/**
1965
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1966
+	 *
1967
+	 * @throws EE_Error
1968
+	 * @throws RuntimeException
1969
+	 */
1970
+	public function restore()
1971
+	{
1972
+		$previous_status = $this->get_extra_meta(
1973
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1974
+			true,
1975
+			EEM_Registration::status_id_cancelled
1976
+		);
1977
+		if ($previous_status) {
1978
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1979
+			$this->set_status($previous_status);
1980
+		}
1981
+		return parent::restore();
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1987
+	 *
1988
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1989
+	 *                                           depending on whether the reg status changes to or from "Approved"
1990
+	 * @return boolean whether the Registration status was updated
1991
+	 * @throws EE_Error
1992
+	 * @throws RuntimeException
1993
+	 */
1994
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1995
+	{
1996
+		$paid = $this->paid();
1997
+		$price = $this->final_price();
1998
+		switch (true) {
1999
+			// overpaid or paid
2000
+			case EEH_Money::compare_floats($paid, $price, '>'):
2001
+			case EEH_Money::compare_floats($paid, $price):
2002
+				$new_status = EEM_Registration::status_id_approved;
2003
+				break;
2004
+			//  underpaid
2005
+			case EEH_Money::compare_floats($paid, $price, '<'):
2006
+				$new_status = EEM_Registration::status_id_pending_payment;
2007
+				break;
2008
+			// uhhh Houston...
2009
+			default:
2010
+				throw new RuntimeException(
2011
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2012
+				);
2013
+		}
2014
+		if ($new_status !== $this->status_ID()) {
2015
+			if ($trigger_set_status_logic) {
2016
+				return $this->set_status($new_status);
2017
+			}
2018
+			parent::set('STS_ID', $new_status);
2019
+			return true;
2020
+		}
2021
+		return false;
2022
+	}
2023
+
2024
+
2025
+	/*************************** DEPRECATED ***************************/
2026
+
2027
+
2028
+	/**
2029
+	 * @deprecated
2030
+	 * @since     4.7.0
2031
+	 * @access    public
2032
+	 */
2033
+	public function price_paid()
2034
+	{
2035
+		EE_Error::doing_it_wrong(
2036
+			'EE_Registration::price_paid()',
2037
+			esc_html__(
2038
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2039
+				'event_espresso'
2040
+			),
2041
+			'4.7.0'
2042
+		);
2043
+		return $this->final_price();
2044
+	}
2045
+
2046
+
2047
+	/**
2048
+	 * @deprecated
2049
+	 * @since     4.7.0
2050
+	 * @access    public
2051
+	 * @param    float $REG_final_price
2052
+	 * @throws EE_Error
2053
+	 * @throws RuntimeException
2054
+	 */
2055
+	public function set_price_paid($REG_final_price = 0.00)
2056
+	{
2057
+		EE_Error::doing_it_wrong(
2058
+			'EE_Registration::set_price_paid()',
2059
+			esc_html__(
2060
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2061
+				'event_espresso'
2062
+			),
2063
+			'4.7.0'
2064
+		);
2065
+		$this->set_final_price($REG_final_price);
2066
+	}
2067
+
2068
+
2069
+	/**
2070
+	 * @deprecated
2071
+	 * @since 4.7.0
2072
+	 * @return string
2073
+	 * @throws EE_Error
2074
+	 */
2075
+	public function pretty_price_paid()
2076
+	{
2077
+		EE_Error::doing_it_wrong(
2078
+			'EE_Registration::pretty_price_paid()',
2079
+			esc_html__(
2080
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2081
+				'event_espresso'
2082
+			),
2083
+			'4.7.0'
2084
+		);
2085
+		return $this->pretty_final_price();
2086
+	}
2087
+
2088
+
2089
+	/**
2090
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2091
+	 *
2092
+	 * @deprecated 4.9.17
2093
+	 * @return EE_Datetime
2094
+	 * @throws EE_Error
2095
+	 * @throws EntityNotFoundException
2096
+	 */
2097
+	public function get_related_primary_datetime()
2098
+	{
2099
+		EE_Error::doing_it_wrong(
2100
+			__METHOD__,
2101
+			esc_html__(
2102
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2103
+				'event_espresso'
2104
+			),
2105
+			'4.9.17',
2106
+			'5.0.0'
2107
+		);
2108
+		return $this->event()->primary_datetime();
2109
+	}
2110
+
2111
+	/**
2112
+	 * Returns the contact's name (or "Unknown" if there is no contact.)
2113
+	 * @since $VID:$
2114
+	 * @return string
2115
+	 * @throws EE_Error
2116
+	 * @throws InvalidArgumentException
2117
+	 * @throws InvalidDataTypeException
2118
+	 * @throws InvalidInterfaceException
2119
+	 * @throws ReflectionException
2120
+	 */
2121
+	public function name()
2122
+	{
2123
+		return $this->attendeeName();
2124
+	}
2125 2125
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.10.12.rc.002');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.10.12.rc.002');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.