Completed
Branch FET-3467-waitlists (78124b)
by
unknown
141:27 queued 128:30
created
core/EE_Dependency_Map.core.php 2 patches
Indentation   +635 added lines, -635 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\services\loaders\LoaderInterface;
5 5
 
6 6
 if (! defined('EVENT_ESPRESSO_VERSION')) {
7
-    exit('No direct script access allowed');
7
+	exit('No direct script access allowed');
8 8
 }
9 9
 
10 10
 
@@ -22,640 +22,640 @@  discard block
 block discarded – undo
22 22
 {
23 23
 
24 24
 
25
-    /**
26
-     * This means that the requested class dependency is not present in the dependency map
27
-     */
28
-    const not_registered = 0;
29
-
30
-
31
-    /**
32
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
33
-     */
34
-    const load_new_object = 1;
35
-
36
-    /**
37
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
38
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
39
-     */
40
-    const load_from_cache = 2;
41
-
42
-    /**
43
-     * @type EE_Dependency_Map $_instance
44
-     */
45
-    protected static $_instance;
46
-
47
-    /**
48
-     * @type EE_Request $request
49
-     */
50
-    protected $_request;
51
-
52
-    /**
53
-     * @type EE_Response $response
54
-     */
55
-    protected $_response;
56
-
57
-    /**
58
-     * @type LoaderInterface $loader
59
-     */
60
-    protected $loader;
61
-
62
-    /**
63
-     * @type array $_dependency_map
64
-     */
65
-    protected $_dependency_map = array();
66
-
67
-    /**
68
-     * @type array $_class_loaders
69
-     */
70
-    protected $_class_loaders = array();
71
-
72
-    /**
73
-     * @type array $_aliases
74
-     */
75
-    protected $_aliases = array();
76
-
77
-
78
-
79
-    /**
80
-     * EE_Dependency_Map constructor.
81
-     *
82
-     * @param EE_Request  $request
83
-     * @param EE_Response $response
84
-     */
85
-    protected function __construct(EE_Request $request, EE_Response $response)
86
-    {
87
-        $this->_request = $request;
88
-        $this->_response = $response;
89
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
90
-        do_action('EE_Dependency_Map____construct');
91
-    }
92
-
93
-
94
-
95
-    /**
96
-     * @throws InvalidDataTypeException
97
-     * @throws InvalidInterfaceException
98
-     * @throws InvalidArgumentException
99
-     */
100
-    public function initialize()
101
-    {
102
-        $this->_register_core_dependencies();
103
-        $this->_register_core_class_loaders();
104
-        $this->_register_core_aliases();
105
-    }
106
-
107
-
108
-
109
-    /**
110
-     * @singleton method used to instantiate class object
111
-     * @access    public
112
-     * @param EE_Request  $request
113
-     * @param EE_Response $response
114
-     * @return EE_Dependency_Map
115
-     */
116
-    public static function instance(EE_Request $request = null, EE_Response $response = null)
117
-    {
118
-        // check if class object is instantiated, and instantiated properly
119
-        if (! self::$_instance instanceof EE_Dependency_Map) {
120
-            self::$_instance = new EE_Dependency_Map($request, $response);
121
-        }
122
-        return self::$_instance;
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * @param LoaderInterface $loader
129
-     */
130
-    public function setLoader(LoaderInterface $loader)
131
-    {
132
-        $this->loader = $loader;
133
-    }
134
-
135
-
136
-
137
-    /**
138
-     * @param string $class
139
-     * @param array  $dependencies
140
-     * @return boolean
141
-     */
142
-    public static function register_dependencies($class, $dependencies)
143
-    {
144
-        $class = trim($class,'\\');
145
-        if (! isset(self::$_instance->_dependency_map[$class])) {
146
-            // we need to make sure that any aliases used when registering a dependency
147
-            // get resolved to the correct class name
148
-            foreach ((array)$dependencies as $dependency => $load_source) {
149
-                $alias = self::$_instance->get_alias($dependency);
150
-                unset($dependencies[$dependency]);
151
-                $dependencies[$alias] = $load_source;
152
-            }
153
-            self::$_instance->_dependency_map[$class] = (array)$dependencies;
154
-            return true;
155
-        }
156
-        return false;
157
-    }
158
-
159
-
160
-
161
-    /**
162
-     * @param string $class_name
163
-     * @param string $loader
164
-     * @return bool
165
-     * @throws EE_Error
166
-     */
167
-    public static function register_class_loader($class_name, $loader = 'load_core')
168
-    {
169
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
170
-        if (
171
-            ! is_callable($loader)
172
-            && (
173
-                strpos($loader, 'load_') !== 0
174
-                || ! method_exists('EE_Registry', $loader)
175
-            )
176
-        ) {
177
-            throw new EE_Error(
178
-                sprintf(
179
-                    esc_html__('"%1$s" is not a valid loader method on EE_Registry.', 'event_espresso'),
180
-                    $loader
181
-                )
182
-            );
183
-        }
184
-        $class_name = self::$_instance->get_alias($class_name);
185
-        if (! isset(self::$_instance->_class_loaders[$class_name])) {
186
-            self::$_instance->_class_loaders[$class_name] = $loader;
187
-            return true;
188
-        }
189
-        return false;
190
-    }
191
-
192
-
193
-
194
-    /**
195
-     * @return array
196
-     */
197
-    public function dependency_map()
198
-    {
199
-        return $this->_dependency_map;
200
-    }
201
-
202
-
203
-
204
-    /**
205
-     * returns TRUE if dependency map contains a listing for the provided class name
206
-     *
207
-     * @param string $class_name
208
-     * @return boolean
209
-     */
210
-    public function has($class_name = '')
211
-    {
212
-        return isset($this->_dependency_map[$class_name]) ? true : false;
213
-    }
214
-
215
-
216
-
217
-    /**
218
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
219
-     *
220
-     * @param string $class_name
221
-     * @param string $dependency
222
-     * @return bool
223
-     */
224
-    public function has_dependency_for_class($class_name = '', $dependency = '')
225
-    {
226
-        $dependency = $this->get_alias($dependency);
227
-        return isset($this->_dependency_map[$class_name], $this->_dependency_map[$class_name][$dependency])
228
-            ? true
229
-            : false;
230
-    }
231
-
232
-
233
-
234
-    /**
235
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
236
-     *
237
-     * @param string $class_name
238
-     * @param string $dependency
239
-     * @return int
240
-     */
241
-    public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
242
-    {
243
-        $dependency = $this->get_alias($dependency);
244
-        return $this->has_dependency_for_class($class_name, $dependency)
245
-            ? $this->_dependency_map[$class_name][$dependency]
246
-            : EE_Dependency_Map::not_registered;
247
-    }
248
-
249
-
250
-
251
-    /**
252
-     * @param string $class_name
253
-     * @return string | Closure
254
-     */
255
-    public function class_loader($class_name)
256
-    {
257
-        $class_name = $this->get_alias($class_name);
258
-        return isset($this->_class_loaders[$class_name]) ? $this->_class_loaders[$class_name] : '';
259
-    }
260
-
261
-
262
-
263
-    /**
264
-     * @return array
265
-     */
266
-    public function class_loaders()
267
-    {
268
-        return $this->_class_loaders;
269
-    }
270
-
271
-
272
-
273
-    /**
274
-     * adds an alias for a classname
275
-     *
276
-     * @param string $class_name the class name that should be used (concrete class to replace interface)
277
-     * @param string $alias      the class name that would be type hinted for (abstract parent or interface)
278
-     * @param string $for_class  the class that has the dependency (is type hinting for the interface)
279
-     */
280
-    public function add_alias($class_name, $alias, $for_class = '')
281
-    {
282
-        if ($for_class !== '') {
283
-            if (! isset($this->_aliases[$for_class])) {
284
-                $this->_aliases[$for_class] = array();
285
-            }
286
-            $this->_aliases[$for_class][$class_name] = $alias;
287
-        }
288
-        $this->_aliases[$class_name] = $alias;
289
-    }
290
-
291
-
292
-
293
-    /**
294
-     * returns TRUE if the provided class name has an alias
295
-     *
296
-     * @param string $class_name
297
-     * @param string $for_class
298
-     * @return bool
299
-     */
300
-    public function has_alias($class_name = '', $for_class = '')
301
-    {
302
-        return isset($this->_aliases[$for_class], $this->_aliases[$for_class][$class_name])
303
-               || (
304
-                   isset($this->_aliases[$class_name])
305
-                   && ! is_array($this->_aliases[$class_name])
306
-               );
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * returns alias for class name if one exists, otherwise returns the original classname
313
-     * functions recursively, so that multiple aliases can be used to drill down to a classname
314
-     *  for example:
315
-     *      if the following two entries were added to the _aliases array:
316
-     *          array(
317
-     *              'interface_alias'           => 'some\namespace\interface'
318
-     *              'some\namespace\interface'  => 'some\namespace\classname'
319
-     *          )
320
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
321
-     *      to load an instance of 'some\namespace\classname'
322
-     *
323
-     * @param string $class_name
324
-     * @param string $for_class
325
-     * @return string
326
-     */
327
-    public function get_alias($class_name = '', $for_class = '')
328
-    {
329
-        if (! $this->has_alias($class_name, $for_class)) {
330
-            return $class_name;
331
-        }
332
-        if ($for_class !== '') {
333
-            return $this->get_alias($this->_aliases[$for_class][$class_name], $for_class);
334
-        }
335
-        return $this->get_alias($this->_aliases[$class_name]);
336
-    }
337
-
338
-
339
-
340
-    /**
341
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
342
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
343
-     * This is done by using the following class constants:
344
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
345
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
346
-     */
347
-    protected function _register_core_dependencies()
348
-    {
349
-        $this->_dependency_map = array(
350
-            'EE_Request_Handler'                                                                                          => array(
351
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
352
-            ),
353
-            'EE_System'                                                                                                   => array(
354
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
355
-            ),
356
-            'EE_Session'                                                                                                  => array(
357
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
358
-                'EE_Encryption'                                           => EE_Dependency_Map::load_from_cache,
359
-            ),
360
-            'EE_Cart'                                                                                                     => array(
361
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
362
-            ),
363
-            'EE_Front_Controller'                                                                                         => array(
364
-                'EE_Registry'              => EE_Dependency_Map::load_from_cache,
365
-                'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
366
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
367
-            ),
368
-            'EE_Messenger_Collection_Loader'                                                                              => array(
369
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
370
-            ),
371
-            'EE_Message_Type_Collection_Loader'                                                                           => array(
372
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
373
-            ),
374
-            'EE_Message_Resource_Manager'                                                                                 => array(
375
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
376
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
377
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
378
-            ),
379
-            'EE_Message_Factory'                                                                                          => array(
380
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
381
-            ),
382
-            'EE_messages'                                                                                                 => array(
383
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
384
-            ),
385
-            'EE_Messages_Generator'                                                                                       => array(
386
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
387
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
388
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
389
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
390
-            ),
391
-            'EE_Messages_Processor'                                                                                       => array(
392
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
393
-            ),
394
-            'EE_Messages_Queue'                                                                                           => array(
395
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
396
-            ),
397
-            'EE_Messages_Template_Defaults'                                                                               => array(
398
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
399
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
400
-            ),
401
-            'EE_Message_To_Generate_From_Request'                                                                         => array(
402
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
403
-                'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
404
-            ),
405
-            'EventEspresso\core\services\commands\CommandBus'                                                             => array(
406
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
407
-            ),
408
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
409
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
410
-            ),
411
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                              => array(
412
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
413
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
414
-            ),
415
-            'EventEspresso\core\services\commands\CommandFactory'                                                              => array(
416
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
417
-            ),
418
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
419
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
420
-            ),
421
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
422
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
423
-            ),
424
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
425
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
426
-            ),
427
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
428
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
429
-            ),
430
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
431
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
432
-            ),
433
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
434
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
435
-            ),
436
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
437
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
438
-            ),
439
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
440
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
441
-            ),
442
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
443
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
444
-            ),
445
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
446
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
447
-            ),
448
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
449
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
450
-            ),
451
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
452
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
453
-            ),
454
-            'EventEspresso\core\services\database\TableManager'                                                           => array(
455
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
456
-            ),
457
-            'EE_Data_Migration_Class_Base'                                                                                => array(
458
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
459
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
460
-            ),
461
-            'EE_DMS_Core_4_1_0'                                                                                           => array(
462
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
463
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
464
-            ),
465
-            'EE_DMS_Core_4_2_0'                                                                                           => array(
466
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
467
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
468
-            ),
469
-            'EE_DMS_Core_4_3_0'                                                                                           => array(
470
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
471
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
472
-            ),
473
-            'EE_DMS_Core_4_4_0'                                                                                           => array(
474
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
475
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
476
-            ),
477
-            'EE_DMS_Core_4_5_0'                                                                                           => array(
478
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
479
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
480
-            ),
481
-            'EE_DMS_Core_4_6_0'                                                                                           => array(
482
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
483
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
484
-            ),
485
-            'EE_DMS_Core_4_7_0'                                                                                           => array(
486
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
487
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
488
-            ),
489
-            'EE_DMS_Core_4_8_0'                                                                                           => array(
490
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
491
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
492
-            ),
493
-            'EE_DMS_Core_4_9_0'                                                                                           => array(
494
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
495
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
496
-            ),
497
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
498
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
499
-            ),
500
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
501
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
502
-            ),
503
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
504
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
505
-            ),
506
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
507
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
508
-            ),
509
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
510
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
511
-            ),
512
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
513
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
514
-            ),
515
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
516
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
517
-            ),
518
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
519
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
520
-            ),
521
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
522
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
523
-            ),
524
-        );
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     * Registers how core classes are loaded.
531
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
532
-     *        'EE_Request_Handler' => 'load_core'
533
-     *        'EE_Messages_Queue'  => 'load_lib'
534
-     *        'EEH_Debug_Tools'    => 'load_helper'
535
-     * or, if greater control is required, by providing a custom closure. For example:
536
-     *        'Some_Class' => function () {
537
-     *            return new Some_Class();
538
-     *        },
539
-     * This is required for instantiating dependencies
540
-     * where an interface has been type hinted in a class constructor. For example:
541
-     *        'Required_Interface' => function () {
542
-     *            return new A_Class_That_Implements_Required_Interface();
543
-     *        },
544
-     */
545
-    protected function _register_core_class_loaders()
546
-    {
547
-        //for PHP5.3 compat, we need to register any properties called here in a variable because `$this` cannot
548
-        //be used in a closure.
549
-        $request = &$this->_request;
550
-        $response = &$this->_response;
551
-        $loader = &$this->loader;
552
-        $this->_class_loaders = array(
553
-            //load_core
554
-            'EE_Capabilities'                      => 'load_core',
555
-            'EE_Encryption'                        => 'load_core',
556
-            'EE_Front_Controller'                  => 'load_core',
557
-            'EE_Module_Request_Router'             => 'load_core',
558
-            'EE_Registry'                          => 'load_core',
559
-            'EE_Request'                           => function () use (&$request) {
560
-                return $request;
561
-            },
562
-            'EE_Response'                          => function () use (&$response) {
563
-                return $response;
564
-            },
565
-            'EE_Request_Handler'                   => 'load_core',
566
-            'EE_Session'                           => 'load_core',
567
-            'EE_System'                            => 'load_core',
568
-            //load_lib
569
-            'EE_Message_Resource_Manager'          => 'load_lib',
570
-            'EE_Message_Type_Collection'           => 'load_lib',
571
-            'EE_Message_Type_Collection_Loader'    => 'load_lib',
572
-            'EE_Messenger_Collection'              => 'load_lib',
573
-            'EE_Messenger_Collection_Loader'       => 'load_lib',
574
-            'EE_Messages_Processor'                => 'load_lib',
575
-            'EE_Message_Repository'                => 'load_lib',
576
-            'EE_Messages_Queue'                    => 'load_lib',
577
-            'EE_Messages_Data_Handler_Collection'  => 'load_lib',
578
-            'EE_Message_Template_Group_Collection' => 'load_lib',
579
-            'EE_Messages_Generator'                => function () {
580
-                return EE_Registry::instance()->load_lib('Messages_Generator', array(), false, false);
581
-            },
582
-            'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
583
-                return EE_Registry::instance()->load_lib('Messages_Template_Defaults', $arguments, false, false);
584
-            },
585
-            //load_model
586
-            'EEM_Attendee'                         => 'load_model',
587
-            'EEM_Message_Template_Group'           => 'load_model',
588
-            'EEM_Message_Template'                 => 'load_model',
589
-            //load_helper
590
-            'EEH_Parse_Shortcodes'                 => function () {
591
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
592
-                    return new EEH_Parse_Shortcodes();
593
-                }
594
-                return null;
595
-            },
596
-            'EventEspresso\core\services\loaders\Loader' => function () use (&$loader) {
597
-                return $loader;
598
-            },
599
-        );
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * can be used for supplying alternate names for classes,
606
-     * or for connecting interface names to instantiable classes
607
-     */
608
-    protected function _register_core_aliases()
609
-    {
610
-        $this->_aliases = array(
611
-            'CommandBusInterface'                                                 => 'EventEspresso\core\services\commands\CommandBusInterface',
612
-            'EventEspresso\core\services\commands\CommandBusInterface'            => 'EventEspresso\core\services\commands\CommandBus',
613
-            'CommandHandlerManagerInterface'                                      => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
614
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface' => 'EventEspresso\core\services\commands\CommandHandlerManager',
615
-            'CapChecker'                                                          => 'EventEspresso\core\services\commands\middleware\CapChecker',
616
-            'AddActionHook'                                                       => 'EventEspresso\core\services\commands\middleware\AddActionHook',
617
-            'CapabilitiesChecker'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
618
-            'CapabilitiesCheckerInterface'                                        => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
619
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
620
-            'CreateRegistrationService'                                           => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
621
-            'CreateRegCodeCommandHandler'                                         => 'EventEspresso\core\services\commands\registration\CreateRegCodeCommand',
622
-            'CreateRegUrlLinkCommandHandler'                                      => 'EventEspresso\core\services\commands\registration\CreateRegUrlLinkCommand',
623
-            'CreateRegistrationCommandHandler'                                    => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
624
-            'CopyRegistrationDetailsCommandHandler'                               => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
625
-            'CopyRegistrationPaymentsCommandHandler'                              => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
626
-            'CancelRegistrationAndTicketLineItemCommandHandler'                   => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
627
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'           => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
628
-            'CreateTicketLineItemCommandHandler'                                  => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
629
-            'TableManager'                                                        => 'EventEspresso\core\services\database\TableManager',
630
-            'TableAnalysis'                                                       => 'EventEspresso\core\services\database\TableAnalysis',
631
-            'CreateTransactionCommandHandler'                                     => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
632
-            'CreateAttendeeCommandHandler'                                        => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
633
-            'EspressoShortcode'                                                   => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
634
-            'ShortcodeInterface'                                                  => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
635
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'           => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
636
-            'EventEspresso\core\services\cache\CacheStorageInterface'             => 'EventEspresso\core\services\cache\TransientCacheStorage',
637
-            'LoaderInterface'                                                     => 'EventEspresso\core\services\loaders\LoaderInterface',
638
-            'EventEspresso\core\services\loaders\LoaderInterface'                 => 'EventEspresso\core\services\loaders\Loader',
639
-            'CommandFactoryInterface'                                             => 'EventEspresso\core\services\commands\CommandFactoryInterface',
640
-            'EventEspresso\core\services\commands\CommandFactoryInterface'        => 'EventEspresso\core\services\commands\CommandFactory',
641
-            'NoticeConverterInterface'                                            => 'EventEspresso\core\services\notices\NoticeConverterInterface',
642
-            'EventEspresso\core\services\notices\NoticeConverterInterface'        => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
643
-            'NoticesContainerInterface'                                            => 'EventEspresso\core\services\notices\NoticesContainerInterface',
644
-            'EventEspresso\core\services\notices\NoticesContainerInterface'        => 'EventEspresso\core\services\notices\NoticesContainer',
645
-        );
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
652
-     * request Primarily used by unit tests.
653
-     */
654
-    public function reset()
655
-    {
656
-        $this->_register_core_class_loaders();
657
-        $this->_register_core_dependencies();
658
-    }
25
+	/**
26
+	 * This means that the requested class dependency is not present in the dependency map
27
+	 */
28
+	const not_registered = 0;
29
+
30
+
31
+	/**
32
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
33
+	 */
34
+	const load_new_object = 1;
35
+
36
+	/**
37
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
38
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
39
+	 */
40
+	const load_from_cache = 2;
41
+
42
+	/**
43
+	 * @type EE_Dependency_Map $_instance
44
+	 */
45
+	protected static $_instance;
46
+
47
+	/**
48
+	 * @type EE_Request $request
49
+	 */
50
+	protected $_request;
51
+
52
+	/**
53
+	 * @type EE_Response $response
54
+	 */
55
+	protected $_response;
56
+
57
+	/**
58
+	 * @type LoaderInterface $loader
59
+	 */
60
+	protected $loader;
61
+
62
+	/**
63
+	 * @type array $_dependency_map
64
+	 */
65
+	protected $_dependency_map = array();
66
+
67
+	/**
68
+	 * @type array $_class_loaders
69
+	 */
70
+	protected $_class_loaders = array();
71
+
72
+	/**
73
+	 * @type array $_aliases
74
+	 */
75
+	protected $_aliases = array();
76
+
77
+
78
+
79
+	/**
80
+	 * EE_Dependency_Map constructor.
81
+	 *
82
+	 * @param EE_Request  $request
83
+	 * @param EE_Response $response
84
+	 */
85
+	protected function __construct(EE_Request $request, EE_Response $response)
86
+	{
87
+		$this->_request = $request;
88
+		$this->_response = $response;
89
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
90
+		do_action('EE_Dependency_Map____construct');
91
+	}
92
+
93
+
94
+
95
+	/**
96
+	 * @throws InvalidDataTypeException
97
+	 * @throws InvalidInterfaceException
98
+	 * @throws InvalidArgumentException
99
+	 */
100
+	public function initialize()
101
+	{
102
+		$this->_register_core_dependencies();
103
+		$this->_register_core_class_loaders();
104
+		$this->_register_core_aliases();
105
+	}
106
+
107
+
108
+
109
+	/**
110
+	 * @singleton method used to instantiate class object
111
+	 * @access    public
112
+	 * @param EE_Request  $request
113
+	 * @param EE_Response $response
114
+	 * @return EE_Dependency_Map
115
+	 */
116
+	public static function instance(EE_Request $request = null, EE_Response $response = null)
117
+	{
118
+		// check if class object is instantiated, and instantiated properly
119
+		if (! self::$_instance instanceof EE_Dependency_Map) {
120
+			self::$_instance = new EE_Dependency_Map($request, $response);
121
+		}
122
+		return self::$_instance;
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * @param LoaderInterface $loader
129
+	 */
130
+	public function setLoader(LoaderInterface $loader)
131
+	{
132
+		$this->loader = $loader;
133
+	}
134
+
135
+
136
+
137
+	/**
138
+	 * @param string $class
139
+	 * @param array  $dependencies
140
+	 * @return boolean
141
+	 */
142
+	public static function register_dependencies($class, $dependencies)
143
+	{
144
+		$class = trim($class,'\\');
145
+		if (! isset(self::$_instance->_dependency_map[$class])) {
146
+			// we need to make sure that any aliases used when registering a dependency
147
+			// get resolved to the correct class name
148
+			foreach ((array)$dependencies as $dependency => $load_source) {
149
+				$alias = self::$_instance->get_alias($dependency);
150
+				unset($dependencies[$dependency]);
151
+				$dependencies[$alias] = $load_source;
152
+			}
153
+			self::$_instance->_dependency_map[$class] = (array)$dependencies;
154
+			return true;
155
+		}
156
+		return false;
157
+	}
158
+
159
+
160
+
161
+	/**
162
+	 * @param string $class_name
163
+	 * @param string $loader
164
+	 * @return bool
165
+	 * @throws EE_Error
166
+	 */
167
+	public static function register_class_loader($class_name, $loader = 'load_core')
168
+	{
169
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
170
+		if (
171
+			! is_callable($loader)
172
+			&& (
173
+				strpos($loader, 'load_') !== 0
174
+				|| ! method_exists('EE_Registry', $loader)
175
+			)
176
+		) {
177
+			throw new EE_Error(
178
+				sprintf(
179
+					esc_html__('"%1$s" is not a valid loader method on EE_Registry.', 'event_espresso'),
180
+					$loader
181
+				)
182
+			);
183
+		}
184
+		$class_name = self::$_instance->get_alias($class_name);
185
+		if (! isset(self::$_instance->_class_loaders[$class_name])) {
186
+			self::$_instance->_class_loaders[$class_name] = $loader;
187
+			return true;
188
+		}
189
+		return false;
190
+	}
191
+
192
+
193
+
194
+	/**
195
+	 * @return array
196
+	 */
197
+	public function dependency_map()
198
+	{
199
+		return $this->_dependency_map;
200
+	}
201
+
202
+
203
+
204
+	/**
205
+	 * returns TRUE if dependency map contains a listing for the provided class name
206
+	 *
207
+	 * @param string $class_name
208
+	 * @return boolean
209
+	 */
210
+	public function has($class_name = '')
211
+	{
212
+		return isset($this->_dependency_map[$class_name]) ? true : false;
213
+	}
214
+
215
+
216
+
217
+	/**
218
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
219
+	 *
220
+	 * @param string $class_name
221
+	 * @param string $dependency
222
+	 * @return bool
223
+	 */
224
+	public function has_dependency_for_class($class_name = '', $dependency = '')
225
+	{
226
+		$dependency = $this->get_alias($dependency);
227
+		return isset($this->_dependency_map[$class_name], $this->_dependency_map[$class_name][$dependency])
228
+			? true
229
+			: false;
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
236
+	 *
237
+	 * @param string $class_name
238
+	 * @param string $dependency
239
+	 * @return int
240
+	 */
241
+	public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
242
+	{
243
+		$dependency = $this->get_alias($dependency);
244
+		return $this->has_dependency_for_class($class_name, $dependency)
245
+			? $this->_dependency_map[$class_name][$dependency]
246
+			: EE_Dependency_Map::not_registered;
247
+	}
248
+
249
+
250
+
251
+	/**
252
+	 * @param string $class_name
253
+	 * @return string | Closure
254
+	 */
255
+	public function class_loader($class_name)
256
+	{
257
+		$class_name = $this->get_alias($class_name);
258
+		return isset($this->_class_loaders[$class_name]) ? $this->_class_loaders[$class_name] : '';
259
+	}
260
+
261
+
262
+
263
+	/**
264
+	 * @return array
265
+	 */
266
+	public function class_loaders()
267
+	{
268
+		return $this->_class_loaders;
269
+	}
270
+
271
+
272
+
273
+	/**
274
+	 * adds an alias for a classname
275
+	 *
276
+	 * @param string $class_name the class name that should be used (concrete class to replace interface)
277
+	 * @param string $alias      the class name that would be type hinted for (abstract parent or interface)
278
+	 * @param string $for_class  the class that has the dependency (is type hinting for the interface)
279
+	 */
280
+	public function add_alias($class_name, $alias, $for_class = '')
281
+	{
282
+		if ($for_class !== '') {
283
+			if (! isset($this->_aliases[$for_class])) {
284
+				$this->_aliases[$for_class] = array();
285
+			}
286
+			$this->_aliases[$for_class][$class_name] = $alias;
287
+		}
288
+		$this->_aliases[$class_name] = $alias;
289
+	}
290
+
291
+
292
+
293
+	/**
294
+	 * returns TRUE if the provided class name has an alias
295
+	 *
296
+	 * @param string $class_name
297
+	 * @param string $for_class
298
+	 * @return bool
299
+	 */
300
+	public function has_alias($class_name = '', $for_class = '')
301
+	{
302
+		return isset($this->_aliases[$for_class], $this->_aliases[$for_class][$class_name])
303
+			   || (
304
+				   isset($this->_aliases[$class_name])
305
+				   && ! is_array($this->_aliases[$class_name])
306
+			   );
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * returns alias for class name if one exists, otherwise returns the original classname
313
+	 * functions recursively, so that multiple aliases can be used to drill down to a classname
314
+	 *  for example:
315
+	 *      if the following two entries were added to the _aliases array:
316
+	 *          array(
317
+	 *              'interface_alias'           => 'some\namespace\interface'
318
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
319
+	 *          )
320
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
321
+	 *      to load an instance of 'some\namespace\classname'
322
+	 *
323
+	 * @param string $class_name
324
+	 * @param string $for_class
325
+	 * @return string
326
+	 */
327
+	public function get_alias($class_name = '', $for_class = '')
328
+	{
329
+		if (! $this->has_alias($class_name, $for_class)) {
330
+			return $class_name;
331
+		}
332
+		if ($for_class !== '') {
333
+			return $this->get_alias($this->_aliases[$for_class][$class_name], $for_class);
334
+		}
335
+		return $this->get_alias($this->_aliases[$class_name]);
336
+	}
337
+
338
+
339
+
340
+	/**
341
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
342
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
343
+	 * This is done by using the following class constants:
344
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
345
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
346
+	 */
347
+	protected function _register_core_dependencies()
348
+	{
349
+		$this->_dependency_map = array(
350
+			'EE_Request_Handler'                                                                                          => array(
351
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
352
+			),
353
+			'EE_System'                                                                                                   => array(
354
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
355
+			),
356
+			'EE_Session'                                                                                                  => array(
357
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
358
+				'EE_Encryption'                                           => EE_Dependency_Map::load_from_cache,
359
+			),
360
+			'EE_Cart'                                                                                                     => array(
361
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
362
+			),
363
+			'EE_Front_Controller'                                                                                         => array(
364
+				'EE_Registry'              => EE_Dependency_Map::load_from_cache,
365
+				'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
366
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
367
+			),
368
+			'EE_Messenger_Collection_Loader'                                                                              => array(
369
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
370
+			),
371
+			'EE_Message_Type_Collection_Loader'                                                                           => array(
372
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
373
+			),
374
+			'EE_Message_Resource_Manager'                                                                                 => array(
375
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
376
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
377
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
378
+			),
379
+			'EE_Message_Factory'                                                                                          => array(
380
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
381
+			),
382
+			'EE_messages'                                                                                                 => array(
383
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
384
+			),
385
+			'EE_Messages_Generator'                                                                                       => array(
386
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
387
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
388
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
389
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
390
+			),
391
+			'EE_Messages_Processor'                                                                                       => array(
392
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
393
+			),
394
+			'EE_Messages_Queue'                                                                                           => array(
395
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
396
+			),
397
+			'EE_Messages_Template_Defaults'                                                                               => array(
398
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
399
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
400
+			),
401
+			'EE_Message_To_Generate_From_Request'                                                                         => array(
402
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
403
+				'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
404
+			),
405
+			'EventEspresso\core\services\commands\CommandBus'                                                             => array(
406
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
407
+			),
408
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
409
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
410
+			),
411
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                              => array(
412
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
413
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
414
+			),
415
+			'EventEspresso\core\services\commands\CommandFactory'                                                              => array(
416
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
417
+			),
418
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
419
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
420
+			),
421
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
422
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
423
+			),
424
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
425
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
426
+			),
427
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
428
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
429
+			),
430
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
431
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
432
+			),
433
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
434
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
435
+			),
436
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
437
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
438
+			),
439
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
440
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
441
+			),
442
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
443
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
444
+			),
445
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
446
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
447
+			),
448
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
449
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
450
+			),
451
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
452
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
453
+			),
454
+			'EventEspresso\core\services\database\TableManager'                                                           => array(
455
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
456
+			),
457
+			'EE_Data_Migration_Class_Base'                                                                                => array(
458
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
459
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
460
+			),
461
+			'EE_DMS_Core_4_1_0'                                                                                           => array(
462
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
463
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
464
+			),
465
+			'EE_DMS_Core_4_2_0'                                                                                           => array(
466
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
467
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
468
+			),
469
+			'EE_DMS_Core_4_3_0'                                                                                           => array(
470
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
471
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
472
+			),
473
+			'EE_DMS_Core_4_4_0'                                                                                           => array(
474
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
475
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
476
+			),
477
+			'EE_DMS_Core_4_5_0'                                                                                           => array(
478
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
479
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
480
+			),
481
+			'EE_DMS_Core_4_6_0'                                                                                           => array(
482
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
483
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
484
+			),
485
+			'EE_DMS_Core_4_7_0'                                                                                           => array(
486
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
487
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
488
+			),
489
+			'EE_DMS_Core_4_8_0'                                                                                           => array(
490
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
491
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
492
+			),
493
+			'EE_DMS_Core_4_9_0'                                                                                           => array(
494
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
495
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
496
+			),
497
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
498
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
499
+			),
500
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
501
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
502
+			),
503
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
504
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
505
+			),
506
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
507
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
508
+			),
509
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
510
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
511
+			),
512
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
513
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
514
+			),
515
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
516
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
517
+			),
518
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
519
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
520
+			),
521
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
522
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
523
+			),
524
+		);
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 * Registers how core classes are loaded.
531
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
532
+	 *        'EE_Request_Handler' => 'load_core'
533
+	 *        'EE_Messages_Queue'  => 'load_lib'
534
+	 *        'EEH_Debug_Tools'    => 'load_helper'
535
+	 * or, if greater control is required, by providing a custom closure. For example:
536
+	 *        'Some_Class' => function () {
537
+	 *            return new Some_Class();
538
+	 *        },
539
+	 * This is required for instantiating dependencies
540
+	 * where an interface has been type hinted in a class constructor. For example:
541
+	 *        'Required_Interface' => function () {
542
+	 *            return new A_Class_That_Implements_Required_Interface();
543
+	 *        },
544
+	 */
545
+	protected function _register_core_class_loaders()
546
+	{
547
+		//for PHP5.3 compat, we need to register any properties called here in a variable because `$this` cannot
548
+		//be used in a closure.
549
+		$request = &$this->_request;
550
+		$response = &$this->_response;
551
+		$loader = &$this->loader;
552
+		$this->_class_loaders = array(
553
+			//load_core
554
+			'EE_Capabilities'                      => 'load_core',
555
+			'EE_Encryption'                        => 'load_core',
556
+			'EE_Front_Controller'                  => 'load_core',
557
+			'EE_Module_Request_Router'             => 'load_core',
558
+			'EE_Registry'                          => 'load_core',
559
+			'EE_Request'                           => function () use (&$request) {
560
+				return $request;
561
+			},
562
+			'EE_Response'                          => function () use (&$response) {
563
+				return $response;
564
+			},
565
+			'EE_Request_Handler'                   => 'load_core',
566
+			'EE_Session'                           => 'load_core',
567
+			'EE_System'                            => 'load_core',
568
+			//load_lib
569
+			'EE_Message_Resource_Manager'          => 'load_lib',
570
+			'EE_Message_Type_Collection'           => 'load_lib',
571
+			'EE_Message_Type_Collection_Loader'    => 'load_lib',
572
+			'EE_Messenger_Collection'              => 'load_lib',
573
+			'EE_Messenger_Collection_Loader'       => 'load_lib',
574
+			'EE_Messages_Processor'                => 'load_lib',
575
+			'EE_Message_Repository'                => 'load_lib',
576
+			'EE_Messages_Queue'                    => 'load_lib',
577
+			'EE_Messages_Data_Handler_Collection'  => 'load_lib',
578
+			'EE_Message_Template_Group_Collection' => 'load_lib',
579
+			'EE_Messages_Generator'                => function () {
580
+				return EE_Registry::instance()->load_lib('Messages_Generator', array(), false, false);
581
+			},
582
+			'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
583
+				return EE_Registry::instance()->load_lib('Messages_Template_Defaults', $arguments, false, false);
584
+			},
585
+			//load_model
586
+			'EEM_Attendee'                         => 'load_model',
587
+			'EEM_Message_Template_Group'           => 'load_model',
588
+			'EEM_Message_Template'                 => 'load_model',
589
+			//load_helper
590
+			'EEH_Parse_Shortcodes'                 => function () {
591
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
592
+					return new EEH_Parse_Shortcodes();
593
+				}
594
+				return null;
595
+			},
596
+			'EventEspresso\core\services\loaders\Loader' => function () use (&$loader) {
597
+				return $loader;
598
+			},
599
+		);
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * can be used for supplying alternate names for classes,
606
+	 * or for connecting interface names to instantiable classes
607
+	 */
608
+	protected function _register_core_aliases()
609
+	{
610
+		$this->_aliases = array(
611
+			'CommandBusInterface'                                                 => 'EventEspresso\core\services\commands\CommandBusInterface',
612
+			'EventEspresso\core\services\commands\CommandBusInterface'            => 'EventEspresso\core\services\commands\CommandBus',
613
+			'CommandHandlerManagerInterface'                                      => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
614
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface' => 'EventEspresso\core\services\commands\CommandHandlerManager',
615
+			'CapChecker'                                                          => 'EventEspresso\core\services\commands\middleware\CapChecker',
616
+			'AddActionHook'                                                       => 'EventEspresso\core\services\commands\middleware\AddActionHook',
617
+			'CapabilitiesChecker'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
618
+			'CapabilitiesCheckerInterface'                                        => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
619
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
620
+			'CreateRegistrationService'                                           => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
621
+			'CreateRegCodeCommandHandler'                                         => 'EventEspresso\core\services\commands\registration\CreateRegCodeCommand',
622
+			'CreateRegUrlLinkCommandHandler'                                      => 'EventEspresso\core\services\commands\registration\CreateRegUrlLinkCommand',
623
+			'CreateRegistrationCommandHandler'                                    => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
624
+			'CopyRegistrationDetailsCommandHandler'                               => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
625
+			'CopyRegistrationPaymentsCommandHandler'                              => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
626
+			'CancelRegistrationAndTicketLineItemCommandHandler'                   => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
627
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'           => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
628
+			'CreateTicketLineItemCommandHandler'                                  => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
629
+			'TableManager'                                                        => 'EventEspresso\core\services\database\TableManager',
630
+			'TableAnalysis'                                                       => 'EventEspresso\core\services\database\TableAnalysis',
631
+			'CreateTransactionCommandHandler'                                     => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
632
+			'CreateAttendeeCommandHandler'                                        => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
633
+			'EspressoShortcode'                                                   => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
634
+			'ShortcodeInterface'                                                  => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
635
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'           => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
636
+			'EventEspresso\core\services\cache\CacheStorageInterface'             => 'EventEspresso\core\services\cache\TransientCacheStorage',
637
+			'LoaderInterface'                                                     => 'EventEspresso\core\services\loaders\LoaderInterface',
638
+			'EventEspresso\core\services\loaders\LoaderInterface'                 => 'EventEspresso\core\services\loaders\Loader',
639
+			'CommandFactoryInterface'                                             => 'EventEspresso\core\services\commands\CommandFactoryInterface',
640
+			'EventEspresso\core\services\commands\CommandFactoryInterface'        => 'EventEspresso\core\services\commands\CommandFactory',
641
+			'NoticeConverterInterface'                                            => 'EventEspresso\core\services\notices\NoticeConverterInterface',
642
+			'EventEspresso\core\services\notices\NoticeConverterInterface'        => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
643
+			'NoticesContainerInterface'                                            => 'EventEspresso\core\services\notices\NoticesContainerInterface',
644
+			'EventEspresso\core\services\notices\NoticesContainerInterface'        => 'EventEspresso\core\services\notices\NoticesContainer',
645
+		);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
652
+	 * request Primarily used by unit tests.
653
+	 */
654
+	public function reset()
655
+	{
656
+		$this->_register_core_class_loaders();
657
+		$this->_register_core_dependencies();
658
+	}
659 659
 
660 660
 
661 661
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\InvalidInterfaceException;
4 4
 use EventEspresso\core\services\loaders\LoaderInterface;
5 5
 
6
-if (! defined('EVENT_ESPRESSO_VERSION')) {
6
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
7 7
     exit('No direct script access allowed');
8 8
 }
9 9
 
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
     public static function instance(EE_Request $request = null, EE_Response $response = null)
117 117
     {
118 118
         // check if class object is instantiated, and instantiated properly
119
-        if (! self::$_instance instanceof EE_Dependency_Map) {
119
+        if ( ! self::$_instance instanceof EE_Dependency_Map) {
120 120
             self::$_instance = new EE_Dependency_Map($request, $response);
121 121
         }
122 122
         return self::$_instance;
@@ -141,16 +141,16 @@  discard block
 block discarded – undo
141 141
      */
142 142
     public static function register_dependencies($class, $dependencies)
143 143
     {
144
-        $class = trim($class,'\\');
145
-        if (! isset(self::$_instance->_dependency_map[$class])) {
144
+        $class = trim($class, '\\');
145
+        if ( ! isset(self::$_instance->_dependency_map[$class])) {
146 146
             // we need to make sure that any aliases used when registering a dependency
147 147
             // get resolved to the correct class name
148
-            foreach ((array)$dependencies as $dependency => $load_source) {
148
+            foreach ((array) $dependencies as $dependency => $load_source) {
149 149
                 $alias = self::$_instance->get_alias($dependency);
150 150
                 unset($dependencies[$dependency]);
151 151
                 $dependencies[$alias] = $load_source;
152 152
             }
153
-            self::$_instance->_dependency_map[$class] = (array)$dependencies;
153
+            self::$_instance->_dependency_map[$class] = (array) $dependencies;
154 154
             return true;
155 155
         }
156 156
         return false;
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
             );
183 183
         }
184 184
         $class_name = self::$_instance->get_alias($class_name);
185
-        if (! isset(self::$_instance->_class_loaders[$class_name])) {
185
+        if ( ! isset(self::$_instance->_class_loaders[$class_name])) {
186 186
             self::$_instance->_class_loaders[$class_name] = $loader;
187 187
             return true;
188 188
         }
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
     public function add_alias($class_name, $alias, $for_class = '')
281 281
     {
282 282
         if ($for_class !== '') {
283
-            if (! isset($this->_aliases[$for_class])) {
283
+            if ( ! isset($this->_aliases[$for_class])) {
284 284
                 $this->_aliases[$for_class] = array();
285 285
             }
286 286
             $this->_aliases[$for_class][$class_name] = $alias;
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
      */
327 327
     public function get_alias($class_name = '', $for_class = '')
328 328
     {
329
-        if (! $this->has_alias($class_name, $for_class)) {
329
+        if ( ! $this->has_alias($class_name, $for_class)) {
330 330
             return $class_name;
331 331
         }
332 332
         if ($for_class !== '') {
@@ -556,10 +556,10 @@  discard block
 block discarded – undo
556 556
             'EE_Front_Controller'                  => 'load_core',
557 557
             'EE_Module_Request_Router'             => 'load_core',
558 558
             'EE_Registry'                          => 'load_core',
559
-            'EE_Request'                           => function () use (&$request) {
559
+            'EE_Request'                           => function() use (&$request) {
560 560
                 return $request;
561 561
             },
562
-            'EE_Response'                          => function () use (&$response) {
562
+            'EE_Response'                          => function() use (&$response) {
563 563
                 return $response;
564 564
             },
565 565
             'EE_Request_Handler'                   => 'load_core',
@@ -576,10 +576,10 @@  discard block
 block discarded – undo
576 576
             'EE_Messages_Queue'                    => 'load_lib',
577 577
             'EE_Messages_Data_Handler_Collection'  => 'load_lib',
578 578
             'EE_Message_Template_Group_Collection' => 'load_lib',
579
-            'EE_Messages_Generator'                => function () {
579
+            'EE_Messages_Generator'                => function() {
580 580
                 return EE_Registry::instance()->load_lib('Messages_Generator', array(), false, false);
581 581
             },
582
-            'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
582
+            'EE_Messages_Template_Defaults'        => function($arguments = array()) {
583 583
                 return EE_Registry::instance()->load_lib('Messages_Template_Defaults', $arguments, false, false);
584 584
             },
585 585
             //load_model
@@ -587,13 +587,13 @@  discard block
 block discarded – undo
587 587
             'EEM_Message_Template_Group'           => 'load_model',
588 588
             'EEM_Message_Template'                 => 'load_model',
589 589
             //load_helper
590
-            'EEH_Parse_Shortcodes'                 => function () {
590
+            'EEH_Parse_Shortcodes'                 => function() {
591 591
                 if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
592 592
                     return new EEH_Parse_Shortcodes();
593 593
                 }
594 594
                 return null;
595 595
             },
596
-            'EventEspresso\core\services\loaders\Loader' => function () use (&$loader) {
596
+            'EventEspresso\core\services\loaders\Loader' => function() use (&$loader) {
597 597
                 return $loader;
598 598
             },
599 599
         );
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 1 patch
Indentation   +1394 added lines, -1394 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -14,1482 +14,1482 @@  discard block
 block discarded – undo
14 14
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
15 15
 {
16 16
 
17
-    /**
18
-     * cached value for the the logical active status for the event
19
-     *
20
-     * @see get_active_status()
21
-     * @var string
22
-     */
23
-    protected $_active_status = '';
24
-
25
-    /**
26
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
27
-     *
28
-     * @var EE_Datetime
29
-     */
30
-    protected $_Primary_Datetime;
31
-
32
-
33
-
34
-    /**
35
-     * @param array  $props_n_values          incoming values
36
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
37
-     *                                        used.)
38
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
39
-     *                                        date_format and the second value is the time format
40
-     * @return EE_Event
41
-     * @throws \EE_Error
42
-     */
43
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
-    {
45
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
47
-    }
48
-
49
-
50
-
51
-    /**
52
-     * @param array  $props_n_values  incoming values from the database
53
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
54
-     *                                the website will be used.
55
-     * @return EE_Event
56
-     * @throws \EE_Error
57
-     */
58
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
59
-    {
60
-        return new self($props_n_values, true, $timezone);
61
-    }
62
-
63
-
64
-
65
-    /**
66
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
67
-     *
68
-     * @param string $field_name
69
-     * @param mixed  $field_value
70
-     * @param bool   $use_default
71
-     * @throws \EE_Error
72
-     */
73
-    public function set($field_name, $field_value, $use_default = false)
74
-    {
75
-        switch ($field_name) {
76
-            case 'status' :
77
-                $this->set_status($field_value, $use_default);
78
-                break;
79
-            default :
80
-                parent::set($field_name, $field_value, $use_default);
81
-        }
82
-    }
83
-
84
-
85
-
86
-    /**
87
-     *    set_status
88
-     * Checks if event status is being changed to SOLD OUT
89
-     * and updates event meta data with previous event status
90
-     * so that we can revert things if/when the event is no longer sold out
91
-     *
92
-     * @access public
93
-     * @param string $new_status
94
-     * @param bool   $use_default
95
-     * @return void
96
-     * @throws \EE_Error
97
-     */
98
-    public function set_status($new_status = null, $use_default = false)
99
-    {
100
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
101
-        if (empty($new_status) && ! $use_default) {
102
-            return;
103
-        }
104
-        // get current Event status
105
-        $old_status = $this->status();
106
-        // if status has changed
107
-        if ($old_status !== $new_status) {
108
-            // TO sold_out
109
-            if ($new_status === EEM_Event::sold_out) {
110
-                // save the previous event status so that we can revert if the event is no longer sold out
111
-                $this->add_post_meta('_previous_event_status', $old_status);
112
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
113
-                // OR FROM  sold_out
114
-            } else if ($old_status === EEM_Event::sold_out) {
115
-                $this->delete_post_meta('_previous_event_status');
116
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
117
-            }
118
-            // update status
119
-            parent::set('status', $new_status, $use_default);
120
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
121
-            return;
122
-        } else {
123
-            // even though the old value matches the new value, it's still good to
124
-            // allow the parent set method to have a say
125
-            parent::set('status', $new_status, $use_default);
126
-            return;
127
-        }
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * Gets all the datetimes for this event
134
-     *
135
-     * @param array $query_params like EEM_Base::get_all
136
-     * @return EE_Datetime[]
137
-     * @throws \EE_Error
138
-     */
139
-    public function datetimes($query_params = array())
140
-    {
141
-        return $this->get_many_related('Datetime', $query_params);
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
148
-     *
149
-     * @return EE_Datetime[]
150
-     * @throws \EE_Error
151
-     */
152
-    public function datetimes_in_chronological_order()
153
-    {
154
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
161
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
162
-     * after running our query, so that this timezone isn't set for EVERY query
163
-     * on EEM_Datetime for the rest of the request, no?
164
-     *
165
-     * @param boolean $show_expired whether or not to include expired events
166
-     * @param boolean $show_deleted whether or not to include deleted events
167
-     * @param null    $limit
168
-     * @return \EE_Datetime[]
169
-     * @throws \EE_Error
170
-     */
171
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
172
-    {
173
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
174
-            $this->ID(),
175
-            $show_expired,
176
-            $show_deleted,
177
-            $limit
178
-        );
179
-    }
180
-
181
-
182
-
183
-    /**
184
-     * Returns one related datetime. Mostly only used by some legacy code.
185
-     *
186
-     * @return EE_Datetime
187
-     * @throws \EE_Error
188
-     */
189
-    public function first_datetime()
190
-    {
191
-        return $this->get_first_related('Datetime');
192
-    }
193
-
194
-
195
-
196
-    /**
197
-     * Returns the 'primary' datetime for the event
198
-     *
199
-     * @param bool $try_to_exclude_expired
200
-     * @param bool $try_to_exclude_deleted
201
-     * @return EE_Datetime
202
-     * @throws \EE_Error
203
-     */
204
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
205
-    {
206
-        if ( ! empty ($this->_Primary_Datetime)) {
207
-            return $this->_Primary_Datetime;
208
-        }
209
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
210
-            $this->ID(),
211
-            $try_to_exclude_expired,
212
-            $try_to_exclude_deleted
213
-        );
214
-        return $this->_Primary_Datetime;
215
-    }
216
-
217
-
218
-
219
-    /**
220
-     * Gets all the tickets available for purchase of this event
221
-     *
222
-     * @param array $query_params like EEM_Base::get_all
223
-     * @return EE_Ticket[]
224
-     * @throws \EE_Error
225
-     */
226
-    public function tickets($query_params = array())
227
-    {
228
-        //first get all datetimes
229
-        $datetimes = $this->datetimes_ordered();
230
-        if ( ! $datetimes) {
231
-            return array();
232
-        }
233
-        $datetime_ids = array();
234
-        foreach ($datetimes as $datetime) {
235
-            $datetime_ids[] = $datetime->ID();
236
-        }
237
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
238
-        //if incoming $query_params has where conditions let's merge but not override existing.
239
-        if (is_array($query_params) && isset($query_params[0])) {
240
-            $where_params = array_merge($query_params[0], $where_params);
241
-            unset($query_params[0]);
242
-        }
243
-        //now add $where_params to $query_params
244
-        $query_params[0] = $where_params;
245
-        return EEM_Ticket::instance()->get_all($query_params);
246
-    }
247
-
248
-
249
-
250
-    /**
251
-     * get all unexpired untrashed tickets
252
-     *
253
-     * @return bool|EE_Ticket[]
254
-     * @throws EE_Error
255
-     */
256
-    public function active_tickets()
257
-    {
258
-        return $this->tickets(array(
259
-            array(
260
-                'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
261
-                'TKT_deleted'  => false,
262
-            ),
263
-        ));
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * @return bool
270
-     * @throws \EE_Error
271
-     */
272
-    public function additional_limit()
273
-    {
274
-        return $this->get('EVT_additional_limit');
275
-    }
276
-
277
-
278
-
279
-    /**
280
-     * @return bool
281
-     * @throws \EE_Error
282
-     */
283
-    public function allow_overflow()
284
-    {
285
-        return $this->get('EVT_allow_overflow');
286
-    }
287
-
288
-
289
-
290
-    /**
291
-     * @return bool
292
-     * @throws \EE_Error
293
-     */
294
-    public function created()
295
-    {
296
-        return $this->get('EVT_created');
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     * @return bool
303
-     * @throws \EE_Error
304
-     */
305
-    public function description()
306
-    {
307
-        return $this->get('EVT_desc');
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * Runs do_shortcode and wpautop on the description
314
-     *
315
-     * @return string of html
316
-     * @throws \EE_Error
317
-     */
318
-    public function description_filtered()
319
-    {
320
-        return $this->get_pretty('EVT_desc');
321
-    }
322
-
323
-
324
-
325
-    /**
326
-     * @return bool
327
-     * @throws \EE_Error
328
-     */
329
-    public function display_description()
330
-    {
331
-        return $this->get('EVT_display_desc');
332
-    }
333
-
334
-
335
-
336
-    /**
337
-     * @return bool
338
-     * @throws \EE_Error
339
-     */
340
-    public function display_ticket_selector()
341
-    {
342
-        return (bool)$this->get('EVT_display_ticket_selector');
343
-    }
344
-
17
+	/**
18
+	 * cached value for the the logical active status for the event
19
+	 *
20
+	 * @see get_active_status()
21
+	 * @var string
22
+	 */
23
+	protected $_active_status = '';
24
+
25
+	/**
26
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
27
+	 *
28
+	 * @var EE_Datetime
29
+	 */
30
+	protected $_Primary_Datetime;
31
+
32
+
33
+
34
+	/**
35
+	 * @param array  $props_n_values          incoming values
36
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
37
+	 *                                        used.)
38
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
39
+	 *                                        date_format and the second value is the time format
40
+	 * @return EE_Event
41
+	 * @throws \EE_Error
42
+	 */
43
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
+	{
45
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
47
+	}
48
+
49
+
50
+
51
+	/**
52
+	 * @param array  $props_n_values  incoming values from the database
53
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
54
+	 *                                the website will be used.
55
+	 * @return EE_Event
56
+	 * @throws \EE_Error
57
+	 */
58
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
59
+	{
60
+		return new self($props_n_values, true, $timezone);
61
+	}
62
+
63
+
64
+
65
+	/**
66
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
67
+	 *
68
+	 * @param string $field_name
69
+	 * @param mixed  $field_value
70
+	 * @param bool   $use_default
71
+	 * @throws \EE_Error
72
+	 */
73
+	public function set($field_name, $field_value, $use_default = false)
74
+	{
75
+		switch ($field_name) {
76
+			case 'status' :
77
+				$this->set_status($field_value, $use_default);
78
+				break;
79
+			default :
80
+				parent::set($field_name, $field_value, $use_default);
81
+		}
82
+	}
83
+
84
+
85
+
86
+	/**
87
+	 *    set_status
88
+	 * Checks if event status is being changed to SOLD OUT
89
+	 * and updates event meta data with previous event status
90
+	 * so that we can revert things if/when the event is no longer sold out
91
+	 *
92
+	 * @access public
93
+	 * @param string $new_status
94
+	 * @param bool   $use_default
95
+	 * @return void
96
+	 * @throws \EE_Error
97
+	 */
98
+	public function set_status($new_status = null, $use_default = false)
99
+	{
100
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
101
+		if (empty($new_status) && ! $use_default) {
102
+			return;
103
+		}
104
+		// get current Event status
105
+		$old_status = $this->status();
106
+		// if status has changed
107
+		if ($old_status !== $new_status) {
108
+			// TO sold_out
109
+			if ($new_status === EEM_Event::sold_out) {
110
+				// save the previous event status so that we can revert if the event is no longer sold out
111
+				$this->add_post_meta('_previous_event_status', $old_status);
112
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
113
+				// OR FROM  sold_out
114
+			} else if ($old_status === EEM_Event::sold_out) {
115
+				$this->delete_post_meta('_previous_event_status');
116
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
117
+			}
118
+			// update status
119
+			parent::set('status', $new_status, $use_default);
120
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
121
+			return;
122
+		} else {
123
+			// even though the old value matches the new value, it's still good to
124
+			// allow the parent set method to have a say
125
+			parent::set('status', $new_status, $use_default);
126
+			return;
127
+		}
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * Gets all the datetimes for this event
134
+	 *
135
+	 * @param array $query_params like EEM_Base::get_all
136
+	 * @return EE_Datetime[]
137
+	 * @throws \EE_Error
138
+	 */
139
+	public function datetimes($query_params = array())
140
+	{
141
+		return $this->get_many_related('Datetime', $query_params);
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
148
+	 *
149
+	 * @return EE_Datetime[]
150
+	 * @throws \EE_Error
151
+	 */
152
+	public function datetimes_in_chronological_order()
153
+	{
154
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
161
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
162
+	 * after running our query, so that this timezone isn't set for EVERY query
163
+	 * on EEM_Datetime for the rest of the request, no?
164
+	 *
165
+	 * @param boolean $show_expired whether or not to include expired events
166
+	 * @param boolean $show_deleted whether or not to include deleted events
167
+	 * @param null    $limit
168
+	 * @return \EE_Datetime[]
169
+	 * @throws \EE_Error
170
+	 */
171
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
172
+	{
173
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
174
+			$this->ID(),
175
+			$show_expired,
176
+			$show_deleted,
177
+			$limit
178
+		);
179
+	}
180
+
181
+
182
+
183
+	/**
184
+	 * Returns one related datetime. Mostly only used by some legacy code.
185
+	 *
186
+	 * @return EE_Datetime
187
+	 * @throws \EE_Error
188
+	 */
189
+	public function first_datetime()
190
+	{
191
+		return $this->get_first_related('Datetime');
192
+	}
193
+
194
+
195
+
196
+	/**
197
+	 * Returns the 'primary' datetime for the event
198
+	 *
199
+	 * @param bool $try_to_exclude_expired
200
+	 * @param bool $try_to_exclude_deleted
201
+	 * @return EE_Datetime
202
+	 * @throws \EE_Error
203
+	 */
204
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
205
+	{
206
+		if ( ! empty ($this->_Primary_Datetime)) {
207
+			return $this->_Primary_Datetime;
208
+		}
209
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
210
+			$this->ID(),
211
+			$try_to_exclude_expired,
212
+			$try_to_exclude_deleted
213
+		);
214
+		return $this->_Primary_Datetime;
215
+	}
216
+
217
+
218
+
219
+	/**
220
+	 * Gets all the tickets available for purchase of this event
221
+	 *
222
+	 * @param array $query_params like EEM_Base::get_all
223
+	 * @return EE_Ticket[]
224
+	 * @throws \EE_Error
225
+	 */
226
+	public function tickets($query_params = array())
227
+	{
228
+		//first get all datetimes
229
+		$datetimes = $this->datetimes_ordered();
230
+		if ( ! $datetimes) {
231
+			return array();
232
+		}
233
+		$datetime_ids = array();
234
+		foreach ($datetimes as $datetime) {
235
+			$datetime_ids[] = $datetime->ID();
236
+		}
237
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
238
+		//if incoming $query_params has where conditions let's merge but not override existing.
239
+		if (is_array($query_params) && isset($query_params[0])) {
240
+			$where_params = array_merge($query_params[0], $where_params);
241
+			unset($query_params[0]);
242
+		}
243
+		//now add $where_params to $query_params
244
+		$query_params[0] = $where_params;
245
+		return EEM_Ticket::instance()->get_all($query_params);
246
+	}
247
+
248
+
249
+
250
+	/**
251
+	 * get all unexpired untrashed tickets
252
+	 *
253
+	 * @return bool|EE_Ticket[]
254
+	 * @throws EE_Error
255
+	 */
256
+	public function active_tickets()
257
+	{
258
+		return $this->tickets(array(
259
+			array(
260
+				'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
261
+				'TKT_deleted'  => false,
262
+			),
263
+		));
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * @return bool
270
+	 * @throws \EE_Error
271
+	 */
272
+	public function additional_limit()
273
+	{
274
+		return $this->get('EVT_additional_limit');
275
+	}
276
+
277
+
278
+
279
+	/**
280
+	 * @return bool
281
+	 * @throws \EE_Error
282
+	 */
283
+	public function allow_overflow()
284
+	{
285
+		return $this->get('EVT_allow_overflow');
286
+	}
287
+
288
+
289
+
290
+	/**
291
+	 * @return bool
292
+	 * @throws \EE_Error
293
+	 */
294
+	public function created()
295
+	{
296
+		return $this->get('EVT_created');
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 * @return bool
303
+	 * @throws \EE_Error
304
+	 */
305
+	public function description()
306
+	{
307
+		return $this->get('EVT_desc');
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * Runs do_shortcode and wpautop on the description
314
+	 *
315
+	 * @return string of html
316
+	 * @throws \EE_Error
317
+	 */
318
+	public function description_filtered()
319
+	{
320
+		return $this->get_pretty('EVT_desc');
321
+	}
322
+
323
+
324
+
325
+	/**
326
+	 * @return bool
327
+	 * @throws \EE_Error
328
+	 */
329
+	public function display_description()
330
+	{
331
+		return $this->get('EVT_display_desc');
332
+	}
333
+
334
+
335
+
336
+	/**
337
+	 * @return bool
338
+	 * @throws \EE_Error
339
+	 */
340
+	public function display_ticket_selector()
341
+	{
342
+		return (bool)$this->get('EVT_display_ticket_selector');
343
+	}
344
+
345 345
 
346 346
 
347
-    /**
348
-     * @return bool
349
-     * @throws \EE_Error
350
-     */
351
-    public function external_url()
352
-    {
353
-        return $this->get('EVT_external_URL');
354
-    }
355
-
347
+	/**
348
+	 * @return bool
349
+	 * @throws \EE_Error
350
+	 */
351
+	public function external_url()
352
+	{
353
+		return $this->get('EVT_external_URL');
354
+	}
355
+
356 356
 
357 357
 
358
-    /**
359
-     * @return bool
360
-     * @throws \EE_Error
361
-     */
362
-    public function member_only()
363
-    {
364
-        return $this->get('EVT_member_only');
365
-    }
358
+	/**
359
+	 * @return bool
360
+	 * @throws \EE_Error
361
+	 */
362
+	public function member_only()
363
+	{
364
+		return $this->get('EVT_member_only');
365
+	}
366 366
 
367 367
 
368 368
 
369
-    /**
370
-     * @return bool
371
-     * @throws \EE_Error
372
-     */
373
-    public function phone()
374
-    {
375
-        return $this->get('EVT_phone');
376
-    }
369
+	/**
370
+	 * @return bool
371
+	 * @throws \EE_Error
372
+	 */
373
+	public function phone()
374
+	{
375
+		return $this->get('EVT_phone');
376
+	}
377 377
 
378 378
 
379 379
 
380
-    /**
381
-     * @return bool
382
-     * @throws \EE_Error
383
-     */
384
-    public function modified()
385
-    {
386
-        return $this->get('EVT_modified');
387
-    }
380
+	/**
381
+	 * @return bool
382
+	 * @throws \EE_Error
383
+	 */
384
+	public function modified()
385
+	{
386
+		return $this->get('EVT_modified');
387
+	}
388 388
 
389 389
 
390 390
 
391
-    /**
392
-     * @return bool
393
-     * @throws \EE_Error
394
-     */
395
-    public function name()
396
-    {
397
-        return $this->get('EVT_name');
398
-    }
391
+	/**
392
+	 * @return bool
393
+	 * @throws \EE_Error
394
+	 */
395
+	public function name()
396
+	{
397
+		return $this->get('EVT_name');
398
+	}
399 399
 
400 400
 
401 401
 
402
-    /**
403
-     * @return bool
404
-     * @throws \EE_Error
405
-     */
406
-    public function order()
407
-    {
408
-        return $this->get('EVT_order');
409
-    }
402
+	/**
403
+	 * @return bool
404
+	 * @throws \EE_Error
405
+	 */
406
+	public function order()
407
+	{
408
+		return $this->get('EVT_order');
409
+	}
410 410
 
411 411
 
412 412
 
413
-    /**
414
-     * @return bool|string
415
-     * @throws \EE_Error
416
-     */
417
-    public function default_registration_status()
418
-    {
419
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
420
-        return ! empty($event_default_registration_status)
421
-            ? $event_default_registration_status
422
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
423
-    }
413
+	/**
414
+	 * @return bool|string
415
+	 * @throws \EE_Error
416
+	 */
417
+	public function default_registration_status()
418
+	{
419
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
420
+		return ! empty($event_default_registration_status)
421
+			? $event_default_registration_status
422
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
423
+	}
424 424
 
425 425
 
426 426
 
427
-    /**
428
-     * @param int  $num_words
429
-     * @param null $more
430
-     * @param bool $not_full_desc
431
-     * @return bool|string
432
-     * @throws \EE_Error
433
-     */
434
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
435
-    {
436
-        $short_desc = $this->get('EVT_short_desc');
437
-        if ( ! empty($short_desc) || $not_full_desc) {
438
-            return $short_desc;
439
-        } else {
440
-            $full_desc = $this->get('EVT_desc');
441
-            return wp_trim_words($full_desc, $num_words, $more);
442
-        }
443
-    }
427
+	/**
428
+	 * @param int  $num_words
429
+	 * @param null $more
430
+	 * @param bool $not_full_desc
431
+	 * @return bool|string
432
+	 * @throws \EE_Error
433
+	 */
434
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
435
+	{
436
+		$short_desc = $this->get('EVT_short_desc');
437
+		if ( ! empty($short_desc) || $not_full_desc) {
438
+			return $short_desc;
439
+		} else {
440
+			$full_desc = $this->get('EVT_desc');
441
+			return wp_trim_words($full_desc, $num_words, $more);
442
+		}
443
+	}
444 444
 
445 445
 
446 446
 
447
-    /**
448
-     * @return bool
449
-     * @throws \EE_Error
450
-     */
451
-    public function slug()
452
-    {
453
-        return $this->get('EVT_slug');
454
-    }
447
+	/**
448
+	 * @return bool
449
+	 * @throws \EE_Error
450
+	 */
451
+	public function slug()
452
+	{
453
+		return $this->get('EVT_slug');
454
+	}
455 455
 
456 456
 
457 457
 
458
-    /**
459
-     * @return bool
460
-     * @throws \EE_Error
461
-     */
462
-    public function timezone_string()
463
-    {
464
-        return $this->get('EVT_timezone_string');
465
-    }
458
+	/**
459
+	 * @return bool
460
+	 * @throws \EE_Error
461
+	 */
462
+	public function timezone_string()
463
+	{
464
+		return $this->get('EVT_timezone_string');
465
+	}
466 466
 
467 467
 
468 468
 
469
-    /**
470
-     * @return bool
471
-     * @throws \EE_Error
472
-     */
473
-    public function visible_on()
474
-    {
475
-        return $this->get('EVT_visible_on');
476
-    }
469
+	/**
470
+	 * @return bool
471
+	 * @throws \EE_Error
472
+	 */
473
+	public function visible_on()
474
+	{
475
+		return $this->get('EVT_visible_on');
476
+	}
477 477
 
478 478
 
479 479
 
480
-    /**
481
-     * @return int
482
-     * @throws \EE_Error
483
-     */
484
-    public function wp_user()
485
-    {
486
-        return $this->get('EVT_wp_user');
487
-    }
480
+	/**
481
+	 * @return int
482
+	 * @throws \EE_Error
483
+	 */
484
+	public function wp_user()
485
+	{
486
+		return $this->get('EVT_wp_user');
487
+	}
488 488
 
489 489
 
490 490
 
491
-    /**
492
-     * @return bool
493
-     * @throws \EE_Error
494
-     */
495
-    public function donations()
496
-    {
497
-        return $this->get('EVT_donations');
498
-    }
491
+	/**
492
+	 * @return bool
493
+	 * @throws \EE_Error
494
+	 */
495
+	public function donations()
496
+	{
497
+		return $this->get('EVT_donations');
498
+	}
499 499
 
500 500
 
501 501
 
502
-    /**
503
-     * @param $limit
504
-     * @throws \EE_Error
505
-     */
506
-    public function set_additional_limit($limit)
507
-    {
508
-        $this->set('EVT_additional_limit', $limit);
509
-    }
502
+	/**
503
+	 * @param $limit
504
+	 * @throws \EE_Error
505
+	 */
506
+	public function set_additional_limit($limit)
507
+	{
508
+		$this->set('EVT_additional_limit', $limit);
509
+	}
510 510
 
511 511
 
512 512
 
513
-    /**
514
-     * @param $created
515
-     * @throws \EE_Error
516
-     */
517
-    public function set_created($created)
518
-    {
519
-        $this->set('EVT_created', $created);
520
-    }
513
+	/**
514
+	 * @param $created
515
+	 * @throws \EE_Error
516
+	 */
517
+	public function set_created($created)
518
+	{
519
+		$this->set('EVT_created', $created);
520
+	}
521 521
 
522 522
 
523 523
 
524
-    /**
525
-     * @param $desc
526
-     * @throws \EE_Error
527
-     */
528
-    public function set_description($desc)
529
-    {
530
-        $this->set('EVT_desc', $desc);
531
-    }
524
+	/**
525
+	 * @param $desc
526
+	 * @throws \EE_Error
527
+	 */
528
+	public function set_description($desc)
529
+	{
530
+		$this->set('EVT_desc', $desc);
531
+	}
532 532
 
533 533
 
534 534
 
535
-    /**
536
-     * @param $display_desc
537
-     * @throws \EE_Error
538
-     */
539
-    public function set_display_description($display_desc)
540
-    {
541
-        $this->set('EVT_display_desc', $display_desc);
542
-    }
535
+	/**
536
+	 * @param $display_desc
537
+	 * @throws \EE_Error
538
+	 */
539
+	public function set_display_description($display_desc)
540
+	{
541
+		$this->set('EVT_display_desc', $display_desc);
542
+	}
543 543
 
544 544
 
545 545
 
546
-    /**
547
-     * @param $display_ticket_selector
548
-     * @throws \EE_Error
549
-     */
550
-    public function set_display_ticket_selector($display_ticket_selector)
551
-    {
552
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
553
-    }
546
+	/**
547
+	 * @param $display_ticket_selector
548
+	 * @throws \EE_Error
549
+	 */
550
+	public function set_display_ticket_selector($display_ticket_selector)
551
+	{
552
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
553
+	}
554 554
 
555 555
 
556 556
 
557
-    /**
558
-     * @param $external_url
559
-     * @throws \EE_Error
560
-     */
561
-    public function set_external_url($external_url)
562
-    {
563
-        $this->set('EVT_external_URL', $external_url);
564
-    }
557
+	/**
558
+	 * @param $external_url
559
+	 * @throws \EE_Error
560
+	 */
561
+	public function set_external_url($external_url)
562
+	{
563
+		$this->set('EVT_external_URL', $external_url);
564
+	}
565 565
 
566 566
 
567 567
 
568
-    /**
569
-     * @param $member_only
570
-     * @throws \EE_Error
571
-     */
572
-    public function set_member_only($member_only)
573
-    {
574
-        $this->set('EVT_member_only', $member_only);
575
-    }
568
+	/**
569
+	 * @param $member_only
570
+	 * @throws \EE_Error
571
+	 */
572
+	public function set_member_only($member_only)
573
+	{
574
+		$this->set('EVT_member_only', $member_only);
575
+	}
576 576
 
577 577
 
578 578
 
579
-    /**
580
-     * @param $event_phone
581
-     * @throws \EE_Error
582
-     */
583
-    public function set_event_phone($event_phone)
584
-    {
585
-        $this->set('EVT_phone', $event_phone);
586
-    }
579
+	/**
580
+	 * @param $event_phone
581
+	 * @throws \EE_Error
582
+	 */
583
+	public function set_event_phone($event_phone)
584
+	{
585
+		$this->set('EVT_phone', $event_phone);
586
+	}
587 587
 
588 588
 
589 589
 
590
-    /**
591
-     * @param $modified
592
-     * @throws \EE_Error
593
-     */
594
-    public function set_modified($modified)
595
-    {
596
-        $this->set('EVT_modified', $modified);
597
-    }
590
+	/**
591
+	 * @param $modified
592
+	 * @throws \EE_Error
593
+	 */
594
+	public function set_modified($modified)
595
+	{
596
+		$this->set('EVT_modified', $modified);
597
+	}
598 598
 
599 599
 
600 600
 
601
-    /**
602
-     * @param $name
603
-     * @throws \EE_Error
604
-     */
605
-    public function set_name($name)
606
-    {
607
-        $this->set('EVT_name', $name);
608
-    }
601
+	/**
602
+	 * @param $name
603
+	 * @throws \EE_Error
604
+	 */
605
+	public function set_name($name)
606
+	{
607
+		$this->set('EVT_name', $name);
608
+	}
609 609
 
610 610
 
611 611
 
612
-    /**
613
-     * @param $order
614
-     * @throws \EE_Error
615
-     */
616
-    public function set_order($order)
617
-    {
618
-        $this->set('EVT_order', $order);
619
-    }
612
+	/**
613
+	 * @param $order
614
+	 * @throws \EE_Error
615
+	 */
616
+	public function set_order($order)
617
+	{
618
+		$this->set('EVT_order', $order);
619
+	}
620 620
 
621 621
 
622 622
 
623
-    /**
624
-     * @param $short_desc
625
-     * @throws \EE_Error
626
-     */
627
-    public function set_short_description($short_desc)
628
-    {
629
-        $this->set('EVT_short_desc', $short_desc);
630
-    }
623
+	/**
624
+	 * @param $short_desc
625
+	 * @throws \EE_Error
626
+	 */
627
+	public function set_short_description($short_desc)
628
+	{
629
+		$this->set('EVT_short_desc', $short_desc);
630
+	}
631 631
 
632 632
 
633 633
 
634
-    /**
635
-     * @param $slug
636
-     * @throws \EE_Error
637
-     */
638
-    public function set_slug($slug)
639
-    {
640
-        $this->set('EVT_slug', $slug);
641
-    }
634
+	/**
635
+	 * @param $slug
636
+	 * @throws \EE_Error
637
+	 */
638
+	public function set_slug($slug)
639
+	{
640
+		$this->set('EVT_slug', $slug);
641
+	}
642 642
 
643 643
 
644 644
 
645
-    /**
646
-     * @param $timezone_string
647
-     * @throws \EE_Error
648
-     */
649
-    public function set_timezone_string($timezone_string)
650
-    {
651
-        $this->set('EVT_timezone_string', $timezone_string);
652
-    }
645
+	/**
646
+	 * @param $timezone_string
647
+	 * @throws \EE_Error
648
+	 */
649
+	public function set_timezone_string($timezone_string)
650
+	{
651
+		$this->set('EVT_timezone_string', $timezone_string);
652
+	}
653 653
 
654 654
 
655 655
 
656
-    /**
657
-     * @param $visible_on
658
-     * @throws \EE_Error
659
-     */
660
-    public function set_visible_on($visible_on)
661
-    {
662
-        $this->set('EVT_visible_on', $visible_on);
663
-    }
664
-
656
+	/**
657
+	 * @param $visible_on
658
+	 * @throws \EE_Error
659
+	 */
660
+	public function set_visible_on($visible_on)
661
+	{
662
+		$this->set('EVT_visible_on', $visible_on);
663
+	}
664
+
665 665
 
666 666
 
667
-    /**
668
-     * @param $wp_user
669
-     * @throws \EE_Error
670
-     */
671
-    public function set_wp_user($wp_user)
672
-    {
673
-        $this->set('EVT_wp_user', $wp_user);
674
-    }
675
-
676
-
677
-
678
-    /**
679
-     * @param $default_registration_status
680
-     * @throws \EE_Error
681
-     */
682
-    public function set_default_registration_status($default_registration_status)
683
-    {
684
-        $this->set('EVT_default_registration_status', $default_registration_status);
685
-    }
686
-
687
-
688
-
689
-    /**
690
-     * @param $donations
691
-     * @throws \EE_Error
692
-     */
693
-    public function set_donations($donations)
694
-    {
695
-        $this->set('EVT_donations', $donations);
696
-    }
697
-
698
-
699
-
700
-    /**
701
-     * Adds a venue to this event
702
-     *
703
-     * @param EE_Venue /int $venue_id_or_obj
704
-     * @return EE_Venue
705
-     * @throws \EE_Error
706
-     */
707
-    public function add_venue($venue_id_or_obj)
708
-    {
709
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
710
-    }
711
-
712
-
713
-
714
-    /**
715
-     * Removes a venue from the event
716
-     *
717
-     * @param EE_Venue /int $venue_id_or_obj
718
-     * @return EE_Venue
719
-     * @throws \EE_Error
720
-     */
721
-    public function remove_venue($venue_id_or_obj)
722
-    {
723
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
724
-    }
725
-
726
-
727
-
728
-    /**
729
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
730
-     *
731
-     * @param array $query_params like EEM_Base::get_all's $query_params
732
-     * @return EE_Venue[]
733
-     * @throws \EE_Error
734
-     */
735
-    public function venues($query_params = array())
736
-    {
737
-        return $this->get_many_related('Venue', $query_params);
738
-    }
739
-
740
-
741
-
742
-    /**
743
-     * check if event id is present and if event is published
744
-     *
745
-     * @access public
746
-     * @return boolean true yes, false no
747
-     * @throws \EE_Error
748
-     */
749
-    private function _has_ID_and_is_published()
750
-    {
751
-        // first check if event id is present and not NULL,
752
-        // then check if this event is published (or any of the equivalent "published" statuses)
753
-        return
754
-            $this->ID() && $this->ID() !== null
755
-            && (
756
-                $this->status() === 'publish'
757
-                || $this->status() === EEM_Event::sold_out
758
-                || $this->status() === EEM_Event::postponed
759
-                || $this->status() === EEM_Event::cancelled
760
-            )
761
-            ? true
762
-            : false;
763
-    }
764
-
765
-
766
-
767
-    /**
768
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
769
-     *
770
-     * @access public
771
-     * @return boolean true yes, false no
772
-     * @throws \EE_Error
773
-     */
774
-    public function is_upcoming()
775
-    {
776
-        // check if event id is present and if this event is published
777
-        if ($this->is_inactive()) {
778
-            return false;
779
-        }
780
-        // set initial value
781
-        $upcoming = false;
782
-        //next let's get all datetimes and loop through them
783
-        $datetimes = $this->datetimes_in_chronological_order();
784
-        foreach ($datetimes as $datetime) {
785
-            if ($datetime instanceof EE_Datetime) {
786
-                //if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
787
-                if ($datetime->is_expired()) {
788
-                    continue;
789
-                }
790
-                //if this dtt is active then we return false.
791
-                if ($datetime->is_active()) {
792
-                    return false;
793
-                }
794
-                //otherwise let's check upcoming status
795
-                $upcoming = $datetime->is_upcoming();
796
-            }
797
-        }
798
-        return $upcoming;
799
-    }
800
-
801
-
802
-
803
-    /**
804
-     * @return bool
805
-     * @throws \EE_Error
806
-     */
807
-    public function is_active()
808
-    {
809
-        // check if event id is present and if this event is published
810
-        if ($this->is_inactive()) {
811
-            return false;
812
-        }
813
-        // set initial value
814
-        $active = false;
815
-        //next let's get all datetimes and loop through them
816
-        $datetimes = $this->datetimes_in_chronological_order();
817
-        foreach ($datetimes as $datetime) {
818
-            if ($datetime instanceof EE_Datetime) {
819
-                //if this dtt is expired then we continue cause one of the other datetimes might be active.
820
-                if ($datetime->is_expired()) {
821
-                    continue;
822
-                }
823
-                //if this dtt is upcoming then we return false.
824
-                if ($datetime->is_upcoming()) {
825
-                    return false;
826
-                }
827
-                //otherwise let's check active status
828
-                $active = $datetime->is_active();
829
-            }
830
-        }
831
-        return $active;
832
-    }
833
-
834
-
835
-
836
-    /**
837
-     * @return bool
838
-     * @throws \EE_Error
839
-     */
840
-    public function is_expired()
841
-    {
842
-        // check if event id is present and if this event is published
843
-        if ($this->is_inactive()) {
844
-            return false;
845
-        }
846
-        // set initial value
847
-        $expired = false;
848
-        //first let's get all datetimes and loop through them
849
-        $datetimes = $this->datetimes_in_chronological_order();
850
-        foreach ($datetimes as $datetime) {
851
-            if ($datetime instanceof EE_Datetime) {
852
-                //if this dtt is upcoming or active then we return false.
853
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
854
-                    return false;
855
-                }
856
-                //otherwise let's check active status
857
-                $expired = $datetime->is_expired();
858
-            }
859
-        }
860
-        return $expired;
861
-    }
862
-
863
-
864
-
865
-    /**
866
-     * @return bool
867
-     * @throws \EE_Error
868
-     */
869
-    public function is_inactive()
870
-    {
871
-        // check if event id is present and if this event is published
872
-        if ($this->_has_ID_and_is_published()) {
873
-            return false;
874
-        }
875
-        return true;
876
-    }
877
-
878
-
879
-
880
-    /**
881
-     * calculate spaces remaining based on "saleable" tickets
882
-     *
883
-     * @param array $tickets
884
-     * @return int
885
-     * @throws EE_Error
886
-     */
887
-    public function spaces_remaining($tickets = array(), $filtered = true)
888
-    {
889
-        // get all unexpired untrashed tickets if nothing was passed
890
-        $tickets = ! empty($tickets) ? $tickets : $this->active_tickets();
891
-        // set initial value
892
-        $spaces_remaining = 0;
893
-        foreach ($tickets as $ticket) {
894
-            if ($ticket instanceof EE_Ticket) {
895
-                $spaces_remaining += $ticket->qty('saleable');
896
-            }
897
-        }
898
-        return $filtered
899
-            ? apply_filters(
900
-                'FHEE_EE_Event__spaces_remaining',
901
-                $spaces_remaining,
902
-                $this,
903
-                $tickets
904
-            )
905
-            : $spaces_remaining;
906
-    }
907
-
908
-
909
-    /**
910
-     *    perform_sold_out_status_check
911
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
912
-     *    if NOT, then the event status will get toggled to 'sold_out'
913
-     *
914
-     * @access public
915
-     * @return bool    return the ACTUAL sold out state.
916
-     * @throws \EE_Error
917
-     */
918
-    public function perform_sold_out_status_check()
919
-    {
920
-        // get all unexpired untrashed tickets
921
-        $tickets = $this->active_tickets();
922
-        // if all the tickets are just expired, then don't update the event status to sold out
923
-        if (empty($tickets)) {
924
-            return true;
925
-        }
926
-        $spaces_remaining = $this->spaces_remaining($tickets);
927
-        if ($spaces_remaining < 1) {
928
-            $this->set_status(EEM_Event::sold_out);
929
-            $this->save();
930
-            $sold_out = true;
931
-        } else {
932
-            $sold_out = false;
933
-            // was event previously marked as sold out ?
934
-            if ($this->status() === EEM_Event::sold_out) {
935
-                // revert status to previous value, if it was set
936
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
937
-                if ($previous_event_status) {
938
-                    $this->set_status($previous_event_status);
939
-                    $this->save();
940
-                }
941
-            }
942
-        }
943
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
944
-        return $sold_out;
945
-    }
946
-
947
-
948
-
949
-    /**
950
-     * This returns the total remaining spaces for sale on this event.
951
-     * ############################
952
-     * VERY IMPORTANT FOR DEVELOPERS:
953
-     * While included here, this method is still being tested internally, so its signature and behaviour COULD change.
954
-     * While this comment block is in place, usage is at your own risk and know that it may change in future builds.
955
-     * ############################
956
-     *
957
-     * @uses EE_Event::total_available_spaces()
958
-     * @return float|int  (EE_INF is returned as float)
959
-     * @throws \EE_Error
960
-     */
961
-    public function spaces_remaining_for_sale()
962
-    {
963
-        //first get total available spaces including consideration for tickets that have already sold.
964
-        $spaces_available = $this->total_available_spaces(true);
965
-        //if total available = 0, then exit right away because that means everything is expired.
966
-        if ($spaces_available === 0) {
967
-            return 0;
968
-        }
969
-        //subtract total approved registrations from spaces available to get how many are remaining.
970
-        $spots_taken = EEM_Registration::instance()->event_reg_count_for_status($this);
971
-        $spaces_remaining = $spaces_available - $spots_taken;
972
-        return $spaces_remaining > 0 ? $spaces_remaining : 0;
973
-    }
974
-
975
-
976
-
977
-    /**
978
-     * This returns the total spaces available for an event while considering all the qtys on the tickets and the reg limits
979
-     * on the datetimes attached to this event.
980
-     * ############################
981
-     * VERY IMPORTANT FOR DEVELOPERS:
982
-     * While included here, this method is still being tested internally, so its signature and behaviour COULD change. While
983
-     * this comment block is in place, usage is at your own risk and know that it may change in future builds.
984
-     * ############################
985
-     * Note: by "spaces available" we are not returning how many spaces remain.  That is a calculation involving using the value
986
-     * from this method and subtracting the approved registrations for the event.
987
-     *
988
-     * @param   bool $current_total_available       Whether to consider any tickets that have already sold in our calculation.
989
-     *                                              If this is false, then we return the most tickets that could ever be sold
990
-     *                                              for this event with the datetime and tickets setup on the event under optimal
991
-     *                                              selling conditions.  Otherwise we return a live calculation of spaces available
992
-     *                                              based on tickets sold.  Depending on setup and stage of sales, this
993
-     *                                              may appear to equal remaining tickets.  However, the more tickets are
994
-     *                                              sold out, the more accurate the "live" total is.
995
-     * @return  int|float  (Note: if EE_INF is returned its considered a float by PHP)
996
-     * @throws \EE_Error
997
-     */
998
-    public function total_available_spaces($current_total_available = false)
999
-    {
1000
-        $spaces_available = 0;
1001
-        //first get all tickets on the event and include expired tickets
1002
-        $tickets = $this->tickets(array('default_where_conditions' => 'none'));
1003
-        $ticket_sums = array();
1004
-        $datetimes = array();
1005
-        $datetime_limits = array();
1006
-        //loop through tickets and normalize them
1007
-        foreach ($tickets as $ticket) {
1008
-            $datetimes = $ticket->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1009
-            if (empty($datetimes)) {
1010
-                continue;
1011
-            }
1012
-            //first datetime should be the lowest datetime
1013
-            $least_datetime = reset($datetimes);
1014
-            //lets reset the ticket quantity to be the lower of either the lowest datetime reg limit or the ticket quantity
1015
-            //IF datetimes sold (and we're not doing current live total available, then use spaces remaining for datetime, not reg_limit.
1016
-            if ($current_total_available) {
1017
-                if ($ticket->is_remaining()) {
1018
-                    $remaining = $ticket->remaining();
1019
-                } else {
1020
-                    $spaces_available += $ticket->sold();
1021
-                    //and we don't cache this ticket to our list because its sold out.
1022
-                    continue;
1023
-                }
1024
-            } else {
1025
-                $remaining = min($ticket->qty(), $least_datetime->reg_limit());
1026
-            }
1027
-            //if $ticket_limit == infinity then let's drop out right away and just return that because any infinity amount trumps all other "available" amounts.
1028
-            if ($remaining === EE_INF) {
1029
-                return EE_INF;
1030
-            }
1031
-            //multiply normalized $tkt quantity by the number of datetimes on the ticket as the "sum"
1032
-            //also include the sum of all the datetime reg limits on the ticket for breaking ties.
1033
-            $ticket_sums[$ticket->ID()]['sum'] = $remaining * count($datetimes);
1034
-            $ticket_sums[$ticket->ID()]['datetime_sums'] = 0;
1035
-            foreach ($datetimes as $datetime) {
1036
-                if ($datetime->reg_limit() === EE_INF) {
1037
-                    $ticket_sums[$ticket->ID()]['datetime_sums'] = EE_INF;
1038
-                } else {
1039
-                    $ticket_sums[$ticket->ID()]['datetime_sums'] += $current_total_available
1040
-                        ? $datetime->spaces_remaining()
1041
-                        : $datetime->reg_limit();
1042
-                }
1043
-                $datetime_limits[$datetime->ID()] = $current_total_available
1044
-                    ? $datetime->spaces_remaining()
1045
-                    : $datetime->reg_limit();
1046
-            }
1047
-            $ticket_sums[$ticket->ID()]['ticket'] = $ticket;
1048
-        }
1049
-        //The order is sorted by lowest available first (which is calculated for each ticket by multiplying the normalized
1050
-        //ticket quantity by the number of datetimes on the ticket).  For tie-breakers, then the next sort is based on the
1051
-        //ticket with the greatest sum of all remaining datetime->spaces_remaining() ( or $datetime->reg_limit() if not
1052
-        //$current_total_available ) for the datetimes on the ticket.
1053
-        usort($ticket_sums, function ($a, $b) {
1054
-            if ($a['sum'] === $b['sum']) {
1055
-                if ($a['datetime_sums'] === $b['datetime_sums']) {
1056
-                    return 0;
1057
-                }
1058
-                return $a['datetime_sums'] < $b['datetime_sums'] ? 1 : -1;
1059
-            }
1060
-            return ($a['sum'] < $b['sum']) ? -1 : 1;
1061
-        });
1062
-        //now let's loop through the sorted tickets and simulate sellouts
1063
-        foreach ($ticket_sums as $ticket_info) {
1064
-            if ($ticket_info['ticket'] instanceof EE_Ticket) {
1065
-                $datetimes = $ticket_info['ticket']->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1066
-                //need to sort these $datetimes by remaining (only if $current_total_available)
1067
-                //setup datetimes for simulation
1068
-                $ticket_datetimes_remaining = array();
1069
-                foreach ($datetimes as $datetime) {
1070
-                    $ticket_datetimes_remaining[$datetime->ID()]['rem'] = $datetime_limits[$datetime->ID()];
1071
-                    $ticket_datetimes_remaining[$datetime->ID()]['datetime'] = $datetime;
1072
-                }
1073
-                usort($ticket_datetimes_remaining, function ($a, $b) {
1074
-                    if ($a['rem'] === $b['rem']) {
1075
-                        return 0;
1076
-                    }
1077
-                    return ($a['rem'] < $b['rem']) ? -1 : 1;
1078
-                });
1079
-                //get the remaining on the first datetime (which should be the one with the least remaining) and that is
1080
-                //what we add to the spaces_available running total.  Then we need to decrease the remaining on our datetime tracker.
1081
-                $lowest_datetime = reset($ticket_datetimes_remaining);
1082
-                //need to get the lower of; what the remaining is on the lowest datetime, and the remaining on the ticket.
1083
-                // If this ends up being 0 (because of previous tickets in our simulation selling out), then it has already
1084
-                // been tracked on $spaces available and this ticket is now sold out for the simulation, so we can continue
1085
-                // to the next ticket.
1086
-                if ($current_total_available) {
1087
-                    $remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->remaining());
1088
-                } else {
1089
-                    $remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->qty());
1090
-                }
1091
-                //if $remaining is infinite that means that all datetimes on this ticket are infinite but we've made it here because all
1092
-                //tickets have a quantity.  So we don't have to track datetimes, we can just use ticket quantities for total
1093
-                //available.
1094
-                if ($remaining === EE_INF) {
1095
-                    $spaces_available += $ticket_info['ticket']->qty();
1096
-                    continue;
1097
-                }
1098
-                //if ticket has sold amounts then we also need to add that (but only if doing live counts)
1099
-                if ($current_total_available) {
1100
-                    $spaces_available += $ticket_info['ticket']->sold();
1101
-                }
1102
-                if ($remaining <= 0) {
1103
-                    continue;
1104
-                } else {
1105
-                    $spaces_available += $remaining;
1106
-                }
1107
-                //loop through the datetimes and sell them out!
1108
-                foreach ($ticket_datetimes_remaining as $datetime_info) {
1109
-                    if ($datetime_info['datetime'] instanceof EE_Datetime) {
1110
-                        $datetime_limits[$datetime_info['datetime']->ID()] += -$remaining;
1111
-                    }
1112
-                }
1113
-            }
1114
-        }
1115
-        return apply_filters(
1116
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
1117
-            $spaces_available,
1118
-            $this,
1119
-            $datetimes,
1120
-            $tickets
1121
-        );
1122
-    }
1123
-
1124
-
1125
-
1126
-    /**
1127
-     * Checks if the event is set to sold out
1128
-     *
1129
-     * @param  bool $actual whether or not to perform calculations to not only figure the
1130
-     *                      actual status but also to flip the status if necessary to sold
1131
-     *                      out If false, we just check the existing status of the event
1132
-     * @return boolean
1133
-     * @throws \EE_Error
1134
-     */
1135
-    public function is_sold_out($actual = false)
1136
-    {
1137
-        if ( ! $actual) {
1138
-            return $this->status() === EEM_Event::sold_out;
1139
-        } else {
1140
-            return $this->perform_sold_out_status_check();
1141
-        }
1142
-    }
1143
-
1144
-
1145
-
1146
-    /**
1147
-     * Checks if the event is marked as postponed
1148
-     *
1149
-     * @return boolean
1150
-     */
1151
-    public function is_postponed()
1152
-    {
1153
-        return $this->status() === EEM_Event::postponed;
1154
-    }
1155
-
1156
-
1157
-
1158
-    /**
1159
-     * Checks if the event is marked as cancelled
1160
-     *
1161
-     * @return boolean
1162
-     */
1163
-    public function is_cancelled()
1164
-    {
1165
-        return $this->status() === EEM_Event::cancelled;
1166
-    }
1167
-
1168
-
1169
-
1170
-    /**
1171
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1172
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1173
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1174
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1175
-     * the event is considered expired.
1176
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1177
-     * set on the EVENT when it is not published and thus is done
1178
-     *
1179
-     * @param bool $reset
1180
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1181
-     * @throws \EE_Error
1182
-     */
1183
-    public function get_active_status($reset = false)
1184
-    {
1185
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1186
-        if ( ! empty($this->_active_status) && ! $reset) {
1187
-            return $this->_active_status;
1188
-        }
1189
-        //first check if event id is present on this object
1190
-        if ( ! $this->ID()) {
1191
-            return false;
1192
-        }
1193
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1194
-        //if event is published:
1195
-        if ($this->status() === 'publish') {
1196
-            //active?
1197
-            if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1198
-                $this->_active_status = EE_Datetime::active;
1199
-            } else {
1200
-                //upcoming?
1201
-                if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1202
-                    $this->_active_status = EE_Datetime::upcoming;
1203
-                } else {
1204
-                    //expired?
1205
-                    if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0) {
1206
-                        $this->_active_status = EE_Datetime::expired;
1207
-                    } else {
1208
-                        //it would be odd if things make it this far because it basically means there are no datetime's
1209
-                        //attached to the event.  So in this case it will just be considered inactive.
1210
-                        $this->_active_status = EE_Datetime::inactive;
1211
-                    }
1212
-                }
1213
-            }
1214
-        } else {
1215
-            //the event is not published, so let's just set it's active status according to its' post status
1216
-            switch ($this->status()) {
1217
-                case EEM_Event::sold_out :
1218
-                    $this->_active_status = EE_Datetime::sold_out;
1219
-                    break;
1220
-                case EEM_Event::cancelled :
1221
-                    $this->_active_status = EE_Datetime::cancelled;
1222
-                    break;
1223
-                case EEM_Event::postponed :
1224
-                    $this->_active_status = EE_Datetime::postponed;
1225
-                    break;
1226
-                default :
1227
-                    $this->_active_status = EE_Datetime::inactive;
1228
-            }
1229
-        }
1230
-        return $this->_active_status;
1231
-    }
1232
-
1233
-
1234
-
1235
-    /**
1236
-     *    pretty_active_status
1237
-     *
1238
-     * @access public
1239
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1240
-     * @return mixed void|string
1241
-     * @throws \EE_Error
1242
-     */
1243
-    public function pretty_active_status($echo = true)
1244
-    {
1245
-        $active_status = $this->get_active_status();
1246
-        $status = '<span class="ee-status event-active-status-'
1247
-                  . $active_status
1248
-                  . '">'
1249
-                  . EEH_Template::pretty_status($active_status, false, 'sentence')
1250
-                  . '</span>';
1251
-        if ($echo) {
1252
-            echo $status;
1253
-            return '';
1254
-        }
1255
-        return $status;
1256
-    }
1257
-
1258
-
1259
-
1260
-    /**
1261
-     * @return bool|int
1262
-     * @throws \EE_Error
1263
-     */
1264
-    public function get_number_of_tickets_sold()
1265
-    {
1266
-        $tkt_sold = 0;
1267
-        if ( ! $this->ID()) {
1268
-            return 0;
1269
-        }
1270
-        $datetimes = $this->datetimes();
1271
-        foreach ($datetimes as $datetime) {
1272
-            if ($datetime instanceof EE_Datetime) {
1273
-                $tkt_sold += $datetime->sold();
1274
-            }
1275
-        }
1276
-        return $tkt_sold;
1277
-    }
1278
-
1279
-
1280
-
1281
-    /**
1282
-     * This just returns a count of all the registrations for this event
1283
-     *
1284
-     * @access  public
1285
-     * @return int
1286
-     * @throws \EE_Error
1287
-     */
1288
-    public function get_count_of_all_registrations()
1289
-    {
1290
-        return EEM_Event::instance()->count_related($this, 'Registration');
1291
-    }
1292
-
1293
-
1294
-
1295
-    /**
1296
-     * This returns the ticket with the earliest start time that is
1297
-     * available for this event (across all datetimes attached to the event)
1298
-     *
1299
-     * @return EE_Ticket
1300
-     * @throws \EE_Error
1301
-     */
1302
-    public function get_ticket_with_earliest_start_time()
1303
-    {
1304
-        $where['Datetime.EVT_ID'] = $this->ID();
1305
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1306
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1307
-    }
1308
-
1309
-
1310
-
1311
-    /**
1312
-     * This returns the ticket with the latest end time that is available
1313
-     * for this event (across all datetimes attached to the event)
1314
-     *
1315
-     * @return EE_Ticket
1316
-     * @throws \EE_Error
1317
-     */
1318
-    public function get_ticket_with_latest_end_time()
1319
-    {
1320
-        $where['Datetime.EVT_ID'] = $this->ID();
1321
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1322
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1323
-    }
1324
-
1325
-
1326
-
1327
-    /**
1328
-     * This returns whether there are any tickets on sale for this event.
1329
-     *
1330
-     * @return bool true = YES tickets on sale.
1331
-     * @throws \EE_Error
1332
-     */
1333
-    public function tickets_on_sale()
1334
-    {
1335
-        $earliest_ticket = $this->get_ticket_with_earliest_start_time();
1336
-        $latest_ticket = $this->get_ticket_with_latest_end_time();
1337
-        if ( ! $latest_ticket instanceof EE_Ticket && ! $earliest_ticket instanceof EE_Ticket) {
1338
-            return false;
1339
-        }
1340
-        //check on sale for these two tickets.
1341
-        if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1342
-            return true;
1343
-        }
1344
-        return false;
1345
-    }
1346
-
1347
-
1348
-
1349
-    /**
1350
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1351
-     * to check for an external URL first
1352
-     *
1353
-     * @return string
1354
-     * @throws \EE_Error
1355
-     */
1356
-    public function get_permalink()
1357
-    {
1358
-        if ($this->external_url()) {
1359
-            return $this->external_url();
1360
-        } else {
1361
-            return parent::get_permalink();
1362
-        }
1363
-    }
1364
-
1365
-
1366
-
1367
-    /**
1368
-     * Gets the first term for 'espresso_event_categories' we can find
1369
-     *
1370
-     * @param array $query_params like EEM_Base::get_all
1371
-     * @return EE_Term
1372
-     * @throws \EE_Error
1373
-     */
1374
-    public function first_event_category($query_params = array())
1375
-    {
1376
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1377
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1378
-        return EEM_Term::instance()->get_one($query_params);
1379
-    }
1380
-
1381
-
1382
-
1383
-    /**
1384
-     * Gets all terms for 'espresso_event_categories' we can find
1385
-     *
1386
-     * @param array $query_params
1387
-     * @return EE_Term[]
1388
-     * @throws \EE_Error
1389
-     */
1390
-    public function get_all_event_categories($query_params = array())
1391
-    {
1392
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1393
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1394
-        return EEM_Term::instance()->get_all($query_params);
1395
-    }
1396
-
1397
-
1398
-
1399
-    /**
1400
-     * Gets all the question groups, ordering them by QSG_order ascending
1401
-     *
1402
-     * @param array $query_params @see EEM_Base::get_all
1403
-     * @return EE_Question_Group[]
1404
-     * @throws \EE_Error
1405
-     */
1406
-    public function question_groups($query_params = array())
1407
-    {
1408
-        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1409
-        return $this->get_many_related('Question_Group', $query_params);
1410
-    }
1411
-
1412
-
1413
-
1414
-    /**
1415
-     * Implementation for EEI_Has_Icon interface method.
1416
-     *
1417
-     * @see EEI_Visual_Representation for comments
1418
-     * @return string
1419
-     */
1420
-    public function get_icon()
1421
-    {
1422
-        return '<span class="dashicons dashicons-flag"></span>';
1423
-    }
1424
-
1425
-
1426
-
1427
-    /**
1428
-     * Implementation for EEI_Admin_Links interface method.
1429
-     *
1430
-     * @see EEI_Admin_Links for comments
1431
-     * @return string
1432
-     * @throws \EE_Error
1433
-     */
1434
-    public function get_admin_details_link()
1435
-    {
1436
-        return $this->get_admin_edit_link();
1437
-    }
1438
-
1439
-
1440
-
1441
-    /**
1442
-     * Implementation for EEI_Admin_Links interface method.
1443
-     *
1444
-     * @see EEI_Admin_Links for comments
1445
-     * @return string
1446
-     * @throws \EE_Error
1447
-     */
1448
-    public function get_admin_edit_link()
1449
-    {
1450
-        return EEH_URL::add_query_args_and_nonce(array(
1451
-            'page'   => 'espresso_events',
1452
-            'action' => 'edit',
1453
-            'post'   => $this->ID(),
1454
-        ),
1455
-            admin_url('admin.php')
1456
-        );
1457
-    }
1458
-
1459
-
1460
-
1461
-    /**
1462
-     * Implementation for EEI_Admin_Links interface method.
1463
-     *
1464
-     * @see EEI_Admin_Links for comments
1465
-     * @return string
1466
-     */
1467
-    public function get_admin_settings_link()
1468
-    {
1469
-        return EEH_URL::add_query_args_and_nonce(array(
1470
-            'page'   => 'espresso_events',
1471
-            'action' => 'default_event_settings',
1472
-        ),
1473
-            admin_url('admin.php')
1474
-        );
1475
-    }
1476
-
1477
-
1478
-
1479
-    /**
1480
-     * Implementation for EEI_Admin_Links interface method.
1481
-     *
1482
-     * @see EEI_Admin_Links for comments
1483
-     * @return string
1484
-     */
1485
-    public function get_admin_overview_link()
1486
-    {
1487
-        return EEH_URL::add_query_args_and_nonce(array(
1488
-            'page'   => 'espresso_events',
1489
-            'action' => 'default',
1490
-        ),
1491
-            admin_url('admin.php')
1492
-        );
1493
-    }
667
+	/**
668
+	 * @param $wp_user
669
+	 * @throws \EE_Error
670
+	 */
671
+	public function set_wp_user($wp_user)
672
+	{
673
+		$this->set('EVT_wp_user', $wp_user);
674
+	}
675
+
676
+
677
+
678
+	/**
679
+	 * @param $default_registration_status
680
+	 * @throws \EE_Error
681
+	 */
682
+	public function set_default_registration_status($default_registration_status)
683
+	{
684
+		$this->set('EVT_default_registration_status', $default_registration_status);
685
+	}
686
+
687
+
688
+
689
+	/**
690
+	 * @param $donations
691
+	 * @throws \EE_Error
692
+	 */
693
+	public function set_donations($donations)
694
+	{
695
+		$this->set('EVT_donations', $donations);
696
+	}
697
+
698
+
699
+
700
+	/**
701
+	 * Adds a venue to this event
702
+	 *
703
+	 * @param EE_Venue /int $venue_id_or_obj
704
+	 * @return EE_Venue
705
+	 * @throws \EE_Error
706
+	 */
707
+	public function add_venue($venue_id_or_obj)
708
+	{
709
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
710
+	}
711
+
712
+
713
+
714
+	/**
715
+	 * Removes a venue from the event
716
+	 *
717
+	 * @param EE_Venue /int $venue_id_or_obj
718
+	 * @return EE_Venue
719
+	 * @throws \EE_Error
720
+	 */
721
+	public function remove_venue($venue_id_or_obj)
722
+	{
723
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
724
+	}
725
+
726
+
727
+
728
+	/**
729
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
730
+	 *
731
+	 * @param array $query_params like EEM_Base::get_all's $query_params
732
+	 * @return EE_Venue[]
733
+	 * @throws \EE_Error
734
+	 */
735
+	public function venues($query_params = array())
736
+	{
737
+		return $this->get_many_related('Venue', $query_params);
738
+	}
739
+
740
+
741
+
742
+	/**
743
+	 * check if event id is present and if event is published
744
+	 *
745
+	 * @access public
746
+	 * @return boolean true yes, false no
747
+	 * @throws \EE_Error
748
+	 */
749
+	private function _has_ID_and_is_published()
750
+	{
751
+		// first check if event id is present and not NULL,
752
+		// then check if this event is published (or any of the equivalent "published" statuses)
753
+		return
754
+			$this->ID() && $this->ID() !== null
755
+			&& (
756
+				$this->status() === 'publish'
757
+				|| $this->status() === EEM_Event::sold_out
758
+				|| $this->status() === EEM_Event::postponed
759
+				|| $this->status() === EEM_Event::cancelled
760
+			)
761
+			? true
762
+			: false;
763
+	}
764
+
765
+
766
+
767
+	/**
768
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
769
+	 *
770
+	 * @access public
771
+	 * @return boolean true yes, false no
772
+	 * @throws \EE_Error
773
+	 */
774
+	public function is_upcoming()
775
+	{
776
+		// check if event id is present and if this event is published
777
+		if ($this->is_inactive()) {
778
+			return false;
779
+		}
780
+		// set initial value
781
+		$upcoming = false;
782
+		//next let's get all datetimes and loop through them
783
+		$datetimes = $this->datetimes_in_chronological_order();
784
+		foreach ($datetimes as $datetime) {
785
+			if ($datetime instanceof EE_Datetime) {
786
+				//if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
787
+				if ($datetime->is_expired()) {
788
+					continue;
789
+				}
790
+				//if this dtt is active then we return false.
791
+				if ($datetime->is_active()) {
792
+					return false;
793
+				}
794
+				//otherwise let's check upcoming status
795
+				$upcoming = $datetime->is_upcoming();
796
+			}
797
+		}
798
+		return $upcoming;
799
+	}
800
+
801
+
802
+
803
+	/**
804
+	 * @return bool
805
+	 * @throws \EE_Error
806
+	 */
807
+	public function is_active()
808
+	{
809
+		// check if event id is present and if this event is published
810
+		if ($this->is_inactive()) {
811
+			return false;
812
+		}
813
+		// set initial value
814
+		$active = false;
815
+		//next let's get all datetimes and loop through them
816
+		$datetimes = $this->datetimes_in_chronological_order();
817
+		foreach ($datetimes as $datetime) {
818
+			if ($datetime instanceof EE_Datetime) {
819
+				//if this dtt is expired then we continue cause one of the other datetimes might be active.
820
+				if ($datetime->is_expired()) {
821
+					continue;
822
+				}
823
+				//if this dtt is upcoming then we return false.
824
+				if ($datetime->is_upcoming()) {
825
+					return false;
826
+				}
827
+				//otherwise let's check active status
828
+				$active = $datetime->is_active();
829
+			}
830
+		}
831
+		return $active;
832
+	}
833
+
834
+
835
+
836
+	/**
837
+	 * @return bool
838
+	 * @throws \EE_Error
839
+	 */
840
+	public function is_expired()
841
+	{
842
+		// check if event id is present and if this event is published
843
+		if ($this->is_inactive()) {
844
+			return false;
845
+		}
846
+		// set initial value
847
+		$expired = false;
848
+		//first let's get all datetimes and loop through them
849
+		$datetimes = $this->datetimes_in_chronological_order();
850
+		foreach ($datetimes as $datetime) {
851
+			if ($datetime instanceof EE_Datetime) {
852
+				//if this dtt is upcoming or active then we return false.
853
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
854
+					return false;
855
+				}
856
+				//otherwise let's check active status
857
+				$expired = $datetime->is_expired();
858
+			}
859
+		}
860
+		return $expired;
861
+	}
862
+
863
+
864
+
865
+	/**
866
+	 * @return bool
867
+	 * @throws \EE_Error
868
+	 */
869
+	public function is_inactive()
870
+	{
871
+		// check if event id is present and if this event is published
872
+		if ($this->_has_ID_and_is_published()) {
873
+			return false;
874
+		}
875
+		return true;
876
+	}
877
+
878
+
879
+
880
+	/**
881
+	 * calculate spaces remaining based on "saleable" tickets
882
+	 *
883
+	 * @param array $tickets
884
+	 * @return int
885
+	 * @throws EE_Error
886
+	 */
887
+	public function spaces_remaining($tickets = array(), $filtered = true)
888
+	{
889
+		// get all unexpired untrashed tickets if nothing was passed
890
+		$tickets = ! empty($tickets) ? $tickets : $this->active_tickets();
891
+		// set initial value
892
+		$spaces_remaining = 0;
893
+		foreach ($tickets as $ticket) {
894
+			if ($ticket instanceof EE_Ticket) {
895
+				$spaces_remaining += $ticket->qty('saleable');
896
+			}
897
+		}
898
+		return $filtered
899
+			? apply_filters(
900
+				'FHEE_EE_Event__spaces_remaining',
901
+				$spaces_remaining,
902
+				$this,
903
+				$tickets
904
+			)
905
+			: $spaces_remaining;
906
+	}
907
+
908
+
909
+	/**
910
+	 *    perform_sold_out_status_check
911
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
912
+	 *    if NOT, then the event status will get toggled to 'sold_out'
913
+	 *
914
+	 * @access public
915
+	 * @return bool    return the ACTUAL sold out state.
916
+	 * @throws \EE_Error
917
+	 */
918
+	public function perform_sold_out_status_check()
919
+	{
920
+		// get all unexpired untrashed tickets
921
+		$tickets = $this->active_tickets();
922
+		// if all the tickets are just expired, then don't update the event status to sold out
923
+		if (empty($tickets)) {
924
+			return true;
925
+		}
926
+		$spaces_remaining = $this->spaces_remaining($tickets);
927
+		if ($spaces_remaining < 1) {
928
+			$this->set_status(EEM_Event::sold_out);
929
+			$this->save();
930
+			$sold_out = true;
931
+		} else {
932
+			$sold_out = false;
933
+			// was event previously marked as sold out ?
934
+			if ($this->status() === EEM_Event::sold_out) {
935
+				// revert status to previous value, if it was set
936
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
937
+				if ($previous_event_status) {
938
+					$this->set_status($previous_event_status);
939
+					$this->save();
940
+				}
941
+			}
942
+		}
943
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
944
+		return $sold_out;
945
+	}
946
+
947
+
948
+
949
+	/**
950
+	 * This returns the total remaining spaces for sale on this event.
951
+	 * ############################
952
+	 * VERY IMPORTANT FOR DEVELOPERS:
953
+	 * While included here, this method is still being tested internally, so its signature and behaviour COULD change.
954
+	 * While this comment block is in place, usage is at your own risk and know that it may change in future builds.
955
+	 * ############################
956
+	 *
957
+	 * @uses EE_Event::total_available_spaces()
958
+	 * @return float|int  (EE_INF is returned as float)
959
+	 * @throws \EE_Error
960
+	 */
961
+	public function spaces_remaining_for_sale()
962
+	{
963
+		//first get total available spaces including consideration for tickets that have already sold.
964
+		$spaces_available = $this->total_available_spaces(true);
965
+		//if total available = 0, then exit right away because that means everything is expired.
966
+		if ($spaces_available === 0) {
967
+			return 0;
968
+		}
969
+		//subtract total approved registrations from spaces available to get how many are remaining.
970
+		$spots_taken = EEM_Registration::instance()->event_reg_count_for_status($this);
971
+		$spaces_remaining = $spaces_available - $spots_taken;
972
+		return $spaces_remaining > 0 ? $spaces_remaining : 0;
973
+	}
974
+
975
+
976
+
977
+	/**
978
+	 * This returns the total spaces available for an event while considering all the qtys on the tickets and the reg limits
979
+	 * on the datetimes attached to this event.
980
+	 * ############################
981
+	 * VERY IMPORTANT FOR DEVELOPERS:
982
+	 * While included here, this method is still being tested internally, so its signature and behaviour COULD change. While
983
+	 * this comment block is in place, usage is at your own risk and know that it may change in future builds.
984
+	 * ############################
985
+	 * Note: by "spaces available" we are not returning how many spaces remain.  That is a calculation involving using the value
986
+	 * from this method and subtracting the approved registrations for the event.
987
+	 *
988
+	 * @param   bool $current_total_available       Whether to consider any tickets that have already sold in our calculation.
989
+	 *                                              If this is false, then we return the most tickets that could ever be sold
990
+	 *                                              for this event with the datetime and tickets setup on the event under optimal
991
+	 *                                              selling conditions.  Otherwise we return a live calculation of spaces available
992
+	 *                                              based on tickets sold.  Depending on setup and stage of sales, this
993
+	 *                                              may appear to equal remaining tickets.  However, the more tickets are
994
+	 *                                              sold out, the more accurate the "live" total is.
995
+	 * @return  int|float  (Note: if EE_INF is returned its considered a float by PHP)
996
+	 * @throws \EE_Error
997
+	 */
998
+	public function total_available_spaces($current_total_available = false)
999
+	{
1000
+		$spaces_available = 0;
1001
+		//first get all tickets on the event and include expired tickets
1002
+		$tickets = $this->tickets(array('default_where_conditions' => 'none'));
1003
+		$ticket_sums = array();
1004
+		$datetimes = array();
1005
+		$datetime_limits = array();
1006
+		//loop through tickets and normalize them
1007
+		foreach ($tickets as $ticket) {
1008
+			$datetimes = $ticket->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1009
+			if (empty($datetimes)) {
1010
+				continue;
1011
+			}
1012
+			//first datetime should be the lowest datetime
1013
+			$least_datetime = reset($datetimes);
1014
+			//lets reset the ticket quantity to be the lower of either the lowest datetime reg limit or the ticket quantity
1015
+			//IF datetimes sold (and we're not doing current live total available, then use spaces remaining for datetime, not reg_limit.
1016
+			if ($current_total_available) {
1017
+				if ($ticket->is_remaining()) {
1018
+					$remaining = $ticket->remaining();
1019
+				} else {
1020
+					$spaces_available += $ticket->sold();
1021
+					//and we don't cache this ticket to our list because its sold out.
1022
+					continue;
1023
+				}
1024
+			} else {
1025
+				$remaining = min($ticket->qty(), $least_datetime->reg_limit());
1026
+			}
1027
+			//if $ticket_limit == infinity then let's drop out right away and just return that because any infinity amount trumps all other "available" amounts.
1028
+			if ($remaining === EE_INF) {
1029
+				return EE_INF;
1030
+			}
1031
+			//multiply normalized $tkt quantity by the number of datetimes on the ticket as the "sum"
1032
+			//also include the sum of all the datetime reg limits on the ticket for breaking ties.
1033
+			$ticket_sums[$ticket->ID()]['sum'] = $remaining * count($datetimes);
1034
+			$ticket_sums[$ticket->ID()]['datetime_sums'] = 0;
1035
+			foreach ($datetimes as $datetime) {
1036
+				if ($datetime->reg_limit() === EE_INF) {
1037
+					$ticket_sums[$ticket->ID()]['datetime_sums'] = EE_INF;
1038
+				} else {
1039
+					$ticket_sums[$ticket->ID()]['datetime_sums'] += $current_total_available
1040
+						? $datetime->spaces_remaining()
1041
+						: $datetime->reg_limit();
1042
+				}
1043
+				$datetime_limits[$datetime->ID()] = $current_total_available
1044
+					? $datetime->spaces_remaining()
1045
+					: $datetime->reg_limit();
1046
+			}
1047
+			$ticket_sums[$ticket->ID()]['ticket'] = $ticket;
1048
+		}
1049
+		//The order is sorted by lowest available first (which is calculated for each ticket by multiplying the normalized
1050
+		//ticket quantity by the number of datetimes on the ticket).  For tie-breakers, then the next sort is based on the
1051
+		//ticket with the greatest sum of all remaining datetime->spaces_remaining() ( or $datetime->reg_limit() if not
1052
+		//$current_total_available ) for the datetimes on the ticket.
1053
+		usort($ticket_sums, function ($a, $b) {
1054
+			if ($a['sum'] === $b['sum']) {
1055
+				if ($a['datetime_sums'] === $b['datetime_sums']) {
1056
+					return 0;
1057
+				}
1058
+				return $a['datetime_sums'] < $b['datetime_sums'] ? 1 : -1;
1059
+			}
1060
+			return ($a['sum'] < $b['sum']) ? -1 : 1;
1061
+		});
1062
+		//now let's loop through the sorted tickets and simulate sellouts
1063
+		foreach ($ticket_sums as $ticket_info) {
1064
+			if ($ticket_info['ticket'] instanceof EE_Ticket) {
1065
+				$datetimes = $ticket_info['ticket']->datetimes(array('order_by' => array('DTT_reg_limit' => 'ASC')));
1066
+				//need to sort these $datetimes by remaining (only if $current_total_available)
1067
+				//setup datetimes for simulation
1068
+				$ticket_datetimes_remaining = array();
1069
+				foreach ($datetimes as $datetime) {
1070
+					$ticket_datetimes_remaining[$datetime->ID()]['rem'] = $datetime_limits[$datetime->ID()];
1071
+					$ticket_datetimes_remaining[$datetime->ID()]['datetime'] = $datetime;
1072
+				}
1073
+				usort($ticket_datetimes_remaining, function ($a, $b) {
1074
+					if ($a['rem'] === $b['rem']) {
1075
+						return 0;
1076
+					}
1077
+					return ($a['rem'] < $b['rem']) ? -1 : 1;
1078
+				});
1079
+				//get the remaining on the first datetime (which should be the one with the least remaining) and that is
1080
+				//what we add to the spaces_available running total.  Then we need to decrease the remaining on our datetime tracker.
1081
+				$lowest_datetime = reset($ticket_datetimes_remaining);
1082
+				//need to get the lower of; what the remaining is on the lowest datetime, and the remaining on the ticket.
1083
+				// If this ends up being 0 (because of previous tickets in our simulation selling out), then it has already
1084
+				// been tracked on $spaces available and this ticket is now sold out for the simulation, so we can continue
1085
+				// to the next ticket.
1086
+				if ($current_total_available) {
1087
+					$remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->remaining());
1088
+				} else {
1089
+					$remaining = min($lowest_datetime['rem'], $ticket_info['ticket']->qty());
1090
+				}
1091
+				//if $remaining is infinite that means that all datetimes on this ticket are infinite but we've made it here because all
1092
+				//tickets have a quantity.  So we don't have to track datetimes, we can just use ticket quantities for total
1093
+				//available.
1094
+				if ($remaining === EE_INF) {
1095
+					$spaces_available += $ticket_info['ticket']->qty();
1096
+					continue;
1097
+				}
1098
+				//if ticket has sold amounts then we also need to add that (but only if doing live counts)
1099
+				if ($current_total_available) {
1100
+					$spaces_available += $ticket_info['ticket']->sold();
1101
+				}
1102
+				if ($remaining <= 0) {
1103
+					continue;
1104
+				} else {
1105
+					$spaces_available += $remaining;
1106
+				}
1107
+				//loop through the datetimes and sell them out!
1108
+				foreach ($ticket_datetimes_remaining as $datetime_info) {
1109
+					if ($datetime_info['datetime'] instanceof EE_Datetime) {
1110
+						$datetime_limits[$datetime_info['datetime']->ID()] += -$remaining;
1111
+					}
1112
+				}
1113
+			}
1114
+		}
1115
+		return apply_filters(
1116
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
1117
+			$spaces_available,
1118
+			$this,
1119
+			$datetimes,
1120
+			$tickets
1121
+		);
1122
+	}
1123
+
1124
+
1125
+
1126
+	/**
1127
+	 * Checks if the event is set to sold out
1128
+	 *
1129
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
1130
+	 *                      actual status but also to flip the status if necessary to sold
1131
+	 *                      out If false, we just check the existing status of the event
1132
+	 * @return boolean
1133
+	 * @throws \EE_Error
1134
+	 */
1135
+	public function is_sold_out($actual = false)
1136
+	{
1137
+		if ( ! $actual) {
1138
+			return $this->status() === EEM_Event::sold_out;
1139
+		} else {
1140
+			return $this->perform_sold_out_status_check();
1141
+		}
1142
+	}
1143
+
1144
+
1145
+
1146
+	/**
1147
+	 * Checks if the event is marked as postponed
1148
+	 *
1149
+	 * @return boolean
1150
+	 */
1151
+	public function is_postponed()
1152
+	{
1153
+		return $this->status() === EEM_Event::postponed;
1154
+	}
1155
+
1156
+
1157
+
1158
+	/**
1159
+	 * Checks if the event is marked as cancelled
1160
+	 *
1161
+	 * @return boolean
1162
+	 */
1163
+	public function is_cancelled()
1164
+	{
1165
+		return $this->status() === EEM_Event::cancelled;
1166
+	}
1167
+
1168
+
1169
+
1170
+	/**
1171
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1172
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1173
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1174
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1175
+	 * the event is considered expired.
1176
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1177
+	 * set on the EVENT when it is not published and thus is done
1178
+	 *
1179
+	 * @param bool $reset
1180
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1181
+	 * @throws \EE_Error
1182
+	 */
1183
+	public function get_active_status($reset = false)
1184
+	{
1185
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1186
+		if ( ! empty($this->_active_status) && ! $reset) {
1187
+			return $this->_active_status;
1188
+		}
1189
+		//first check if event id is present on this object
1190
+		if ( ! $this->ID()) {
1191
+			return false;
1192
+		}
1193
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1194
+		//if event is published:
1195
+		if ($this->status() === 'publish') {
1196
+			//active?
1197
+			if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1198
+				$this->_active_status = EE_Datetime::active;
1199
+			} else {
1200
+				//upcoming?
1201
+				if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1202
+					$this->_active_status = EE_Datetime::upcoming;
1203
+				} else {
1204
+					//expired?
1205
+					if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0) {
1206
+						$this->_active_status = EE_Datetime::expired;
1207
+					} else {
1208
+						//it would be odd if things make it this far because it basically means there are no datetime's
1209
+						//attached to the event.  So in this case it will just be considered inactive.
1210
+						$this->_active_status = EE_Datetime::inactive;
1211
+					}
1212
+				}
1213
+			}
1214
+		} else {
1215
+			//the event is not published, so let's just set it's active status according to its' post status
1216
+			switch ($this->status()) {
1217
+				case EEM_Event::sold_out :
1218
+					$this->_active_status = EE_Datetime::sold_out;
1219
+					break;
1220
+				case EEM_Event::cancelled :
1221
+					$this->_active_status = EE_Datetime::cancelled;
1222
+					break;
1223
+				case EEM_Event::postponed :
1224
+					$this->_active_status = EE_Datetime::postponed;
1225
+					break;
1226
+				default :
1227
+					$this->_active_status = EE_Datetime::inactive;
1228
+			}
1229
+		}
1230
+		return $this->_active_status;
1231
+	}
1232
+
1233
+
1234
+
1235
+	/**
1236
+	 *    pretty_active_status
1237
+	 *
1238
+	 * @access public
1239
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1240
+	 * @return mixed void|string
1241
+	 * @throws \EE_Error
1242
+	 */
1243
+	public function pretty_active_status($echo = true)
1244
+	{
1245
+		$active_status = $this->get_active_status();
1246
+		$status = '<span class="ee-status event-active-status-'
1247
+				  . $active_status
1248
+				  . '">'
1249
+				  . EEH_Template::pretty_status($active_status, false, 'sentence')
1250
+				  . '</span>';
1251
+		if ($echo) {
1252
+			echo $status;
1253
+			return '';
1254
+		}
1255
+		return $status;
1256
+	}
1257
+
1258
+
1259
+
1260
+	/**
1261
+	 * @return bool|int
1262
+	 * @throws \EE_Error
1263
+	 */
1264
+	public function get_number_of_tickets_sold()
1265
+	{
1266
+		$tkt_sold = 0;
1267
+		if ( ! $this->ID()) {
1268
+			return 0;
1269
+		}
1270
+		$datetimes = $this->datetimes();
1271
+		foreach ($datetimes as $datetime) {
1272
+			if ($datetime instanceof EE_Datetime) {
1273
+				$tkt_sold += $datetime->sold();
1274
+			}
1275
+		}
1276
+		return $tkt_sold;
1277
+	}
1278
+
1279
+
1280
+
1281
+	/**
1282
+	 * This just returns a count of all the registrations for this event
1283
+	 *
1284
+	 * @access  public
1285
+	 * @return int
1286
+	 * @throws \EE_Error
1287
+	 */
1288
+	public function get_count_of_all_registrations()
1289
+	{
1290
+		return EEM_Event::instance()->count_related($this, 'Registration');
1291
+	}
1292
+
1293
+
1294
+
1295
+	/**
1296
+	 * This returns the ticket with the earliest start time that is
1297
+	 * available for this event (across all datetimes attached to the event)
1298
+	 *
1299
+	 * @return EE_Ticket
1300
+	 * @throws \EE_Error
1301
+	 */
1302
+	public function get_ticket_with_earliest_start_time()
1303
+	{
1304
+		$where['Datetime.EVT_ID'] = $this->ID();
1305
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1306
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1307
+	}
1308
+
1309
+
1310
+
1311
+	/**
1312
+	 * This returns the ticket with the latest end time that is available
1313
+	 * for this event (across all datetimes attached to the event)
1314
+	 *
1315
+	 * @return EE_Ticket
1316
+	 * @throws \EE_Error
1317
+	 */
1318
+	public function get_ticket_with_latest_end_time()
1319
+	{
1320
+		$where['Datetime.EVT_ID'] = $this->ID();
1321
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1322
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1323
+	}
1324
+
1325
+
1326
+
1327
+	/**
1328
+	 * This returns whether there are any tickets on sale for this event.
1329
+	 *
1330
+	 * @return bool true = YES tickets on sale.
1331
+	 * @throws \EE_Error
1332
+	 */
1333
+	public function tickets_on_sale()
1334
+	{
1335
+		$earliest_ticket = $this->get_ticket_with_earliest_start_time();
1336
+		$latest_ticket = $this->get_ticket_with_latest_end_time();
1337
+		if ( ! $latest_ticket instanceof EE_Ticket && ! $earliest_ticket instanceof EE_Ticket) {
1338
+			return false;
1339
+		}
1340
+		//check on sale for these two tickets.
1341
+		if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1342
+			return true;
1343
+		}
1344
+		return false;
1345
+	}
1346
+
1347
+
1348
+
1349
+	/**
1350
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1351
+	 * to check for an external URL first
1352
+	 *
1353
+	 * @return string
1354
+	 * @throws \EE_Error
1355
+	 */
1356
+	public function get_permalink()
1357
+	{
1358
+		if ($this->external_url()) {
1359
+			return $this->external_url();
1360
+		} else {
1361
+			return parent::get_permalink();
1362
+		}
1363
+	}
1364
+
1365
+
1366
+
1367
+	/**
1368
+	 * Gets the first term for 'espresso_event_categories' we can find
1369
+	 *
1370
+	 * @param array $query_params like EEM_Base::get_all
1371
+	 * @return EE_Term
1372
+	 * @throws \EE_Error
1373
+	 */
1374
+	public function first_event_category($query_params = array())
1375
+	{
1376
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1377
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1378
+		return EEM_Term::instance()->get_one($query_params);
1379
+	}
1380
+
1381
+
1382
+
1383
+	/**
1384
+	 * Gets all terms for 'espresso_event_categories' we can find
1385
+	 *
1386
+	 * @param array $query_params
1387
+	 * @return EE_Term[]
1388
+	 * @throws \EE_Error
1389
+	 */
1390
+	public function get_all_event_categories($query_params = array())
1391
+	{
1392
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1393
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1394
+		return EEM_Term::instance()->get_all($query_params);
1395
+	}
1396
+
1397
+
1398
+
1399
+	/**
1400
+	 * Gets all the question groups, ordering them by QSG_order ascending
1401
+	 *
1402
+	 * @param array $query_params @see EEM_Base::get_all
1403
+	 * @return EE_Question_Group[]
1404
+	 * @throws \EE_Error
1405
+	 */
1406
+	public function question_groups($query_params = array())
1407
+	{
1408
+		$query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1409
+		return $this->get_many_related('Question_Group', $query_params);
1410
+	}
1411
+
1412
+
1413
+
1414
+	/**
1415
+	 * Implementation for EEI_Has_Icon interface method.
1416
+	 *
1417
+	 * @see EEI_Visual_Representation for comments
1418
+	 * @return string
1419
+	 */
1420
+	public function get_icon()
1421
+	{
1422
+		return '<span class="dashicons dashicons-flag"></span>';
1423
+	}
1424
+
1425
+
1426
+
1427
+	/**
1428
+	 * Implementation for EEI_Admin_Links interface method.
1429
+	 *
1430
+	 * @see EEI_Admin_Links for comments
1431
+	 * @return string
1432
+	 * @throws \EE_Error
1433
+	 */
1434
+	public function get_admin_details_link()
1435
+	{
1436
+		return $this->get_admin_edit_link();
1437
+	}
1438
+
1439
+
1440
+
1441
+	/**
1442
+	 * Implementation for EEI_Admin_Links interface method.
1443
+	 *
1444
+	 * @see EEI_Admin_Links for comments
1445
+	 * @return string
1446
+	 * @throws \EE_Error
1447
+	 */
1448
+	public function get_admin_edit_link()
1449
+	{
1450
+		return EEH_URL::add_query_args_and_nonce(array(
1451
+			'page'   => 'espresso_events',
1452
+			'action' => 'edit',
1453
+			'post'   => $this->ID(),
1454
+		),
1455
+			admin_url('admin.php')
1456
+		);
1457
+	}
1458
+
1459
+
1460
+
1461
+	/**
1462
+	 * Implementation for EEI_Admin_Links interface method.
1463
+	 *
1464
+	 * @see EEI_Admin_Links for comments
1465
+	 * @return string
1466
+	 */
1467
+	public function get_admin_settings_link()
1468
+	{
1469
+		return EEH_URL::add_query_args_and_nonce(array(
1470
+			'page'   => 'espresso_events',
1471
+			'action' => 'default_event_settings',
1472
+		),
1473
+			admin_url('admin.php')
1474
+		);
1475
+	}
1476
+
1477
+
1478
+
1479
+	/**
1480
+	 * Implementation for EEI_Admin_Links interface method.
1481
+	 *
1482
+	 * @see EEI_Admin_Links for comments
1483
+	 * @return string
1484
+	 */
1485
+	public function get_admin_overview_link()
1486
+	{
1487
+		return EEH_URL::add_query_args_and_nonce(array(
1488
+			'page'   => 'espresso_events',
1489
+			'action' => 'default',
1490
+		),
1491
+			admin_url('admin.php')
1492
+		);
1493
+	}
1494 1494
 
1495 1495
 }
Please login to merge, or discard this patch.