Completed
Branch Gutenberg/event-attendees-bloc... (76b12a)
by
unknown
78:26 queued 65:41
created
modules/core_rest_api/EED_Core_Rest_Api.module.php 2 patches
Indentation   +1264 added lines, -1264 removed lines patch added patch discarded remove patch
@@ -22,1268 +22,1268 @@
 block discarded – undo
22 22
 class EED_Core_Rest_Api extends \EED_Module
23 23
 {
24 24
 
25
-    const ee_api_namespace = Domain::API_NAMESPACE;
26
-
27
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
28
-
29
-    const saved_routes_option_names = 'ee_core_routes';
30
-
31
-    /**
32
-     * string used in _links response bodies to make them globally unique.
33
-     *
34
-     * @see http://v2.wp-api.org/extending/linking/
35
-     */
36
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
37
-
38
-    /**
39
-     * @var CalculatedModelFields
40
-     */
41
-    protected static $_field_calculator;
42
-
43
-
44
-    /**
45
-     * @return EED_Core_Rest_Api|EED_Module
46
-     */
47
-    public static function instance()
48
-    {
49
-        self::$_field_calculator = new CalculatedModelFields();
50
-        return parent::get_instance(__CLASS__);
51
-    }
52
-
53
-
54
-    /**
55
-     *    set_hooks - for hooking into EE Core, other modules, etc
56
-     *
57
-     * @access    public
58
-     * @return    void
59
-     */
60
-    public static function set_hooks()
61
-    {
62
-        self::set_hooks_both();
63
-    }
64
-
65
-
66
-    /**
67
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
68
-     *
69
-     * @access    public
70
-     * @return    void
71
-     */
72
-    public static function set_hooks_admin()
73
-    {
74
-        self::set_hooks_both();
75
-    }
76
-
77
-
78
-    public static function set_hooks_both()
79
-    {
80
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
81
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
82
-        add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
83
-        add_filter(
84
-            'rest_index',
85
-            array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex')
86
-        );
87
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
88
-    }
89
-
90
-
91
-    /**
92
-     * sets up hooks which only need to be included as part of REST API requests;
93
-     * other requests like to the frontend or admin etc don't need them
94
-     *
95
-     * @throws \EE_Error
96
-     */
97
-    public static function set_hooks_rest_api()
98
-    {
99
-        // set hooks which account for changes made to the API
100
-        EED_Core_Rest_Api::_set_hooks_for_changes();
101
-    }
102
-
103
-
104
-    /**
105
-     * public wrapper of _set_hooks_for_changes.
106
-     * Loads all the hooks which make requests to old versions of the API
107
-     * appear the same as they always did
108
-     *
109
-     * @throws EE_Error
110
-     */
111
-    public static function set_hooks_for_changes()
112
-    {
113
-        self::_set_hooks_for_changes();
114
-    }
115
-
116
-
117
-    /**
118
-     * Loads all the hooks which make requests to old versions of the API
119
-     * appear the same as they always did
120
-     *
121
-     * @throws EE_Error
122
-     */
123
-    protected static function _set_hooks_for_changes()
124
-    {
125
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
126
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
127
-            // ignore the base parent class
128
-            // and legacy named classes
129
-            if ($classname_in_namespace === 'ChangesInBase'
130
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
131
-            ) {
132
-                continue;
133
-            }
134
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
135
-            if (class_exists($full_classname)) {
136
-                $instance_of_class = new $full_classname;
137
-                if ($instance_of_class instanceof ChangesInBase) {
138
-                    $instance_of_class->setHooks();
139
-                }
140
-            }
141
-        }
142
-    }
143
-
144
-
145
-    /**
146
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
147
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
148
-     *
149
-     * @throws \EE_Error
150
-     */
151
-    public static function register_routes()
152
-    {
153
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
154
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
155
-                /**
156
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
157
-                 *                                         but can also contain route options like {
158
-                 * @type array    $schema                      {
159
-                 * @type callable $schema_callback
160
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
161
-                 * WP_REST_Request of course
162
-                 * }
163
-                 * }
164
-                 */
165
-                // when registering routes, register all the endpoints' data at the same time
166
-                $multiple_endpoint_args = array();
167
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
168
-                    /**
169
-                     * @var array     $data_for_single_endpoint {
170
-                     * @type callable $callback
171
-                     * @type string methods
172
-                     * @type array args
173
-                     * @type array _links
174
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
175
-                     * WP_REST_Request of course
176
-                     * }
177
-                     */
178
-                    // skip route options
179
-                    if (! is_numeric($endpoint_key)) {
180
-                        continue;
181
-                    }
182
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
183
-                        throw new EE_Error(
184
-                            esc_html__(
185
-                            // @codingStandardsIgnoreStart
186
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
187
-                                // @codingStandardsIgnoreEnd
188
-                                'event_espresso'
189
-                            )
190
-                        );
191
-                    }
192
-                    $callback = $data_for_single_endpoint['callback'];
193
-                    $single_endpoint_args = array(
194
-                        'methods' => $data_for_single_endpoint['methods'],
195
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
196
-                            : array(),
197
-                    );
198
-                    if (isset($data_for_single_endpoint['_links'])) {
199
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
200
-                    }
201
-                    if (isset($data_for_single_endpoint['callback_args'])) {
202
-                        $callback_args = $data_for_single_endpoint['callback_args'];
203
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
204
-                            $callback,
205
-                            $callback_args
206
-                        ) {
207
-                            array_unshift($callback_args, $request);
208
-                            return call_user_func_array(
209
-                                $callback,
210
-                                $callback_args
211
-                            );
212
-                        };
213
-                    } else {
214
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
215
-                    }
216
-                    $multiple_endpoint_args[] = $single_endpoint_args;
217
-                }
218
-                if (isset($data_for_multiple_endpoints['schema'])) {
219
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
220
-                    $schema_callback = $schema_route_data['schema_callback'];
221
-                    $callback_args = $schema_route_data['callback_args'];
222
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
223
-                        return call_user_func_array(
224
-                            $schema_callback,
225
-                            $callback_args
226
-                        );
227
-                    };
228
-                }
229
-                register_rest_route(
230
-                    $namespace,
231
-                    $relative_route,
232
-                    $multiple_endpoint_args
233
-                );
234
-            }
235
-        }
236
-    }
237
-
238
-
239
-    /**
240
-     * Checks if there was a version change or something that merits invalidating the cached
241
-     * route data. If so, invalidates the cached route data so that it gets refreshed
242
-     * next time the WP API is used
243
-     */
244
-    public static function invalidate_cached_route_data_on_version_change()
245
-    {
246
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
247
-            EED_Core_Rest_Api::invalidate_cached_route_data();
248
-        }
249
-        foreach (EE_Registry::instance()->addons as $addon) {
250
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
251
-                EED_Core_Rest_Api::invalidate_cached_route_data();
252
-            }
253
-        }
254
-    }
255
-
256
-
257
-    /**
258
-     * Removes the cached route data so it will get refreshed next time the WP API is used
259
-     */
260
-    public static function invalidate_cached_route_data()
261
-    {
262
-        // delete the saved EE REST API routes
263
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
264
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
265
-        }
266
-    }
267
-
268
-
269
-    /**
270
-     * Gets the EE route data
271
-     *
272
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
273
-     * @throws \EE_Error
274
-     * @type string|array $callback
275
-     * @type string       $methods
276
-     * @type boolean      $hidden_endpoint
277
-     * }
278
-     */
279
-    public static function get_ee_route_data()
280
-    {
281
-        $ee_routes = array();
282
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
283
-            $ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
284
-                $version,
285
-                $hidden_endpoints
286
-            );
287
-        }
288
-        return $ee_routes;
289
-    }
290
-
291
-
292
-    /**
293
-     * Gets the EE route data from the wp options if it exists already,
294
-     * otherwise re-generates it and saves it to the option
295
-     *
296
-     * @param string  $version
297
-     * @param boolean $hidden_endpoints
298
-     * @return array
299
-     * @throws \EE_Error
300
-     */
301
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
302
-    {
303
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
304
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
305
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
306
-        }
307
-        return $ee_routes;
308
-    }
309
-
310
-
311
-    /**
312
-     * Saves the EE REST API route data to a wp option and returns it
313
-     *
314
-     * @param string  $version
315
-     * @param boolean $hidden_endpoints
316
-     * @return mixed|null
317
-     * @throws \EE_Error
318
-     */
319
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
320
-    {
321
-        $instance = self::instance();
322
-        $routes = apply_filters(
323
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
324
-            array_replace_recursive(
325
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
326
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
327
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
328
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
329
-            )
330
-        );
331
-        $option_name = self::saved_routes_option_names . $version;
332
-        if (get_option($option_name)) {
333
-            update_option($option_name, $routes, true);
334
-        } else {
335
-            add_option($option_name, $routes, null, 'no');
336
-        }
337
-        return $routes;
338
-    }
339
-
340
-
341
-    /**
342
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
343
-     * need to calculate it on every request
344
-     *
345
-     * @deprecated since version 4.9.1
346
-     * @return void
347
-     */
348
-    public static function save_ee_routes()
349
-    {
350
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
351
-            $instance = self::instance();
352
-            $routes = apply_filters(
353
-                'EED_Core_Rest_Api__save_ee_routes__routes',
354
-                array_replace_recursive(
355
-                    $instance->_register_config_routes(),
356
-                    $instance->_register_meta_routes(),
357
-                    $instance->_register_model_routes(),
358
-                    $instance->_register_rpc_routes()
359
-                )
360
-            );
361
-            update_option(self::saved_routes_option_names, $routes, true);
362
-        }
363
-    }
364
-
365
-
366
-    /**
367
-     * Gets all the route information relating to EE models
368
-     *
369
-     * @return array @see get_ee_route_data
370
-     * @deprecated since version 4.9.1
371
-     */
372
-    protected function _register_model_routes()
373
-    {
374
-        $model_routes = array();
375
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
376
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
377
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
378
-        }
379
-        return $model_routes;
380
-    }
381
-
382
-
383
-    /**
384
-     * Decides whether or not to add write endpoints for this model.
385
-     *
386
-     * Currently, this defaults to exclude all global tables and models
387
-     * which would allow inserting WP core data (we don't want to duplicate
388
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
389
-     *
390
-     * @param EEM_Base $model
391
-     * @return bool
392
-     */
393
-    public static function should_have_write_endpoints(EEM_Base $model)
394
-    {
395
-        if ($model->is_wp_core_model()) {
396
-            return false;
397
-        }
398
-        foreach ($model->get_tables() as $table) {
399
-            if ($table->is_global()) {
400
-                return false;
401
-            }
402
-        }
403
-        return true;
404
-    }
405
-
406
-
407
-    /**
408
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
409
-     * in this versioned namespace of EE4
410
-     *
411
-     * @param $version
412
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
413
-     */
414
-    public static function model_names_with_plural_routes($version)
415
-    {
416
-        $model_version_info = new ModelVersionInfo($version);
417
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
418
-        // let's not bother having endpoints for extra metas
419
-        unset(
420
-            $models_to_register['Extra_Meta'],
421
-            $models_to_register['Extra_Join'],
422
-            $models_to_register['Post_Meta']
423
-        );
424
-        return apply_filters(
425
-            'FHEE__EED_Core_REST_API___register_model_routes',
426
-            $models_to_register
427
-        );
428
-    }
429
-
430
-
431
-    /**
432
-     * Gets the route data for EE models in the specified version
433
-     *
434
-     * @param string  $version
435
-     * @param boolean $hidden_endpoint
436
-     * @return array
437
-     * @throws EE_Error
438
-     */
439
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
440
-    {
441
-        $model_routes = array();
442
-        $model_version_info = new ModelVersionInfo($version);
443
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
444
-            $model = \EE_Registry::instance()->load_model($model_name);
445
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
446
-            if (! $model instanceof EEM_Base) {
447
-                continue;
448
-            }
449
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
450
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
451
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
452
-            $model_routes[ $plural_model_route ] = array(
453
-                array(
454
-                    'callback'        => array(
455
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
456
-                        'handleRequestGetAll',
457
-                    ),
458
-                    'callback_args'   => array($version, $model_name),
459
-                    'methods'         => WP_REST_Server::READABLE,
460
-                    'hidden_endpoint' => $hidden_endpoint,
461
-                    'args'            => $this->_get_read_query_params($model, $version),
462
-                    '_links'          => array(
463
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
464
-                    ),
465
-                ),
466
-                'schema' => array(
467
-                    'schema_callback' => array(
468
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
469
-                        'handleSchemaRequest',
470
-                    ),
471
-                    'callback_args'   => array($version, $model_name),
472
-                ),
473
-            );
474
-            $model_routes[ $singular_model_route ] = array(
475
-                array(
476
-                    'callback'        => array(
477
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
478
-                        'handleRequestGetOne',
479
-                    ),
480
-                    'callback_args'   => array($version, $model_name),
481
-                    'methods'         => WP_REST_Server::READABLE,
482
-                    'hidden_endpoint' => $hidden_endpoint,
483
-                    'args'            => $this->_get_response_selection_query_params($model, $version),
484
-                ),
485
-            );
486
-            if (apply_filters(
487
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
488
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
489
-                $model
490
-            )) {
491
-                $model_routes[ $plural_model_route ][] = array(
492
-                    'callback'        => array(
493
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
494
-                        'handleRequestInsert',
495
-                    ),
496
-                    'callback_args'   => array($version, $model_name),
497
-                    'methods'         => WP_REST_Server::CREATABLE,
498
-                    'hidden_endpoint' => $hidden_endpoint,
499
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
500
-                );
501
-                $model_routes[ $singular_model_route ] = array_merge(
502
-                    $model_routes[ $singular_model_route ],
503
-                    array(
504
-                        array(
505
-                            'callback'        => array(
506
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
507
-                                'handleRequestUpdate',
508
-                            ),
509
-                            'callback_args'   => array($version, $model_name),
510
-                            'methods'         => WP_REST_Server::EDITABLE,
511
-                            'hidden_endpoint' => $hidden_endpoint,
512
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
513
-                        ),
514
-                        array(
515
-                            'callback'        => array(
516
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
517
-                                'handleRequestDelete',
518
-                            ),
519
-                            'callback_args'   => array($version, $model_name),
520
-                            'methods'         => WP_REST_Server::DELETABLE,
521
-                            'hidden_endpoint' => $hidden_endpoint,
522
-                            'args'            => $this->_get_delete_query_params($model, $version),
523
-                        ),
524
-                    )
525
-                );
526
-            }
527
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
528
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
529
-                    $model,
530
-                    '(?P<id>[^\/]+)',
531
-                    $relation_obj
532
-                );
533
-                $endpoints = array(
534
-                    array(
535
-                        'callback'        => array(
536
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
537
-                            'handleRequestGetRelated',
538
-                        ),
539
-                        'callback_args'   => array($version, $model_name, $relation_name),
540
-                        'methods'         => WP_REST_Server::READABLE,
541
-                        'hidden_endpoint' => $hidden_endpoint,
542
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
543
-                    ),
544
-                );
545
-                $model_routes[ $related_route ] = $endpoints;
546
-            }
547
-        }
548
-        return $model_routes;
549
-    }
550
-
551
-
552
-    /**
553
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
554
-     * excluding the preceding slash.
555
-     * Eg you pass get_plural_route_to('Event') = 'events'
556
-     *
557
-     * @param EEM_Base $model
558
-     * @return string
559
-     */
560
-    public static function get_collection_route(EEM_Base $model)
561
-    {
562
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
563
-    }
564
-
565
-
566
-    /**
567
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
568
-     * excluding the preceding slash.
569
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
570
-     *
571
-     * @param EEM_Base $model eg Event or Venue
572
-     * @param string   $id
573
-     * @return string
574
-     */
575
-    public static function get_entity_route($model, $id)
576
-    {
577
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
578
-    }
579
-
580
-
581
-    /**
582
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
583
-     * excluding the preceding slash.
584
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
585
-     *
586
-     * @param EEM_Base               $model eg Event or Venue
587
-     * @param string                 $id
588
-     * @param EE_Model_Relation_Base $relation_obj
589
-     * @return string
590
-     */
591
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
592
-    {
593
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
594
-            $relation_obj->get_other_model()->get_this_model_name(),
595
-            $relation_obj
596
-        );
597
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
598
-    }
599
-
600
-
601
-    /**
602
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
603
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
604
-     *
605
-     * @param string $relative_route
606
-     * @param string $version
607
-     * @return string
608
-     */
609
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
610
-    {
611
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
612
-    }
613
-
614
-
615
-    /**
616
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
617
-     * routes that don't conform to the traditional REST CRUD-style).
618
-     *
619
-     * @deprecated since 4.9.1
620
-     */
621
-    protected function _register_rpc_routes()
622
-    {
623
-        $routes = array();
624
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
625
-            $routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
626
-                $version,
627
-                $hidden_endpoint
628
-            );
629
-        }
630
-        return $routes;
631
-    }
632
-
633
-
634
-    /**
635
-     * @param string  $version
636
-     * @param boolean $hidden_endpoint
637
-     * @return array
638
-     */
639
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
640
-    {
641
-        $this_versions_routes = array();
642
-        // checkin endpoint
643
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
644
-            array(
645
-                'callback'        => array(
646
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
647
-                    'handleRequestToggleCheckin',
648
-                ),
649
-                'methods'         => WP_REST_Server::CREATABLE,
650
-                'hidden_endpoint' => $hidden_endpoint,
651
-                'args'            => array(
652
-                    'force' => array(
653
-                        'required'    => false,
654
-                        'default'     => false,
655
-                        'description' => __(
656
-                        // @codingStandardsIgnoreStart
657
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
658
-                            // @codingStandardsIgnoreEnd
659
-                            'event_espresso'
660
-                        ),
661
-                    ),
662
-                ),
663
-                'callback_args'   => array($version),
664
-            ),
665
-        );
666
-        return apply_filters(
667
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
668
-            $this_versions_routes,
669
-            $version,
670
-            $hidden_endpoint
671
-        );
672
-    }
673
-
674
-
675
-    /**
676
-     * Gets the query params that can be used when request one or many
677
-     *
678
-     * @param EEM_Base $model
679
-     * @param string   $version
680
-     * @return array
681
-     */
682
-    protected function _get_response_selection_query_params(\EEM_Base $model, $version)
683
-    {
684
-        return apply_filters(
685
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
686
-            array(
687
-                'include'   => array(
688
-                    'required' => false,
689
-                    'default'  => '*',
690
-                    'type'     => 'string',
691
-                ),
692
-                'calculate' => array(
693
-                    'required'          => false,
694
-                    'default'           => '',
695
-                    'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
696
-                    'type'              => 'string',
697
-                    // because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
698
-                    // freaks out. We'll just validate this argument while handling the request
699
-                    'validate_callback' => null,
700
-                    'sanitize_callback' => null,
701
-                ),
702
-            ),
703
-            $model,
704
-            $version
705
-        );
706
-    }
707
-
708
-
709
-    /**
710
-     * Gets the parameters acceptable for delete requests
711
-     *
712
-     * @param \EEM_Base $model
713
-     * @param string    $version
714
-     * @return array
715
-     */
716
-    protected function _get_delete_query_params(\EEM_Base $model, $version)
717
-    {
718
-        $params_for_delete = array(
719
-            'allow_blocking' => array(
720
-                'required' => false,
721
-                'default'  => true,
722
-                'type'     => 'boolean',
723
-            ),
724
-        );
725
-        $params_for_delete['force'] = array(
726
-            'required' => false,
727
-            'default'  => false,
728
-            'type'     => 'boolean',
729
-        );
730
-        return apply_filters(
731
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
732
-            $params_for_delete,
733
-            $model,
734
-            $version
735
-        );
736
-    }
737
-
738
-
739
-    /**
740
-     * Gets info about reading query params that are acceptable
741
-     *
742
-     * @param \EEM_Base $model eg 'Event' or 'Venue'
743
-     * @param  string   $version
744
-     * @return array    describing the args acceptable when querying this model
745
-     * @throws EE_Error
746
-     */
747
-    protected function _get_read_query_params(\EEM_Base $model, $version)
748
-    {
749
-        $default_orderby = array();
750
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
751
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
752
-        }
753
-        return array_merge(
754
-            $this->_get_response_selection_query_params($model, $version),
755
-            array(
756
-                'where'    => array(
757
-                    'required'          => false,
758
-                    'default'           => array(),
759
-                    'type'              => 'object',
760
-                    // because we accept an almost infinite list of possible where conditions, WP
761
-                    // core validation and sanitization freaks out. We'll just validate this argument
762
-                    // while handling the request
763
-                    'validate_callback' => null,
764
-                    'sanitize_callback' => null,
765
-                ),
766
-                'limit'    => array(
767
-                    'required'          => false,
768
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
769
-                    'type'              => array(
770
-                        'array',
771
-                        'string',
772
-                        'integer',
773
-                    ),
774
-                    // because we accept a variety of types, WP core validation and sanitization
775
-                    // freaks out. We'll just validate this argument while handling the request
776
-                    'validate_callback' => null,
777
-                    'sanitize_callback' => null,
778
-                ),
779
-                'order_by' => array(
780
-                    'required'          => false,
781
-                    'default'           => $default_orderby,
782
-                    'type'              => array(
783
-                        'object',
784
-                        'string',
785
-                    ),// because we accept a variety of types, WP core validation and sanitization
786
-                    // freaks out. We'll just validate this argument while handling the request
787
-                    'validate_callback' => null,
788
-                    'sanitize_callback' => null,
789
-                ),
790
-                'group_by' => array(
791
-                    'required'          => false,
792
-                    'default'           => null,
793
-                    'type'              => array(
794
-                        'object',
795
-                        'string',
796
-                    ),
797
-                    // because we accept  an almost infinite list of possible groupings,
798
-                    // WP core validation and sanitization
799
-                    // freaks out. We'll just validate this argument while handling the request
800
-                    'validate_callback' => null,
801
-                    'sanitize_callback' => null,
802
-                ),
803
-                'having'   => array(
804
-                    'required'          => false,
805
-                    'default'           => null,
806
-                    'type'              => 'object',
807
-                    // because we accept an almost infinite list of possible where conditions, WP
808
-                    // core validation and sanitization freaks out. We'll just validate this argument
809
-                    // while handling the request
810
-                    'validate_callback' => null,
811
-                    'sanitize_callback' => null,
812
-                ),
813
-                'caps'     => array(
814
-                    'required' => false,
815
-                    'default'  => EEM_Base::caps_read,
816
-                    'type'     => 'string',
817
-                    'enum'     => array(
818
-                        EEM_Base::caps_read,
819
-                        EEM_Base::caps_read_admin,
820
-                        EEM_Base::caps_edit,
821
-                        EEM_Base::caps_delete,
822
-                    ),
823
-                ),
824
-            )
825
-        );
826
-    }
827
-
828
-
829
-    /**
830
-     * Gets parameter information for a model regarding writing data
831
-     *
832
-     * @param string           $model_name
833
-     * @param ModelVersionInfo $model_version_info
834
-     * @param boolean          $create                                       whether this is for request to create (in
835
-     *                                                                       which case we need all required params) or
836
-     *                                                                       just to update (in which case we don't
837
-     *                                                                       need those on every request)
838
-     * @return array
839
-     */
840
-    protected function _get_write_params(
841
-        $model_name,
842
-        ModelVersionInfo $model_version_info,
843
-        $create = false
844
-    ) {
845
-        $model = EE_Registry::instance()->load_model($model_name);
846
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
847
-        $args_info = array();
848
-        foreach ($fields as $field_name => $field_obj) {
849
-            if ($field_obj->is_auto_increment()) {
850
-                // totally ignore auto increment IDs
851
-                continue;
852
-            }
853
-            $arg_info = $field_obj->getSchema();
854
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
855
-            $arg_info['required'] = $required;
856
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
857
-            unset($arg_info['readonly']);
858
-            $schema_properties = $field_obj->getSchemaProperties();
859
-            if (isset($schema_properties['raw'])
860
-                && $field_obj->getSchemaType() === 'object'
861
-            ) {
862
-                // if there's a "raw" form of this argument, use those properties instead
863
-                $arg_info = array_replace(
864
-                    $arg_info,
865
-                    $schema_properties['raw']
866
-                );
867
-            }
868
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
869
-                $field_obj,
870
-                $field_obj->get_default_value(),
871
-                $model_version_info->requestedVersion()
872
-            );
873
-            // we do our own validation and sanitization within the controller
874
-            if (function_exists('rest_validate_value_from_schema')) {
875
-                $sanitize_callback = array(
876
-                    'EED_Core_Rest_Api',
877
-                    'default_sanitize_callback',
878
-                );
879
-            } else {
880
-                $sanitize_callback = null;
881
-            }
882
-            $arg_info['sanitize_callback'] = $sanitize_callback;
883
-            $args_info[ $field_name ] = $arg_info;
884
-            if ($field_obj instanceof EE_Datetime_Field) {
885
-                $gmt_arg_info = $arg_info;
886
-                $gmt_arg_info['description'] = sprintf(
887
-                    esc_html__(
888
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
889
-                        'event_espresso'
890
-                    ),
891
-                    $field_obj->get_nicename(),
892
-                    $field_name
893
-                );
894
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
895
-            }
896
-        }
897
-        return $args_info;
898
-    }
899
-
900
-
901
-    /**
902
-     * Replacement for WP API's 'rest_parse_request_arg'.
903
-     * If the value is blank but not required, don't bother validating it.
904
-     * Also, it uses our email validation instead of WP API's default.
905
-     *
906
-     * @param                 $value
907
-     * @param WP_REST_Request $request
908
-     * @param                 $param
909
-     * @return bool|true|WP_Error
910
-     * @throws InvalidArgumentException
911
-     * @throws InvalidInterfaceException
912
-     * @throws InvalidDataTypeException
913
-     */
914
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
915
-    {
916
-        $attributes = $request->get_attributes();
917
-        if (! isset($attributes['args'][ $param ])
918
-            || ! is_array($attributes['args'][ $param ])) {
919
-            $validation_result = true;
920
-        } else {
921
-            $args = $attributes['args'][ $param ];
922
-            if ((
923
-                    $value === ''
924
-                    || $value === null
925
-                )
926
-                && (! isset($args['required'])
927
-                    || $args['required'] === false
928
-                )
929
-            ) {
930
-                // not required and not provided? that's cool
931
-                $validation_result = true;
932
-            } elseif (isset($args['format'])
933
-                      && $args['format'] === 'email'
934
-            ) {
935
-                $validation_result = true;
936
-                if (! self::_validate_email($value)) {
937
-                    $validation_result = new WP_Error(
938
-                        'rest_invalid_param',
939
-                        esc_html__(
940
-                            'The email address is not valid or does not exist.',
941
-                            'event_espresso'
942
-                        )
943
-                    );
944
-                }
945
-            } else {
946
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
947
-            }
948
-        }
949
-        if (is_wp_error($validation_result)) {
950
-            return $validation_result;
951
-        }
952
-        return rest_sanitize_request_arg($value, $request, $param);
953
-    }
954
-
955
-
956
-    /**
957
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
958
-     *
959
-     * @param $email
960
-     * @return bool
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidInterfaceException
963
-     * @throws InvalidDataTypeException
964
-     */
965
-    protected static function _validate_email($email)
966
-    {
967
-        try {
968
-            EmailAddressFactory::create($email);
969
-            return true;
970
-        } catch (EmailValidationException $e) {
971
-            return false;
972
-        }
973
-    }
974
-
975
-
976
-    /**
977
-     * Gets routes for the config
978
-     *
979
-     * @return array @see _register_model_routes
980
-     * @deprecated since version 4.9.1
981
-     */
982
-    protected function _register_config_routes()
983
-    {
984
-        $config_routes = array();
985
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
986
-            $config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
987
-                $version,
988
-                $hidden_endpoint
989
-            );
990
-        }
991
-        return $config_routes;
992
-    }
993
-
994
-
995
-    /**
996
-     * Gets routes for the config for the specified version
997
-     *
998
-     * @param string  $version
999
-     * @param boolean $hidden_endpoint
1000
-     * @return array
1001
-     */
1002
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1003
-    {
1004
-        return array(
1005
-            'config'    => array(
1006
-                array(
1007
-                    'callback'        => array(
1008
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1009
-                        'handleRequest',
1010
-                    ),
1011
-                    'methods'         => WP_REST_Server::READABLE,
1012
-                    'hidden_endpoint' => $hidden_endpoint,
1013
-                    'callback_args'   => array($version),
1014
-                ),
1015
-            ),
1016
-            'site_info' => array(
1017
-                array(
1018
-                    'callback'        => array(
1019
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1020
-                        'handleRequestSiteInfo',
1021
-                    ),
1022
-                    'methods'         => WP_REST_Server::READABLE,
1023
-                    'hidden_endpoint' => $hidden_endpoint,
1024
-                    'callback_args'   => array($version),
1025
-                ),
1026
-            ),
1027
-        );
1028
-    }
1029
-
1030
-
1031
-    /**
1032
-     * Gets the meta info routes
1033
-     *
1034
-     * @return array @see _register_model_routes
1035
-     * @deprecated since version 4.9.1
1036
-     */
1037
-    protected function _register_meta_routes()
1038
-    {
1039
-        $meta_routes = array();
1040
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1041
-            $meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1042
-                $version,
1043
-                $hidden_endpoint
1044
-            );
1045
-        }
1046
-        return $meta_routes;
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     * @param string  $version
1052
-     * @param boolean $hidden_endpoint
1053
-     * @return array
1054
-     */
1055
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1056
-    {
1057
-        return array(
1058
-            'resources' => array(
1059
-                array(
1060
-                    'callback'        => array(
1061
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1062
-                        'handleRequestModelsMeta',
1063
-                    ),
1064
-                    'methods'         => WP_REST_Server::READABLE,
1065
-                    'hidden_endpoint' => $hidden_endpoint,
1066
-                    'callback_args'   => array($version),
1067
-                ),
1068
-            ),
1069
-        );
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     * Tries to hide old 4.6 endpoints from the
1075
-     *
1076
-     * @param array $route_data
1077
-     * @return array
1078
-     * @throws \EE_Error
1079
-     */
1080
-    public static function hide_old_endpoints($route_data)
1081
-    {
1082
-        // allow API clients to override which endpoints get hidden, in case
1083
-        // they want to discover particular endpoints
1084
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1085
-        $force_show_ee_namespace = ltrim(
1086
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1087
-            '/'
1088
-        );
1089
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1090
-            foreach ($relative_urls as $resource_name => $endpoints) {
1091
-                foreach ($endpoints as $key => $endpoint) {
1092
-                    // skip schema and other route options
1093
-                    if (! is_numeric($key)) {
1094
-                        continue;
1095
-                    }
1096
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1097
-                    // to $force_show_ee_namespace, in which case only show that one
1098
-                    // namespace's endpoints (and hide all others)
1099
-                    if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1100
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1101
-                    ) {
1102
-                        $full_route = '/' . ltrim($namespace, '/');
1103
-                        $full_route .= '/' . ltrim($resource_name, '/');
1104
-                        unset($route_data[ $full_route ]);
1105
-                    }
1106
-                }
1107
-            }
1108
-        }
1109
-        return $route_data;
1110
-    }
1111
-
1112
-
1113
-    /**
1114
-     * Returns an array describing which versions of core support serving requests for.
1115
-     * Keys are core versions' major and minor version, and values are the
1116
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1117
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1118
-     * the answers table entirely, in which case it would be very difficult for
1119
-     * it to serve 4.6-style responses.
1120
-     * Versions of core that are missing from this array are unknowns.
1121
-     * previous ver
1122
-     *
1123
-     * @return array
1124
-     */
1125
-    public static function version_compatibilities()
1126
-    {
1127
-        return apply_filters(
1128
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1129
-            array(
1130
-                '4.8.29' => '4.8.29',
1131
-                '4.8.33' => '4.8.29',
1132
-                '4.8.34' => '4.8.29',
1133
-                '4.8.36' => '4.8.29',
1134
-            )
1135
-        );
1136
-    }
1137
-
1138
-
1139
-    /**
1140
-     * Gets the latest API version served. Eg if there
1141
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1142
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1143
-     *
1144
-     * @return string
1145
-     */
1146
-    public static function latest_rest_api_version()
1147
-    {
1148
-        $versions_served = \EED_Core_Rest_Api::versions_served();
1149
-        $versions_served_keys = array_keys($versions_served);
1150
-        return end($versions_served_keys);
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1156
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1157
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1158
-     * We also indicate whether or not this version should be put in the index or not
1159
-     *
1160
-     * @return array keys are API version numbers (just major and minor numbers), and values
1161
-     * are whether or not they should be hidden
1162
-     */
1163
-    public static function versions_served()
1164
-    {
1165
-        $versions_served = array();
1166
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1167
-        $lowest_compatible_version = end($possibly_served_versions);
1168
-        reset($possibly_served_versions);
1169
-        $versions_served_historically = array_keys($possibly_served_versions);
1170
-        $latest_version = end($versions_served_historically);
1171
-        reset($versions_served_historically);
1172
-        // for each version of core we have ever served:
1173
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1174
-            // if it's not above the current core version, and it's compatible with the current version of core
1175
-            if ($key_versioned_endpoint === $latest_version) {
1176
-                // don't hide the latest version in the index
1177
-                $versions_served[ $key_versioned_endpoint ] = false;
1178
-            } elseif ($key_versioned_endpoint >= $lowest_compatible_version
1179
-                && $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1180
-            ) {
1181
-                // include, but hide, previous versions which are still supported
1182
-                $versions_served[ $key_versioned_endpoint ] = true;
1183
-            } elseif (apply_filters(
1184
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1185
-                false,
1186
-                $possibly_served_versions
1187
-            )) {
1188
-                // if a version is no longer supported, don't include it in index or list of versions served
1189
-                $versions_served[ $key_versioned_endpoint ] = true;
1190
-            }
1191
-        }
1192
-        return $versions_served;
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * Gets the major and minor version of EE core's version string
1198
-     *
1199
-     * @return string
1200
-     */
1201
-    public static function core_version()
1202
-    {
1203
-        return apply_filters(
1204
-            'FHEE__EED_Core_REST_API__core_version',
1205
-            implode(
1206
-                '.',
1207
-                array_slice(
1208
-                    explode(
1209
-                        '.',
1210
-                        espresso_version()
1211
-                    ),
1212
-                    0,
1213
-                    3
1214
-                )
1215
-            )
1216
-        );
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     * Gets the default limit that should be used when querying for resources
1222
-     *
1223
-     * @return int
1224
-     */
1225
-    public static function get_default_query_limit()
1226
-    {
1227
-        // we actually don't use a const because we want folks to always use
1228
-        // this method, not the const directly
1229
-        return apply_filters(
1230
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1231
-            50
1232
-        );
1233
-    }
1234
-
1235
-
1236
-    /**
1237
-     *
1238
-     * @param string $version api version string (i.e. '4.8.36')
1239
-     * @return array
1240
-     */
1241
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1242
-    {
1243
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1244
-        $model_names = self::model_names_with_plural_routes($version);
1245
-        $collection_routes = array();
1246
-        foreach ($model_names as $model_name => $model_class_name) {
1247
-            $collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1248
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1249
-        }
1250
-        return $collection_routes;
1251
-    }
1252
-
1253
-
1254
-    /**
1255
-     * Returns an array of primary key names indexed by model names.
1256
-     * @param string $version
1257
-     * @return array
1258
-     */
1259
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1260
-    {
1261
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1262
-        $model_names = self::model_names_with_plural_routes($version);
1263
-        $primary_key_items = array();
1264
-        foreach ($model_names as $model_name => $model_class_name) {
1265
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1266
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1267
-                if (count($primary_keys) > 1) {
1268
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1269
-                } else {
1270
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1271
-                }
1272
-            }
1273
-        }
1274
-        return $primary_key_items;
1275
-    }
1276
-
1277
-
1278
-
1279
-    /**
1280
-     *    run - initial module setup
1281
-     *
1282
-     * @access    public
1283
-     * @param  WP $WP
1284
-     * @return    void
1285
-     */
1286
-    public function run($WP)
1287
-    {
1288
-    }
25
+	const ee_api_namespace = Domain::API_NAMESPACE;
26
+
27
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
28
+
29
+	const saved_routes_option_names = 'ee_core_routes';
30
+
31
+	/**
32
+	 * string used in _links response bodies to make them globally unique.
33
+	 *
34
+	 * @see http://v2.wp-api.org/extending/linking/
35
+	 */
36
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
37
+
38
+	/**
39
+	 * @var CalculatedModelFields
40
+	 */
41
+	protected static $_field_calculator;
42
+
43
+
44
+	/**
45
+	 * @return EED_Core_Rest_Api|EED_Module
46
+	 */
47
+	public static function instance()
48
+	{
49
+		self::$_field_calculator = new CalculatedModelFields();
50
+		return parent::get_instance(__CLASS__);
51
+	}
52
+
53
+
54
+	/**
55
+	 *    set_hooks - for hooking into EE Core, other modules, etc
56
+	 *
57
+	 * @access    public
58
+	 * @return    void
59
+	 */
60
+	public static function set_hooks()
61
+	{
62
+		self::set_hooks_both();
63
+	}
64
+
65
+
66
+	/**
67
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
68
+	 *
69
+	 * @access    public
70
+	 * @return    void
71
+	 */
72
+	public static function set_hooks_admin()
73
+	{
74
+		self::set_hooks_both();
75
+	}
76
+
77
+
78
+	public static function set_hooks_both()
79
+	{
80
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
81
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
82
+		add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
83
+		add_filter(
84
+			'rest_index',
85
+			array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex')
86
+		);
87
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
88
+	}
89
+
90
+
91
+	/**
92
+	 * sets up hooks which only need to be included as part of REST API requests;
93
+	 * other requests like to the frontend or admin etc don't need them
94
+	 *
95
+	 * @throws \EE_Error
96
+	 */
97
+	public static function set_hooks_rest_api()
98
+	{
99
+		// set hooks which account for changes made to the API
100
+		EED_Core_Rest_Api::_set_hooks_for_changes();
101
+	}
102
+
103
+
104
+	/**
105
+	 * public wrapper of _set_hooks_for_changes.
106
+	 * Loads all the hooks which make requests to old versions of the API
107
+	 * appear the same as they always did
108
+	 *
109
+	 * @throws EE_Error
110
+	 */
111
+	public static function set_hooks_for_changes()
112
+	{
113
+		self::_set_hooks_for_changes();
114
+	}
115
+
116
+
117
+	/**
118
+	 * Loads all the hooks which make requests to old versions of the API
119
+	 * appear the same as they always did
120
+	 *
121
+	 * @throws EE_Error
122
+	 */
123
+	protected static function _set_hooks_for_changes()
124
+	{
125
+		$folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
126
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
127
+			// ignore the base parent class
128
+			// and legacy named classes
129
+			if ($classname_in_namespace === 'ChangesInBase'
130
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
131
+			) {
132
+				continue;
133
+			}
134
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
135
+			if (class_exists($full_classname)) {
136
+				$instance_of_class = new $full_classname;
137
+				if ($instance_of_class instanceof ChangesInBase) {
138
+					$instance_of_class->setHooks();
139
+				}
140
+			}
141
+		}
142
+	}
143
+
144
+
145
+	/**
146
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
147
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
148
+	 *
149
+	 * @throws \EE_Error
150
+	 */
151
+	public static function register_routes()
152
+	{
153
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
154
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
155
+				/**
156
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
157
+				 *                                         but can also contain route options like {
158
+				 * @type array    $schema                      {
159
+				 * @type callable $schema_callback
160
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
161
+				 * WP_REST_Request of course
162
+				 * }
163
+				 * }
164
+				 */
165
+				// when registering routes, register all the endpoints' data at the same time
166
+				$multiple_endpoint_args = array();
167
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
168
+					/**
169
+					 * @var array     $data_for_single_endpoint {
170
+					 * @type callable $callback
171
+					 * @type string methods
172
+					 * @type array args
173
+					 * @type array _links
174
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
175
+					 * WP_REST_Request of course
176
+					 * }
177
+					 */
178
+					// skip route options
179
+					if (! is_numeric($endpoint_key)) {
180
+						continue;
181
+					}
182
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
183
+						throw new EE_Error(
184
+							esc_html__(
185
+							// @codingStandardsIgnoreStart
186
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
187
+								// @codingStandardsIgnoreEnd
188
+								'event_espresso'
189
+							)
190
+						);
191
+					}
192
+					$callback = $data_for_single_endpoint['callback'];
193
+					$single_endpoint_args = array(
194
+						'methods' => $data_for_single_endpoint['methods'],
195
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
196
+							: array(),
197
+					);
198
+					if (isset($data_for_single_endpoint['_links'])) {
199
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
200
+					}
201
+					if (isset($data_for_single_endpoint['callback_args'])) {
202
+						$callback_args = $data_for_single_endpoint['callback_args'];
203
+						$single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
204
+							$callback,
205
+							$callback_args
206
+						) {
207
+							array_unshift($callback_args, $request);
208
+							return call_user_func_array(
209
+								$callback,
210
+								$callback_args
211
+							);
212
+						};
213
+					} else {
214
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
215
+					}
216
+					$multiple_endpoint_args[] = $single_endpoint_args;
217
+				}
218
+				if (isset($data_for_multiple_endpoints['schema'])) {
219
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
220
+					$schema_callback = $schema_route_data['schema_callback'];
221
+					$callback_args = $schema_route_data['callback_args'];
222
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
223
+						return call_user_func_array(
224
+							$schema_callback,
225
+							$callback_args
226
+						);
227
+					};
228
+				}
229
+				register_rest_route(
230
+					$namespace,
231
+					$relative_route,
232
+					$multiple_endpoint_args
233
+				);
234
+			}
235
+		}
236
+	}
237
+
238
+
239
+	/**
240
+	 * Checks if there was a version change or something that merits invalidating the cached
241
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
242
+	 * next time the WP API is used
243
+	 */
244
+	public static function invalidate_cached_route_data_on_version_change()
245
+	{
246
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
247
+			EED_Core_Rest_Api::invalidate_cached_route_data();
248
+		}
249
+		foreach (EE_Registry::instance()->addons as $addon) {
250
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
251
+				EED_Core_Rest_Api::invalidate_cached_route_data();
252
+			}
253
+		}
254
+	}
255
+
256
+
257
+	/**
258
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
259
+	 */
260
+	public static function invalidate_cached_route_data()
261
+	{
262
+		// delete the saved EE REST API routes
263
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
264
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
265
+		}
266
+	}
267
+
268
+
269
+	/**
270
+	 * Gets the EE route data
271
+	 *
272
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
273
+	 * @throws \EE_Error
274
+	 * @type string|array $callback
275
+	 * @type string       $methods
276
+	 * @type boolean      $hidden_endpoint
277
+	 * }
278
+	 */
279
+	public static function get_ee_route_data()
280
+	{
281
+		$ee_routes = array();
282
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
283
+			$ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
284
+				$version,
285
+				$hidden_endpoints
286
+			);
287
+		}
288
+		return $ee_routes;
289
+	}
290
+
291
+
292
+	/**
293
+	 * Gets the EE route data from the wp options if it exists already,
294
+	 * otherwise re-generates it and saves it to the option
295
+	 *
296
+	 * @param string  $version
297
+	 * @param boolean $hidden_endpoints
298
+	 * @return array
299
+	 * @throws \EE_Error
300
+	 */
301
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
302
+	{
303
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
304
+		if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
305
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
306
+		}
307
+		return $ee_routes;
308
+	}
309
+
310
+
311
+	/**
312
+	 * Saves the EE REST API route data to a wp option and returns it
313
+	 *
314
+	 * @param string  $version
315
+	 * @param boolean $hidden_endpoints
316
+	 * @return mixed|null
317
+	 * @throws \EE_Error
318
+	 */
319
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
320
+	{
321
+		$instance = self::instance();
322
+		$routes = apply_filters(
323
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
324
+			array_replace_recursive(
325
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
326
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
327
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
328
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
329
+			)
330
+		);
331
+		$option_name = self::saved_routes_option_names . $version;
332
+		if (get_option($option_name)) {
333
+			update_option($option_name, $routes, true);
334
+		} else {
335
+			add_option($option_name, $routes, null, 'no');
336
+		}
337
+		return $routes;
338
+	}
339
+
340
+
341
+	/**
342
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
343
+	 * need to calculate it on every request
344
+	 *
345
+	 * @deprecated since version 4.9.1
346
+	 * @return void
347
+	 */
348
+	public static function save_ee_routes()
349
+	{
350
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
351
+			$instance = self::instance();
352
+			$routes = apply_filters(
353
+				'EED_Core_Rest_Api__save_ee_routes__routes',
354
+				array_replace_recursive(
355
+					$instance->_register_config_routes(),
356
+					$instance->_register_meta_routes(),
357
+					$instance->_register_model_routes(),
358
+					$instance->_register_rpc_routes()
359
+				)
360
+			);
361
+			update_option(self::saved_routes_option_names, $routes, true);
362
+		}
363
+	}
364
+
365
+
366
+	/**
367
+	 * Gets all the route information relating to EE models
368
+	 *
369
+	 * @return array @see get_ee_route_data
370
+	 * @deprecated since version 4.9.1
371
+	 */
372
+	protected function _register_model_routes()
373
+	{
374
+		$model_routes = array();
375
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
376
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
377
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
378
+		}
379
+		return $model_routes;
380
+	}
381
+
382
+
383
+	/**
384
+	 * Decides whether or not to add write endpoints for this model.
385
+	 *
386
+	 * Currently, this defaults to exclude all global tables and models
387
+	 * which would allow inserting WP core data (we don't want to duplicate
388
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
389
+	 *
390
+	 * @param EEM_Base $model
391
+	 * @return bool
392
+	 */
393
+	public static function should_have_write_endpoints(EEM_Base $model)
394
+	{
395
+		if ($model->is_wp_core_model()) {
396
+			return false;
397
+		}
398
+		foreach ($model->get_tables() as $table) {
399
+			if ($table->is_global()) {
400
+				return false;
401
+			}
402
+		}
403
+		return true;
404
+	}
405
+
406
+
407
+	/**
408
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
409
+	 * in this versioned namespace of EE4
410
+	 *
411
+	 * @param $version
412
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
413
+	 */
414
+	public static function model_names_with_plural_routes($version)
415
+	{
416
+		$model_version_info = new ModelVersionInfo($version);
417
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
418
+		// let's not bother having endpoints for extra metas
419
+		unset(
420
+			$models_to_register['Extra_Meta'],
421
+			$models_to_register['Extra_Join'],
422
+			$models_to_register['Post_Meta']
423
+		);
424
+		return apply_filters(
425
+			'FHEE__EED_Core_REST_API___register_model_routes',
426
+			$models_to_register
427
+		);
428
+	}
429
+
430
+
431
+	/**
432
+	 * Gets the route data for EE models in the specified version
433
+	 *
434
+	 * @param string  $version
435
+	 * @param boolean $hidden_endpoint
436
+	 * @return array
437
+	 * @throws EE_Error
438
+	 */
439
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
440
+	{
441
+		$model_routes = array();
442
+		$model_version_info = new ModelVersionInfo($version);
443
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
444
+			$model = \EE_Registry::instance()->load_model($model_name);
445
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
446
+			if (! $model instanceof EEM_Base) {
447
+				continue;
448
+			}
449
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
450
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
451
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
452
+			$model_routes[ $plural_model_route ] = array(
453
+				array(
454
+					'callback'        => array(
455
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
456
+						'handleRequestGetAll',
457
+					),
458
+					'callback_args'   => array($version, $model_name),
459
+					'methods'         => WP_REST_Server::READABLE,
460
+					'hidden_endpoint' => $hidden_endpoint,
461
+					'args'            => $this->_get_read_query_params($model, $version),
462
+					'_links'          => array(
463
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
464
+					),
465
+				),
466
+				'schema' => array(
467
+					'schema_callback' => array(
468
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
469
+						'handleSchemaRequest',
470
+					),
471
+					'callback_args'   => array($version, $model_name),
472
+				),
473
+			);
474
+			$model_routes[ $singular_model_route ] = array(
475
+				array(
476
+					'callback'        => array(
477
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
478
+						'handleRequestGetOne',
479
+					),
480
+					'callback_args'   => array($version, $model_name),
481
+					'methods'         => WP_REST_Server::READABLE,
482
+					'hidden_endpoint' => $hidden_endpoint,
483
+					'args'            => $this->_get_response_selection_query_params($model, $version),
484
+				),
485
+			);
486
+			if (apply_filters(
487
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
488
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
489
+				$model
490
+			)) {
491
+				$model_routes[ $plural_model_route ][] = array(
492
+					'callback'        => array(
493
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
494
+						'handleRequestInsert',
495
+					),
496
+					'callback_args'   => array($version, $model_name),
497
+					'methods'         => WP_REST_Server::CREATABLE,
498
+					'hidden_endpoint' => $hidden_endpoint,
499
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
500
+				);
501
+				$model_routes[ $singular_model_route ] = array_merge(
502
+					$model_routes[ $singular_model_route ],
503
+					array(
504
+						array(
505
+							'callback'        => array(
506
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
507
+								'handleRequestUpdate',
508
+							),
509
+							'callback_args'   => array($version, $model_name),
510
+							'methods'         => WP_REST_Server::EDITABLE,
511
+							'hidden_endpoint' => $hidden_endpoint,
512
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
513
+						),
514
+						array(
515
+							'callback'        => array(
516
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
517
+								'handleRequestDelete',
518
+							),
519
+							'callback_args'   => array($version, $model_name),
520
+							'methods'         => WP_REST_Server::DELETABLE,
521
+							'hidden_endpoint' => $hidden_endpoint,
522
+							'args'            => $this->_get_delete_query_params($model, $version),
523
+						),
524
+					)
525
+				);
526
+			}
527
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
528
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
529
+					$model,
530
+					'(?P<id>[^\/]+)',
531
+					$relation_obj
532
+				);
533
+				$endpoints = array(
534
+					array(
535
+						'callback'        => array(
536
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
537
+							'handleRequestGetRelated',
538
+						),
539
+						'callback_args'   => array($version, $model_name, $relation_name),
540
+						'methods'         => WP_REST_Server::READABLE,
541
+						'hidden_endpoint' => $hidden_endpoint,
542
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
543
+					),
544
+				);
545
+				$model_routes[ $related_route ] = $endpoints;
546
+			}
547
+		}
548
+		return $model_routes;
549
+	}
550
+
551
+
552
+	/**
553
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
554
+	 * excluding the preceding slash.
555
+	 * Eg you pass get_plural_route_to('Event') = 'events'
556
+	 *
557
+	 * @param EEM_Base $model
558
+	 * @return string
559
+	 */
560
+	public static function get_collection_route(EEM_Base $model)
561
+	{
562
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
563
+	}
564
+
565
+
566
+	/**
567
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
568
+	 * excluding the preceding slash.
569
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
570
+	 *
571
+	 * @param EEM_Base $model eg Event or Venue
572
+	 * @param string   $id
573
+	 * @return string
574
+	 */
575
+	public static function get_entity_route($model, $id)
576
+	{
577
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
578
+	}
579
+
580
+
581
+	/**
582
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
583
+	 * excluding the preceding slash.
584
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
585
+	 *
586
+	 * @param EEM_Base               $model eg Event or Venue
587
+	 * @param string                 $id
588
+	 * @param EE_Model_Relation_Base $relation_obj
589
+	 * @return string
590
+	 */
591
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
592
+	{
593
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
594
+			$relation_obj->get_other_model()->get_this_model_name(),
595
+			$relation_obj
596
+		);
597
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
598
+	}
599
+
600
+
601
+	/**
602
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
603
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
604
+	 *
605
+	 * @param string $relative_route
606
+	 * @param string $version
607
+	 * @return string
608
+	 */
609
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
610
+	{
611
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
612
+	}
613
+
614
+
615
+	/**
616
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
617
+	 * routes that don't conform to the traditional REST CRUD-style).
618
+	 *
619
+	 * @deprecated since 4.9.1
620
+	 */
621
+	protected function _register_rpc_routes()
622
+	{
623
+		$routes = array();
624
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
625
+			$routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
626
+				$version,
627
+				$hidden_endpoint
628
+			);
629
+		}
630
+		return $routes;
631
+	}
632
+
633
+
634
+	/**
635
+	 * @param string  $version
636
+	 * @param boolean $hidden_endpoint
637
+	 * @return array
638
+	 */
639
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
640
+	{
641
+		$this_versions_routes = array();
642
+		// checkin endpoint
643
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
644
+			array(
645
+				'callback'        => array(
646
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
647
+					'handleRequestToggleCheckin',
648
+				),
649
+				'methods'         => WP_REST_Server::CREATABLE,
650
+				'hidden_endpoint' => $hidden_endpoint,
651
+				'args'            => array(
652
+					'force' => array(
653
+						'required'    => false,
654
+						'default'     => false,
655
+						'description' => __(
656
+						// @codingStandardsIgnoreStart
657
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
658
+							// @codingStandardsIgnoreEnd
659
+							'event_espresso'
660
+						),
661
+					),
662
+				),
663
+				'callback_args'   => array($version),
664
+			),
665
+		);
666
+		return apply_filters(
667
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
668
+			$this_versions_routes,
669
+			$version,
670
+			$hidden_endpoint
671
+		);
672
+	}
673
+
674
+
675
+	/**
676
+	 * Gets the query params that can be used when request one or many
677
+	 *
678
+	 * @param EEM_Base $model
679
+	 * @param string   $version
680
+	 * @return array
681
+	 */
682
+	protected function _get_response_selection_query_params(\EEM_Base $model, $version)
683
+	{
684
+		return apply_filters(
685
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
686
+			array(
687
+				'include'   => array(
688
+					'required' => false,
689
+					'default'  => '*',
690
+					'type'     => 'string',
691
+				),
692
+				'calculate' => array(
693
+					'required'          => false,
694
+					'default'           => '',
695
+					'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
696
+					'type'              => 'string',
697
+					// because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
698
+					// freaks out. We'll just validate this argument while handling the request
699
+					'validate_callback' => null,
700
+					'sanitize_callback' => null,
701
+				),
702
+			),
703
+			$model,
704
+			$version
705
+		);
706
+	}
707
+
708
+
709
+	/**
710
+	 * Gets the parameters acceptable for delete requests
711
+	 *
712
+	 * @param \EEM_Base $model
713
+	 * @param string    $version
714
+	 * @return array
715
+	 */
716
+	protected function _get_delete_query_params(\EEM_Base $model, $version)
717
+	{
718
+		$params_for_delete = array(
719
+			'allow_blocking' => array(
720
+				'required' => false,
721
+				'default'  => true,
722
+				'type'     => 'boolean',
723
+			),
724
+		);
725
+		$params_for_delete['force'] = array(
726
+			'required' => false,
727
+			'default'  => false,
728
+			'type'     => 'boolean',
729
+		);
730
+		return apply_filters(
731
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
732
+			$params_for_delete,
733
+			$model,
734
+			$version
735
+		);
736
+	}
737
+
738
+
739
+	/**
740
+	 * Gets info about reading query params that are acceptable
741
+	 *
742
+	 * @param \EEM_Base $model eg 'Event' or 'Venue'
743
+	 * @param  string   $version
744
+	 * @return array    describing the args acceptable when querying this model
745
+	 * @throws EE_Error
746
+	 */
747
+	protected function _get_read_query_params(\EEM_Base $model, $version)
748
+	{
749
+		$default_orderby = array();
750
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
751
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
752
+		}
753
+		return array_merge(
754
+			$this->_get_response_selection_query_params($model, $version),
755
+			array(
756
+				'where'    => array(
757
+					'required'          => false,
758
+					'default'           => array(),
759
+					'type'              => 'object',
760
+					// because we accept an almost infinite list of possible where conditions, WP
761
+					// core validation and sanitization freaks out. We'll just validate this argument
762
+					// while handling the request
763
+					'validate_callback' => null,
764
+					'sanitize_callback' => null,
765
+				),
766
+				'limit'    => array(
767
+					'required'          => false,
768
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
769
+					'type'              => array(
770
+						'array',
771
+						'string',
772
+						'integer',
773
+					),
774
+					// because we accept a variety of types, WP core validation and sanitization
775
+					// freaks out. We'll just validate this argument while handling the request
776
+					'validate_callback' => null,
777
+					'sanitize_callback' => null,
778
+				),
779
+				'order_by' => array(
780
+					'required'          => false,
781
+					'default'           => $default_orderby,
782
+					'type'              => array(
783
+						'object',
784
+						'string',
785
+					),// because we accept a variety of types, WP core validation and sanitization
786
+					// freaks out. We'll just validate this argument while handling the request
787
+					'validate_callback' => null,
788
+					'sanitize_callback' => null,
789
+				),
790
+				'group_by' => array(
791
+					'required'          => false,
792
+					'default'           => null,
793
+					'type'              => array(
794
+						'object',
795
+						'string',
796
+					),
797
+					// because we accept  an almost infinite list of possible groupings,
798
+					// WP core validation and sanitization
799
+					// freaks out. We'll just validate this argument while handling the request
800
+					'validate_callback' => null,
801
+					'sanitize_callback' => null,
802
+				),
803
+				'having'   => array(
804
+					'required'          => false,
805
+					'default'           => null,
806
+					'type'              => 'object',
807
+					// because we accept an almost infinite list of possible where conditions, WP
808
+					// core validation and sanitization freaks out. We'll just validate this argument
809
+					// while handling the request
810
+					'validate_callback' => null,
811
+					'sanitize_callback' => null,
812
+				),
813
+				'caps'     => array(
814
+					'required' => false,
815
+					'default'  => EEM_Base::caps_read,
816
+					'type'     => 'string',
817
+					'enum'     => array(
818
+						EEM_Base::caps_read,
819
+						EEM_Base::caps_read_admin,
820
+						EEM_Base::caps_edit,
821
+						EEM_Base::caps_delete,
822
+					),
823
+				),
824
+			)
825
+		);
826
+	}
827
+
828
+
829
+	/**
830
+	 * Gets parameter information for a model regarding writing data
831
+	 *
832
+	 * @param string           $model_name
833
+	 * @param ModelVersionInfo $model_version_info
834
+	 * @param boolean          $create                                       whether this is for request to create (in
835
+	 *                                                                       which case we need all required params) or
836
+	 *                                                                       just to update (in which case we don't
837
+	 *                                                                       need those on every request)
838
+	 * @return array
839
+	 */
840
+	protected function _get_write_params(
841
+		$model_name,
842
+		ModelVersionInfo $model_version_info,
843
+		$create = false
844
+	) {
845
+		$model = EE_Registry::instance()->load_model($model_name);
846
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
847
+		$args_info = array();
848
+		foreach ($fields as $field_name => $field_obj) {
849
+			if ($field_obj->is_auto_increment()) {
850
+				// totally ignore auto increment IDs
851
+				continue;
852
+			}
853
+			$arg_info = $field_obj->getSchema();
854
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
855
+			$arg_info['required'] = $required;
856
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
857
+			unset($arg_info['readonly']);
858
+			$schema_properties = $field_obj->getSchemaProperties();
859
+			if (isset($schema_properties['raw'])
860
+				&& $field_obj->getSchemaType() === 'object'
861
+			) {
862
+				// if there's a "raw" form of this argument, use those properties instead
863
+				$arg_info = array_replace(
864
+					$arg_info,
865
+					$schema_properties['raw']
866
+				);
867
+			}
868
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
869
+				$field_obj,
870
+				$field_obj->get_default_value(),
871
+				$model_version_info->requestedVersion()
872
+			);
873
+			// we do our own validation and sanitization within the controller
874
+			if (function_exists('rest_validate_value_from_schema')) {
875
+				$sanitize_callback = array(
876
+					'EED_Core_Rest_Api',
877
+					'default_sanitize_callback',
878
+				);
879
+			} else {
880
+				$sanitize_callback = null;
881
+			}
882
+			$arg_info['sanitize_callback'] = $sanitize_callback;
883
+			$args_info[ $field_name ] = $arg_info;
884
+			if ($field_obj instanceof EE_Datetime_Field) {
885
+				$gmt_arg_info = $arg_info;
886
+				$gmt_arg_info['description'] = sprintf(
887
+					esc_html__(
888
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
889
+						'event_espresso'
890
+					),
891
+					$field_obj->get_nicename(),
892
+					$field_name
893
+				);
894
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
895
+			}
896
+		}
897
+		return $args_info;
898
+	}
899
+
900
+
901
+	/**
902
+	 * Replacement for WP API's 'rest_parse_request_arg'.
903
+	 * If the value is blank but not required, don't bother validating it.
904
+	 * Also, it uses our email validation instead of WP API's default.
905
+	 *
906
+	 * @param                 $value
907
+	 * @param WP_REST_Request $request
908
+	 * @param                 $param
909
+	 * @return bool|true|WP_Error
910
+	 * @throws InvalidArgumentException
911
+	 * @throws InvalidInterfaceException
912
+	 * @throws InvalidDataTypeException
913
+	 */
914
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
915
+	{
916
+		$attributes = $request->get_attributes();
917
+		if (! isset($attributes['args'][ $param ])
918
+			|| ! is_array($attributes['args'][ $param ])) {
919
+			$validation_result = true;
920
+		} else {
921
+			$args = $attributes['args'][ $param ];
922
+			if ((
923
+					$value === ''
924
+					|| $value === null
925
+				)
926
+				&& (! isset($args['required'])
927
+					|| $args['required'] === false
928
+				)
929
+			) {
930
+				// not required and not provided? that's cool
931
+				$validation_result = true;
932
+			} elseif (isset($args['format'])
933
+					  && $args['format'] === 'email'
934
+			) {
935
+				$validation_result = true;
936
+				if (! self::_validate_email($value)) {
937
+					$validation_result = new WP_Error(
938
+						'rest_invalid_param',
939
+						esc_html__(
940
+							'The email address is not valid or does not exist.',
941
+							'event_espresso'
942
+						)
943
+					);
944
+				}
945
+			} else {
946
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
947
+			}
948
+		}
949
+		if (is_wp_error($validation_result)) {
950
+			return $validation_result;
951
+		}
952
+		return rest_sanitize_request_arg($value, $request, $param);
953
+	}
954
+
955
+
956
+	/**
957
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
958
+	 *
959
+	 * @param $email
960
+	 * @return bool
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidInterfaceException
963
+	 * @throws InvalidDataTypeException
964
+	 */
965
+	protected static function _validate_email($email)
966
+	{
967
+		try {
968
+			EmailAddressFactory::create($email);
969
+			return true;
970
+		} catch (EmailValidationException $e) {
971
+			return false;
972
+		}
973
+	}
974
+
975
+
976
+	/**
977
+	 * Gets routes for the config
978
+	 *
979
+	 * @return array @see _register_model_routes
980
+	 * @deprecated since version 4.9.1
981
+	 */
982
+	protected function _register_config_routes()
983
+	{
984
+		$config_routes = array();
985
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
986
+			$config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
987
+				$version,
988
+				$hidden_endpoint
989
+			);
990
+		}
991
+		return $config_routes;
992
+	}
993
+
994
+
995
+	/**
996
+	 * Gets routes for the config for the specified version
997
+	 *
998
+	 * @param string  $version
999
+	 * @param boolean $hidden_endpoint
1000
+	 * @return array
1001
+	 */
1002
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1003
+	{
1004
+		return array(
1005
+			'config'    => array(
1006
+				array(
1007
+					'callback'        => array(
1008
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1009
+						'handleRequest',
1010
+					),
1011
+					'methods'         => WP_REST_Server::READABLE,
1012
+					'hidden_endpoint' => $hidden_endpoint,
1013
+					'callback_args'   => array($version),
1014
+				),
1015
+			),
1016
+			'site_info' => array(
1017
+				array(
1018
+					'callback'        => array(
1019
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1020
+						'handleRequestSiteInfo',
1021
+					),
1022
+					'methods'         => WP_REST_Server::READABLE,
1023
+					'hidden_endpoint' => $hidden_endpoint,
1024
+					'callback_args'   => array($version),
1025
+				),
1026
+			),
1027
+		);
1028
+	}
1029
+
1030
+
1031
+	/**
1032
+	 * Gets the meta info routes
1033
+	 *
1034
+	 * @return array @see _register_model_routes
1035
+	 * @deprecated since version 4.9.1
1036
+	 */
1037
+	protected function _register_meta_routes()
1038
+	{
1039
+		$meta_routes = array();
1040
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1041
+			$meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1042
+				$version,
1043
+				$hidden_endpoint
1044
+			);
1045
+		}
1046
+		return $meta_routes;
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 * @param string  $version
1052
+	 * @param boolean $hidden_endpoint
1053
+	 * @return array
1054
+	 */
1055
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1056
+	{
1057
+		return array(
1058
+			'resources' => array(
1059
+				array(
1060
+					'callback'        => array(
1061
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1062
+						'handleRequestModelsMeta',
1063
+					),
1064
+					'methods'         => WP_REST_Server::READABLE,
1065
+					'hidden_endpoint' => $hidden_endpoint,
1066
+					'callback_args'   => array($version),
1067
+				),
1068
+			),
1069
+		);
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 * Tries to hide old 4.6 endpoints from the
1075
+	 *
1076
+	 * @param array $route_data
1077
+	 * @return array
1078
+	 * @throws \EE_Error
1079
+	 */
1080
+	public static function hide_old_endpoints($route_data)
1081
+	{
1082
+		// allow API clients to override which endpoints get hidden, in case
1083
+		// they want to discover particular endpoints
1084
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1085
+		$force_show_ee_namespace = ltrim(
1086
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1087
+			'/'
1088
+		);
1089
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1090
+			foreach ($relative_urls as $resource_name => $endpoints) {
1091
+				foreach ($endpoints as $key => $endpoint) {
1092
+					// skip schema and other route options
1093
+					if (! is_numeric($key)) {
1094
+						continue;
1095
+					}
1096
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1097
+					// to $force_show_ee_namespace, in which case only show that one
1098
+					// namespace's endpoints (and hide all others)
1099
+					if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1100
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1101
+					) {
1102
+						$full_route = '/' . ltrim($namespace, '/');
1103
+						$full_route .= '/' . ltrim($resource_name, '/');
1104
+						unset($route_data[ $full_route ]);
1105
+					}
1106
+				}
1107
+			}
1108
+		}
1109
+		return $route_data;
1110
+	}
1111
+
1112
+
1113
+	/**
1114
+	 * Returns an array describing which versions of core support serving requests for.
1115
+	 * Keys are core versions' major and minor version, and values are the
1116
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1117
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1118
+	 * the answers table entirely, in which case it would be very difficult for
1119
+	 * it to serve 4.6-style responses.
1120
+	 * Versions of core that are missing from this array are unknowns.
1121
+	 * previous ver
1122
+	 *
1123
+	 * @return array
1124
+	 */
1125
+	public static function version_compatibilities()
1126
+	{
1127
+		return apply_filters(
1128
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1129
+			array(
1130
+				'4.8.29' => '4.8.29',
1131
+				'4.8.33' => '4.8.29',
1132
+				'4.8.34' => '4.8.29',
1133
+				'4.8.36' => '4.8.29',
1134
+			)
1135
+		);
1136
+	}
1137
+
1138
+
1139
+	/**
1140
+	 * Gets the latest API version served. Eg if there
1141
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1142
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1143
+	 *
1144
+	 * @return string
1145
+	 */
1146
+	public static function latest_rest_api_version()
1147
+	{
1148
+		$versions_served = \EED_Core_Rest_Api::versions_served();
1149
+		$versions_served_keys = array_keys($versions_served);
1150
+		return end($versions_served_keys);
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1156
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1157
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1158
+	 * We also indicate whether or not this version should be put in the index or not
1159
+	 *
1160
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1161
+	 * are whether or not they should be hidden
1162
+	 */
1163
+	public static function versions_served()
1164
+	{
1165
+		$versions_served = array();
1166
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1167
+		$lowest_compatible_version = end($possibly_served_versions);
1168
+		reset($possibly_served_versions);
1169
+		$versions_served_historically = array_keys($possibly_served_versions);
1170
+		$latest_version = end($versions_served_historically);
1171
+		reset($versions_served_historically);
1172
+		// for each version of core we have ever served:
1173
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1174
+			// if it's not above the current core version, and it's compatible with the current version of core
1175
+			if ($key_versioned_endpoint === $latest_version) {
1176
+				// don't hide the latest version in the index
1177
+				$versions_served[ $key_versioned_endpoint ] = false;
1178
+			} elseif ($key_versioned_endpoint >= $lowest_compatible_version
1179
+				&& $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1180
+			) {
1181
+				// include, but hide, previous versions which are still supported
1182
+				$versions_served[ $key_versioned_endpoint ] = true;
1183
+			} elseif (apply_filters(
1184
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1185
+				false,
1186
+				$possibly_served_versions
1187
+			)) {
1188
+				// if a version is no longer supported, don't include it in index or list of versions served
1189
+				$versions_served[ $key_versioned_endpoint ] = true;
1190
+			}
1191
+		}
1192
+		return $versions_served;
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * Gets the major and minor version of EE core's version string
1198
+	 *
1199
+	 * @return string
1200
+	 */
1201
+	public static function core_version()
1202
+	{
1203
+		return apply_filters(
1204
+			'FHEE__EED_Core_REST_API__core_version',
1205
+			implode(
1206
+				'.',
1207
+				array_slice(
1208
+					explode(
1209
+						'.',
1210
+						espresso_version()
1211
+					),
1212
+					0,
1213
+					3
1214
+				)
1215
+			)
1216
+		);
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 * Gets the default limit that should be used when querying for resources
1222
+	 *
1223
+	 * @return int
1224
+	 */
1225
+	public static function get_default_query_limit()
1226
+	{
1227
+		// we actually don't use a const because we want folks to always use
1228
+		// this method, not the const directly
1229
+		return apply_filters(
1230
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1231
+			50
1232
+		);
1233
+	}
1234
+
1235
+
1236
+	/**
1237
+	 *
1238
+	 * @param string $version api version string (i.e. '4.8.36')
1239
+	 * @return array
1240
+	 */
1241
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1242
+	{
1243
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1244
+		$model_names = self::model_names_with_plural_routes($version);
1245
+		$collection_routes = array();
1246
+		foreach ($model_names as $model_name => $model_class_name) {
1247
+			$collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1248
+															. EEH_Inflector::pluralize_and_lower($model_name);
1249
+		}
1250
+		return $collection_routes;
1251
+	}
1252
+
1253
+
1254
+	/**
1255
+	 * Returns an array of primary key names indexed by model names.
1256
+	 * @param string $version
1257
+	 * @return array
1258
+	 */
1259
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1260
+	{
1261
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1262
+		$model_names = self::model_names_with_plural_routes($version);
1263
+		$primary_key_items = array();
1264
+		foreach ($model_names as $model_name => $model_class_name) {
1265
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1266
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1267
+				if (count($primary_keys) > 1) {
1268
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1269
+				} else {
1270
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1271
+				}
1272
+			}
1273
+		}
1274
+		return $primary_key_items;
1275
+	}
1276
+
1277
+
1278
+
1279
+	/**
1280
+	 *    run - initial module setup
1281
+	 *
1282
+	 * @access    public
1283
+	 * @param  WP $WP
1284
+	 * @return    void
1285
+	 */
1286
+	public function run($WP)
1287
+	{
1288
+	}
1289 1289
 }
