Completed
Branch Gutenberg/create-wp.data-store... (b0284b)
by
unknown
41:02 queued 27:55
created
modules/core_rest_api/EED_Core_Rest_Api.module.php 2 patches
Indentation   +1272 added lines, -1272 removed lines patch added patch discarded remove patch
@@ -26,1279 +26,1279 @@
 block discarded – undo
26 26
 class EED_Core_Rest_Api extends \EED_Module
27 27
 {
28 28
 
29
-    const ee_api_namespace           = Domain::API_NAMESPACE;
29
+	const ee_api_namespace           = Domain::API_NAMESPACE;
30 30
 
31
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
32
-
33
-    const saved_routes_option_names  = 'ee_core_routes';
34
-
35
-    /**
36
-     * string used in _links response bodies to make them globally unique.
37
-     *
38
-     * @see http://v2.wp-api.org/extending/linking/
39
-     */
40
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
41
-
42
-    /**
43
-     * @var CalculatedModelFields
44
-     */
45
-    protected static $_field_calculator;
46
-
47
-
48
-
49
-    /**
50
-     * @return EED_Core_Rest_Api|EED_Module
51
-     */
52
-    public static function instance()
53
-    {
54
-        self::$_field_calculator = new CalculatedModelFields();
55
-        return parent::get_instance(__CLASS__);
56
-    }
57
-
58
-
59
-
60
-    /**
61
-     *    set_hooks - for hooking into EE Core, other modules, etc
62
-     *
63
-     * @access    public
64
-     * @return    void
65
-     */
66
-    public static function set_hooks()
67
-    {
68
-        self::set_hooks_both();
69
-    }
70
-
71
-
72
-
73
-    /**
74
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
75
-     *
76
-     * @access    public
77
-     * @return    void
78
-     */
79
-    public static function set_hooks_admin()
80
-    {
81
-        self::set_hooks_both();
82
-    }
83
-
84
-
85
-
86
-    public static function set_hooks_both()
87
-    {
88
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
89
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
90
-        add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
91
-        add_filter('rest_index',
92
-            array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
93
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
94
-    }
95
-
96
-
97
-
98
-    /**
99
-     * sets up hooks which only need to be included as part of REST API requests;
100
-     * other requests like to the frontend or admin etc don't need them
101
-     *
102
-     * @throws \EE_Error
103
-     */
104
-    public static function set_hooks_rest_api()
105
-    {
106
-        //set hooks which account for changes made to the API
107
-        EED_Core_Rest_Api::_set_hooks_for_changes();
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * public wrapper of _set_hooks_for_changes.
114
-     * Loads all the hooks which make requests to old versions of the API
115
-     * appear the same as they always did
116
-     *
117
-     * @throws EE_Error
118
-     */
119
-    public static function set_hooks_for_changes()
120
-    {
121
-        self::_set_hooks_for_changes();
122
-    }
123
-
124
-
125
-
126
-    /**
127
-     * Loads all the hooks which make requests to old versions of the API
128
-     * appear the same as they always did
129
-     *
130
-     * @throws EE_Error
131
-     */
132
-    protected static function _set_hooks_for_changes()
133
-    {
134
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
135
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
136
-            //ignore the base parent class
137
-            //and legacy named classes
138
-            if ($classname_in_namespace === 'ChangesInBase'
139
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
140
-            ) {
141
-                continue;
142
-            }
143
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
144
-            if (class_exists($full_classname)) {
145
-                $instance_of_class = new $full_classname;
146
-                if ($instance_of_class instanceof ChangesInBase) {
147
-                    $instance_of_class->setHooks();
148
-                }
149
-            }
150
-        }
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
157
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
158
-     *
159
-     * @throws \EE_Error
160
-     */
161
-    public static function register_routes()
162
-    {
163
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
164
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
165
-                /**
166
-                 * @var array $data_for_multiple_endpoints numerically indexed array
167
-                 *                                         but can also contain route options like {
168
-                 * @type array    $schema                      {
169
-                 * @type callable $schema_callback
170
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
171
-                 * WP_REST_Request of course
172
-                 * }
173
-                 * }
174
-                 */
175
-                //when registering routes, register all the endpoints' data at the same time
176
-                $multiple_endpoint_args = array();
177
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
178
-                    /**
179
-                     * @var array     $data_for_single_endpoint {
180
-                     * @type callable $callback
181
-                     * @type string methods
182
-                     * @type array args
183
-                     * @type array _links
184
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
185
-                     * WP_REST_Request of course
186
-                     * }
187
-                     */
188
-                    //skip route options
189
-                    if (! is_numeric($endpoint_key)) {
190
-                        continue;
191
-                    }
192
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193
-                        throw new EE_Error(
194
-                            esc_html__(
195
-                                // @codingStandardsIgnoreStart
196
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
197
-                                // @codingStandardsIgnoreEnd
198
-                                'event_espresso')
199
-                        );
200
-                    }
201
-                    $callback = $data_for_single_endpoint['callback'];
202
-                    $single_endpoint_args = array(
203
-                        'methods' => $data_for_single_endpoint['methods'],
204
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
-                            : array(),
206
-                    );
207
-                    if (isset($data_for_single_endpoint['_links'])) {
208
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
-                    }
210
-                    if (isset($data_for_single_endpoint['callback_args'])) {
211
-                        $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
213
-                            $callback,
214
-                            $callback_args
215
-                        ) {
216
-                            array_unshift($callback_args, $request);
217
-                            return call_user_func_array(
218
-                                $callback,
219
-                                $callback_args
220
-                            );
221
-                        };
222
-                    } else {
223
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
-                    }
225
-                    $multiple_endpoint_args[] = $single_endpoint_args;
226
-                }
227
-                if (isset($data_for_multiple_endpoints['schema'])) {
228
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
229
-                    $schema_callback = $schema_route_data['schema_callback'];
230
-                    $callback_args = $schema_route_data['callback_args'];
231
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
232
-                        return call_user_func_array(
233
-                            $schema_callback,
234
-                            $callback_args
235
-                        );
236
-                    };
237
-                }
238
-                register_rest_route(
239
-                    $namespace,
240
-                    $relative_route,
241
-                    $multiple_endpoint_args
242
-                );
243
-            }
244
-        }
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     * Checks if there was a version change or something that merits invalidating the cached
251
-     * route data. If so, invalidates the cached route data so that it gets refreshed
252
-     * next time the WP API is used
253
-     */
254
-    public static function invalidate_cached_route_data_on_version_change()
255
-    {
256
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
257
-            EED_Core_Rest_Api::invalidate_cached_route_data();
258
-        }
259
-        foreach (EE_Registry::instance()->addons as $addon) {
260
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
261
-                EED_Core_Rest_Api::invalidate_cached_route_data();
262
-            }
263
-        }
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * Removes the cached route data so it will get refreshed next time the WP API is used
270
-     */
271
-    public static function invalidate_cached_route_data()
272
-    {
273
-        //delete the saved EE REST API routes
274
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
276
-        }
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * Gets the EE route data
283
-     *
284
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
285
-     * @throws \EE_Error
286
-     * @type string|array $callback
287
-     * @type string       $methods
288
-     * @type boolean      $hidden_endpoint
289
-     * }
290
-     */
291
-    public static function get_ee_route_data()
292
-    {
293
-        $ee_routes = array();
294
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
295
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
296
-                $version,
297
-                $hidden_endpoints
298
-            );
299
-        }
300
-        return $ee_routes;
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     * Gets the EE route data from the wp options if it exists already,
307
-     * otherwise re-generates it and saves it to the option
308
-     *
309
-     * @param string  $version
310
-     * @param boolean $hidden_endpoints
311
-     * @return array
312
-     * @throws \EE_Error
313
-     */
314
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315
-    {
316
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319
-        }
320
-        return $ee_routes;
321
-    }
322
-
323
-
324
-
325
-    /**
326
-     * Saves the EE REST API route data to a wp option and returns it
327
-     *
328
-     * @param string  $version
329
-     * @param boolean $hidden_endpoints
330
-     * @return mixed|null
331
-     * @throws \EE_Error
332
-     */
333
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
334
-    {
335
-        $instance = self::instance();
336
-        $routes = apply_filters(
337
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
338
-            array_replace_recursive(
339
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
340
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
341
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
342
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343
-            )
344
-        );
345
-        $option_name = self::saved_routes_option_names . $version;
346
-        if (get_option($option_name)) {
347
-            update_option($option_name, $routes, true);
348
-        } else {
349
-            add_option($option_name, $routes, null, 'no');
350
-        }
351
-        return $routes;
352
-    }
353
-
354
-
355
-
356
-    /**
357
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
358
-     * need to calculate it on every request
359
-     *
360
-     * @deprecated since version 4.9.1
361
-     * @return void
362
-     */
363
-    public static function save_ee_routes()
364
-    {
365
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
366
-            $instance = self::instance();
367
-            $routes = apply_filters(
368
-                'EED_Core_Rest_Api__save_ee_routes__routes',
369
-                array_replace_recursive(
370
-                    $instance->_register_config_routes(),
371
-                    $instance->_register_meta_routes(),
372
-                    $instance->_register_model_routes(),
373
-                    $instance->_register_rpc_routes()
374
-                )
375
-            );
376
-            update_option(self::saved_routes_option_names, $routes, true);
377
-        }
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * Gets all the route information relating to EE models
384
-     *
385
-     * @return array @see get_ee_route_data
386
-     * @deprecated since version 4.9.1
387
-     */
388
-    protected function _register_model_routes()
389
-    {
390
-        $model_routes = array();
391
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
392
-            $model_routes[EED_Core_Rest_Api::ee_api_namespace
393
-                          . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
394
-        }
395
-        return $model_routes;
396
-    }
397
-
398
-
399
-
400
-    /**
401
-     * Decides whether or not to add write endpoints for this model.
402
-     *
403
-     * Currently, this defaults to exclude all global tables and models
404
-     * which would allow inserting WP core data (we don't want to duplicate
405
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
406
-     * @param EEM_Base $model
407
-     * @return bool
408
-     */
409
-    public static function should_have_write_endpoints(EEM_Base $model)
410
-    {
411
-        if ($model->is_wp_core_model()){
412
-            return false;
413
-        }
414
-        foreach($model->get_tables() as $table){
415
-            if( $table->is_global()){
416
-                return false;
417
-            }
418
-        }
419
-        return true;
420
-    }
421
-
422
-
423
-
424
-    /**
425
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
426
-     * in this versioned namespace of EE4
427
-     * @param $version
428
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429
-     */
430
-    public static function model_names_with_plural_routes($version){
431
-        $model_version_info = new ModelVersionInfo($version);
432
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
433
-        //let's not bother having endpoints for extra metas
434
-        unset(
435
-            $models_to_register['Extra_Meta'],
436
-            $models_to_register['Extra_Join'],
437
-            $models_to_register['Post_Meta']
438
-        );
439
-        return apply_filters(
440
-            'FHEE__EED_Core_REST_API___register_model_routes',
441
-            $models_to_register
442
-        );
443
-    }
444
-
445
-
446
-
447
-    /**
448
-     * Gets the route data for EE models in the specified version
449
-     *
450
-     * @param string  $version
451
-     * @param boolean $hidden_endpoint
452
-     * @return array
453
-     * @throws EE_Error
454
-     */
455
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
456
-    {
457
-        $model_routes = array();
458
-        $model_version_info = new ModelVersionInfo($version);
459
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460
-            $model = \EE_Registry::instance()->load_model($model_name);
461
-            //if this isn't a valid model then let's skip iterate to the next item in the loop.
462
-            if (! $model instanceof EEM_Base) {
463
-                continue;
464
-            }
465
-            //yes we could just register one route for ALL models, but then they wouldn't show up in the index
466
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
467
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
468
-            $model_routes[$plural_model_route] = array(
469
-                array(
470
-                    'callback'        => array(
471
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
472
-                        'handleRequestGetAll',
473
-                    ),
474
-                    'callback_args'   => array($version, $model_name),
475
-                    'methods'         => WP_REST_Server::READABLE,
476
-                    'hidden_endpoint' => $hidden_endpoint,
477
-                    'args'            => $this->_get_read_query_params($model, $version),
478
-                    '_links'          => array(
479
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
480
-                    ),
481
-                ),
482
-                'schema' => array(
483
-                    'schema_callback' => array(
484
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
485
-                        'handleSchemaRequest',
486
-                    ),
487
-                    'callback_args'   => array($version, $model_name),
488
-                ),
489
-            );
490
-            $model_routes[$singular_model_route] = array(
491
-                array(
492
-                    'callback'        => array(
493
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
494
-                        'handleRequestGetOne',
495
-                    ),
496
-                    'callback_args'   => array($version, $model_name),
497
-                    'methods'         => WP_REST_Server::READABLE,
498
-                    'hidden_endpoint' => $hidden_endpoint,
499
-                    'args'            => $this->_get_response_selection_query_params($model, $version),
500
-                ),
501
-            );
502
-            if( apply_filters(
503
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
505
-                $model
506
-            )){
507
-                $model_routes[$plural_model_route][] = array(
508
-                    'callback'        => array(
509
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
510
-                        'handleRequestInsert',
511
-                    ),
512
-                    'callback_args'   => array($version, $model_name),
513
-                    'methods'         => WP_REST_Server::CREATABLE,
514
-                    'hidden_endpoint' => $hidden_endpoint,
515
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
516
-                );
517
-                $model_routes[$singular_model_route] = array_merge(
518
-                    $model_routes[$singular_model_route],
519
-                    array(
520
-                        array(
521
-                            'callback'        => array(
522
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
523
-                                'handleRequestUpdate',
524
-                            ),
525
-                            'callback_args'   => array($version, $model_name),
526
-                            'methods'         => WP_REST_Server::EDITABLE,
527
-                            'hidden_endpoint' => $hidden_endpoint,
528
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
529
-                        ),
530
-                        array(
531
-                            'callback'        => array(
532
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
533
-                                'handleRequestDelete',
534
-                            ),
535
-                            'callback_args'   => array($version, $model_name),
536
-                            'methods'         => WP_REST_Server::DELETABLE,
537
-                            'hidden_endpoint' => $hidden_endpoint,
538
-                            'args'            => $this->_get_delete_query_params($model, $version),
539
-                        )
540
-                    )
541
-                );
542
-            }
543
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
544
-
545
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
546
-                    $model,
547
-                    '(?P<id>[^\/]+)',
548
-                    $relation_obj
549
-                );
550
-                $endpoints = array(
551
-                    array(
552
-                        'callback'        => array(
553
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
554
-                            'handleRequestGetRelated',
555
-                        ),
556
-                        'callback_args'   => array($version, $model_name, $relation_name),
557
-                        'methods'         => WP_REST_Server::READABLE,
558
-                        'hidden_endpoint' => $hidden_endpoint,
559
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
560
-                    ),
561
-                );
562
-                $model_routes[$related_route] = $endpoints;
563
-            }
564
-        }
565
-        return $model_routes;
566
-    }
567
-
568
-
569
-
570
-    /**
571
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
572
-     * excluding the preceding slash.
573
-     * Eg you pass get_plural_route_to('Event') = 'events'
574
-     *
575
-     * @param EEM_Base $model
576
-     * @return string
577
-     */
578
-    public static function get_collection_route(EEM_Base $model)
579
-    {
580
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
587
-     * excluding the preceding slash.
588
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
589
-     *
590
-     * @param EEM_Base $model eg Event or Venue
591
-     * @param string $id
592
-     * @return string
593
-     */
594
-    public static function get_entity_route($model, $id)
595
-    {
596
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
597
-    }
598
-
599
-
600
-    /**
601
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
602
-     * excluding the preceding slash.
603
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
604
-     *
605
-     * @param EEM_Base                 $model eg Event or Venue
606
-     * @param string                 $id
607
-     * @param EE_Model_Relation_Base $relation_obj
608
-     * @return string
609
-     */
610
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
611
-    {
612
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
613
-            $relation_obj->get_other_model()->get_this_model_name(),
614
-            $relation_obj
615
-        );
616
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
617
-    }
618
-
619
-
620
-
621
-    /**
622
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
623
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
624
-     * @param string $relative_route
625
-     * @param string $version
626
-     * @return string
627
-     */
628
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
630
-    }
631
-
632
-
633
-
634
-    /**
635
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
636
-     * routes that don't conform to the traditional REST CRUD-style).
637
-     *
638
-     * @deprecated since 4.9.1
639
-     */
640
-    protected function _register_rpc_routes()
641
-    {
642
-        $routes = array();
643
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
644
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
645
-                $version,
646
-                $hidden_endpoint
647
-            );
648
-        }
649
-        return $routes;
650
-    }
651
-
652
-
653
-
654
-    /**
655
-     * @param string  $version
656
-     * @param boolean $hidden_endpoint
657
-     * @return array
658
-     */
659
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
660
-    {
661
-        $this_versions_routes = array();
662
-        //checkin endpoint
663
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
664
-            array(
665
-                'callback'        => array(
666
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
667
-                    'handleRequestToggleCheckin',
668
-                ),
669
-                'methods'         => WP_REST_Server::CREATABLE,
670
-                'hidden_endpoint' => $hidden_endpoint,
671
-                'args'            => array(
672
-                    'force' => array(
673
-                        'required'    => false,
674
-                        'default'     => false,
675
-                        'description' => __(
676
-                            // @codingStandardsIgnoreStart
677
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
678
-                            // @codingStandardsIgnoreEnd
679
-                            'event_espresso'
680
-                        ),
681
-                    ),
682
-                ),
683
-                'callback_args'   => array($version),
684
-            ),
685
-        );
686
-        return apply_filters(
687
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
688
-            $this_versions_routes,
689
-            $version,
690
-            $hidden_endpoint
691
-        );
692
-    }
693
-
694
-
695
-
696
-    /**
697
-     * Gets the query params that can be used when request one or many
698
-     *
699
-     * @param EEM_Base $model
700
-     * @param string   $version
701
-     * @return array
702
-     */
703
-    protected function _get_response_selection_query_params(\EEM_Base $model, $version)
704
-    {
705
-        return apply_filters(
706
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
707
-            array(
708
-                'include'   => array(
709
-                    'required' => false,
710
-                    'default'  => '*',
711
-                    'type'     => 'string',
712
-                ),
713
-                'calculate' => array(
714
-                    'required'          => false,
715
-                    'default'           => '',
716
-                    'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
717
-                    'type'              => 'string',
718
-                    //because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
719
-                    //freaks out. We'll just validate this argument while handling the request
720
-                    'validate_callback' => null,
721
-                    'sanitize_callback' => null,
722
-                ),
723
-            ),
724
-            $model,
725
-            $version
726
-        );
727
-    }
728
-
729
-
730
-
731
-    /**
732
-     * Gets the parameters acceptable for delete requests
733
-     *
734
-     * @param \EEM_Base $model
735
-     * @param string    $version
736
-     * @return array
737
-     */
738
-    protected function _get_delete_query_params(\EEM_Base $model, $version)
739
-    {
740
-        $params_for_delete = array(
741
-            'allow_blocking' => array(
742
-                'required' => false,
743
-                'default'  => true,
744
-                'type'     => 'boolean',
745
-            ),
746
-        );
747
-        $params_for_delete['force'] = array(
748
-            'required' => false,
749
-            'default'  => false,
750
-            'type'     => 'boolean',
751
-        );
752
-        return apply_filters(
753
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
754
-            $params_for_delete,
755
-            $model,
756
-            $version
757
-        );
758
-    }
759
-
760
-
761
-
762
-    /**
763
-     * Gets info about reading query params that are acceptable
764
-     *
765
-     * @param \EEM_Base $model eg 'Event' or 'Venue'
766
-     * @param  string   $version
767
-     * @return array    describing the args acceptable when querying this model
768
-     * @throws EE_Error
769
-     */
770
-    protected function _get_read_query_params(\EEM_Base $model, $version)
771
-    {
772
-        $default_orderby = array();
773
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
774
-            $default_orderby[$key_field->get_name()] = 'ASC';
775
-        }
776
-        return array_merge(
777
-            $this->_get_response_selection_query_params($model, $version),
778
-            array(
779
-                'where'    => array(
780
-                    'required' => false,
781
-                    'default'  => array(),
782
-                    'type'     => 'object',
783
-                    //because we accept an almost infinite list of possible where conditions, WP
784
-                    // core validation and sanitization freaks out. We'll just validate this argument
785
-                    // while handling the request
786
-                    'validate_callback' => null,
787
-                    'sanitize_callback' => null,
788
-                ),
789
-                'limit'    => array(
790
-                    'required' => false,
791
-                    'default'  => EED_Core_Rest_Api::get_default_query_limit(),
792
-                    'type'     => array(
793
-                        'array',
794
-                        'string',
795
-                        'integer',
796
-                    ),
797
-                    //because we accept a variety of types, WP core validation and sanitization
798
-                    //freaks out. We'll just validate this argument while handling the request
799
-                    'validate_callback' => null,
800
-                    'sanitize_callback' => null,
801
-                ),
802
-                'order_by' => array(
803
-                    'required' => false,
804
-                    'default'  => $default_orderby,
805
-                    'type'     => array(
806
-                        'object',
807
-                        'string',
808
-                    ),//because we accept a variety of types, WP core validation and sanitization
809
-                    //freaks out. We'll just validate this argument while handling the request
810
-                    'validate_callback' => null,
811
-                    'sanitize_callback' => null,
812
-                ),
813
-                'group_by' => array(
814
-                    'required' => false,
815
-                    'default'  => null,
816
-                    'type'     => array(
817
-                        'object',
818
-                        'string',
819
-                    ),
820
-                    //because we accept  an almost infinite list of possible groupings,
821
-                    // WP core validation and sanitization
822
-                    //freaks out. We'll just validate this argument while handling the request
823
-                    'validate_callback' => null,
824
-                    'sanitize_callback' => null,
825
-                ),
826
-                'having'   => array(
827
-                    'required' => false,
828
-                    'default'  => null,
829
-                    'type'     => 'object',
830
-                    //because we accept an almost infinite list of possible where conditions, WP
831
-                    // core validation and sanitization freaks out. We'll just validate this argument
832
-                    // while handling the request
833
-                    'validate_callback' => null,
834
-                    'sanitize_callback' => null,
835
-                ),
836
-                'caps'     => array(
837
-                    'required' => false,
838
-                    'default'  => EEM_Base::caps_read,
839
-                    'type'     => 'string',
840
-                    'enum'     => array(
841
-                        EEM_Base::caps_read,
842
-                        EEM_Base::caps_read_admin,
843
-                        EEM_Base::caps_edit,
844
-                        EEM_Base::caps_delete
845
-                    )
846
-                ),
847
-            )
848
-        );
849
-    }
850
-
851
-
852
-
853
-    /**
854
-     * Gets parameter information for a model regarding writing data
855
-     *
856
-     * @param string           $model_name
857
-     * @param ModelVersionInfo $model_version_info
858
-     * @param boolean          $create                                       whether this is for request to create (in which case we need
859
-     *                                                                       all required params) or just to update (in which case we don't need those on every request)
860
-     * @return array
861
-     */
862
-    protected function _get_write_params(
863
-        $model_name,
864
-        ModelVersionInfo $model_version_info,
865
-        $create = false
866
-    ) {
867
-        $model = EE_Registry::instance()->load_model($model_name);
868
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
869
-        $args_info = array();
870
-        foreach ($fields as $field_name => $field_obj) {
871
-            if ($field_obj->is_auto_increment()) {
872
-                //totally ignore auto increment IDs
873
-                continue;
874
-            }
875
-            $arg_info = $field_obj->getSchema();
876
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
877
-            $arg_info['required'] = $required;
878
-            //remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
879
-            unset($arg_info['readonly']);
880
-            $schema_properties = $field_obj->getSchemaProperties();
881
-            if (
882
-                isset($schema_properties['raw'])
883
-                && $field_obj->getSchemaType() === 'object'
884
-            ) {
885
-                //if there's a "raw" form of this argument, use those properties instead
886
-                $arg_info = array_replace(
887
-                    $arg_info,
888
-                    $schema_properties['raw']
889
-                );
890
-            }
891
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
892
-                $field_obj,
893
-                $field_obj->get_default_value(),
894
-                $model_version_info->requestedVersion()
895
-            );
896
-            //we do our own validation and sanitization within the controller
897
-            if(function_exists('rest_validate_value_from_schema')){
898
-                $sanitize_callback = array(
899
-                    'EED_Core_Rest_Api',
900
-                    'default_sanitize_callback',
901
-                );
902
-            } else {
903
-                $sanitize_callback = null;
904
-            }
905
-            $arg_info['sanitize_callback'] = $sanitize_callback;
906
-            $args_info[$field_name] = $arg_info;
907
-            if ($field_obj instanceof EE_Datetime_Field) {
908
-                $gmt_arg_info = $arg_info;
909
-                $gmt_arg_info['description'] = sprintf(
910
-                    esc_html__(
911
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
912
-                        'event_espresso'
913
-                    ),
914
-                    $field_obj->get_nicename(),
915
-                    $field_name
916
-                );
917
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
918
-            }
919
-        }
920
-        return $args_info;
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * Replacement for WP API's 'rest_parse_request_arg'.
927
-     * If the value is blank but not required, don't bother validating it.
928
-     * Also, it uses our email validation instead of WP API's default.
929
-     *
930
-     * @param                 $value
931
-     * @param WP_REST_Request $request
932
-     * @param                 $param
933
-     * @return bool|true|WP_Error
934
-     * @throws InvalidArgumentException
935
-     * @throws InvalidInterfaceException
936
-     * @throws InvalidDataTypeException
937
-     */
938
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
939
-    {
940
-        $attributes = $request->get_attributes();
941
-        if (! isset($attributes['args'][$param])
942
-            || ! is_array($attributes['args'][$param])) {
943
-            $validation_result = true;
944
-        } else {
945
-            $args = $attributes['args'][$param];
946
-            if ((
947
-                    $value === ''
948
-                    || $value === null
949
-                )
950
-                && (! isset($args['required'])
951
-                    || $args['required'] === false
952
-                )
953
-            ) {
954
-                //not required and not provided? that's cool
955
-                $validation_result = true;
956
-            } elseif (isset($args['format'])
957
-                && $args['format'] === 'email'
958
-            ) {
959
-                $validation_result = true;
960
-                if (! self::_validate_email($value)) {
961
-                    $validation_result = new WP_Error(
962
-                        'rest_invalid_param',
963
-                        esc_html__(
964
-                            'The email address is not valid or does not exist.',
965
-                            'event_espresso'
966
-                        )
967
-                    );
968
-                }
969
-            } else {
970
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
971
-            }
972
-        }
973
-        if (is_wp_error($validation_result)) {
974
-            return $validation_result;
975
-        }
976
-        return rest_sanitize_request_arg($value, $request, $param);
977
-    }
978
-
979
-
980
-
981
-    /**
982
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
983
-     *
984
-     * @param $email
985
-     * @return bool
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidInterfaceException
988
-     * @throws InvalidDataTypeException
989
-     */
990
-    protected static function _validate_email($email){
991
-        try {
992
-            EmailAddressFactory::create($email);
993
-            return true;
994
-        } catch (EmailValidationException $e) {
995
-            return false;
996
-        }
997
-    }
998
-
999
-
1000
-
1001
-    /**
1002
-     * Gets routes for the config
1003
-     *
1004
-     * @return array @see _register_model_routes
1005
-     * @deprecated since version 4.9.1
1006
-     */
1007
-    protected function _register_config_routes()
1008
-    {
1009
-        $config_routes = array();
1010
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1012
-                $version,
1013
-                $hidden_endpoint
1014
-            );
1015
-        }
1016
-        return $config_routes;
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * Gets routes for the config for the specified version
1023
-     *
1024
-     * @param string  $version
1025
-     * @param boolean $hidden_endpoint
1026
-     * @return array
1027
-     */
1028
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1029
-    {
1030
-        return array(
1031
-            'config'    => array(
1032
-                array(
1033
-                    'callback'        => array(
1034
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1035
-                        'handleRequest',
1036
-                    ),
1037
-                    'methods'         => WP_REST_Server::READABLE,
1038
-                    'hidden_endpoint' => $hidden_endpoint,
1039
-                    'callback_args'   => array($version),
1040
-                ),
1041
-            ),
1042
-            'site_info' => array(
1043
-                array(
1044
-                    'callback'        => array(
1045
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1046
-                        'handleRequestSiteInfo',
1047
-                    ),
1048
-                    'methods'         => WP_REST_Server::READABLE,
1049
-                    'hidden_endpoint' => $hidden_endpoint,
1050
-                    'callback_args'   => array($version),
1051
-                ),
1052
-            ),
1053
-        );
1054
-    }
1055
-
1056
-
1057
-
1058
-    /**
1059
-     * Gets the meta info routes
1060
-     *
1061
-     * @return array @see _register_model_routes
1062
-     * @deprecated since version 4.9.1
1063
-     */
1064
-    protected function _register_meta_routes()
1065
-    {
1066
-        $meta_routes = array();
1067
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1069
-                $version,
1070
-                $hidden_endpoint
1071
-            );
1072
-        }
1073
-        return $meta_routes;
1074
-    }
1075
-
1076
-
1077
-
1078
-    /**
1079
-     * @param string  $version
1080
-     * @param boolean $hidden_endpoint
1081
-     * @return array
1082
-     */
1083
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1084
-    {
1085
-        return array(
1086
-            'resources' => array(
1087
-                array(
1088
-                    'callback'        => array(
1089
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1090
-                        'handleRequestModelsMeta',
1091
-                    ),
1092
-                    'methods'         => WP_REST_Server::READABLE,
1093
-                    'hidden_endpoint' => $hidden_endpoint,
1094
-                    'callback_args'   => array($version),
1095
-                ),
1096
-            ),
1097
-        );
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * Tries to hide old 4.6 endpoints from the
1104
-     *
1105
-     * @param array $route_data
1106
-     * @return array
1107
-     * @throws \EE_Error
1108
-     */
1109
-    public static function hide_old_endpoints($route_data)
1110
-    {
1111
-        //allow API clients to override which endpoints get hidden, in case
1112
-        //they want to discover particular endpoints
1113
-        //also, we don't have access to the request so we have to just grab it from the superglobal
1114
-        $force_show_ee_namespace = ltrim(
1115
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1116
-            '/'
1117
-        );
1118
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1119
-            foreach ($relative_urls as $resource_name => $endpoints) {
1120
-                foreach ($endpoints as $key => $endpoint) {
1121
-                    //skip schema and other route options
1122
-                    if (! is_numeric($key)) {
1123
-                        continue;
1124
-                    }
1125
-                    //by default, hide "hidden_endpoint"s, unless the request indicates
1126
-                    //to $force_show_ee_namespace, in which case only show that one
1127
-                    //namespace's endpoints (and hide all others)
1128
-                    if (
1129
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131
-                    ) {
1132
-                        $full_route = '/' . ltrim($namespace, '/');
1133
-                        $full_route .= '/' . ltrim($resource_name, '/');
1134
-                        unset($route_data[$full_route]);
1135
-                    }
1136
-                }
1137
-            }
1138
-        }
1139
-        return $route_data;
1140
-    }
1141
-
1142
-
1143
-
1144
-    /**
1145
-     * Returns an array describing which versions of core support serving requests for.
1146
-     * Keys are core versions' major and minor version, and values are the
1147
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1148
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1149
-     * the answers table entirely, in which case it would be very difficult for
1150
-     * it to serve 4.6-style responses.
1151
-     * Versions of core that are missing from this array are unknowns.
1152
-     * previous ver
1153
-     *
1154
-     * @return array
1155
-     */
1156
-    public static function version_compatibilities()
1157
-    {
1158
-        return apply_filters(
1159
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1160
-            array(
1161
-                '4.8.29' => '4.8.29',
1162
-                '4.8.33' => '4.8.29',
1163
-                '4.8.34' => '4.8.29',
1164
-                '4.8.36' => '4.8.29',
1165
-            )
1166
-        );
1167
-    }
1168
-
1169
-
1170
-
1171
-    /**
1172
-     * Gets the latest API version served. Eg if there
1173
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1174
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1175
-     *
1176
-     * @return string
1177
-     */
1178
-    public static function latest_rest_api_version()
1179
-    {
1180
-        $versions_served = \EED_Core_Rest_Api::versions_served();
1181
-        $versions_served_keys = array_keys($versions_served);
1182
-        return end($versions_served_keys);
1183
-    }
1184
-
1185
-
1186
-
1187
-    /**
1188
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1189
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1190
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1191
-     * We also indicate whether or not this version should be put in the index or not
1192
-     *
1193
-     * @return array keys are API version numbers (just major and minor numbers), and values
1194
-     * are whether or not they should be hidden
1195
-     */
1196
-    public static function versions_served()
1197
-    {
1198
-        $versions_served = array();
1199
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1200
-        $lowest_compatible_version = end($possibly_served_versions);
1201
-        reset($possibly_served_versions);
1202
-        $versions_served_historically = array_keys($possibly_served_versions);
1203
-        $latest_version = end($versions_served_historically);
1204
-        reset($versions_served_historically);
1205
-        //for each version of core we have ever served:
1206
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1207
-            //if it's not above the current core version, and it's compatible with the current version of core
1208
-            if ($key_versioned_endpoint === $latest_version) {
1209
-                //don't hide the latest version in the index
1210
-                $versions_served[$key_versioned_endpoint] = false;
1211
-            } elseif (
1212
-                $key_versioned_endpoint >= $lowest_compatible_version
1213
-                && $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1214
-            ) {
1215
-                //include, but hide, previous versions which are still supported
1216
-                $versions_served[$key_versioned_endpoint] = true;
1217
-            } elseif (apply_filters(
1218
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1219
-                false,
1220
-                $possibly_served_versions
1221
-            )) {
1222
-                //if a version is no longer supported, don't include it in index or list of versions served
1223
-                $versions_served[$key_versioned_endpoint] = true;
1224
-            }
1225
-        }
1226
-        return $versions_served;
1227
-    }
1228
-
1229
-
1230
-
1231
-    /**
1232
-     * Gets the major and minor version of EE core's version string
1233
-     *
1234
-     * @return string
1235
-     */
1236
-    public static function core_version()
1237
-    {
1238
-        return apply_filters(
1239
-            'FHEE__EED_Core_REST_API__core_version',
1240
-            implode(
1241
-                '.',
1242
-                array_slice(
1243
-                    explode(
1244
-                        '.',
1245
-                        espresso_version()
1246
-                    ),
1247
-                0,
1248
-                3
1249
-                )
1250
-            )
1251
-        );
1252
-    }
1253
-
1254
-
1255
-
1256
-    /**
1257
-     * Gets the default limit that should be used when querying for resources
1258
-     *
1259
-     * @return int
1260
-     */
1261
-    public static function get_default_query_limit()
1262
-    {
1263
-        //we actually don't use a const because we want folks to always use
1264
-        //this method, not the const directly
1265
-        return apply_filters(
1266
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1267
-            50
1268
-        );
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     *
1274
-     * @param string $version api version string (i.e. '4.8.36')
1275
-     * @return array
1276
-     */
1277
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1278
-    {
1279
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1280
-        $model_names = self::model_names_with_plural_routes($version);
1281
-        $collection_routes = array();
1282
-        foreach ($model_names as $model_name => $model_class_name) {
1283
-            $collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1284
-                                                          . EEH_Inflector::pluralize_and_lower($model_name);
1285
-
1286
-        }
1287
-        return $collection_routes;
1288
-    }
1289
-
1290
-
1291
-
1292
-    /**
1293
-     *    run - initial module setup
1294
-     *
1295
-     * @access    public
1296
-     * @param  WP $WP
1297
-     * @return    void
1298
-     */
1299
-    public function run($WP)
1300
-    {
1301
-    }
31
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
32
+
33
+	const saved_routes_option_names  = 'ee_core_routes';
34
+
35
+	/**
36
+	 * string used in _links response bodies to make them globally unique.
37
+	 *
38
+	 * @see http://v2.wp-api.org/extending/linking/
39
+	 */
40
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
41
+
42
+	/**
43
+	 * @var CalculatedModelFields
44
+	 */
45
+	protected static $_field_calculator;
46
+
47
+
48
+
49
+	/**
50
+	 * @return EED_Core_Rest_Api|EED_Module
51
+	 */
52
+	public static function instance()
53
+	{
54
+		self::$_field_calculator = new CalculatedModelFields();
55
+		return parent::get_instance(__CLASS__);
56
+	}
57
+
58
+
59
+
60
+	/**
61
+	 *    set_hooks - for hooking into EE Core, other modules, etc
62
+	 *
63
+	 * @access    public
64
+	 * @return    void
65
+	 */
66
+	public static function set_hooks()
67
+	{
68
+		self::set_hooks_both();
69
+	}
70
+
71
+
72
+
73
+	/**
74
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
75
+	 *
76
+	 * @access    public
77
+	 * @return    void
78
+	 */
79
+	public static function set_hooks_admin()
80
+	{
81
+		self::set_hooks_both();
82
+	}
83
+
84
+
85
+
86
+	public static function set_hooks_both()
87
+	{
88
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
89
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
90
+		add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
91
+		add_filter('rest_index',
92
+			array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
93
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
94
+	}
95
+
96
+
97
+
98
+	/**
99
+	 * sets up hooks which only need to be included as part of REST API requests;
100
+	 * other requests like to the frontend or admin etc don't need them
101
+	 *
102
+	 * @throws \EE_Error
103
+	 */
104
+	public static function set_hooks_rest_api()
105
+	{
106
+		//set hooks which account for changes made to the API
107
+		EED_Core_Rest_Api::_set_hooks_for_changes();
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * public wrapper of _set_hooks_for_changes.
114
+	 * Loads all the hooks which make requests to old versions of the API
115
+	 * appear the same as they always did
116
+	 *
117
+	 * @throws EE_Error
118
+	 */
119
+	public static function set_hooks_for_changes()
120
+	{
121
+		self::_set_hooks_for_changes();
122
+	}
123
+
124
+
125
+
126
+	/**
127
+	 * Loads all the hooks which make requests to old versions of the API
128
+	 * appear the same as they always did
129
+	 *
130
+	 * @throws EE_Error
131
+	 */
132
+	protected static function _set_hooks_for_changes()
133
+	{
134
+		$folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
135
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
136
+			//ignore the base parent class
137
+			//and legacy named classes
138
+			if ($classname_in_namespace === 'ChangesInBase'
139
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
140
+			) {
141
+				continue;
142
+			}
143
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
144
+			if (class_exists($full_classname)) {
145
+				$instance_of_class = new $full_classname;
146
+				if ($instance_of_class instanceof ChangesInBase) {
147
+					$instance_of_class->setHooks();
148
+				}
149
+			}
150
+		}
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
157
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
158
+	 *
159
+	 * @throws \EE_Error
160
+	 */
161
+	public static function register_routes()
162
+	{
163
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
164
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
165
+				/**
166
+				 * @var array $data_for_multiple_endpoints numerically indexed array
167
+				 *                                         but can also contain route options like {
168
+				 * @type array    $schema                      {
169
+				 * @type callable $schema_callback
170
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
171
+				 * WP_REST_Request of course
172
+				 * }
173
+				 * }
174
+				 */
175
+				//when registering routes, register all the endpoints' data at the same time
176
+				$multiple_endpoint_args = array();
177
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
178
+					/**
179
+					 * @var array     $data_for_single_endpoint {
180
+					 * @type callable $callback
181
+					 * @type string methods
182
+					 * @type array args
183
+					 * @type array _links
184
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
185
+					 * WP_REST_Request of course
186
+					 * }
187
+					 */
188
+					//skip route options
189
+					if (! is_numeric($endpoint_key)) {
190
+						continue;
191
+					}
192
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193
+						throw new EE_Error(
194
+							esc_html__(
195
+								// @codingStandardsIgnoreStart
196
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
197
+								// @codingStandardsIgnoreEnd
198
+								'event_espresso')
199
+						);
200
+					}
201
+					$callback = $data_for_single_endpoint['callback'];
202
+					$single_endpoint_args = array(
203
+						'methods' => $data_for_single_endpoint['methods'],
204
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
+							: array(),
206
+					);
207
+					if (isset($data_for_single_endpoint['_links'])) {
208
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
+					}
210
+					if (isset($data_for_single_endpoint['callback_args'])) {
211
+						$callback_args = $data_for_single_endpoint['callback_args'];
212
+						$single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
213
+							$callback,
214
+							$callback_args
215
+						) {
216
+							array_unshift($callback_args, $request);
217
+							return call_user_func_array(
218
+								$callback,
219
+								$callback_args
220
+							);
221
+						};
222
+					} else {
223
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
+					}
225
+					$multiple_endpoint_args[] = $single_endpoint_args;
226
+				}
227
+				if (isset($data_for_multiple_endpoints['schema'])) {
228
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
229
+					$schema_callback = $schema_route_data['schema_callback'];
230
+					$callback_args = $schema_route_data['callback_args'];
231
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
232
+						return call_user_func_array(
233
+							$schema_callback,
234
+							$callback_args
235
+						);
236
+					};
237
+				}
238
+				register_rest_route(
239
+					$namespace,
240
+					$relative_route,
241
+					$multiple_endpoint_args
242
+				);
243
+			}
244
+		}
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 * Checks if there was a version change or something that merits invalidating the cached
251
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
252
+	 * next time the WP API is used
253
+	 */
254
+	public static function invalidate_cached_route_data_on_version_change()
255
+	{
256
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
257
+			EED_Core_Rest_Api::invalidate_cached_route_data();
258
+		}
259
+		foreach (EE_Registry::instance()->addons as $addon) {
260
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
261
+				EED_Core_Rest_Api::invalidate_cached_route_data();
262
+			}
263
+		}
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
270
+	 */
271
+	public static function invalidate_cached_route_data()
272
+	{
273
+		//delete the saved EE REST API routes
274
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
276
+		}
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * Gets the EE route data
283
+	 *
284
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
285
+	 * @throws \EE_Error
286
+	 * @type string|array $callback
287
+	 * @type string       $methods
288
+	 * @type boolean      $hidden_endpoint
289
+	 * }
290
+	 */
291
+	public static function get_ee_route_data()
292
+	{
293
+		$ee_routes = array();
294
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
295
+			$ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
296
+				$version,
297
+				$hidden_endpoints
298
+			);
299
+		}
300
+		return $ee_routes;
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 * Gets the EE route data from the wp options if it exists already,
307
+	 * otherwise re-generates it and saves it to the option
308
+	 *
309
+	 * @param string  $version
310
+	 * @param boolean $hidden_endpoints
311
+	 * @return array
312
+	 * @throws \EE_Error
313
+	 */
314
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315
+	{
316
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
+		if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319
+		}
320
+		return $ee_routes;
321
+	}
322
+
323
+
324
+
325
+	/**
326
+	 * Saves the EE REST API route data to a wp option and returns it
327
+	 *
328
+	 * @param string  $version
329
+	 * @param boolean $hidden_endpoints
330
+	 * @return mixed|null
331
+	 * @throws \EE_Error
332
+	 */
333
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
334
+	{
335
+		$instance = self::instance();
336
+		$routes = apply_filters(
337
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
338
+			array_replace_recursive(
339
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
340
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
341
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
342
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343
+			)
344
+		);
345
+		$option_name = self::saved_routes_option_names . $version;
346
+		if (get_option($option_name)) {
347
+			update_option($option_name, $routes, true);
348
+		} else {
349
+			add_option($option_name, $routes, null, 'no');
350
+		}
351
+		return $routes;
352
+	}
353
+
354
+
355
+
356
+	/**
357
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
358
+	 * need to calculate it on every request
359
+	 *
360
+	 * @deprecated since version 4.9.1
361
+	 * @return void
362
+	 */
363
+	public static function save_ee_routes()
364
+	{
365
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
366
+			$instance = self::instance();
367
+			$routes = apply_filters(
368
+				'EED_Core_Rest_Api__save_ee_routes__routes',
369
+				array_replace_recursive(
370
+					$instance->_register_config_routes(),
371
+					$instance->_register_meta_routes(),
372
+					$instance->_register_model_routes(),
373
+					$instance->_register_rpc_routes()
374
+				)
375
+			);
376
+			update_option(self::saved_routes_option_names, $routes, true);
377
+		}
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Gets all the route information relating to EE models
384
+	 *
385
+	 * @return array @see get_ee_route_data
386
+	 * @deprecated since version 4.9.1
387
+	 */
388
+	protected function _register_model_routes()
389
+	{
390
+		$model_routes = array();
391
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
392
+			$model_routes[EED_Core_Rest_Api::ee_api_namespace
393
+						  . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
394
+		}
395
+		return $model_routes;
396
+	}
397
+
398
+
399
+
400
+	/**
401
+	 * Decides whether or not to add write endpoints for this model.
402
+	 *
403
+	 * Currently, this defaults to exclude all global tables and models
404
+	 * which would allow inserting WP core data (we don't want to duplicate
405
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
406
+	 * @param EEM_Base $model
407
+	 * @return bool
408
+	 */
409
+	public static function should_have_write_endpoints(EEM_Base $model)
410
+	{
411
+		if ($model->is_wp_core_model()){
412
+			return false;
413
+		}
414
+		foreach($model->get_tables() as $table){
415
+			if( $table->is_global()){
416
+				return false;
417
+			}
418
+		}
419
+		return true;
420
+	}
421
+
422
+
423
+
424
+	/**
425
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
426
+	 * in this versioned namespace of EE4
427
+	 * @param $version
428
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429
+	 */
430
+	public static function model_names_with_plural_routes($version){
431
+		$model_version_info = new ModelVersionInfo($version);
432
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
433
+		//let's not bother having endpoints for extra metas
434
+		unset(
435
+			$models_to_register['Extra_Meta'],
436
+			$models_to_register['Extra_Join'],
437
+			$models_to_register['Post_Meta']
438
+		);
439
+		return apply_filters(
440
+			'FHEE__EED_Core_REST_API___register_model_routes',
441
+			$models_to_register
442
+		);
443
+	}
444
+
445
+
446
+
447
+	/**
448
+	 * Gets the route data for EE models in the specified version
449
+	 *
450
+	 * @param string  $version
451
+	 * @param boolean $hidden_endpoint
452
+	 * @return array
453
+	 * @throws EE_Error
454
+	 */
455
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
456
+	{
457
+		$model_routes = array();
458
+		$model_version_info = new ModelVersionInfo($version);
459
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460
+			$model = \EE_Registry::instance()->load_model($model_name);
461
+			//if this isn't a valid model then let's skip iterate to the next item in the loop.
462
+			if (! $model instanceof EEM_Base) {
463
+				continue;
464
+			}
465
+			//yes we could just register one route for ALL models, but then they wouldn't show up in the index
466
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
467
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
468
+			$model_routes[$plural_model_route] = array(
469
+				array(
470
+					'callback'        => array(
471
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
472
+						'handleRequestGetAll',
473
+					),
474
+					'callback_args'   => array($version, $model_name),
475
+					'methods'         => WP_REST_Server::READABLE,
476
+					'hidden_endpoint' => $hidden_endpoint,
477
+					'args'            => $this->_get_read_query_params($model, $version),
478
+					'_links'          => array(
479
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
480
+					),
481
+				),
482
+				'schema' => array(
483
+					'schema_callback' => array(
484
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
485
+						'handleSchemaRequest',
486
+					),
487
+					'callback_args'   => array($version, $model_name),
488
+				),
489
+			);
490
+			$model_routes[$singular_model_route] = array(
491
+				array(
492
+					'callback'        => array(
493
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
494
+						'handleRequestGetOne',
495
+					),
496
+					'callback_args'   => array($version, $model_name),
497
+					'methods'         => WP_REST_Server::READABLE,
498
+					'hidden_endpoint' => $hidden_endpoint,
499
+					'args'            => $this->_get_response_selection_query_params($model, $version),
500
+				),
501
+			);
502
+			if( apply_filters(
503
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
505
+				$model
506
+			)){
507
+				$model_routes[$plural_model_route][] = array(
508
+					'callback'        => array(
509
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
510
+						'handleRequestInsert',
511
+					),
512
+					'callback_args'   => array($version, $model_name),
513
+					'methods'         => WP_REST_Server::CREATABLE,
514
+					'hidden_endpoint' => $hidden_endpoint,
515
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
516
+				);
517
+				$model_routes[$singular_model_route] = array_merge(
518
+					$model_routes[$singular_model_route],
519
+					array(
520
+						array(
521
+							'callback'        => array(
522
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
523
+								'handleRequestUpdate',
524
+							),
525
+							'callback_args'   => array($version, $model_name),
526
+							'methods'         => WP_REST_Server::EDITABLE,
527
+							'hidden_endpoint' => $hidden_endpoint,
528
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
529
+						),
530
+						array(
531
+							'callback'        => array(
532
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
533
+								'handleRequestDelete',
534
+							),
535
+							'callback_args'   => array($version, $model_name),
536
+							'methods'         => WP_REST_Server::DELETABLE,
537
+							'hidden_endpoint' => $hidden_endpoint,
538
+							'args'            => $this->_get_delete_query_params($model, $version),
539
+						)
540
+					)
541
+				);
542
+			}
543
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
544
+
545
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
546
+					$model,
547
+					'(?P<id>[^\/]+)',
548
+					$relation_obj
549
+				);
550
+				$endpoints = array(
551
+					array(
552
+						'callback'        => array(
553
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
554
+							'handleRequestGetRelated',
555
+						),
556
+						'callback_args'   => array($version, $model_name, $relation_name),
557
+						'methods'         => WP_REST_Server::READABLE,
558
+						'hidden_endpoint' => $hidden_endpoint,
559
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
560
+					),
561
+				);
562
+				$model_routes[$related_route] = $endpoints;
563
+			}
564
+		}
565
+		return $model_routes;
566
+	}
567
+
568
+
569
+
570
+	/**
571
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
572
+	 * excluding the preceding slash.
573
+	 * Eg you pass get_plural_route_to('Event') = 'events'
574
+	 *
575
+	 * @param EEM_Base $model
576
+	 * @return string
577
+	 */
578
+	public static function get_collection_route(EEM_Base $model)
579
+	{
580
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
587
+	 * excluding the preceding slash.
588
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
589
+	 *
590
+	 * @param EEM_Base $model eg Event or Venue
591
+	 * @param string $id
592
+	 * @return string
593
+	 */
594
+	public static function get_entity_route($model, $id)
595
+	{
596
+		return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
597
+	}
598
+
599
+
600
+	/**
601
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
602
+	 * excluding the preceding slash.
603
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
604
+	 *
605
+	 * @param EEM_Base                 $model eg Event or Venue
606
+	 * @param string                 $id
607
+	 * @param EE_Model_Relation_Base $relation_obj
608
+	 * @return string
609
+	 */
610
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
611
+	{
612
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
613
+			$relation_obj->get_other_model()->get_this_model_name(),
614
+			$relation_obj
615
+		);
616
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
617
+	}
618
+
619
+
620
+
621
+	/**
622
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
623
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
624
+	 * @param string $relative_route
625
+	 * @param string $version
626
+	 * @return string
627
+	 */
628
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
630
+	}
631
+
632
+
633
+
634
+	/**
635
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
636
+	 * routes that don't conform to the traditional REST CRUD-style).
637
+	 *
638
+	 * @deprecated since 4.9.1
639
+	 */
640
+	protected function _register_rpc_routes()
641
+	{
642
+		$routes = array();
643
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
644
+			$routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
645
+				$version,
646
+				$hidden_endpoint
647
+			);
648
+		}
649
+		return $routes;
650
+	}
651
+
652
+
653
+
654
+	/**
655
+	 * @param string  $version
656
+	 * @param boolean $hidden_endpoint
657
+	 * @return array
658
+	 */
659
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
660
+	{
661
+		$this_versions_routes = array();
662
+		//checkin endpoint
663
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
664
+			array(
665
+				'callback'        => array(
666
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
667
+					'handleRequestToggleCheckin',
668
+				),
669
+				'methods'         => WP_REST_Server::CREATABLE,
670
+				'hidden_endpoint' => $hidden_endpoint,
671
+				'args'            => array(
672
+					'force' => array(
673
+						'required'    => false,
674
+						'default'     => false,
675
+						'description' => __(
676
+							// @codingStandardsIgnoreStart
677
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
678
+							// @codingStandardsIgnoreEnd
679
+							'event_espresso'
680
+						),
681
+					),
682
+				),
683
+				'callback_args'   => array($version),
684
+			),
685
+		);
686
+		return apply_filters(
687
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
688
+			$this_versions_routes,
689
+			$version,
690
+			$hidden_endpoint
691
+		);
692
+	}
693
+
694
+
695
+
696
+	/**
697
+	 * Gets the query params that can be used when request one or many
698
+	 *
699
+	 * @param EEM_Base $model
700
+	 * @param string   $version
701
+	 * @return array
702
+	 */
703
+	protected function _get_response_selection_query_params(\EEM_Base $model, $version)
704
+	{
705
+		return apply_filters(
706
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
707
+			array(
708
+				'include'   => array(
709
+					'required' => false,
710
+					'default'  => '*',
711
+					'type'     => 'string',
712
+				),
713
+				'calculate' => array(
714
+					'required'          => false,
715
+					'default'           => '',
716
+					'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
717
+					'type'              => 'string',
718
+					//because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
719
+					//freaks out. We'll just validate this argument while handling the request
720
+					'validate_callback' => null,
721
+					'sanitize_callback' => null,
722
+				),
723
+			),
724
+			$model,
725
+			$version
726
+		);
727
+	}
728
+
729
+
730
+
731
+	/**
732
+	 * Gets the parameters acceptable for delete requests
733
+	 *
734
+	 * @param \EEM_Base $model
735
+	 * @param string    $version
736
+	 * @return array
737
+	 */
738
+	protected function _get_delete_query_params(\EEM_Base $model, $version)
739
+	{
740
+		$params_for_delete = array(
741
+			'allow_blocking' => array(
742
+				'required' => false,
743
+				'default'  => true,
744
+				'type'     => 'boolean',
745
+			),
746
+		);
747
+		$params_for_delete['force'] = array(
748
+			'required' => false,
749
+			'default'  => false,
750
+			'type'     => 'boolean',
751
+		);
752
+		return apply_filters(
753
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
754
+			$params_for_delete,
755
+			$model,
756
+			$version
757
+		);
758
+	}
759
+
760
+
761
+
762
+	/**
763
+	 * Gets info about reading query params that are acceptable
764
+	 *
765
+	 * @param \EEM_Base $model eg 'Event' or 'Venue'
766
+	 * @param  string   $version
767
+	 * @return array    describing the args acceptable when querying this model
768
+	 * @throws EE_Error
769
+	 */
770
+	protected function _get_read_query_params(\EEM_Base $model, $version)
771
+	{
772
+		$default_orderby = array();
773
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
774
+			$default_orderby[$key_field->get_name()] = 'ASC';
775
+		}
776
+		return array_merge(
777
+			$this->_get_response_selection_query_params($model, $version),
778
+			array(
779
+				'where'    => array(
780
+					'required' => false,
781
+					'default'  => array(),
782
+					'type'     => 'object',
783
+					//because we accept an almost infinite list of possible where conditions, WP
784
+					// core validation and sanitization freaks out. We'll just validate this argument
785
+					// while handling the request
786
+					'validate_callback' => null,
787
+					'sanitize_callback' => null,
788
+				),
789
+				'limit'    => array(
790
+					'required' => false,
791
+					'default'  => EED_Core_Rest_Api::get_default_query_limit(),
792
+					'type'     => array(
793
+						'array',
794
+						'string',
795
+						'integer',
796
+					),
797
+					//because we accept a variety of types, WP core validation and sanitization
798
+					//freaks out. We'll just validate this argument while handling the request
799
+					'validate_callback' => null,
800
+					'sanitize_callback' => null,
801
+				),
802
+				'order_by' => array(
803
+					'required' => false,
804
+					'default'  => $default_orderby,
805
+					'type'     => array(
806
+						'object',
807
+						'string',
808
+					),//because we accept a variety of types, WP core validation and sanitization
809
+					//freaks out. We'll just validate this argument while handling the request
810
+					'validate_callback' => null,
811
+					'sanitize_callback' => null,
812
+				),
813
+				'group_by' => array(
814
+					'required' => false,
815
+					'default'  => null,
816
+					'type'     => array(
817
+						'object',
818
+						'string',
819
+					),
820
+					//because we accept  an almost infinite list of possible groupings,
821
+					// WP core validation and sanitization
822
+					//freaks out. We'll just validate this argument while handling the request
823
+					'validate_callback' => null,
824
+					'sanitize_callback' => null,
825
+				),
826
+				'having'   => array(
827
+					'required' => false,
828
+					'default'  => null,
829
+					'type'     => 'object',
830
+					//because we accept an almost infinite list of possible where conditions, WP
831
+					// core validation and sanitization freaks out. We'll just validate this argument
832
+					// while handling the request
833
+					'validate_callback' => null,
834
+					'sanitize_callback' => null,
835
+				),
836
+				'caps'     => array(
837
+					'required' => false,
838
+					'default'  => EEM_Base::caps_read,
839
+					'type'     => 'string',
840
+					'enum'     => array(
841
+						EEM_Base::caps_read,
842
+						EEM_Base::caps_read_admin,
843
+						EEM_Base::caps_edit,
844
+						EEM_Base::caps_delete
845
+					)
846
+				),
847
+			)
848
+		);
849
+	}
850
+
851
+
852
+
853
+	/**
854
+	 * Gets parameter information for a model regarding writing data
855
+	 *
856
+	 * @param string           $model_name
857
+	 * @param ModelVersionInfo $model_version_info
858
+	 * @param boolean          $create                                       whether this is for request to create (in which case we need
859
+	 *                                                                       all required params) or just to update (in which case we don't need those on every request)
860
+	 * @return array
861
+	 */
862
+	protected function _get_write_params(
863
+		$model_name,
864
+		ModelVersionInfo $model_version_info,
865
+		$create = false
866
+	) {
867
+		$model = EE_Registry::instance()->load_model($model_name);
868
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
869
+		$args_info = array();
870
+		foreach ($fields as $field_name => $field_obj) {
871
+			if ($field_obj->is_auto_increment()) {
872
+				//totally ignore auto increment IDs
873
+				continue;
874
+			}
875
+			$arg_info = $field_obj->getSchema();
876
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
877
+			$arg_info['required'] = $required;
878
+			//remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
879
+			unset($arg_info['readonly']);
880
+			$schema_properties = $field_obj->getSchemaProperties();
881
+			if (
882
+				isset($schema_properties['raw'])
883
+				&& $field_obj->getSchemaType() === 'object'
884
+			) {
885
+				//if there's a "raw" form of this argument, use those properties instead
886
+				$arg_info = array_replace(
887
+					$arg_info,
888
+					$schema_properties['raw']
889
+				);
890
+			}
891
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
892
+				$field_obj,
893
+				$field_obj->get_default_value(),
894
+				$model_version_info->requestedVersion()
895
+			);
896
+			//we do our own validation and sanitization within the controller
897
+			if(function_exists('rest_validate_value_from_schema')){
898
+				$sanitize_callback = array(
899
+					'EED_Core_Rest_Api',
900
+					'default_sanitize_callback',
901
+				);
902
+			} else {
903
+				$sanitize_callback = null;
904
+			}
905
+			$arg_info['sanitize_callback'] = $sanitize_callback;
906
+			$args_info[$field_name] = $arg_info;
907
+			if ($field_obj instanceof EE_Datetime_Field) {
908
+				$gmt_arg_info = $arg_info;
909
+				$gmt_arg_info['description'] = sprintf(
910
+					esc_html__(
911
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
912
+						'event_espresso'
913
+					),
914
+					$field_obj->get_nicename(),
915
+					$field_name
916
+				);
917
+				$args_info[$field_name . '_gmt'] = $gmt_arg_info;
918
+			}
919
+		}
920
+		return $args_info;
921
+	}
922
+
923
+
924
+
925
+	/**
926
+	 * Replacement for WP API's 'rest_parse_request_arg'.
927
+	 * If the value is blank but not required, don't bother validating it.
928
+	 * Also, it uses our email validation instead of WP API's default.
929
+	 *
930
+	 * @param                 $value
931
+	 * @param WP_REST_Request $request
932
+	 * @param                 $param
933
+	 * @return bool|true|WP_Error
934
+	 * @throws InvalidArgumentException
935
+	 * @throws InvalidInterfaceException
936
+	 * @throws InvalidDataTypeException
937
+	 */
938
+	public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
939
+	{
940
+		$attributes = $request->get_attributes();
941
+		if (! isset($attributes['args'][$param])
942
+			|| ! is_array($attributes['args'][$param])) {
943
+			$validation_result = true;
944
+		} else {
945
+			$args = $attributes['args'][$param];
946
+			if ((
947
+					$value === ''
948
+					|| $value === null
949
+				)
950
+				&& (! isset($args['required'])
951
+					|| $args['required'] === false
952
+				)
953
+			) {
954
+				//not required and not provided? that's cool
955
+				$validation_result = true;
956
+			} elseif (isset($args['format'])
957
+				&& $args['format'] === 'email'
958
+			) {
959
+				$validation_result = true;
960
+				if (! self::_validate_email($value)) {
961
+					$validation_result = new WP_Error(
962
+						'rest_invalid_param',
963
+						esc_html__(
964
+							'The email address is not valid or does not exist.',
965
+							'event_espresso'
966
+						)
967
+					);
968
+				}
969
+			} else {
970
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
971
+			}
972
+		}
973
+		if (is_wp_error($validation_result)) {
974
+			return $validation_result;
975
+		}
976
+		return rest_sanitize_request_arg($value, $request, $param);
977
+	}
978
+
979
+
980
+
981
+	/**
982
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
983
+	 *
984
+	 * @param $email
985
+	 * @return bool
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidInterfaceException
988
+	 * @throws InvalidDataTypeException
989
+	 */
990
+	protected static function _validate_email($email){
991
+		try {
992
+			EmailAddressFactory::create($email);
993
+			return true;
994
+		} catch (EmailValidationException $e) {
995
+			return false;
996
+		}
997
+	}
998
+
999
+
1000
+
1001
+	/**
1002
+	 * Gets routes for the config
1003
+	 *
1004
+	 * @return array @see _register_model_routes
1005
+	 * @deprecated since version 4.9.1
1006
+	 */
1007
+	protected function _register_config_routes()
1008
+	{
1009
+		$config_routes = array();
1010
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
+			$config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1012
+				$version,
1013
+				$hidden_endpoint
1014
+			);
1015
+		}
1016
+		return $config_routes;
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * Gets routes for the config for the specified version
1023
+	 *
1024
+	 * @param string  $version
1025
+	 * @param boolean $hidden_endpoint
1026
+	 * @return array
1027
+	 */
1028
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1029
+	{
1030
+		return array(
1031
+			'config'    => array(
1032
+				array(
1033
+					'callback'        => array(
1034
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1035
+						'handleRequest',
1036
+					),
1037
+					'methods'         => WP_REST_Server::READABLE,
1038
+					'hidden_endpoint' => $hidden_endpoint,
1039
+					'callback_args'   => array($version),
1040
+				),
1041
+			),
1042
+			'site_info' => array(
1043
+				array(
1044
+					'callback'        => array(
1045
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1046
+						'handleRequestSiteInfo',
1047
+					),
1048
+					'methods'         => WP_REST_Server::READABLE,
1049
+					'hidden_endpoint' => $hidden_endpoint,
1050
+					'callback_args'   => array($version),
1051
+				),
1052
+			),
1053
+		);
1054
+	}
1055
+
1056
+
1057
+
1058
+	/**
1059
+	 * Gets the meta info routes
1060
+	 *
1061
+	 * @return array @see _register_model_routes
1062
+	 * @deprecated since version 4.9.1
1063
+	 */
1064
+	protected function _register_meta_routes()
1065
+	{
1066
+		$meta_routes = array();
1067
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
+			$meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1069
+				$version,
1070
+				$hidden_endpoint
1071
+			);
1072
+		}
1073
+		return $meta_routes;
1074
+	}
1075
+
1076
+
1077
+
1078
+	/**
1079
+	 * @param string  $version
1080
+	 * @param boolean $hidden_endpoint
1081
+	 * @return array
1082
+	 */
1083
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1084
+	{
1085
+		return array(
1086
+			'resources' => array(
1087
+				array(
1088
+					'callback'        => array(
1089
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1090
+						'handleRequestModelsMeta',
1091
+					),
1092
+					'methods'         => WP_REST_Server::READABLE,
1093
+					'hidden_endpoint' => $hidden_endpoint,
1094
+					'callback_args'   => array($version),
1095
+				),
1096
+			),
1097
+		);
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * Tries to hide old 4.6 endpoints from the
1104
+	 *
1105
+	 * @param array $route_data
1106
+	 * @return array
1107
+	 * @throws \EE_Error
1108
+	 */
1109
+	public static function hide_old_endpoints($route_data)
1110
+	{
1111
+		//allow API clients to override which endpoints get hidden, in case
1112
+		//they want to discover particular endpoints
1113
+		//also, we don't have access to the request so we have to just grab it from the superglobal
1114
+		$force_show_ee_namespace = ltrim(
1115
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1116
+			'/'
1117
+		);
1118
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1119
+			foreach ($relative_urls as $resource_name => $endpoints) {
1120
+				foreach ($endpoints as $key => $endpoint) {
1121
+					//skip schema and other route options
1122
+					if (! is_numeric($key)) {
1123
+						continue;
1124
+					}
1125
+					//by default, hide "hidden_endpoint"s, unless the request indicates
1126
+					//to $force_show_ee_namespace, in which case only show that one
1127
+					//namespace's endpoints (and hide all others)
1128
+					if (
1129
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131
+					) {
1132
+						$full_route = '/' . ltrim($namespace, '/');
1133
+						$full_route .= '/' . ltrim($resource_name, '/');
1134
+						unset($route_data[$full_route]);
1135
+					}
1136
+				}
1137
+			}
1138
+		}
1139
+		return $route_data;
1140
+	}
1141
+
1142
+
1143
+
1144
+	/**
1145
+	 * Returns an array describing which versions of core support serving requests for.
1146
+	 * Keys are core versions' major and minor version, and values are the
1147
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1148
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1149
+	 * the answers table entirely, in which case it would be very difficult for
1150
+	 * it to serve 4.6-style responses.
1151
+	 * Versions of core that are missing from this array are unknowns.
1152
+	 * previous ver
1153
+	 *
1154
+	 * @return array
1155
+	 */
1156
+	public static function version_compatibilities()
1157
+	{
1158
+		return apply_filters(
1159
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1160
+			array(
1161
+				'4.8.29' => '4.8.29',
1162
+				'4.8.33' => '4.8.29',
1163
+				'4.8.34' => '4.8.29',
1164
+				'4.8.36' => '4.8.29',
1165
+			)
1166
+		);
1167
+	}
1168
+
1169
+
1170
+
1171
+	/**
1172
+	 * Gets the latest API version served. Eg if there
1173
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1174
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1175
+	 *
1176
+	 * @return string
1177
+	 */
1178
+	public static function latest_rest_api_version()
1179
+	{
1180
+		$versions_served = \EED_Core_Rest_Api::versions_served();
1181
+		$versions_served_keys = array_keys($versions_served);
1182
+		return end($versions_served_keys);
1183
+	}
1184
+
1185
+
1186
+
1187
+	/**
1188
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1189
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1190
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1191
+	 * We also indicate whether or not this version should be put in the index or not
1192
+	 *
1193
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1194
+	 * are whether or not they should be hidden
1195
+	 */
1196
+	public static function versions_served()
1197
+	{
1198
+		$versions_served = array();
1199
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1200
+		$lowest_compatible_version = end($possibly_served_versions);
1201
+		reset($possibly_served_versions);
1202
+		$versions_served_historically = array_keys($possibly_served_versions);
1203
+		$latest_version = end($versions_served_historically);
1204
+		reset($versions_served_historically);
1205
+		//for each version of core we have ever served:
1206
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1207
+			//if it's not above the current core version, and it's compatible with the current version of core
1208
+			if ($key_versioned_endpoint === $latest_version) {
1209
+				//don't hide the latest version in the index
1210
+				$versions_served[$key_versioned_endpoint] = false;
1211
+			} elseif (
1212
+				$key_versioned_endpoint >= $lowest_compatible_version
1213
+				&& $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1214
+			) {
1215
+				//include, but hide, previous versions which are still supported
1216
+				$versions_served[$key_versioned_endpoint] = true;
1217
+			} elseif (apply_filters(
1218
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1219
+				false,
1220
+				$possibly_served_versions
1221
+			)) {
1222
+				//if a version is no longer supported, don't include it in index or list of versions served
1223
+				$versions_served[$key_versioned_endpoint] = true;
1224
+			}
1225
+		}
1226
+		return $versions_served;
1227
+	}
1228
+
1229
+
1230
+
1231
+	/**
1232
+	 * Gets the major and minor version of EE core's version string
1233
+	 *
1234
+	 * @return string
1235
+	 */
1236
+	public static function core_version()
1237
+	{
1238
+		return apply_filters(
1239
+			'FHEE__EED_Core_REST_API__core_version',
1240
+			implode(
1241
+				'.',
1242
+				array_slice(
1243
+					explode(
1244
+						'.',
1245
+						espresso_version()
1246
+					),
1247
+				0,
1248
+				3
1249
+				)
1250
+			)
1251
+		);
1252
+	}
1253
+
1254
+
1255
+
1256
+	/**
1257
+	 * Gets the default limit that should be used when querying for resources
1258
+	 *
1259
+	 * @return int
1260
+	 */
1261
+	public static function get_default_query_limit()
1262
+	{
1263
+		//we actually don't use a const because we want folks to always use
1264
+		//this method, not the const directly
1265
+		return apply_filters(
1266
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1267
+			50
1268
+		);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 *
1274
+	 * @param string $version api version string (i.e. '4.8.36')
1275
+	 * @return array
1276
+	 */
1277
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1278
+	{
1279
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1280
+		$model_names = self::model_names_with_plural_routes($version);
1281
+		$collection_routes = array();
1282
+		foreach ($model_names as $model_name => $model_class_name) {
1283
+			$collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1284
+														  . EEH_Inflector::pluralize_and_lower($model_name);
1285
+
1286
+		}
1287
+		return $collection_routes;
1288
+	}
1289
+
1290
+
1291
+
1292
+	/**
1293
+	 *    run - initial module setup
1294
+	 *
1295
+	 * @access    public
1296
+	 * @param  WP $WP
1297
+	 * @return    void
1298
+	 */
1299
+	public function run($WP)
1300
+	{
1301
+	}
1302 1302
 }