Please login to merge, or discard this patch.
Spacing   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
      */
123 123
     protected static function _set_hooks_for_changes()
124 124
     {
125
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
125
+        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES.'rest_api'.DS.'changes'), false);
126 126
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
127 127
             // ignore the base parent class
128 128
             // and legacy named classes
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
             ) {
132 132
                 continue;
133 133
             }
134
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
134
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
135 135
             if (class_exists($full_classname)) {
136 136
                 $instance_of_class = new $full_classname;
137 137
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -176,10 +176,10 @@  discard block
 block discarded – undo
176 176
                      * }
177 177
                      */
178 178
                     // skip route options
179
-                    if (! is_numeric($endpoint_key)) {
179
+                    if ( ! is_numeric($endpoint_key)) {
180 180
                         continue;
181 181
                     }
182
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
182
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
183 183
                         throw new EE_Error(
184 184
                             esc_html__(
185 185
                             // @codingStandardsIgnoreStart
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
                     }
201 201
                     if (isset($data_for_single_endpoint['callback_args'])) {
202 202
                         $callback_args = $data_for_single_endpoint['callback_args'];
203
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
203
+                        $single_endpoint_args['callback'] = function(\WP_REST_Request $request) use (
204 204
                             $callback,
205 205
                             $callback_args
206 206
                         ) {
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
220 220
                     $schema_callback = $schema_route_data['schema_callback'];
221 221
                     $callback_args = $schema_route_data['callback_args'];
222
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
222
+                    $multiple_endpoint_args['schema'] = function() use ($schema_callback, $callback_args) {
223 223
                         return call_user_func_array(
224 224
                             $schema_callback,
225 225
                             $callback_args
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
     {
262 262
         // delete the saved EE REST API routes
263 263
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
264
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
264
+            delete_option(EED_Core_Rest_Api::saved_routes_option_names.$version);
265 265
         }
266 266
     }
267 267
 
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
     {
281 281
         $ee_routes = array();
282 282
         foreach (self::versions_served() as $version => $hidden_endpoints) {
283
-            $ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
283
+            $ee_routes[self::ee_api_namespace.$version] = self::_get_ee_route_data_for_version(
284 284
                 $version,
285 285
                 $hidden_endpoints
286 286
             );
@@ -300,8 +300,8 @@  discard block
 block discarded – undo
300 300
      */
301 301
     protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
302 302
     {
303
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
304
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
303
+        $ee_routes = get_option(self::saved_routes_option_names.$version, null);
304
+        if ( ! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
305 305
             $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
306 306
         }
307 307
         return $ee_routes;
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
                 $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
329 329
             )
330 330
         );
331
-        $option_name = self::saved_routes_option_names . $version;
331
+        $option_name = self::saved_routes_option_names.$version;
332 332
         if (get_option($option_name)) {
333 333
             update_option($option_name, $routes, true);
334 334
         } else {
@@ -373,8 +373,8 @@  discard block
 block discarded – undo
373 373
     {
374 374
         $model_routes = array();
375 375
         foreach (self::versions_served() as $version => $hidden_endpoint) {
376
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
377
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
376
+            $model_routes[EED_Core_Rest_Api::ee_api_namespace
377
+                           . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
378 378
         }
379 379
         return $model_routes;
380 380
     }
@@ -443,13 +443,13 @@  discard block
 block discarded – undo
443 443
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
444 444
             $model = \EE_Registry::instance()->load_model($model_name);
445 445
             // if this isn't a valid model then let's skip iterate to the next item in the loop.
446
-            if (! $model instanceof EEM_Base) {
446
+            if ( ! $model instanceof EEM_Base) {
447 447
                 continue;
448 448
             }
449 449
             // yes we could just register one route for ALL models, but then they wouldn't show up in the index
450 450
             $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
451 451
             $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
452
-            $model_routes[ $plural_model_route ] = array(
452
+            $model_routes[$plural_model_route] = array(
453 453
                 array(
454 454
                     'callback'        => array(
455 455
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -460,7 +460,7 @@  discard block
 block discarded – undo
460 460
                     'hidden_endpoint' => $hidden_endpoint,
461 461
                     'args'            => $this->_get_read_query_params($model, $version),
462 462
                     '_links'          => array(
463
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
463
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
464 464
                     ),
465 465
                 ),
466 466
                 'schema' => array(
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
                     'callback_args'   => array($version, $model_name),
472 472
                 ),
473 473
             );
474
-            $model_routes[ $singular_model_route ] = array(
474
+            $model_routes[$singular_model_route] = array(
475 475
                 array(
476 476
                     'callback'        => array(
477 477
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -488,7 +488,7 @@  discard block
 block discarded – undo
488 488
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
489 489
                 $model
490 490
             )) {
491
-                $model_routes[ $plural_model_route ][] = array(
491
+                $model_routes[$plural_model_route][] = array(
492 492
                     'callback'        => array(
493 493
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
494 494
                         'handleRequestInsert',
@@ -498,8 +498,8 @@  discard block
 block discarded – undo
498 498
                     'hidden_endpoint' => $hidden_endpoint,
499 499
                     'args'            => $this->_get_write_params($model_name, $model_version_info, true),
500 500
                 );
501
-                $model_routes[ $singular_model_route ] = array_merge(
502
-                    $model_routes[ $singular_model_route ],
501
+                $model_routes[$singular_model_route] = array_merge(
502
+                    $model_routes[$singular_model_route],
503 503
                     array(
504 504
                         array(
505 505
                             'callback'        => array(
@@ -542,7 +542,7 @@  discard block
 block discarded – undo
542 542
                         'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
543 543
                     ),
544 544
                 );
545
-                $model_routes[ $related_route ] = $endpoints;
545
+                $model_routes[$related_route] = $endpoints;
546 546
             }
547 547
         }
548 548
         return $model_routes;
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
      */
575 575
     public static function get_entity_route($model, $id)
576 576
     {
577
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
577
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
578 578
     }
579 579
 
580 580
 
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
             $relation_obj->get_other_model()->get_this_model_name(),
595 595
             $relation_obj
596 596
         );
597
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
597
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
598 598
     }
599 599
 
600 600
 
@@ -608,7 +608,7 @@  discard block
 block discarded – undo
608 608
      */
609 609
     public static function get_versioned_route_to($relative_route, $version = '4.8.36')
610 610
     {
611
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
611
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
612 612
     }
613 613
 
614 614
 
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
     {
623 623
         $routes = array();
624 624
         foreach (self::versions_served() as $version => $hidden_endpoint) {
625
-            $routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
625
+            $routes[self::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
626 626
                 $version,
627 627
                 $hidden_endpoint
628 628
             );
@@ -748,7 +748,7 @@  discard block
 block discarded – undo
748 748
     {
749 749
         $default_orderby = array();
750 750
         foreach ($model->get_combined_primary_key_fields() as $key_field) {
751
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
751
+            $default_orderby[$key_field->get_name()] = 'ASC';
752 752
         }
753 753
         return array_merge(
754 754
             $this->_get_response_selection_query_params($model, $version),
@@ -782,7 +782,7 @@  discard block
 block discarded – undo
782 782
                     'type'              => array(
783 783
                         'object',
784 784
                         'string',
785
-                    ),// because we accept a variety of types, WP core validation and sanitization
785
+                    ), // because we accept a variety of types, WP core validation and sanitization
786 786
                     // freaks out. We'll just validate this argument while handling the request
787 787
                     'validate_callback' => null,
788 788
                     'sanitize_callback' => null,
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
                 $sanitize_callback = null;
881 881
             }
882 882
             $arg_info['sanitize_callback'] = $sanitize_callback;
883
-            $args_info[ $field_name ] = $arg_info;
883
+            $args_info[$field_name] = $arg_info;
884 884
             if ($field_obj instanceof EE_Datetime_Field) {
885 885
                 $gmt_arg_info = $arg_info;
886 886
                 $gmt_arg_info['description'] = sprintf(
@@ -891,7 +891,7 @@  discard block
 block discarded – undo
891 891
                     $field_obj->get_nicename(),
892 892
                     $field_name
893 893
                 );
894
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
894
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
895 895
             }
896 896
         }
897 897
         return $args_info;
@@ -914,16 +914,16 @@  discard block
 block discarded – undo
914 914
     public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
915 915
     {
916 916
         $attributes = $request->get_attributes();
917
-        if (! isset($attributes['args'][ $param ])
918
-            || ! is_array($attributes['args'][ $param ])) {
917
+        if ( ! isset($attributes['args'][$param])
918
+            || ! is_array($attributes['args'][$param])) {
919 919
             $validation_result = true;
920 920
         } else {
921
-            $args = $attributes['args'][ $param ];
921
+            $args = $attributes['args'][$param];
922 922
             if ((
923 923
                     $value === ''
924 924
                     || $value === null
925 925
                 )
926
-                && (! isset($args['required'])
926
+                && ( ! isset($args['required'])
927 927
                     || $args['required'] === false
928 928
                 )
929 929
             ) {
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
                       && $args['format'] === 'email'
934 934
             ) {
935 935
                 $validation_result = true;
936
-                if (! self::_validate_email($value)) {
936
+                if ( ! self::_validate_email($value)) {
937 937
                     $validation_result = new WP_Error(
938 938
                         'rest_invalid_param',
939 939
                         esc_html__(
@@ -983,7 +983,7 @@  discard block
 block discarded – undo
983 983
     {
984 984
         $config_routes = array();
985 985
         foreach (self::versions_served() as $version => $hidden_endpoint) {
986
-            $config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
986
+            $config_routes[self::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
987 987
                 $version,
988 988
                 $hidden_endpoint
989 989
             );
@@ -1038,7 +1038,7 @@  discard block
 block discarded – undo
1038 1038
     {
1039 1039
         $meta_routes = array();
1040 1040
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1041
-            $meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1041
+            $meta_routes[self::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1042 1042
                 $version,
1043 1043
                 $hidden_endpoint
1044 1044
             );
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
             foreach ($relative_urls as $resource_name => $endpoints) {
1091 1091
                 foreach ($endpoints as $key => $endpoint) {
1092 1092
                     // skip schema and other route options
1093
-                    if (! is_numeric($key)) {
1093
+                    if ( ! is_numeric($key)) {
1094 1094
                         continue;
1095 1095
                     }
1096 1096
                     // by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1099,9 +1099,9 @@  discard block
 block discarded – undo
1099 1099
                     if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1100 1100
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1101 1101
                     ) {
1102
-                        $full_route = '/' . ltrim($namespace, '/');
1103
-                        $full_route .= '/' . ltrim($resource_name, '/');
1104
-                        unset($route_data[ $full_route ]);
1102
+                        $full_route = '/'.ltrim($namespace, '/');
1103
+                        $full_route .= '/'.ltrim($resource_name, '/');
1104
+                        unset($route_data[$full_route]);
1105 1105
                     }
1106 1106
                 }
1107 1107
             }
@@ -1174,19 +1174,19 @@  discard block
 block discarded – undo
1174 1174
             // if it's not above the current core version, and it's compatible with the current version of core
1175 1175
             if ($key_versioned_endpoint === $latest_version) {
1176 1176
                 // don't hide the latest version in the index
1177
-                $versions_served[ $key_versioned_endpoint ] = false;
1177
+                $versions_served[$key_versioned_endpoint] = false;
1178 1178
             } elseif ($key_versioned_endpoint >= $lowest_compatible_version
1179 1179
                 && $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1180 1180
             ) {
1181 1181
                 // include, but hide, previous versions which are still supported
1182
-                $versions_served[ $key_versioned_endpoint ] = true;
1182
+                $versions_served[$key_versioned_endpoint] = true;
1183 1183
             } elseif (apply_filters(
1184 1184
                 'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1185 1185
                 false,
1186 1186
                 $possibly_served_versions
1187 1187
             )) {
1188 1188
                 // if a version is no longer supported, don't include it in index or list of versions served
1189
-                $versions_served[ $key_versioned_endpoint ] = true;
1189
+                $versions_served[$key_versioned_endpoint] = true;
1190 1190
             }
1191 1191
         }
1192 1192
         return $versions_served;
@@ -1244,7 +1244,7 @@  discard block
 block discarded – undo
1244 1244
         $model_names = self::model_names_with_plural_routes($version);
1245 1245
         $collection_routes = array();
1246 1246
         foreach ($model_names as $model_name => $model_class_name) {
1247
-            $collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1247
+            $collection_routes[strtolower($model_name)] = '/'.self::ee_api_namespace.$version.'/'
1248 1248
                                                             . EEH_Inflector::pluralize_and_lower($model_name);
1249 1249
         }
1250 1250
         return $collection_routes;
@@ -1265,9 +1265,9 @@  discard block
 block discarded – undo
1265 1265
             $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1266 1266
             foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1267 1267
                 if (count($primary_keys) > 1) {
1268
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1268
+                    $primary_key_items[strtolower($model_name)][] = $primary_key_name;
1269 1269
                 } else {
1270
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1270
+                    $primary_key_items[strtolower($model_name)] = $primary_key_name;
1271 1271
                 }
1272 1272
             }
1273 1273
         }
Please login to merge, or discard this patch.
core/db_models/EEM_CPT_Base.model.php 1 patch
Indentation   +557 added lines, -557 removed lines patch added patch discarded remove patch
@@ -16,561 +16,561 @@
 block discarded – undo
16 16
 abstract class EEM_CPT_Base extends EEM_Soft_Delete_Base
17 17
 {
18 18
 
19
-    const EVENT_CATEGORY_TAXONOMY = 'espresso_event_category';
20
-
21
-    /**
22
-     * @var string post_status_publish - the wp post status for published cpts
23
-     */
24
-    const post_status_publish = 'publish';
25
-
26
-    /**
27
-     * @var string post_status_future - the wp post status for scheduled cpts
28
-     */
29
-    const post_status_future = 'future';
30
-
31
-    /**
32
-     * @var string post_status_draft - the wp post status for draft cpts
33
-     */
34
-    const post_status_draft = 'draft';
35
-
36
-    /**
37
-     * @var string post_status_pending - the wp post status for pending cpts
38
-     */
39
-    const post_status_pending = 'pending';
40
-
41
-    /**
42
-     * @var string post_status_private - the wp post status for private cpts
43
-     */
44
-    const post_status_private = 'private';
45
-
46
-    /**
47
-     * @var string post_status_trashed - the wp post status for trashed cpts
48
-     */
49
-    const post_status_trashed = 'trash';
50
-
51
-    /**
52
-     * This is an array of custom statuses for the given CPT model (modified by children)
53
-     * format:
54
-     * array(
55
-     *        'status_name' => array(
56
-     *            'label' => __('Status Name', 'event_espresso'),
57
-     *            'public' => TRUE //whether a public status or not.
58
-     *        )
59
-     * )
60
-     *
61
-     * @var array
62
-     */
63
-    protected $_custom_stati = array();
64
-
65
-
66
-    /**
67
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
68
-     *
69
-     * @param string $timezone
70
-     * @throws \EE_Error
71
-     */
72
-    protected function __construct($timezone = null)
73
-    {
74
-        // adds a relationship to Term_Taxonomy for all these models. For this to work
75
-        // Term_Relationship must have a relation to each model subclassing EE_CPT_Base explicitly
76
-        // eg, in EEM_Term_Relationship, inside the _model_relations array, there must be an entry
77
-        // with key equalling the subclassing model's model name (eg 'Event' or 'Venue'), and the value
78
-        // must also be new EE_HABTM_Relation('Term_Relationship');
79
-        $this->_model_relations['Term_Taxonomy'] = new EE_HABTM_Relation('Term_Relationship');
80
-        $primary_table_name = null;
81
-        // add  the common _status field to all CPT primary tables.
82
-        foreach ($this->_tables as $alias => $table_obj) {
83
-            if ($table_obj instanceof EE_Primary_Table) {
84
-                $primary_table_name = $alias;
85
-            }
86
-        }
87
-        // set default wp post statuses if child has not already set.
88
-        if (! isset($this->_fields[ $primary_table_name ]['status'])) {
89
-            $this->_fields[ $primary_table_name ]['status'] = new EE_WP_Post_Status_Field(
90
-                'post_status',
91
-                __("Event Status", "event_espresso"),
92
-                false,
93
-                'draft'
94
-            );
95
-        }
96
-        if (! isset($this->_fields[ $primary_table_name ]['to_ping'])) {
97
-            $this->_fields[ $primary_table_name ]['to_ping'] = new EE_DB_Only_Text_Field(
98
-                'to_ping',
99
-                __('To Ping', 'event_espresso'),
100
-                false,
101
-                ''
102
-            );
103
-        }
104
-        if (! isset($this->_fields[ $primary_table_name ]['pinged'])) {
105
-            $this->_fields[ $primary_table_name ]['pinged'] = new EE_DB_Only_Text_Field(
106
-                'pinged',
107
-                __('Pinged', 'event_espresso'),
108
-                false,
109
-                ''
110
-            );
111
-        }
112
-        if (! isset($this->_fields[ $primary_table_name ]['comment_status'])) {
113
-            $this->_fields[ $primary_table_name ]['comment_status'] = new EE_Plain_Text_Field(
114
-                'comment_status',
115
-                __('Comment Status', 'event_espresso'),
116
-                false,
117
-                'open'
118
-            );
119
-        }
120
-        if (! isset($this->_fields[ $primary_table_name ]['ping_status'])) {
121
-            $this->_fields[ $primary_table_name ]['ping_status'] = new EE_Plain_Text_Field(
122
-                'ping_status',
123
-                __('Ping Status', 'event_espresso'),
124
-                false,
125
-                'open'
126
-            );
127
-        }
128
-        if (! isset($this->_fields[ $primary_table_name ]['post_content_filtered'])) {
129
-            $this->_fields[ $primary_table_name ]['post_content_filtered'] = new EE_DB_Only_Text_Field(
130
-                'post_content_filtered',
131
-                __('Post Content Filtered', 'event_espresso'),
132
-                false,
133
-                ''
134
-            );
135
-        }
136
-        if (! isset($this->_model_relations['Post_Meta'])) {
137
-            // don't block deletes though because we want to maintain the current behaviour
138
-            $this->_model_relations['Post_Meta'] = new EE_Has_Many_Relation(false);
139
-        }
140
-        if (! $this->_minimum_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
141
-            // nothing was set during child constructor, so set default
142
-            $this->_minimum_where_conditions_strategy = new EE_CPT_Minimum_Where_Conditions($this->post_type());
143
-        }
144
-        if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
145
-            // nothing was set during child constructor, so set default
146
-            // it's ok for child classes to specify this, but generally this is more DRY
147
-            $this->_default_where_conditions_strategy = new EE_CPT_Where_Conditions($this->post_type());
148
-        }
149
-        parent::__construct($timezone);
150
-    }
151
-
152
-
153
-    /**
154
-     * @return array
155
-     */
156
-    public function public_event_stati()
157
-    {
158
-        // @see wp-includes/post.php
159
-        return get_post_stati(array('public' => true));
160
-    }
161
-
162
-
163
-    /**
164
-     * Searches for field on this model of type 'deleted_flag'. if it is found,
165
-     * returns it's name. BUT That doesn't apply to CPTs. We should instead use post_status_field_name
166
-     *
167
-     * @return string
168
-     * @throws EE_Error
169
-     */
170
-    public function deleted_field_name()
171
-    {
172
-        throw new EE_Error(
173
-            sprintf(
174
-                __(
175
-                    "EEM_CPT_Base should nto call deleted_field_name! It should instead use post_status_field_name",
176
-                    "event_espresso"
177
-                )
178
-            )
179
-        );
180
-    }
181
-
182
-
183
-    /**
184
-     * Gets the field's name that sets the post status
185
-     *
186
-     * @return string
187
-     * @throws EE_Error
188
-     */
189
-    public function post_status_field_name()
190
-    {
191
-        $field = $this->get_a_field_of_type('EE_WP_Post_Status_Field');
192
-        if ($field) {
193
-            return $field->get_name();
194
-        } else {
195
-            throw new EE_Error(
196
-                sprintf(
197
-                    __(
198
-                        'We are trying to find the post status flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
199
-                        'event_espresso'
200
-                    ),
201
-                    get_class($this),
202
-                    get_class($this)
203
-                )
204
-            );
205
-        }
206
-    }
207
-
208
-
209
-    /**
210
-     * Alters the query params so that only trashed/soft-deleted items are considered
211
-     *
212
-     * @param array $query_params like EEM_Base::get_all's $query_params
213
-     * @return array like EEM_Base::get_all's $query_params
214
-     */
215
-    protected function _alter_query_params_so_only_trashed_items_included($query_params)
216
-    {
217
-        $post_status_field_name = $this->post_status_field_name();
218
-        $query_params[0][ $post_status_field_name ] = self::post_status_trashed;
219
-        return $query_params;
220
-    }
221
-
222
-
223
-    /**
224
-     * Alters the query params so each item's deleted status is ignored.
225
-     *
226
-     * @param array $query_params
227
-     * @return array
228
-     */
229
-    protected function _alter_query_params_so_deleted_and_undeleted_items_included($query_params)
230
-    {
231
-        $query_params['default_where_conditions'] = 'minimum';
232
-        return $query_params;
233
-    }
234
-
235
-
236
-    /**
237
-     * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
238
-     *
239
-     * @param boolean $delete       true to indicate deletion, false to indicate restoration
240
-     * @param array   $query_params like EEM_Base::get_all
241
-     * @return boolean success
242
-     */
243
-    public function delete_or_restore($delete = true, $query_params = array())
244
-    {
245
-        $post_status_field_name = $this->post_status_field_name();
246
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
247
-        $new_status = $delete ? self::post_status_trashed : 'draft';
248
-        if ($this->update(array($post_status_field_name => $new_status), $query_params)) {
249
-            return true;
250
-        } else {
251
-            return false;
252
-        }
253
-    }
254
-
255
-
256
-    /**
257
-     * meta_table
258
-     * returns first EE_Secondary_Table table name
259
-     *
260
-     * @access public
261
-     * @return string
262
-     */
263
-    public function meta_table()
264
-    {
265
-        $meta_table = $this->_get_other_tables();
266
-        $meta_table = reset($meta_table);
267
-        return $meta_table instanceof EE_Secondary_Table ? $meta_table->get_table_name() : null;
268
-    }
269
-
270
-
271
-    /**
272
-     * This simply returns an array of the meta table fields (useful for when we just need to update those fields)
273
-     *
274
-     * @param  bool $all triggers whether we include DB_Only fields or JUST non DB_Only fields.  Defaults to false (no
275
-     *                   db only fields)
276
-     * @return array
277
-     */
278
-    public function get_meta_table_fields($all = false)
279
-    {
280
-        $all_fields = $fields_to_return = array();
281
-        foreach ($this->_tables as $alias => $table_obj) {
282
-            if ($table_obj instanceof EE_Secondary_Table) {
283
-                $all_fields = array_merge($this->_get_fields_for_table($alias), $all_fields);
284
-            }
285
-        }
286
-        if (! $all) {
287
-            foreach ($all_fields as $name => $obj) {
288
-                if ($obj instanceof EE_DB_Only_Field_Base) {
289
-                    continue;
290
-                }
291
-                $fields_to_return[] = $name;
292
-            }
293
-        } else {
294
-            $fields_to_return = array_keys($all_fields);
295
-        }
296
-        return $fields_to_return;
297
-    }
298
-
299
-
300
-    /**
301
-     * Adds an event category with the specified name and description to the specified
302
-     * $cpt_model_object. Intelligently adds a term if necessary, and adds a term_taxonomy if necessary,
303
-     * and adds an entry in the term_relationship if necessary.
304
-     *
305
-     * @param EE_CPT_Base $cpt_model_object
306
-     * @param string      $category_name (used to derive the term slug too)
307
-     * @param string      $category_description
308
-     * @param int         $parent_term_taxonomy_id
309
-     * @return EE_Term_Taxonomy
310
-     */
311
-    public function add_event_category(
312
-        EE_CPT_Base $cpt_model_object,
313
-        $category_name,
314
-        $category_description = '',
315
-        $parent_term_taxonomy_id = null
316
-    ) {
317
-        // create term
318
-        require_once(EE_MODELS . 'EEM_Term.model.php');
319
-        // first, check for a term by the same name or slug
320
-        $category_slug = sanitize_title($category_name);
321
-        $term = EEM_Term::instance()->get_one(
322
-            array(
323
-                array(
324
-                    'OR' => array(
325
-                        'name' => $category_name,
326
-                        'slug' => $category_slug,
327
-                    ),
328
-                ),
329
-            )
330
-        );
331
-        if (! $term) {
332
-            $term = EE_Term::new_instance(
333
-                array(
334
-                    'name' => $category_name,
335
-                    'slug' => $category_slug,
336
-                )
337
-            );
338
-            $term->save();
339
-        }
340
-        // make sure there's a term-taxonomy entry too
341
-        require_once(EE_MODELS . 'EEM_Term_Taxonomy.model.php');
342
-        $term_taxonomy = EEM_Term_Taxonomy::instance()->get_one(
343
-            array(
344
-                array(
345
-                    'term_id'  => $term->ID(),
346
-                    'taxonomy' => self::EVENT_CATEGORY_TAXONOMY,
347
-                ),
348
-            )
349
-        );
350
-        /** @var $term_taxonomy EE_Term_Taxonomy */
351
-        if (! $term_taxonomy) {
352
-            $term_taxonomy = EE_Term_Taxonomy::new_instance(
353
-                array(
354
-                    'term_id'     => $term->ID(),
355
-                    'taxonomy'    => self::EVENT_CATEGORY_TAXONOMY,
356
-                    'description' => $category_description,
357
-                    'term_count'       => 1,
358
-                    'parent'      => $parent_term_taxonomy_id,
359
-                )
360
-            );
361
-            $term_taxonomy->save();
362
-        } else {
363
-            $term_taxonomy->set_count($term_taxonomy->count() + 1);
364
-            $term_taxonomy->save();
365
-        }
366
-        return $this->add_relationship_to($cpt_model_object, $term_taxonomy, 'Term_Taxonomy');
367
-    }
368
-
369
-
370
-    /**
371
-     * Removed the category specified by name as having a relation to this event.
372
-     * Does not remove the term or term_taxonomy.
373
-     *
374
-     * @param EE_CPT_Base $cpt_model_object_event
375
-     * @param string      $category_name name of the event category (term)
376
-     * @return bool
377
-     */
378
-    public function remove_event_category(EE_CPT_Base $cpt_model_object_event, $category_name)
379
-    {
380
-        // find the term_taxonomy by that name
381
-        $term_taxonomy = $this->get_first_related(
382
-            $cpt_model_object_event,
383
-            'Term_Taxonomy',
384
-            array(array('Term.name' => $category_name, 'taxonomy' => self::EVENT_CATEGORY_TAXONOMY))
385
-        );
386
-        /** @var $term_taxonomy EE_Term_Taxonomy */
387
-        if ($term_taxonomy) {
388
-            $term_taxonomy->set_count($term_taxonomy->count() - 1);
389
-            $term_taxonomy->save();
390
-        }
391
-        return $this->remove_relationship_to($cpt_model_object_event, $term_taxonomy, 'Term_Taxonomy');
392
-    }
393
-
394
-
395
-    /**
396
-     * This is a wrapper for the WordPress get_the_post_thumbnail() function that returns the feature image for the
397
-     * given CPT ID.  It accepts the same params as what get_the_post_thumbnail() accepts.
398
-     *
399
-     * @link   http://codex.wordpress.org/Function_Reference/get_the_post_thumbnail
400
-     * @access public
401
-     * @param int          $id   the ID for the cpt we want the feature image for
402
-     * @param string|array $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
403
-     *                           representing width and height in pixels (i.e. array(32,32) ).
404
-     * @param string|array $attr Optional. Query string or array of attributes.
405
-     * @return string HTML image element
406
-     */
407
-    public function get_feature_image($id, $size = 'thumbnail', $attr = '')
408
-    {
409
-        return get_the_post_thumbnail($id, $size, $attr);
410
-    }
411
-
412
-
413
-    /**
414
-     * Just a handy way to get the list of post statuses currently registered with WP.
415
-     *
416
-     * @global array $wp_post_statuses set in wp core for storing all the post stati
417
-     * @return array
418
-     */
419
-    public function get_post_statuses()
420
-    {
421
-        global $wp_post_statuses;
422
-        $statuses = array();
423
-        foreach ($wp_post_statuses as $post_status => $args_object) {
424
-            $statuses[ $post_status ] = $args_object->label;
425
-        }
426
-        return $statuses;
427
-    }
428
-
429
-
430
-    /**
431
-     * public method that can be used to retrieve the protected status array on the instantiated cpt model
432
-     *
433
-     * @return array array of statuses.
434
-     */
435
-    public function get_status_array()
436
-    {
437
-        $statuses = $this->get_post_statuses();
438
-        // first the global filter
439
-        $statuses = apply_filters('FHEE_EEM_CPT_Base__get_status_array', $statuses);
440
-        // now the class specific filter
441
-        $statuses = apply_filters('FHEE_EEM_' . get_class($this) . '__get_status_array', $statuses);
442
-        return $statuses;
443
-    }
444
-
445
-
446
-    /**
447
-     * this returns the post statuses that are NOT the default wordpress status
448
-     *
449
-     * @return array
450
-     */
451
-    public function get_custom_post_statuses()
452
-    {
453
-        $new_stati = array();
454
-        foreach ($this->_custom_stati as $status => $props) {
455
-            $new_stati[ $status ] = $props['label'];
456
-        }
457
-        return $new_stati;
458
-    }
459
-
460
-
461
-    /**
462
-     * Creates a child of EE_CPT_Base given a WP_Post or array of wpdb results which
463
-     * are a row from the posts table. If we're missing any fields required for the model,
464
-     * we just fetch the entire entry from the DB (ie, if you want to use this to save DB queries,
465
-     * make sure you are attaching all the model's fields onto the post)
466
-     *
467
-     * @param WP_Post|array $post
468
-     * @return EE_Base_Class|EE_Soft_Delete_Base_Class
469
-     */
470
-    public function instantiate_class_from_post_object_orig($post)
471
-    {
472
-        $post = (array) $post;
473
-        $has_all_necessary_fields_for_table = true;
474
-        // check if the post has fields on the meta table already
475
-        foreach ($this->_get_other_tables() as $table_obj) {
476
-            $fields_for_that_table = $this->_get_fields_for_table($table_obj->get_table_alias());
477
-            foreach ($fields_for_that_table as $field_obj) {
478
-                if (! isset($post[ $field_obj->get_table_column() ])
479
-                    && ! isset($post[ $field_obj->get_qualified_column() ])
480
-                ) {
481
-                    $has_all_necessary_fields_for_table = false;
482
-                }
483
-            }
484
-        }
485
-        // if we don't have all the fields we need, then just fetch the proper model from the DB
486
-        if (! $has_all_necessary_fields_for_table) {
487
-            return $this->get_one_by_ID($post['ID']);
488
-        } else {
489
-            return $this->instantiate_class_from_array_or_object($post);
490
-        }
491
-    }
492
-
493
-
494
-    /**
495
-     * @param null $post
496
-     * @return EE_Base_Class|EE_Soft_Delete_Base_Class
497
-     */
498
-    public function instantiate_class_from_post_object($post = null)
499
-    {
500
-        if (empty($post)) {
501
-            global $post;
502
-        }
503
-        $post = (array) $post;
504
-        $tables_needing_to_be_queried = array();
505
-        // check if the post has fields on the meta table already
506
-        foreach ($this->get_tables() as $table_obj) {
507
-            $fields_for_that_table = $this->_get_fields_for_table($table_obj->get_table_alias());
508
-            foreach ($fields_for_that_table as $field_obj) {
509
-                if (! isset($post[ $field_obj->get_table_column() ])
510
-                    && ! isset($post[ $field_obj->get_qualified_column() ])
511
-                ) {
512
-                    $tables_needing_to_be_queried[ $table_obj->get_table_alias() ] = $table_obj;
513
-                }
514
-            }
515
-        }
516
-        // if we don't have all the fields we need, then just fetch the proper model from the DB
517
-        if ($tables_needing_to_be_queried) {
518
-            if (count($tables_needing_to_be_queried) == 1
519
-                && reset($tables_needing_to_be_queried)
520
-                   instanceof
521
-                   EE_Secondary_Table
522
-            ) {
523
-                // so we're only missing data from a secondary table. Well that's not too hard to query for
524
-                $table_to_query = reset($tables_needing_to_be_queried);
525
-                $missing_data = $this->_do_wpdb_query(
526
-                    'get_row',
527
-                    array(
528
-                        'SELECT * FROM '
529
-                        . $table_to_query->get_table_name()
530
-                        . ' WHERE '
531
-                        . $table_to_query->get_fk_on_table()
532
-                        . ' = '
533
-                        . $post['ID'],
534
-                        ARRAY_A,
535
-                    )
536
-                );
537
-                if (! empty($missing_data)) {
538
-                    $post = array_merge($post, $missing_data);
539
-                }
540
-            } else {
541
-                return $this->get_one_by_ID($post['ID']);
542
-            }
543
-        }
544
-        return $this->instantiate_class_from_array_or_object($post);
545
-    }
546
-
547
-
548
-    /**
549
-     * Gets the post type associated with this
550
-     *
551
-     * @throws EE_Error
552
-     * @return string
553
-     */
554
-    public function post_type()
555
-    {
556
-        $post_type_field = null;
557
-        foreach ($this->field_settings(true) as $field_obj) {
558
-            if ($field_obj instanceof EE_WP_Post_Type_Field) {
559
-                $post_type_field = $field_obj;
560
-                break;
561
-            }
562
-        }
563
-        if ($post_type_field == null) {
564
-            throw new EE_Error(
565
-                sprintf(
566
-                    __(
567
-                        "CPT Model %s should have a field of type EE_WP_Post_Type, but doesnt",
568
-                        "event_espresso"
569
-                    ),
570
-                    get_class($this)
571
-                )
572
-            );
573
-        }
574
-        return $post_type_field->get_default_value();
575
-    }
19
+	const EVENT_CATEGORY_TAXONOMY = 'espresso_event_category';
20
+
21
+	/**
22
+	 * @var string post_status_publish - the wp post status for published cpts
23
+	 */
24
+	const post_status_publish = 'publish';
25
+
26
+	/**
27
+	 * @var string post_status_future - the wp post status for scheduled cpts
28
+	 */
29
+	const post_status_future = 'future';
30
+
31
+	/**
32
+	 * @var string post_status_draft - the wp post status for draft cpts
33
+	 */
34
+	const post_status_draft = 'draft';
35
+
36
+	/**
37
+	 * @var string post_status_pending - the wp post status for pending cpts
38
+	 */
39
+	const post_status_pending = 'pending';
40
+
41
+	/**
42
+	 * @var string post_status_private - the wp post status for private cpts
43
+	 */
44
+	const post_status_private = 'private';
45
+
46
+	/**
47
+	 * @var string post_status_trashed - the wp post status for trashed cpts
48
+	 */
49
+	const post_status_trashed = 'trash';
50
+
51
+	/**
52
+	 * This is an array of custom statuses for the given CPT model (modified by children)
53
+	 * format:
54
+	 * array(
55
+	 *        'status_name' => array(
56
+	 *            'label' => __('Status Name', 'event_espresso'),
57
+	 *            'public' => TRUE //whether a public status or not.
58
+	 *        )
59
+	 * )
60
+	 *
61
+	 * @var array
62
+	 */
63
+	protected $_custom_stati = array();
64
+
65
+
66
+	/**
67
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
68
+	 *
69
+	 * @param string $timezone
70
+	 * @throws \EE_Error
71
+	 */
72
+	protected function __construct($timezone = null)
73
+	{
74
+		// adds a relationship to Term_Taxonomy for all these models. For this to work
75
+		// Term_Relationship must have a relation to each model subclassing EE_CPT_Base explicitly
76
+		// eg, in EEM_Term_Relationship, inside the _model_relations array, there must be an entry
77
+		// with key equalling the subclassing model's model name (eg 'Event' or 'Venue'), and the value
78
+		// must also be new EE_HABTM_Relation('Term_Relationship');
79
+		$this->_model_relations['Term_Taxonomy'] = new EE_HABTM_Relation('Term_Relationship');
80
+		$primary_table_name = null;
81
+		// add  the common _status field to all CPT primary tables.
82
+		foreach ($this->_tables as $alias => $table_obj) {
83
+			if ($table_obj instanceof EE_Primary_Table) {
84
+				$primary_table_name = $alias;
85
+			}
86
+		}
87
+		// set default wp post statuses if child has not already set.
88
+		if (! isset($this->_fields[ $primary_table_name ]['status'])) {
89
+			$this->_fields[ $primary_table_name ]['status'] = new EE_WP_Post_Status_Field(
90
+				'post_status',
91
+				__("Event Status", "event_espresso"),
92
+				false,
93
+				'draft'
94
+			);
95
+		}
96
+		if (! isset($this->_fields[ $primary_table_name ]['to_ping'])) {
97
+			$this->_fields[ $primary_table_name ]['to_ping'] = new EE_DB_Only_Text_Field(
98
+				'to_ping',
99
+				__('To Ping', 'event_espresso'),
100
+				false,
101
+				''
102
+			);
103
+		}
104
+		if (! isset($this->_fields[ $primary_table_name ]['pinged'])) {
105
+			$this->_fields[ $primary_table_name ]['pinged'] = new EE_DB_Only_Text_Field(
106
+				'pinged',
107
+				__('Pinged', 'event_espresso'),
108
+				false,
109
+				''
110
+			);
111
+		}
112
+		if (! isset($this->_fields[ $primary_table_name ]['comment_status'])) {
113
+			$this->_fields[ $primary_table_name ]['comment_status'] = new EE_Plain_Text_Field(
114
+				'comment_status',
115
+				__('Comment Status', 'event_espresso'),
116
+				false,
117
+				'open'
118
+			);
119
+		}
120
+		if (! isset($this->_fields[ $primary_table_name ]['ping_status'])) {
121
+			$this->_fields[ $primary_table_name ]['ping_status'] = new EE_Plain_Text_Field(
122
+				'ping_status',
123
+				__('Ping Status', 'event_espresso'),
124
+				false,
125
+				'open'
126
+			);
127
+		}
128
+		if (! isset($this->_fields[ $primary_table_name ]['post_content_filtered'])) {
129
+			$this->_fields[ $primary_table_name ]['post_content_filtered'] = new EE_DB_Only_Text_Field(
130
+				'post_content_filtered',
131
+				__('Post Content Filtered', 'event_espresso'),
132
+				false,
133
+				''
134
+			);
135
+		}
136
+		if (! isset($this->_model_relations['Post_Meta'])) {
137
+			// don't block deletes though because we want to maintain the current behaviour
138
+			$this->_model_relations['Post_Meta'] = new EE_Has_Many_Relation(false);
139
+		}
140
+		if (! $this->_minimum_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
141
+			// nothing was set during child constructor, so set default
142
+			$this->_minimum_where_conditions_strategy = new EE_CPT_Minimum_Where_Conditions($this->post_type());
143
+		}
144
+		if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
145
+			// nothing was set during child constructor, so set default
146
+			// it's ok for child classes to specify this, but generally this is more DRY
147
+			$this->_default_where_conditions_strategy = new EE_CPT_Where_Conditions($this->post_type());
148
+		}
149
+		parent::__construct($timezone);
150
+	}
151
+
152
+
153
+	/**
154
+	 * @return array
155
+	 */
156
+	public function public_event_stati()
157
+	{
158
+		// @see wp-includes/post.php
159
+		return get_post_stati(array('public' => true));
160
+	}
161
+
162
+
163
+	/**
164
+	 * Searches for field on this model of type 'deleted_flag'. if it is found,
165
+	 * returns it's name. BUT That doesn't apply to CPTs. We should instead use post_status_field_name
166
+	 *
167
+	 * @return string
168
+	 * @throws EE_Error
169
+	 */
170
+	public function deleted_field_name()
171
+	{
172
+		throw new EE_Error(
173
+			sprintf(
174
+				__(
175
+					"EEM_CPT_Base should nto call deleted_field_name! It should instead use post_status_field_name",
176
+					"event_espresso"
177
+				)
178
+			)
179
+		);
180
+	}
181
+
182
+
183
+	/**
184
+	 * Gets the field's name that sets the post status
185
+	 *
186
+	 * @return string
187
+	 * @throws EE_Error
188
+	 */
189
+	public function post_status_field_name()
190
+	{
191
+		$field = $this->get_a_field_of_type('EE_WP_Post_Status_Field');
192
+		if ($field) {
193
+			return $field->get_name();
194
+		} else {
195
+			throw new EE_Error(
196
+				sprintf(
197
+					__(
198
+						'We are trying to find the post status flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
199
+						'event_espresso'
200
+					),
201
+					get_class($this),
202
+					get_class($this)
203
+				)
204
+			);
205
+		}
206
+	}
207
+
208
+
209
+	/**
210
+	 * Alters the query params so that only trashed/soft-deleted items are considered
211
+	 *
212
+	 * @param array $query_params like EEM_Base::get_all's $query_params
213
+	 * @return array like EEM_Base::get_all's $query_params
214
+	 */
215
+	protected function _alter_query_params_so_only_trashed_items_included($query_params)
216
+	{
217
+		$post_status_field_name = $this->post_status_field_name();
218
+		$query_params[0][ $post_status_field_name ] = self::post_status_trashed;
219
+		return $query_params;
220
+	}
221
+
222
+
223
+	/**
224
+	 * Alters the query params so each item's deleted status is ignored.
225
+	 *
226
+	 * @param array $query_params
227
+	 * @return array
228
+	 */
229
+	protected function _alter_query_params_so_deleted_and_undeleted_items_included($query_params)
230
+	{
231
+		$query_params['default_where_conditions'] = 'minimum';
232
+		return $query_params;
233
+	}
234
+
235
+
236
+	/**
237
+	 * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
238
+	 *
239
+	 * @param boolean $delete       true to indicate deletion, false to indicate restoration
240
+	 * @param array   $query_params like EEM_Base::get_all
241
+	 * @return boolean success
242
+	 */
243
+	public function delete_or_restore($delete = true, $query_params = array())
244
+	{
245
+		$post_status_field_name = $this->post_status_field_name();
246
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
247
+		$new_status = $delete ? self::post_status_trashed : 'draft';
248
+		if ($this->update(array($post_status_field_name => $new_status), $query_params)) {
249
+			return true;
250
+		} else {
251
+			return false;
252
+		}
253
+	}
254
+
255
+
256
+	/**
257
+	 * meta_table
258
+	 * returns first EE_Secondary_Table table name
259
+	 *
260
+	 * @access public
261
+	 * @return string
262
+	 */
263
+	public function meta_table()
264
+	{
265
+		$meta_table = $this->_get_other_tables();
266
+		$meta_table = reset($meta_table);
267
+		return $meta_table instanceof EE_Secondary_Table ? $meta_table->get_table_name() : null;
268
+	}
269
+
270
+
271
+	/**
272
+	 * This simply returns an array of the meta table fields (useful for when we just need to update those fields)
273
+	 *
274
+	 * @param  bool $all triggers whether we include DB_Only fields or JUST non DB_Only fields.  Defaults to false (no
275
+	 *                   db only fields)
276
+	 * @return array
277
+	 */
278
+	public function get_meta_table_fields($all = false)
279
+	{
280
+		$all_fields = $fields_to_return = array();
281
+		foreach ($this->_tables as $alias => $table_obj) {
282
+			if ($table_obj instanceof EE_Secondary_Table) {
283
+				$all_fields = array_merge($this->_get_fields_for_table($alias), $all_fields);
284
+			}
285
+		}
286
+		if (! $all) {
287
+			foreach ($all_fields as $name => $obj) {
288
+				if ($obj instanceof EE_DB_Only_Field_Base) {
289
+					continue;
290
+				}
291
+				$fields_to_return[] = $name;
292
+			}
293
+		} else {
294
+			$fields_to_return = array_keys($all_fields);
295
+		}
296
+		return $fields_to_return;
297
+	}
298
+
299
+
300
+	/**
301
+	 * Adds an event category with the specified name and description to the specified
302
+	 * $cpt_model_object. Intelligently adds a term if necessary, and adds a term_taxonomy if necessary,
303
+	 * and adds an entry in the term_relationship if necessary.
304
+	 *
305
+	 * @param EE_CPT_Base $cpt_model_object
306
+	 * @param string      $category_name (used to derive the term slug too)
307
+	 * @param string      $category_description
308
+	 * @param int         $parent_term_taxonomy_id
309
+	 * @return EE_Term_Taxonomy
310
+	 */
311
+	public function add_event_category(
312
+		EE_CPT_Base $cpt_model_object,
313
+		$category_name,
314
+		$category_description = '',
315
+		$parent_term_taxonomy_id = null
316
+	) {
317
+		// create term
318
+		require_once(EE_MODELS . 'EEM_Term.model.php');
319
+		// first, check for a term by the same name or slug
320
+		$category_slug = sanitize_title($category_name);
321
+		$term = EEM_Term::instance()->get_one(
322
+			array(
323
+				array(
324
+					'OR' => array(
325
+						'name' => $category_name,
326
+						'slug' => $category_slug,
327
+					),
328
+				),
329
+			)
330
+		);
331
+		if (! $term) {
332
+			$term = EE_Term::new_instance(
333
+				array(
334
+					'name' => $category_name,
335
+					'slug' => $category_slug,
336
+				)
337
+			);
338
+			$term->save();
339
+		}
340
+		// make sure there's a term-taxonomy entry too
341
+		require_once(EE_MODELS . 'EEM_Term_Taxonomy.model.php');
342
+		$term_taxonomy = EEM_Term_Taxonomy::instance()->get_one(
343
+			array(
344
+				array(
345
+					'term_id'  => $term->ID(),
346
+					'taxonomy' => self::EVENT_CATEGORY_TAXONOMY,
347
+				),
348
+			)
349
+		);
350
+		/** @var $term_taxonomy EE_Term_Taxonomy */
351
+		if (! $term_taxonomy) {
352
+			$term_taxonomy = EE_Term_Taxonomy::new_instance(
353
+				array(
354
+					'term_id'     => $term->ID(),
355
+					'taxonomy'    => self::EVENT_CATEGORY_TAXONOMY,
356
+					'description' => $category_description,
357
+					'term_count'       => 1,
358
+					'parent'      => $parent_term_taxonomy_id,
359
+				)
360
+			);
361
+			$term_taxonomy->save();
362
+		} else {
363
+			$term_taxonomy->set_count($term_taxonomy->count() + 1);
364
+			$term_taxonomy->save();
365
+		}
366
+		return $this->add_relationship_to($cpt_model_object, $term_taxonomy, 'Term_Taxonomy');
367
+	}
368
+
369
+
370
+	/**
371
+	 * Removed the category specified by name as having a relation to this event.
372
+	 * Does not remove the term or term_taxonomy.
373
+	 *
374
+	 * @param EE_CPT_Base $cpt_model_object_event
375
+	 * @param string      $category_name name of the event category (term)
376
+	 * @return bool
377
+	 */
378
+	public function remove_event_category(EE_CPT_Base $cpt_model_object_event, $category_name)
379
+	{
380
+		// find the term_taxonomy by that name
381
+		$term_taxonomy = $this->get_first_related(
382
+			$cpt_model_object_event,
383
+			'Term_Taxonomy',
384
+			array(array('Term.name' => $category_name, 'taxonomy' => self::EVENT_CATEGORY_TAXONOMY))
385
+		);
386
+		/** @var $term_taxonomy EE_Term_Taxonomy */
387
+		if ($term_taxonomy) {
388
+			$term_taxonomy->set_count($term_taxonomy->count() - 1);
389
+			$term_taxonomy->save();
390
+		}
391
+		return $this->remove_relationship_to($cpt_model_object_event, $term_taxonomy, 'Term_Taxonomy');
392
+	}
393
+
394
+
395
+	/**
396
+	 * This is a wrapper for the WordPress get_the_post_thumbnail() function that returns the feature image for the
397
+	 * given CPT ID.  It accepts the same params as what get_the_post_thumbnail() accepts.
398
+	 *
399
+	 * @link   http://codex.wordpress.org/Function_Reference/get_the_post_thumbnail
400
+	 * @access public
401
+	 * @param int          $id   the ID for the cpt we want the feature image for
402
+	 * @param string|array $size (optional) Image size. Defaults to 'post-thumbnail' but can also be a 2-item array
403
+	 *                           representing width and height in pixels (i.e. array(32,32) ).
404
+	 * @param string|array $attr Optional. Query string or array of attributes.
405
+	 * @return string HTML image element
406
+	 */
407
+	public function get_feature_image($id, $size = 'thumbnail', $attr = '')
408
+	{
409
+		return get_the_post_thumbnail($id, $size, $attr);
410
+	}
411
+
412
+
413
+	/**
414
+	 * Just a handy way to get the list of post statuses currently registered with WP.
415
+	 *
416
+	 * @global array $wp_post_statuses set in wp core for storing all the post stati
417
+	 * @return array
418
+	 */
419
+	public function get_post_statuses()
420
+	{
421
+		global $wp_post_statuses;
422
+		$statuses = array();
423
+		foreach ($wp_post_statuses as $post_status => $args_object) {
424
+			$statuses[ $post_status ] = $args_object->label;
425
+		}
426
+		return $statuses;
427
+	}
428
+
429
+
430
+	/**
431
+	 * public method that can be used to retrieve the protected status array on the instantiated cpt model
432
+	 *
433
+	 * @return array array of statuses.
434
+	 */
435
+	public function get_status_array()
436
+	{
437
+		$statuses = $this->get_post_statuses();
438
+		// first the global filter
439
+		$statuses = apply_filters('FHEE_EEM_CPT_Base__get_status_array', $statuses);
440
+		// now the class specific filter
441
+		$statuses = apply_filters('FHEE_EEM_' . get_class($this) . '__get_status_array', $statuses);
442
+		return $statuses;
443
+	}
444
+
445
+
446
+	/**
447
+	 * this returns the post statuses that are NOT the default wordpress status
448
+	 *
449
+	 * @return array
450
+	 */
451
+	public function get_custom_post_statuses()
452
+	{
453
+		$new_stati = array();
454
+		foreach ($this->_custom_stati as $status => $props) {
455
+			$new_stati[ $status ] = $props['label'];
456
+		}
457
+		return $new_stati;
458
+	}
459
+
460
+
461
+	/**
462
+	 * Creates a child of EE_CPT_Base given a WP_Post or array of wpdb results which
463
+	 * are a row from the posts table. If we're missing any fields required for the model,
464
+	 * we just fetch the entire entry from the DB (ie, if you want to use this to save DB queries,
465
+	 * make sure you are attaching all the model's fields onto the post)
466
+	 *
467
+	 * @param WP_Post|array $post
468
+	 * @return EE_Base_Class|EE_Soft_Delete_Base_Class
469
+	 */
470
+	public function instantiate_class_from_post_object_orig($post)
471
+	{
472
+		$post = (array) $post;
473
+		$has_all_necessary_fields_for_table = true;
474
+		// check if the post has fields on the meta table already
475
+		foreach ($this->_get_other_tables() as $table_obj) {
476
+			$fields_for_that_table = $this->_get_fields_for_table($table_obj->get_table_alias());
477
+			foreach ($fields_for_that_table as $field_obj) {
478
+				if (! isset($post[ $field_obj->get_table_column() ])
479
+					&& ! isset($post[ $field_obj->get_qualified_column() ])
480
+				) {
481
+					$has_all_necessary_fields_for_table = false;
482
+				}
483
+			}
484
+		}
485
+		// if we don't have all the fields we need, then just fetch the proper model from the DB
486
+		if (! $has_all_necessary_fields_for_table) {
487
+			return $this->get_one_by_ID($post['ID']);
488
+		} else {
489
+			return $this->instantiate_class_from_array_or_object($post);
490
+		}
491
+	}
492
+
493
+
494
+	/**
495
+	 * @param null $post
496
+	 * @return EE_Base_Class|EE_Soft_Delete_Base_Class
497
+	 */
498
+	public function instantiate_class_from_post_object($post = null)
499
+	{
500
+		if (empty($post)) {
501
+			global $post;
502
+		}
503
+		$post = (array) $post;
504
+		$tables_needing_to_be_queried = array();
505
+		// check if the post has fields on the meta table already
506
+		foreach ($this->get_tables() as $table_obj) {
507
+			$fields_for_that_table = $this->_get_fields_for_table($table_obj->get_table_alias());
508
+			foreach ($fields_for_that_table as $field_obj) {
509
+				if (! isset($post[ $field_obj->get_table_column() ])
510
+					&& ! isset($post[ $field_obj->get_qualified_column() ])
511
+				) {
512
+					$tables_needing_to_be_queried[ $table_obj->get_table_alias() ] = $table_obj;
513
+				}
514
+			}
515
+		}
516
+		// if we don't have all the fields we need, then just fetch the proper model from the DB
517
+		if ($tables_needing_to_be_queried) {
518
+			if (count($tables_needing_to_be_queried) == 1
519
+				&& reset($tables_needing_to_be_queried)
520
+				   instanceof
521
+				   EE_Secondary_Table
522
+			) {
523
+				// so we're only missing data from a secondary table. Well that's not too hard to query for
524
+				$table_to_query = reset($tables_needing_to_be_queried);
525
+				$missing_data = $this->_do_wpdb_query(
526
+					'get_row',
527
+					array(
528
+						'SELECT * FROM '
529
+						. $table_to_query->get_table_name()
530
+						. ' WHERE '
531
+						. $table_to_query->get_fk_on_table()
532
+						. ' = '
533
+						. $post['ID'],
534
+						ARRAY_A,
535
+					)
536
+				);
537
+				if (! empty($missing_data)) {
538
+					$post = array_merge($post, $missing_data);
539
+				}
540
+			} else {
541
+				return $this->get_one_by_ID($post['ID']);
542
+			}
543
+		}
544
+		return $this->instantiate_class_from_array_or_object($post);
545
+	}
546
+
547
+
548
+	/**
549
+	 * Gets the post type associated with this
550
+	 *
551
+	 * @throws EE_Error
552
+	 * @return string
553
+	 */
554
+	public function post_type()
555
+	{
556
+		$post_type_field = null;
557
+		foreach ($this->field_settings(true) as $field_obj) {
558
+			if ($field_obj instanceof EE_WP_Post_Type_Field) {
559
+				$post_type_field = $field_obj;
560
+				break;
561
+			}
562
+		}
563
+		if ($post_type_field == null) {
564
+			throw new EE_Error(
565
+				sprintf(
566
+					__(
567
+						"CPT Model %s should have a field of type EE_WP_Post_Type, but doesnt",
568
+						"event_espresso"
569
+					),
570
+					get_class($this)
571
+				)
572
+			);
573
+		}
574
+		return $post_type_field->get_default_value();
575
+	}
576 576
 }
Please login to merge, or discard this patch.
core/domain/entities/editor/Block.php 2 patches
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -20,216 +20,216 @@
 block discarded – undo
20 20
 abstract class Block implements BlockInterface
21 21
 {
22 22
 
23
-    /**
24
-     * BlockAssetManager that this editor block uses for asset registration
25
-     *
26
-     * @var BlockAssetManagerInterface $block_asset_manager
27
-     */
28
-    protected $block_asset_manager;
29
-
30
-    /**
31
-     * @var array $attributes
32
-     */
33
-    private $attributes;
34
-
35
-    /**
36
-     * If set to true, then the block will render its content client side
37
-     * If false, then the block will render its content server side using the renderBlock() method
38
-     *
39
-     * @var bool $dynamic
40
-     */
41
-    private $dynamic = false;
42
-
43
-    /**
44
-     * @var string $block_type
45
-     */
46
-    private $block_type;
47
-
48
-    /**
49
-     * @var array $supported_post_types
50
-     */
51
-    private $supported_post_types;
52
-
53
-    /**
54
-     * @var WP_Block_Type $wp_block_type
55
-     */
56
-    private $wp_block_type;
57
-
58
-
59
-    /**
60
-     * BlockLoader constructor.
61
-     *
62
-     * @param BlockAssetManagerInterface $block_asset_manager
63
-     */
64
-    public function __construct(BlockAssetManagerInterface $block_asset_manager)
65
-    {
66
-        $this->block_asset_manager = $block_asset_manager;
67
-    }
68
-
69
-
70
-    /**
71
-     * @return string
72
-     */
73
-    public function blockType()
74
-    {
75
-        return $this->block_type;
76
-    }
77
-
78
-
79
-    /**
80
-     * @return string
81
-     */
82
-    public function namespacedBlockType()
83
-    {
84
-        return self::NAME_SPACE . '/' . $this->block_type;
85
-    }
86
-
87
-
88
-    /**
89
-     * @param string $block_type
90
-     */
91
-    protected function setBlockType($block_type)
92
-    {
93
-        $this->block_type = $block_type;
94
-    }
95
-
96
-
97
-    /**
98
-     * BlockAssetManager that this editor block uses for asset registration
99
-     *
100
-     * @return BlockAssetManagerInterface
101
-     */
102
-    public function assetManager()
103
-    {
104
-        return $this->block_asset_manager;
105
-    }
106
-
107
-
108
-    /**
109
-     * @param WP_Block_Type $wp_block_type
110
-     */
111
-    protected function setWpBlockType($wp_block_type)
112
-    {
113
-        $this->wp_block_type = $wp_block_type;
114
-    }
115
-
116
-
117
-    /**
118
-     * @param array $supported_post_types
119
-     */
120
-    protected function setSupportedPostTypes(array $supported_post_types)
121
-    {
122
-        $this->supported_post_types = $supported_post_types;
123
-    }
124
-
125
-
126
-    /**
127
-     * @return array
128
-     */
129
-    public function attributes()
130
-    {
131
-        return $this->attributes;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param array $attributes
137
-     */
138
-    public function setAttributes(array $attributes)
139
-    {
140
-        $this->attributes = $attributes;
141
-    }
142
-
143
-
144
-    /**
145
-     * @return bool
146
-     */
147
-    public function isDynamic()
148
-    {
149
-        return $this->dynamic;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param bool $dynamic
155
-     */
156
-    public function setDynamic($dynamic = true)
157
-    {
158
-        $this->dynamic = filter_var($dynamic, FILTER_VALIDATE_BOOLEAN);
159
-    }
160
-
161
-
162
-    /**
163
-     * Registers the Editor Block with WP core;
164
-     * Returns the registered block type on success, or false on failure.
165
-     *
166
-     * @return WP_Block_Type|false
167
-     */
168
-    public function registerBlock()
169
-    {
170
-        $args = array(
171
-            'attributes'    => $this->attributes(),
172
-            'editor_script' => $this->block_asset_manager->getEditorScriptHandle(),
173
-            'editor_style'  => $this->block_asset_manager->getEditorStyleHandle(),
174
-            'script'        => $this->block_asset_manager->getScriptHandle(),
175
-            'style'         => $this->block_asset_manager->getStyleHandle(),
176
-        );
177
-        if (! $this->isDynamic()) {
178
-            $args['render_callback'] = $this->renderBlock();
179
-        }
180
-        $wp_block_type = register_block_type(
181
-            new WP_Block_Type(
182
-                $this->namespacedBlockType(),
183
-                $args
184
-            )
185
-        );
186
-        $this->setWpBlockType($wp_block_type);
187
-        return $wp_block_type;
188
-    }
189
-
190
-
191
-    /**
192
-     * @return WP_Block_Type|false The registered block type on success, or false on failure.
193
-     */
194
-    public function unRegisterBlock()
195
-    {
196
-        return unregister_block_type($this->namespacedBlockType());
197
-    }
198
-
199
-
200
-    /**
201
-     * returns true if the block type applies for the supplied post type
202
-     * and should be added to that post type's editor
203
-     *
204
-     * @param string $post_type
205
-     * @return boolean
206
-     */
207
-    public function appliesToPostType($post_type)
208
-    {
209
-        return in_array($post_type, $this->supported_post_types, true);
210
-    }
211
-
212
-
213
-    /**
214
-     * @return array
215
-     */
216
-    public function getEditorContainer()
217
-    {
218
-        return array(
219
-            $this->namespacedBlockType(),
220
-            array(),
221
-        );
222
-    }
223
-
224
-
225
-    /**
226
-     * returns the rendered HTML for the block
227
-     *
228
-     * @param array $attributes
229
-     * @return string
230
-     */
231
-    public function renderBlock(array $attributes = array())
232
-    {
233
-        return '';
234
-    }
23
+	/**
24
+	 * BlockAssetManager that this editor block uses for asset registration
25
+	 *
26
+	 * @var BlockAssetManagerInterface $block_asset_manager
27
+	 */
28
+	protected $block_asset_manager;
29
+
30
+	/**
31
+	 * @var array $attributes
32
+	 */
33
+	private $attributes;
34
+
35
+	/**
36
+	 * If set to true, then the block will render its content client side
37
+	 * If false, then the block will render its content server side using the renderBlock() method
38
+	 *
39
+	 * @var bool $dynamic
40
+	 */
41
+	private $dynamic = false;
42
+
43
+	/**
44
+	 * @var string $block_type
45
+	 */
46
+	private $block_type;
47
+
48
+	/**
49
+	 * @var array $supported_post_types
50
+	 */
51
+	private $supported_post_types;
52
+
53
+	/**
54
+	 * @var WP_Block_Type $wp_block_type
55
+	 */
56
+	private $wp_block_type;
57
+
58
+
59
+	/**
60
+	 * BlockLoader constructor.
61
+	 *
62
+	 * @param BlockAssetManagerInterface $block_asset_manager
63
+	 */
64
+	public function __construct(BlockAssetManagerInterface $block_asset_manager)
65
+	{
66
+		$this->block_asset_manager = $block_asset_manager;
67
+	}
68
+
69
+
70
+	/**
71
+	 * @return string
72
+	 */
73
+	public function blockType()
74
+	{
75
+		return $this->block_type;
76
+	}
77
+
78
+
79
+	/**
80
+	 * @return string
81
+	 */
82
+	public function namespacedBlockType()
83
+	{
84
+		return self::NAME_SPACE . '/' . $this->block_type;
85
+	}
86
+
87
+
88
+	/**
89
+	 * @param string $block_type
90
+	 */
91
+	protected function setBlockType($block_type)
92
+	{
93
+		$this->block_type = $block_type;
94
+	}
95
+
96
+
97
+	/**
98
+	 * BlockAssetManager that this editor block uses for asset registration
99
+	 *
100
+	 * @return BlockAssetManagerInterface
101
+	 */
102
+	public function assetManager()
103
+	{
104
+		return $this->block_asset_manager;
105
+	}
106
+
107
+
108
+	/**
109
+	 * @param WP_Block_Type $wp_block_type
110
+	 */
111
+	protected function setWpBlockType($wp_block_type)
112
+	{
113
+		$this->wp_block_type = $wp_block_type;
114
+	}
115
+
116
+
117
+	/**
118
+	 * @param array $supported_post_types
119
+	 */
120
+	protected function setSupportedPostTypes(array $supported_post_types)
121
+	{
122
+		$this->supported_post_types = $supported_post_types;
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return array
128
+	 */
129
+	public function attributes()
130
+	{
131
+		return $this->attributes;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param array $attributes
137
+	 */
138
+	public function setAttributes(array $attributes)
139
+	{
140
+		$this->attributes = $attributes;
141
+	}
142
+
143
+
144
+	/**
145
+	 * @return bool
146
+	 */
147
+	public function isDynamic()
148
+	{
149
+		return $this->dynamic;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param bool $dynamic
155
+	 */
156
+	public function setDynamic($dynamic = true)
157
+	{
158
+		$this->dynamic = filter_var($dynamic, FILTER_VALIDATE_BOOLEAN);
159
+	}
160
+
161
+
162
+	/**
163
+	 * Registers the Editor Block with WP core;
164
+	 * Returns the registered block type on success, or false on failure.
165
+	 *
166
+	 * @return WP_Block_Type|false
167
+	 */
168
+	public function registerBlock()
169
+	{
170
+		$args = array(
171
+			'attributes'    => $this->attributes(),
172
+			'editor_script' => $this->block_asset_manager->getEditorScriptHandle(),
173
+			'editor_style'  => $this->block_asset_manager->getEditorStyleHandle(),
174
+			'script'        => $this->block_asset_manager->getScriptHandle(),
175
+			'style'         => $this->block_asset_manager->getStyleHandle(),
176
+		);
177
+		if (! $this->isDynamic()) {
178
+			$args['render_callback'] = $this->renderBlock();
179
+		}
180
+		$wp_block_type = register_block_type(
181
+			new WP_Block_Type(
182
+				$this->namespacedBlockType(),
183
+				$args
184
+			)
185
+		);
186
+		$this->setWpBlockType($wp_block_type);
187
+		return $wp_block_type;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @return WP_Block_Type|false The registered block type on success, or false on failure.
193
+	 */
194
+	public function unRegisterBlock()
195
+	{
196
+		return unregister_block_type($this->namespacedBlockType());
197
+	}
198
+
199
+
200
+	/**
201
+	 * returns true if the block type applies for the supplied post type
202
+	 * and should be added to that post type's editor
203
+	 *
204
+	 * @param string $post_type
205
+	 * @return boolean
206
+	 */
207
+	public function appliesToPostType($post_type)
208
+	{
209
+		return in_array($post_type, $this->supported_post_types, true);
210
+	}
211
+
212
+
213
+	/**
214
+	 * @return array
215
+	 */
216
+	public function getEditorContainer()
217
+	{
218
+		return array(
219
+			$this->namespacedBlockType(),
220
+			array(),
221
+		);
222
+	}
223
+
224
+
225
+	/**
226
+	 * returns the rendered HTML for the block
227
+	 *
228
+	 * @param array $attributes
229
+	 * @return string
230
+	 */
231
+	public function renderBlock(array $attributes = array())
232
+	{
233
+		return '';
234
+	}
235 235
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
      */
82 82
     public function namespacedBlockType()
83 83
     {
84
-        return self::NAME_SPACE . '/' . $this->block_type;
84
+        return self::NAME_SPACE.'/'.$this->block_type;
85 85
     }
86 86
 
87 87
 
@@ -174,7 +174,7 @@  discard block
 block discarded – undo
174 174
             'script'        => $this->block_asset_manager->getScriptHandle(),
175 175
             'style'         => $this->block_asset_manager->getStyleHandle(),
176 176
         );
177
-        if (! $this->isDynamic()) {
177
+        if ( ! $this->isDynamic()) {
178 178
             $args['render_callback'] = $this->renderBlock();
179 179
         }
180 180
         $wp_block_type = register_block_type(
Please login to merge, or discard this patch.
core/domain/entities/editor/BlockInterface.php 1 patch
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -22,70 +22,70 @@
 block discarded – undo
22 22
 interface BlockInterface
23 23
 {
24 24
 
25
-    const NAME_SPACE = 'eventespresso';
26
-
27
-    /**
28
-     * Perform any early setup required by the block
29
-     * including setting the block type and supported post types
30
-     *
31
-     * @return void
32
-     */
33
-    public function initialize();
34
-
35
-
36
-    /**
37
-     * @return string
38
-     */
39
-    public function blockType();
40
-
41
-
42
-    /**
43
-     * AssetRegister that this editor block uses for asset registration
44
-     *
45
-     * @return BlockAssetManagerInterface
46
-     */
47
-    public function assetManager();
48
-
49
-
50
-    /**
51
-     * Registers the Editor Block with WP core;
52
-     * Returns the registered block type on success, or false on failure.
53
-     *
54
-     * @return WP_Block_Type|false
55
-     */
56
-    public function registerBlock();
57
-
58
-
59
-    /**
60
-     * Un-registers the Editor Block with WP core;
61
-     * Returns the registered block type on success, or false on failure.
62
-     *
63
-     * @return WP_Block_Type|false
64
-     */
65
-    public function unRegisterBlock();
66
-
67
-
68
-    /**
69
-     * returns true if the block type applies for the supplied post type
70
-     * and should be added to that post type's editor
71
-     *
72
-     * @param string $post_type
73
-     * @return boolean
74
-     */
75
-    public function appliesToPostType($post_type);
76
-
77
-
78
-    /**
79
-     * @return array
80
-     */
81
-    public function getEditorContainer();
82
-
83
-
84
-    /**
85
-     * returns the rendered HTML for the block
86
-     *
87
-     * @param array $attributes
88
-     * @return string
89
-     */
90
-    public function renderBlock(array $attributes = array());
25
+	const NAME_SPACE = 'eventespresso';
26
+
27
+	/**
28
+	 * Perform any early setup required by the block
29
+	 * including setting the block type and supported post types
30
+	 *
31
+	 * @return void
32
+	 */
33
+	public function initialize();
34
+
35
+
36
+	/**
37
+	 * @return string
38
+	 */
39
+	public function blockType();
40
+
41
+
42
+	/**
43
+	 * AssetRegister that this editor block uses for asset registration
44
+	 *
45
+	 * @return BlockAssetManagerInterface
46
+	 */
47
+	public function assetManager();
48
+
49
+
50
+	/**
51
+	 * Registers the Editor Block with WP core;
52
+	 * Returns the registered block type on success, or false on failure.
53
+	 *
54
+	 * @return WP_Block_Type|false
55
+	 */
56
+	public function registerBlock();
57
+
58
+
59
+	/**
60
+	 * Un-registers the Editor Block with WP core;
61
+	 * Returns the registered block type on success, or false on failure.
62
+	 *
63
+	 * @return WP_Block_Type|false
64
+	 */
65
+	public function unRegisterBlock();
66
+
67
+
68
+	/**
69
+	 * returns true if the block type applies for the supplied post type
70
+	 * and should be added to that post type's editor
71
+	 *
72
+	 * @param string $post_type
73
+	 * @return boolean
74
+	 */
75
+	public function appliesToPostType($post_type);
76
+
77
+
78
+	/**
79
+	 * @return array
80
+	 */
81
+	public function getEditorContainer();
82
+
83
+
84
+	/**
85
+	 * returns the rendered HTML for the block
86
+	 *
87
+	 * @param array $attributes
88
+	 * @return string
89
+	 */
90
+	public function renderBlock(array $attributes = array());
91 91
 }
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_CPT.lib.php 1 patch
Indentation   +230 added lines, -230 removed lines patch added patch discarded remove patch
@@ -13,257 +13,257 @@
 block discarded – undo
13 13
 class EE_Register_CPT implements EEI_Plugin_API
14 14
 {
15 15
 
16
-    /**
17
-     * Holds values for registered variations
18
-     *
19
-     * @since 4.5.0
20
-     *
21
-     * @var array[][][]
22
-     */
23
-    protected static $_registry = array();
16
+	/**
17
+	 * Holds values for registered variations
18
+	 *
19
+	 * @since 4.5.0
20
+	 *
21
+	 * @var array[][][]
22
+	 */
23
+	protected static $_registry = array();
24 24
 
25 25
 
26
-    /**
27
-     * Used to register new CPTs and Taxonomies.
28
-     *
29
-     * @param string $cpt_ref                 reference used for the addon registering cpts and cts
30
-     * @param array  $setup_args              {
31
-     *                                        An array of required values for registering the cpts and taxonomies
32
-     * @type array   $cpts                    {
33
-     *                                        An array of cpts and their arguments.(short example below)
34
-     * @see CustomPostTypeDefinitions::setDefinitions for a more complete example.
35
-     *                                        'people' => array(
36
-     *                                        'singular_name' => __('People', 'event_espresso'),
37
-     *                                        'plural_name' => __('People', 'event_espresso'),
38
-     *                                        'singular_slug' => __('people', 'event_espresso'),
39
-     *                                        'plural_slug' => __('peoples', 'event_espresso'),
40
-     *                                        'class_name' => 'EE_People'
41
-     *                                        )
42
-     *                                        },
43
-     * @type array   $cts                     {
44
-     *                                        An array of custom taxonomies and their arguments (short example below).
45
-     * @see CustomTaxonomyDefinitions::setTaxonomies() for a more complete example.
46
-     *                                        'espresso_people_type' => array(
47
-     *                                        'singular_name' => __('People Type', 'event_espresso'),
48
-     *                                        'plural_name' => __('People Types', 'event_espresso'),
49
-     *                                        'args' => array()
50
-     *                                        )
51
-     *                                        },
52
-     * @type array   $default_terms           {
53
-     *                                        An array of terms to set as the default for a given taxonomy and the
54
-     *                                        custom post types applied to.
55
-     *                                        'taxonomy_name' => array(
56
-     *                                        'term' => array( 'cpt_a_name', 'cpt_b_name' )
57
-     *                                        )
58
-     *                                        }
59
-     *                                        }
60
-     * @throws  EE_Error
61
-     * @return void
62
-     */
63
-    public static function register($cpt_ref = null, $setup_args = array())
64
-    {
26
+	/**
27
+	 * Used to register new CPTs and Taxonomies.
28
+	 *
29
+	 * @param string $cpt_ref                 reference used for the addon registering cpts and cts
30
+	 * @param array  $setup_args              {
31
+	 *                                        An array of required values for registering the cpts and taxonomies
32
+	 * @type array   $cpts                    {
33
+	 *                                        An array of cpts and their arguments.(short example below)
34
+	 * @see CustomPostTypeDefinitions::setDefinitions for a more complete example.
35
+	 *                                        'people' => array(
36
+	 *                                        'singular_name' => __('People', 'event_espresso'),
37
+	 *                                        'plural_name' => __('People', 'event_espresso'),
38
+	 *                                        'singular_slug' => __('people', 'event_espresso'),
39
+	 *                                        'plural_slug' => __('peoples', 'event_espresso'),
40
+	 *                                        'class_name' => 'EE_People'
41
+	 *                                        )
42
+	 *                                        },
43
+	 * @type array   $cts                     {
44
+	 *                                        An array of custom taxonomies and their arguments (short example below).
45
+	 * @see CustomTaxonomyDefinitions::setTaxonomies() for a more complete example.
46
+	 *                                        'espresso_people_type' => array(
47
+	 *                                        'singular_name' => __('People Type', 'event_espresso'),
48
+	 *                                        'plural_name' => __('People Types', 'event_espresso'),
49
+	 *                                        'args' => array()
50
+	 *                                        )
51
+	 *                                        },
52
+	 * @type array   $default_terms           {
53
+	 *                                        An array of terms to set as the default for a given taxonomy and the
54
+	 *                                        custom post types applied to.
55
+	 *                                        'taxonomy_name' => array(
56
+	 *                                        'term' => array( 'cpt_a_name', 'cpt_b_name' )
57
+	 *                                        )
58
+	 *                                        }
59
+	 *                                        }
60
+	 * @throws  EE_Error
61
+	 * @return void
62
+	 */
63
+	public static function register($cpt_ref = null, $setup_args = array())
64
+	{
65 65
 
66
-        // check for required params
67
-        if (empty($cpt_ref)) {
68
-            throw new EE_Error(
69
-                __(
70
-                    'In order to register custom post types and custom taxonomies, you must include a value to reference what had been registered',
71
-                    'event_espresso'
72
-                )
73
-            );
74
-        }
66
+		// check for required params
67
+		if (empty($cpt_ref)) {
68
+			throw new EE_Error(
69
+				__(
70
+					'In order to register custom post types and custom taxonomies, you must include a value to reference what had been registered',
71
+					'event_espresso'
72
+				)
73
+			);
74
+		}
75 75
 
76
-        if (! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) {
77
-            throw new EE_Error(
78
-                __(
79
-                    'In order to register custom post types or custom taxonomies, you must include an array containing either an array of custom post types to register (key "cpts"), an array of custom taxonomies ("cts") or both.',
80
-                    'event_espresso'
81
-                )
82
-            );
83
-        }
76
+		if (! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) {
77
+			throw new EE_Error(
78
+				__(
79
+					'In order to register custom post types or custom taxonomies, you must include an array containing either an array of custom post types to register (key "cpts"), an array of custom taxonomies ("cts") or both.',
80
+					'event_espresso'
81
+				)
82
+			);
83
+		}
84 84
 
85
-        // make sure we don't register twice
86
-        if (isset(self::$_registry[ $cpt_ref ])) {
87
-            return;
88
-        }
85
+		// make sure we don't register twice
86
+		if (isset(self::$_registry[ $cpt_ref ])) {
87
+			return;
88
+		}
89 89
 
90
-        // make sure cpt ref is unique.
91
-        if (isset(self::$_registry[ $cpt_ref ])) {
92
-            $cpt_ref = uniqid() . '_' . $cpt_ref;
93
-        }
90
+		// make sure cpt ref is unique.
91
+		if (isset(self::$_registry[ $cpt_ref ])) {
92
+			$cpt_ref = uniqid() . '_' . $cpt_ref;
93
+		}
94 94
 
95
-        // make sure this was called in the right place!
96
-        if (did_action('AHEE__EE_System__load_CPTs_and_session__complete')) {
97
-            EE_Error::doing_it_wrong(
98
-                __METHOD__,
99
-                sprintf(
100
-                    __(
101
-                        'EE_Register_CPT has been called and given a reference of "%s".  It may or may not work because it should be called on or before "AHEE__EE_System__load_CPTs_and_session__complete" action hook.',
102
-                        'event_espresso'
103
-                    ),
104
-                    $cpt_ref
105
-                ),
106
-                '4.5.0'
107
-            );
108
-        }
109
-        // validate incoming args
110
-        $validated = array(
111
-            'cpts'          => isset($setup_args['cpts'])
112
-                ? (array) $setup_args['cpts']
113
-                : array(),
114
-            'cts'           => isset($setup_args['cts'])
115
-                ? (array) $setup_args['cts']
116
-                : array(),
117
-            'default_terms' => isset($setup_args['default_terms'])
118
-                ? (array) $setup_args['default_terms']
119
-                : array(),
120
-        );
95
+		// make sure this was called in the right place!
96
+		if (did_action('AHEE__EE_System__load_CPTs_and_session__complete')) {
97
+			EE_Error::doing_it_wrong(
98
+				__METHOD__,
99
+				sprintf(
100
+					__(
101
+						'EE_Register_CPT has been called and given a reference of "%s".  It may or may not work because it should be called on or before "AHEE__EE_System__load_CPTs_and_session__complete" action hook.',
102
+						'event_espresso'
103
+					),
104
+					$cpt_ref
105
+				),
106
+				'4.5.0'
107
+			);
108
+		}
109
+		// validate incoming args
110
+		$validated = array(
111
+			'cpts'          => isset($setup_args['cpts'])
112
+				? (array) $setup_args['cpts']
113
+				: array(),
114
+			'cts'           => isset($setup_args['cts'])
115
+				? (array) $setup_args['cts']
116
+				: array(),
117
+			'default_terms' => isset($setup_args['default_terms'])
118
+				? (array) $setup_args['default_terms']
119
+				: array(),
120
+		);
121 121
 
122
-        self::$_registry[ $cpt_ref ] = $validated;
122
+		self::$_registry[ $cpt_ref ] = $validated;
123 123
 
124
-        // hook into to cpt system
125
-        add_filter(
126
-            'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes',
127
-            array(__CLASS__, 'filterCustomPostTypeDefinitions'),
128
-            5
129
-        );
130
-        add_filter(
131
-            'FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies',
132
-            array(__CLASS__, 'filterCustomTaxonomyDefinitions'),
133
-            5
134
-        );
135
-        add_action(
136
-            'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end',
137
-            array(__CLASS__, 'registerCustomTaxonomyTerm'),
138
-            5
139
-        );
140
-    }
124
+		// hook into to cpt system
125
+		add_filter(
126
+			'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes',
127
+			array(__CLASS__, 'filterCustomPostTypeDefinitions'),
128
+			5
129
+		);
130
+		add_filter(
131
+			'FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies',
132
+			array(__CLASS__, 'filterCustomTaxonomyDefinitions'),
133
+			5
134
+		);
135
+		add_action(
136
+			'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end',
137
+			array(__CLASS__, 'registerCustomTaxonomyTerm'),
138
+			5
139
+		);
140
+	}
141 141
 
142 142
 
143
-    /**
144
-     * Callback for
145
-     * FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes
146
-     * that adds additional custom post types to be registered.
147
-     *
148
-     * @param array $custom_post_type_definitions array of cpts that are already set
149
-     * @return array new array of cpts and their registration information
150
-     */
151
-    public static function filterCustomPostTypeDefinitions($custom_post_type_definitions)
152
-    {
153
-        foreach (self::$_registry as $registries) {
154
-            foreach ($registries['cpts'] as $cpt_name => $cpt_settings) {
155
-                $custom_post_type_definitions[ $cpt_name ] = $cpt_settings;
156
-            }
157
-        }
158
-        return $custom_post_type_definitions;
159
-    }
143
+	/**
144
+	 * Callback for
145
+	 * FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes
146
+	 * that adds additional custom post types to be registered.
147
+	 *
148
+	 * @param array $custom_post_type_definitions array of cpts that are already set
149
+	 * @return array new array of cpts and their registration information
150
+	 */
151
+	public static function filterCustomPostTypeDefinitions($custom_post_type_definitions)
152
+	{
153
+		foreach (self::$_registry as $registries) {
154
+			foreach ($registries['cpts'] as $cpt_name => $cpt_settings) {
155
+				$custom_post_type_definitions[ $cpt_name ] = $cpt_settings;
156
+			}
157
+		}
158
+		return $custom_post_type_definitions;
159
+	}
160 160
 
161 161
 
162
-    /**
163
-     * Callback for
164
-     * FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies
165
-     * that adds additional custom taxonomies to be registered.
166
-     *
167
-     * @param array $custom_taxonomy_definitions array of cts that are already set.
168
-     * @return array new array of cts and their registration information.
169
-     */
170
-    public static function filterCustomTaxonomyDefinitions($custom_taxonomy_definitions)
171
-    {
172
-        foreach (self::$_registry as $registries) {
173
-            foreach ($registries['cts'] as $ct_name => $ct_settings) {
174
-                $custom_taxonomy_definitions[ $ct_name ] = $ct_settings;
175
-            }
176
-        }
177
-        return $custom_taxonomy_definitions;
178
-    }
162
+	/**
163
+	 * Callback for
164
+	 * FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies
165
+	 * that adds additional custom taxonomies to be registered.
166
+	 *
167
+	 * @param array $custom_taxonomy_definitions array of cts that are already set.
168
+	 * @return array new array of cts and their registration information.
169
+	 */
170
+	public static function filterCustomTaxonomyDefinitions($custom_taxonomy_definitions)
171
+	{
172
+		foreach (self::$_registry as $registries) {
173
+			foreach ($registries['cts'] as $ct_name => $ct_settings) {
174
+				$custom_taxonomy_definitions[ $ct_name ] = $ct_settings;
175
+			}
176
+		}
177
+		return $custom_taxonomy_definitions;
178
+	}
179 179
 
180 180
 
181
-    /**
182
-     * Callback for
183
-     * AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end
184
-     * which is used to set the default terms
185
-     *
186
-     * @param RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms
187
-     * @return void
188
-     */
189
-    public static function registerCustomTaxonomyTerm(RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms)
190
-    {
191
-        foreach (self::$_registry as $registries) {
192
-            foreach ($registries['default_terms'] as $taxonomy => $terms) {
193
-                foreach ($terms as $term => $cpts) {
194
-                    $register_custom_taxonomy_terms->registerCustomTaxonomyTerm(
195
-                        $taxonomy,
196
-                        $term,
197
-                        $cpts
198
-                    );
199
-                }
200
-            }
201
-        }
202
-    }
181
+	/**
182
+	 * Callback for
183
+	 * AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end
184
+	 * which is used to set the default terms
185
+	 *
186
+	 * @param RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms
187
+	 * @return void
188
+	 */
189
+	public static function registerCustomTaxonomyTerm(RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms)
190
+	{
191
+		foreach (self::$_registry as $registries) {
192
+			foreach ($registries['default_terms'] as $taxonomy => $terms) {
193
+				foreach ($terms as $term => $cpts) {
194
+					$register_custom_taxonomy_terms->registerCustomTaxonomyTerm(
195
+						$taxonomy,
196
+						$term,
197
+						$cpts
198
+					);
199
+				}
200
+			}
201
+		}
202
+	}
203 203
 
204 204
 
205
-    /**
206
-     * @deprecated 4.9.62.p
207
-     * @param array $cpts array of cpts that are already set
208
-     * @return array new array of cpts and their registration information
209
-     */
210
-    public static function filter_cpts($cpts)
211
-    {
212
-        foreach (self::$_registry as $registries) {
213
-            foreach ($registries['cpts'] as $cpt_name => $cpt_settings) {
214
-                $cpts[ $cpt_name ] = $cpt_settings;
215
-            }
216
-        }
217
-        return $cpts;
218
-    }
205
+	/**
206
+	 * @deprecated 4.9.62.p
207
+	 * @param array $cpts array of cpts that are already set
208
+	 * @return array new array of cpts and their registration information
209
+	 */
210
+	public static function filter_cpts($cpts)
211
+	{
212
+		foreach (self::$_registry as $registries) {
213
+			foreach ($registries['cpts'] as $cpt_name => $cpt_settings) {
214
+				$cpts[ $cpt_name ] = $cpt_settings;
215
+			}
216
+		}
217
+		return $cpts;
218
+	}
219 219
 
220 220
 
221
-    /**
222
-     * @deprecated 4.9.62.p
223
-     * @param array $cts array of cts that are already set.
224
-     * @return array new array of cts and their registration information.
225
-     */
226
-    public static function filter_cts($cts)
227
-    {
228
-        foreach (self::$_registry as $registries) {
229
-            foreach ($registries['cts'] as $ct_name => $ct_settings) {
230
-                $cts[ $ct_name ] = $ct_settings;
231
-            }
232
-        }
233
-        return $cts;
234
-    }
221
+	/**
222
+	 * @deprecated 4.9.62.p
223
+	 * @param array $cts array of cts that are already set.
224
+	 * @return array new array of cts and their registration information.
225
+	 */
226
+	public static function filter_cts($cts)
227
+	{
228
+		foreach (self::$_registry as $registries) {
229
+			foreach ($registries['cts'] as $ct_name => $ct_settings) {
230
+				$cts[ $ct_name ] = $ct_settings;
231
+			}
232
+		}
233
+		return $cts;
234
+	}
235 235
 
236 236
 
237
-    /**
238
-     * @deprecated 4.9.62.p
239
-     * @param EE_Register_CPTs $cpt_class
240
-     * @return void
241
-     */
242
-    public static function default_terms(EE_Register_CPTs $cpt_class)
243
-    {
244
-        foreach (self::$_registry as $registries) {
245
-            foreach ($registries['default_terms'] as $taxonomy => $terms) {
246
-                foreach ($terms as $term => $cpts) {
247
-                    $cpt_class->set_default_term($taxonomy, $term, $cpts);
248
-                }
249
-            }
250
-        }
251
-    }
237
+	/**
238
+	 * @deprecated 4.9.62.p
239
+	 * @param EE_Register_CPTs $cpt_class
240
+	 * @return void
241
+	 */
242
+	public static function default_terms(EE_Register_CPTs $cpt_class)
243
+	{
244
+		foreach (self::$_registry as $registries) {
245
+			foreach ($registries['default_terms'] as $taxonomy => $terms) {
246
+				foreach ($terms as $term => $cpts) {
247
+					$cpt_class->set_default_term($taxonomy, $term, $cpts);
248
+				}
249
+			}
250
+		}
251
+	}
252 252
 
253 253
 
254
-    /**
255
-     * This deregisters whats been registered on this class (for the given slug).
256
-     *
257
-     * @since 4.5.0
258
-     *
259
-     * @param string $cpt_ref The reference for the item registered to be removed.
260
-     *
261
-     * @return void
262
-     */
263
-    public static function deregister($cpt_ref = null)
264
-    {
265
-        if (! empty(self::$_registry[ $cpt_ref ])) {
266
-            unset(self::$_registry[ $cpt_ref ]);
267
-        }
268
-    }
254
+	/**
255
+	 * This deregisters whats been registered on this class (for the given slug).
256
+	 *
257
+	 * @since 4.5.0
258
+	 *
259
+	 * @param string $cpt_ref The reference for the item registered to be removed.
260
+	 *
261
+	 * @return void
262
+	 */
263
+	public static function deregister($cpt_ref = null)
264
+	{
265
+		if (! empty(self::$_registry[ $cpt_ref ])) {
266
+			unset(self::$_registry[ $cpt_ref ]);
267
+		}
268
+	}
269 269
 }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1660 added lines, -1660 removed lines patch added patch discarded remove patch
@@ -23,1664 +23,1664 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var Mirror
38
-     */
39
-    private $mirror;
40
-
41
-    /**
42
-     * @var ClassInterfaceCache $class_cache
43
-     */
44
-    private $class_cache;
45
-
46
-    /**
47
-     * @var array $_class_abbreviations
48
-     */
49
-    protected $_class_abbreviations = array();
50
-
51
-    /**
52
-     * @var CommandBusInterface $BUS
53
-     */
54
-    public $BUS;
55
-
56
-    /**
57
-     * @var EE_Cart $CART
58
-     */
59
-    public $CART;
60
-
61
-    /**
62
-     * @var EE_Config $CFG
63
-     */
64
-    public $CFG;
65
-
66
-    /**
67
-     * @var EE_Network_Config $NET_CFG
68
-     */
69
-    public $NET_CFG;
70
-
71
-    /**
72
-     * StdClass object for storing library classes in
73
-     *
74
-     * @var RegistryContainer $LIB
75
-     */
76
-    public $LIB;
77
-
78
-    /**
79
-     * @var EE_Request_Handler $REQ
80
-     */
81
-    public $REQ;
82
-
83
-    /**
84
-     * @var EE_Session $SSN
85
-     */
86
-    public $SSN;
87
-
88
-    /**
89
-     * @since 4.5.0
90
-     * @var EE_Capabilities $CAP
91
-     */
92
-    public $CAP;
93
-
94
-    /**
95
-     * @since 4.9.0
96
-     * @var EE_Message_Resource_Manager $MRM
97
-     */
98
-    public $MRM;
99
-
100
-    /**
101
-     * @var Registry $AssetsRegistry
102
-     */
103
-    public $AssetsRegistry;
104
-
105
-    /**
106
-     * StdClass object for holding addons which have registered themselves to work with EE core
107
-     *
108
-     * @var EE_Addon[] $addons
109
-     */
110
-    public $addons;
111
-
112
-    /**
113
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
-     *
115
-     * @var EEM_Base[] $models
116
-     */
117
-    public $models = array();
118
-
119
-    /**
120
-     * @var EED_Module[] $modules
121
-     */
122
-    public $modules;
123
-
124
-    /**
125
-     * @var EES_Shortcode[] $shortcodes
126
-     */
127
-    public $shortcodes;
128
-
129
-    /**
130
-     * @var WP_Widget[] $widgets
131
-     */
132
-    public $widgets;
133
-
134
-    /**
135
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
-     * classnames (eg "EEM_Event")
139
-     *
140
-     * @var array $non_abstract_db_models
141
-     */
142
-    public $non_abstract_db_models = array();
143
-
144
-    /**
145
-     * internationalization for JS strings
146
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
-     *    in js file:  var translatedString = eei18n.string_key;
148
-     *
149
-     * @var array $i18n_js_strings
150
-     */
151
-    public static $i18n_js_strings = array();
152
-
153
-    /**
154
-     * $main_file - path to espresso.php
155
-     *
156
-     * @var array $main_file
157
-     */
158
-    public $main_file;
159
-
160
-    /**
161
-     * array of ReflectionClass objects where the key is the class name
162
-     *
163
-     * @deprecated 4.9.62.p
164
-     * @var ReflectionClass[] $_reflectors
165
-     */
166
-    public $_reflectors;
167
-
168
-    /**
169
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
-     *
171
-     * @var boolean $_cache_on
172
-     */
173
-    protected $_cache_on = true;
174
-
175
-    /**
176
-     * @var ObjectIdentifier
177
-     */
178
-    private $object_identifier;
179
-
180
-
181
-    /**
182
-     * @singleton method used to instantiate class object
183
-     * @param EE_Dependency_Map|null   $dependency_map
184
-     * @param Mirror|null              $mirror
185
-     * @param ClassInterfaceCache|null $class_cache
186
-     * @param ObjectIdentifier|null    $object_identifier
187
-     * @return EE_Registry instance
188
-     */
189
-    public static function instance(
190
-        EE_Dependency_Map $dependency_map = null,
191
-        Mirror $mirror = null,
192
-        ClassInterfaceCache $class_cache = null,
193
-        ObjectIdentifier $object_identifier = null
194
-    ) {
195
-        // check if class object is instantiated
196
-        if (! self::$_instance instanceof EE_Registry
197
-            && $dependency_map instanceof EE_Dependency_Map
198
-            && $mirror instanceof Mirror
199
-            && $class_cache instanceof ClassInterfaceCache
200
-            && $object_identifier instanceof ObjectIdentifier
201
-        ) {
202
-            self::$_instance = new self(
203
-                $dependency_map,
204
-                $mirror,
205
-                $class_cache,
206
-                $object_identifier
207
-            );
208
-        }
209
-        return self::$_instance;
210
-    }
211
-
212
-
213
-    /**
214
-     * protected constructor to prevent direct creation
215
-     *
216
-     * @Constructor
217
-     * @param  EE_Dependency_Map  $dependency_map
218
-     * @param Mirror              $mirror
219
-     * @param ClassInterfaceCache $class_cache
220
-     * @param ObjectIdentifier    $object_identifier
221
-     */
222
-    protected function __construct(
223
-        EE_Dependency_Map $dependency_map,
224
-        Mirror $mirror,
225
-        ClassInterfaceCache $class_cache,
226
-        ObjectIdentifier $object_identifier
227
-    ) {
228
-        $this->_dependency_map = $dependency_map;
229
-        $this->mirror = $mirror;
230
-        $this->class_cache = $class_cache;
231
-        $this->object_identifier = $object_identifier;
232
-        // $registry_container = new RegistryContainer();
233
-        $this->LIB = new RegistryContainer();
234
-        $this->addons = new RegistryContainer();
235
-        $this->modules = new RegistryContainer();
236
-        $this->shortcodes = new RegistryContainer();
237
-        $this->widgets = new RegistryContainer();
238
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
239
-    }
240
-
241
-
242
-    /**
243
-     * initialize
244
-     *
245
-     * @throws OutOfBoundsException
246
-     * @throws InvalidArgumentException
247
-     * @throws InvalidInterfaceException
248
-     * @throws InvalidDataTypeException
249
-     * @throws EE_Error
250
-     * @throws ReflectionException
251
-     */
252
-    public function initialize()
253
-    {
254
-        $this->_class_abbreviations = apply_filters(
255
-            'FHEE__EE_Registry____construct___class_abbreviations',
256
-            array(
257
-                'EE_Config'                                       => 'CFG',
258
-                'EE_Session'                                      => 'SSN',
259
-                'EE_Capabilities'                                 => 'CAP',
260
-                'EE_Cart'                                         => 'CART',
261
-                'EE_Network_Config'                               => 'NET_CFG',
262
-                'EE_Request_Handler'                              => 'REQ',
263
-                'EE_Message_Resource_Manager'                     => 'MRM',
264
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
265
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
266
-            )
267
-        );
268
-        $this->load_core('Base', array(), true);
269
-        // add our request and response objects to the cache
270
-        $request_loader = $this->_dependency_map->class_loader(
271
-            'EventEspresso\core\services\request\Request'
272
-        );
273
-        $this->_set_cached_class(
274
-            $request_loader(),
275
-            'EventEspresso\core\services\request\Request'
276
-        );
277
-        $response_loader = $this->_dependency_map->class_loader(
278
-            'EventEspresso\core\services\request\Response'
279
-        );
280
-        $this->_set_cached_class(
281
-            $response_loader(),
282
-            'EventEspresso\core\services\request\Response'
283
-        );
284
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
285
-    }
286
-
287
-
288
-    /**
289
-     * @return void
290
-     */
291
-    public function init()
292
-    {
293
-        // Get current page protocol
294
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
295
-        // Output admin-ajax.php URL with same protocol as current page
296
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
297
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
298
-    }
299
-
300
-
301
-    /**
302
-     * localize_i18n_js_strings
303
-     *
304
-     * @return string
305
-     */
306
-    public static function localize_i18n_js_strings()
307
-    {
308
-        $i18n_js_strings = (array) self::$i18n_js_strings;
309
-        foreach ($i18n_js_strings as $key => $value) {
310
-            if (is_scalar($value)) {
311
-                $i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
-            }
313
-        }
314
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
315
-    }
316
-
317
-
318
-    /**
319
-     * @param mixed string | EED_Module $module
320
-     * @throws OutOfBoundsException
321
-     * @throws InvalidArgumentException
322
-     * @throws InvalidInterfaceException
323
-     * @throws InvalidDataTypeException
324
-     * @throws EE_Error
325
-     * @throws ReflectionException
326
-     */
327
-    public function add_module($module)
328
-    {
329
-        if ($module instanceof EED_Module) {
330
-            $module_class = get_class($module);
331
-            $this->modules->{$module_class} = $module;
332
-        } else {
333
-            if (! class_exists('EE_Module_Request_Router', false)) {
334
-                $this->load_core('Module_Request_Router');
335
-            }
336
-            EE_Module_Request_Router::module_factory($module);
337
-        }
338
-    }
339
-
340
-
341
-    /**
342
-     * @param string $module_name
343
-     * @return mixed EED_Module | NULL
344
-     */
345
-    public function get_module($module_name = '')
346
-    {
347
-        return isset($this->modules->{$module_name})
348
-            ? $this->modules->{$module_name}
349
-            : null;
350
-    }
351
-
352
-
353
-    /**
354
-     * loads core classes - must be singletons
355
-     *
356
-     * @param string $class_name - simple class name ie: session
357
-     * @param mixed  $arguments
358
-     * @param bool   $load_only
359
-     * @return mixed
360
-     * @throws InvalidInterfaceException
361
-     * @throws InvalidDataTypeException
362
-     * @throws EE_Error
363
-     * @throws ReflectionException
364
-     * @throws InvalidArgumentException
365
-     */
366
-    public function load_core($class_name, $arguments = array(), $load_only = false)
367
-    {
368
-        $core_paths = apply_filters(
369
-            'FHEE__EE_Registry__load_core__core_paths',
370
-            array(
371
-                EE_CORE,
372
-                EE_ADMIN,
373
-                EE_CPTS,
374
-                EE_CORE . 'data_migration_scripts' . DS,
375
-                EE_CORE . 'capabilities' . DS,
376
-                EE_CORE . 'request_stack' . DS,
377
-                EE_CORE . 'middleware' . DS,
378
-            )
379
-        );
380
-        // retrieve instantiated class
381
-        return $this->_load(
382
-            $core_paths,
383
-            'EE_',
384
-            $class_name,
385
-            'core',
386
-            $arguments,
387
-            false,
388
-            true,
389
-            $load_only
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * loads service classes
396
-     *
397
-     * @param string $class_name - simple class name ie: session
398
-     * @param mixed  $arguments
399
-     * @param bool   $load_only
400
-     * @return mixed
401
-     * @throws InvalidInterfaceException
402
-     * @throws InvalidDataTypeException
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     * @throws InvalidArgumentException
406
-     */
407
-    public function load_service($class_name, $arguments = array(), $load_only = false)
408
-    {
409
-        $service_paths = apply_filters(
410
-            'FHEE__EE_Registry__load_service__service_paths',
411
-            array(
412
-                EE_CORE . 'services' . DS,
413
-            )
414
-        );
415
-        // retrieve instantiated class
416
-        return $this->_load(
417
-            $service_paths,
418
-            'EE_',
419
-            $class_name,
420
-            'class',
421
-            $arguments,
422
-            false,
423
-            true,
424
-            $load_only
425
-        );
426
-    }
427
-
428
-
429
-    /**
430
-     * loads data_migration_scripts
431
-     *
432
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
433
-     * @param mixed  $arguments
434
-     * @return EE_Data_Migration_Script_Base|mixed
435
-     * @throws InvalidInterfaceException
436
-     * @throws InvalidDataTypeException
437
-     * @throws EE_Error
438
-     * @throws ReflectionException
439
-     * @throws InvalidArgumentException
440
-     */
441
-    public function load_dms($class_name, $arguments = array())
442
-    {
443
-        // retrieve instantiated class
444
-        return $this->_load(
445
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
446
-            'EE_DMS_',
447
-            $class_name,
448
-            'dms',
449
-            $arguments,
450
-            false,
451
-            false
452
-        );
453
-    }
454
-
455
-
456
-    /**
457
-     * loads object creating classes - must be singletons
458
-     *
459
-     * @param string $class_name - simple class name ie: attendee
460
-     * @param mixed  $arguments  - an array of arguments to pass to the class
461
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
462
-     *                           instantiate
463
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
464
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
465
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
466
-     *                           (default)
467
-     * @return EE_Base_Class | bool
468
-     * @throws InvalidInterfaceException
469
-     * @throws InvalidDataTypeException
470
-     * @throws EE_Error
471
-     * @throws ReflectionException
472
-     * @throws InvalidArgumentException
473
-     */
474
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
475
-    {
476
-        $paths = apply_filters(
477
-            'FHEE__EE_Registry__load_class__paths',
478
-            array(
479
-                EE_CORE,
480
-                EE_CLASSES,
481
-                EE_BUSINESS,
482
-            )
483
-        );
484
-        // retrieve instantiated class
485
-        return $this->_load(
486
-            $paths,
487
-            'EE_',
488
-            $class_name,
489
-            'class',
490
-            $arguments,
491
-            $from_db,
492
-            $cache,
493
-            $load_only
494
-        );
495
-    }
496
-
497
-
498
-    /**
499
-     * loads helper classes - must be singletons
500
-     *
501
-     * @param string $class_name - simple class name ie: price
502
-     * @param mixed  $arguments
503
-     * @param bool   $load_only
504
-     * @return EEH_Base | bool
505
-     * @throws InvalidInterfaceException
506
-     * @throws InvalidDataTypeException
507
-     * @throws EE_Error
508
-     * @throws ReflectionException
509
-     * @throws InvalidArgumentException
510
-     */
511
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
512
-    {
513
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
514
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
515
-        // retrieve instantiated class
516
-        return $this->_load(
517
-            $helper_paths,
518
-            'EEH_',
519
-            $class_name,
520
-            'helper',
521
-            $arguments,
522
-            false,
523
-            true,
524
-            $load_only
525
-        );
526
-    }
527
-
528
-
529
-    /**
530
-     * loads core classes - must be singletons
531
-     *
532
-     * @param string $class_name - simple class name ie: session
533
-     * @param mixed  $arguments
534
-     * @param bool   $load_only
535
-     * @param bool   $cache      whether to cache the object or not.
536
-     * @return mixed
537
-     * @throws InvalidInterfaceException
538
-     * @throws InvalidDataTypeException
539
-     * @throws EE_Error
540
-     * @throws ReflectionException
541
-     * @throws InvalidArgumentException
542
-     */
543
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
544
-    {
545
-        $paths = array(
546
-            EE_LIBRARIES,
547
-            EE_LIBRARIES . 'messages' . DS,
548
-            EE_LIBRARIES . 'shortcodes' . DS,
549
-            EE_LIBRARIES . 'qtips' . DS,
550
-            EE_LIBRARIES . 'payment_methods' . DS,
551
-        );
552
-        // retrieve instantiated class
553
-        return $this->_load(
554
-            $paths,
555
-            'EE_',
556
-            $class_name,
557
-            'lib',
558
-            $arguments,
559
-            false,
560
-            $cache,
561
-            $load_only
562
-        );
563
-    }
564
-
565
-
566
-    /**
567
-     * loads model classes - must be singletons
568
-     *
569
-     * @param string $class_name - simple class name ie: price
570
-     * @param mixed  $arguments
571
-     * @param bool   $load_only
572
-     * @return EEM_Base | bool
573
-     * @throws InvalidInterfaceException
574
-     * @throws InvalidDataTypeException
575
-     * @throws EE_Error
576
-     * @throws ReflectionException
577
-     * @throws InvalidArgumentException
578
-     */
579
-    public function load_model($class_name, $arguments = array(), $load_only = false)
580
-    {
581
-        $paths = apply_filters(
582
-            'FHEE__EE_Registry__load_model__paths',
583
-            array(
584
-                EE_MODELS,
585
-                EE_CORE,
586
-            )
587
-        );
588
-        // retrieve instantiated class
589
-        return $this->_load(
590
-            $paths,
591
-            'EEM_',
592
-            $class_name,
593
-            'model',
594
-            $arguments,
595
-            false,
596
-            true,
597
-            $load_only
598
-        );
599
-    }
600
-
601
-
602
-    /**
603
-     * loads model classes - must be singletons
604
-     *
605
-     * @param string $class_name - simple class name ie: price
606
-     * @param mixed  $arguments
607
-     * @param bool   $load_only
608
-     * @return mixed | bool
609
-     * @throws InvalidInterfaceException
610
-     * @throws InvalidDataTypeException
611
-     * @throws EE_Error
612
-     * @throws ReflectionException
613
-     * @throws InvalidArgumentException
614
-     */
615
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
616
-    {
617
-        $paths = array(
618
-            EE_MODELS . 'fields' . DS,
619
-            EE_MODELS . 'helpers' . DS,
620
-            EE_MODELS . 'relations' . DS,
621
-            EE_MODELS . 'strategies' . DS,
622
-        );
623
-        // retrieve instantiated class
624
-        return $this->_load(
625
-            $paths,
626
-            'EE_',
627
-            $class_name,
628
-            '',
629
-            $arguments,
630
-            false,
631
-            true,
632
-            $load_only
633
-        );
634
-    }
635
-
636
-
637
-    /**
638
-     * Determines if $model_name is the name of an actual EE model.
639
-     *
640
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
641
-     * @return boolean
642
-     */
643
-    public function is_model_name($model_name)
644
-    {
645
-        return isset($this->models[ $model_name ]);
646
-    }
647
-
648
-
649
-    /**
650
-     * generic class loader
651
-     *
652
-     * @param string $path_to_file - directory path to file location, not including filename
653
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
654
-     * @param string $type         - file type - core? class? helper? model?
655
-     * @param mixed  $arguments
656
-     * @param bool   $load_only
657
-     * @return mixed
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws ReflectionException
662
-     * @throws InvalidArgumentException
663
-     */
664
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
665
-    {
666
-        // retrieve instantiated class
667
-        return $this->_load(
668
-            $path_to_file,
669
-            '',
670
-            $file_name,
671
-            $type,
672
-            $arguments,
673
-            false,
674
-            true,
675
-            $load_only
676
-        );
677
-    }
678
-
679
-
680
-    /**
681
-     * @param string $path_to_file - directory path to file location, not including filename
682
-     * @param string $class_name   - full class name  ie:  My_Class
683
-     * @param string $type         - file type - core? class? helper? model?
684
-     * @param mixed  $arguments
685
-     * @param bool   $load_only
686
-     * @return bool|EE_Addon|object
687
-     * @throws InvalidInterfaceException
688
-     * @throws InvalidDataTypeException
689
-     * @throws EE_Error
690
-     * @throws ReflectionException
691
-     * @throws InvalidArgumentException
692
-     */
693
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
694
-    {
695
-        // retrieve instantiated class
696
-        return $this->_load(
697
-            $path_to_file,
698
-            'addon',
699
-            $class_name,
700
-            $type,
701
-            $arguments,
702
-            false,
703
-            true,
704
-            $load_only
705
-        );
706
-    }
707
-
708
-
709
-    /**
710
-     * instantiates, caches, and automatically resolves dependencies
711
-     * for classes that use a Fully Qualified Class Name.
712
-     * if the class is not capable of being loaded using PSR-4 autoloading,
713
-     * then you need to use one of the existing load_*() methods
714
-     * which can resolve the classname and filepath from the passed arguments
715
-     *
716
-     * @param bool|string $class_name   Fully Qualified Class Name
717
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
718
-     * @param bool        $cache        whether to cache the instantiated object for reuse
719
-     * @param bool        $from_db      some classes are instantiated from the db
720
-     *                                  and thus call a different method to instantiate
721
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
722
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
723
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
724
-     *                                  object = class loaded and instantiated successfully.
725
-     *                                  bool = fail or success when $load_only is true
726
-     * @throws InvalidInterfaceException
727
-     * @throws InvalidDataTypeException
728
-     * @throws EE_Error
729
-     * @throws ReflectionException
730
-     * @throws InvalidArgumentException
731
-     */
732
-    public function create(
733
-        $class_name = false,
734
-        $arguments = array(),
735
-        $cache = false,
736
-        $from_db = false,
737
-        $load_only = false,
738
-        $addon = false
739
-    ) {
740
-        $class_name = ltrim($class_name, '\\');
741
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
742
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
743
-        // if a non-FQCN was passed, then
744
-        // verifyClassExists() might return an object
745
-        // or it could return null if the class just could not be found anywhere
746
-        if ($class_exists instanceof $class_name || $class_exists === null) {
747
-            // either way, return the results
748
-            return $class_exists;
749
-        }
750
-        $class_name = $class_exists;
751
-        // if we're only loading the class and it already exists, then let's just return true immediately
752
-        if ($load_only) {
753
-            return true;
754
-        }
755
-        $addon = $addon ? 'addon' : '';
756
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
757
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
758
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
759
-        if ($this->_cache_on && $cache && ! $load_only) {
760
-            // return object if it's already cached
761
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
762
-            if ($cached_class !== null) {
763
-                return $cached_class;
764
-            }
765
-        }// obtain the loader method from the dependency map
766
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
767
-        if ($loader instanceof Closure) {
768
-            $class_obj = $loader($arguments);
769
-        } else {
770
-            if ($loader && method_exists($this, $loader)) {
771
-                $class_obj = $this->{$loader}($class_name, $arguments);
772
-            } else {
773
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
774
-            }
775
-        }
776
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
777
-            // save it for later... kinda like gum  { : $
778
-            $this->_set_cached_class(
779
-                $class_obj,
780
-                $class_name,
781
-                $addon,
782
-                $from_db,
783
-                $arguments
784
-            );
785
-        }
786
-        $this->_cache_on = true;
787
-        return $class_obj;
788
-    }
789
-
790
-
791
-    /**
792
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
793
-     *
794
-     * @param string|object $class_name
795
-     * @param array         $arguments
796
-     * @param int           $attempt
797
-     * @return mixed
798
-     */
799
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
800
-    {
801
-        if (is_object($class_name) || class_exists($class_name)) {
802
-            return $class_name;
803
-        }
804
-        switch ($attempt) {
805
-            case 1:
806
-                // if it's a FQCN then maybe the class is registered with a preceding \
807
-                $class_name = strpos($class_name, '\\') !== false
808
-                    ? '\\' . ltrim($class_name, '\\')
809
-                    : $class_name;
810
-                break;
811
-            case 2:
812
-                //
813
-                $loader = $this->_dependency_map->class_loader($class_name);
814
-                if ($loader && method_exists($this, $loader)) {
815
-                    return $this->{$loader}($class_name, $arguments);
816
-                }
817
-                break;
818
-            case 3:
819
-            default:
820
-                return null;
821
-        }
822
-        $attempt++;
823
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
824
-    }
825
-
826
-
827
-    /**
828
-     * instantiates, caches, and injects dependencies for classes
829
-     *
830
-     * @param array       $file_paths   an array of paths to folders to look in
831
-     * @param string      $class_prefix EE  or EEM or... ???
832
-     * @param bool|string $class_name   $class name
833
-     * @param string      $type         file type - core? class? helper? model?
834
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
835
-     * @param bool        $from_db      some classes are instantiated from the db
836
-     *                                  and thus call a different method to instantiate
837
-     * @param bool        $cache        whether to cache the instantiated object for reuse
838
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
839
-     * @return bool|null|object null = failure to load or instantiate class object.
840
-     *                                  object = class loaded and instantiated successfully.
841
-     *                                  bool = fail or success when $load_only is true
842
-     * @throws EE_Error
843
-     * @throws ReflectionException
844
-     * @throws InvalidInterfaceException
845
-     * @throws InvalidDataTypeException
846
-     * @throws InvalidArgumentException
847
-     */
848
-    protected function _load(
849
-        $file_paths = array(),
850
-        $class_prefix = 'EE_',
851
-        $class_name = false,
852
-        $type = 'class',
853
-        $arguments = array(),
854
-        $from_db = false,
855
-        $cache = true,
856
-        $load_only = false
857
-    ) {
858
-        $class_name = ltrim($class_name, '\\');
859
-        // strip php file extension
860
-        $class_name = str_replace('.php', '', trim($class_name));
861
-        // does the class have a prefix ?
862
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
863
-            // make sure $class_prefix is uppercase
864
-            $class_prefix = strtoupper(trim($class_prefix));
865
-            // add class prefix ONCE!!!
866
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
867
-        }
868
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
869
-        $class_exists = class_exists($class_name, false);
870
-        // if we're only loading the class and it already exists, then let's just return true immediately
871
-        if ($load_only && $class_exists) {
872
-            return true;
873
-        }
874
-        $arguments = is_array($arguments) ? $arguments : array($arguments);
875
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
876
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
877
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
878
-        if ($this->_cache_on && $cache && ! $load_only) {
879
-            // return object if it's already cached
880
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
881
-            if ($cached_class !== null) {
882
-                return $cached_class;
883
-            }
884
-        }
885
-        // if the class doesn't already exist.. then we need to try and find the file and load it
886
-        if (! $class_exists) {
887
-            // get full path to file
888
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
889
-            // load the file
890
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
891
-            // if we are only loading a file but NOT instantiating an object
892
-            // then return boolean for whether class was loaded or not
893
-            if ($load_only) {
894
-                return $loaded;
895
-            }
896
-            // if an object was expected but loading failed, then return nothing
897
-            if (! $loaded) {
898
-                return null;
899
-            }
900
-        }
901
-        // instantiate the requested object
902
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
903
-        if ($this->_cache_on && $cache) {
904
-            // save it for later... kinda like gum  { : $
905
-            $this->_set_cached_class(
906
-                $class_obj,
907
-                $class_name,
908
-                $class_prefix,
909
-                $from_db,
910
-                $arguments
911
-            );
912
-        }
913
-        $this->_cache_on = true;
914
-        return $class_obj;
915
-    }
916
-
917
-
918
-    /**
919
-     * @param string $class_name
920
-     * @param string $default have to specify something, but not anything that will conflict
921
-     * @return mixed|string
922
-     */
923
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
924
-    {
925
-        return isset($this->_class_abbreviations[ $class_name ])
926
-            ? $this->_class_abbreviations[ $class_name ]
927
-            : $default;
928
-    }
929
-
930
-
931
-    /**
932
-     * attempts to find a cached version of the requested class
933
-     * by looking in the following places:
934
-     *        $this->{$class_abbreviation}            ie:    $this->CART
935
-     *        $this->{$class_name}                        ie:    $this->Some_Class
936
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
937
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
938
-     *
939
-     * @param string $class_name
940
-     * @param string $class_prefix
941
-     * @param array  $arguments
942
-     * @return mixed
943
-     */
944
-    protected function _get_cached_class(
945
-        $class_name,
946
-        $class_prefix = '',
947
-        $arguments = array()
948
-    ) {
949
-        if ($class_name === 'EE_Registry') {
950
-            return $this;
951
-        }
952
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
953
-        // check if class has already been loaded, and return it if it has been
954
-        if (isset($this->{$class_abbreviation})) {
955
-            return $this->{$class_abbreviation};
956
-        }
957
-        $class_name = str_replace('\\', '_', $class_name);
958
-        if (isset($this->{$class_name})) {
959
-            return $this->{$class_name};
960
-        }
961
-        if ($class_prefix === 'addon' && isset($this->addons->{$class_name})) {
962
-            return $this->addons->{$class_name};
963
-        }
964
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
965
-        if (isset($this->LIB->{$object_identifier})) {
966
-            return $this->LIB->{$object_identifier};
967
-        }
968
-        foreach ($this->LIB as $key => $object) {
969
-            if (// request does not contain new arguments and therefore no args identifier
970
-                ! $this->object_identifier->hasArguments($object_identifier)
971
-                // but previously cached class with args was found
972
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
973
-            ) {
974
-                return $object;
975
-            }
976
-        }
977
-        return null;
978
-    }
979
-
980
-
981
-    /**
982
-     * removes a cached version of the requested class
983
-     *
984
-     * @param string  $class_name
985
-     * @param boolean $addon
986
-     * @param array   $arguments
987
-     * @return boolean
988
-     */
989
-    public function clear_cached_class(
990
-        $class_name,
991
-        $addon = false,
992
-        $arguments = array()
993
-    ) {
994
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
995
-        // check if class has already been loaded, and return it if it has been
996
-        if (isset($this->{$class_abbreviation})) {
997
-            $this->{$class_abbreviation} = null;
998
-            return true;
999
-        }
1000
-        $class_name = str_replace('\\', '_', $class_name);
1001
-        if (isset($this->{$class_name})) {
1002
-            $this->{$class_name} = null;
1003
-            return true;
1004
-        }
1005
-        if ($addon && isset($this->addons->{$class_name})) {
1006
-            unset($this->addons->{$class_name});
1007
-            return true;
1008
-        }
1009
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1010
-        if (isset($this->LIB->{$class_name})) {
1011
-            unset($this->LIB->{$class_name});
1012
-            return true;
1013
-        }
1014
-        return false;
1015
-    }
1016
-
1017
-
1018
-    /**
1019
-     * _set_cached_class
1020
-     * attempts to cache the instantiated class locally
1021
-     * in one of the following places, in the following order:
1022
-     *        $this->{class_abbreviation}   ie:    $this->CART
1023
-     *        $this->{$class_name}          ie:    $this->Some_Class
1024
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1025
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1026
-     *
1027
-     * @param object $class_obj
1028
-     * @param string $class_name
1029
-     * @param string $class_prefix
1030
-     * @param bool   $from_db
1031
-     * @param array  $arguments
1032
-     * @return void
1033
-     */
1034
-    protected function _set_cached_class(
1035
-        $class_obj,
1036
-        $class_name,
1037
-        $class_prefix = '',
1038
-        $from_db = false,
1039
-        $arguments = array()
1040
-    ) {
1041
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1042
-            return;
1043
-        }
1044
-        // return newly instantiated class
1045
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1046
-        if ($class_abbreviation) {
1047
-            $this->{$class_abbreviation} = $class_obj;
1048
-            return;
1049
-        }
1050
-        $class_name = str_replace('\\', '_', $class_name);
1051
-        if (property_exists($this, $class_name)) {
1052
-            $this->{$class_name} = $class_obj;
1053
-            return;
1054
-        }
1055
-        if ($class_prefix === 'addon') {
1056
-            $this->addons->{$class_name} = $class_obj;
1057
-            return;
1058
-        }
1059
-        if (! $from_db) {
1060
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1061
-            $this->LIB->{$class_name} = $class_obj;
1062
-        }
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * attempts to find a full valid filepath for the requested class.
1068
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1069
-     * then returns that path if the target file has been found and is readable
1070
-     *
1071
-     * @param string $class_name
1072
-     * @param string $type
1073
-     * @param array  $file_paths
1074
-     * @return string | bool
1075
-     */
1076
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
1077
-    {
1078
-        // make sure $file_paths is an array
1079
-        $file_paths = is_array($file_paths)
1080
-            ? $file_paths
1081
-            : array($file_paths);
1082
-        // cycle thru paths
1083
-        foreach ($file_paths as $key => $file_path) {
1084
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
1085
-            $file_path = $file_path
1086
-                ? str_replace(array('/', '\\'), DS, $file_path)
1087
-                : EE_CLASSES;
1088
-            // prep file type
1089
-            $type = ! empty($type)
1090
-                ? trim($type, '.') . '.'
1091
-                : '';
1092
-            // build full file path
1093
-            $file_paths[ $key ] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
1094
-            // does the file exist and can be read ?
1095
-            if (is_readable($file_paths[ $key ])) {
1096
-                return $file_paths[ $key ];
1097
-            }
1098
-        }
1099
-        return false;
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * basically just performs a require_once()
1105
-     * but with some error handling
1106
-     *
1107
-     * @param  string $path
1108
-     * @param  string $class_name
1109
-     * @param  string $type
1110
-     * @param  array  $file_paths
1111
-     * @return bool
1112
-     * @throws EE_Error
1113
-     * @throws ReflectionException
1114
-     */
1115
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1116
-    {
1117
-        $this->resolve_legacy_class_parent($class_name);
1118
-        // don't give up! you gotta...
1119
-        try {
1120
-            // does the file exist and can it be read ?
1121
-            if (! $path) {
1122
-                // just in case the file has already been autoloaded,
1123
-                // but discrepancies in the naming schema are preventing it from
1124
-                // being loaded via one of the EE_Registry::load_*() methods,
1125
-                // then let's try one last hail mary before throwing an exception
1126
-                // and call class_exists() again, but with autoloading turned ON
1127
-                if (class_exists($class_name)) {
1128
-                    return true;
1129
-                }
1130
-                // so sorry, can't find the file
1131
-                throw new EE_Error(
1132
-                    sprintf(
1133
-                        esc_html__(
1134
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1135
-                            'event_espresso'
1136
-                        ),
1137
-                        trim($type, '.'),
1138
-                        $class_name,
1139
-                        '<br />' . implode(',<br />', $file_paths)
1140
-                    )
1141
-                );
1142
-            }
1143
-            // get the file
1144
-            require_once($path);
1145
-            // if the class isn't already declared somewhere
1146
-            if (class_exists($class_name, false) === false) {
1147
-                // so sorry, not a class
1148
-                throw new EE_Error(
1149
-                    sprintf(
1150
-                        esc_html__(
1151
-                            'The %s file %s does not appear to contain the %s Class.',
1152
-                            'event_espresso'
1153
-                        ),
1154
-                        $type,
1155
-                        $path,
1156
-                        $class_name
1157
-                    )
1158
-                );
1159
-            }
1160
-        } catch (EE_Error $e) {
1161
-            $e->get_error();
1162
-            return false;
1163
-        }
1164
-        return true;
1165
-    }
1166
-
1167
-
1168
-    /**
1169
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1170
-     * before their class declaration in order to ensure that the parent class was loaded.
1171
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1172
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1173
-     *
1174
-     * @param string $class_name
1175
-     */
1176
-    protected function resolve_legacy_class_parent($class_name = '')
1177
-    {
1178
-        try {
1179
-            $legacy_parent_class_map = array(
1180
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1181
-            );
1182
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1183
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1184
-            }
1185
-        } catch (Exception $exception) {
1186
-        }
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * _create_object
1192
-     * Attempts to instantiate the requested class via any of the
1193
-     * commonly used instantiation methods employed throughout EE.
1194
-     * The priority for instantiation is as follows:
1195
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1196
-     *        - model objects via their 'new_instance_from_db' method
1197
-     *        - model objects via their 'new_instance' method
1198
-     *        - "singleton" classes" via their 'instance' method
1199
-     *    - standard instantiable classes via their __constructor
1200
-     * Prior to instantiation, if the classname exists in the dependency_map,
1201
-     * then the constructor for the requested class will be examined to determine
1202
-     * if any dependencies exist, and if they can be injected.
1203
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1204
-     *
1205
-     * @param string $class_name
1206
-     * @param array  $arguments
1207
-     * @param string $type
1208
-     * @param bool   $from_db
1209
-     * @return null|object|bool
1210
-     * @throws InvalidArgumentException
1211
-     * @throws InvalidInterfaceException
1212
-     * @throws EE_Error
1213
-     * @throws ReflectionException
1214
-     * @throws InvalidDataTypeException
1215
-     */
1216
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1217
-    {
1218
-        // create reflection
1219
-        $reflector = $this->mirror->getReflectionClass($class_name);
1220
-        // make sure arguments are an array
1221
-        $arguments = is_array($arguments)
1222
-            ? $arguments
1223
-            : array($arguments);
1224
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1225
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1226
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1227
-            ? $arguments
1228
-            : array($arguments);
1229
-        // attempt to inject dependencies ?
1230
-        if ($this->_dependency_map->has($class_name)) {
1231
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1232
-        }
1233
-        // instantiate the class if possible
1234
-        if ($reflector->isAbstract()) {
1235
-            // nothing to instantiate, loading file was enough
1236
-            // does not throw an exception so $instantiation_mode is unused
1237
-            // $instantiation_mode = "1) no constructor abstract class";
1238
-            return true;
1239
-        }
1240
-        if (empty($arguments)
1241
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1242
-            && $reflector->isInstantiable()
1243
-        ) {
1244
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1245
-            // $instantiation_mode = "2) no constructor but instantiable";
1246
-            return $reflector->newInstance();
1247
-        }
1248
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1249
-            // $instantiation_mode = "3) new_instance_from_db()";
1250
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1251
-        }
1252
-        if (method_exists($class_name, 'new_instance')) {
1253
-            // $instantiation_mode = "4) new_instance()";
1254
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1255
-        }
1256
-        if (method_exists($class_name, 'instance')) {
1257
-            // $instantiation_mode = "5) instance()";
1258
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1259
-        }
1260
-        if ($reflector->isInstantiable()) {
1261
-            // $instantiation_mode = "6) constructor";
1262
-            return $reflector->newInstanceArgs($arguments);
1263
-        }
1264
-        // heh ? something's not right !
1265
-        throw new EE_Error(
1266
-            sprintf(
1267
-                __('The %s file %s could not be instantiated.', 'event_espresso'),
1268
-                $type,
1269
-                $class_name
1270
-            )
1271
-        );
1272
-    }
1273
-
1274
-
1275
-    /**
1276
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1277
-     * @param array $array
1278
-     * @return bool
1279
-     */
1280
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1281
-    {
1282
-        return ! empty($array)
1283
-            ? array_keys($array) === range(0, count($array) - 1)
1284
-            : true;
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * _resolve_dependencies
1290
-     * examines the constructor for the requested class to determine
1291
-     * if any dependencies exist, and if they can be injected.
1292
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1293
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1294
-     * For example:
1295
-     *        if attempting to load a class "Foo" with the following constructor:
1296
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1297
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1298
-     *        but only IF they are NOT already present in the incoming arguments array,
1299
-     *        and the correct classes can be loaded
1300
-     *
1301
-     * @param ReflectionClass $reflector
1302
-     * @param string          $class_name
1303
-     * @param array           $arguments
1304
-     * @return array
1305
-     * @throws InvalidArgumentException
1306
-     * @throws InvalidDataTypeException
1307
-     * @throws InvalidInterfaceException
1308
-     * @throws ReflectionException
1309
-     */
1310
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1311
-    {
1312
-        // let's examine the constructor
1313
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1314
-        // whu? huh? nothing?
1315
-        if (! $constructor) {
1316
-            return $arguments;
1317
-        }
1318
-        // get constructor parameters
1319
-        $params = $this->mirror->getParametersFromReflection($reflector);
1320
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1321
-        $argument_keys = array_keys($arguments);
1322
-        // now loop thru all of the constructors expected parameters
1323
-        foreach ($params as $index => $param) {
1324
-            // is this a dependency for a specific class ?
1325
-            $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1326
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1327
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1328
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1329
-                : $param_class;
1330
-            if (// param is not even a class
1331
-                $param_class === null
1332
-                // and something already exists in the incoming arguments for this param
1333
-                && array_key_exists($index, $argument_keys)
1334
-                && array_key_exists($argument_keys[ $index ], $arguments)
1335
-            ) {
1336
-                // so let's skip this argument and move on to the next
1337
-                continue;
1338
-            }
1339
-            if (// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1340
-                $param_class !== null
1341
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1342
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1343
-            ) {
1344
-                // skip this argument and move on to the next
1345
-                continue;
1346
-            }
1347
-            if (// parameter is type hinted as a class, and should be injected
1348
-                $param_class !== null
1349
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1350
-            ) {
1351
-                $arguments = $this->_resolve_dependency(
1352
-                    $class_name,
1353
-                    $param_class,
1354
-                    $arguments,
1355
-                    $index
1356
-                );
1357
-            } else {
1358
-                $arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1359
-                    $param,
1360
-                    $class_name,
1361
-                    $index
1362
-                );
1363
-            }
1364
-        }
1365
-        return $arguments;
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * @param string $class_name
1371
-     * @param string $param_class
1372
-     * @param array  $arguments
1373
-     * @param mixed  $index
1374
-     * @return array
1375
-     * @throws InvalidArgumentException
1376
-     * @throws InvalidInterfaceException
1377
-     * @throws InvalidDataTypeException
1378
-     */
1379
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1380
-    {
1381
-        $dependency = null;
1382
-        // should dependency be loaded from cache ?
1383
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1384
-            $class_name,
1385
-            $param_class
1386
-        );
1387
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1388
-        // we might have a dependency...
1389
-        // let's MAYBE try and find it in our cache if that's what's been requested
1390
-        $cached_class = $cache_on
1391
-            ? $this->_get_cached_class($param_class)
1392
-            : null;
1393
-        // and grab it if it exists
1394
-        if ($cached_class instanceof $param_class) {
1395
-            $dependency = $cached_class;
1396
-        } elseif ($param_class !== $class_name) {
1397
-            // obtain the loader method from the dependency map
1398
-            $loader = $this->_dependency_map->class_loader($param_class);
1399
-            // is loader a custom closure ?
1400
-            if ($loader instanceof Closure) {
1401
-                $dependency = $loader($arguments);
1402
-            } else {
1403
-                // set the cache on property for the recursive loading call
1404
-                $this->_cache_on = $cache_on;
1405
-                // if not, then let's try and load it via the registry
1406
-                if ($loader && method_exists($this, $loader)) {
1407
-                    $dependency = $this->{$loader}($param_class);
1408
-                } else {
1409
-                    $dependency = LoaderFactory::getLoader()->load(
1410
-                        $param_class,
1411
-                        array(),
1412
-                        $cache_on
1413
-                    );
1414
-                }
1415
-            }
1416
-        }
1417
-        // did we successfully find the correct dependency ?
1418
-        if ($dependency instanceof $param_class) {
1419
-            // then let's inject it into the incoming array of arguments at the correct location
1420
-            $arguments[ $index ] = $dependency;
1421
-        }
1422
-        return $arguments;
1423
-    }
1424
-
1425
-
1426
-    /**
1427
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1428
-     *
1429
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1430
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1431
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1432
-     * @param array  $arguments
1433
-     * @return object
1434
-     */
1435
-    public static function factory($classname, $arguments = array())
1436
-    {
1437
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1438
-        if ($loader instanceof Closure) {
1439
-            return $loader($arguments);
1440
-        }
1441
-        if (method_exists(self::instance(), $loader)) {
1442
-            return self::instance()->{$loader}($classname, $arguments);
1443
-        }
1444
-        return null;
1445
-    }
1446
-
1447
-
1448
-    /**
1449
-     * Gets the addon by its class name
1450
-     *
1451
-     * @param string $class_name
1452
-     * @return EE_Addon
1453
-     */
1454
-    public function getAddon($class_name)
1455
-    {
1456
-        $class_name = str_replace('\\', '_', $class_name);
1457
-        return $this->addons->{$class_name};
1458
-    }
1459
-
1460
-
1461
-    /**
1462
-     * removes the addon from the internal cache
1463
-     *
1464
-     * @param string $class_name
1465
-     * @return void
1466
-     */
1467
-    public function removeAddon($class_name)
1468
-    {
1469
-        $class_name = str_replace('\\', '_', $class_name);
1470
-        unset($this->addons->{$class_name});
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * Gets the addon by its name/slug (not classname. For that, just
1476
-     * use the get_addon() method above
1477
-     *
1478
-     * @param string $name
1479
-     * @return EE_Addon
1480
-     */
1481
-    public function get_addon_by_name($name)
1482
-    {
1483
-        foreach ($this->addons as $addon) {
1484
-            if ($addon->name() === $name) {
1485
-                return $addon;
1486
-            }
1487
-        }
1488
-        return null;
1489
-    }
1490
-
1491
-
1492
-    /**
1493
-     * Gets an array of all the registered addons, where the keys are their names.
1494
-     * (ie, what each returns for their name() function)
1495
-     * They're already available on EE_Registry::instance()->addons as properties,
1496
-     * where each property's name is the addon's classname,
1497
-     * So if you just want to get the addon by classname,
1498
-     * OR use the get_addon() method above.
1499
-     * PLEASE  NOTE:
1500
-     * addons with Fully Qualified Class Names
1501
-     * have had the namespace separators converted to underscores,
1502
-     * so a classname like Fully\Qualified\ClassName
1503
-     * would have been converted to Fully_Qualified_ClassName
1504
-     *
1505
-     * @return EE_Addon[] where the KEYS are the addon's name()
1506
-     */
1507
-    public function get_addons_by_name()
1508
-    {
1509
-        $addons = array();
1510
-        foreach ($this->addons as $addon) {
1511
-            $addons[ $addon->name() ] = $addon;
1512
-        }
1513
-        return $addons;
1514
-    }
1515
-
1516
-
1517
-    /**
1518
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1519
-     * a stale copy of it around
1520
-     *
1521
-     * @param string $model_name
1522
-     * @return \EEM_Base
1523
-     * @throws \EE_Error
1524
-     */
1525
-    public function reset_model($model_name)
1526
-    {
1527
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1528
-            ? "EEM_{$model_name}"
1529
-            : $model_name;
1530
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1531
-            return null;
1532
-        }
1533
-        // get that model reset it and make sure we nuke the old reference to it
1534
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1535
-            && is_callable(
1536
-                array($model_class_name, 'reset')
1537
-            )) {
1538
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1539
-        } else {
1540
-            throw new EE_Error(
1541
-                sprintf(
1542
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1543
-                    $model_name
1544
-                )
1545
-            );
1546
-        }
1547
-        return $this->LIB->{$model_class_name};
1548
-    }
1549
-
1550
-
1551
-    /**
1552
-     * Resets the registry.
1553
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1554
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1555
-     * - $_dependency_map
1556
-     * - $_class_abbreviations
1557
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1558
-     * - $REQ:  Still on the same request so no need to change.
1559
-     * - $CAP: There is no site specific state in the EE_Capability class.
1560
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1561
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1562
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1563
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1564
-     *             switch or on the restore.
1565
-     * - $modules
1566
-     * - $shortcodes
1567
-     * - $widgets
1568
-     *
1569
-     * @param boolean $hard             [deprecated]
1570
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1571
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1572
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1573
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1574
-     *                                  client
1575
-     *                                  code instead can just change the model context to a different blog id if
1576
-     *                                  necessary
1577
-     * @return EE_Registry
1578
-     * @throws InvalidInterfaceException
1579
-     * @throws InvalidDataTypeException
1580
-     * @throws EE_Error
1581
-     * @throws ReflectionException
1582
-     * @throws InvalidArgumentException
1583
-     */
1584
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1585
-    {
1586
-        $instance = self::instance();
1587
-        $instance->_cache_on = true;
1588
-        // reset some "special" classes
1589
-        EEH_Activation::reset();
1590
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1591
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1592
-        $instance->CART = null;
1593
-        $instance->MRM = null;
1594
-        $instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1595
-            'EventEspresso\core\services\assets\Registry'
1596
-        );
1597
-        // messages reset
1598
-        EED_Messages::reset();
1599
-        // handle of objects cached on LIB
1600
-        foreach (array('LIB', 'modules') as $cache) {
1601
-            foreach ($instance->{$cache} as $class_name => $class) {
1602
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1603
-                    unset($instance->{$cache}->{$class_name});
1604
-                }
1605
-            }
1606
-        }
1607
-        return $instance;
1608
-    }
1609
-
1610
-
1611
-    /**
1612
-     * if passed object implements ResettableInterface, then call it's reset() method
1613
-     * if passed object implements InterminableInterface, then return false,
1614
-     * to indicate that it should NOT be cleared from the Registry cache
1615
-     *
1616
-     * @param      $object
1617
-     * @param bool $reset_models
1618
-     * @return bool returns true if cached object should be unset
1619
-     */
1620
-    private static function _reset_and_unset_object($object, $reset_models)
1621
-    {
1622
-        if (! is_object($object)) {
1623
-            // don't unset anything that's not an object
1624
-            return false;
1625
-        }
1626
-        if ($object instanceof EED_Module) {
1627
-            $object::reset();
1628
-            // don't unset modules
1629
-            return false;
1630
-        }
1631
-        if ($object instanceof ResettableInterface) {
1632
-            if ($object instanceof EEM_Base) {
1633
-                if ($reset_models) {
1634
-                    $object->reset();
1635
-                    return true;
1636
-                }
1637
-                return false;
1638
-            }
1639
-            $object->reset();
1640
-            return true;
1641
-        }
1642
-        if (! $object instanceof InterminableInterface) {
1643
-            return true;
1644
-        }
1645
-        return false;
1646
-    }
1647
-
1648
-
1649
-    /**
1650
-     * Gets all the custom post type models defined
1651
-     *
1652
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1653
-     */
1654
-    public function cpt_models()
1655
-    {
1656
-        $cpt_models = array();
1657
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1658
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1659
-                $cpt_models[ $short_name ] = $classname;
1660
-            }
1661
-        }
1662
-        return $cpt_models;
1663
-    }
1664
-
1665
-
1666
-    /**
1667
-     * @return \EE_Config
1668
-     */
1669
-    public static function CFG()
1670
-    {
1671
-        return self::instance()->CFG;
1672
-    }
1673
-
1674
-
1675
-    /**
1676
-     * @deprecated 4.9.62.p
1677
-     * @param string $class_name
1678
-     * @return ReflectionClass
1679
-     * @throws ReflectionException
1680
-     * @throws InvalidDataTypeException
1681
-     */
1682
-    public function get_ReflectionClass($class_name)
1683
-    {
1684
-        return $this->mirror->getReflectionClass($class_name);
1685
-    }
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var Mirror
38
+	 */
39
+	private $mirror;
40
+
41
+	/**
42
+	 * @var ClassInterfaceCache $class_cache
43
+	 */
44
+	private $class_cache;
45
+
46
+	/**
47
+	 * @var array $_class_abbreviations
48
+	 */
49
+	protected $_class_abbreviations = array();
50
+
51
+	/**
52
+	 * @var CommandBusInterface $BUS
53
+	 */
54
+	public $BUS;
55
+
56
+	/**
57
+	 * @var EE_Cart $CART
58
+	 */
59
+	public $CART;
60
+
61
+	/**
62
+	 * @var EE_Config $CFG
63
+	 */
64
+	public $CFG;
65
+
66
+	/**
67
+	 * @var EE_Network_Config $NET_CFG
68
+	 */
69
+	public $NET_CFG;
70
+
71
+	/**
72
+	 * StdClass object for storing library classes in
73
+	 *
74
+	 * @var RegistryContainer $LIB
75
+	 */
76
+	public $LIB;
77
+
78
+	/**
79
+	 * @var EE_Request_Handler $REQ
80
+	 */
81
+	public $REQ;
82
+
83
+	/**
84
+	 * @var EE_Session $SSN
85
+	 */
86
+	public $SSN;
87
+
88
+	/**
89
+	 * @since 4.5.0
90
+	 * @var EE_Capabilities $CAP
91
+	 */
92
+	public $CAP;
93
+
94
+	/**
95
+	 * @since 4.9.0
96
+	 * @var EE_Message_Resource_Manager $MRM
97
+	 */
98
+	public $MRM;
99
+
100
+	/**
101
+	 * @var Registry $AssetsRegistry
102
+	 */
103
+	public $AssetsRegistry;
104
+
105
+	/**
106
+	 * StdClass object for holding addons which have registered themselves to work with EE core
107
+	 *
108
+	 * @var EE_Addon[] $addons
109
+	 */
110
+	public $addons;
111
+
112
+	/**
113
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
+	 *
115
+	 * @var EEM_Base[] $models
116
+	 */
117
+	public $models = array();
118
+
119
+	/**
120
+	 * @var EED_Module[] $modules
121
+	 */
122
+	public $modules;
123
+
124
+	/**
125
+	 * @var EES_Shortcode[] $shortcodes
126
+	 */
127
+	public $shortcodes;
128
+
129
+	/**
130
+	 * @var WP_Widget[] $widgets
131
+	 */
132
+	public $widgets;
133
+
134
+	/**
135
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
+	 * classnames (eg "EEM_Event")
139
+	 *
140
+	 * @var array $non_abstract_db_models
141
+	 */
142
+	public $non_abstract_db_models = array();
143
+
144
+	/**
145
+	 * internationalization for JS strings
146
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
+	 *    in js file:  var translatedString = eei18n.string_key;
148
+	 *
149
+	 * @var array $i18n_js_strings
150
+	 */
151
+	public static $i18n_js_strings = array();
152
+
153
+	/**
154
+	 * $main_file - path to espresso.php
155
+	 *
156
+	 * @var array $main_file
157
+	 */
158
+	public $main_file;
159
+
160
+	/**
161
+	 * array of ReflectionClass objects where the key is the class name
162
+	 *
163
+	 * @deprecated 4.9.62.p
164
+	 * @var ReflectionClass[] $_reflectors
165
+	 */
166
+	public $_reflectors;
167
+
168
+	/**
169
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
+	 *
171
+	 * @var boolean $_cache_on
172
+	 */
173
+	protected $_cache_on = true;
174
+
175
+	/**
176
+	 * @var ObjectIdentifier
177
+	 */
178
+	private $object_identifier;
179
+
180
+
181
+	/**
182
+	 * @singleton method used to instantiate class object
183
+	 * @param EE_Dependency_Map|null   $dependency_map
184
+	 * @param Mirror|null              $mirror
185
+	 * @param ClassInterfaceCache|null $class_cache
186
+	 * @param ObjectIdentifier|null    $object_identifier
187
+	 * @return EE_Registry instance
188
+	 */
189
+	public static function instance(
190
+		EE_Dependency_Map $dependency_map = null,
191
+		Mirror $mirror = null,
192
+		ClassInterfaceCache $class_cache = null,
193
+		ObjectIdentifier $object_identifier = null
194
+	) {
195
+		// check if class object is instantiated
196
+		if (! self::$_instance instanceof EE_Registry
197
+			&& $dependency_map instanceof EE_Dependency_Map
198
+			&& $mirror instanceof Mirror
199
+			&& $class_cache instanceof ClassInterfaceCache
200
+			&& $object_identifier instanceof ObjectIdentifier
201
+		) {
202
+			self::$_instance = new self(
203
+				$dependency_map,
204
+				$mirror,
205
+				$class_cache,
206
+				$object_identifier
207
+			);
208
+		}
209
+		return self::$_instance;
210
+	}
211
+
212
+
213
+	/**
214
+	 * protected constructor to prevent direct creation
215
+	 *
216
+	 * @Constructor
217
+	 * @param  EE_Dependency_Map  $dependency_map
218
+	 * @param Mirror              $mirror
219
+	 * @param ClassInterfaceCache $class_cache
220
+	 * @param ObjectIdentifier    $object_identifier
221
+	 */
222
+	protected function __construct(
223
+		EE_Dependency_Map $dependency_map,
224
+		Mirror $mirror,
225
+		ClassInterfaceCache $class_cache,
226
+		ObjectIdentifier $object_identifier
227
+	) {
228
+		$this->_dependency_map = $dependency_map;
229
+		$this->mirror = $mirror;
230
+		$this->class_cache = $class_cache;
231
+		$this->object_identifier = $object_identifier;
232
+		// $registry_container = new RegistryContainer();
233
+		$this->LIB = new RegistryContainer();
234
+		$this->addons = new RegistryContainer();
235
+		$this->modules = new RegistryContainer();
236
+		$this->shortcodes = new RegistryContainer();
237
+		$this->widgets = new RegistryContainer();
238
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
239
+	}
240
+
241
+
242
+	/**
243
+	 * initialize
244
+	 *
245
+	 * @throws OutOfBoundsException
246
+	 * @throws InvalidArgumentException
247
+	 * @throws InvalidInterfaceException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws EE_Error
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function initialize()
253
+	{
254
+		$this->_class_abbreviations = apply_filters(
255
+			'FHEE__EE_Registry____construct___class_abbreviations',
256
+			array(
257
+				'EE_Config'                                       => 'CFG',
258
+				'EE_Session'                                      => 'SSN',
259
+				'EE_Capabilities'                                 => 'CAP',
260
+				'EE_Cart'                                         => 'CART',
261
+				'EE_Network_Config'                               => 'NET_CFG',
262
+				'EE_Request_Handler'                              => 'REQ',
263
+				'EE_Message_Resource_Manager'                     => 'MRM',
264
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
265
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
266
+			)
267
+		);
268
+		$this->load_core('Base', array(), true);
269
+		// add our request and response objects to the cache
270
+		$request_loader = $this->_dependency_map->class_loader(
271
+			'EventEspresso\core\services\request\Request'
272
+		);
273
+		$this->_set_cached_class(
274
+			$request_loader(),
275
+			'EventEspresso\core\services\request\Request'
276
+		);
277
+		$response_loader = $this->_dependency_map->class_loader(
278
+			'EventEspresso\core\services\request\Response'
279
+		);
280
+		$this->_set_cached_class(
281
+			$response_loader(),
282
+			'EventEspresso\core\services\request\Response'
283
+		);
284
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return void
290
+	 */
291
+	public function init()
292
+	{
293
+		// Get current page protocol
294
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
295
+		// Output admin-ajax.php URL with same protocol as current page
296
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
297
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
298
+	}
299
+
300
+
301
+	/**
302
+	 * localize_i18n_js_strings
303
+	 *
304
+	 * @return string
305
+	 */
306
+	public static function localize_i18n_js_strings()
307
+	{
308
+		$i18n_js_strings = (array) self::$i18n_js_strings;
309
+		foreach ($i18n_js_strings as $key => $value) {
310
+			if (is_scalar($value)) {
311
+				$i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
+			}
313
+		}
314
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param mixed string | EED_Module $module
320
+	 * @throws OutOfBoundsException
321
+	 * @throws InvalidArgumentException
322
+	 * @throws InvalidInterfaceException
323
+	 * @throws InvalidDataTypeException
324
+	 * @throws EE_Error
325
+	 * @throws ReflectionException
326
+	 */
327
+	public function add_module($module)
328
+	{
329
+		if ($module instanceof EED_Module) {
330
+			$module_class = get_class($module);
331
+			$this->modules->{$module_class} = $module;
332
+		} else {
333
+			if (! class_exists('EE_Module_Request_Router', false)) {
334
+				$this->load_core('Module_Request_Router');
335
+			}
336
+			EE_Module_Request_Router::module_factory($module);
337
+		}
338
+	}
339
+
340
+
341
+	/**
342
+	 * @param string $module_name
343
+	 * @return mixed EED_Module | NULL
344
+	 */
345
+	public function get_module($module_name = '')
346
+	{
347
+		return isset($this->modules->{$module_name})
348
+			? $this->modules->{$module_name}
349
+			: null;
350
+	}
351
+
352
+
353
+	/**
354
+	 * loads core classes - must be singletons
355
+	 *
356
+	 * @param string $class_name - simple class name ie: session
357
+	 * @param mixed  $arguments
358
+	 * @param bool   $load_only
359
+	 * @return mixed
360
+	 * @throws InvalidInterfaceException
361
+	 * @throws InvalidDataTypeException
362
+	 * @throws EE_Error
363
+	 * @throws ReflectionException
364
+	 * @throws InvalidArgumentException
365
+	 */
366
+	public function load_core($class_name, $arguments = array(), $load_only = false)
367
+	{
368
+		$core_paths = apply_filters(
369
+			'FHEE__EE_Registry__load_core__core_paths',
370
+			array(
371
+				EE_CORE,
372
+				EE_ADMIN,
373
+				EE_CPTS,
374
+				EE_CORE . 'data_migration_scripts' . DS,
375
+				EE_CORE . 'capabilities' . DS,
376
+				EE_CORE . 'request_stack' . DS,
377
+				EE_CORE . 'middleware' . DS,
378
+			)
379
+		);
380
+		// retrieve instantiated class
381
+		return $this->_load(
382
+			$core_paths,
383
+			'EE_',
384
+			$class_name,
385
+			'core',
386
+			$arguments,
387
+			false,
388
+			true,
389
+			$load_only
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * loads service classes
396
+	 *
397
+	 * @param string $class_name - simple class name ie: session
398
+	 * @param mixed  $arguments
399
+	 * @param bool   $load_only
400
+	 * @return mixed
401
+	 * @throws InvalidInterfaceException
402
+	 * @throws InvalidDataTypeException
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 * @throws InvalidArgumentException
406
+	 */
407
+	public function load_service($class_name, $arguments = array(), $load_only = false)
408
+	{
409
+		$service_paths = apply_filters(
410
+			'FHEE__EE_Registry__load_service__service_paths',
411
+			array(
412
+				EE_CORE . 'services' . DS,
413
+			)
414
+		);
415
+		// retrieve instantiated class
416
+		return $this->_load(
417
+			$service_paths,
418
+			'EE_',
419
+			$class_name,
420
+			'class',
421
+			$arguments,
422
+			false,
423
+			true,
424
+			$load_only
425
+		);
426
+	}
427
+
428
+
429
+	/**
430
+	 * loads data_migration_scripts
431
+	 *
432
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
433
+	 * @param mixed  $arguments
434
+	 * @return EE_Data_Migration_Script_Base|mixed
435
+	 * @throws InvalidInterfaceException
436
+	 * @throws InvalidDataTypeException
437
+	 * @throws EE_Error
438
+	 * @throws ReflectionException
439
+	 * @throws InvalidArgumentException
440
+	 */
441
+	public function load_dms($class_name, $arguments = array())
442
+	{
443
+		// retrieve instantiated class
444
+		return $this->_load(
445
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
446
+			'EE_DMS_',
447
+			$class_name,
448
+			'dms',
449
+			$arguments,
450
+			false,
451
+			false
452
+		);
453
+	}
454
+
455
+
456
+	/**
457
+	 * loads object creating classes - must be singletons
458
+	 *
459
+	 * @param string $class_name - simple class name ie: attendee
460
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
461
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
462
+	 *                           instantiate
463
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
464
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
465
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
466
+	 *                           (default)
467
+	 * @return EE_Base_Class | bool
468
+	 * @throws InvalidInterfaceException
469
+	 * @throws InvalidDataTypeException
470
+	 * @throws EE_Error
471
+	 * @throws ReflectionException
472
+	 * @throws InvalidArgumentException
473
+	 */
474
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
475
+	{
476
+		$paths = apply_filters(
477
+			'FHEE__EE_Registry__load_class__paths',
478
+			array(
479
+				EE_CORE,
480
+				EE_CLASSES,
481
+				EE_BUSINESS,
482
+			)
483
+		);
484
+		// retrieve instantiated class
485
+		return $this->_load(
486
+			$paths,
487
+			'EE_',
488
+			$class_name,
489
+			'class',
490
+			$arguments,
491
+			$from_db,
492
+			$cache,
493
+			$load_only
494
+		);
495
+	}
496
+
497
+
498
+	/**
499
+	 * loads helper classes - must be singletons
500
+	 *
501
+	 * @param string $class_name - simple class name ie: price
502
+	 * @param mixed  $arguments
503
+	 * @param bool   $load_only
504
+	 * @return EEH_Base | bool
505
+	 * @throws InvalidInterfaceException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws EE_Error
508
+	 * @throws ReflectionException
509
+	 * @throws InvalidArgumentException
510
+	 */
511
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
512
+	{
513
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
514
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
515
+		// retrieve instantiated class
516
+		return $this->_load(
517
+			$helper_paths,
518
+			'EEH_',
519
+			$class_name,
520
+			'helper',
521
+			$arguments,
522
+			false,
523
+			true,
524
+			$load_only
525
+		);
526
+	}
527
+
528
+
529
+	/**
530
+	 * loads core classes - must be singletons
531
+	 *
532
+	 * @param string $class_name - simple class name ie: session
533
+	 * @param mixed  $arguments
534
+	 * @param bool   $load_only
535
+	 * @param bool   $cache      whether to cache the object or not.
536
+	 * @return mixed
537
+	 * @throws InvalidInterfaceException
538
+	 * @throws InvalidDataTypeException
539
+	 * @throws EE_Error
540
+	 * @throws ReflectionException
541
+	 * @throws InvalidArgumentException
542
+	 */
543
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
544
+	{
545
+		$paths = array(
546
+			EE_LIBRARIES,
547
+			EE_LIBRARIES . 'messages' . DS,
548
+			EE_LIBRARIES . 'shortcodes' . DS,
549
+			EE_LIBRARIES . 'qtips' . DS,
550
+			EE_LIBRARIES . 'payment_methods' . DS,
551
+		);
552
+		// retrieve instantiated class
553
+		return $this->_load(
554
+			$paths,
555
+			'EE_',
556
+			$class_name,
557
+			'lib',
558
+			$arguments,
559
+			false,
560
+			$cache,
561
+			$load_only
562
+		);
563
+	}
564
+
565
+
566
+	/**
567
+	 * loads model classes - must be singletons
568
+	 *
569
+	 * @param string $class_name - simple class name ie: price
570
+	 * @param mixed  $arguments
571
+	 * @param bool   $load_only
572
+	 * @return EEM_Base | bool
573
+	 * @throws InvalidInterfaceException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws EE_Error
576
+	 * @throws ReflectionException
577
+	 * @throws InvalidArgumentException
578
+	 */
579
+	public function load_model($class_name, $arguments = array(), $load_only = false)
580
+	{
581
+		$paths = apply_filters(
582
+			'FHEE__EE_Registry__load_model__paths',
583
+			array(
584
+				EE_MODELS,
585
+				EE_CORE,
586
+			)
587
+		);
588
+		// retrieve instantiated class
589
+		return $this->_load(
590
+			$paths,
591
+			'EEM_',
592
+			$class_name,
593
+			'model',
594
+			$arguments,
595
+			false,
596
+			true,
597
+			$load_only
598
+		);
599
+	}
600
+
601
+
602
+	/**
603
+	 * loads model classes - must be singletons
604
+	 *
605
+	 * @param string $class_name - simple class name ie: price
606
+	 * @param mixed  $arguments
607
+	 * @param bool   $load_only
608
+	 * @return mixed | bool
609
+	 * @throws InvalidInterfaceException
610
+	 * @throws InvalidDataTypeException
611
+	 * @throws EE_Error
612
+	 * @throws ReflectionException
613
+	 * @throws InvalidArgumentException
614
+	 */
615
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
616
+	{
617
+		$paths = array(
618
+			EE_MODELS . 'fields' . DS,
619
+			EE_MODELS . 'helpers' . DS,
620
+			EE_MODELS . 'relations' . DS,
621
+			EE_MODELS . 'strategies' . DS,
622
+		);
623
+		// retrieve instantiated class
624
+		return $this->_load(
625
+			$paths,
626
+			'EE_',
627
+			$class_name,
628
+			'',
629
+			$arguments,
630
+			false,
631
+			true,
632
+			$load_only
633
+		);
634
+	}
635
+
636
+
637
+	/**
638
+	 * Determines if $model_name is the name of an actual EE model.
639
+	 *
640
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
641
+	 * @return boolean
642
+	 */
643
+	public function is_model_name($model_name)
644
+	{
645
+		return isset($this->models[ $model_name ]);
646
+	}
647
+
648
+
649
+	/**
650
+	 * generic class loader
651
+	 *
652
+	 * @param string $path_to_file - directory path to file location, not including filename
653
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
654
+	 * @param string $type         - file type - core? class? helper? model?
655
+	 * @param mixed  $arguments
656
+	 * @param bool   $load_only
657
+	 * @return mixed
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws ReflectionException
662
+	 * @throws InvalidArgumentException
663
+	 */
664
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
665
+	{
666
+		// retrieve instantiated class
667
+		return $this->_load(
668
+			$path_to_file,
669
+			'',
670
+			$file_name,
671
+			$type,
672
+			$arguments,
673
+			false,
674
+			true,
675
+			$load_only
676
+		);
677
+	}
678
+
679
+
680
+	/**
681
+	 * @param string $path_to_file - directory path to file location, not including filename
682
+	 * @param string $class_name   - full class name  ie:  My_Class
683
+	 * @param string $type         - file type - core? class? helper? model?
684
+	 * @param mixed  $arguments
685
+	 * @param bool   $load_only
686
+	 * @return bool|EE_Addon|object
687
+	 * @throws InvalidInterfaceException
688
+	 * @throws InvalidDataTypeException
689
+	 * @throws EE_Error
690
+	 * @throws ReflectionException
691
+	 * @throws InvalidArgumentException
692
+	 */
693
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
694
+	{
695
+		// retrieve instantiated class
696
+		return $this->_load(
697
+			$path_to_file,
698
+			'addon',
699
+			$class_name,
700
+			$type,
701
+			$arguments,
702
+			false,
703
+			true,
704
+			$load_only
705
+		);
706
+	}
707
+
708
+
709
+	/**
710
+	 * instantiates, caches, and automatically resolves dependencies
711
+	 * for classes that use a Fully Qualified Class Name.
712
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
713
+	 * then you need to use one of the existing load_*() methods
714
+	 * which can resolve the classname and filepath from the passed arguments
715
+	 *
716
+	 * @param bool|string $class_name   Fully Qualified Class Name
717
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
718
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
719
+	 * @param bool        $from_db      some classes are instantiated from the db
720
+	 *                                  and thus call a different method to instantiate
721
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
722
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
723
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
724
+	 *                                  object = class loaded and instantiated successfully.
725
+	 *                                  bool = fail or success when $load_only is true
726
+	 * @throws InvalidInterfaceException
727
+	 * @throws InvalidDataTypeException
728
+	 * @throws EE_Error
729
+	 * @throws ReflectionException
730
+	 * @throws InvalidArgumentException
731
+	 */
732
+	public function create(
733
+		$class_name = false,
734
+		$arguments = array(),
735
+		$cache = false,
736
+		$from_db = false,
737
+		$load_only = false,
738
+		$addon = false
739
+	) {
740
+		$class_name = ltrim($class_name, '\\');
741
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
742
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
743
+		// if a non-FQCN was passed, then
744
+		// verifyClassExists() might return an object
745
+		// or it could return null if the class just could not be found anywhere
746
+		if ($class_exists instanceof $class_name || $class_exists === null) {
747
+			// either way, return the results
748
+			return $class_exists;
749
+		}
750
+		$class_name = $class_exists;
751
+		// if we're only loading the class and it already exists, then let's just return true immediately
752
+		if ($load_only) {
753
+			return true;
754
+		}
755
+		$addon = $addon ? 'addon' : '';
756
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
757
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
758
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
759
+		if ($this->_cache_on && $cache && ! $load_only) {
760
+			// return object if it's already cached
761
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
762
+			if ($cached_class !== null) {
763
+				return $cached_class;
764
+			}
765
+		}// obtain the loader method from the dependency map
766
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
767
+		if ($loader instanceof Closure) {
768
+			$class_obj = $loader($arguments);
769
+		} else {
770
+			if ($loader && method_exists($this, $loader)) {
771
+				$class_obj = $this->{$loader}($class_name, $arguments);
772
+			} else {
773
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
774
+			}
775
+		}
776
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
777
+			// save it for later... kinda like gum  { : $
778
+			$this->_set_cached_class(
779
+				$class_obj,
780
+				$class_name,
781
+				$addon,
782
+				$from_db,
783
+				$arguments
784
+			);
785
+		}
786
+		$this->_cache_on = true;
787
+		return $class_obj;
788
+	}
789
+
790
+
791
+	/**
792
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
793
+	 *
794
+	 * @param string|object $class_name
795
+	 * @param array         $arguments
796
+	 * @param int           $attempt
797
+	 * @return mixed
798
+	 */
799
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
800
+	{
801
+		if (is_object($class_name) || class_exists($class_name)) {
802
+			return $class_name;
803
+		}
804
+		switch ($attempt) {
805
+			case 1:
806
+				// if it's a FQCN then maybe the class is registered with a preceding \
807
+				$class_name = strpos($class_name, '\\') !== false
808
+					? '\\' . ltrim($class_name, '\\')
809
+					: $class_name;
810
+				break;
811
+			case 2:
812
+				//
813
+				$loader = $this->_dependency_map->class_loader($class_name);
814
+				if ($loader && method_exists($this, $loader)) {
815
+					return $this->{$loader}($class_name, $arguments);
816
+				}
817
+				break;
818
+			case 3:
819
+			default:
820
+				return null;
821
+		}
822
+		$attempt++;
823
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
824
+	}
825
+
826
+
827
+	/**
828
+	 * instantiates, caches, and injects dependencies for classes
829
+	 *
830
+	 * @param array       $file_paths   an array of paths to folders to look in
831
+	 * @param string      $class_prefix EE  or EEM or... ???
832
+	 * @param bool|string $class_name   $class name
833
+	 * @param string      $type         file type - core? class? helper? model?
834
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
835
+	 * @param bool        $from_db      some classes are instantiated from the db
836
+	 *                                  and thus call a different method to instantiate
837
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
838
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
839
+	 * @return bool|null|object null = failure to load or instantiate class object.
840
+	 *                                  object = class loaded and instantiated successfully.
841
+	 *                                  bool = fail or success when $load_only is true
842
+	 * @throws EE_Error
843
+	 * @throws ReflectionException
844
+	 * @throws InvalidInterfaceException
845
+	 * @throws InvalidDataTypeException
846
+	 * @throws InvalidArgumentException
847
+	 */
848
+	protected function _load(
849
+		$file_paths = array(),
850
+		$class_prefix = 'EE_',
851
+		$class_name = false,
852
+		$type = 'class',
853
+		$arguments = array(),
854
+		$from_db = false,
855
+		$cache = true,
856
+		$load_only = false
857
+	) {
858
+		$class_name = ltrim($class_name, '\\');
859
+		// strip php file extension
860
+		$class_name = str_replace('.php', '', trim($class_name));
861
+		// does the class have a prefix ?
862
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
863
+			// make sure $class_prefix is uppercase
864
+			$class_prefix = strtoupper(trim($class_prefix));
865
+			// add class prefix ONCE!!!
866
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
867
+		}
868
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
869
+		$class_exists = class_exists($class_name, false);
870
+		// if we're only loading the class and it already exists, then let's just return true immediately
871
+		if ($load_only && $class_exists) {
872
+			return true;
873
+		}
874
+		$arguments = is_array($arguments) ? $arguments : array($arguments);
875
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
876
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
877
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
878
+		if ($this->_cache_on && $cache && ! $load_only) {
879
+			// return object if it's already cached
880
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
881
+			if ($cached_class !== null) {
882
+				return $cached_class;
883
+			}
884
+		}
885
+		// if the class doesn't already exist.. then we need to try and find the file and load it
886
+		if (! $class_exists) {
887
+			// get full path to file
888
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
889
+			// load the file
890
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
891
+			// if we are only loading a file but NOT instantiating an object
892
+			// then return boolean for whether class was loaded or not
893
+			if ($load_only) {
894
+				return $loaded;
895
+			}
896
+			// if an object was expected but loading failed, then return nothing
897
+			if (! $loaded) {
898
+				return null;
899
+			}
900
+		}
901
+		// instantiate the requested object
902
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
903
+		if ($this->_cache_on && $cache) {
904
+			// save it for later... kinda like gum  { : $
905
+			$this->_set_cached_class(
906
+				$class_obj,
907
+				$class_name,
908
+				$class_prefix,
909
+				$from_db,
910
+				$arguments
911
+			);
912
+		}
913
+		$this->_cache_on = true;
914
+		return $class_obj;
915
+	}
916
+
917
+
918
+	/**
919
+	 * @param string $class_name
920
+	 * @param string $default have to specify something, but not anything that will conflict
921
+	 * @return mixed|string
922
+	 */
923
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
924
+	{
925
+		return isset($this->_class_abbreviations[ $class_name ])
926
+			? $this->_class_abbreviations[ $class_name ]
927
+			: $default;
928
+	}
929
+
930
+
931
+	/**
932
+	 * attempts to find a cached version of the requested class
933
+	 * by looking in the following places:
934
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
935
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
936
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
937
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
938
+	 *
939
+	 * @param string $class_name
940
+	 * @param string $class_prefix
941
+	 * @param array  $arguments
942
+	 * @return mixed
943
+	 */
944
+	protected function _get_cached_class(
945
+		$class_name,
946
+		$class_prefix = '',
947
+		$arguments = array()
948
+	) {
949
+		if ($class_name === 'EE_Registry') {
950
+			return $this;
951
+		}
952
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
953
+		// check if class has already been loaded, and return it if it has been
954
+		if (isset($this->{$class_abbreviation})) {
955
+			return $this->{$class_abbreviation};
956
+		}
957
+		$class_name = str_replace('\\', '_', $class_name);
958
+		if (isset($this->{$class_name})) {
959
+			return $this->{$class_name};
960
+		}
961
+		if ($class_prefix === 'addon' && isset($this->addons->{$class_name})) {
962
+			return $this->addons->{$class_name};
963
+		}
964
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
965
+		if (isset($this->LIB->{$object_identifier})) {
966
+			return $this->LIB->{$object_identifier};
967
+		}
968
+		foreach ($this->LIB as $key => $object) {
969
+			if (// request does not contain new arguments and therefore no args identifier
970
+				! $this->object_identifier->hasArguments($object_identifier)
971
+				// but previously cached class with args was found
972
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
973
+			) {
974
+				return $object;
975
+			}
976
+		}
977
+		return null;
978
+	}
979
+
980
+
981
+	/**
982
+	 * removes a cached version of the requested class
983
+	 *
984
+	 * @param string  $class_name
985
+	 * @param boolean $addon
986
+	 * @param array   $arguments
987
+	 * @return boolean
988
+	 */
989
+	public function clear_cached_class(
990
+		$class_name,
991
+		$addon = false,
992
+		$arguments = array()
993
+	) {
994
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
995
+		// check if class has already been loaded, and return it if it has been
996
+		if (isset($this->{$class_abbreviation})) {
997
+			$this->{$class_abbreviation} = null;
998
+			return true;
999
+		}
1000
+		$class_name = str_replace('\\', '_', $class_name);
1001
+		if (isset($this->{$class_name})) {
1002
+			$this->{$class_name} = null;
1003
+			return true;
1004
+		}
1005
+		if ($addon && isset($this->addons->{$class_name})) {
1006
+			unset($this->addons->{$class_name});
1007
+			return true;
1008
+		}
1009
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1010
+		if (isset($this->LIB->{$class_name})) {
1011
+			unset($this->LIB->{$class_name});
1012
+			return true;
1013
+		}
1014
+		return false;
1015
+	}
1016
+
1017
+
1018
+	/**
1019
+	 * _set_cached_class
1020
+	 * attempts to cache the instantiated class locally
1021
+	 * in one of the following places, in the following order:
1022
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1023
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1024
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1025
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1026
+	 *
1027
+	 * @param object $class_obj
1028
+	 * @param string $class_name
1029
+	 * @param string $class_prefix
1030
+	 * @param bool   $from_db
1031
+	 * @param array  $arguments
1032
+	 * @return void
1033
+	 */
1034
+	protected function _set_cached_class(
1035
+		$class_obj,
1036
+		$class_name,
1037
+		$class_prefix = '',
1038
+		$from_db = false,
1039
+		$arguments = array()
1040
+	) {
1041
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1042
+			return;
1043
+		}
1044
+		// return newly instantiated class
1045
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1046
+		if ($class_abbreviation) {
1047
+			$this->{$class_abbreviation} = $class_obj;
1048
+			return;
1049
+		}
1050
+		$class_name = str_replace('\\', '_', $class_name);
1051
+		if (property_exists($this, $class_name)) {
1052
+			$this->{$class_name} = $class_obj;
1053
+			return;
1054
+		}
1055
+		if ($class_prefix === 'addon') {
1056
+			$this->addons->{$class_name} = $class_obj;
1057
+			return;
1058
+		}
1059
+		if (! $from_db) {
1060
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1061
+			$this->LIB->{$class_name} = $class_obj;
1062
+		}
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * attempts to find a full valid filepath for the requested class.
1068
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1069
+	 * then returns that path if the target file has been found and is readable
1070
+	 *
1071
+	 * @param string $class_name
1072
+	 * @param string $type
1073
+	 * @param array  $file_paths
1074
+	 * @return string | bool
1075
+	 */
1076
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
1077
+	{
1078
+		// make sure $file_paths is an array
1079
+		$file_paths = is_array($file_paths)
1080
+			? $file_paths
1081
+			: array($file_paths);
1082
+		// cycle thru paths
1083
+		foreach ($file_paths as $key => $file_path) {
1084
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
1085
+			$file_path = $file_path
1086
+				? str_replace(array('/', '\\'), DS, $file_path)
1087
+				: EE_CLASSES;
1088
+			// prep file type
1089
+			$type = ! empty($type)
1090
+				? trim($type, '.') . '.'
1091
+				: '';
1092
+			// build full file path
1093
+			$file_paths[ $key ] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
1094
+			// does the file exist and can be read ?
1095
+			if (is_readable($file_paths[ $key ])) {
1096
+				return $file_paths[ $key ];
1097
+			}
1098
+		}
1099
+		return false;
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * basically just performs a require_once()
1105
+	 * but with some error handling
1106
+	 *
1107
+	 * @param  string $path
1108
+	 * @param  string $class_name
1109
+	 * @param  string $type
1110
+	 * @param  array  $file_paths
1111
+	 * @return bool
1112
+	 * @throws EE_Error
1113
+	 * @throws ReflectionException
1114
+	 */
1115
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1116
+	{
1117
+		$this->resolve_legacy_class_parent($class_name);
1118
+		// don't give up! you gotta...
1119
+		try {
1120
+			// does the file exist and can it be read ?
1121
+			if (! $path) {
1122
+				// just in case the file has already been autoloaded,
1123
+				// but discrepancies in the naming schema are preventing it from
1124
+				// being loaded via one of the EE_Registry::load_*() methods,
1125
+				// then let's try one last hail mary before throwing an exception
1126
+				// and call class_exists() again, but with autoloading turned ON
1127
+				if (class_exists($class_name)) {
1128
+					return true;
1129
+				}
1130
+				// so sorry, can't find the file
1131
+				throw new EE_Error(
1132
+					sprintf(
1133
+						esc_html__(
1134
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1135
+							'event_espresso'
1136
+						),
1137
+						trim($type, '.'),
1138
+						$class_name,
1139
+						'<br />' . implode(',<br />', $file_paths)
1140
+					)
1141
+				);
1142
+			}
1143
+			// get the file
1144
+			require_once($path);
1145
+			// if the class isn't already declared somewhere
1146
+			if (class_exists($class_name, false) === false) {
1147
+				// so sorry, not a class
1148
+				throw new EE_Error(
1149
+					sprintf(
1150
+						esc_html__(
1151
+							'The %s file %s does not appear to contain the %s Class.',
1152
+							'event_espresso'
1153
+						),
1154
+						$type,
1155
+						$path,
1156
+						$class_name
1157
+					)
1158
+				);
1159
+			}
1160
+		} catch (EE_Error $e) {
1161
+			$e->get_error();
1162
+			return false;
1163
+		}
1164
+		return true;
1165
+	}
1166
+
1167
+
1168
+	/**
1169
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1170
+	 * before their class declaration in order to ensure that the parent class was loaded.
1171
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1172
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1173
+	 *
1174
+	 * @param string $class_name
1175
+	 */
1176
+	protected function resolve_legacy_class_parent($class_name = '')
1177
+	{
1178
+		try {
1179
+			$legacy_parent_class_map = array(
1180
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1181
+			);
1182
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1183
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1184
+			}
1185
+		} catch (Exception $exception) {
1186
+		}
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * _create_object
1192
+	 * Attempts to instantiate the requested class via any of the
1193
+	 * commonly used instantiation methods employed throughout EE.
1194
+	 * The priority for instantiation is as follows:
1195
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1196
+	 *        - model objects via their 'new_instance_from_db' method
1197
+	 *        - model objects via their 'new_instance' method
1198
+	 *        - "singleton" classes" via their 'instance' method
1199
+	 *    - standard instantiable classes via their __constructor
1200
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1201
+	 * then the constructor for the requested class will be examined to determine
1202
+	 * if any dependencies exist, and if they can be injected.
1203
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1204
+	 *
1205
+	 * @param string $class_name
1206
+	 * @param array  $arguments
1207
+	 * @param string $type
1208
+	 * @param bool   $from_db
1209
+	 * @return null|object|bool
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws InvalidInterfaceException
1212
+	 * @throws EE_Error
1213
+	 * @throws ReflectionException
1214
+	 * @throws InvalidDataTypeException
1215
+	 */
1216
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1217
+	{
1218
+		// create reflection
1219
+		$reflector = $this->mirror->getReflectionClass($class_name);
1220
+		// make sure arguments are an array
1221
+		$arguments = is_array($arguments)
1222
+			? $arguments
1223
+			: array($arguments);
1224
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1225
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1226
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1227
+			? $arguments
1228
+			: array($arguments);
1229
+		// attempt to inject dependencies ?
1230
+		if ($this->_dependency_map->has($class_name)) {
1231
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1232
+		}
1233
+		// instantiate the class if possible
1234
+		if ($reflector->isAbstract()) {
1235
+			// nothing to instantiate, loading file was enough
1236
+			// does not throw an exception so $instantiation_mode is unused
1237
+			// $instantiation_mode = "1) no constructor abstract class";
1238
+			return true;
1239
+		}
1240
+		if (empty($arguments)
1241
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1242
+			&& $reflector->isInstantiable()
1243
+		) {
1244
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1245
+			// $instantiation_mode = "2) no constructor but instantiable";
1246
+			return $reflector->newInstance();
1247
+		}
1248
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1249
+			// $instantiation_mode = "3) new_instance_from_db()";
1250
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1251
+		}
1252
+		if (method_exists($class_name, 'new_instance')) {
1253
+			// $instantiation_mode = "4) new_instance()";
1254
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1255
+		}
1256
+		if (method_exists($class_name, 'instance')) {
1257
+			// $instantiation_mode = "5) instance()";
1258
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1259
+		}
1260
+		if ($reflector->isInstantiable()) {
1261
+			// $instantiation_mode = "6) constructor";
1262
+			return $reflector->newInstanceArgs($arguments);
1263
+		}
1264
+		// heh ? something's not right !
1265
+		throw new EE_Error(
1266
+			sprintf(
1267
+				__('The %s file %s could not be instantiated.', 'event_espresso'),
1268
+				$type,
1269
+				$class_name
1270
+			)
1271
+		);
1272
+	}
1273
+
1274
+
1275
+	/**
1276
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1277
+	 * @param array $array
1278
+	 * @return bool
1279
+	 */
1280
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1281
+	{
1282
+		return ! empty($array)
1283
+			? array_keys($array) === range(0, count($array) - 1)
1284
+			: true;
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * _resolve_dependencies
1290
+	 * examines the constructor for the requested class to determine
1291
+	 * if any dependencies exist, and if they can be injected.
1292
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1293
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1294
+	 * For example:
1295
+	 *        if attempting to load a class "Foo" with the following constructor:
1296
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1297
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1298
+	 *        but only IF they are NOT already present in the incoming arguments array,
1299
+	 *        and the correct classes can be loaded
1300
+	 *
1301
+	 * @param ReflectionClass $reflector
1302
+	 * @param string          $class_name
1303
+	 * @param array           $arguments
1304
+	 * @return array
1305
+	 * @throws InvalidArgumentException
1306
+	 * @throws InvalidDataTypeException
1307
+	 * @throws InvalidInterfaceException
1308
+	 * @throws ReflectionException
1309
+	 */
1310
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1311
+	{
1312
+		// let's examine the constructor
1313
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1314
+		// whu? huh? nothing?
1315
+		if (! $constructor) {
1316
+			return $arguments;
1317
+		}
1318
+		// get constructor parameters
1319
+		$params = $this->mirror->getParametersFromReflection($reflector);
1320
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1321
+		$argument_keys = array_keys($arguments);
1322
+		// now loop thru all of the constructors expected parameters
1323
+		foreach ($params as $index => $param) {
1324
+			// is this a dependency for a specific class ?
1325
+			$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1326
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1327
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1328
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1329
+				: $param_class;
1330
+			if (// param is not even a class
1331
+				$param_class === null
1332
+				// and something already exists in the incoming arguments for this param
1333
+				&& array_key_exists($index, $argument_keys)
1334
+				&& array_key_exists($argument_keys[ $index ], $arguments)
1335
+			) {
1336
+				// so let's skip this argument and move on to the next
1337
+				continue;
1338
+			}
1339
+			if (// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1340
+				$param_class !== null
1341
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1342
+				&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1343
+			) {
1344
+				// skip this argument and move on to the next
1345
+				continue;
1346
+			}
1347
+			if (// parameter is type hinted as a class, and should be injected
1348
+				$param_class !== null
1349
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1350
+			) {
1351
+				$arguments = $this->_resolve_dependency(
1352
+					$class_name,
1353
+					$param_class,
1354
+					$arguments,
1355
+					$index
1356
+				);
1357
+			} else {
1358
+				$arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1359
+					$param,
1360
+					$class_name,
1361
+					$index
1362
+				);
1363
+			}
1364
+		}
1365
+		return $arguments;
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * @param string $class_name
1371
+	 * @param string $param_class
1372
+	 * @param array  $arguments
1373
+	 * @param mixed  $index
1374
+	 * @return array
1375
+	 * @throws InvalidArgumentException
1376
+	 * @throws InvalidInterfaceException
1377
+	 * @throws InvalidDataTypeException
1378
+	 */
1379
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1380
+	{
1381
+		$dependency = null;
1382
+		// should dependency be loaded from cache ?
1383
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1384
+			$class_name,
1385
+			$param_class
1386
+		);
1387
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1388
+		// we might have a dependency...
1389
+		// let's MAYBE try and find it in our cache if that's what's been requested
1390
+		$cached_class = $cache_on
1391
+			? $this->_get_cached_class($param_class)
1392
+			: null;
1393
+		// and grab it if it exists
1394
+		if ($cached_class instanceof $param_class) {
1395
+			$dependency = $cached_class;
1396
+		} elseif ($param_class !== $class_name) {
1397
+			// obtain the loader method from the dependency map
1398
+			$loader = $this->_dependency_map->class_loader($param_class);
1399
+			// is loader a custom closure ?
1400
+			if ($loader instanceof Closure) {
1401
+				$dependency = $loader($arguments);
1402
+			} else {
1403
+				// set the cache on property for the recursive loading call
1404
+				$this->_cache_on = $cache_on;
1405
+				// if not, then let's try and load it via the registry
1406
+				if ($loader && method_exists($this, $loader)) {
1407
+					$dependency = $this->{$loader}($param_class);
1408
+				} else {
1409
+					$dependency = LoaderFactory::getLoader()->load(
1410
+						$param_class,
1411
+						array(),
1412
+						$cache_on
1413
+					);
1414
+				}
1415
+			}
1416
+		}
1417
+		// did we successfully find the correct dependency ?
1418
+		if ($dependency instanceof $param_class) {
1419
+			// then let's inject it into the incoming array of arguments at the correct location
1420
+			$arguments[ $index ] = $dependency;
1421
+		}
1422
+		return $arguments;
1423
+	}
1424
+
1425
+
1426
+	/**
1427
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1428
+	 *
1429
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1430
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1431
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1432
+	 * @param array  $arguments
1433
+	 * @return object
1434
+	 */
1435
+	public static function factory($classname, $arguments = array())
1436
+	{
1437
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1438
+		if ($loader instanceof Closure) {
1439
+			return $loader($arguments);
1440
+		}
1441
+		if (method_exists(self::instance(), $loader)) {
1442
+			return self::instance()->{$loader}($classname, $arguments);
1443
+		}
1444
+		return null;
1445
+	}
1446
+
1447
+
1448
+	/**
1449
+	 * Gets the addon by its class name
1450
+	 *
1451
+	 * @param string $class_name
1452
+	 * @return EE_Addon
1453
+	 */
1454
+	public function getAddon($class_name)
1455
+	{
1456
+		$class_name = str_replace('\\', '_', $class_name);
1457
+		return $this->addons->{$class_name};
1458
+	}
1459
+
1460
+
1461
+	/**
1462
+	 * removes the addon from the internal cache
1463
+	 *
1464
+	 * @param string $class_name
1465
+	 * @return void
1466
+	 */
1467
+	public function removeAddon($class_name)
1468
+	{
1469
+		$class_name = str_replace('\\', '_', $class_name);
1470
+		unset($this->addons->{$class_name});
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * Gets the addon by its name/slug (not classname. For that, just
1476
+	 * use the get_addon() method above
1477
+	 *
1478
+	 * @param string $name
1479
+	 * @return EE_Addon
1480
+	 */
1481
+	public function get_addon_by_name($name)
1482
+	{
1483
+		foreach ($this->addons as $addon) {
1484
+			if ($addon->name() === $name) {
1485
+				return $addon;
1486
+			}
1487
+		}
1488
+		return null;
1489
+	}
1490
+
1491
+
1492
+	/**
1493
+	 * Gets an array of all the registered addons, where the keys are their names.
1494
+	 * (ie, what each returns for their name() function)
1495
+	 * They're already available on EE_Registry::instance()->addons as properties,
1496
+	 * where each property's name is the addon's classname,
1497
+	 * So if you just want to get the addon by classname,
1498
+	 * OR use the get_addon() method above.
1499
+	 * PLEASE  NOTE:
1500
+	 * addons with Fully Qualified Class Names
1501
+	 * have had the namespace separators converted to underscores,
1502
+	 * so a classname like Fully\Qualified\ClassName
1503
+	 * would have been converted to Fully_Qualified_ClassName
1504
+	 *
1505
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1506
+	 */
1507
+	public function get_addons_by_name()
1508
+	{
1509
+		$addons = array();
1510
+		foreach ($this->addons as $addon) {
1511
+			$addons[ $addon->name() ] = $addon;
1512
+		}
1513
+		return $addons;
1514
+	}
1515
+
1516
+
1517
+	/**
1518
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1519
+	 * a stale copy of it around
1520
+	 *
1521
+	 * @param string $model_name
1522
+	 * @return \EEM_Base
1523
+	 * @throws \EE_Error
1524
+	 */
1525
+	public function reset_model($model_name)
1526
+	{
1527
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1528
+			? "EEM_{$model_name}"
1529
+			: $model_name;
1530
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1531
+			return null;
1532
+		}
1533
+		// get that model reset it and make sure we nuke the old reference to it
1534
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1535
+			&& is_callable(
1536
+				array($model_class_name, 'reset')
1537
+			)) {
1538
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1539
+		} else {
1540
+			throw new EE_Error(
1541
+				sprintf(
1542
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1543
+					$model_name
1544
+				)
1545
+			);
1546
+		}
1547
+		return $this->LIB->{$model_class_name};
1548
+	}
1549
+
1550
+
1551
+	/**
1552
+	 * Resets the registry.
1553
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1554
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1555
+	 * - $_dependency_map
1556
+	 * - $_class_abbreviations
1557
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1558
+	 * - $REQ:  Still on the same request so no need to change.
1559
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1560
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1561
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1562
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1563
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1564
+	 *             switch or on the restore.
1565
+	 * - $modules
1566
+	 * - $shortcodes
1567
+	 * - $widgets
1568
+	 *
1569
+	 * @param boolean $hard             [deprecated]
1570
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1571
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1572
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1573
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1574
+	 *                                  client
1575
+	 *                                  code instead can just change the model context to a different blog id if
1576
+	 *                                  necessary
1577
+	 * @return EE_Registry
1578
+	 * @throws InvalidInterfaceException
1579
+	 * @throws InvalidDataTypeException
1580
+	 * @throws EE_Error
1581
+	 * @throws ReflectionException
1582
+	 * @throws InvalidArgumentException
1583
+	 */
1584
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1585
+	{
1586
+		$instance = self::instance();
1587
+		$instance->_cache_on = true;
1588
+		// reset some "special" classes
1589
+		EEH_Activation::reset();
1590
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1591
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1592
+		$instance->CART = null;
1593
+		$instance->MRM = null;
1594
+		$instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1595
+			'EventEspresso\core\services\assets\Registry'
1596
+		);
1597
+		// messages reset
1598
+		EED_Messages::reset();
1599
+		// handle of objects cached on LIB
1600
+		foreach (array('LIB', 'modules') as $cache) {
1601
+			foreach ($instance->{$cache} as $class_name => $class) {
1602
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1603
+					unset($instance->{$cache}->{$class_name});
1604
+				}
1605
+			}
1606
+		}
1607
+		return $instance;
1608
+	}
1609
+
1610
+
1611
+	/**
1612
+	 * if passed object implements ResettableInterface, then call it's reset() method
1613
+	 * if passed object implements InterminableInterface, then return false,
1614
+	 * to indicate that it should NOT be cleared from the Registry cache
1615
+	 *
1616
+	 * @param      $object
1617
+	 * @param bool $reset_models
1618
+	 * @return bool returns true if cached object should be unset
1619
+	 */
1620
+	private static function _reset_and_unset_object($object, $reset_models)
1621
+	{
1622
+		if (! is_object($object)) {
1623
+			// don't unset anything that's not an object
1624
+			return false;
1625
+		}
1626
+		if ($object instanceof EED_Module) {
1627
+			$object::reset();
1628
+			// don't unset modules
1629
+			return false;
1630
+		}
1631
+		if ($object instanceof ResettableInterface) {
1632
+			if ($object instanceof EEM_Base) {
1633
+				if ($reset_models) {
1634
+					$object->reset();
1635
+					return true;
1636
+				}
1637
+				return false;
1638
+			}
1639
+			$object->reset();
1640
+			return true;
1641
+		}
1642
+		if (! $object instanceof InterminableInterface) {
1643
+			return true;
1644
+		}
1645
+		return false;
1646
+	}
1647
+
1648
+
1649
+	/**
1650
+	 * Gets all the custom post type models defined
1651
+	 *
1652
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1653
+	 */
1654
+	public function cpt_models()
1655
+	{
1656
+		$cpt_models = array();
1657
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1658
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1659
+				$cpt_models[ $short_name ] = $classname;
1660
+			}
1661
+		}
1662
+		return $cpt_models;
1663
+	}
1664
+
1665
+
1666
+	/**
1667
+	 * @return \EE_Config
1668
+	 */
1669
+	public static function CFG()
1670
+	{
1671
+		return self::instance()->CFG;
1672
+	}
1673
+
1674
+
1675
+	/**
1676
+	 * @deprecated 4.9.62.p
1677
+	 * @param string $class_name
1678
+	 * @return ReflectionClass
1679
+	 * @throws ReflectionException
1680
+	 * @throws InvalidDataTypeException
1681
+	 */
1682
+	public function get_ReflectionClass($class_name)
1683
+	{
1684
+		return $this->mirror->getReflectionClass($class_name);
1685
+	}
1686 1686
 }
Please login to merge, or discard this patch.
core/services/assets/AssetManagerInterface.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -20,85 +20,85 @@
 block discarded – undo
20 20
 interface AssetManagerInterface
21 21
 {
22 22
 
23
-    /**
24
-     * @since 4.9.62.p
25
-     */
26
-    public function addAssets();
27
-
28
-
29
-    /**
30
-     * @return ManifestFile
31
-     * @throws DuplicateCollectionIdentifierException
32
-     * @throws InvalidDataTypeException
33
-     * @throws InvalidEntityException
34
-     * @since 4.9.62.p
35
-     */
36
-    public function addManifestFile();
37
-
38
-
39
-    /**
40
-     * @return ManifestFile[]
41
-     * @since 4.9.62.p
42
-     */
43
-    public function getManifestFile();
44
-
45
-
46
-    /**
47
-     * @param string $handle
48
-     * @param string $source
49
-     * @param array  $dependencies
50
-     * @param bool   $load_in_footer
51
-     * @return JavascriptAsset
52
-     * @throws DuplicateCollectionIdentifierException
53
-     * @throws InvalidDataTypeException
54
-     * @throws InvalidEntityException
55
-     * @since 4.9.62.p
56
-     */
57
-    public function addJavascript(
58
-        $handle,
59
-        $source,
60
-        array $dependencies = array(),
61
-        $load_in_footer = true
62
-    );
63
-
64
-
65
-    /**
66
-     * @return JavascriptAsset[]
67
-     * @since 4.9.62.p
68
-     */
69
-    public function getJavascriptAssets();
70
-
71
-
72
-    /**
73
-     * @param string $handle
74
-     * @param string $source
75
-     * @param array  $dependencies
76
-     * @param string $media
77
-     * @return StylesheetAsset
78
-     * @throws DuplicateCollectionIdentifierException
79
-     * @throws InvalidDataTypeException
80
-     * @throws InvalidEntityException
81
-     * @since 4.9.62.p
82
-     */
83
-    public function addStylesheet(
84
-        $handle,
85
-        $source,
86
-        array $dependencies = array(),
87
-        $media = 'all'
88
-    );
89
-
90
-
91
-    /**
92
-     * @return StylesheetAsset[]
93
-     * @since 4.9.62.p
94
-     */
95
-    public function getStylesheetAssets();
96
-
97
-
98
-    /**
99
-     * @param string $handle
100
-     * @return bool
101
-     * @since 4.9.62.p
102
-     */
103
-    public function enqueueAsset($handle);
23
+	/**
24
+	 * @since 4.9.62.p
25
+	 */
26
+	public function addAssets();
27
+
28
+
29
+	/**
30
+	 * @return ManifestFile
31
+	 * @throws DuplicateCollectionIdentifierException
32
+	 * @throws InvalidDataTypeException
33
+	 * @throws InvalidEntityException
34
+	 * @since 4.9.62.p
35
+	 */
36
+	public function addManifestFile();
37
+
38
+
39
+	/**
40
+	 * @return ManifestFile[]
41
+	 * @since 4.9.62.p
42
+	 */
43
+	public function getManifestFile();
44
+
45
+
46
+	/**
47
+	 * @param string $handle
48
+	 * @param string $source
49
+	 * @param array  $dependencies
50
+	 * @param bool   $load_in_footer
51
+	 * @return JavascriptAsset
52
+	 * @throws DuplicateCollectionIdentifierException
53
+	 * @throws InvalidDataTypeException
54
+	 * @throws InvalidEntityException
55
+	 * @since 4.9.62.p
56
+	 */
57
+	public function addJavascript(
58
+		$handle,
59
+		$source,
60
+		array $dependencies = array(),
61
+		$load_in_footer = true
62
+	);
63
+
64
+
65
+	/**
66
+	 * @return JavascriptAsset[]
67
+	 * @since 4.9.62.p
68
+	 */
69
+	public function getJavascriptAssets();
70
+
71
+
72
+	/**
73
+	 * @param string $handle
74
+	 * @param string $source
75
+	 * @param array  $dependencies
76
+	 * @param string $media
77
+	 * @return StylesheetAsset
78
+	 * @throws DuplicateCollectionIdentifierException
79
+	 * @throws InvalidDataTypeException
80
+	 * @throws InvalidEntityException
81
+	 * @since 4.9.62.p
82
+	 */
83
+	public function addStylesheet(
84
+		$handle,
85
+		$source,
86
+		array $dependencies = array(),
87
+		$media = 'all'
88
+	);
89
+
90
+
91
+	/**
92
+	 * @return StylesheetAsset[]
93
+	 * @since 4.9.62.p
94
+	 */
95
+	public function getStylesheetAssets();
96
+
97
+
98
+	/**
99
+	 * @param string $handle
100
+	 * @return bool
101
+	 * @since 4.9.62.p
102
+	 */
103
+	public function enqueueAsset($handle);
104 104
 }
Please login to merge, or discard this patch.
core/services/assets/AssetManager.php 1 patch
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -21,161 +21,161 @@
 block discarded – undo
21 21
 abstract class AssetManager implements AssetManagerInterface
22 22
 {
23 23
 
24
-    /**
25
-     * @var AssetCollection $assets
26
-     */
27
-    protected $assets;
28
-
29
-    /**
30
-     * @var DomainInterface
31
-     */
32
-    protected $domain;
33
-
34
-    /**
35
-     * @var Registry $registry
36
-     */
37
-    protected $registry;
38
-
39
-
40
-    /**
41
-     * AssetRegister constructor.
42
-     *
43
-     * @param DomainInterface $domain
44
-     * @param AssetCollection $assets
45
-     * @param Registry        $registry
46
-     */
47
-    public function __construct(DomainInterface $domain, AssetCollection $assets, Registry $registry)
48
-    {
49
-        $this->domain = $domain;
50
-        $this->assets = $assets;
51
-        $this->registry = $registry;
52
-        add_action('wp_enqueue_scripts', array($this, 'addManifestFile'), 0);
53
-        add_action('admin_enqueue_scripts', array($this, 'addManifestFile'), 0);
54
-        add_action('wp_enqueue_scripts', array($this, 'addAssets'), 2);
55
-        add_action('admin_enqueue_scripts', array($this, 'addAssets'), 2);
56
-    }
57
-
58
-
59
-    /**
60
-     * @return void
61
-     * @throws DuplicateCollectionIdentifierException
62
-     * @throws InvalidDataTypeException
63
-     * @throws InvalidEntityException
64
-     * @since 4.9.62.p
65
-     */
66
-    public function addManifestFile()
67
-    {
68
-        // if a manifest file has already been added for this domain, then just return that one
69
-        if ($this->assets->has($this->domain->assetNamespace())) {
70
-            return;
71
-        }
72
-        $asset = new ManifestFile($this->domain);
73
-        $this->assets->add($asset, $this->domain->assetNamespace());
74
-    }
75
-
76
-
77
-    /**
78
-     * @return ManifestFile[]
79
-     * @since 4.9.62.p
80
-     */
81
-    public function getManifestFile()
82
-    {
83
-        return $this->assets->getManifestFiles();
84
-    }
85
-
86
-
87
-    /**
88
-     * @param string $handle
89
-     * @param string $source
90
-     * @param array  $dependencies
91
-     * @param bool   $load_in_footer
92
-     * @return JavascriptAsset
93
-     * @throws DuplicateCollectionIdentifierException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidEntityException
96
-     * @since 4.9.62.p
97
-     */
98
-    public function addJavascript(
99
-        $handle,
100
-        $source,
101
-        array $dependencies = array(),
102
-        $load_in_footer = true
103
-    ) {
104
-        $asset = new JavascriptAsset(
105
-            $handle,
106
-            $source,
107
-            $dependencies,
108
-            $load_in_footer,
109
-            $this->domain
110
-        );
111
-        $this->assets->add($asset, $handle);
112
-        return $asset;
113
-    }
114
-
115
-
116
-    /**
117
-     * @return JavascriptAsset[]
118
-     * @since 4.9.62.p
119
-     */
120
-    public function getJavascriptAssets()
121
-    {
122
-        return $this->assets->getJavascriptAssets();
123
-    }
124
-
125
-
126
-    /**
127
-     * @param string $handle
128
-     * @param string $source
129
-     * @param array  $dependencies
130
-     * @param string $media
131
-     * @return StylesheetAsset
132
-     * @throws DuplicateCollectionIdentifierException
133
-     * @throws InvalidDataTypeException
134
-     * @throws InvalidEntityException
135
-     * @since 4.9.62.p
136
-     */
137
-    public function addStylesheet(
138
-        $handle,
139
-        $source,
140
-        array $dependencies = array(),
141
-        $media = 'all'
142
-    ) {
143
-        $asset = new StylesheetAsset(
144
-            $handle,
145
-            $source,
146
-            $dependencies,
147
-            $this->domain,
148
-            $media
149
-        );
150
-        $this->assets->add($asset, $handle);
151
-        return $asset;
152
-    }
153
-
154
-
155
-    /**
156
-     * @return StylesheetAsset[]
157
-     * @since 4.9.62.p
158
-     */
159
-    public function getStylesheetAssets()
160
-    {
161
-        return $this->assets->getStylesheetAssets();
162
-    }
163
-
164
-
165
-    /**
166
-     * @param string $handle
167
-     * @return bool
168
-     * @since 4.9.62.p
169
-     */
170
-    public function enqueueAsset($handle)
171
-    {
172
-        if ($this->assets->has($handle)) {
173
-            $asset = $this->assets->get($handle);
174
-            if ($asset->isRegistered()) {
175
-                $asset->enqueueAsset();
176
-                return true;
177
-            }
178
-        }
179
-        return false;
180
-    }
24
+	/**
25
+	 * @var AssetCollection $assets
26
+	 */
27
+	protected $assets;
28
+
29
+	/**
30
+	 * @var DomainInterface
31
+	 */
32
+	protected $domain;
33
+
34
+	/**
35
+	 * @var Registry $registry
36
+	 */
37
+	protected $registry;
38
+
39
+
40
+	/**
41
+	 * AssetRegister constructor.
42
+	 *
43
+	 * @param DomainInterface $domain
44
+	 * @param AssetCollection $assets
45
+	 * @param Registry        $registry
46
+	 */
47
+	public function __construct(DomainInterface $domain, AssetCollection $assets, Registry $registry)
48
+	{
49
+		$this->domain = $domain;
50
+		$this->assets = $assets;
51
+		$this->registry = $registry;
52
+		add_action('wp_enqueue_scripts', array($this, 'addManifestFile'), 0);
53
+		add_action('admin_enqueue_scripts', array($this, 'addManifestFile'), 0);
54
+		add_action('wp_enqueue_scripts', array($this, 'addAssets'), 2);
55
+		add_action('admin_enqueue_scripts', array($this, 'addAssets'), 2);
56
+	}
57
+
58
+
59
+	/**
60
+	 * @return void
61
+	 * @throws DuplicateCollectionIdentifierException
62
+	 * @throws InvalidDataTypeException
63
+	 * @throws InvalidEntityException
64
+	 * @since 4.9.62.p
65
+	 */
66
+	public function addManifestFile()
67
+	{
68
+		// if a manifest file has already been added for this domain, then just return that one
69
+		if ($this->assets->has($this->domain->assetNamespace())) {
70
+			return;
71
+		}
72
+		$asset = new ManifestFile($this->domain);
73
+		$this->assets->add($asset, $this->domain->assetNamespace());
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return ManifestFile[]
79
+	 * @since 4.9.62.p
80
+	 */
81
+	public function getManifestFile()
82
+	{
83
+		return $this->assets->getManifestFiles();
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param string $handle
89
+	 * @param string $source
90
+	 * @param array  $dependencies
91
+	 * @param bool   $load_in_footer
92
+	 * @return JavascriptAsset
93
+	 * @throws DuplicateCollectionIdentifierException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidEntityException
96
+	 * @since 4.9.62.p
97
+	 */
98
+	public function addJavascript(
99
+		$handle,
100
+		$source,
101
+		array $dependencies = array(),
102
+		$load_in_footer = true
103
+	) {
104
+		$asset = new JavascriptAsset(
105
+			$handle,
106
+			$source,
107
+			$dependencies,
108
+			$load_in_footer,
109
+			$this->domain
110
+		);
111
+		$this->assets->add($asset, $handle);
112
+		return $asset;
113
+	}
114
+
115
+
116
+	/**
117
+	 * @return JavascriptAsset[]
118
+	 * @since 4.9.62.p
119
+	 */
120
+	public function getJavascriptAssets()
121
+	{
122
+		return $this->assets->getJavascriptAssets();
123
+	}
124
+
125
+
126
+	/**
127
+	 * @param string $handle
128
+	 * @param string $source
129
+	 * @param array  $dependencies
130
+	 * @param string $media
131
+	 * @return StylesheetAsset
132
+	 * @throws DuplicateCollectionIdentifierException
133
+	 * @throws InvalidDataTypeException
134
+	 * @throws InvalidEntityException
135
+	 * @since 4.9.62.p
136
+	 */
137
+	public function addStylesheet(
138
+		$handle,
139
+		$source,
140
+		array $dependencies = array(),
141
+		$media = 'all'
142
+	) {
143
+		$asset = new StylesheetAsset(
144
+			$handle,
145
+			$source,
146
+			$dependencies,
147
+			$this->domain,
148
+			$media
149
+		);
150
+		$this->assets->add($asset, $handle);
151
+		return $asset;
152
+	}
153
+
154
+
155
+	/**
156
+	 * @return StylesheetAsset[]
157
+	 * @since 4.9.62.p
158
+	 */
159
+	public function getStylesheetAssets()
160
+	{
161
+		return $this->assets->getStylesheetAssets();
162
+	}
163
+
164
+
165
+	/**
166
+	 * @param string $handle
167
+	 * @return bool
168
+	 * @since 4.9.62.p
169
+	 */
170
+	public function enqueueAsset($handle)
171
+	{
172
+		if ($this->assets->has($handle)) {
173
+			$asset = $this->assets->get($handle);
174
+			if ($asset->isRegistered()) {
175
+				$asset->enqueueAsset();
176
+				return true;
177
+			}
178
+		}
179
+		return false;
180
+	}
181 181
 }
Please login to merge, or discard this patch.
core/services/loaders/CachingLoader.php 1 patch
Indentation   +150 added lines, -150 removed lines patch added patch discarded remove patch
@@ -17,154 +17,154 @@
 block discarded – undo
17 17
 class CachingLoader extends CachingLoaderDecorator
18 18
 {
19 19
 
20
-    /**
21
-     * @var string $identifier
22
-     */
23
-    protected $identifier;
24
-
25
-    /**
26
-     * @var CollectionInterface $cache
27
-     */
28
-    protected $cache;
29
-
30
-    /**
31
-     * @var ObjectIdentifier
32
-     */
33
-    private $object_identifier;
34
-
35
-
36
-    /**
37
-     * CachingLoader constructor.
38
-     *
39
-     * @param LoaderDecoratorInterface $loader
40
-     * @param CollectionInterface      $cache
41
-     * @param ObjectIdentifier         $object_identifier
42
-     * @param string                   $identifier
43
-     * @throws InvalidDataTypeException
44
-     */
45
-    public function __construct(
46
-        LoaderDecoratorInterface $loader,
47
-        CollectionInterface $cache,
48
-        ObjectIdentifier $object_identifier,
49
-        $identifier = ''
50
-    ) {
51
-        parent::__construct($loader);
52
-        $this->cache       = $cache;
53
-        $this->object_identifier = $object_identifier;
54
-        $this->setIdentifier($identifier);
55
-        if ($this->identifier !== '') {
56
-            // to only clear this cache, and assuming an identifier has been set, simply do the following:
57
-            // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
58
-            // where "IDENTIFIER" = the string that was set during construction
59
-            add_action(
60
-                "AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
61
-                array($this, 'reset')
62
-            );
63
-        }
64
-        // to clear ALL caches, simply do the following:
65
-        // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
66
-        add_action(
67
-            'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
68
-            array($this, 'reset')
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * @return string
75
-     */
76
-    public function identifier()
77
-    {
78
-        return $this->identifier;
79
-    }
80
-
81
-
82
-    /**
83
-     * @param string $identifier
84
-     * @throws InvalidDataTypeException
85
-     */
86
-    private function setIdentifier($identifier)
87
-    {
88
-        if (! is_string($identifier)) {
89
-            throw new InvalidDataTypeException('$identifier', $identifier, 'string');
90
-        }
91
-        $this->identifier = $identifier;
92
-    }
93
-
94
-
95
-    /**
96
-     * @param FullyQualifiedName|string $fqcn
97
-     * @param mixed                     $object
98
-     * @return bool
99
-     * @throws InvalidArgumentException
100
-     */
101
-    public function share($fqcn, $object)
102
-    {
103
-        if ($object instanceof $fqcn) {
104
-            return $this->cache->add($object, md5($fqcn));
105
-        }
106
-        throw new InvalidArgumentException(
107
-            sprintf(
108
-                esc_html__(
109
-                    'The supplied class name "%1$s" must match the class of the supplied object.',
110
-                    'event_espresso'
111
-                ),
112
-                $fqcn
113
-            )
114
-        );
115
-    }
116
-
117
-
118
-    /**
119
-     * @param FullyQualifiedName|string $fqcn
120
-     * @param array                     $arguments
121
-     * @param bool                      $shared
122
-     * @param array                     $interfaces
123
-     * @return mixed
124
-     */
125
-    public function load($fqcn, $arguments = array(), $shared = true, array $interfaces = array())
126
-    {
127
-        $fqcn = ltrim($fqcn, '\\');
128
-        // caching can be turned off via the following code:
129
-        // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
130
-        if (apply_filters(
131
-            'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
132
-            false,
133
-            $this
134
-        )) {
135
-            // even though $shared might be true, caching could be bypassed for whatever reason,
136
-            // so we don't want the core loader to cache anything, therefore caching is turned off
137
-            return $this->loader->load($fqcn, $arguments, false);
138
-        }
139
-        $object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
140
-        if ($this->cache->has($object_identifier)) {
141
-            return $this->cache->get($object_identifier);
142
-        }
143
-        $object = $this->loader->load($fqcn, $arguments, $shared);
144
-        if ($object instanceof $fqcn) {
145
-            $this->cache->add($object, $object_identifier);
146
-        }
147
-        return $object;
148
-    }
149
-
150
-
151
-    /**
152
-     * empties cache and calls reset() on loader if method exists
153
-     */
154
-    public function reset()
155
-    {
156
-        $this->clearCache();
157
-        $this->loader->reset();
158
-    }
159
-
160
-
161
-    /**
162
-     * unsets and detaches ALL objects from the cache
163
-     *
164
-     * @since 4.9.62.p
165
-     */
166
-    public function clearCache()
167
-    {
168
-        $this->cache->trashAndDetachAll();
169
-    }
20
+	/**
21
+	 * @var string $identifier
22
+	 */
23
+	protected $identifier;
24
+
25
+	/**
26
+	 * @var CollectionInterface $cache
27
+	 */
28
+	protected $cache;
29
+
30
+	/**
31
+	 * @var ObjectIdentifier
32
+	 */
33
+	private $object_identifier;
34
+
35
+
36
+	/**
37
+	 * CachingLoader constructor.
38
+	 *
39
+	 * @param LoaderDecoratorInterface $loader
40
+	 * @param CollectionInterface      $cache
41
+	 * @param ObjectIdentifier         $object_identifier
42
+	 * @param string                   $identifier
43
+	 * @throws InvalidDataTypeException
44
+	 */
45
+	public function __construct(
46
+		LoaderDecoratorInterface $loader,
47
+		CollectionInterface $cache,
48
+		ObjectIdentifier $object_identifier,
49
+		$identifier = ''
50
+	) {
51
+		parent::__construct($loader);
52
+		$this->cache       = $cache;
53
+		$this->object_identifier = $object_identifier;
54
+		$this->setIdentifier($identifier);
55
+		if ($this->identifier !== '') {
56
+			// to only clear this cache, and assuming an identifier has been set, simply do the following:
57
+			// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
58
+			// where "IDENTIFIER" = the string that was set during construction
59
+			add_action(
60
+				"AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
61
+				array($this, 'reset')
62
+			);
63
+		}
64
+		// to clear ALL caches, simply do the following:
65
+		// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
66
+		add_action(
67
+			'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
68
+			array($this, 'reset')
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @return string
75
+	 */
76
+	public function identifier()
77
+	{
78
+		return $this->identifier;
79
+	}
80
+
81
+
82
+	/**
83
+	 * @param string $identifier
84
+	 * @throws InvalidDataTypeException
85
+	 */
86
+	private function setIdentifier($identifier)
87
+	{
88
+		if (! is_string($identifier)) {
89
+			throw new InvalidDataTypeException('$identifier', $identifier, 'string');
90
+		}
91
+		$this->identifier = $identifier;
92
+	}
93
+
94
+
95
+	/**
96
+	 * @param FullyQualifiedName|string $fqcn
97
+	 * @param mixed                     $object
98
+	 * @return bool
99
+	 * @throws InvalidArgumentException
100
+	 */
101
+	public function share($fqcn, $object)
102
+	{
103
+		if ($object instanceof $fqcn) {
104
+			return $this->cache->add($object, md5($fqcn));
105
+		}
106
+		throw new InvalidArgumentException(
107
+			sprintf(
108
+				esc_html__(
109
+					'The supplied class name "%1$s" must match the class of the supplied object.',
110
+					'event_espresso'
111
+				),
112
+				$fqcn
113
+			)
114
+		);
115
+	}
116
+
117
+
118
+	/**
119
+	 * @param FullyQualifiedName|string $fqcn
120
+	 * @param array                     $arguments
121
+	 * @param bool                      $shared
122
+	 * @param array                     $interfaces
123
+	 * @return mixed
124
+	 */
125
+	public function load($fqcn, $arguments = array(), $shared = true, array $interfaces = array())
126
+	{
127
+		$fqcn = ltrim($fqcn, '\\');
128
+		// caching can be turned off via the following code:
129
+		// add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
130
+		if (apply_filters(
131
+			'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
132
+			false,
133
+			$this
134
+		)) {
135
+			// even though $shared might be true, caching could be bypassed for whatever reason,
136
+			// so we don't want the core loader to cache anything, therefore caching is turned off
137
+			return $this->loader->load($fqcn, $arguments, false);
138
+		}
139
+		$object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
140
+		if ($this->cache->has($object_identifier)) {
141
+			return $this->cache->get($object_identifier);
142
+		}
143
+		$object = $this->loader->load($fqcn, $arguments, $shared);
144
+		if ($object instanceof $fqcn) {
145
+			$this->cache->add($object, $object_identifier);
146
+		}
147
+		return $object;
148
+	}
149
+
150
+
151
+	/**
152
+	 * empties cache and calls reset() on loader if method exists
153
+	 */
154
+	public function reset()
155
+	{
156
+		$this->clearCache();
157
+		$this->loader->reset();
158
+	}
159
+
160
+
161
+	/**
162
+	 * unsets and detaches ALL objects from the cache
163
+	 *
164
+	 * @since 4.9.62.p
165
+	 */
166
+	public function clearCache()
167
+	{
168
+		$this->cache->trashAndDetachAll();
169
+	}
170 170
 }
Please login to merge, or discard this patch.