1303 1303
 
1304 1304
 // End of file EED_Core_Rest_Api.module.php
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
      */
132 132
     protected static function _set_hooks_for_changes()
133 133
     {
134
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
134
+        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES.'rest_api'.DS.'changes'), false);
135 135
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
136 136
             //ignore the base parent class
137 137
             //and legacy named classes
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
             ) {
141 141
                 continue;
142 142
             }
143
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
144 144
             if (class_exists($full_classname)) {
145 145
                 $instance_of_class = new $full_classname;
146 146
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -186,10 +186,10 @@  discard block
 block discarded – undo
186 186
                      * }
187 187
                      */
188 188
                     //skip route options
189
-                    if (! is_numeric($endpoint_key)) {
189
+                    if ( ! is_numeric($endpoint_key)) {
190 190
                         continue;
191 191
                     }
192
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
193 193
                         throw new EE_Error(
194 194
                             esc_html__(
195 195
                                 // @codingStandardsIgnoreStart
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
                     }
210 210
                     if (isset($data_for_single_endpoint['callback_args'])) {
211 211
                         $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
212
+                        $single_endpoint_args['callback'] = function(\WP_REST_Request $request) use (
213 213
                             $callback,
214 214
                             $callback_args
215 215
                         ) {
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
229 229
                     $schema_callback = $schema_route_data['schema_callback'];
230 230
                     $callback_args = $schema_route_data['callback_args'];
231
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
231
+                    $multiple_endpoint_args['schema'] = function() use ($schema_callback, $callback_args) {
232 232
                         return call_user_func_array(
233 233
                             $schema_callback,
234 234
                             $callback_args
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
     {
273 273
         //delete the saved EE REST API routes
274 274
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
275
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
275
+            delete_option(EED_Core_Rest_Api::saved_routes_option_names.$version);
276 276
         }
277 277
     }
278 278
 
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
     {
293 293
         $ee_routes = array();
294 294
         foreach (self::versions_served() as $version => $hidden_endpoints) {
295
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
295
+            $ee_routes[self::ee_api_namespace.$version] = self::_get_ee_route_data_for_version(
296 296
                 $version,
297 297
                 $hidden_endpoints
298 298
             );
@@ -313,8 +313,8 @@  discard block
 block discarded – undo
313 313
      */
314 314
     protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
315 315
     {
316
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
317
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
316
+        $ee_routes = get_option(self::saved_routes_option_names.$version, null);
317
+        if ( ! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
318 318
             $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
319 319
         }
320 320
         return $ee_routes;
@@ -342,7 +342,7 @@  discard block
 block discarded – undo
342 342
                 $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
343 343
             )
344 344
         );
345
-        $option_name = self::saved_routes_option_names . $version;
345
+        $option_name = self::saved_routes_option_names.$version;
346 346
         if (get_option($option_name)) {
347 347
             update_option($option_name, $routes, true);
348 348
         } else {
@@ -408,11 +408,11 @@  discard block
 block discarded – undo
408 408
      */
409 409
     public static function should_have_write_endpoints(EEM_Base $model)
410 410
     {
411
-        if ($model->is_wp_core_model()){
411
+        if ($model->is_wp_core_model()) {
412 412
             return false;
413 413
         }
414
-        foreach($model->get_tables() as $table){
415
-            if( $table->is_global()){
414
+        foreach ($model->get_tables() as $table) {
415
+            if ($table->is_global()) {
416 416
                 return false;
417 417
             }
418 418
         }
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
      * @param $version
428 428
      * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
429 429
      */
430
-    public static function model_names_with_plural_routes($version){
430
+    public static function model_names_with_plural_routes($version) {
431 431
         $model_version_info = new ModelVersionInfo($version);
432 432
         $models_to_register = $model_version_info->modelsForRequestedVersion();
433 433
         //let's not bother having endpoints for extra metas
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
460 460
             $model = \EE_Registry::instance()->load_model($model_name);
461 461
             //if this isn't a valid model then let's skip iterate to the next item in the loop.
462
-            if (! $model instanceof EEM_Base) {
462
+            if ( ! $model instanceof EEM_Base) {
463 463
                 continue;
464 464
             }
465 465
             //yes we could just register one route for ALL models, but then they wouldn't show up in the index
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
                     'hidden_endpoint' => $hidden_endpoint,
477 477
                     'args'            => $this->_get_read_query_params($model, $version),
478 478
                     '_links'          => array(
479
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
479
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
480 480
                     ),
481 481
                 ),
482 482
                 'schema' => array(
@@ -499,11 +499,11 @@  discard block
 block discarded – undo
499 499
                     'args'            => $this->_get_response_selection_query_params($model, $version),
500 500
                 ),
501 501
             );
502
-            if( apply_filters(
502
+            if (apply_filters(
503 503
                 'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
504 504
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
505 505
                 $model
506
-            )){
506
+            )) {
507 507
                 $model_routes[$plural_model_route][] = array(
508 508
                     'callback'        => array(
509 509
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
@@ -593,7 +593,7 @@  discard block
 block discarded – undo
593 593
      */
594 594
     public static function get_entity_route($model, $id)
595 595
     {
596
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
596
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
597 597
     }
598 598
 
599 599
 
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
             $relation_obj->get_other_model()->get_this_model_name(),
614 614
             $relation_obj
615 615
         );
616
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
616
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
617 617
     }
618 618
 
619 619
 
@@ -625,8 +625,8 @@  discard block
 block discarded – undo
625 625
      * @param string $version
626 626
      * @return string
627 627
      */
628
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
629
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
628
+    public static function get_versioned_route_to($relative_route, $version = '4.8.36') {
629
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
630 630
     }
631 631
 
632 632
 
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
     {
642 642
         $routes = array();
643 643
         foreach (self::versions_served() as $version => $hidden_endpoint) {
644
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
644
+            $routes[self::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
645 645
                 $version,
646 646
                 $hidden_endpoint
647 647
             );
@@ -805,7 +805,7 @@  discard block
 block discarded – undo
805 805
                     'type'     => array(
806 806
                         'object',
807 807
                         'string',
808
-                    ),//because we accept a variety of types, WP core validation and sanitization
808
+                    ), //because we accept a variety of types, WP core validation and sanitization
809 809
                     //freaks out. We'll just validate this argument while handling the request
810 810
                     'validate_callback' => null,
811 811
                     'sanitize_callback' => null,
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
                 $model_version_info->requestedVersion()
895 895
             );
896 896
             //we do our own validation and sanitization within the controller
897
-            if(function_exists('rest_validate_value_from_schema')){
897
+            if (function_exists('rest_validate_value_from_schema')) {
898 898
                 $sanitize_callback = array(
899 899
                     'EED_Core_Rest_Api',
900 900
                     'default_sanitize_callback',
@@ -914,7 +914,7 @@  discard block
 block discarded – undo
914 914
                     $field_obj->get_nicename(),
915 915
                     $field_name
916 916
                 );
917
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
917
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
918 918
             }
919 919
         }
920 920
         return $args_info;
@@ -935,10 +935,10 @@  discard block
 block discarded – undo
935 935
      * @throws InvalidInterfaceException
936 936
      * @throws InvalidDataTypeException
937 937
      */
938
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
938
+    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
939 939
     {
940 940
         $attributes = $request->get_attributes();
941
-        if (! isset($attributes['args'][$param])
941
+        if ( ! isset($attributes['args'][$param])
942 942
             || ! is_array($attributes['args'][$param])) {
943 943
             $validation_result = true;
944 944
         } else {
@@ -947,7 +947,7 @@  discard block
 block discarded – undo
947 947
                     $value === ''
948 948
                     || $value === null
949 949
                 )
950
-                && (! isset($args['required'])
950
+                && ( ! isset($args['required'])
951 951
                     || $args['required'] === false
952 952
                 )
953 953
             ) {
@@ -957,7 +957,7 @@  discard block
 block discarded – undo
957 957
                 && $args['format'] === 'email'
958 958
             ) {
959 959
                 $validation_result = true;
960
-                if (! self::_validate_email($value)) {
960
+                if ( ! self::_validate_email($value)) {
961 961
                     $validation_result = new WP_Error(
962 962
                         'rest_invalid_param',
963 963
                         esc_html__(
@@ -987,7 +987,7 @@  discard block
 block discarded – undo
987 987
      * @throws InvalidInterfaceException
988 988
      * @throws InvalidDataTypeException
989 989
      */
990
-    protected static function _validate_email($email){
990
+    protected static function _validate_email($email) {
991 991
         try {
992 992
             EmailAddressFactory::create($email);
993 993
             return true;
@@ -1008,7 +1008,7 @@  discard block
 block discarded – undo
1008 1008
     {
1009 1009
         $config_routes = array();
1010 1010
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1011
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1011
+            $config_routes[self::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1012 1012
                 $version,
1013 1013
                 $hidden_endpoint
1014 1014
             );
@@ -1065,7 +1065,7 @@  discard block
 block discarded – undo
1065 1065
     {
1066 1066
         $meta_routes = array();
1067 1067
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1068
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1068
+            $meta_routes[self::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1069 1069
                 $version,
1070 1070
                 $hidden_endpoint
1071 1071
             );
@@ -1119,7 +1119,7 @@  discard block
 block discarded – undo
1119 1119
             foreach ($relative_urls as $resource_name => $endpoints) {
1120 1120
                 foreach ($endpoints as $key => $endpoint) {
1121 1121
                     //skip schema and other route options
1122
-                    if (! is_numeric($key)) {
1122
+                    if ( ! is_numeric($key)) {
1123 1123
                         continue;
1124 1124
                     }
1125 1125
                     //by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1129,8 +1129,8 @@  discard block
 block discarded – undo
1129 1129
                         ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1130 1130
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1131 1131
                     ) {
1132
-                        $full_route = '/' . ltrim($namespace, '/');
1133
-                        $full_route .= '/' . ltrim($resource_name, '/');
1132
+                        $full_route = '/'.ltrim($namespace, '/');
1133
+                        $full_route .= '/'.ltrim($resource_name, '/');
1134 1134
                         unset($route_data[$full_route]);
1135 1135
                     }
1136 1136
                 }
@@ -1280,7 +1280,7 @@  discard block
 block discarded – undo
1280 1280
         $model_names = self::model_names_with_plural_routes($version);
1281 1281
         $collection_routes = array();
1282 1282
         foreach ($model_names as $model_name => $model_class_name) {
1283
-            $collection_routes[strtolower($model_name)] = '/' . self::ee_api_namespace . $version . '/'
1283
+            $collection_routes[strtolower($model_name)] = '/'.self::ee_api_namespace.$version.'/'
1284 1284
                                                           . EEH_Inflector::pluralize_and_lower($model_name);
1285 1285
 
1286 1286
         }
Please login to merge, or discard this patch.