Completed
Branch EDTR/routing (72994a)
by
unknown
35:59 queued 27:19
created
modules/core_rest_api/EED_Core_Rest_Api.module.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -780,7 +780,7 @@
 block discarded – undo
780 780
     /**
781 781
      * @param EEM_Base $source_model
782 782
      * @param EEM_Base $related_model
783
-     * @param          $version
783
+     * @param          string $version
784 784
      * @return array
785 785
      * @throws EE_Error
786 786
      * @since $VID:$
Please login to merge, or discard this patch.
Indentation   +1351 added lines, -1351 removed lines patch added patch discarded remove patch
@@ -22,1355 +22,1355 @@
 block discarded – undo
22 22
 class EED_Core_Rest_Api extends EED_Module
23 23
 {
24 24
 
25
-    const ee_api_namespace = Domain::API_NAMESPACE;
26
-
27
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
28
-
29
-    const saved_routes_option_names = 'ee_core_routes';
30
-
31
-    /**
32
-     * string used in _links response bodies to make them globally unique.
33
-     *
34
-     * @see http://v2.wp-api.org/extending/linking/
35
-     */
36
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
37
-
38
-    /**
39
-     * @var CalculatedModelFields
40
-     */
41
-    protected static $_field_calculator;
42
-
43
-
44
-    /**
45
-     * @return EED_Core_Rest_Api|EED_Module
46
-     */
47
-    public static function instance()
48
-    {
49
-        return parent::get_instance(EED_Core_Rest_Api::class);
50
-    }
51
-
52
-
53
-    /**
54
-     *    set_hooks - for hooking into EE Core, other modules, etc
55
-     *
56
-     * @access    public
57
-     * @return    void
58
-     */
59
-    public static function set_hooks()
60
-    {
61
-        EED_Core_Rest_Api::set_hooks_both();
62
-    }
63
-
64
-
65
-    /**
66
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
67
-     *
68
-     * @access    public
69
-     * @return    void
70
-     */
71
-    public static function set_hooks_admin()
72
-    {
73
-        EED_Core_Rest_Api::set_hooks_both();
74
-    }
75
-
76
-
77
-    public static function set_hooks_both()
78
-    {
79
-        /** @var EventEspresso\core\services\request\Request $request */
80
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
81
-        if (! $request->isWordPressApi()) {
82
-            return;
83
-        }
84
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
85
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
86
-        add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
87
-        add_filter(
88
-            'rest_index',
89
-            ['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
90
-        );
91
-        EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
-        );
94
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
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
-     * public wrapper of _set_hooks_for_changes.
113
-     * Loads all the hooks which make requests to old versions of the API
114
-     * appear the same as they always did
115
-     *
116
-     * @throws EE_Error
117
-     */
118
-    public static function set_hooks_for_changes()
119
-    {
120
-        EED_Core_Rest_Api::_set_hooks_for_changes();
121
-    }
122
-
123
-
124
-    /**
125
-     * Loads all the hooks which make requests to old versions of the API
126
-     * appear the same as they always did
127
-     *
128
-     * @throws EE_Error
129
-     */
130
-    protected static function _set_hooks_for_changes()
131
-    {
132
-        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
-            // ignore the base parent class
135
-            // and legacy named classes
136
-            if ($classname_in_namespace === 'ChangesInBase'
137
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
138
-            ) {
139
-                continue;
140
-            }
141
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
142
-            if (class_exists($full_classname)) {
143
-                $instance_of_class = new $full_classname;
144
-                if ($instance_of_class instanceof ChangesInBase) {
145
-                    $instance_of_class->setHooks();
146
-                }
147
-            }
148
-        }
149
-    }
150
-
151
-
152
-    /**
153
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
154
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
155
-     *
156
-     * @throws EE_Error
157
-     * @throws ReflectionException
158
-     */
159
-    public static function register_routes()
160
-    {
161
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
162
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
163
-                /**
164
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
165
-                 *                                         but can also contain route options like {
166
-                 * @type array    $schema                      {
167
-                 * @type callable $schema_callback
168
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
169
-                 * WP_REST_Request of course
170
-                 * }
171
-                 * }
172
-                 */
173
-                // when registering routes, register all the endpoints' data at the same time
174
-                $multiple_endpoint_args = [];
175
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
176
-                    /**
177
-                     * @var array     $data_for_single_endpoint {
178
-                     * @type callable $callback
179
-                     * @type string methods
180
-                     * @type array args
181
-                     * @type array _links
182
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
183
-                     * WP_REST_Request of course
184
-                     * }
185
-                     */
186
-                    // skip route options
187
-                    if (! is_numeric($endpoint_key)) {
188
-                        continue;
189
-                    }
190
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
191
-                        throw new EE_Error(
192
-                            esc_html__(
193
-                            // @codingStandardsIgnoreStart
194
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
195
-                                // @codingStandardsIgnoreEnd
196
-                                'event_espresso'
197
-                            )
198
-                        );
199
-                    }
200
-                    $callback = $data_for_single_endpoint['callback'];
201
-                    $single_endpoint_args = [
202
-                        'methods' => $data_for_single_endpoint['methods'],
203
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
204
-                            : [],
205
-                    ];
206
-                    if (isset($data_for_single_endpoint['_links'])) {
207
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
208
-                    }
209
-                    if (isset($data_for_single_endpoint['callback_args'])) {
210
-                        $callback_args = $data_for_single_endpoint['callback_args'];
211
-                        $single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
212
-                            $callback,
213
-                            $callback_args
214
-                        ) {
215
-                            array_unshift($callback_args, $request);
216
-                            return call_user_func_array(
217
-                                $callback,
218
-                                $callback_args
219
-                            );
220
-                        };
221
-                    } else {
222
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
223
-                    }
224
-                    $multiple_endpoint_args[] = $single_endpoint_args;
225
-                }
226
-                if (isset($data_for_multiple_endpoints['schema'])) {
227
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
228
-                    $schema_callback = $schema_route_data['schema_callback'];
229
-                    $callback_args = $schema_route_data['callback_args'];
230
-                    $multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
231
-                        return call_user_func_array(
232
-                            $schema_callback,
233
-                            $callback_args
234
-                        );
235
-                    };
236
-                }
237
-                register_rest_route(
238
-                    $namespace,
239
-                    $relative_route,
240
-                    $multiple_endpoint_args
241
-                );
242
-            }
243
-        }
244
-    }
245
-
246
-
247
-    /**
248
-     * Checks if there was a version change or something that merits invalidating the cached
249
-     * route data. If so, invalidates the cached route data so that it gets refreshed
250
-     * next time the WP API is used
251
-     */
252
-    public static function invalidate_cached_route_data_on_version_change()
253
-    {
254
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
255
-            EED_Core_Rest_Api::invalidate_cached_route_data();
256
-        }
257
-        foreach (EE_Registry::instance()->addons as $addon) {
258
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
259
-                EED_Core_Rest_Api::invalidate_cached_route_data();
260
-            }
261
-        }
262
-    }
263
-
264
-
265
-    /**
266
-     * Removes the cached route data so it will get refreshed next time the WP API is used
267
-     */
268
-    public static function invalidate_cached_route_data()
269
-    {
270
-        // delete the saved EE REST API routes
271
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
272
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
273
-        }
274
-    }
275
-
276
-
277
-    /**
278
-     * Gets the EE route data
279
-     *
280
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
281
-     * @throws EE_Error
282
-     * @throws ReflectionException
283
-     * @type string|array $callback
284
-     * @type string       $methods
285
-     * @type boolean      $hidden_endpoint
286
-     * }
287
-     */
288
-    public static function get_ee_route_data()
289
-    {
290
-        $ee_routes = [];
291
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
292
-            $ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
293
-                $version,
294
-                $hidden_endpoints
295
-            );
296
-        }
297
-        return $ee_routes;
298
-    }
299
-
300
-
301
-    /**
302
-     * Gets the EE route data from the wp options if it exists already,
303
-     * otherwise re-generates it and saves it to the option
304
-     *
305
-     * @param string  $version
306
-     * @param boolean $hidden_endpoints
307
-     * @return array
308
-     * @throws EE_Error
309
-     * @throws ReflectionException
310
-     */
311
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
312
-    {
313
-        $ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
314
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
315
-            $ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
316
-        }
317
-        return $ee_routes;
318
-    }
319
-
320
-
321
-    /**
322
-     * Saves the EE REST API route data to a wp option and returns it
323
-     *
324
-     * @param string  $version
325
-     * @param boolean $hidden_endpoints
326
-     * @return mixed|null
327
-     * @throws EE_Error
328
-     * @throws ReflectionException
329
-     */
330
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
331
-    {
332
-        $instance = EED_Core_Rest_Api::instance();
333
-        $routes = apply_filters(
334
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
335
-            array_replace_recursive(
336
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
337
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
338
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
339
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
340
-            )
341
-        );
342
-        $option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
343
-        if (get_option($option_name)) {
344
-            update_option($option_name, $routes, true);
345
-        } else {
346
-            add_option($option_name, $routes, null, 'no');
347
-        }
348
-        return $routes;
349
-    }
350
-
351
-
352
-    /**
353
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
354
-     * need to calculate it on every request
355
-     *
356
-     * @return void
357
-     * @deprecated since version 4.9.1
358
-     */
359
-    public static function save_ee_routes()
360
-    {
361
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
362
-            $instance = EED_Core_Rest_Api::instance();
363
-            $routes = apply_filters(
364
-                'EED_Core_Rest_Api__save_ee_routes__routes',
365
-                array_replace_recursive(
366
-                    $instance->_register_config_routes(),
367
-                    $instance->_register_meta_routes(),
368
-                    $instance->_register_model_routes(),
369
-                    $instance->_register_rpc_routes()
370
-                )
371
-            );
372
-            update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
373
-        }
374
-    }
375
-
376
-
377
-    /**
378
-     * Gets all the route information relating to EE models
379
-     *
380
-     * @return array @see get_ee_route_data
381
-     * @deprecated since version 4.9.1
382
-     */
383
-    protected function _register_model_routes()
384
-    {
385
-        $model_routes = [];
386
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
387
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
388
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
389
-        }
390
-        return $model_routes;
391
-    }
392
-
393
-
394
-    /**
395
-     * Decides whether or not to add write endpoints for this model.
396
-     * Currently, this defaults to exclude all global tables and models
397
-     * which would allow inserting WP core data (we don't want to duplicate
398
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
399
-     *
400
-     * @param EEM_Base $model
401
-     * @return bool
402
-     */
403
-    public static function should_have_write_endpoints(EEM_Base $model)
404
-    {
405
-        if ($model->is_wp_core_model()) {
406
-            return false;
407
-        }
408
-        foreach ($model->get_tables() as $table) {
409
-            if ($table->is_global()) {
410
-                return false;
411
-            }
412
-        }
413
-        return true;
414
-    }
415
-
416
-
417
-    /**
418
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
419
-     * in this versioned namespace of EE4
420
-     *
421
-     * @param $version
422
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
423
-     */
424
-    public static function model_names_with_plural_routes($version)
425
-    {
426
-        $model_version_info = new ModelVersionInfo($version);
427
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
428
-        // let's not bother having endpoints for extra metas
429
-        unset(
430
-            $models_to_register['Extra_Meta'],
431
-            $models_to_register['Extra_Join'],
432
-            $models_to_register['Post_Meta']
433
-        );
434
-        return apply_filters(
435
-            'FHEE__EED_Core_REST_API___register_model_routes',
436
-            $models_to_register
437
-        );
438
-    }
439
-
440
-
441
-    /**
442
-     * Gets the route data for EE models in the specified version
443
-     *
444
-     * @param string  $version
445
-     * @param boolean $hidden_endpoint
446
-     * @return array
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
451
-    {
452
-        $model_routes = [];
453
-        $model_version_info = new ModelVersionInfo($version);
454
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
455
-            $model = EE_Registry::instance()->load_model($model_name);
456
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
457
-            if (! $model instanceof EEM_Base) {
458
-                continue;
459
-            }
460
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
461
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
462
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
463
-            $model_routes[ $plural_model_route ] = [
464
-                [
465
-                    'callback'        => [
466
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
467
-                        'handleRequestGetAll',
468
-                    ],
469
-                    'callback_args'   => [$version, $model_name],
470
-                    'methods'         => WP_REST_Server::READABLE,
471
-                    'hidden_endpoint' => $hidden_endpoint,
472
-                    'args'            => $this->_get_read_query_params($model, $version),
473
-                    '_links'          => [
474
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
475
-                    ],
476
-                ],
477
-                'schema' => [
478
-                    'schema_callback' => [
479
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
480
-                        'handleSchemaRequest',
481
-                    ],
482
-                    'callback_args'   => [$version, $model_name],
483
-                ],
484
-            ];
485
-            $model_routes[ $singular_model_route ] = [
486
-                [
487
-                    'callback'        => [
488
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
489
-                        'handleRequestGetOne',
490
-                    ],
491
-                    'callback_args'   => [$version, $model_name],
492
-                    'methods'         => WP_REST_Server::READABLE,
493
-                    'hidden_endpoint' => $hidden_endpoint,
494
-                    'args'            => $this->_get_response_selection_query_params($model, $version, true),
495
-                ],
496
-            ];
497
-            if (apply_filters(
498
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
499
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
500
-                $model
501
-            )) {
502
-                $model_routes[ $plural_model_route ][] = [
503
-                    'callback'        => [
504
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
505
-                        'handleRequestInsert',
506
-                    ],
507
-                    'callback_args'   => [$version, $model_name],
508
-                    'methods'         => WP_REST_Server::CREATABLE,
509
-                    'hidden_endpoint' => $hidden_endpoint,
510
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
511
-                ];
512
-                $model_routes[ $singular_model_route ] = array_merge(
513
-                    $model_routes[ $singular_model_route ],
514
-                    [
515
-                        [
516
-                            'callback'        => [
517
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
518
-                                'handleRequestUpdate',
519
-                            ],
520
-                            'callback_args'   => [$version, $model_name],
521
-                            'methods'         => WP_REST_Server::EDITABLE,
522
-                            'hidden_endpoint' => $hidden_endpoint,
523
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
524
-                        ],
525
-                        [
526
-                            'callback'        => [
527
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
-                                'handleRequestDelete',
529
-                            ],
530
-                            'callback_args'   => [$version, $model_name],
531
-                            'methods'         => WP_REST_Server::DELETABLE,
532
-                            'hidden_endpoint' => $hidden_endpoint,
533
-                            'args'            => $this->_get_delete_query_params($model, $version),
534
-                        ],
535
-                    ]
536
-                );
537
-            }
538
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
539
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
540
-                    $model,
541
-                    '(?P<id>[^\/]+)',
542
-                    $relation_obj
543
-                );
544
-                $model_routes[ $related_route ] = [
545
-                    [
546
-                        'callback'        => [
547
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
548
-                            'handleRequestGetRelated',
549
-                        ],
550
-                        'callback_args'   => [$version, $model_name, $relation_name],
551
-                        'methods'         => WP_REST_Server::READABLE,
552
-                        'hidden_endpoint' => $hidden_endpoint,
553
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
554
-                    ],
555
-                ];
556
-
557
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
558
-                $model_routes[ $related_write_route ] = [
559
-                    [
560
-                        'callback'        => [
561
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
562
-                            'handleRequestAddRelation',
563
-                        ],
564
-                        'callback_args'   => [$version, $model_name, $relation_name],
565
-                        'methods'         => WP_REST_Server::EDITABLE,
566
-                        'hidden_endpoint' => $hidden_endpoint,
567
-                        'args'            => $this->_get_add_relation_query_params($model,
568
-                            $relation_obj->get_other_model(), $version),
569
-                    ],
570
-                    [
571
-                        'callback'        => [
572
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
573
-                            'handleRequestRemoveRelation',
574
-                        ],
575
-                        'callback_args'   => [$version, $model_name, $relation_name],
576
-                        'methods'         => WP_REST_Server::DELETABLE,
577
-                        'hidden_endpoint' => $hidden_endpoint,
578
-                        'args'            => [],
579
-                    ],
580
-                ];
581
-            }
582
-        }
583
-        return $model_routes;
584
-    }
585
-
586
-
587
-    /**
588
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
589
-     * excluding the preceding slash.
590
-     * Eg you pass get_plural_route_to('Event') = 'events'
591
-     *
592
-     * @param EEM_Base $model
593
-     * @return string
594
-     */
595
-    public static function get_collection_route(EEM_Base $model)
596
-    {
597
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
598
-    }
599
-
600
-
601
-    /**
602
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
603
-     * excluding the preceding slash.
604
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
605
-     *
606
-     * @param EEM_Base $model eg Event or Venue
607
-     * @param string   $id
608
-     * @return string
609
-     */
610
-    public static function get_entity_route($model, $id)
611
-    {
612
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
613
-    }
614
-
615
-
616
-    /**
617
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
618
-     * excluding the preceding slash.
619
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
620
-     *
621
-     * @param EEM_Base               $model eg Event or Venue
622
-     * @param string                 $id
623
-     * @param EE_Model_Relation_Base $relation_obj
624
-     * @return string
625
-     */
626
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
627
-    {
628
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
629
-            $relation_obj->get_other_model()->get_this_model_name(),
630
-            $relation_obj
631
-        );
632
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
633
-    }
634
-
635
-
636
-    /**
637
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
638
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
639
-     *
640
-     * @param string $relative_route
641
-     * @param string $version
642
-     * @return string
643
-     */
644
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
645
-    {
646
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
647
-    }
648
-
649
-
650
-    /**
651
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
652
-     * routes that don't conform to the traditional REST CRUD-style).
653
-     *
654
-     * @deprecated since 4.9.1
655
-     */
656
-    protected function _register_rpc_routes()
657
-    {
658
-        $routes = [];
659
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
660
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
661
-                $version,
662
-                $hidden_endpoint
663
-            );
664
-        }
665
-        return $routes;
666
-    }
667
-
668
-
669
-    /**
670
-     * @param string  $version
671
-     * @param boolean $hidden_endpoint
672
-     * @return array
673
-     */
674
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
675
-    {
676
-        $this_versions_routes = [];
677
-        // checkin endpoint
678
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
679
-            [
680
-                'callback'        => [
681
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
682
-                    'handleRequestToggleCheckin',
683
-                ],
684
-                'methods'         => WP_REST_Server::CREATABLE,
685
-                'hidden_endpoint' => $hidden_endpoint,
686
-                'args'            => [
687
-                    'force' => [
688
-                        'required'    => false,
689
-                        'default'     => false,
690
-                        'description' => __(
691
-                        // @codingStandardsIgnoreStart
692
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
693
-                            // @codingStandardsIgnoreEnd
694
-                            'event_espresso'
695
-                        ),
696
-                    ],
697
-                ],
698
-                'callback_args'   => [$version],
699
-            ],
700
-        ];
701
-        return apply_filters(
702
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
703
-            $this_versions_routes,
704
-            $version,
705
-            $hidden_endpoint
706
-        );
707
-    }
708
-
709
-
710
-    /**
711
-     * Gets the query params that can be used when request one or many
712
-     *
713
-     * @param EEM_Base $model
714
-     * @param string   $version
715
-     * @return array
716
-     */
717
-    protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
718
-    {
719
-        $query_params = [
720
-            'include'   => [
721
-                'required' => false,
722
-                'default'  => '*',
723
-                'type'     => 'string',
724
-            ],
725
-            'calculate' => [
726
-                'required'          => false,
727
-                'default'           => '',
728
-                'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
729
-                'type'              => 'string',
730
-                // because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
731
-                // freaks out. We'll just validate this argument while handling the request
732
-                'validate_callback' => null,
733
-                'sanitize_callback' => null,
734
-            ],
735
-            'password'  => [
736
-                'required' => false,
737
-                'default'  => '',
738
-                'type'     => 'string',
739
-            ],
740
-        ];
741
-        return apply_filters(
742
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
743
-            $query_params,
744
-            $model,
745
-            $version
746
-        );
747
-    }
748
-
749
-
750
-    /**
751
-     * Gets the parameters acceptable for delete requests
752
-     *
753
-     * @param EEM_Base $model
754
-     * @param string   $version
755
-     * @return array
756
-     */
757
-    protected function _get_delete_query_params(EEM_Base $model, $version)
758
-    {
759
-        $params_for_delete = [
760
-            'allow_blocking' => [
761
-                'required' => false,
762
-                'default'  => true,
763
-                'type'     => 'boolean',
764
-            ],
765
-        ];
766
-        $params_for_delete['force'] = [
767
-            'required' => false,
768
-            'default'  => false,
769
-            'type'     => 'boolean',
770
-        ];
771
-        return apply_filters(
772
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
773
-            $params_for_delete,
774
-            $model,
775
-            $version
776
-        );
777
-    }
778
-
779
-
780
-    /**
781
-     * @param EEM_Base $source_model
782
-     * @param EEM_Base $related_model
783
-     * @param          $version
784
-     * @return array
785
-     * @throws EE_Error
786
-     * @since $VID:$
787
-     */
788
-    protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
789
-    {
790
-        // if they're related through a HABTM relation, check for any non-FKs
791
-        $all_relation_settings = $source_model->relation_settings();
792
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
793
-        $params = [];
794
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
795
-            foreach ($relation_settings->getNonKeyFields() as $field) {
796
-                /* @var $field EE_Model_Field_Base */
797
-                $params[ $field->get_name() ] = [
798
-                    'required'          => ! $field->is_nullable(),
799
-                    'default'           => ModelDataTranslator::prepareFieldValueForJson($field,
800
-                        $field->get_default_value(), $version),
801
-                    'type'              => $field->getSchemaType(),
802
-                    'validate_callback' => null,
803
-                    'sanitize_callback' => null,
804
-                ];
805
-            }
806
-        }
807
-        return $params;
808
-    }
809
-
810
-
811
-    /**
812
-     * Gets info about reading query params that are acceptable
813
-     *
814
-     * @param EEM_Base $model eg 'Event' or 'Venue'
815
-     * @param string   $version
816
-     * @return array    describing the args acceptable when querying this model
817
-     * @throws EE_Error
818
-     */
819
-    protected function _get_read_query_params(EEM_Base $model, $version)
820
-    {
821
-        $default_orderby = [];
822
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
823
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
824
-        }
825
-        return array_merge(
826
-            $this->_get_response_selection_query_params($model, $version),
827
-            [
828
-                'where'    => [
829
-                    'required'          => false,
830
-                    'default'           => [],
831
-                    'type'              => 'object',
832
-                    // because we accept an almost infinite list of possible where conditions, WP
833
-                    // core validation and sanitization freaks out. We'll just validate this argument
834
-                    // while handling the request
835
-                    'validate_callback' => null,
836
-                    'sanitize_callback' => null,
837
-                ],
838
-                'limit'    => [
839
-                    'required'          => false,
840
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
841
-                    'type'              => [
842
-                        'array',
843
-                        'string',
844
-                        'integer',
845
-                    ],
846
-                    // because we accept a variety of types, WP core validation and sanitization
847
-                    // freaks out. We'll just validate this argument while handling the request
848
-                    'validate_callback' => null,
849
-                    'sanitize_callback' => null,
850
-                ],
851
-                'order_by' => [
852
-                    'required'          => false,
853
-                    'default'           => $default_orderby,
854
-                    'type'              => [
855
-                        'object',
856
-                        'string',
857
-                    ],// because we accept a variety of types, WP core validation and sanitization
858
-                    // freaks out. We'll just validate this argument while handling the request
859
-                    'validate_callback' => null,
860
-                    'sanitize_callback' => null,
861
-                ],
862
-                'group_by' => [
863
-                    'required'          => false,
864
-                    'default'           => null,
865
-                    'type'              => [
866
-                        'object',
867
-                        'string',
868
-                    ],
869
-                    // because we accept  an almost infinite list of possible groupings,
870
-                    // WP core validation and sanitization
871
-                    // freaks out. We'll just validate this argument while handling the request
872
-                    'validate_callback' => null,
873
-                    'sanitize_callback' => null,
874
-                ],
875
-                'having'   => [
876
-                    'required'          => false,
877
-                    'default'           => null,
878
-                    'type'              => 'object',
879
-                    // because we accept an almost infinite list of possible where conditions, WP
880
-                    // core validation and sanitization freaks out. We'll just validate this argument
881
-                    // while handling the request
882
-                    'validate_callback' => null,
883
-                    'sanitize_callback' => null,
884
-                ],
885
-                'caps'     => [
886
-                    'required' => false,
887
-                    'default'  => EEM_Base::caps_read,
888
-                    'type'     => 'string',
889
-                    'enum'     => [
890
-                        EEM_Base::caps_read,
891
-                        EEM_Base::caps_read_admin,
892
-                        EEM_Base::caps_edit,
893
-                        EEM_Base::caps_delete,
894
-                    ],
895
-                ],
896
-            ]
897
-        );
898
-    }
899
-
900
-
901
-    /**
902
-     * Gets parameter information for a model regarding writing data
903
-     *
904
-     * @param string           $model_name
905
-     * @param ModelVersionInfo $model_version_info
906
-     * @param boolean          $create                                       whether this is for request to create (in
907
-     *                                                                       which case we need all required params) or
908
-     *                                                                       just to update (in which case we don't
909
-     *                                                                       need those on every request)
910
-     * @return array
911
-     * @throws EE_Error
912
-     * @throws ReflectionException
913
-     */
914
-    protected function _get_write_params(
915
-        $model_name,
916
-        ModelVersionInfo $model_version_info,
917
-        $create = false
918
-    ) {
919
-        $model = EE_Registry::instance()->load_model($model_name);
920
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
921
-
922
-        // we do our own validation and sanitization within the controller
923
-        $sanitize_callback = function_exists('rest_validate_value_from_schema')
924
-            ? ['EED_Core_Rest_Api', 'default_sanitize_callback']
925
-            : null;
926
-        $args_info = [];
927
-        foreach ($fields as $field_name => $field_obj) {
928
-            if ($field_obj->is_auto_increment()) {
929
-                // totally ignore auto increment IDs
930
-                continue;
931
-            }
932
-            $arg_info = $field_obj->getSchema();
933
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
934
-            $arg_info['required'] = $required;
935
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
936
-            unset($arg_info['readonly']);
937
-            $schema_properties = $field_obj->getSchemaProperties();
938
-            if (isset($schema_properties['raw'])
939
-                && $field_obj->getSchemaType() === 'object'
940
-            ) {
941
-                // if there's a "raw" form of this argument, use those properties instead
942
-                $arg_info = array_replace(
943
-                    $arg_info,
944
-                    $schema_properties['raw']
945
-                );
946
-            }
947
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
948
-                $field_obj,
949
-                $field_obj->get_default_value(),
950
-                $model_version_info->requestedVersion()
951
-            );
952
-            $arg_info['sanitize_callback'] = $sanitize_callback;
953
-            $args_info[ $field_name ] = $arg_info;
954
-            if ($field_obj instanceof EE_Datetime_Field) {
955
-                $gmt_arg_info = $arg_info;
956
-                $gmt_arg_info['description'] = sprintf(
957
-                    esc_html__(
958
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
959
-                        'event_espresso'
960
-                    ),
961
-                    $field_obj->get_nicename(),
962
-                    $field_name
963
-                );
964
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
965
-            }
966
-        }
967
-        return $args_info;
968
-    }
969
-
970
-
971
-    /**
972
-     * Replacement for WP API's 'rest_parse_request_arg'.
973
-     * If the value is blank but not required, don't bother validating it.
974
-     * Also, it uses our email validation instead of WP API's default.
975
-     *
976
-     * @param                 $value
977
-     * @param WP_REST_Request $request
978
-     * @param                 $param
979
-     * @return bool|true|WP_Error
980
-     * @throws InvalidArgumentException
981
-     * @throws InvalidInterfaceException
982
-     * @throws InvalidDataTypeException
983
-     */
984
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
985
-    {
986
-        $attributes = $request->get_attributes();
987
-        if (! isset($attributes['args'][ $param ])
988
-            || ! is_array($attributes['args'][ $param ])) {
989
-            $validation_result = true;
990
-        } else {
991
-            $args = $attributes['args'][ $param ];
992
-            if ((
993
-                    $value === ''
994
-                    || $value === null
995
-                )
996
-                && (! isset($args['required'])
997
-                    || $args['required'] === false
998
-                )
999
-            ) {
1000
-                // not required and not provided? that's cool
1001
-                $validation_result = true;
1002
-            } elseif (isset($args['format'])
1003
-                      && $args['format'] === 'email'
1004
-            ) {
1005
-                $validation_result = true;
1006
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1007
-                    $validation_result = new WP_Error(
1008
-                        'rest_invalid_param',
1009
-                        esc_html__(
1010
-                            'The email address is not valid or does not exist.',
1011
-                            'event_espresso'
1012
-                        )
1013
-                    );
1014
-                }
1015
-            } else {
1016
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
1017
-            }
1018
-        }
1019
-        if (is_wp_error($validation_result)) {
1020
-            return $validation_result;
1021
-        }
1022
-        return rest_sanitize_request_arg($value, $request, $param);
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1028
-     *
1029
-     * @param $email
1030
-     * @return bool
1031
-     * @throws InvalidArgumentException
1032
-     * @throws InvalidInterfaceException
1033
-     * @throws InvalidDataTypeException
1034
-     */
1035
-    protected static function _validate_email($email)
1036
-    {
1037
-        try {
1038
-            EmailAddressFactory::create($email);
1039
-            return true;
1040
-        } catch (EmailValidationException $e) {
1041
-            return false;
1042
-        }
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     * Gets routes for the config
1048
-     *
1049
-     * @return array @see _register_model_routes
1050
-     * @deprecated since version 4.9.1
1051
-     */
1052
-    protected function _register_config_routes()
1053
-    {
1054
-        $config_routes = [];
1055
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1056
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1057
-                $version,
1058
-                $hidden_endpoint
1059
-            );
1060
-        }
1061
-        return $config_routes;
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * Gets routes for the config for the specified version
1067
-     *
1068
-     * @param string  $version
1069
-     * @param boolean $hidden_endpoint
1070
-     * @return array
1071
-     */
1072
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1073
-    {
1074
-        return [
1075
-            'config'    => [
1076
-                [
1077
-                    'callback'        => [
1078
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1079
-                        'handleRequest',
1080
-                    ],
1081
-                    'methods'         => WP_REST_Server::READABLE,
1082
-                    'hidden_endpoint' => $hidden_endpoint,
1083
-                    'callback_args'   => [$version],
1084
-                ],
1085
-            ],
1086
-            'site_info' => [
1087
-                [
1088
-                    'callback'        => [
1089
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1090
-                        'handleRequestSiteInfo',
1091
-                    ],
1092
-                    'methods'         => WP_REST_Server::READABLE,
1093
-                    'hidden_endpoint' => $hidden_endpoint,
1094
-                    'callback_args'   => [$version],
1095
-                ],
1096
-            ],
1097
-        ];
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * Gets the meta info routes
1103
-     *
1104
-     * @return array @see _register_model_routes
1105
-     * @deprecated since version 4.9.1
1106
-     */
1107
-    protected function _register_meta_routes()
1108
-    {
1109
-        $meta_routes = [];
1110
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1111
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1112
-                $version,
1113
-                $hidden_endpoint
1114
-            );
1115
-        }
1116
-        return $meta_routes;
1117
-    }
1118
-
1119
-
1120
-    /**
1121
-     * @param string  $version
1122
-     * @param boolean $hidden_endpoint
1123
-     * @return array
1124
-     */
1125
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1126
-    {
1127
-        return [
1128
-            'resources' => [
1129
-                [
1130
-                    'callback'        => [
1131
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1132
-                        'handleRequestModelsMeta',
1133
-                    ],
1134
-                    'methods'         => WP_REST_Server::READABLE,
1135
-                    'hidden_endpoint' => $hidden_endpoint,
1136
-                    'callback_args'   => [$version],
1137
-                ],
1138
-            ],
1139
-        ];
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * Tries to hide old 4.6 endpoints from the
1145
-     *
1146
-     * @param array $route_data
1147
-     * @return array
1148
-     * @throws EE_Error
1149
-     * @throws ReflectionException
1150
-     */
1151
-    public static function hide_old_endpoints($route_data)
1152
-    {
1153
-        // allow API clients to override which endpoints get hidden, in case
1154
-        // they want to discover particular endpoints
1155
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1156
-        $force_show_ee_namespace = ltrim(
1157
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1158
-            '/'
1159
-        );
1160
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1161
-            foreach ($relative_urls as $resource_name => $endpoints) {
1162
-                foreach ($endpoints as $key => $endpoint) {
1163
-                    // skip schema and other route options
1164
-                    if (! is_numeric($key)) {
1165
-                        continue;
1166
-                    }
1167
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1168
-                    // to $force_show_ee_namespace, in which case only show that one
1169
-                    // namespace's endpoints (and hide all others)
1170
-                    if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1171
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1172
-                    ) {
1173
-                        $full_route = '/' . ltrim($namespace, '/');
1174
-                        $full_route .= '/' . ltrim($resource_name, '/');
1175
-                        unset($route_data[ $full_route ]);
1176
-                    }
1177
-                }
1178
-            }
1179
-        }
1180
-        return $route_data;
1181
-    }
1182
-
1183
-
1184
-    /**
1185
-     * Returns an array describing which versions of core support serving requests for.
1186
-     * Keys are core versions' major and minor version, and values are the
1187
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1188
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1189
-     * the answers table entirely, in which case it would be very difficult for
1190
-     * it to serve 4.6-style responses.
1191
-     * Versions of core that are missing from this array are unknowns.
1192
-     * previous ver
1193
-     *
1194
-     * @return array
1195
-     */
1196
-    public static function version_compatibilities()
1197
-    {
1198
-        return apply_filters(
1199
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1200
-            [
1201
-                '4.8.29' => '4.8.29',
1202
-                '4.8.33' => '4.8.29',
1203
-                '4.8.34' => '4.8.29',
1204
-                '4.8.36' => '4.8.29',
1205
-            ]
1206
-        );
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Gets the latest API version served. Eg if there
1212
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1213
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1214
-     *
1215
-     * @return string
1216
-     */
1217
-    public static function latest_rest_api_version()
1218
-    {
1219
-        $versions_served = EED_Core_Rest_Api::versions_served();
1220
-        $versions_served_keys = array_keys($versions_served);
1221
-        return end($versions_served_keys);
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1227
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1228
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1229
-     * We also indicate whether or not this version should be put in the index or not
1230
-     *
1231
-     * @return array keys are API version numbers (just major and minor numbers), and values
1232
-     * are whether or not they should be hidden
1233
-     */
1234
-    public static function versions_served()
1235
-    {
1236
-        $versions_served = [];
1237
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1238
-        $lowest_compatible_version = end($possibly_served_versions);
1239
-        reset($possibly_served_versions);
1240
-        $versions_served_historically = array_keys($possibly_served_versions);
1241
-        $latest_version = end($versions_served_historically);
1242
-        reset($versions_served_historically);
1243
-        // for each version of core we have ever served:
1244
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1245
-            // if it's not above the current core version, and it's compatible with the current version of core
1246
-
1247
-            if ($key_versioned_endpoint === $latest_version) {
1248
-                // don't hide the latest version in the index
1249
-                $versions_served[ $key_versioned_endpoint ] = false;
1250
-            } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1251
-                      && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1252
-            ) {
1253
-                // include, but hide, previous versions which are still supported
1254
-                $versions_served[ $key_versioned_endpoint ] = true;
1255
-            } elseif (apply_filters(
1256
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1257
-                false,
1258
-                $possibly_served_versions
1259
-            )) {
1260
-                // if a version is no longer supported, don't include it in index or list of versions served
1261
-                $versions_served[ $key_versioned_endpoint ] = true;
1262
-            }
1263
-        }
1264
-        return $versions_served;
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * Gets the major and minor version of EE core's version string
1270
-     *
1271
-     * @return string
1272
-     */
1273
-    public static function core_version()
1274
-    {
1275
-        return apply_filters(
1276
-            'FHEE__EED_Core_REST_API__core_version',
1277
-            implode(
1278
-                '.',
1279
-                array_slice(
1280
-                    explode(
1281
-                        '.',
1282
-                        espresso_version()
1283
-                    ),
1284
-                    0,
1285
-                    3
1286
-                )
1287
-            )
1288
-        );
1289
-    }
1290
-
1291
-
1292
-    /**
1293
-     * Gets the default limit that should be used when querying for resources
1294
-     *
1295
-     * @return int
1296
-     */
1297
-    public static function get_default_query_limit()
1298
-    {
1299
-        // we actually don't use a const because we want folks to always use
1300
-        // this method, not the const directly
1301
-        return apply_filters(
1302
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1303
-            50
1304
-        );
1305
-    }
1306
-
1307
-
1308
-    /**
1309
-     * @param string $version api version string (i.e. '4.8.36')
1310
-     * @return array
1311
-     */
1312
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1313
-    {
1314
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1315
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1316
-        $collection_routes = [];
1317
-        foreach ($model_names as $model_name => $model_class_name) {
1318
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1319
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1320
-        }
1321
-        return $collection_routes;
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * Returns an array of primary key names indexed by model names.
1327
-     *
1328
-     * @param string $version
1329
-     * @return array
1330
-     */
1331
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1332
-    {
1333
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1334
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1335
-        $primary_key_items = [];
1336
-        foreach ($model_names as $model_name => $model_class_name) {
1337
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1338
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1339
-                if (count($primary_keys) > 1) {
1340
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1341
-                } else {
1342
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1343
-                }
1344
-            }
1345
-        }
1346
-        return $primary_key_items;
1347
-    }
1348
-
1349
-
1350
-    /**
1351
-     * Determines the EE REST API debug mode is activated, or not.
1352
-     *
1353
-     * @return bool
1354
-     * @since 4.9.76.p
1355
-     */
1356
-    public static function debugMode()
1357
-    {
1358
-        static $debug_mode = null; // could be class prop
1359
-        if ($debug_mode === null) {
1360
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1361
-        }
1362
-        return $debug_mode;
1363
-    }
1364
-
1365
-
1366
-    /**
1367
-     *    run - initial module setup
1368
-     *
1369
-     * @access    public
1370
-     * @param WP $WP
1371
-     * @return    void
1372
-     */
1373
-    public function run($WP)
1374
-    {
1375
-    }
25
+	const ee_api_namespace = Domain::API_NAMESPACE;
26
+
27
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
28
+
29
+	const saved_routes_option_names = 'ee_core_routes';
30
+
31
+	/**
32
+	 * string used in _links response bodies to make them globally unique.
33
+	 *
34
+	 * @see http://v2.wp-api.org/extending/linking/
35
+	 */
36
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
37
+
38
+	/**
39
+	 * @var CalculatedModelFields
40
+	 */
41
+	protected static $_field_calculator;
42
+
43
+
44
+	/**
45
+	 * @return EED_Core_Rest_Api|EED_Module
46
+	 */
47
+	public static function instance()
48
+	{
49
+		return parent::get_instance(EED_Core_Rest_Api::class);
50
+	}
51
+
52
+
53
+	/**
54
+	 *    set_hooks - for hooking into EE Core, other modules, etc
55
+	 *
56
+	 * @access    public
57
+	 * @return    void
58
+	 */
59
+	public static function set_hooks()
60
+	{
61
+		EED_Core_Rest_Api::set_hooks_both();
62
+	}
63
+
64
+
65
+	/**
66
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
67
+	 *
68
+	 * @access    public
69
+	 * @return    void
70
+	 */
71
+	public static function set_hooks_admin()
72
+	{
73
+		EED_Core_Rest_Api::set_hooks_both();
74
+	}
75
+
76
+
77
+	public static function set_hooks_both()
78
+	{
79
+		/** @var EventEspresso\core\services\request\Request $request */
80
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
81
+		if (! $request->isWordPressApi()) {
82
+			return;
83
+		}
84
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
85
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
86
+		add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
87
+		add_filter(
88
+			'rest_index',
89
+			['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
90
+		);
91
+		EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
+		);
94
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
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
+	 * public wrapper of _set_hooks_for_changes.
113
+	 * Loads all the hooks which make requests to old versions of the API
114
+	 * appear the same as they always did
115
+	 *
116
+	 * @throws EE_Error
117
+	 */
118
+	public static function set_hooks_for_changes()
119
+	{
120
+		EED_Core_Rest_Api::_set_hooks_for_changes();
121
+	}
122
+
123
+
124
+	/**
125
+	 * Loads all the hooks which make requests to old versions of the API
126
+	 * appear the same as they always did
127
+	 *
128
+	 * @throws EE_Error
129
+	 */
130
+	protected static function _set_hooks_for_changes()
131
+	{
132
+		$folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
+			// ignore the base parent class
135
+			// and legacy named classes
136
+			if ($classname_in_namespace === 'ChangesInBase'
137
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
138
+			) {
139
+				continue;
140
+			}
141
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
142
+			if (class_exists($full_classname)) {
143
+				$instance_of_class = new $full_classname;
144
+				if ($instance_of_class instanceof ChangesInBase) {
145
+					$instance_of_class->setHooks();
146
+				}
147
+			}
148
+		}
149
+	}
150
+
151
+
152
+	/**
153
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
154
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
155
+	 *
156
+	 * @throws EE_Error
157
+	 * @throws ReflectionException
158
+	 */
159
+	public static function register_routes()
160
+	{
161
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
162
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
163
+				/**
164
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
165
+				 *                                         but can also contain route options like {
166
+				 * @type array    $schema                      {
167
+				 * @type callable $schema_callback
168
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
169
+				 * WP_REST_Request of course
170
+				 * }
171
+				 * }
172
+				 */
173
+				// when registering routes, register all the endpoints' data at the same time
174
+				$multiple_endpoint_args = [];
175
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
176
+					/**
177
+					 * @var array     $data_for_single_endpoint {
178
+					 * @type callable $callback
179
+					 * @type string methods
180
+					 * @type array args
181
+					 * @type array _links
182
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
183
+					 * WP_REST_Request of course
184
+					 * }
185
+					 */
186
+					// skip route options
187
+					if (! is_numeric($endpoint_key)) {
188
+						continue;
189
+					}
190
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
191
+						throw new EE_Error(
192
+							esc_html__(
193
+							// @codingStandardsIgnoreStart
194
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
195
+								// @codingStandardsIgnoreEnd
196
+								'event_espresso'
197
+							)
198
+						);
199
+					}
200
+					$callback = $data_for_single_endpoint['callback'];
201
+					$single_endpoint_args = [
202
+						'methods' => $data_for_single_endpoint['methods'],
203
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
204
+							: [],
205
+					];
206
+					if (isset($data_for_single_endpoint['_links'])) {
207
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
208
+					}
209
+					if (isset($data_for_single_endpoint['callback_args'])) {
210
+						$callback_args = $data_for_single_endpoint['callback_args'];
211
+						$single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
212
+							$callback,
213
+							$callback_args
214
+						) {
215
+							array_unshift($callback_args, $request);
216
+							return call_user_func_array(
217
+								$callback,
218
+								$callback_args
219
+							);
220
+						};
221
+					} else {
222
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
223
+					}
224
+					$multiple_endpoint_args[] = $single_endpoint_args;
225
+				}
226
+				if (isset($data_for_multiple_endpoints['schema'])) {
227
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
228
+					$schema_callback = $schema_route_data['schema_callback'];
229
+					$callback_args = $schema_route_data['callback_args'];
230
+					$multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
231
+						return call_user_func_array(
232
+							$schema_callback,
233
+							$callback_args
234
+						);
235
+					};
236
+				}
237
+				register_rest_route(
238
+					$namespace,
239
+					$relative_route,
240
+					$multiple_endpoint_args
241
+				);
242
+			}
243
+		}
244
+	}
245
+
246
+
247
+	/**
248
+	 * Checks if there was a version change or something that merits invalidating the cached
249
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
250
+	 * next time the WP API is used
251
+	 */
252
+	public static function invalidate_cached_route_data_on_version_change()
253
+	{
254
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
255
+			EED_Core_Rest_Api::invalidate_cached_route_data();
256
+		}
257
+		foreach (EE_Registry::instance()->addons as $addon) {
258
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
259
+				EED_Core_Rest_Api::invalidate_cached_route_data();
260
+			}
261
+		}
262
+	}
263
+
264
+
265
+	/**
266
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
267
+	 */
268
+	public static function invalidate_cached_route_data()
269
+	{
270
+		// delete the saved EE REST API routes
271
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
272
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
273
+		}
274
+	}
275
+
276
+
277
+	/**
278
+	 * Gets the EE route data
279
+	 *
280
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
281
+	 * @throws EE_Error
282
+	 * @throws ReflectionException
283
+	 * @type string|array $callback
284
+	 * @type string       $methods
285
+	 * @type boolean      $hidden_endpoint
286
+	 * }
287
+	 */
288
+	public static function get_ee_route_data()
289
+	{
290
+		$ee_routes = [];
291
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
292
+			$ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
293
+				$version,
294
+				$hidden_endpoints
295
+			);
296
+		}
297
+		return $ee_routes;
298
+	}
299
+
300
+
301
+	/**
302
+	 * Gets the EE route data from the wp options if it exists already,
303
+	 * otherwise re-generates it and saves it to the option
304
+	 *
305
+	 * @param string  $version
306
+	 * @param boolean $hidden_endpoints
307
+	 * @return array
308
+	 * @throws EE_Error
309
+	 * @throws ReflectionException
310
+	 */
311
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
312
+	{
313
+		$ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
314
+		if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
315
+			$ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
316
+		}
317
+		return $ee_routes;
318
+	}
319
+
320
+
321
+	/**
322
+	 * Saves the EE REST API route data to a wp option and returns it
323
+	 *
324
+	 * @param string  $version
325
+	 * @param boolean $hidden_endpoints
326
+	 * @return mixed|null
327
+	 * @throws EE_Error
328
+	 * @throws ReflectionException
329
+	 */
330
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
331
+	{
332
+		$instance = EED_Core_Rest_Api::instance();
333
+		$routes = apply_filters(
334
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
335
+			array_replace_recursive(
336
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
337
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
338
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
339
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
340
+			)
341
+		);
342
+		$option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
343
+		if (get_option($option_name)) {
344
+			update_option($option_name, $routes, true);
345
+		} else {
346
+			add_option($option_name, $routes, null, 'no');
347
+		}
348
+		return $routes;
349
+	}
350
+
351
+
352
+	/**
353
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
354
+	 * need to calculate it on every request
355
+	 *
356
+	 * @return void
357
+	 * @deprecated since version 4.9.1
358
+	 */
359
+	public static function save_ee_routes()
360
+	{
361
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
362
+			$instance = EED_Core_Rest_Api::instance();
363
+			$routes = apply_filters(
364
+				'EED_Core_Rest_Api__save_ee_routes__routes',
365
+				array_replace_recursive(
366
+					$instance->_register_config_routes(),
367
+					$instance->_register_meta_routes(),
368
+					$instance->_register_model_routes(),
369
+					$instance->_register_rpc_routes()
370
+				)
371
+			);
372
+			update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
373
+		}
374
+	}
375
+
376
+
377
+	/**
378
+	 * Gets all the route information relating to EE models
379
+	 *
380
+	 * @return array @see get_ee_route_data
381
+	 * @deprecated since version 4.9.1
382
+	 */
383
+	protected function _register_model_routes()
384
+	{
385
+		$model_routes = [];
386
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
387
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
388
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
389
+		}
390
+		return $model_routes;
391
+	}
392
+
393
+
394
+	/**
395
+	 * Decides whether or not to add write endpoints for this model.
396
+	 * Currently, this defaults to exclude all global tables and models
397
+	 * which would allow inserting WP core data (we don't want to duplicate
398
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
399
+	 *
400
+	 * @param EEM_Base $model
401
+	 * @return bool
402
+	 */
403
+	public static function should_have_write_endpoints(EEM_Base $model)
404
+	{
405
+		if ($model->is_wp_core_model()) {
406
+			return false;
407
+		}
408
+		foreach ($model->get_tables() as $table) {
409
+			if ($table->is_global()) {
410
+				return false;
411
+			}
412
+		}
413
+		return true;
414
+	}
415
+
416
+
417
+	/**
418
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
419
+	 * in this versioned namespace of EE4
420
+	 *
421
+	 * @param $version
422
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
423
+	 */
424
+	public static function model_names_with_plural_routes($version)
425
+	{
426
+		$model_version_info = new ModelVersionInfo($version);
427
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
428
+		// let's not bother having endpoints for extra metas
429
+		unset(
430
+			$models_to_register['Extra_Meta'],
431
+			$models_to_register['Extra_Join'],
432
+			$models_to_register['Post_Meta']
433
+		);
434
+		return apply_filters(
435
+			'FHEE__EED_Core_REST_API___register_model_routes',
436
+			$models_to_register
437
+		);
438
+	}
439
+
440
+
441
+	/**
442
+	 * Gets the route data for EE models in the specified version
443
+	 *
444
+	 * @param string  $version
445
+	 * @param boolean $hidden_endpoint
446
+	 * @return array
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
451
+	{
452
+		$model_routes = [];
453
+		$model_version_info = new ModelVersionInfo($version);
454
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
455
+			$model = EE_Registry::instance()->load_model($model_name);
456
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
457
+			if (! $model instanceof EEM_Base) {
458
+				continue;
459
+			}
460
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
461
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
462
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
463
+			$model_routes[ $plural_model_route ] = [
464
+				[
465
+					'callback'        => [
466
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
467
+						'handleRequestGetAll',
468
+					],
469
+					'callback_args'   => [$version, $model_name],
470
+					'methods'         => WP_REST_Server::READABLE,
471
+					'hidden_endpoint' => $hidden_endpoint,
472
+					'args'            => $this->_get_read_query_params($model, $version),
473
+					'_links'          => [
474
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
475
+					],
476
+				],
477
+				'schema' => [
478
+					'schema_callback' => [
479
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
480
+						'handleSchemaRequest',
481
+					],
482
+					'callback_args'   => [$version, $model_name],
483
+				],
484
+			];
485
+			$model_routes[ $singular_model_route ] = [
486
+				[
487
+					'callback'        => [
488
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
489
+						'handleRequestGetOne',
490
+					],
491
+					'callback_args'   => [$version, $model_name],
492
+					'methods'         => WP_REST_Server::READABLE,
493
+					'hidden_endpoint' => $hidden_endpoint,
494
+					'args'            => $this->_get_response_selection_query_params($model, $version, true),
495
+				],
496
+			];
497
+			if (apply_filters(
498
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
499
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
500
+				$model
501
+			)) {
502
+				$model_routes[ $plural_model_route ][] = [
503
+					'callback'        => [
504
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
505
+						'handleRequestInsert',
506
+					],
507
+					'callback_args'   => [$version, $model_name],
508
+					'methods'         => WP_REST_Server::CREATABLE,
509
+					'hidden_endpoint' => $hidden_endpoint,
510
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
511
+				];
512
+				$model_routes[ $singular_model_route ] = array_merge(
513
+					$model_routes[ $singular_model_route ],
514
+					[
515
+						[
516
+							'callback'        => [
517
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
518
+								'handleRequestUpdate',
519
+							],
520
+							'callback_args'   => [$version, $model_name],
521
+							'methods'         => WP_REST_Server::EDITABLE,
522
+							'hidden_endpoint' => $hidden_endpoint,
523
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
524
+						],
525
+						[
526
+							'callback'        => [
527
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
+								'handleRequestDelete',
529
+							],
530
+							'callback_args'   => [$version, $model_name],
531
+							'methods'         => WP_REST_Server::DELETABLE,
532
+							'hidden_endpoint' => $hidden_endpoint,
533
+							'args'            => $this->_get_delete_query_params($model, $version),
534
+						],
535
+					]
536
+				);
537
+			}
538
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
539
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
540
+					$model,
541
+					'(?P<id>[^\/]+)',
542
+					$relation_obj
543
+				);
544
+				$model_routes[ $related_route ] = [
545
+					[
546
+						'callback'        => [
547
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
548
+							'handleRequestGetRelated',
549
+						],
550
+						'callback_args'   => [$version, $model_name, $relation_name],
551
+						'methods'         => WP_REST_Server::READABLE,
552
+						'hidden_endpoint' => $hidden_endpoint,
553
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
554
+					],
555
+				];
556
+
557
+				$related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
558
+				$model_routes[ $related_write_route ] = [
559
+					[
560
+						'callback'        => [
561
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
562
+							'handleRequestAddRelation',
563
+						],
564
+						'callback_args'   => [$version, $model_name, $relation_name],
565
+						'methods'         => WP_REST_Server::EDITABLE,
566
+						'hidden_endpoint' => $hidden_endpoint,
567
+						'args'            => $this->_get_add_relation_query_params($model,
568
+							$relation_obj->get_other_model(), $version),
569
+					],
570
+					[
571
+						'callback'        => [
572
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
573
+							'handleRequestRemoveRelation',
574
+						],
575
+						'callback_args'   => [$version, $model_name, $relation_name],
576
+						'methods'         => WP_REST_Server::DELETABLE,
577
+						'hidden_endpoint' => $hidden_endpoint,
578
+						'args'            => [],
579
+					],
580
+				];
581
+			}
582
+		}
583
+		return $model_routes;
584
+	}
585
+
586
+
587
+	/**
588
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
589
+	 * excluding the preceding slash.
590
+	 * Eg you pass get_plural_route_to('Event') = 'events'
591
+	 *
592
+	 * @param EEM_Base $model
593
+	 * @return string
594
+	 */
595
+	public static function get_collection_route(EEM_Base $model)
596
+	{
597
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
598
+	}
599
+
600
+
601
+	/**
602
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
603
+	 * excluding the preceding slash.
604
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
605
+	 *
606
+	 * @param EEM_Base $model eg Event or Venue
607
+	 * @param string   $id
608
+	 * @return string
609
+	 */
610
+	public static function get_entity_route($model, $id)
611
+	{
612
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
613
+	}
614
+
615
+
616
+	/**
617
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
618
+	 * excluding the preceding slash.
619
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
620
+	 *
621
+	 * @param EEM_Base               $model eg Event or Venue
622
+	 * @param string                 $id
623
+	 * @param EE_Model_Relation_Base $relation_obj
624
+	 * @return string
625
+	 */
626
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
627
+	{
628
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
629
+			$relation_obj->get_other_model()->get_this_model_name(),
630
+			$relation_obj
631
+		);
632
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
633
+	}
634
+
635
+
636
+	/**
637
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
638
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
639
+	 *
640
+	 * @param string $relative_route
641
+	 * @param string $version
642
+	 * @return string
643
+	 */
644
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
645
+	{
646
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
647
+	}
648
+
649
+
650
+	/**
651
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
652
+	 * routes that don't conform to the traditional REST CRUD-style).
653
+	 *
654
+	 * @deprecated since 4.9.1
655
+	 */
656
+	protected function _register_rpc_routes()
657
+	{
658
+		$routes = [];
659
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
660
+			$routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
661
+				$version,
662
+				$hidden_endpoint
663
+			);
664
+		}
665
+		return $routes;
666
+	}
667
+
668
+
669
+	/**
670
+	 * @param string  $version
671
+	 * @param boolean $hidden_endpoint
672
+	 * @return array
673
+	 */
674
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
675
+	{
676
+		$this_versions_routes = [];
677
+		// checkin endpoint
678
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
679
+			[
680
+				'callback'        => [
681
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
682
+					'handleRequestToggleCheckin',
683
+				],
684
+				'methods'         => WP_REST_Server::CREATABLE,
685
+				'hidden_endpoint' => $hidden_endpoint,
686
+				'args'            => [
687
+					'force' => [
688
+						'required'    => false,
689
+						'default'     => false,
690
+						'description' => __(
691
+						// @codingStandardsIgnoreStart
692
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
693
+							// @codingStandardsIgnoreEnd
694
+							'event_espresso'
695
+						),
696
+					],
697
+				],
698
+				'callback_args'   => [$version],
699
+			],
700
+		];
701
+		return apply_filters(
702
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
703
+			$this_versions_routes,
704
+			$version,
705
+			$hidden_endpoint
706
+		);
707
+	}
708
+
709
+
710
+	/**
711
+	 * Gets the query params that can be used when request one or many
712
+	 *
713
+	 * @param EEM_Base $model
714
+	 * @param string   $version
715
+	 * @return array
716
+	 */
717
+	protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
718
+	{
719
+		$query_params = [
720
+			'include'   => [
721
+				'required' => false,
722
+				'default'  => '*',
723
+				'type'     => 'string',
724
+			],
725
+			'calculate' => [
726
+				'required'          => false,
727
+				'default'           => '',
728
+				'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
729
+				'type'              => 'string',
730
+				// because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
731
+				// freaks out. We'll just validate this argument while handling the request
732
+				'validate_callback' => null,
733
+				'sanitize_callback' => null,
734
+			],
735
+			'password'  => [
736
+				'required' => false,
737
+				'default'  => '',
738
+				'type'     => 'string',
739
+			],
740
+		];
741
+		return apply_filters(
742
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
743
+			$query_params,
744
+			$model,
745
+			$version
746
+		);
747
+	}
748
+
749
+
750
+	/**
751
+	 * Gets the parameters acceptable for delete requests
752
+	 *
753
+	 * @param EEM_Base $model
754
+	 * @param string   $version
755
+	 * @return array
756
+	 */
757
+	protected function _get_delete_query_params(EEM_Base $model, $version)
758
+	{
759
+		$params_for_delete = [
760
+			'allow_blocking' => [
761
+				'required' => false,
762
+				'default'  => true,
763
+				'type'     => 'boolean',
764
+			],
765
+		];
766
+		$params_for_delete['force'] = [
767
+			'required' => false,
768
+			'default'  => false,
769
+			'type'     => 'boolean',
770
+		];
771
+		return apply_filters(
772
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
773
+			$params_for_delete,
774
+			$model,
775
+			$version
776
+		);
777
+	}
778
+
779
+
780
+	/**
781
+	 * @param EEM_Base $source_model
782
+	 * @param EEM_Base $related_model
783
+	 * @param          $version
784
+	 * @return array
785
+	 * @throws EE_Error
786
+	 * @since $VID:$
787
+	 */
788
+	protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
789
+	{
790
+		// if they're related through a HABTM relation, check for any non-FKs
791
+		$all_relation_settings = $source_model->relation_settings();
792
+		$relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
793
+		$params = [];
794
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
795
+			foreach ($relation_settings->getNonKeyFields() as $field) {
796
+				/* @var $field EE_Model_Field_Base */
797
+				$params[ $field->get_name() ] = [
798
+					'required'          => ! $field->is_nullable(),
799
+					'default'           => ModelDataTranslator::prepareFieldValueForJson($field,
800
+						$field->get_default_value(), $version),
801
+					'type'              => $field->getSchemaType(),
802
+					'validate_callback' => null,
803
+					'sanitize_callback' => null,
804
+				];
805
+			}
806
+		}
807
+		return $params;
808
+	}
809
+
810
+
811
+	/**
812
+	 * Gets info about reading query params that are acceptable
813
+	 *
814
+	 * @param EEM_Base $model eg 'Event' or 'Venue'
815
+	 * @param string   $version
816
+	 * @return array    describing the args acceptable when querying this model
817
+	 * @throws EE_Error
818
+	 */
819
+	protected function _get_read_query_params(EEM_Base $model, $version)
820
+	{
821
+		$default_orderby = [];
822
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
823
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
824
+		}
825
+		return array_merge(
826
+			$this->_get_response_selection_query_params($model, $version),
827
+			[
828
+				'where'    => [
829
+					'required'          => false,
830
+					'default'           => [],
831
+					'type'              => 'object',
832
+					// because we accept an almost infinite list of possible where conditions, WP
833
+					// core validation and sanitization freaks out. We'll just validate this argument
834
+					// while handling the request
835
+					'validate_callback' => null,
836
+					'sanitize_callback' => null,
837
+				],
838
+				'limit'    => [
839
+					'required'          => false,
840
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
841
+					'type'              => [
842
+						'array',
843
+						'string',
844
+						'integer',
845
+					],
846
+					// because we accept a variety of types, WP core validation and sanitization
847
+					// freaks out. We'll just validate this argument while handling the request
848
+					'validate_callback' => null,
849
+					'sanitize_callback' => null,
850
+				],
851
+				'order_by' => [
852
+					'required'          => false,
853
+					'default'           => $default_orderby,
854
+					'type'              => [
855
+						'object',
856
+						'string',
857
+					],// because we accept a variety of types, WP core validation and sanitization
858
+					// freaks out. We'll just validate this argument while handling the request
859
+					'validate_callback' => null,
860
+					'sanitize_callback' => null,
861
+				],
862
+				'group_by' => [
863
+					'required'          => false,
864
+					'default'           => null,
865
+					'type'              => [
866
+						'object',
867
+						'string',
868
+					],
869
+					// because we accept  an almost infinite list of possible groupings,
870
+					// WP core validation and sanitization
871
+					// freaks out. We'll just validate this argument while handling the request
872
+					'validate_callback' => null,
873
+					'sanitize_callback' => null,
874
+				],
875
+				'having'   => [
876
+					'required'          => false,
877
+					'default'           => null,
878
+					'type'              => 'object',
879
+					// because we accept an almost infinite list of possible where conditions, WP
880
+					// core validation and sanitization freaks out. We'll just validate this argument
881
+					// while handling the request
882
+					'validate_callback' => null,
883
+					'sanitize_callback' => null,
884
+				],
885
+				'caps'     => [
886
+					'required' => false,
887
+					'default'  => EEM_Base::caps_read,
888
+					'type'     => 'string',
889
+					'enum'     => [
890
+						EEM_Base::caps_read,
891
+						EEM_Base::caps_read_admin,
892
+						EEM_Base::caps_edit,
893
+						EEM_Base::caps_delete,
894
+					],
895
+				],
896
+			]
897
+		);
898
+	}
899
+
900
+
901
+	/**
902
+	 * Gets parameter information for a model regarding writing data
903
+	 *
904
+	 * @param string           $model_name
905
+	 * @param ModelVersionInfo $model_version_info
906
+	 * @param boolean          $create                                       whether this is for request to create (in
907
+	 *                                                                       which case we need all required params) or
908
+	 *                                                                       just to update (in which case we don't
909
+	 *                                                                       need those on every request)
910
+	 * @return array
911
+	 * @throws EE_Error
912
+	 * @throws ReflectionException
913
+	 */
914
+	protected function _get_write_params(
915
+		$model_name,
916
+		ModelVersionInfo $model_version_info,
917
+		$create = false
918
+	) {
919
+		$model = EE_Registry::instance()->load_model($model_name);
920
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
921
+
922
+		// we do our own validation and sanitization within the controller
923
+		$sanitize_callback = function_exists('rest_validate_value_from_schema')
924
+			? ['EED_Core_Rest_Api', 'default_sanitize_callback']
925
+			: null;
926
+		$args_info = [];
927
+		foreach ($fields as $field_name => $field_obj) {
928
+			if ($field_obj->is_auto_increment()) {
929
+				// totally ignore auto increment IDs
930
+				continue;
931
+			}
932
+			$arg_info = $field_obj->getSchema();
933
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
934
+			$arg_info['required'] = $required;
935
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
936
+			unset($arg_info['readonly']);
937
+			$schema_properties = $field_obj->getSchemaProperties();
938
+			if (isset($schema_properties['raw'])
939
+				&& $field_obj->getSchemaType() === 'object'
940
+			) {
941
+				// if there's a "raw" form of this argument, use those properties instead
942
+				$arg_info = array_replace(
943
+					$arg_info,
944
+					$schema_properties['raw']
945
+				);
946
+			}
947
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
948
+				$field_obj,
949
+				$field_obj->get_default_value(),
950
+				$model_version_info->requestedVersion()
951
+			);
952
+			$arg_info['sanitize_callback'] = $sanitize_callback;
953
+			$args_info[ $field_name ] = $arg_info;
954
+			if ($field_obj instanceof EE_Datetime_Field) {
955
+				$gmt_arg_info = $arg_info;
956
+				$gmt_arg_info['description'] = sprintf(
957
+					esc_html__(
958
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
959
+						'event_espresso'
960
+					),
961
+					$field_obj->get_nicename(),
962
+					$field_name
963
+				);
964
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
965
+			}
966
+		}
967
+		return $args_info;
968
+	}
969
+
970
+
971
+	/**
972
+	 * Replacement for WP API's 'rest_parse_request_arg'.
973
+	 * If the value is blank but not required, don't bother validating it.
974
+	 * Also, it uses our email validation instead of WP API's default.
975
+	 *
976
+	 * @param                 $value
977
+	 * @param WP_REST_Request $request
978
+	 * @param                 $param
979
+	 * @return bool|true|WP_Error
980
+	 * @throws InvalidArgumentException
981
+	 * @throws InvalidInterfaceException
982
+	 * @throws InvalidDataTypeException
983
+	 */
984
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
985
+	{
986
+		$attributes = $request->get_attributes();
987
+		if (! isset($attributes['args'][ $param ])
988
+			|| ! is_array($attributes['args'][ $param ])) {
989
+			$validation_result = true;
990
+		} else {
991
+			$args = $attributes['args'][ $param ];
992
+			if ((
993
+					$value === ''
994
+					|| $value === null
995
+				)
996
+				&& (! isset($args['required'])
997
+					|| $args['required'] === false
998
+				)
999
+			) {
1000
+				// not required and not provided? that's cool
1001
+				$validation_result = true;
1002
+			} elseif (isset($args['format'])
1003
+					  && $args['format'] === 'email'
1004
+			) {
1005
+				$validation_result = true;
1006
+				if (! EED_Core_Rest_Api::_validate_email($value)) {
1007
+					$validation_result = new WP_Error(
1008
+						'rest_invalid_param',
1009
+						esc_html__(
1010
+							'The email address is not valid or does not exist.',
1011
+							'event_espresso'
1012
+						)
1013
+					);
1014
+				}
1015
+			} else {
1016
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
1017
+			}
1018
+		}
1019
+		if (is_wp_error($validation_result)) {
1020
+			return $validation_result;
1021
+		}
1022
+		return rest_sanitize_request_arg($value, $request, $param);
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1028
+	 *
1029
+	 * @param $email
1030
+	 * @return bool
1031
+	 * @throws InvalidArgumentException
1032
+	 * @throws InvalidInterfaceException
1033
+	 * @throws InvalidDataTypeException
1034
+	 */
1035
+	protected static function _validate_email($email)
1036
+	{
1037
+		try {
1038
+			EmailAddressFactory::create($email);
1039
+			return true;
1040
+		} catch (EmailValidationException $e) {
1041
+			return false;
1042
+		}
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 * Gets routes for the config
1048
+	 *
1049
+	 * @return array @see _register_model_routes
1050
+	 * @deprecated since version 4.9.1
1051
+	 */
1052
+	protected function _register_config_routes()
1053
+	{
1054
+		$config_routes = [];
1055
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1056
+			$config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1057
+				$version,
1058
+				$hidden_endpoint
1059
+			);
1060
+		}
1061
+		return $config_routes;
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * Gets routes for the config for the specified version
1067
+	 *
1068
+	 * @param string  $version
1069
+	 * @param boolean $hidden_endpoint
1070
+	 * @return array
1071
+	 */
1072
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1073
+	{
1074
+		return [
1075
+			'config'    => [
1076
+				[
1077
+					'callback'        => [
1078
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1079
+						'handleRequest',
1080
+					],
1081
+					'methods'         => WP_REST_Server::READABLE,
1082
+					'hidden_endpoint' => $hidden_endpoint,
1083
+					'callback_args'   => [$version],
1084
+				],
1085
+			],
1086
+			'site_info' => [
1087
+				[
1088
+					'callback'        => [
1089
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1090
+						'handleRequestSiteInfo',
1091
+					],
1092
+					'methods'         => WP_REST_Server::READABLE,
1093
+					'hidden_endpoint' => $hidden_endpoint,
1094
+					'callback_args'   => [$version],
1095
+				],
1096
+			],
1097
+		];
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * Gets the meta info routes
1103
+	 *
1104
+	 * @return array @see _register_model_routes
1105
+	 * @deprecated since version 4.9.1
1106
+	 */
1107
+	protected function _register_meta_routes()
1108
+	{
1109
+		$meta_routes = [];
1110
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1111
+			$meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1112
+				$version,
1113
+				$hidden_endpoint
1114
+			);
1115
+		}
1116
+		return $meta_routes;
1117
+	}
1118
+
1119
+
1120
+	/**
1121
+	 * @param string  $version
1122
+	 * @param boolean $hidden_endpoint
1123
+	 * @return array
1124
+	 */
1125
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1126
+	{
1127
+		return [
1128
+			'resources' => [
1129
+				[
1130
+					'callback'        => [
1131
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1132
+						'handleRequestModelsMeta',
1133
+					],
1134
+					'methods'         => WP_REST_Server::READABLE,
1135
+					'hidden_endpoint' => $hidden_endpoint,
1136
+					'callback_args'   => [$version],
1137
+				],
1138
+			],
1139
+		];
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * Tries to hide old 4.6 endpoints from the
1145
+	 *
1146
+	 * @param array $route_data
1147
+	 * @return array
1148
+	 * @throws EE_Error
1149
+	 * @throws ReflectionException
1150
+	 */
1151
+	public static function hide_old_endpoints($route_data)
1152
+	{
1153
+		// allow API clients to override which endpoints get hidden, in case
1154
+		// they want to discover particular endpoints
1155
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1156
+		$force_show_ee_namespace = ltrim(
1157
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1158
+			'/'
1159
+		);
1160
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1161
+			foreach ($relative_urls as $resource_name => $endpoints) {
1162
+				foreach ($endpoints as $key => $endpoint) {
1163
+					// skip schema and other route options
1164
+					if (! is_numeric($key)) {
1165
+						continue;
1166
+					}
1167
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1168
+					// to $force_show_ee_namespace, in which case only show that one
1169
+					// namespace's endpoints (and hide all others)
1170
+					if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1171
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1172
+					) {
1173
+						$full_route = '/' . ltrim($namespace, '/');
1174
+						$full_route .= '/' . ltrim($resource_name, '/');
1175
+						unset($route_data[ $full_route ]);
1176
+					}
1177
+				}
1178
+			}
1179
+		}
1180
+		return $route_data;
1181
+	}
1182
+
1183
+
1184
+	/**
1185
+	 * Returns an array describing which versions of core support serving requests for.
1186
+	 * Keys are core versions' major and minor version, and values are the
1187
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1188
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1189
+	 * the answers table entirely, in which case it would be very difficult for
1190
+	 * it to serve 4.6-style responses.
1191
+	 * Versions of core that are missing from this array are unknowns.
1192
+	 * previous ver
1193
+	 *
1194
+	 * @return array
1195
+	 */
1196
+	public static function version_compatibilities()
1197
+	{
1198
+		return apply_filters(
1199
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1200
+			[
1201
+				'4.8.29' => '4.8.29',
1202
+				'4.8.33' => '4.8.29',
1203
+				'4.8.34' => '4.8.29',
1204
+				'4.8.36' => '4.8.29',
1205
+			]
1206
+		);
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Gets the latest API version served. Eg if there
1212
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1213
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1214
+	 *
1215
+	 * @return string
1216
+	 */
1217
+	public static function latest_rest_api_version()
1218
+	{
1219
+		$versions_served = EED_Core_Rest_Api::versions_served();
1220
+		$versions_served_keys = array_keys($versions_served);
1221
+		return end($versions_served_keys);
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1227
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1228
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1229
+	 * We also indicate whether or not this version should be put in the index or not
1230
+	 *
1231
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1232
+	 * are whether or not they should be hidden
1233
+	 */
1234
+	public static function versions_served()
1235
+	{
1236
+		$versions_served = [];
1237
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1238
+		$lowest_compatible_version = end($possibly_served_versions);
1239
+		reset($possibly_served_versions);
1240
+		$versions_served_historically = array_keys($possibly_served_versions);
1241
+		$latest_version = end($versions_served_historically);
1242
+		reset($versions_served_historically);
1243
+		// for each version of core we have ever served:
1244
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1245
+			// if it's not above the current core version, and it's compatible with the current version of core
1246
+
1247
+			if ($key_versioned_endpoint === $latest_version) {
1248
+				// don't hide the latest version in the index
1249
+				$versions_served[ $key_versioned_endpoint ] = false;
1250
+			} elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1251
+					  && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1252
+			) {
1253
+				// include, but hide, previous versions which are still supported
1254
+				$versions_served[ $key_versioned_endpoint ] = true;
1255
+			} elseif (apply_filters(
1256
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1257
+				false,
1258
+				$possibly_served_versions
1259
+			)) {
1260
+				// if a version is no longer supported, don't include it in index or list of versions served
1261
+				$versions_served[ $key_versioned_endpoint ] = true;
1262
+			}
1263
+		}
1264
+		return $versions_served;
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * Gets the major and minor version of EE core's version string
1270
+	 *
1271
+	 * @return string
1272
+	 */
1273
+	public static function core_version()
1274
+	{
1275
+		return apply_filters(
1276
+			'FHEE__EED_Core_REST_API__core_version',
1277
+			implode(
1278
+				'.',
1279
+				array_slice(
1280
+					explode(
1281
+						'.',
1282
+						espresso_version()
1283
+					),
1284
+					0,
1285
+					3
1286
+				)
1287
+			)
1288
+		);
1289
+	}
1290
+
1291
+
1292
+	/**
1293
+	 * Gets the default limit that should be used when querying for resources
1294
+	 *
1295
+	 * @return int
1296
+	 */
1297
+	public static function get_default_query_limit()
1298
+	{
1299
+		// we actually don't use a const because we want folks to always use
1300
+		// this method, not the const directly
1301
+		return apply_filters(
1302
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1303
+			50
1304
+		);
1305
+	}
1306
+
1307
+
1308
+	/**
1309
+	 * @param string $version api version string (i.e. '4.8.36')
1310
+	 * @return array
1311
+	 */
1312
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1313
+	{
1314
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1315
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1316
+		$collection_routes = [];
1317
+		foreach ($model_names as $model_name => $model_class_name) {
1318
+			$collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1319
+															. EEH_Inflector::pluralize_and_lower($model_name);
1320
+		}
1321
+		return $collection_routes;
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * Returns an array of primary key names indexed by model names.
1327
+	 *
1328
+	 * @param string $version
1329
+	 * @return array
1330
+	 */
1331
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1332
+	{
1333
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1334
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1335
+		$primary_key_items = [];
1336
+		foreach ($model_names as $model_name => $model_class_name) {
1337
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1338
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1339
+				if (count($primary_keys) > 1) {
1340
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1341
+				} else {
1342
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1343
+				}
1344
+			}
1345
+		}
1346
+		return $primary_key_items;
1347
+	}
1348
+
1349
+
1350
+	/**
1351
+	 * Determines the EE REST API debug mode is activated, or not.
1352
+	 *
1353
+	 * @return bool
1354
+	 * @since 4.9.76.p
1355
+	 */
1356
+	public static function debugMode()
1357
+	{
1358
+		static $debug_mode = null; // could be class prop
1359
+		if ($debug_mode === null) {
1360
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1361
+		}
1362
+		return $debug_mode;
1363
+	}
1364
+
1365
+
1366
+	/**
1367
+	 *    run - initial module setup
1368
+	 *
1369
+	 * @access    public
1370
+	 * @param WP $WP
1371
+	 * @return    void
1372
+	 */
1373
+	public function run($WP)
1374
+	{
1375
+	}
1376 1376
 }
Please login to merge, or discard this patch.
Spacing   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
     {
79 79
         /** @var EventEspresso\core\services\request\Request $request */
80 80
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
81
-        if (! $request->isWordPressApi()) {
81
+        if ( ! $request->isWordPressApi()) {
82 82
             return;
83 83
         }
84 84
         add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
      */
130 130
     protected static function _set_hooks_for_changes()
131 131
     {
132
-        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
132
+        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES.'rest_api/changes'], false);
133 133
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
134 134
             // ignore the base parent class
135 135
             // and legacy named classes
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
             ) {
139 139
                 continue;
140 140
             }
141
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
141
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
142 142
             if (class_exists($full_classname)) {
143 143
                 $instance_of_class = new $full_classname;
144 144
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -184,10 +184,10 @@  discard block
 block discarded – undo
184 184
                      * }
185 185
                      */
186 186
                     // skip route options
187
-                    if (! is_numeric($endpoint_key)) {
187
+                    if ( ! is_numeric($endpoint_key)) {
188 188
                         continue;
189 189
                     }
190
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
190
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
191 191
                         throw new EE_Error(
192 192
                             esc_html__(
193 193
                             // @codingStandardsIgnoreStart
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
                     }
209 209
                     if (isset($data_for_single_endpoint['callback_args'])) {
210 210
                         $callback_args = $data_for_single_endpoint['callback_args'];
211
-                        $single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
211
+                        $single_endpoint_args['callback'] = static function(WP_REST_Request $request) use (
212 212
                             $callback,
213 213
                             $callback_args
214 214
                         ) {
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
228 228
                     $schema_callback = $schema_route_data['schema_callback'];
229 229
                     $callback_args = $schema_route_data['callback_args'];
230
-                    $multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
230
+                    $multiple_endpoint_args['schema'] = static function() use ($schema_callback, $callback_args) {
231 231
                         return call_user_func_array(
232 232
                             $schema_callback,
233 233
                             $callback_args
@@ -269,7 +269,7 @@  discard block
 block discarded – undo
269 269
     {
270 270
         // delete the saved EE REST API routes
271 271
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
272
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
272
+            delete_option(EED_Core_Rest_Api::saved_routes_option_names.$version);
273 273
         }
274 274
     }
275 275
 
@@ -289,7 +289,7 @@  discard block
 block discarded – undo
289 289
     {
290 290
         $ee_routes = [];
291 291
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
292
-            $ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
292
+            $ee_routes[EED_Core_Rest_Api::ee_api_namespace.$version] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
293 293
                 $version,
294 294
                 $hidden_endpoints
295 295
             );
@@ -310,8 +310,8 @@  discard block
 block discarded – undo
310 310
      */
311 311
     protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
312 312
     {
313
-        $ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
314
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
313
+        $ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names.$version, null);
314
+        if ( ! $ee_routes || EED_Core_Rest_Api::debugMode()) {
315 315
             $ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
316 316
         }
317 317
         return $ee_routes;
@@ -339,7 +339,7 @@  discard block
 block discarded – undo
339 339
                 $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
340 340
             )
341 341
         );
342
-        $option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
342
+        $option_name = EED_Core_Rest_Api::saved_routes_option_names.$version;
343 343
         if (get_option($option_name)) {
344 344
             update_option($option_name, $routes, true);
345 345
         } else {
@@ -384,8 +384,8 @@  discard block
 block discarded – undo
384 384
     {
385 385
         $model_routes = [];
386 386
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
387
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
388
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
387
+            $model_routes[EED_Core_Rest_Api::ee_api_namespace
388
+                           . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
389 389
         }
390 390
         return $model_routes;
391 391
     }
@@ -454,13 +454,13 @@  discard block
 block discarded – undo
454 454
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
455 455
             $model = EE_Registry::instance()->load_model($model_name);
456 456
             // if this isn't a valid model then let's skip iterate to the next item in the loop.
457
-            if (! $model instanceof EEM_Base) {
457
+            if ( ! $model instanceof EEM_Base) {
458 458
                 continue;
459 459
             }
460 460
             // yes we could just register one route for ALL models, but then they wouldn't show up in the index
461 461
             $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
462 462
             $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
463
-            $model_routes[ $plural_model_route ] = [
463
+            $model_routes[$plural_model_route] = [
464 464
                 [
465 465
                     'callback'        => [
466 466
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
                     'hidden_endpoint' => $hidden_endpoint,
472 472
                     'args'            => $this->_get_read_query_params($model, $version),
473 473
                     '_links'          => [
474
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
474
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
475 475
                     ],
476 476
                 ],
477 477
                 'schema' => [
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
                     'callback_args'   => [$version, $model_name],
483 483
                 ],
484 484
             ];
485
-            $model_routes[ $singular_model_route ] = [
485
+            $model_routes[$singular_model_route] = [
486 486
                 [
487 487
                     'callback'        => [
488 488
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
500 500
                 $model
501 501
             )) {
502
-                $model_routes[ $plural_model_route ][] = [
502
+                $model_routes[$plural_model_route][] = [
503 503
                     'callback'        => [
504 504
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
505 505
                         'handleRequestInsert',
@@ -509,8 +509,8 @@  discard block
 block discarded – undo
509 509
                     'hidden_endpoint' => $hidden_endpoint,
510 510
                     'args'            => $this->_get_write_params($model_name, $model_version_info, true),
511 511
                 ];
512
-                $model_routes[ $singular_model_route ] = array_merge(
513
-                    $model_routes[ $singular_model_route ],
512
+                $model_routes[$singular_model_route] = array_merge(
513
+                    $model_routes[$singular_model_route],
514 514
                     [
515 515
                         [
516 516
                             'callback'        => [
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
                     '(?P<id>[^\/]+)',
542 542
                     $relation_obj
543 543
                 );
544
-                $model_routes[ $related_route ] = [
544
+                $model_routes[$related_route] = [
545 545
                     [
546 546
                         'callback'        => [
547 547
                             'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -554,8 +554,8 @@  discard block
 block discarded – undo
554 554
                     ],
555 555
                 ];
556 556
 
557
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
558
-                $model_routes[ $related_write_route ] = [
557
+                $related_write_route = $related_route.'/'.'(?P<related_id>[^\/]+)';
558
+                $model_routes[$related_write_route] = [
559 559
                     [
560 560
                         'callback'        => [
561 561
                             'EventEspresso\core\libraries\rest_api\controllers\model\Write',
@@ -609,7 +609,7 @@  discard block
 block discarded – undo
609 609
      */
610 610
     public static function get_entity_route($model, $id)
611 611
     {
612
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
612
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
613 613
     }
614 614
 
615 615
 
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
             $relation_obj->get_other_model()->get_this_model_name(),
630 630
             $relation_obj
631 631
         );
632
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
632
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
633 633
     }
634 634
 
635 635
 
@@ -643,7 +643,7 @@  discard block
 block discarded – undo
643 643
      */
644 644
     public static function get_versioned_route_to($relative_route, $version = '4.8.36')
645 645
     {
646
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
646
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
647 647
     }
648 648
 
649 649
 
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
     {
658 658
         $routes = [];
659 659
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
660
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
660
+            $routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
661 661
                 $version,
662 662
                 $hidden_endpoint
663 663
             );
@@ -789,12 +789,12 @@  discard block
 block discarded – undo
789 789
     {
790 790
         // if they're related through a HABTM relation, check for any non-FKs
791 791
         $all_relation_settings = $source_model->relation_settings();
792
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
792
+        $relation_settings = $all_relation_settings[$related_model->get_this_model_name()];
793 793
         $params = [];
794 794
         if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
795 795
             foreach ($relation_settings->getNonKeyFields() as $field) {
796 796
                 /* @var $field EE_Model_Field_Base */
797
-                $params[ $field->get_name() ] = [
797
+                $params[$field->get_name()] = [
798 798
                     'required'          => ! $field->is_nullable(),
799 799
                     'default'           => ModelDataTranslator::prepareFieldValueForJson($field,
800 800
                         $field->get_default_value(), $version),
@@ -820,7 +820,7 @@  discard block
 block discarded – undo
820 820
     {
821 821
         $default_orderby = [];
822 822
         foreach ($model->get_combined_primary_key_fields() as $key_field) {
823
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
823
+            $default_orderby[$key_field->get_name()] = 'ASC';
824 824
         }
825 825
         return array_merge(
826 826
             $this->_get_response_selection_query_params($model, $version),
@@ -854,7 +854,7 @@  discard block
 block discarded – undo
854 854
                     'type'              => [
855 855
                         'object',
856 856
                         'string',
857
-                    ],// because we accept a variety of types, WP core validation and sanitization
857
+                    ], // because we accept a variety of types, WP core validation and sanitization
858 858
                     // freaks out. We'll just validate this argument while handling the request
859 859
                     'validate_callback' => null,
860 860
                     'sanitize_callback' => null,
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
                 $model_version_info->requestedVersion()
951 951
             );
952 952
             $arg_info['sanitize_callback'] = $sanitize_callback;
953
-            $args_info[ $field_name ] = $arg_info;
953
+            $args_info[$field_name] = $arg_info;
954 954
             if ($field_obj instanceof EE_Datetime_Field) {
955 955
                 $gmt_arg_info = $arg_info;
956 956
                 $gmt_arg_info['description'] = sprintf(
@@ -961,7 +961,7 @@  discard block
 block discarded – undo
961 961
                     $field_obj->get_nicename(),
962 962
                     $field_name
963 963
                 );
964
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
964
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
965 965
             }
966 966
         }
967 967
         return $args_info;
@@ -984,16 +984,16 @@  discard block
 block discarded – undo
984 984
     public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
985 985
     {
986 986
         $attributes = $request->get_attributes();
987
-        if (! isset($attributes['args'][ $param ])
988
-            || ! is_array($attributes['args'][ $param ])) {
987
+        if ( ! isset($attributes['args'][$param])
988
+            || ! is_array($attributes['args'][$param])) {
989 989
             $validation_result = true;
990 990
         } else {
991
-            $args = $attributes['args'][ $param ];
991
+            $args = $attributes['args'][$param];
992 992
             if ((
993 993
                     $value === ''
994 994
                     || $value === null
995 995
                 )
996
-                && (! isset($args['required'])
996
+                && ( ! isset($args['required'])
997 997
                     || $args['required'] === false
998 998
                 )
999 999
             ) {
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
                       && $args['format'] === 'email'
1004 1004
             ) {
1005 1005
                 $validation_result = true;
1006
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1006
+                if ( ! EED_Core_Rest_Api::_validate_email($value)) {
1007 1007
                     $validation_result = new WP_Error(
1008 1008
                         'rest_invalid_param',
1009 1009
                         esc_html__(
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
     {
1054 1054
         $config_routes = [];
1055 1055
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1056
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1056
+            $config_routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1057 1057
                 $version,
1058 1058
                 $hidden_endpoint
1059 1059
             );
@@ -1108,7 +1108,7 @@  discard block
 block discarded – undo
1108 1108
     {
1109 1109
         $meta_routes = [];
1110 1110
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1111
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1111
+            $meta_routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1112 1112
                 $version,
1113 1113
                 $hidden_endpoint
1114 1114
             );
@@ -1161,7 +1161,7 @@  discard block
 block discarded – undo
1161 1161
             foreach ($relative_urls as $resource_name => $endpoints) {
1162 1162
                 foreach ($endpoints as $key => $endpoint) {
1163 1163
                     // skip schema and other route options
1164
-                    if (! is_numeric($key)) {
1164
+                    if ( ! is_numeric($key)) {
1165 1165
                         continue;
1166 1166
                     }
1167 1167
                     // by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1170,9 +1170,9 @@  discard block
 block discarded – undo
1170 1170
                     if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1171 1171
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1172 1172
                     ) {
1173
-                        $full_route = '/' . ltrim($namespace, '/');
1174
-                        $full_route .= '/' . ltrim($resource_name, '/');
1175
-                        unset($route_data[ $full_route ]);
1173
+                        $full_route = '/'.ltrim($namespace, '/');
1174
+                        $full_route .= '/'.ltrim($resource_name, '/');
1175
+                        unset($route_data[$full_route]);
1176 1176
                     }
1177 1177
                 }
1178 1178
             }
@@ -1246,19 +1246,19 @@  discard block
 block discarded – undo
1246 1246
 
1247 1247
             if ($key_versioned_endpoint === $latest_version) {
1248 1248
                 // don't hide the latest version in the index
1249
-                $versions_served[ $key_versioned_endpoint ] = false;
1249
+                $versions_served[$key_versioned_endpoint] = false;
1250 1250
             } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1251 1251
                       && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1252 1252
             ) {
1253 1253
                 // include, but hide, previous versions which are still supported
1254
-                $versions_served[ $key_versioned_endpoint ] = true;
1254
+                $versions_served[$key_versioned_endpoint] = true;
1255 1255
             } elseif (apply_filters(
1256 1256
                 'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1257 1257
                 false,
1258 1258
                 $possibly_served_versions
1259 1259
             )) {
1260 1260
                 // if a version is no longer supported, don't include it in index or list of versions served
1261
-                $versions_served[ $key_versioned_endpoint ] = true;
1261
+                $versions_served[$key_versioned_endpoint] = true;
1262 1262
             }
1263 1263
         }
1264 1264
         return $versions_served;
@@ -1315,7 +1315,7 @@  discard block
 block discarded – undo
1315 1315
         $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1316 1316
         $collection_routes = [];
1317 1317
         foreach ($model_names as $model_name => $model_class_name) {
1318
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1318
+            $collection_routes[strtolower($model_name)] = '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'
1319 1319
                                                             . EEH_Inflector::pluralize_and_lower($model_name);
1320 1320
         }
1321 1321
         return $collection_routes;
@@ -1337,9 +1337,9 @@  discard block
 block discarded – undo
1337 1337
             $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1338 1338
             foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1339 1339
                 if (count($primary_keys) > 1) {
1340
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1340
+                    $primary_key_items[strtolower($model_name)][] = $primary_key_name;
1341 1341
                 } else {
1342
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1342
+                    $primary_key_items[strtolower($model_name)] = $primary_key_name;
1343 1343
                 }
1344 1344
             }
1345 1345
         }
Please login to merge, or discard this patch.
core/domain/services/assets/EspressoLegacyAdminAssetManager.php 2 patches
Indentation   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -15,121 +15,121 @@
 block discarded – undo
15 15
 class EspressoLegacyAdminAssetManager extends AssetManager
16 16
 {
17 17
 
18
-    const JS_HANDLE_INJECT_WP = 'ee-inject-wp';
19
-
20
-    const JS_HANDLE_JQUERY_COOKIE = 'jquery-cookie';
21
-
22
-    const JS_HANDLE_JOYRIDE_MODERNIZR = 'joyride-modernizr';
23
-
24
-    const JS_HANDLE_JQUERY_JOYRIDE = 'jquery-joyride';
25
-
26
-    const CSS_HANDLE_EE_JOYRIDE = 'ee-joyride-css';
27
-
28
-    const CSS_HANDLE_JOYRIDE = 'joyride-css';
29
-
30
-
31
-    /**
32
-     * @inheritDoc
33
-     */
34
-    public function addAssets()
35
-    {
36
-        $joyride = filter_var(apply_filters('FHEE_load_joyride', false), FILTER_VALIDATE_BOOLEAN);
37
-        $this->registerJavascript($joyride);
38
-        $this->registerStyleSheets($joyride);
39
-    }
40
-
41
-
42
-    /**
43
-     * Register javascript assets
44
-     *
45
-     * @param bool $joyride
46
-     */
47
-    private function registerJavascript($joyride = false)
48
-    {
49
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
50
-        // Note: the intention of this script is to only do TARGETED injections.
51
-        //ie: only injecting on certain script calls.
52
-        $this->addJavascript(
53
-            EspressoLegacyAdminAssetManager::JS_HANDLE_INJECT_WP,
54
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
55
-            ['jquery'],
56
-            true,
57
-            EVENT_ESPRESSO_VERSION
58
-        );
59
-        // joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
60
-        // can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
61
-        if (! $joyride) {
62
-            return;
63
-        }
64
-        // register cookie script for future dependencies
65
-        $this->addJavascript(
66
-            EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
67
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
68
-            ['jquery'],
69
-            true,
70
-            '2.1'
71
-        );
72
-        $this->addJavascript(
73
-            EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
74
-            EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
75
-            [],
76
-            true,
77
-            '2.1'
78
-        );
79
-        // wanna go for a joyride?
80
-        $this->addJavascript(
81
-            EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
82
-            EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
83
-            [
84
-                EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
85
-                EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR
86
-            ],
87
-            '2.1',
88
-            true
89
-        )->enqueueAsset();
90
-        $this->loadQtipJs();
91
-    }
92
-
93
-
94
-    /**
95
-     * Register CSS assets.
96
-     *
97
-     * @param bool $joyride
98
-     */
99
-    private function registerStyleSheets($joyride = false)
100
-    {
101
-        if (! $joyride) {
102
-            return;
103
-        }       // joyride style
104
-        $this->addStylesheet(
105
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
106
-            EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
107
-            [],
108
-            'all',
109
-            '2.1'
110
-        );
111
-        $this->addStylesheet(
112
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
113
-            EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
114
-            ['joyride-css'],
115
-            'all',
116
-            EVENT_ESPRESSO_VERSION
117
-        )->enqueueAsset();
118
-    }
119
-
120
-
121
-    /**
122
-     * registers assets for cleaning your ears
123
-     */
124
-    public function loadQtipJs()
125
-    {
126
-        // qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
127
-        // can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
128
-        if (apply_filters('FHEE_load_qtip', false)) {
129
-            $qtip_loader = EEH_Qtip_Loader::instance();
130
-            if ($qtip_loader instanceof EEH_Qtip_Loader) {
131
-                $qtip_loader->register_and_enqueue();
132
-            }
133
-        }
134
-    }
18
+	const JS_HANDLE_INJECT_WP = 'ee-inject-wp';
19
+
20
+	const JS_HANDLE_JQUERY_COOKIE = 'jquery-cookie';
21
+
22
+	const JS_HANDLE_JOYRIDE_MODERNIZR = 'joyride-modernizr';
23
+
24
+	const JS_HANDLE_JQUERY_JOYRIDE = 'jquery-joyride';
25
+
26
+	const CSS_HANDLE_EE_JOYRIDE = 'ee-joyride-css';
27
+
28
+	const CSS_HANDLE_JOYRIDE = 'joyride-css';
29
+
30
+
31
+	/**
32
+	 * @inheritDoc
33
+	 */
34
+	public function addAssets()
35
+	{
36
+		$joyride = filter_var(apply_filters('FHEE_load_joyride', false), FILTER_VALIDATE_BOOLEAN);
37
+		$this->registerJavascript($joyride);
38
+		$this->registerStyleSheets($joyride);
39
+	}
40
+
41
+
42
+	/**
43
+	 * Register javascript assets
44
+	 *
45
+	 * @param bool $joyride
46
+	 */
47
+	private function registerJavascript($joyride = false)
48
+	{
49
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
50
+		// Note: the intention of this script is to only do TARGETED injections.
51
+		//ie: only injecting on certain script calls.
52
+		$this->addJavascript(
53
+			EspressoLegacyAdminAssetManager::JS_HANDLE_INJECT_WP,
54
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
55
+			['jquery'],
56
+			true,
57
+			EVENT_ESPRESSO_VERSION
58
+		);
59
+		// joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
60
+		// can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
61
+		if (! $joyride) {
62
+			return;
63
+		}
64
+		// register cookie script for future dependencies
65
+		$this->addJavascript(
66
+			EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
67
+			EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
68
+			['jquery'],
69
+			true,
70
+			'2.1'
71
+		);
72
+		$this->addJavascript(
73
+			EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
74
+			EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
75
+			[],
76
+			true,
77
+			'2.1'
78
+		);
79
+		// wanna go for a joyride?
80
+		$this->addJavascript(
81
+			EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
82
+			EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
83
+			[
84
+				EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
85
+				EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR
86
+			],
87
+			'2.1',
88
+			true
89
+		)->enqueueAsset();
90
+		$this->loadQtipJs();
91
+	}
92
+
93
+
94
+	/**
95
+	 * Register CSS assets.
96
+	 *
97
+	 * @param bool $joyride
98
+	 */
99
+	private function registerStyleSheets($joyride = false)
100
+	{
101
+		if (! $joyride) {
102
+			return;
103
+		}       // joyride style
104
+		$this->addStylesheet(
105
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
106
+			EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
107
+			[],
108
+			'all',
109
+			'2.1'
110
+		);
111
+		$this->addStylesheet(
112
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
113
+			EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
114
+			['joyride-css'],
115
+			'all',
116
+			EVENT_ESPRESSO_VERSION
117
+		)->enqueueAsset();
118
+	}
119
+
120
+
121
+	/**
122
+	 * registers assets for cleaning your ears
123
+	 */
124
+	public function loadQtipJs()
125
+	{
126
+		// qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
127
+		// can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
128
+		if (apply_filters('FHEE_load_qtip', false)) {
129
+			$qtip_loader = EEH_Qtip_Loader::instance();
130
+			if ($qtip_loader instanceof EEH_Qtip_Loader) {
131
+				$qtip_loader->register_and_enqueue();
132
+			}
133
+		}
134
+	}
135 135
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -51,27 +51,27 @@  discard block
 block discarded – undo
51 51
         //ie: only injecting on certain script calls.
52 52
         $this->addJavascript(
53 53
             EspressoLegacyAdminAssetManager::JS_HANDLE_INJECT_WP,
54
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
54
+            EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js',
55 55
             ['jquery'],
56 56
             true,
57 57
             EVENT_ESPRESSO_VERSION
58 58
         );
59 59
         // joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
60 60
         // can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
61
-        if (! $joyride) {
61
+        if ( ! $joyride) {
62 62
             return;
63 63
         }
64 64
         // register cookie script for future dependencies
65 65
         $this->addJavascript(
66 66
             EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
67
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
67
+            EE_THIRD_PARTY_URL.'joyride/jquery.cookie.js',
68 68
             ['jquery'],
69 69
             true,
70 70
             '2.1'
71 71
         );
72 72
         $this->addJavascript(
73 73
             EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
74
-            EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
74
+            EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js',
75 75
             [],
76 76
             true,
77 77
             '2.1'
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
         // wanna go for a joyride?
80 80
         $this->addJavascript(
81 81
             EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
82
-            EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
82
+            EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js',
83 83
             [
84 84
                 EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_COOKIE,
85 85
                 EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR
@@ -98,19 +98,19 @@  discard block
 block discarded – undo
98 98
      */
99 99
     private function registerStyleSheets($joyride = false)
100 100
     {
101
-        if (! $joyride) {
101
+        if ( ! $joyride) {
102 102
             return;
103 103
         }       // joyride style
104 104
         $this->addStylesheet(
105 105
             EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
106
-            EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
106
+            EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css',
107 107
             [],
108 108
             'all',
109 109
             '2.1'
110 110
         );
111 111
         $this->addStylesheet(
112 112
             EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
113
-            EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
113
+            EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css',
114 114
             ['joyride-css'],
115 115
             'all',
116 116
             EVENT_ESPRESSO_VERSION
Please login to merge, or discard this patch.
core/services/dependencies/DependencyResolver.php 2 patches
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -23,168 +23,168 @@
 block discarded – undo
23 23
 class DependencyResolver implements DependencyResolverInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var Mirror $mirror
28
-     */
29
-    private $mirror;
30
-
31
-    /**
32
-     * @var ClassInterfaceCache $class_cache
33
-     */
34
-    private $class_cache;
35
-
36
-    /**
37
-     * @var EE_Dependency_Map $dependency_map
38
-     */
39
-    private $dependency_map;
40
-
41
-    /**
42
-     * @var ClassAlias[] $aliases
43
-     */
44
-    protected $aliases = array();
45
-
46
-    /**
47
-     * @var array $namespace_roots
48
-     */
49
-    protected $namespace_roots = array();
50
-
51
-
52
-    /**
53
-     * RouteMatchSpecificationDependencyResolver constructor.
54
-     *
55
-     * @param Mirror              $mirror
56
-     * @param ClassInterfaceCache $class_cache
57
-     * @param EE_Dependency_Map   $dependency_map
58
-     */
59
-    public function __construct(
60
-        Mirror $mirror,
61
-        ClassInterfaceCache $class_cache,
62
-        EE_Dependency_Map $dependency_map
63
-    ) {
64
-        $this->mirror = $mirror;
65
-        $this->class_cache = $class_cache;
66
-        $this->dependency_map = $dependency_map;
67
-        $this->initialize();
68
-    }
69
-
70
-
71
-    /**
72
-     * Used to configure and/or setup any aliases or namespace roots required by the DependencyResolver
73
-     *
74
-     * @throws InvalidAliasException
75
-     * @since 4.9.71.p
76
-     */
77
-    public function initialize()
78
-    {
79
-        // nothing to do here for default resolver
80
-    }
81
-
82
-
83
-    /**
84
-     * @return Mirror
85
-     */
86
-    public function mirror()
87
-    {
88
-        return $this->mirror;
89
-    }
90
-
91
-    /**
92
-     * @return ClassInterfaceCache
93
-     */
94
-    public function classCache()
95
-    {
96
-        return $this->class_cache;
97
-    }
98
-
99
-    /**
100
-     * @return EE_Dependency_Map
101
-     */
102
-    public function dependencyMap()
103
-    {
104
-        return $this->dependency_map;
105
-    }
106
-
107
-    /**
108
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
109
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
110
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
111
-     * @throws InvalidAliasException
112
-     */
113
-    public function addAlias($fqcn, $alias, $for_class = '')
114
-    {
115
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
116
-    }
117
-
118
-    /**
119
-     * @param string $param_fqcn Fully Qualified Class Name for dependency parameter
120
-     * @return string
121
-     */
122
-    public function resolveAlias($param_fqcn)
123
-    {
124
-        return $this->class_cache->getFqnForAlias($param_fqcn);
125
-    }
126
-
127
-    /**
128
-     * Primarily used to indicate the namespace root for composite objects
129
-     * so that dependencies requiring the same DependencyResolver can be acquired
130
-     * for example:
131
-     * Vendor\path\to\class\A, Vendor\path\to\class\B, and Vendor\path\to\class\C
132
-     * may all implement Vendor\path\to\Interface,
133
-     * but Vendor\path\to\class\C could be a composite object
134
-     * that requires Vendor\path\to\class\A and Vendor\path\to\class\B,
135
-     * and needs both of those dependencies resolved, which would therefore require
136
-     * the use of the same DependencyResolver.
137
-     *
138
-     * By specifying a namespace root of "Vendor\path\to\",
139
-     * then all classes that are descendants of that namespace
140
-     * will use DependencyResolver to acquire the classes they need
141
-     *
142
-     * @param string $namespace_root Partial namespace used for detecting other classes
143
-     *                               that should employ this same DependencyResolver
144
-     */
145
-    public function addNamespaceRoot($namespace_root)
146
-    {
147
-        $this->namespace_roots[] = $namespace_root;
148
-    }
149
-
150
-    /**
151
-     * Returns true if the parameter FQCN belongs to one of
152
-     * the namespaces that utilizes this DependencyResolver
153
-     *
154
-     * @param string $param_fqcn Fully Qualified Class Name for dependency parameter
155
-     * @return boolean
156
-     * @since 4.9.71.p
157
-     */
158
-    public function dependencyRecursionExists($param_fqcn)
159
-    {
160
-        foreach ($this->namespace_roots as $namespace_root) {
161
-            if (strpos($param_fqcn, $namespace_root) !== false) {
162
-                return true;
163
-            }
164
-        }
165
-        return false;
166
-    }
167
-
168
-
169
-    /**
170
-     * @param string $fqcn Fully Qualified Class Name
171
-     * @throws InvalidDataTypeException
172
-     * @throws ReflectionException
173
-     * @since 4.9.71.p
174
-     */
175
-    public function resolveDependenciesForClass($fqcn)
176
-    {
177
-        $dependencies = array();
178
-        $params = $this->mirror()->getParameters($fqcn);
179
-        foreach ($params as $index => $param) {
180
-            // is this a dependency for a specific class ?
181
-            $param_class = $this->mirror()->getParameterClassName($param, $fqcn, $index);
182
-            if ($this->dependencyRecursionExists($param_class)) {
183
-                $this->resolveDependenciesForClass($param_class);
184
-            }
185
-            $param_class = $this->resolveAlias($param_class);
186
-            $dependencies[ $param_class ] = EE_Dependency_Map::load_from_cache;
187
-        }
188
-        $this->dependencyMap()->registerDependencies($fqcn, $dependencies);
189
-    }
26
+	/**
27
+	 * @var Mirror $mirror
28
+	 */
29
+	private $mirror;
30
+
31
+	/**
32
+	 * @var ClassInterfaceCache $class_cache
33
+	 */
34
+	private $class_cache;
35
+
36
+	/**
37
+	 * @var EE_Dependency_Map $dependency_map
38
+	 */
39
+	private $dependency_map;
40
+
41
+	/**
42
+	 * @var ClassAlias[] $aliases
43
+	 */
44
+	protected $aliases = array();
45
+
46
+	/**
47
+	 * @var array $namespace_roots
48
+	 */
49
+	protected $namespace_roots = array();
50
+
51
+
52
+	/**
53
+	 * RouteMatchSpecificationDependencyResolver constructor.
54
+	 *
55
+	 * @param Mirror              $mirror
56
+	 * @param ClassInterfaceCache $class_cache
57
+	 * @param EE_Dependency_Map   $dependency_map
58
+	 */
59
+	public function __construct(
60
+		Mirror $mirror,
61
+		ClassInterfaceCache $class_cache,
62
+		EE_Dependency_Map $dependency_map
63
+	) {
64
+		$this->mirror = $mirror;
65
+		$this->class_cache = $class_cache;
66
+		$this->dependency_map = $dependency_map;
67
+		$this->initialize();
68
+	}
69
+
70
+
71
+	/**
72
+	 * Used to configure and/or setup any aliases or namespace roots required by the DependencyResolver
73
+	 *
74
+	 * @throws InvalidAliasException
75
+	 * @since 4.9.71.p
76
+	 */
77
+	public function initialize()
78
+	{
79
+		// nothing to do here for default resolver
80
+	}
81
+
82
+
83
+	/**
84
+	 * @return Mirror
85
+	 */
86
+	public function mirror()
87
+	{
88
+		return $this->mirror;
89
+	}
90
+
91
+	/**
92
+	 * @return ClassInterfaceCache
93
+	 */
94
+	public function classCache()
95
+	{
96
+		return $this->class_cache;
97
+	}
98
+
99
+	/**
100
+	 * @return EE_Dependency_Map
101
+	 */
102
+	public function dependencyMap()
103
+	{
104
+		return $this->dependency_map;
105
+	}
106
+
107
+	/**
108
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
109
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
110
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
111
+	 * @throws InvalidAliasException
112
+	 */
113
+	public function addAlias($fqcn, $alias, $for_class = '')
114
+	{
115
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
116
+	}
117
+
118
+	/**
119
+	 * @param string $param_fqcn Fully Qualified Class Name for dependency parameter
120
+	 * @return string
121
+	 */
122
+	public function resolveAlias($param_fqcn)
123
+	{
124
+		return $this->class_cache->getFqnForAlias($param_fqcn);
125
+	}
126
+
127
+	/**
128
+	 * Primarily used to indicate the namespace root for composite objects
129
+	 * so that dependencies requiring the same DependencyResolver can be acquired
130
+	 * for example:
131
+	 * Vendor\path\to\class\A, Vendor\path\to\class\B, and Vendor\path\to\class\C
132
+	 * may all implement Vendor\path\to\Interface,
133
+	 * but Vendor\path\to\class\C could be a composite object
134
+	 * that requires Vendor\path\to\class\A and Vendor\path\to\class\B,
135
+	 * and needs both of those dependencies resolved, which would therefore require
136
+	 * the use of the same DependencyResolver.
137
+	 *
138
+	 * By specifying a namespace root of "Vendor\path\to\",
139
+	 * then all classes that are descendants of that namespace
140
+	 * will use DependencyResolver to acquire the classes they need
141
+	 *
142
+	 * @param string $namespace_root Partial namespace used for detecting other classes
143
+	 *                               that should employ this same DependencyResolver
144
+	 */
145
+	public function addNamespaceRoot($namespace_root)
146
+	{
147
+		$this->namespace_roots[] = $namespace_root;
148
+	}
149
+
150
+	/**
151
+	 * Returns true if the parameter FQCN belongs to one of
152
+	 * the namespaces that utilizes this DependencyResolver
153
+	 *
154
+	 * @param string $param_fqcn Fully Qualified Class Name for dependency parameter
155
+	 * @return boolean
156
+	 * @since 4.9.71.p
157
+	 */
158
+	public function dependencyRecursionExists($param_fqcn)
159
+	{
160
+		foreach ($this->namespace_roots as $namespace_root) {
161
+			if (strpos($param_fqcn, $namespace_root) !== false) {
162
+				return true;
163
+			}
164
+		}
165
+		return false;
166
+	}
167
+
168
+
169
+	/**
170
+	 * @param string $fqcn Fully Qualified Class Name
171
+	 * @throws InvalidDataTypeException
172
+	 * @throws ReflectionException
173
+	 * @since 4.9.71.p
174
+	 */
175
+	public function resolveDependenciesForClass($fqcn)
176
+	{
177
+		$dependencies = array();
178
+		$params = $this->mirror()->getParameters($fqcn);
179
+		foreach ($params as $index => $param) {
180
+			// is this a dependency for a specific class ?
181
+			$param_class = $this->mirror()->getParameterClassName($param, $fqcn, $index);
182
+			if ($this->dependencyRecursionExists($param_class)) {
183
+				$this->resolveDependenciesForClass($param_class);
184
+			}
185
+			$param_class = $this->resolveAlias($param_class);
186
+			$dependencies[ $param_class ] = EE_Dependency_Map::load_from_cache;
187
+		}
188
+		$this->dependencyMap()->registerDependencies($fqcn, $dependencies);
189
+	}
190 190
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -183,7 +183,7 @@
 block discarded – undo
183 183
                 $this->resolveDependenciesForClass($param_class);
184 184
             }
185 185
             $param_class = $this->resolveAlias($param_class);
186
-            $dependencies[ $param_class ] = EE_Dependency_Map::load_from_cache;
186
+            $dependencies[$param_class] = EE_Dependency_Map::load_from_cache;
187 187
         }
188 188
         $this->dependencyMap()->registerDependencies($fqcn, $dependencies);
189 189
     }
Please login to merge, or discard this patch.
core/services/routing/RouteMatchSpecificationDependencyResolver.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -21,18 +21,18 @@
 block discarded – undo
21 21
 class RouteMatchSpecificationDependencyResolver extends DependencyResolver
22 22
 {
23 23
 
24
-    /**
25
-     * Used to configure and/or setup any aliases or namespace roots required by the DependencyResolver
26
-     *
27
-     * @since 4.9.71.p
28
-     * @throws InvalidAliasException
29
-     */
30
-    public function initialize()
31
-    {
32
-        $this->addAlias(
33
-            'EventEspresso\core\services\request\Request',
34
-            'EventEspresso\core\services\request\RequestInterface'
35
-        );
36
-        $this->addNamespaceRoot('EventEspresso\core\domain\entities\routing\specifications');
37
-    }
24
+	/**
25
+	 * Used to configure and/or setup any aliases or namespace roots required by the DependencyResolver
26
+	 *
27
+	 * @since 4.9.71.p
28
+	 * @throws InvalidAliasException
29
+	 */
30
+	public function initialize()
31
+	{
32
+		$this->addAlias(
33
+			'EventEspresso\core\services\request\Request',
34
+			'EventEspresso\core\services\request\RequestInterface'
35
+		);
36
+		$this->addNamespaceRoot('EventEspresso\core\domain\entities\routing\specifications');
37
+	}
38 38
 }
Please login to merge, or discard this patch.
core/services/routing/RouteHandler.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@
 block discarded – undo
56 56
     {
57 57
         try {
58 58
             $route = $this->loader->getShared($fqcn);
59
-            if (! $route instanceof RouteInterface) {
59
+            if ( ! $route instanceof RouteInterface) {
60 60
                 throw new InvalidClassException(
61 61
                     sprintf(
62 62
                         esc_html__(
Please login to merge, or discard this patch.
Indentation   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -19,80 +19,80 @@
 block discarded – undo
19 19
 class RouteHandler
20 20
 {
21 21
 
22
-    /**
23
-     * @var LoaderInterface
24
-     */
25
-    private $loader;
22
+	/**
23
+	 * @var LoaderInterface
24
+	 */
25
+	private $loader;
26 26
 
27
-    /**
28
-     * @var RouteCollection $routes
29
-     */
30
-    private $routes;
27
+	/**
28
+	 * @var RouteCollection $routes
29
+	 */
30
+	private $routes;
31 31
 
32 32
 
33
-    /**
34
-     * RouteHandler constructor.
35
-     *
36
-     * @param LoaderInterface  $loader
37
-     * @param RouteCollection $routes
38
-     */
39
-    public function __construct(LoaderInterface $loader, RouteCollection $routes) {
40
-        $this->loader = $loader;
41
-        $this->routes = $routes;
42
-    }
33
+	/**
34
+	 * RouteHandler constructor.
35
+	 *
36
+	 * @param LoaderInterface  $loader
37
+	 * @param RouteCollection $routes
38
+	 */
39
+	public function __construct(LoaderInterface $loader, RouteCollection $routes) {
40
+		$this->loader = $loader;
41
+		$this->routes = $routes;
42
+	}
43 43
 
44 44
 
45
-    /**
46
-     * @param string $fqcn   Fully Qualified Class Name for Route
47
-     * @param bool   $handle if true [default] will immediately call RouteInterface::handleRequest()
48
-     * @throws Exception
49
-     * @since $VID:$
50
-     */
51
-    public function addRoute($fqcn, $handle = true)
52
-    {
53
-        try {
54
-            $route = $this->loader->getShared($fqcn);
55
-            if (! $route instanceof RouteInterface) {
56
-                throw new InvalidClassException(
57
-                    sprintf(
58
-                        esc_html__(
59
-                            'The supplied FQCN (%1$s) must be an instance of RouteInterface.',
60
-                            'eventespresso'
61
-                        ),
62
-                        $fqcn
63
-                    )
64
-                );
65
-            }
66
-            $this->routes->add($route);
67
-            if ($handle) {
68
-                $route->handleRequest();
69
-            }
70
-        } catch (Exception $exception) {
71
-            new ExceptionStackTraceDisplay($exception);
72
-        }
73
-    }
45
+	/**
46
+	 * @param string $fqcn   Fully Qualified Class Name for Route
47
+	 * @param bool   $handle if true [default] will immediately call RouteInterface::handleRequest()
48
+	 * @throws Exception
49
+	 * @since $VID:$
50
+	 */
51
+	public function addRoute($fqcn, $handle = true)
52
+	{
53
+		try {
54
+			$route = $this->loader->getShared($fqcn);
55
+			if (! $route instanceof RouteInterface) {
56
+				throw new InvalidClassException(
57
+					sprintf(
58
+						esc_html__(
59
+							'The supplied FQCN (%1$s) must be an instance of RouteInterface.',
60
+							'eventespresso'
61
+						),
62
+						$fqcn
63
+					)
64
+				);
65
+			}
66
+			$this->routes->add($route);
67
+			if ($handle) {
68
+				$route->handleRequest();
69
+			}
70
+		} catch (Exception $exception) {
71
+			new ExceptionStackTraceDisplay($exception);
72
+		}
73
+	}
74 74
 
75 75
 
76
-    /**
77
-     * finds and returns all Routes that have yet to be handled
78
-     *
79
-     * @return RouteInterface[]
80
-     */
81
-    public function getRoutesForCurrentRequest()
82
-    {
83
-        return $this->routes->getRoutesForCurrentRequest();
84
-    }
76
+	/**
77
+	 * finds and returns all Routes that have yet to be handled
78
+	 *
79
+	 * @return RouteInterface[]
80
+	 */
81
+	public function getRoutesForCurrentRequest()
82
+	{
83
+		return $this->routes->getRoutesForCurrentRequest();
84
+	}
85 85
 
86 86
 
87
-    /**
88
-     * calls RouteInterface::handleRequest() on all Routes that
89
-     *      - match current request
90
-     *      - have yet to be handled
91
-     *
92
-     * @return void
93
-     */
94
-    public function handleRoutesForCurrentRequest()
95
-    {
96
-        $this->routes->handleRoutesForCurrentRequest();
97
-    }
87
+	/**
88
+	 * calls RouteInterface::handleRequest() on all Routes that
89
+	 *      - match current request
90
+	 *      - have yet to be handled
91
+	 *
92
+	 * @return void
93
+	 */
94
+	public function handleRoutesForCurrentRequest()
95
+	{
96
+		$this->routes->handleRoutesForCurrentRequest();
97
+	}
98 98
 }
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 2 patches
Indentation   +1147 added lines, -1147 removed lines patch added patch discarded remove patch
@@ -16,1151 +16,1151 @@
 block discarded – undo
16 16
 class Payments_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * Variables used for when we're re-sorting the logs results, in case
21
-     * we needed to do two queries and we need to resort
22
-     *
23
-     * @var string
24
-     */
25
-    private $_sort_logs_again_direction;
26
-
27
-
28
-    /**
29
-     * @Constructor
30
-     * @access public
31
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
-     * @throws EE_Error
33
-     * @throws InvalidArgumentException
34
-     * @throws InvalidDataTypeException
35
-     * @throws InvalidInterfaceException
36
-     * @throws ReflectionException
37
-     */
38
-    public function __construct($routing = true)
39
-    {
40
-        parent::__construct($routing);
41
-    }
42
-
43
-
44
-    protected function _init_page_props()
45
-    {
46
-        $this->page_slug = EE_PAYMENTS_PG_SLUG;
47
-        $this->page_label = __('Payment Methods', 'event_espresso');
48
-        $this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
-    }
51
-
52
-
53
-    protected function _ajax_hooks()
54
-    {
55
-        // todo: all hooks for ajax goes here.
56
-    }
57
-
58
-
59
-    protected function _define_page_props()
60
-    {
61
-        $this->_admin_page_title = $this->page_label;
62
-        $this->_labels = array(
63
-            'publishbox' => __('Update Settings', 'event_espresso'),
64
-        );
65
-    }
66
-
67
-
68
-    protected function _set_page_routes()
69
-    {
70
-        /**
71
-         * note that with payment method capabilities, although we've implemented
72
-         * capability mapping which will be used for accessing payment methods owned by
73
-         * other users.  This is not fully implemented yet in the payment method ui.
74
-         * Currently only the "plural" caps are in active use.
75
-         * When cap mapping is implemented, some routes will need to use the singular form of
76
-         * capability method and also include the $id of the payment method for the route.
77
-         **/
78
-        $this->_page_routes = array(
79
-            'default'                   => array(
80
-                'func'       => '_payment_methods_list',
81
-                'capability' => 'ee_edit_payment_methods',
82
-            ),
83
-            'payment_settings'          => array(
84
-                'func'       => '_payment_settings',
85
-                'capability' => 'ee_manage_gateways',
86
-            ),
87
-            'activate_payment_method'   => array(
88
-                'func'       => '_activate_payment_method',
89
-                'noheader'   => true,
90
-                'capability' => 'ee_edit_payment_methods',
91
-            ),
92
-            'deactivate_payment_method' => array(
93
-                'func'       => '_deactivate_payment_method',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_delete_payment_methods',
96
-            ),
97
-            'update_payment_method'     => array(
98
-                'func'               => '_update_payment_method',
99
-                'noheader'           => true,
100
-                'headers_sent_route' => 'default',
101
-                'capability'         => 'ee_edit_payment_methods',
102
-            ),
103
-            'update_payment_settings'   => array(
104
-                'func'       => '_update_payment_settings',
105
-                'noheader'   => true,
106
-                'capability' => 'ee_manage_gateways',
107
-            ),
108
-            'payment_log'               => array(
109
-                'func'       => '_payment_log_overview_list_table',
110
-                'capability' => 'ee_read_payment_methods',
111
-            ),
112
-            'payment_log_details'       => array(
113
-                'func'       => '_payment_log_details',
114
-                'capability' => 'ee_read_payment_methods',
115
-            ),
116
-        );
117
-    }
118
-
119
-
120
-    protected function _set_page_config()
121
-    {
122
-        $payment_method_list_config = array(
123
-            'nav'           => array(
124
-                'label' => __('Payment Methods', 'event_espresso'),
125
-                'order' => 10,
126
-            ),
127
-            'metaboxes'     => $this->_default_espresso_metaboxes,
128
-            'help_tabs'     => array_merge(
129
-                array(
130
-                    'payment_methods_overview_help_tab' => array(
131
-                        'title'    => __('Payment Methods Overview', 'event_espresso'),
132
-                        'filename' => 'payment_methods_overview',
133
-                    ),
134
-                ),
135
-                $this->_add_payment_method_help_tabs()
136
-            ),
137
-            'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
138
-            'require_nonce' => false,
139
-        );
140
-        $this->_page_config = array(
141
-            'default'          => $payment_method_list_config,
142
-            'payment_settings' => array(
143
-                'nav'           => array(
144
-                    'label' => __('Settings', 'event_espresso'),
145
-                    'order' => 20,
146
-                ),
147
-                'help_tabs'     => array(
148
-                    'payment_methods_settings_help_tab' => array(
149
-                        'title'    => __('Payment Method Settings', 'event_espresso'),
150
-                        'filename' => 'payment_methods_settings',
151
-                    ),
152
-                ),
153
-                // 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
154
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
155
-                'require_nonce' => false,
156
-            ),
157
-            'payment_log'      => array(
158
-                'nav'           => array(
159
-                    'label' => __("Logs", 'event_espresso'),
160
-                    'order' => 30,
161
-                ),
162
-                'list_table'    => 'Payment_Log_Admin_List_Table',
163
-                'metaboxes'     => $this->_default_espresso_metaboxes,
164
-                'require_nonce' => false,
165
-            ),
166
-        );
167
-    }
168
-
169
-
170
-    /**
171
-     * @return array
172
-     * @throws DomainException
173
-     * @throws EE_Error
174
-     * @throws InvalidArgumentException
175
-     * @throws InvalidDataTypeException
176
-     * @throws InvalidInterfaceException
177
-     * @throws ReflectionException
178
-     */
179
-    protected function _add_payment_method_help_tabs()
180
-    {
181
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
182
-        $payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
183
-        $all_pmt_help_tabs_config = array();
184
-        foreach ($payment_method_types as $payment_method_type) {
185
-            if (! EE_Registry::instance()->CAP->current_user_can(
186
-                $payment_method_type->cap_name(),
187
-                'specific_payment_method_type_access'
188
-            )
189
-            ) {
190
-                continue;
191
-            }
192
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
193
-                $template_args = isset($config['template_args']) ? $config['template_args'] : array();
194
-                $template_args['admin_page_obj'] = $this;
195
-                $all_pmt_help_tabs_config[ $help_tab_name ] = array(
196
-                    'title'   => $config['title'],
197
-                    'content' => EEH_Template::display_template(
198
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
199
-                        $template_args,
200
-                        true
201
-                    ),
202
-                );
203
-            }
204
-        }
205
-        return $all_pmt_help_tabs_config;
206
-    }
207
-
208
-
209
-    // none of the below group are currently used for Gateway Settings
210
-    protected function _add_screen_options()
211
-    {
212
-    }
213
-
214
-
215
-    protected function _add_feature_pointers()
216
-    {
217
-    }
218
-
219
-
220
-    public function admin_init()
221
-    {
222
-    }
223
-
224
-
225
-    public function admin_notices()
226
-    {
227
-    }
228
-
229
-
230
-    public function admin_footer_scripts()
231
-    {
232
-    }
233
-
234
-
235
-    public function load_scripts_styles()
236
-    {
237
-        wp_enqueue_script('ee_admin_js');
238
-        wp_enqueue_script('ee-text-links');
239
-        wp_enqueue_script(
240
-            'espresso_payments',
241
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
242
-            ['ee-datepicker'],
243
-            EVENT_ESPRESSO_VERSION,
244
-            true
245
-        );
246
-        wp_enqueue_style('espresso-ui-theme');
247
-    }
248
-
249
-
250
-    public function load_scripts_styles_default()
251
-    {
252
-        // styles
253
-        wp_register_style(
254
-            'espresso_payments',
255
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
256
-            array(),
257
-            EVENT_ESPRESSO_VERSION
258
-        );
259
-        wp_enqueue_style('espresso_payments');
260
-        wp_enqueue_style('ee-text-links');
261
-        // scripts
262
-    }
263
-
264
-
265
-    protected function _payment_methods_list()
266
-    {
267
-        /**
268
-         * first let's ensure payment methods have been setup. We do this here because when people activate a
269
-         * payment method for the first time (as an addon), it may not setup its capabilities or get registered
270
-         * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
271
-         * safe to do a recheck here.
272
-         */
273
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
274
-        EEM_Payment_Method::instance()->verify_button_urls();
275
-        // setup tabs, one for each payment method type
276
-        $tabs = array();
277
-        $payment_methods = array();
278
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
279
-            // we don't want to show admin-only PMTs for now
280
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
281
-                continue;
282
-            }
283
-            // check access
284
-            if (! EE_Registry::instance()->CAP->current_user_can(
285
-                $pmt_obj->cap_name(),
286
-                'specific_payment_method_type_access'
287
-            )
288
-            ) {
289
-                continue;
290
-            }
291
-            // check for any active pms of that type
292
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
293
-            if (! $payment_method instanceof EE_Payment_Method) {
294
-                $payment_method = EE_Payment_Method::new_instance(
295
-                    array(
296
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
297
-                        'PMD_type'       => $pmt_obj->system_name(),
298
-                        'PMD_name'       => $pmt_obj->pretty_name(),
299
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
300
-                    )
301
-                );
302
-            }
303
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
304
-        }
305
-        $payment_methods = apply_filters(
306
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
307
-            $payment_methods
308
-        );
309
-        foreach ($payment_methods as $payment_method) {
310
-            if ($payment_method instanceof EE_Payment_Method) {
311
-                add_meta_box(
312
-                    // html id
313
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
314
-                    // title
315
-                    sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
316
-                    // callback
317
-                    array($this, 'payment_method_settings_meta_box'),
318
-                    // post type
319
-                    null,
320
-                    // context
321
-                    'normal',
322
-                    // priority
323
-                    'default',
324
-                    // callback args
325
-                    array('payment_method' => $payment_method)
326
-                );
327
-                // setup for tabbed content
328
-                $tabs[ $payment_method->slug() ] = array(
329
-                    'label' => $payment_method->admin_name(),
330
-                    'class' => $payment_method->active() ? 'gateway-active' : '',
331
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
332
-                    'title' => __('Modify this Payment Method', 'event_espresso'),
333
-                    'slug'  => $payment_method->slug(),
334
-                );
335
-            }
336
-        }
337
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
338
-            $tabs,
339
-            'payment_method_links',
340
-            '|',
341
-            $this->_get_active_payment_method_slug()
342
-        );
343
-        $this->display_admin_page_with_sidebar();
344
-    }
345
-
346
-
347
-    /**
348
-     *   _get_active_payment_method_slug
349
-     *
350
-     * @return string
351
-     */
352
-    protected function _get_active_payment_method_slug()
353
-    {
354
-        $payment_method_slug = false;
355
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
356
-        if (isset($this->_req_data['payment_method'])) {
357
-            // if they provided the current payment method, use it
358
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
359
-        }
360
-        $payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
361
-        // if that didn't work or wasn't provided, find another way to select the current pm
362
-        if (! $this->_verify_payment_method($payment_method)) {
363
-            // like, looking for an active one
364
-            $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
365
-            // test that one as well
366
-            if ($this->_verify_payment_method($payment_method)) {
367
-                $payment_method_slug = $payment_method->slug();
368
-            } else {
369
-                $payment_method_slug = 'paypal_standard';
370
-            }
371
-        }
372
-        return $payment_method_slug;
373
-    }
374
-
375
-
376
-    /**
377
-     *    payment_method_settings_meta_box
378
-     *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
379
-     *    capabilities to access it
380
-     *
381
-     * @param EE_Payment_Method $payment_method
382
-     * @return boolean
383
-     */
384
-    protected function _verify_payment_method($payment_method)
385
-    {
386
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
387
-            && EE_Registry::instance()->CAP->current_user_can(
388
-                $payment_method->type_obj()->cap_name(),
389
-                'specific_payment_method_type_access'
390
-            )
391
-        ) {
392
-            return true;
393
-        }
394
-        return false;
395
-    }
396
-
397
-
398
-    /**
399
-     *    payment_method_settings_meta_box
400
-     *
401
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
402
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
403
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
404
-     * @return string
405
-     * @throws EE_Error
406
-     */
407
-    public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
408
-    {
409
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
410
-            ? $metabox['args']['payment_method'] : null;
411
-        if (! $payment_method instanceof EE_Payment_Method) {
412
-            throw new EE_Error(
413
-                sprintf(
414
-                    __(
415
-                        'Payment method metabox setup incorrectly. No Payment method object was supplied',
416
-                        'event_espresso'
417
-                    )
418
-                )
419
-            );
420
-        }
421
-        $payment_method_scopes = $payment_method->active();
422
-        // if the payment method really exists show its form, otherwise the activation template
423
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
424
-            $form = $this->_generate_payment_method_settings_form($payment_method);
425
-            if ($form->form_data_present_in($this->_req_data)) {
426
-                $form->receive_form_submission($this->_req_data);
427
-            }
428
-            echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
429
-        } else {
430
-            echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
431
-        }
432
-    }
433
-
434
-
435
-    /**
436
-     * Gets the form for all the settings related to this payment method type
437
-     *
438
-     * @access protected
439
-     * @param EE_Payment_Method $payment_method
440
-     * @return EE_Form_Section_Proper
441
-     */
442
-    protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
443
-    {
444
-        if (! $payment_method instanceof EE_Payment_Method) {
445
-            return new EE_Form_Section_Proper();
446
-        }
447
-        return new EE_Form_Section_Proper(
448
-            array(
449
-                'name'            => $payment_method->slug() . '_settings_form',
450
-                'html_id'         => $payment_method->slug() . '_settings_form',
451
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
452
-                    array(
453
-                        'action'         => 'update_payment_method',
454
-                        'payment_method' => $payment_method->slug(),
455
-                    ),
456
-                    EE_PAYMENTS_ADMIN_URL
457
-                ),
458
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
459
-                'subsections'     => apply_filters(
460
-                    'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
461
-                    array(
462
-                        'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
463
-                        'currency_support'        => $this->_currency_support($payment_method),
464
-                        'payment_method_settings' => $this->_payment_method_settings($payment_method),
465
-                        'update'                  => $this->_update_payment_method_button($payment_method),
466
-                        'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
467
-                        'fine_print'              => $this->_fine_print(),
468
-                    ),
469
-                    $payment_method
470
-                ),
471
-            )
472
-        );
473
-    }
474
-
475
-
476
-    /**
477
-     * _pci_dss_compliance
478
-     *
479
-     * @access protected
480
-     * @param EE_Payment_Method $payment_method
481
-     * @return EE_Form_Section_Proper
482
-     */
483
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
484
-    {
485
-        if ($payment_method->type_obj()->requires_https()) {
486
-            return new EE_Form_Section_HTML(
487
-                EEH_HTML::table(
488
-                    EEH_HTML::tr(
489
-                        EEH_HTML::th(
490
-                            EEH_HTML::label(
491
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
492
-                            )
493
-                        ) .
494
-                        EEH_HTML::td(
495
-                            EEH_HTML::strong(
496
-                                __(
497
-                                    'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
498
-                                    'event_espresso'
499
-                                )
500
-                            )
501
-                            .
502
-                            EEH_HTML::br()
503
-                            .
504
-                            __('Learn more about ', 'event_espresso')
505
-                            . EEH_HTML::link(
506
-                                'https://www.pcisecuritystandards.org/merchants/index.php',
507
-                                __('PCI DSS compliance', 'event_espresso')
508
-                            )
509
-                        )
510
-                    )
511
-                )
512
-            );
513
-        } else {
514
-            return new EE_Form_Section_HTML('');
515
-        }
516
-    }
517
-
518
-
519
-    /**
520
-     * _currency_support
521
-     *
522
-     * @access protected
523
-     * @param EE_Payment_Method $payment_method
524
-     * @return EE_Form_Section_Proper
525
-     */
526
-    protected function _currency_support(EE_Payment_Method $payment_method)
527
-    {
528
-        if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
529
-            return new EE_Form_Section_HTML(
530
-                EEH_HTML::table(
531
-                    EEH_HTML::tr(
532
-                        EEH_HTML::th(
533
-                            EEH_HTML::label(
534
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
535
-                            )
536
-                        ) .
537
-                        EEH_HTML::td(
538
-                            EEH_HTML::strong(
539
-                                sprintf(
540
-                                    __(
541
-                                        'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
542
-                                        'event_espresso'
543
-                                    ),
544
-                                    EE_Config::instance()->currency->code
545
-                                )
546
-                            )
547
-                        )
548
-                    )
549
-                )
550
-            );
551
-        } else {
552
-            return new EE_Form_Section_HTML('');
553
-        }
554
-    }
555
-
556
-
557
-    /**
558
-     * _update_payment_method_button
559
-     *
560
-     * @access protected
561
-     * @param EE_Payment_Method $payment_method
562
-     * @return EE_Payment_Method_Form
563
-     */
564
-    protected function _payment_method_settings(EE_Payment_Method $payment_method)
565
-    {
566
-        // modify the form so we only have/show fields that will be implemented for this version
567
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
568
-    }
569
-
570
-
571
-    /**
572
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
573
-     *
574
-     * @param EE_Form_Section_Proper $form_section
575
-     * @param string                 $payment_method_name
576
-     * @return EE_Payment_Method_Form
577
-     * @throws EE_Error
578
-     */
579
-    protected function _simplify_form($form_section, $payment_method_name = '')
580
-    {
581
-        if ($form_section instanceof EE_Payment_Method_Form) {
582
-            $form_section->exclude(
583
-                array(
584
-                    'PMD_type', // dont want them changing the type
585
-                    'PMD_slug', // or the slug (probably never)
586
-                    'PMD_wp_user', // or the user's ID
587
-                    'Currency' // or the currency, until the rest of EE supports simultaneous currencies
588
-                )
589
-            );
590
-            return $form_section;
591
-        } else {
592
-            throw new EE_Error(
593
-                sprintf(
594
-                    __(
595
-                        'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
596
-                        'event_espresso'
597
-                    ),
598
-                    $payment_method_name
599
-                )
600
-            );
601
-        }
602
-    }
603
-
604
-
605
-    /**
606
-     * _update_payment_method_button
607
-     *
608
-     * @access protected
609
-     * @param EE_Payment_Method $payment_method
610
-     * @return EE_Form_Section_HTML
611
-     */
612
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method)
613
-    {
614
-        $update_button = new EE_Submit_Input(
615
-            array(
616
-                'name'       => 'submit',
617
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
618
-                'default'    => sprintf(
619
-                    __('Update %s Payment Settings', 'event_espresso'),
620
-                    $payment_method->admin_name()
621
-                ),
622
-                'html_label' => EEH_HTML::nbsp(),
623
-            )
624
-        );
625
-        return new EE_Form_Section_HTML(
626
-            EEH_HTML::table(
627
-                EEH_HTML::no_row(EEH_HTML::br(2)) .
628
-                EEH_HTML::tr(
629
-                    EEH_HTML::th(__('Update Settings', 'event_espresso')) .
630
-                    EEH_HTML::td(
631
-                        $update_button->get_html_for_input()
632
-                    )
633
-                )
634
-            )
635
-        );
636
-    }
637
-
638
-
639
-    /**
640
-     * _deactivate_payment_method_button
641
-     *
642
-     * @access protected
643
-     * @param EE_Payment_Method $payment_method
644
-     * @return EE_Form_Section_Proper
645
-     */
646
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
647
-    {
648
-        $link_text_and_title = sprintf(
649
-            __('Deactivate %1$s Payments?', 'event_espresso'),
650
-            $payment_method->admin_name()
651
-        );
652
-        return new EE_Form_Section_HTML(
653
-            EEH_HTML::table(
654
-                EEH_HTML::tr(
655
-                    EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
656
-                    EEH_HTML::td(
657
-                        EEH_HTML::link(
658
-                            EE_Admin_Page::add_query_args_and_nonce(
659
-                                array(
660
-                                    'action'         => 'deactivate_payment_method',
661
-                                    'payment_method' => $payment_method->slug(),
662
-                                ),
663
-                                EE_PAYMENTS_ADMIN_URL
664
-                            ),
665
-                            $link_text_and_title,
666
-                            $link_text_and_title,
667
-                            'deactivate_' . $payment_method->slug(),
668
-                            'espresso-button button-secondary'
669
-                        )
670
-                    )
671
-                )
672
-            )
673
-        );
674
-    }
675
-
676
-
677
-    /**
678
-     * _activate_payment_method_button
679
-     *
680
-     * @access protected
681
-     * @param EE_Payment_Method $payment_method
682
-     * @return EE_Form_Section_Proper
683
-     */
684
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
685
-    {
686
-        $link_text_and_title = sprintf(
687
-            __('Activate %1$s Payment Method?', 'event_espresso'),
688
-            $payment_method->admin_name()
689
-        );
690
-        return new EE_Form_Section_Proper(
691
-            array(
692
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
693
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
694
-                'action'          => '#',
695
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
696
-                'subsections'     => apply_filters(
697
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
698
-                    array(
699
-                        new EE_Form_Section_HTML(
700
-                            EEH_HTML::table(
701
-                                EEH_HTML::tr(
702
-                                    EEH_HTML::td(
703
-                                        $payment_method->type_obj()->introductory_html(),
704
-                                        '',
705
-                                        '',
706
-                                        '',
707
-                                        'colspan="2"'
708
-                                    )
709
-                                ) .
710
-                                EEH_HTML::tr(
711
-                                    EEH_HTML::th(
712
-                                        EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
713
-                                    ) .
714
-                                    EEH_HTML::td(
715
-                                        EEH_HTML::link(
716
-                                            EE_Admin_Page::add_query_args_and_nonce(
717
-                                                array(
718
-                                                    'action'              => 'activate_payment_method',
719
-                                                    'payment_method_type' => $payment_method->type(),
720
-                                                ),
721
-                                                EE_PAYMENTS_ADMIN_URL
722
-                                            ),
723
-                                            $link_text_and_title,
724
-                                            $link_text_and_title,
725
-                                            'activate_' . $payment_method->slug(),
726
-                                            'espresso-button-green button-primary'
727
-                                        )
728
-                                    )
729
-                                )
730
-                            )
731
-                        ),
732
-                    ),
733
-                    $payment_method
734
-                ),
735
-            )
736
-        );
737
-    }
738
-
739
-
740
-    /**
741
-     * _fine_print
742
-     *
743
-     * @access protected
744
-     * @return EE_Form_Section_HTML
745
-     */
746
-    protected function _fine_print()
747
-    {
748
-        return new EE_Form_Section_HTML(
749
-            EEH_HTML::table(
750
-                EEH_HTML::tr(
751
-                    EEH_HTML::th() .
752
-                    EEH_HTML::td(
753
-                        EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
754
-                    )
755
-                )
756
-            )
757
-        );
758
-    }
759
-
760
-
761
-    /**
762
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
763
-     *
764
-     * @global WP_User $current_user
765
-     */
766
-    protected function _activate_payment_method()
767
-    {
768
-        if (isset($this->_req_data['payment_method_type'])) {
769
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
770
-            // see if one exists
771
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
772
-            $payment_method = EE_Payment_Method_Manager::instance()
773
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
774
-            $this->_redirect_after_action(
775
-                1,
776
-                'Payment Method',
777
-                'activated',
778
-                array('action' => 'default', 'payment_method' => $payment_method->slug())
779
-            );
780
-        } else {
781
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
782
-        }
783
-    }
784
-
785
-
786
-    /**
787
-     * Deactivates the payment method with the specified slug, and redirects.
788
-     */
789
-    protected function _deactivate_payment_method()
790
-    {
791
-        if (isset($this->_req_data['payment_method'])) {
792
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
793
-            // deactivate it
794
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
795
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
796
-            $this->_redirect_after_action(
797
-                $count_updated,
798
-                'Payment Method',
799
-                'deactivated',
800
-                array('action' => 'default', 'payment_method' => $payment_method_slug)
801
-            );
802
-        } else {
803
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
804
-        }
805
-    }
806
-
807
-
808
-    /**
809
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
810
-     * processing because we first need to identify WHICH form was processed and which payment method
811
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
812
-     * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
813
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
814
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
815
-     *
816
-     * @return void
817
-     */
818
-    protected function _update_payment_method()
819
-    {
820
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
821
-            // ok let's find which gateway form to use based on the form input
822
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
823
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
824
-            $correct_pmt_form_to_use = null;
825
-            $payment_method = null;
826
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
827
-                // get the form and simplify it, like what we do when we display it
828
-                $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
829
-                if ($pmt_form->form_data_present_in($this->_req_data)) {
830
-                    $correct_pmt_form_to_use = $pmt_form;
831
-                    break;
832
-                }
833
-            }
834
-            // if we couldn't find the correct payment method type...
835
-            if (! $correct_pmt_form_to_use) {
836
-                EE_Error::add_error(
837
-                    __(
838
-                        "We could not find which payment method type your form submission related to. Please contact support",
839
-                        'event_espresso'
840
-                    ),
841
-                    __FILE__,
842
-                    __FUNCTION__,
843
-                    __LINE__
844
-                );
845
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
846
-            }
847
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
848
-            if ($correct_pmt_form_to_use->is_valid()) {
849
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
850
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
851
-                    throw new EE_Error(
852
-                        sprintf(
853
-                            __(
854
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
855
-                                'event_espresso'
856
-                            ),
857
-                            'payment_method_settings'
858
-                        )
859
-                    );
860
-                }
861
-                $payment_settings_subform->save();
862
-                /** @var $pm EE_Payment_Method */
863
-                $this->_redirect_after_action(
864
-                    true,
865
-                    'Payment Method',
866
-                    'updated',
867
-                    array('action' => 'default', 'payment_method' => $payment_method->slug())
868
-                );
869
-            } else {
870
-                EE_Error::add_error(
871
-                    sprintf(
872
-                        __(
873
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
874
-                            'event_espresso'
875
-                        ),
876
-                        $payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
877
-                            : __('"(unknown)"', 'event_espresso')
878
-                    ),
879
-                    __FILE__,
880
-                    __FUNCTION__,
881
-                    __LINE__
882
-                );
883
-            }
884
-        }
885
-        return;
886
-    }
887
-
888
-
889
-    /**
890
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
891
-     * @throws DomainException
892
-     * @throws EE_Error
893
-     * @throws InvalidArgumentException
894
-     * @throws InvalidDataTypeException
895
-     * @throws InvalidInterfaceException
896
-     */
897
-    protected function _payment_settings()
898
-    {
899
-        $form = $this->getPaymentSettingsForm();
900
-        $this->_set_add_edit_form_tags('update_payment_settings');
901
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
902
-        $this->_template_args['admin_page_content'] =  $form->get_html_and_js();
903
-        $this->display_admin_page_with_sidebar();
904
-    }
905
-
906
-
907
-    /**
908
-     *        _update_payment_settings
909
-     *
910
-     * @access protected
911
-     * @return void
912
-     * @throws EE_Error
913
-     * @throws InvalidArgumentException
914
-     * @throws InvalidDataTypeException
915
-     * @throws InvalidInterfaceException
916
-     */
917
-    protected function _update_payment_settings()
918
-    {
919
-        $form = $this->getPaymentSettingsForm();
920
-        if ($form->was_submitted($this->_req_data)) {
921
-            $form->receive_form_submission($this->_req_data);
922
-            if ($form->is_valid()) {
923
-                /**
924
-                 * @var $reg_config EE_Registration_Config
925
-                 */
926
-                $loader = LoaderFactory::getLoader();
927
-                $reg_config = $loader->getShared('EE_Registration_Config');
928
-                $valid_data = $form->valid_data();
929
-                $reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
930
-                $reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
931
-            }
932
-        }
933
-        EE_Registry::instance()->CFG = apply_filters(
934
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
935
-            EE_Registry::instance()->CFG
936
-        );
937
-
938
-        $cfg =  EE_Registry::instance()->CFG ;
939
-
940
-        $what = __('Payment Settings', 'event_espresso');
941
-        $success = $this->_update_espresso_configuration(
942
-            $what,
943
-            EE_Registry::instance()->CFG,
944
-            __FILE__,
945
-            __FUNCTION__,
946
-            __LINE__
947
-        );
948
-        $this->_redirect_after_action(
949
-            $success,
950
-            $what,
951
-            __('updated', 'event_espresso'),
952
-            array('action' => 'payment_settings')
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * Gets the form used for updating payment settings
959
-     *
960
-     * @return EE_Form_Section_Proper
961
-     * @throws EE_Error
962
-     * @throws InvalidArgumentException
963
-     * @throws InvalidDataTypeException
964
-     * @throws InvalidInterfaceException
965
-     */
966
-    protected function getPaymentSettingsForm()
967
-    {
968
-        /**
969
-         * @var $reg_config EE_Registration_Config
970
-         */
971
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
972
-        return new EE_Form_Section_Proper(
973
-            array(
974
-                'name' => 'payment-settings',
975
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
976
-                'subsections' => array(
977
-                    'show_pending_payment_options' => new EE_Yes_No_Input(
978
-                        array(
979
-                            'html_name' => 'show_pending_payment_options',
980
-                            'default' => $reg_config->show_pending_payment_options,
981
-                            'html_help_text' => esc_html__(
982
-                                "If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
983
-                                'event_espresso'
984
-                            )
985
-                        )
986
-                    ),
987
-                    'gateway_log_lifespan' => new EE_Select_Input(
988
-                        $reg_config->gatewayLogLifespanOptions(),
989
-                        array(
990
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
991
-                            'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
992
-                            'default' => $reg_config->gateway_log_lifespan,
993
-                        )
994
-                    )
995
-                )
996
-            )
997
-        );
998
-    }
999
-
1000
-
1001
-    protected function _payment_log_overview_list_table()
1002
-    {
1003
-        $this->display_admin_list_table_page_with_sidebar();
1004
-    }
1005
-
1006
-
1007
-    protected function _set_list_table_views_payment_log()
1008
-    {
1009
-        $this->_views = array(
1010
-            'all' => array(
1011
-                'slug'  => 'all',
1012
-                'label' => __('View All Logs', 'event_espresso'),
1013
-                'count' => 0,
1014
-            ),
1015
-        );
1016
-    }
1017
-
1018
-
1019
-    /**
1020
-     * @param int  $per_page
1021
-     * @param int  $current_page
1022
-     * @param bool $count
1023
-     * @return array
1024
-     */
1025
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1026
-    {
1027
-        EE_Registry::instance()->load_model('Change_Log');
1028
-        // we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1029
-        $query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1030
-        // check if they've selected a specific payment method
1031
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1032
-            $query_params[0]['OR*pm_or_pay_pm'] = array(
1033
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1034
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1035
-            );
1036
-        }
1037
-        // take into account search
1038
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1039
-            $similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1040
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1041
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1042
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1043
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1044
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1045
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1046
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1047
-            $query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1048
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1049
-            $query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1050
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1051
-        }
1052
-        if (isset($this->_req_data['payment-filter-start-date'])
1053
-            && isset($this->_req_data['payment-filter-end-date'])
1054
-        ) {
1055
-            // add date
1056
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1057
-            $end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1058
-            // make sure our timestamps start and end right at the boundaries for each day
1059
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1060
-            $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1061
-            // convert to timestamps
1062
-            $start_date = strtotime($start_date);
1063
-            $end_date = strtotime($end_date);
1064
-            // makes sure start date is the lowest value and vice versa
1065
-            $start_date = min($start_date, $end_date);
1066
-            $end_date = max($start_date, $end_date);
1067
-            // convert for query
1068
-            $start_date = EEM_Change_Log::instance()
1069
-                                        ->convert_datetime_for_query(
1070
-                                            'LOG_time',
1071
-                                            date('Y-m-d H:i:s', $start_date),
1072
-                                            'Y-m-d H:i:s'
1073
-                                        );
1074
-            $end_date = EEM_Change_Log::instance()
1075
-                                      ->convert_datetime_for_query(
1076
-                                          'LOG_time',
1077
-                                          date('Y-m-d H:i:s', $end_date),
1078
-                                          'Y-m-d H:i:s'
1079
-                                      );
1080
-            $query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1081
-        }
1082
-        if ($count) {
1083
-            return EEM_Change_Log::instance()->count($query_params);
1084
-        }
1085
-        if (isset($this->_req_data['order'])) {
1086
-            $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1087
-                : 'DESC';
1088
-            $query_params['order_by'] = array('LOG_time' => $sort);
1089
-        } else {
1090
-            $query_params['order_by'] = array('LOG_time' => 'DESC');
1091
-        }
1092
-        $offset = ($current_page - 1) * $per_page;
1093
-        if (! isset($this->_req_data['download_results'])) {
1094
-            $query_params['limit'] = array($offset, $per_page);
1095
-        }
1096
-        // now they've requested to instead just download the file instead of viewing it.
1097
-        if (isset($this->_req_data['download_results'])) {
1098
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1099
-            header('Content-Disposition: attachment');
1100
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1101
-            echo "<h1>Payment Logs for " . site_url() . "</h1>";
1102
-            echo "<h3>Query:</h3>";
1103
-            var_dump($query_params);
1104
-            echo "<h3>Results:</h3>";
1105
-            var_dump($wpdb_results);
1106
-            die;
1107
-        }
1108
-        $results = EEM_Change_Log::instance()->get_all($query_params);
1109
-        return $results;
1110
-    }
1111
-
1112
-
1113
-    /**
1114
-     * Used by usort to RE-sort log query results, because we lose the ordering
1115
-     * because we're possibly combining the results from two queries
1116
-     *
1117
-     * @param EE_Change_Log $logA
1118
-     * @param EE_Change_Log $logB
1119
-     * @return int
1120
-     */
1121
-    protected function _sort_logs_again($logA, $logB)
1122
-    {
1123
-        $timeA = $logA->get_raw('LOG_time');
1124
-        $timeB = $logB->get_raw('LOG_time');
1125
-        if ($timeA == $timeB) {
1126
-            return 0;
1127
-        }
1128
-        $comparison = $timeA < $timeB ? -1 : 1;
1129
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1130
-            return $comparison * -1;
1131
-        } else {
1132
-            return $comparison;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    protected function _payment_log_details()
1138
-    {
1139
-        EE_Registry::instance()->load_model('Change_Log');
1140
-        /** @var $payment_log EE_Change_Log */
1141
-        $payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1142
-        $payment_method = null;
1143
-        $transaction = null;
1144
-        if ($payment_log instanceof EE_Change_Log) {
1145
-            if ($payment_log->object() instanceof EE_Payment) {
1146
-                $payment_method = $payment_log->object()->payment_method();
1147
-                $transaction = $payment_log->object()->transaction();
1148
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1149
-                $payment_method = $payment_log->object();
1150
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1151
-                $transaction = $payment_log->object();
1152
-                $payment_method = $transaction->payment_method();
1153
-            }
1154
-        }
1155
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1156
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1157
-            array(
1158
-                'payment_log'    => $payment_log,
1159
-                'payment_method' => $payment_method,
1160
-                'transaction'    => $transaction,
1161
-            ),
1162
-            true
1163
-        );
1164
-        $this->display_admin_page_with_sidebar();
1165
-    }
19
+	/**
20
+	 * Variables used for when we're re-sorting the logs results, in case
21
+	 * we needed to do two queries and we need to resort
22
+	 *
23
+	 * @var string
24
+	 */
25
+	private $_sort_logs_again_direction;
26
+
27
+
28
+	/**
29
+	 * @Constructor
30
+	 * @access public
31
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
+	 * @throws EE_Error
33
+	 * @throws InvalidArgumentException
34
+	 * @throws InvalidDataTypeException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws ReflectionException
37
+	 */
38
+	public function __construct($routing = true)
39
+	{
40
+		parent::__construct($routing);
41
+	}
42
+
43
+
44
+	protected function _init_page_props()
45
+	{
46
+		$this->page_slug = EE_PAYMENTS_PG_SLUG;
47
+		$this->page_label = __('Payment Methods', 'event_espresso');
48
+		$this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
+	}
51
+
52
+
53
+	protected function _ajax_hooks()
54
+	{
55
+		// todo: all hooks for ajax goes here.
56
+	}
57
+
58
+
59
+	protected function _define_page_props()
60
+	{
61
+		$this->_admin_page_title = $this->page_label;
62
+		$this->_labels = array(
63
+			'publishbox' => __('Update Settings', 'event_espresso'),
64
+		);
65
+	}
66
+
67
+
68
+	protected function _set_page_routes()
69
+	{
70
+		/**
71
+		 * note that with payment method capabilities, although we've implemented
72
+		 * capability mapping which will be used for accessing payment methods owned by
73
+		 * other users.  This is not fully implemented yet in the payment method ui.
74
+		 * Currently only the "plural" caps are in active use.
75
+		 * When cap mapping is implemented, some routes will need to use the singular form of
76
+		 * capability method and also include the $id of the payment method for the route.
77
+		 **/
78
+		$this->_page_routes = array(
79
+			'default'                   => array(
80
+				'func'       => '_payment_methods_list',
81
+				'capability' => 'ee_edit_payment_methods',
82
+			),
83
+			'payment_settings'          => array(
84
+				'func'       => '_payment_settings',
85
+				'capability' => 'ee_manage_gateways',
86
+			),
87
+			'activate_payment_method'   => array(
88
+				'func'       => '_activate_payment_method',
89
+				'noheader'   => true,
90
+				'capability' => 'ee_edit_payment_methods',
91
+			),
92
+			'deactivate_payment_method' => array(
93
+				'func'       => '_deactivate_payment_method',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_delete_payment_methods',
96
+			),
97
+			'update_payment_method'     => array(
98
+				'func'               => '_update_payment_method',
99
+				'noheader'           => true,
100
+				'headers_sent_route' => 'default',
101
+				'capability'         => 'ee_edit_payment_methods',
102
+			),
103
+			'update_payment_settings'   => array(
104
+				'func'       => '_update_payment_settings',
105
+				'noheader'   => true,
106
+				'capability' => 'ee_manage_gateways',
107
+			),
108
+			'payment_log'               => array(
109
+				'func'       => '_payment_log_overview_list_table',
110
+				'capability' => 'ee_read_payment_methods',
111
+			),
112
+			'payment_log_details'       => array(
113
+				'func'       => '_payment_log_details',
114
+				'capability' => 'ee_read_payment_methods',
115
+			),
116
+		);
117
+	}
118
+
119
+
120
+	protected function _set_page_config()
121
+	{
122
+		$payment_method_list_config = array(
123
+			'nav'           => array(
124
+				'label' => __('Payment Methods', 'event_espresso'),
125
+				'order' => 10,
126
+			),
127
+			'metaboxes'     => $this->_default_espresso_metaboxes,
128
+			'help_tabs'     => array_merge(
129
+				array(
130
+					'payment_methods_overview_help_tab' => array(
131
+						'title'    => __('Payment Methods Overview', 'event_espresso'),
132
+						'filename' => 'payment_methods_overview',
133
+					),
134
+				),
135
+				$this->_add_payment_method_help_tabs()
136
+			),
137
+			'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
138
+			'require_nonce' => false,
139
+		);
140
+		$this->_page_config = array(
141
+			'default'          => $payment_method_list_config,
142
+			'payment_settings' => array(
143
+				'nav'           => array(
144
+					'label' => __('Settings', 'event_espresso'),
145
+					'order' => 20,
146
+				),
147
+				'help_tabs'     => array(
148
+					'payment_methods_settings_help_tab' => array(
149
+						'title'    => __('Payment Method Settings', 'event_espresso'),
150
+						'filename' => 'payment_methods_settings',
151
+					),
152
+				),
153
+				// 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
154
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
155
+				'require_nonce' => false,
156
+			),
157
+			'payment_log'      => array(
158
+				'nav'           => array(
159
+					'label' => __("Logs", 'event_espresso'),
160
+					'order' => 30,
161
+				),
162
+				'list_table'    => 'Payment_Log_Admin_List_Table',
163
+				'metaboxes'     => $this->_default_espresso_metaboxes,
164
+				'require_nonce' => false,
165
+			),
166
+		);
167
+	}
168
+
169
+
170
+	/**
171
+	 * @return array
172
+	 * @throws DomainException
173
+	 * @throws EE_Error
174
+	 * @throws InvalidArgumentException
175
+	 * @throws InvalidDataTypeException
176
+	 * @throws InvalidInterfaceException
177
+	 * @throws ReflectionException
178
+	 */
179
+	protected function _add_payment_method_help_tabs()
180
+	{
181
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
182
+		$payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
183
+		$all_pmt_help_tabs_config = array();
184
+		foreach ($payment_method_types as $payment_method_type) {
185
+			if (! EE_Registry::instance()->CAP->current_user_can(
186
+				$payment_method_type->cap_name(),
187
+				'specific_payment_method_type_access'
188
+			)
189
+			) {
190
+				continue;
191
+			}
192
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
193
+				$template_args = isset($config['template_args']) ? $config['template_args'] : array();
194
+				$template_args['admin_page_obj'] = $this;
195
+				$all_pmt_help_tabs_config[ $help_tab_name ] = array(
196
+					'title'   => $config['title'],
197
+					'content' => EEH_Template::display_template(
198
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
199
+						$template_args,
200
+						true
201
+					),
202
+				);
203
+			}
204
+		}
205
+		return $all_pmt_help_tabs_config;
206
+	}
207
+
208
+
209
+	// none of the below group are currently used for Gateway Settings
210
+	protected function _add_screen_options()
211
+	{
212
+	}
213
+
214
+
215
+	protected function _add_feature_pointers()
216
+	{
217
+	}
218
+
219
+
220
+	public function admin_init()
221
+	{
222
+	}
223
+
224
+
225
+	public function admin_notices()
226
+	{
227
+	}
228
+
229
+
230
+	public function admin_footer_scripts()
231
+	{
232
+	}
233
+
234
+
235
+	public function load_scripts_styles()
236
+	{
237
+		wp_enqueue_script('ee_admin_js');
238
+		wp_enqueue_script('ee-text-links');
239
+		wp_enqueue_script(
240
+			'espresso_payments',
241
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
242
+			['ee-datepicker'],
243
+			EVENT_ESPRESSO_VERSION,
244
+			true
245
+		);
246
+		wp_enqueue_style('espresso-ui-theme');
247
+	}
248
+
249
+
250
+	public function load_scripts_styles_default()
251
+	{
252
+		// styles
253
+		wp_register_style(
254
+			'espresso_payments',
255
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
256
+			array(),
257
+			EVENT_ESPRESSO_VERSION
258
+		);
259
+		wp_enqueue_style('espresso_payments');
260
+		wp_enqueue_style('ee-text-links');
261
+		// scripts
262
+	}
263
+
264
+
265
+	protected function _payment_methods_list()
266
+	{
267
+		/**
268
+		 * first let's ensure payment methods have been setup. We do this here because when people activate a
269
+		 * payment method for the first time (as an addon), it may not setup its capabilities or get registered
270
+		 * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
271
+		 * safe to do a recheck here.
272
+		 */
273
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
274
+		EEM_Payment_Method::instance()->verify_button_urls();
275
+		// setup tabs, one for each payment method type
276
+		$tabs = array();
277
+		$payment_methods = array();
278
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
279
+			// we don't want to show admin-only PMTs for now
280
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
281
+				continue;
282
+			}
283
+			// check access
284
+			if (! EE_Registry::instance()->CAP->current_user_can(
285
+				$pmt_obj->cap_name(),
286
+				'specific_payment_method_type_access'
287
+			)
288
+			) {
289
+				continue;
290
+			}
291
+			// check for any active pms of that type
292
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
293
+			if (! $payment_method instanceof EE_Payment_Method) {
294
+				$payment_method = EE_Payment_Method::new_instance(
295
+					array(
296
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
297
+						'PMD_type'       => $pmt_obj->system_name(),
298
+						'PMD_name'       => $pmt_obj->pretty_name(),
299
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
300
+					)
301
+				);
302
+			}
303
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
304
+		}
305
+		$payment_methods = apply_filters(
306
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
307
+			$payment_methods
308
+		);
309
+		foreach ($payment_methods as $payment_method) {
310
+			if ($payment_method instanceof EE_Payment_Method) {
311
+				add_meta_box(
312
+					// html id
313
+					'espresso_' . $payment_method->slug() . '_payment_settings',
314
+					// title
315
+					sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
316
+					// callback
317
+					array($this, 'payment_method_settings_meta_box'),
318
+					// post type
319
+					null,
320
+					// context
321
+					'normal',
322
+					// priority
323
+					'default',
324
+					// callback args
325
+					array('payment_method' => $payment_method)
326
+				);
327
+				// setup for tabbed content
328
+				$tabs[ $payment_method->slug() ] = array(
329
+					'label' => $payment_method->admin_name(),
330
+					'class' => $payment_method->active() ? 'gateway-active' : '',
331
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
332
+					'title' => __('Modify this Payment Method', 'event_espresso'),
333
+					'slug'  => $payment_method->slug(),
334
+				);
335
+			}
336
+		}
337
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
338
+			$tabs,
339
+			'payment_method_links',
340
+			'|',
341
+			$this->_get_active_payment_method_slug()
342
+		);
343
+		$this->display_admin_page_with_sidebar();
344
+	}
345
+
346
+
347
+	/**
348
+	 *   _get_active_payment_method_slug
349
+	 *
350
+	 * @return string
351
+	 */
352
+	protected function _get_active_payment_method_slug()
353
+	{
354
+		$payment_method_slug = false;
355
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
356
+		if (isset($this->_req_data['payment_method'])) {
357
+			// if they provided the current payment method, use it
358
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
359
+		}
360
+		$payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
361
+		// if that didn't work or wasn't provided, find another way to select the current pm
362
+		if (! $this->_verify_payment_method($payment_method)) {
363
+			// like, looking for an active one
364
+			$payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
365
+			// test that one as well
366
+			if ($this->_verify_payment_method($payment_method)) {
367
+				$payment_method_slug = $payment_method->slug();
368
+			} else {
369
+				$payment_method_slug = 'paypal_standard';
370
+			}
371
+		}
372
+		return $payment_method_slug;
373
+	}
374
+
375
+
376
+	/**
377
+	 *    payment_method_settings_meta_box
378
+	 *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
379
+	 *    capabilities to access it
380
+	 *
381
+	 * @param EE_Payment_Method $payment_method
382
+	 * @return boolean
383
+	 */
384
+	protected function _verify_payment_method($payment_method)
385
+	{
386
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
387
+			&& EE_Registry::instance()->CAP->current_user_can(
388
+				$payment_method->type_obj()->cap_name(),
389
+				'specific_payment_method_type_access'
390
+			)
391
+		) {
392
+			return true;
393
+		}
394
+		return false;
395
+	}
396
+
397
+
398
+	/**
399
+	 *    payment_method_settings_meta_box
400
+	 *
401
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
402
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
403
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
404
+	 * @return string
405
+	 * @throws EE_Error
406
+	 */
407
+	public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
408
+	{
409
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
410
+			? $metabox['args']['payment_method'] : null;
411
+		if (! $payment_method instanceof EE_Payment_Method) {
412
+			throw new EE_Error(
413
+				sprintf(
414
+					__(
415
+						'Payment method metabox setup incorrectly. No Payment method object was supplied',
416
+						'event_espresso'
417
+					)
418
+				)
419
+			);
420
+		}
421
+		$payment_method_scopes = $payment_method->active();
422
+		// if the payment method really exists show its form, otherwise the activation template
423
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
424
+			$form = $this->_generate_payment_method_settings_form($payment_method);
425
+			if ($form->form_data_present_in($this->_req_data)) {
426
+				$form->receive_form_submission($this->_req_data);
427
+			}
428
+			echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
429
+		} else {
430
+			echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
431
+		}
432
+	}
433
+
434
+
435
+	/**
436
+	 * Gets the form for all the settings related to this payment method type
437
+	 *
438
+	 * @access protected
439
+	 * @param EE_Payment_Method $payment_method
440
+	 * @return EE_Form_Section_Proper
441
+	 */
442
+	protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
443
+	{
444
+		if (! $payment_method instanceof EE_Payment_Method) {
445
+			return new EE_Form_Section_Proper();
446
+		}
447
+		return new EE_Form_Section_Proper(
448
+			array(
449
+				'name'            => $payment_method->slug() . '_settings_form',
450
+				'html_id'         => $payment_method->slug() . '_settings_form',
451
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
452
+					array(
453
+						'action'         => 'update_payment_method',
454
+						'payment_method' => $payment_method->slug(),
455
+					),
456
+					EE_PAYMENTS_ADMIN_URL
457
+				),
458
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
459
+				'subsections'     => apply_filters(
460
+					'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
461
+					array(
462
+						'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
463
+						'currency_support'        => $this->_currency_support($payment_method),
464
+						'payment_method_settings' => $this->_payment_method_settings($payment_method),
465
+						'update'                  => $this->_update_payment_method_button($payment_method),
466
+						'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
467
+						'fine_print'              => $this->_fine_print(),
468
+					),
469
+					$payment_method
470
+				),
471
+			)
472
+		);
473
+	}
474
+
475
+
476
+	/**
477
+	 * _pci_dss_compliance
478
+	 *
479
+	 * @access protected
480
+	 * @param EE_Payment_Method $payment_method
481
+	 * @return EE_Form_Section_Proper
482
+	 */
483
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
484
+	{
485
+		if ($payment_method->type_obj()->requires_https()) {
486
+			return new EE_Form_Section_HTML(
487
+				EEH_HTML::table(
488
+					EEH_HTML::tr(
489
+						EEH_HTML::th(
490
+							EEH_HTML::label(
491
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
492
+							)
493
+						) .
494
+						EEH_HTML::td(
495
+							EEH_HTML::strong(
496
+								__(
497
+									'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
498
+									'event_espresso'
499
+								)
500
+							)
501
+							.
502
+							EEH_HTML::br()
503
+							.
504
+							__('Learn more about ', 'event_espresso')
505
+							. EEH_HTML::link(
506
+								'https://www.pcisecuritystandards.org/merchants/index.php',
507
+								__('PCI DSS compliance', 'event_espresso')
508
+							)
509
+						)
510
+					)
511
+				)
512
+			);
513
+		} else {
514
+			return new EE_Form_Section_HTML('');
515
+		}
516
+	}
517
+
518
+
519
+	/**
520
+	 * _currency_support
521
+	 *
522
+	 * @access protected
523
+	 * @param EE_Payment_Method $payment_method
524
+	 * @return EE_Form_Section_Proper
525
+	 */
526
+	protected function _currency_support(EE_Payment_Method $payment_method)
527
+	{
528
+		if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
529
+			return new EE_Form_Section_HTML(
530
+				EEH_HTML::table(
531
+					EEH_HTML::tr(
532
+						EEH_HTML::th(
533
+							EEH_HTML::label(
534
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
535
+							)
536
+						) .
537
+						EEH_HTML::td(
538
+							EEH_HTML::strong(
539
+								sprintf(
540
+									__(
541
+										'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
542
+										'event_espresso'
543
+									),
544
+									EE_Config::instance()->currency->code
545
+								)
546
+							)
547
+						)
548
+					)
549
+				)
550
+			);
551
+		} else {
552
+			return new EE_Form_Section_HTML('');
553
+		}
554
+	}
555
+
556
+
557
+	/**
558
+	 * _update_payment_method_button
559
+	 *
560
+	 * @access protected
561
+	 * @param EE_Payment_Method $payment_method
562
+	 * @return EE_Payment_Method_Form
563
+	 */
564
+	protected function _payment_method_settings(EE_Payment_Method $payment_method)
565
+	{
566
+		// modify the form so we only have/show fields that will be implemented for this version
567
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
568
+	}
569
+
570
+
571
+	/**
572
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
573
+	 *
574
+	 * @param EE_Form_Section_Proper $form_section
575
+	 * @param string                 $payment_method_name
576
+	 * @return EE_Payment_Method_Form
577
+	 * @throws EE_Error
578
+	 */
579
+	protected function _simplify_form($form_section, $payment_method_name = '')
580
+	{
581
+		if ($form_section instanceof EE_Payment_Method_Form) {
582
+			$form_section->exclude(
583
+				array(
584
+					'PMD_type', // dont want them changing the type
585
+					'PMD_slug', // or the slug (probably never)
586
+					'PMD_wp_user', // or the user's ID
587
+					'Currency' // or the currency, until the rest of EE supports simultaneous currencies
588
+				)
589
+			);
590
+			return $form_section;
591
+		} else {
592
+			throw new EE_Error(
593
+				sprintf(
594
+					__(
595
+						'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
596
+						'event_espresso'
597
+					),
598
+					$payment_method_name
599
+				)
600
+			);
601
+		}
602
+	}
603
+
604
+
605
+	/**
606
+	 * _update_payment_method_button
607
+	 *
608
+	 * @access protected
609
+	 * @param EE_Payment_Method $payment_method
610
+	 * @return EE_Form_Section_HTML
611
+	 */
612
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method)
613
+	{
614
+		$update_button = new EE_Submit_Input(
615
+			array(
616
+				'name'       => 'submit',
617
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
618
+				'default'    => sprintf(
619
+					__('Update %s Payment Settings', 'event_espresso'),
620
+					$payment_method->admin_name()
621
+				),
622
+				'html_label' => EEH_HTML::nbsp(),
623
+			)
624
+		);
625
+		return new EE_Form_Section_HTML(
626
+			EEH_HTML::table(
627
+				EEH_HTML::no_row(EEH_HTML::br(2)) .
628
+				EEH_HTML::tr(
629
+					EEH_HTML::th(__('Update Settings', 'event_espresso')) .
630
+					EEH_HTML::td(
631
+						$update_button->get_html_for_input()
632
+					)
633
+				)
634
+			)
635
+		);
636
+	}
637
+
638
+
639
+	/**
640
+	 * _deactivate_payment_method_button
641
+	 *
642
+	 * @access protected
643
+	 * @param EE_Payment_Method $payment_method
644
+	 * @return EE_Form_Section_Proper
645
+	 */
646
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
647
+	{
648
+		$link_text_and_title = sprintf(
649
+			__('Deactivate %1$s Payments?', 'event_espresso'),
650
+			$payment_method->admin_name()
651
+		);
652
+		return new EE_Form_Section_HTML(
653
+			EEH_HTML::table(
654
+				EEH_HTML::tr(
655
+					EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
656
+					EEH_HTML::td(
657
+						EEH_HTML::link(
658
+							EE_Admin_Page::add_query_args_and_nonce(
659
+								array(
660
+									'action'         => 'deactivate_payment_method',
661
+									'payment_method' => $payment_method->slug(),
662
+								),
663
+								EE_PAYMENTS_ADMIN_URL
664
+							),
665
+							$link_text_and_title,
666
+							$link_text_and_title,
667
+							'deactivate_' . $payment_method->slug(),
668
+							'espresso-button button-secondary'
669
+						)
670
+					)
671
+				)
672
+			)
673
+		);
674
+	}
675
+
676
+
677
+	/**
678
+	 * _activate_payment_method_button
679
+	 *
680
+	 * @access protected
681
+	 * @param EE_Payment_Method $payment_method
682
+	 * @return EE_Form_Section_Proper
683
+	 */
684
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
685
+	{
686
+		$link_text_and_title = sprintf(
687
+			__('Activate %1$s Payment Method?', 'event_espresso'),
688
+			$payment_method->admin_name()
689
+		);
690
+		return new EE_Form_Section_Proper(
691
+			array(
692
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
693
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
694
+				'action'          => '#',
695
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
696
+				'subsections'     => apply_filters(
697
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
698
+					array(
699
+						new EE_Form_Section_HTML(
700
+							EEH_HTML::table(
701
+								EEH_HTML::tr(
702
+									EEH_HTML::td(
703
+										$payment_method->type_obj()->introductory_html(),
704
+										'',
705
+										'',
706
+										'',
707
+										'colspan="2"'
708
+									)
709
+								) .
710
+								EEH_HTML::tr(
711
+									EEH_HTML::th(
712
+										EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
713
+									) .
714
+									EEH_HTML::td(
715
+										EEH_HTML::link(
716
+											EE_Admin_Page::add_query_args_and_nonce(
717
+												array(
718
+													'action'              => 'activate_payment_method',
719
+													'payment_method_type' => $payment_method->type(),
720
+												),
721
+												EE_PAYMENTS_ADMIN_URL
722
+											),
723
+											$link_text_and_title,
724
+											$link_text_and_title,
725
+											'activate_' . $payment_method->slug(),
726
+											'espresso-button-green button-primary'
727
+										)
728
+									)
729
+								)
730
+							)
731
+						),
732
+					),
733
+					$payment_method
734
+				),
735
+			)
736
+		);
737
+	}
738
+
739
+
740
+	/**
741
+	 * _fine_print
742
+	 *
743
+	 * @access protected
744
+	 * @return EE_Form_Section_HTML
745
+	 */
746
+	protected function _fine_print()
747
+	{
748
+		return new EE_Form_Section_HTML(
749
+			EEH_HTML::table(
750
+				EEH_HTML::tr(
751
+					EEH_HTML::th() .
752
+					EEH_HTML::td(
753
+						EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
754
+					)
755
+				)
756
+			)
757
+		);
758
+	}
759
+
760
+
761
+	/**
762
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
763
+	 *
764
+	 * @global WP_User $current_user
765
+	 */
766
+	protected function _activate_payment_method()
767
+	{
768
+		if (isset($this->_req_data['payment_method_type'])) {
769
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
770
+			// see if one exists
771
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
772
+			$payment_method = EE_Payment_Method_Manager::instance()
773
+													   ->activate_a_payment_method_of_type($payment_method_type);
774
+			$this->_redirect_after_action(
775
+				1,
776
+				'Payment Method',
777
+				'activated',
778
+				array('action' => 'default', 'payment_method' => $payment_method->slug())
779
+			);
780
+		} else {
781
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
782
+		}
783
+	}
784
+
785
+
786
+	/**
787
+	 * Deactivates the payment method with the specified slug, and redirects.
788
+	 */
789
+	protected function _deactivate_payment_method()
790
+	{
791
+		if (isset($this->_req_data['payment_method'])) {
792
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
793
+			// deactivate it
794
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
795
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
796
+			$this->_redirect_after_action(
797
+				$count_updated,
798
+				'Payment Method',
799
+				'deactivated',
800
+				array('action' => 'default', 'payment_method' => $payment_method_slug)
801
+			);
802
+		} else {
803
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
804
+		}
805
+	}
806
+
807
+
808
+	/**
809
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
810
+	 * processing because we first need to identify WHICH form was processed and which payment method
811
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
812
+	 * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
813
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
814
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
815
+	 *
816
+	 * @return void
817
+	 */
818
+	protected function _update_payment_method()
819
+	{
820
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
821
+			// ok let's find which gateway form to use based on the form input
822
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
823
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
824
+			$correct_pmt_form_to_use = null;
825
+			$payment_method = null;
826
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
827
+				// get the form and simplify it, like what we do when we display it
828
+				$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
829
+				if ($pmt_form->form_data_present_in($this->_req_data)) {
830
+					$correct_pmt_form_to_use = $pmt_form;
831
+					break;
832
+				}
833
+			}
834
+			// if we couldn't find the correct payment method type...
835
+			if (! $correct_pmt_form_to_use) {
836
+				EE_Error::add_error(
837
+					__(
838
+						"We could not find which payment method type your form submission related to. Please contact support",
839
+						'event_espresso'
840
+					),
841
+					__FILE__,
842
+					__FUNCTION__,
843
+					__LINE__
844
+				);
845
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
846
+			}
847
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
848
+			if ($correct_pmt_form_to_use->is_valid()) {
849
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
850
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
851
+					throw new EE_Error(
852
+						sprintf(
853
+							__(
854
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
855
+								'event_espresso'
856
+							),
857
+							'payment_method_settings'
858
+						)
859
+					);
860
+				}
861
+				$payment_settings_subform->save();
862
+				/** @var $pm EE_Payment_Method */
863
+				$this->_redirect_after_action(
864
+					true,
865
+					'Payment Method',
866
+					'updated',
867
+					array('action' => 'default', 'payment_method' => $payment_method->slug())
868
+				);
869
+			} else {
870
+				EE_Error::add_error(
871
+					sprintf(
872
+						__(
873
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
874
+							'event_espresso'
875
+						),
876
+						$payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
877
+							: __('"(unknown)"', 'event_espresso')
878
+					),
879
+					__FILE__,
880
+					__FUNCTION__,
881
+					__LINE__
882
+				);
883
+			}
884
+		}
885
+		return;
886
+	}
887
+
888
+
889
+	/**
890
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
891
+	 * @throws DomainException
892
+	 * @throws EE_Error
893
+	 * @throws InvalidArgumentException
894
+	 * @throws InvalidDataTypeException
895
+	 * @throws InvalidInterfaceException
896
+	 */
897
+	protected function _payment_settings()
898
+	{
899
+		$form = $this->getPaymentSettingsForm();
900
+		$this->_set_add_edit_form_tags('update_payment_settings');
901
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
902
+		$this->_template_args['admin_page_content'] =  $form->get_html_and_js();
903
+		$this->display_admin_page_with_sidebar();
904
+	}
905
+
906
+
907
+	/**
908
+	 *        _update_payment_settings
909
+	 *
910
+	 * @access protected
911
+	 * @return void
912
+	 * @throws EE_Error
913
+	 * @throws InvalidArgumentException
914
+	 * @throws InvalidDataTypeException
915
+	 * @throws InvalidInterfaceException
916
+	 */
917
+	protected function _update_payment_settings()
918
+	{
919
+		$form = $this->getPaymentSettingsForm();
920
+		if ($form->was_submitted($this->_req_data)) {
921
+			$form->receive_form_submission($this->_req_data);
922
+			if ($form->is_valid()) {
923
+				/**
924
+				 * @var $reg_config EE_Registration_Config
925
+				 */
926
+				$loader = LoaderFactory::getLoader();
927
+				$reg_config = $loader->getShared('EE_Registration_Config');
928
+				$valid_data = $form->valid_data();
929
+				$reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
930
+				$reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
931
+			}
932
+		}
933
+		EE_Registry::instance()->CFG = apply_filters(
934
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
935
+			EE_Registry::instance()->CFG
936
+		);
937
+
938
+		$cfg =  EE_Registry::instance()->CFG ;
939
+
940
+		$what = __('Payment Settings', 'event_espresso');
941
+		$success = $this->_update_espresso_configuration(
942
+			$what,
943
+			EE_Registry::instance()->CFG,
944
+			__FILE__,
945
+			__FUNCTION__,
946
+			__LINE__
947
+		);
948
+		$this->_redirect_after_action(
949
+			$success,
950
+			$what,
951
+			__('updated', 'event_espresso'),
952
+			array('action' => 'payment_settings')
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * Gets the form used for updating payment settings
959
+	 *
960
+	 * @return EE_Form_Section_Proper
961
+	 * @throws EE_Error
962
+	 * @throws InvalidArgumentException
963
+	 * @throws InvalidDataTypeException
964
+	 * @throws InvalidInterfaceException
965
+	 */
966
+	protected function getPaymentSettingsForm()
967
+	{
968
+		/**
969
+		 * @var $reg_config EE_Registration_Config
970
+		 */
971
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
972
+		return new EE_Form_Section_Proper(
973
+			array(
974
+				'name' => 'payment-settings',
975
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
976
+				'subsections' => array(
977
+					'show_pending_payment_options' => new EE_Yes_No_Input(
978
+						array(
979
+							'html_name' => 'show_pending_payment_options',
980
+							'default' => $reg_config->show_pending_payment_options,
981
+							'html_help_text' => esc_html__(
982
+								"If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
983
+								'event_espresso'
984
+							)
985
+						)
986
+					),
987
+					'gateway_log_lifespan' => new EE_Select_Input(
988
+						$reg_config->gatewayLogLifespanOptions(),
989
+						array(
990
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
991
+							'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
992
+							'default' => $reg_config->gateway_log_lifespan,
993
+						)
994
+					)
995
+				)
996
+			)
997
+		);
998
+	}
999
+
1000
+
1001
+	protected function _payment_log_overview_list_table()
1002
+	{
1003
+		$this->display_admin_list_table_page_with_sidebar();
1004
+	}
1005
+
1006
+
1007
+	protected function _set_list_table_views_payment_log()
1008
+	{
1009
+		$this->_views = array(
1010
+			'all' => array(
1011
+				'slug'  => 'all',
1012
+				'label' => __('View All Logs', 'event_espresso'),
1013
+				'count' => 0,
1014
+			),
1015
+		);
1016
+	}
1017
+
1018
+
1019
+	/**
1020
+	 * @param int  $per_page
1021
+	 * @param int  $current_page
1022
+	 * @param bool $count
1023
+	 * @return array
1024
+	 */
1025
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1026
+	{
1027
+		EE_Registry::instance()->load_model('Change_Log');
1028
+		// we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1029
+		$query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1030
+		// check if they've selected a specific payment method
1031
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1032
+			$query_params[0]['OR*pm_or_pay_pm'] = array(
1033
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1034
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1035
+			);
1036
+		}
1037
+		// take into account search
1038
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1039
+			$similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1040
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1041
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1042
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1043
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1044
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1045
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1046
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1047
+			$query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1048
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1049
+			$query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1050
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1051
+		}
1052
+		if (isset($this->_req_data['payment-filter-start-date'])
1053
+			&& isset($this->_req_data['payment-filter-end-date'])
1054
+		) {
1055
+			// add date
1056
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1057
+			$end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1058
+			// make sure our timestamps start and end right at the boundaries for each day
1059
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1060
+			$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1061
+			// convert to timestamps
1062
+			$start_date = strtotime($start_date);
1063
+			$end_date = strtotime($end_date);
1064
+			// makes sure start date is the lowest value and vice versa
1065
+			$start_date = min($start_date, $end_date);
1066
+			$end_date = max($start_date, $end_date);
1067
+			// convert for query
1068
+			$start_date = EEM_Change_Log::instance()
1069
+										->convert_datetime_for_query(
1070
+											'LOG_time',
1071
+											date('Y-m-d H:i:s', $start_date),
1072
+											'Y-m-d H:i:s'
1073
+										);
1074
+			$end_date = EEM_Change_Log::instance()
1075
+									  ->convert_datetime_for_query(
1076
+										  'LOG_time',
1077
+										  date('Y-m-d H:i:s', $end_date),
1078
+										  'Y-m-d H:i:s'
1079
+									  );
1080
+			$query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1081
+		}
1082
+		if ($count) {
1083
+			return EEM_Change_Log::instance()->count($query_params);
1084
+		}
1085
+		if (isset($this->_req_data['order'])) {
1086
+			$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1087
+				: 'DESC';
1088
+			$query_params['order_by'] = array('LOG_time' => $sort);
1089
+		} else {
1090
+			$query_params['order_by'] = array('LOG_time' => 'DESC');
1091
+		}
1092
+		$offset = ($current_page - 1) * $per_page;
1093
+		if (! isset($this->_req_data['download_results'])) {
1094
+			$query_params['limit'] = array($offset, $per_page);
1095
+		}
1096
+		// now they've requested to instead just download the file instead of viewing it.
1097
+		if (isset($this->_req_data['download_results'])) {
1098
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1099
+			header('Content-Disposition: attachment');
1100
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1101
+			echo "<h1>Payment Logs for " . site_url() . "</h1>";
1102
+			echo "<h3>Query:</h3>";
1103
+			var_dump($query_params);
1104
+			echo "<h3>Results:</h3>";
1105
+			var_dump($wpdb_results);
1106
+			die;
1107
+		}
1108
+		$results = EEM_Change_Log::instance()->get_all($query_params);
1109
+		return $results;
1110
+	}
1111
+
1112
+
1113
+	/**
1114
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1115
+	 * because we're possibly combining the results from two queries
1116
+	 *
1117
+	 * @param EE_Change_Log $logA
1118
+	 * @param EE_Change_Log $logB
1119
+	 * @return int
1120
+	 */
1121
+	protected function _sort_logs_again($logA, $logB)
1122
+	{
1123
+		$timeA = $logA->get_raw('LOG_time');
1124
+		$timeB = $logB->get_raw('LOG_time');
1125
+		if ($timeA == $timeB) {
1126
+			return 0;
1127
+		}
1128
+		$comparison = $timeA < $timeB ? -1 : 1;
1129
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1130
+			return $comparison * -1;
1131
+		} else {
1132
+			return $comparison;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	protected function _payment_log_details()
1138
+	{
1139
+		EE_Registry::instance()->load_model('Change_Log');
1140
+		/** @var $payment_log EE_Change_Log */
1141
+		$payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1142
+		$payment_method = null;
1143
+		$transaction = null;
1144
+		if ($payment_log instanceof EE_Change_Log) {
1145
+			if ($payment_log->object() instanceof EE_Payment) {
1146
+				$payment_method = $payment_log->object()->payment_method();
1147
+				$transaction = $payment_log->object()->transaction();
1148
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1149
+				$payment_method = $payment_log->object();
1150
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1151
+				$transaction = $payment_log->object();
1152
+				$payment_method = $transaction->payment_method();
1153
+			}
1154
+		}
1155
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1156
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1157
+			array(
1158
+				'payment_log'    => $payment_log,
1159
+				'payment_method' => $payment_method,
1160
+				'transaction'    => $transaction,
1161
+			),
1162
+			true
1163
+		);
1164
+		$this->display_admin_page_with_sidebar();
1165
+	}
1166 1166
 }
Please login to merge, or discard this patch.
Spacing   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
         $payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
183 183
         $all_pmt_help_tabs_config = array();
184 184
         foreach ($payment_method_types as $payment_method_type) {
185
-            if (! EE_Registry::instance()->CAP->current_user_can(
185
+            if ( ! EE_Registry::instance()->CAP->current_user_can(
186 186
                 $payment_method_type->cap_name(),
187 187
                 'specific_payment_method_type_access'
188 188
             )
@@ -192,10 +192,10 @@  discard block
 block discarded – undo
192 192
             foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
193 193
                 $template_args = isset($config['template_args']) ? $config['template_args'] : array();
194 194
                 $template_args['admin_page_obj'] = $this;
195
-                $all_pmt_help_tabs_config[ $help_tab_name ] = array(
195
+                $all_pmt_help_tabs_config[$help_tab_name] = array(
196 196
                     'title'   => $config['title'],
197 197
                     'content' => EEH_Template::display_template(
198
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
198
+                        $payment_method_type->file_folder().'help_tabs/'.$config['filename'].'.help_tab.php',
199 199
                         $template_args,
200 200
                         true
201 201
                     ),
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
         wp_enqueue_script('ee-text-links');
239 239
         wp_enqueue_script(
240 240
             'espresso_payments',
241
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
241
+            EE_PAYMENTS_ASSETS_URL.'espresso_payments_admin.js',
242 242
             ['ee-datepicker'],
243 243
             EVENT_ESPRESSO_VERSION,
244 244
             true
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
         // styles
253 253
         wp_register_style(
254 254
             'espresso_payments',
255
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
255
+            EE_PAYMENTS_ASSETS_URL.'ee-payments.css',
256 256
             array(),
257 257
             EVENT_ESPRESSO_VERSION
258 258
         );
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
                 continue;
282 282
             }
283 283
             // check access
284
-            if (! EE_Registry::instance()->CAP->current_user_can(
284
+            if ( ! EE_Registry::instance()->CAP->current_user_can(
285 285
                 $pmt_obj->cap_name(),
286 286
                 'specific_payment_method_type_access'
287 287
             )
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
             }
291 291
             // check for any active pms of that type
292 292
             $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
293
-            if (! $payment_method instanceof EE_Payment_Method) {
293
+            if ( ! $payment_method instanceof EE_Payment_Method) {
294 294
                 $payment_method = EE_Payment_Method::new_instance(
295 295
                     array(
296 296
                         'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
                     )
301 301
                 );
302 302
             }
303
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
303
+            $payment_methods[$payment_method->slug()] = $payment_method;
304 304
         }
305 305
         $payment_methods = apply_filters(
306 306
             'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
             if ($payment_method instanceof EE_Payment_Method) {
311 311
                 add_meta_box(
312 312
                     // html id
313
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
313
+                    'espresso_'.$payment_method->slug().'_payment_settings',
314 314
                     // title
315 315
                     sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
316 316
                     // callback
@@ -325,10 +325,10 @@  discard block
 block discarded – undo
325 325
                     array('payment_method' => $payment_method)
326 326
                 );
327 327
                 // setup for tabbed content
328
-                $tabs[ $payment_method->slug() ] = array(
328
+                $tabs[$payment_method->slug()] = array(
329 329
                     'label' => $payment_method->admin_name(),
330 330
                     'class' => $payment_method->active() ? 'gateway-active' : '',
331
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
331
+                    'href'  => 'espresso_'.$payment_method->slug().'_payment_settings',
332 332
                     'title' => __('Modify this Payment Method', 'event_espresso'),
333 333
                     'slug'  => $payment_method->slug(),
334 334
                 );
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
         }
360 360
         $payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
361 361
         // if that didn't work or wasn't provided, find another way to select the current pm
362
-        if (! $this->_verify_payment_method($payment_method)) {
362
+        if ( ! $this->_verify_payment_method($payment_method)) {
363 363
             // like, looking for an active one
364 364
             $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
365 365
             // test that one as well
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
     {
409 409
         $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
410 410
             ? $metabox['args']['payment_method'] : null;
411
-        if (! $payment_method instanceof EE_Payment_Method) {
411
+        if ( ! $payment_method instanceof EE_Payment_Method) {
412 412
             throw new EE_Error(
413 413
                 sprintf(
414 414
                     __(
@@ -425,7 +425,7 @@  discard block
 block discarded – undo
425 425
             if ($form->form_data_present_in($this->_req_data)) {
426 426
                 $form->receive_form_submission($this->_req_data);
427 427
             }
428
-            echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
428
+            echo $form->form_open().$form->get_html_and_js().$form->form_close();
429 429
         } else {
430 430
             echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
431 431
         }
@@ -441,13 +441,13 @@  discard block
 block discarded – undo
441 441
      */
442 442
     protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
443 443
     {
444
-        if (! $payment_method instanceof EE_Payment_Method) {
444
+        if ( ! $payment_method instanceof EE_Payment_Method) {
445 445
             return new EE_Form_Section_Proper();
446 446
         }
447 447
         return new EE_Form_Section_Proper(
448 448
             array(
449
-                'name'            => $payment_method->slug() . '_settings_form',
450
-                'html_id'         => $payment_method->slug() . '_settings_form',
449
+                'name'            => $payment_method->slug().'_settings_form',
450
+                'html_id'         => $payment_method->slug().'_settings_form',
451 451
                 'action'          => EE_Admin_Page::add_query_args_and_nonce(
452 452
                     array(
453 453
                         'action'         => 'update_payment_method',
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
                             EEH_HTML::label(
491 491
                                 EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
492 492
                             )
493
-                        ) .
493
+                        ).
494 494
                         EEH_HTML::td(
495 495
                             EEH_HTML::strong(
496 496
                                 __(
@@ -525,7 +525,7 @@  discard block
 block discarded – undo
525 525
      */
526 526
     protected function _currency_support(EE_Payment_Method $payment_method)
527 527
     {
528
-        if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
528
+        if ( ! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
529 529
             return new EE_Form_Section_HTML(
530 530
                 EEH_HTML::table(
531 531
                     EEH_HTML::tr(
@@ -533,7 +533,7 @@  discard block
 block discarded – undo
533 533
                             EEH_HTML::label(
534 534
                                 EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
535 535
                             )
536
-                        ) .
536
+                        ).
537 537
                         EEH_HTML::td(
538 538
                             EEH_HTML::strong(
539 539
                                 sprintf(
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
         $update_button = new EE_Submit_Input(
615 615
             array(
616 616
                 'name'       => 'submit',
617
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
617
+                'html_id'    => 'save_'.$payment_method->slug().'_settings',
618 618
                 'default'    => sprintf(
619 619
                     __('Update %s Payment Settings', 'event_espresso'),
620 620
                     $payment_method->admin_name()
@@ -624,9 +624,9 @@  discard block
 block discarded – undo
624 624
         );
625 625
         return new EE_Form_Section_HTML(
626 626
             EEH_HTML::table(
627
-                EEH_HTML::no_row(EEH_HTML::br(2)) .
627
+                EEH_HTML::no_row(EEH_HTML::br(2)).
628 628
                 EEH_HTML::tr(
629
-                    EEH_HTML::th(__('Update Settings', 'event_espresso')) .
629
+                    EEH_HTML::th(__('Update Settings', 'event_espresso')).
630 630
                     EEH_HTML::td(
631 631
                         $update_button->get_html_for_input()
632 632
                     )
@@ -652,7 +652,7 @@  discard block
 block discarded – undo
652 652
         return new EE_Form_Section_HTML(
653 653
             EEH_HTML::table(
654 654
                 EEH_HTML::tr(
655
-                    EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
655
+                    EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')).
656 656
                     EEH_HTML::td(
657 657
                         EEH_HTML::link(
658 658
                             EE_Admin_Page::add_query_args_and_nonce(
@@ -664,7 +664,7 @@  discard block
 block discarded – undo
664 664
                             ),
665 665
                             $link_text_and_title,
666 666
                             $link_text_and_title,
667
-                            'deactivate_' . $payment_method->slug(),
667
+                            'deactivate_'.$payment_method->slug(),
668 668
                             'espresso-button button-secondary'
669 669
                         )
670 670
                     )
@@ -689,8 +689,8 @@  discard block
 block discarded – undo
689 689
         );
690 690
         return new EE_Form_Section_Proper(
691 691
             array(
692
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
693
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
692
+                'name'            => 'activate_'.$payment_method->slug().'_settings_form',
693
+                'html_id'         => 'activate_'.$payment_method->slug().'_settings_form',
694 694
                 'action'          => '#',
695 695
                 'layout_strategy' => new EE_Admin_Two_Column_Layout(),
696 696
                 'subsections'     => apply_filters(
@@ -706,11 +706,11 @@  discard block
 block discarded – undo
706 706
                                         '',
707 707
                                         'colspan="2"'
708 708
                                     )
709
-                                ) .
709
+                                ).
710 710
                                 EEH_HTML::tr(
711 711
                                     EEH_HTML::th(
712 712
                                         EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
713
-                                    ) .
713
+                                    ).
714 714
                                     EEH_HTML::td(
715 715
                                         EEH_HTML::link(
716 716
                                             EE_Admin_Page::add_query_args_and_nonce(
@@ -722,7 +722,7 @@  discard block
 block discarded – undo
722 722
                                             ),
723 723
                                             $link_text_and_title,
724 724
                                             $link_text_and_title,
725
-                                            'activate_' . $payment_method->slug(),
725
+                                            'activate_'.$payment_method->slug(),
726 726
                                             'espresso-button-green button-primary'
727 727
                                         )
728 728
                                     )
@@ -748,7 +748,7 @@  discard block
 block discarded – undo
748 748
         return new EE_Form_Section_HTML(
749 749
             EEH_HTML::table(
750 750
                 EEH_HTML::tr(
751
-                    EEH_HTML::th() .
751
+                    EEH_HTML::th().
752 752
                     EEH_HTML::td(
753 753
                         EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
754 754
                     )
@@ -832,7 +832,7 @@  discard block
 block discarded – undo
832 832
                 }
833 833
             }
834 834
             // if we couldn't find the correct payment method type...
835
-            if (! $correct_pmt_form_to_use) {
835
+            if ( ! $correct_pmt_form_to_use) {
836 836
                 EE_Error::add_error(
837 837
                     __(
838 838
                         "We could not find which payment method type your form submission related to. Please contact support",
@@ -847,7 +847,7 @@  discard block
 block discarded – undo
847 847
             $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
848 848
             if ($correct_pmt_form_to_use->is_valid()) {
849 849
                 $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
850
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
850
+                if ( ! $payment_settings_subform instanceof EE_Payment_Method_Form) {
851 851
                     throw new EE_Error(
852 852
                         sprintf(
853 853
                             __(
@@ -899,7 +899,7 @@  discard block
 block discarded – undo
899 899
         $form = $this->getPaymentSettingsForm();
900 900
         $this->_set_add_edit_form_tags('update_payment_settings');
901 901
         $this->_set_publish_post_box_vars(null, false, false, null, false);
902
-        $this->_template_args['admin_page_content'] =  $form->get_html_and_js();
902
+        $this->_template_args['admin_page_content'] = $form->get_html_and_js();
903 903
         $this->display_admin_page_with_sidebar();
904 904
     }
905 905
 
@@ -935,7 +935,7 @@  discard block
 block discarded – undo
935 935
             EE_Registry::instance()->CFG
936 936
         );
937 937
 
938
-        $cfg =  EE_Registry::instance()->CFG ;
938
+        $cfg = EE_Registry::instance()->CFG;
939 939
 
940 940
         $what = __('Payment Settings', 'event_espresso');
941 941
         $success = $this->_update_espresso_configuration(
@@ -1036,7 +1036,7 @@  discard block
 block discarded – undo
1036 1036
         }
1037 1037
         // take into account search
1038 1038
         if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1039
-            $similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1039
+            $similarity_string = array('LIKE', '%'.str_replace("", "%", $this->_req_data['s']).'%');
1040 1040
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1041 1041
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1042 1042
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
@@ -1056,8 +1056,8 @@  discard block
 block discarded – undo
1056 1056
             $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1057 1057
             $end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1058 1058
             // make sure our timestamps start and end right at the boundaries for each day
1059
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1060
-            $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1059
+            $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
1060
+            $end_date = date('Y-m-d', strtotime($end_date)).' 23:59:59';
1061 1061
             // convert to timestamps
1062 1062
             $start_date = strtotime($start_date);
1063 1063
             $end_date = strtotime($end_date);
@@ -1090,15 +1090,15 @@  discard block
 block discarded – undo
1090 1090
             $query_params['order_by'] = array('LOG_time' => 'DESC');
1091 1091
         }
1092 1092
         $offset = ($current_page - 1) * $per_page;
1093
-        if (! isset($this->_req_data['download_results'])) {
1093
+        if ( ! isset($this->_req_data['download_results'])) {
1094 1094
             $query_params['limit'] = array($offset, $per_page);
1095 1095
         }
1096 1096
         // now they've requested to instead just download the file instead of viewing it.
1097 1097
         if (isset($this->_req_data['download_results'])) {
1098 1098
             $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1099 1099
             header('Content-Disposition: attachment');
1100
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1101
-            echo "<h1>Payment Logs for " . site_url() . "</h1>";
1100
+            header("Content-Disposition: attachment; filename=ee_payment_logs_for_".sanitize_key(site_url()));
1101
+            echo "<h1>Payment Logs for ".site_url()."</h1>";
1102 1102
             echo "<h3>Query:</h3>";
1103 1103
             var_dump($query_params);
1104 1104
             echo "<h3>Results:</h3>";
@@ -1153,7 +1153,7 @@  discard block
 block discarded – undo
1153 1153
             }
1154 1154
         }
1155 1155
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1156
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1156
+            EE_PAYMENTS_TEMPLATE_PATH.'payment_log_details.template.php',
1157 1157
             array(
1158 1158
                 'payment_log'    => $payment_log,
1159 1159
                 'payment_method' => $payment_method,
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_CPT.core.php 1 patch
Indentation   +1454 added lines, -1454 removed lines patch added patch discarded remove patch
@@ -26,467 +26,467 @@  discard block
 block discarded – undo
26 26
 {
27 27
 
28 28
 
29
-    /**
30
-     * This gets set in _setup_cpt
31
-     * It will contain the object for the custom post type.
32
-     *
33
-     * @var EE_CPT_Base
34
-     */
35
-    protected $_cpt_object;
36
-
37
-
38
-    /**
39
-     * a boolean flag to set whether the current route is a cpt route or not.
40
-     *
41
-     * @var bool
42
-     */
43
-    protected $_cpt_route = false;
44
-
45
-
46
-    /**
47
-     * This property allows cpt classes to define multiple routes as cpt routes.
48
-     * //in this array we define what the custom post type for this route is.
49
-     * array(
50
-     * 'route_name' => 'custom_post_type_slug'
51
-     * )
52
-     *
53
-     * @var array
54
-     */
55
-    protected $_cpt_routes = array();
56
-
57
-
58
-    /**
59
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
60
-     * in this format:
61
-     * array(
62
-     * 'post_type_slug' => 'edit_route'
63
-     * )
64
-     *
65
-     * @var array
66
-     */
67
-    protected $_cpt_edit_routes = array();
68
-
69
-
70
-    /**
71
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
72
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
73
-     * _cpt_model_names property should be in the following format: array(
74
-     * 'route_defined_by_action_param' => 'Model_Name')
75
-     *
76
-     * @var array $_cpt_model_names
77
-     */
78
-    protected $_cpt_model_names = array();
79
-
80
-
81
-    /**
82
-     * @var EE_CPT_Base
83
-     */
84
-    protected $_cpt_model_obj = false;
85
-
86
-
87
-    /**
88
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
89
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
90
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
91
-     * Registration of containers should be done before load_page_dependencies() is run.
92
-     *
93
-     * @var array()
94
-     */
95
-    protected $_autosave_containers = array();
96
-    protected $_autosave_fields = array();
97
-
98
-    /**
99
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
100
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
101
-     *
102
-     * @var array
103
-     */
104
-    protected $_pagenow_map;
105
-
106
-
107
-
108
-    /**
109
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
110
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
111
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
112
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
113
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
114
-     *
115
-     * @access protected
116
-     * @abstract
117
-     * @param  string      $post_id The ID of the cpt that was saved (so you can link relationally)
118
-     * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
119
-     * @return void
120
-     */
121
-    abstract protected function _insert_update_cpt_item($post_id, $post);
122
-
123
-
124
-    /**
125
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
126
-     *
127
-     * @abstract
128
-     * @access public
129
-     * @param  string $post_id The ID of the cpt that was trashed
130
-     * @return void
131
-     */
132
-    abstract public function trash_cpt_item($post_id);
133
-
134
-
135
-    /**
136
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
137
-     *
138
-     * @param  string $post_id theID of the cpt that was untrashed
139
-     * @return void
140
-     */
141
-    abstract public function restore_cpt_item($post_id);
142
-
143
-
144
-    /**
145
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
146
-     * from the db
147
-     *
148
-     * @param  string $post_id the ID of the cpt that was deleted
149
-     * @return void
150
-     */
151
-    abstract public function delete_cpt_item($post_id);
152
-
153
-
154
-    /**
155
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
156
-     *
157
-     * @access protected
158
-     * @return void
159
-     */
160
-    protected function _before_page_setup()
161
-    {
162
-        $page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
163
-        $this->_cpt_routes = array_merge(
164
-            array(
165
-                'create_new' => $this->page_slug,
166
-                'edit'       => $this->page_slug,
167
-                'trash'      => $this->page_slug,
168
-            ),
169
-            $this->_cpt_routes
170
-        );
171
-        // let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
172
-        $this->_cpt_object = isset($this->_req_data['action'], $this->_cpt_routes[ $this->_req_data['action'] ])
173
-            ? get_post_type_object($this->_cpt_routes[ $this->_req_data['action'] ])
174
-            : get_post_type_object($page);
175
-        // tweak pagenow for page loading.
176
-        if (! $this->_pagenow_map) {
177
-            $this->_pagenow_map = array(
178
-                'create_new' => 'post-new.php',
179
-                'edit'       => 'post.php',
180
-                'trash'      => 'post.php',
181
-            );
182
-        }
183
-        add_action('current_screen', array($this, 'modify_pagenow'));
184
-        // TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
185
-        // get current page from autosave
186
-        $current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
187
-            ? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
188
-            : null;
189
-        $this->_current_page = isset($this->_req_data['current_page'])
190
-            ? $this->_req_data['current_page']
191
-            : $current_page;
192
-        // autosave... make sure its only for the correct page
193
-        // if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
194
-        // setup autosave ajax hook
195
-        // add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
196
-        // }
197
-    }
198
-
199
-
200
-    /**
201
-     * Simply ensure that we simulate the correct post route for cpt screens
202
-     *
203
-     * @param WP_Screen $current_screen
204
-     * @return void
205
-     */
206
-    public function modify_pagenow($current_screen)
207
-    {
208
-        global $pagenow, $hook_suffix;
209
-        // possibly reset pagenow.
210
-        if (! empty($this->_req_data['page'])
211
-            && $this->_req_data['page'] === $this->page_slug
212
-            && ! empty($this->_req_data['action'])
213
-            && isset($this->_pagenow_map[ $this->_req_data['action'] ])
214
-        ) {
215
-            $pagenow = $this->_pagenow_map[ $this->_req_data['action'] ];
216
-            $hook_suffix = $pagenow;
217
-        }
218
-    }
219
-
220
-
221
-    /**
222
-     * This method is used to register additional autosave containers to the _autosave_containers property.
223
-     *
224
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
225
-     *       automatically register the id for the post metabox as a container.
226
-     * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
227
-     *                    you would send along the id of a metabox container.
228
-     * @return void
229
-     */
230
-    protected function _register_autosave_containers($ids)
231
-    {
232
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
233
-    }
234
-
235
-
236
-    /**
237
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
238
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
239
-     */
240
-    protected function _set_autosave_containers()
241
-    {
242
-        global $wp_meta_boxes;
243
-        $containers = array();
244
-        if (empty($wp_meta_boxes)) {
245
-            return;
246
-        }
247
-        $current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : array();
248
-        foreach ($current_metaboxes as $box_context) {
249
-            foreach ($box_context as $box_details) {
250
-                foreach ($box_details as $box) {
251
-                    if (is_array($box) && is_array($box['callback'])
252
-                        && (
253
-                            $box['callback'][0] instanceof EE_Admin_Page
254
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
255
-                        )
256
-                    ) {
257
-                        $containers[] = $box['id'];
258
-                    }
259
-                }
260
-            }
261
-        }
262
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
263
-        // add hidden inputs container
264
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
265
-    }
266
-
267
-
268
-    protected function _load_autosave_scripts_styles()
269
-    {
270
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
29
+	/**
30
+	 * This gets set in _setup_cpt
31
+	 * It will contain the object for the custom post type.
32
+	 *
33
+	 * @var EE_CPT_Base
34
+	 */
35
+	protected $_cpt_object;
36
+
37
+
38
+	/**
39
+	 * a boolean flag to set whether the current route is a cpt route or not.
40
+	 *
41
+	 * @var bool
42
+	 */
43
+	protected $_cpt_route = false;
44
+
45
+
46
+	/**
47
+	 * This property allows cpt classes to define multiple routes as cpt routes.
48
+	 * //in this array we define what the custom post type for this route is.
49
+	 * array(
50
+	 * 'route_name' => 'custom_post_type_slug'
51
+	 * )
52
+	 *
53
+	 * @var array
54
+	 */
55
+	protected $_cpt_routes = array();
56
+
57
+
58
+	/**
59
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
60
+	 * in this format:
61
+	 * array(
62
+	 * 'post_type_slug' => 'edit_route'
63
+	 * )
64
+	 *
65
+	 * @var array
66
+	 */
67
+	protected $_cpt_edit_routes = array();
68
+
69
+
70
+	/**
71
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
72
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
73
+	 * _cpt_model_names property should be in the following format: array(
74
+	 * 'route_defined_by_action_param' => 'Model_Name')
75
+	 *
76
+	 * @var array $_cpt_model_names
77
+	 */
78
+	protected $_cpt_model_names = array();
79
+
80
+
81
+	/**
82
+	 * @var EE_CPT_Base
83
+	 */
84
+	protected $_cpt_model_obj = false;
85
+
86
+
87
+	/**
88
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
89
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
90
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
91
+	 * Registration of containers should be done before load_page_dependencies() is run.
92
+	 *
93
+	 * @var array()
94
+	 */
95
+	protected $_autosave_containers = array();
96
+	protected $_autosave_fields = array();
97
+
98
+	/**
99
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
100
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
101
+	 *
102
+	 * @var array
103
+	 */
104
+	protected $_pagenow_map;
105
+
106
+
107
+
108
+	/**
109
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
110
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
111
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
112
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
113
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
114
+	 *
115
+	 * @access protected
116
+	 * @abstract
117
+	 * @param  string      $post_id The ID of the cpt that was saved (so you can link relationally)
118
+	 * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
119
+	 * @return void
120
+	 */
121
+	abstract protected function _insert_update_cpt_item($post_id, $post);
122
+
123
+
124
+	/**
125
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
126
+	 *
127
+	 * @abstract
128
+	 * @access public
129
+	 * @param  string $post_id The ID of the cpt that was trashed
130
+	 * @return void
131
+	 */
132
+	abstract public function trash_cpt_item($post_id);
133
+
134
+
135
+	/**
136
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
137
+	 *
138
+	 * @param  string $post_id theID of the cpt that was untrashed
139
+	 * @return void
140
+	 */
141
+	abstract public function restore_cpt_item($post_id);
142
+
143
+
144
+	/**
145
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
146
+	 * from the db
147
+	 *
148
+	 * @param  string $post_id the ID of the cpt that was deleted
149
+	 * @return void
150
+	 */
151
+	abstract public function delete_cpt_item($post_id);
152
+
153
+
154
+	/**
155
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
156
+	 *
157
+	 * @access protected
158
+	 * @return void
159
+	 */
160
+	protected function _before_page_setup()
161
+	{
162
+		$page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
163
+		$this->_cpt_routes = array_merge(
164
+			array(
165
+				'create_new' => $this->page_slug,
166
+				'edit'       => $this->page_slug,
167
+				'trash'      => $this->page_slug,
168
+			),
169
+			$this->_cpt_routes
170
+		);
171
+		// let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
172
+		$this->_cpt_object = isset($this->_req_data['action'], $this->_cpt_routes[ $this->_req_data['action'] ])
173
+			? get_post_type_object($this->_cpt_routes[ $this->_req_data['action'] ])
174
+			: get_post_type_object($page);
175
+		// tweak pagenow for page loading.
176
+		if (! $this->_pagenow_map) {
177
+			$this->_pagenow_map = array(
178
+				'create_new' => 'post-new.php',
179
+				'edit'       => 'post.php',
180
+				'trash'      => 'post.php',
181
+			);
182
+		}
183
+		add_action('current_screen', array($this, 'modify_pagenow'));
184
+		// TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
185
+		// get current page from autosave
186
+		$current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
187
+			? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
188
+			: null;
189
+		$this->_current_page = isset($this->_req_data['current_page'])
190
+			? $this->_req_data['current_page']
191
+			: $current_page;
192
+		// autosave... make sure its only for the correct page
193
+		// if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
194
+		// setup autosave ajax hook
195
+		// add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
196
+		// }
197
+	}
198
+
199
+
200
+	/**
201
+	 * Simply ensure that we simulate the correct post route for cpt screens
202
+	 *
203
+	 * @param WP_Screen $current_screen
204
+	 * @return void
205
+	 */
206
+	public function modify_pagenow($current_screen)
207
+	{
208
+		global $pagenow, $hook_suffix;
209
+		// possibly reset pagenow.
210
+		if (! empty($this->_req_data['page'])
211
+			&& $this->_req_data['page'] === $this->page_slug
212
+			&& ! empty($this->_req_data['action'])
213
+			&& isset($this->_pagenow_map[ $this->_req_data['action'] ])
214
+		) {
215
+			$pagenow = $this->_pagenow_map[ $this->_req_data['action'] ];
216
+			$hook_suffix = $pagenow;
217
+		}
218
+	}
219
+
220
+
221
+	/**
222
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
223
+	 *
224
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
225
+	 *       automatically register the id for the post metabox as a container.
226
+	 * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
227
+	 *                    you would send along the id of a metabox container.
228
+	 * @return void
229
+	 */
230
+	protected function _register_autosave_containers($ids)
231
+	{
232
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
233
+	}
234
+
235
+
236
+	/**
237
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
238
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
239
+	 */
240
+	protected function _set_autosave_containers()
241
+	{
242
+		global $wp_meta_boxes;
243
+		$containers = array();
244
+		if (empty($wp_meta_boxes)) {
245
+			return;
246
+		}
247
+		$current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : array();
248
+		foreach ($current_metaboxes as $box_context) {
249
+			foreach ($box_context as $box_details) {
250
+				foreach ($box_details as $box) {
251
+					if (is_array($box) && is_array($box['callback'])
252
+						&& (
253
+							$box['callback'][0] instanceof EE_Admin_Page
254
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
255
+						)
256
+					) {
257
+						$containers[] = $box['id'];
258
+					}
259
+				}
260
+			}
261
+		}
262
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
263
+		// add hidden inputs container
264
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
265
+	}
266
+
267
+
268
+	protected function _load_autosave_scripts_styles()
269
+	{
270
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
271 271
         wp_enqueue_script('cpt-autosave');/**/ // todo re-enable when we start doing autosave again in 4.2
272 272
 
273
-        // filter _autosave_containers
274
-        $containers = apply_filters(
275
-            'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
276
-            $this->_autosave_containers,
277
-            $this
278
-        );
279
-        $containers = apply_filters(
280
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
281
-            $containers,
282
-            $this
283
-        );
284
-
285
-        wp_localize_script(
286
-            'event_editor_js',
287
-            'EE_AUTOSAVE_IDS',
288
-            $containers
289
-        ); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
290
-
291
-        $unsaved_data_msg = array(
292
-            'eventmsg'     => sprintf(
293
-                __(
294
-                    'The changes you made to this %s will be lost if you navigate away from this page.',
295
-                    'event_espresso'
296
-                ),
297
-                $this->_cpt_object->labels->singular_name
298
-            ),
299
-            'inputChanged' => 0,
300
-        );
301
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
302
-    }
303
-
304
-
305
-    /**
306
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
307
-     *
308
-     * @access protected
309
-     * @return void
310
-     * @throws EE_Error
311
-     * @throws ReflectionException
312
-     */
313
-    protected function _load_page_dependencies()
314
-    {
315
-        // we only add stuff if this is a cpt_route!
316
-        if (! $this->_cpt_route) {
317
-            parent::_load_page_dependencies();
318
-            return;
319
-        }
320
-        // now let's do some automatic filters into the wp_system
321
-        // and we'll check to make sure the CHILD class
322
-        // automatically has the required methods in place.
323
-        // the following filters are for setting all the redirects
324
-        // on DEFAULT WP custom post type actions
325
-        // let's add a hidden input to the post-edit form
326
-        // so we know when we have to trigger our custom redirects!
327
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
328
-        add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
329
-        // inject our Admin page nav tabs...
330
-        // let's make sure the nav tabs are set if they aren't already
331
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
332
-        add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
333
-        // modify the post_updated messages array
334
-        add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
335
-        // add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
336
-        // cpts use the same format for shortlinks as posts!
337
-        add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
338
-        // This basically allows us to change the title of the "publish" metabox area
339
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
340
-        if (! empty($this->_labels['publishbox'])) {
341
-            $box_label = is_array($this->_labels['publishbox'])
342
-                         && isset($this->_labels['publishbox'][ $this->_req_action ])
343
-                ? $this->_labels['publishbox'][ $this->_req_action ]
344
-                : $this->_labels['publishbox'];
345
-            add_meta_box(
346
-                'submitdiv',
347
-                $box_label,
348
-                'post_submit_meta_box',
349
-                $this->_cpt_routes[ $this->_req_action ],
350
-                'side',
351
-                'core'
352
-            );
353
-        }
354
-        // let's add page_templates metabox if this cpt added support for it.
355
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
356
-            add_meta_box(
357
-                'page_templates',
358
-                __('Page Template', 'event_espresso'),
359
-                array($this, 'page_template_meta_box'),
360
-                $this->_cpt_routes[ $this->_req_action ],
361
-                'side',
362
-                'default'
363
-            );
364
-        }
365
-        // this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
366
-        if (method_exists($this, 'extra_permalink_field_buttons')) {
367
-            add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
368
-        }
369
-        // add preview button
370
-        add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
371
-        // insert our own post_stati dropdown
372
-        add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
373
-        // This allows adding additional information to the publish post submitbox on the wp post edit form
374
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
375
-            add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
376
-        }
377
-        // This allows for adding additional stuff after the title field on the wp post edit form.
378
-        // This is also before the wp_editor for post description field.
379
-        if (method_exists($this, 'edit_form_after_title')) {
380
-            add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
381
-        }
382
-        /**
383
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
384
-         */
385
-        add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
386
-        parent::_load_page_dependencies();
387
-        // notice we are ALSO going to load the pagenow hook set for this route
388
-        // (see _before_page_setup for the reset of the pagenow global ).
389
-        // This is for any plugins that are doing things properly
390
-        // and hooking into the load page hook for core wp cpt routes.
391
-        global $pagenow;
392
-        add_action('load-' . $pagenow, array($this, 'modify_current_screen'), 20);
393
-        do_action('load-' . $pagenow);
394
-        add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
395
-        // we route REALLY early.
396
-        try {
397
-            $this->_route_admin_request();
398
-        } catch (EE_Error $e) {
399
-            $e->get_error();
400
-        }
401
-    }
402
-
403
-
404
-    /**
405
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
406
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
407
-     * route instead.
408
-     *
409
-     * @param string $good_protocol_url The escaped url.
410
-     * @param string $original_url      The original url.
411
-     * @param string $_context          The context sent to the esc_url method.
412
-     * @return string possibly a new url for our route.
413
-     */
414
-    public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
415
-    {
416
-        $routes_to_match = array(
417
-            0 => array(
418
-                'edit.php?post_type=espresso_attendees',
419
-                'admin.php?page=espresso_registrations&action=contact_list',
420
-            ),
421
-            1 => array(
422
-                'edit.php?post_type=' . $this->_cpt_object->name,
423
-                'admin.php?page=' . $this->_cpt_object->name,
424
-            ),
425
-        );
426
-        foreach ($routes_to_match as $route_matches) {
427
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
428
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
429
-            }
430
-        }
431
-        return $good_protocol_url;
432
-    }
433
-
434
-
435
-    /**
436
-     * Determine whether the current cpt supports page templates or not.
437
-     *
438
-     * @since %VER%
439
-     * @param string $cpt_name The cpt slug we're checking on.
440
-     * @return bool True supported, false not.
441
-     * @throws InvalidArgumentException
442
-     * @throws InvalidDataTypeException
443
-     * @throws InvalidInterfaceException
444
-     */
445
-    private function _supports_page_templates($cpt_name)
446
-    {
447
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
448
-        $custom_post_types = $this->loader->getShared(
449
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
450
-        );
451
-        $cpt_args = $custom_post_types->getDefinitions();
452
-        $cpt_args = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : array();
453
-        $cpt_has_support = ! empty($cpt_args['page_templates']);
454
-
455
-        // if the installed version of WP is > 4.7 we do some additional checks.
456
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
457
-            $post_templates = wp_get_theme()->get_post_templates();
458
-            // if there are $post_templates for this cpt, then we return false for this method because
459
-            // that means we aren't going to load our page template manager and leave that up to the native
460
-            // cpt template manager.
461
-            $cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
462
-        }
463
-
464
-        return $cpt_has_support;
465
-    }
466
-
467
-
468
-    /**
469
-     * Callback for the page_templates metabox selector.
470
-     *
471
-     * @since %VER%
472
-     * @return void
473
-     */
474
-    public function page_template_meta_box()
475
-    {
476
-        global $post;
477
-        $template = '';
478
-
479
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
480
-            $page_template_count = count(get_page_templates());
481
-        } else {
482
-            $page_template_count = count(get_page_templates($post));
483
-        }
484
-
485
-        if ($page_template_count) {
486
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
487
-            $template = ! empty($page_template) ? $page_template : '';
488
-        }
489
-        ?>
273
+		// filter _autosave_containers
274
+		$containers = apply_filters(
275
+			'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
276
+			$this->_autosave_containers,
277
+			$this
278
+		);
279
+		$containers = apply_filters(
280
+			'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
281
+			$containers,
282
+			$this
283
+		);
284
+
285
+		wp_localize_script(
286
+			'event_editor_js',
287
+			'EE_AUTOSAVE_IDS',
288
+			$containers
289
+		); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
290
+
291
+		$unsaved_data_msg = array(
292
+			'eventmsg'     => sprintf(
293
+				__(
294
+					'The changes you made to this %s will be lost if you navigate away from this page.',
295
+					'event_espresso'
296
+				),
297
+				$this->_cpt_object->labels->singular_name
298
+			),
299
+			'inputChanged' => 0,
300
+		);
301
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
302
+	}
303
+
304
+
305
+	/**
306
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
307
+	 *
308
+	 * @access protected
309
+	 * @return void
310
+	 * @throws EE_Error
311
+	 * @throws ReflectionException
312
+	 */
313
+	protected function _load_page_dependencies()
314
+	{
315
+		// we only add stuff if this is a cpt_route!
316
+		if (! $this->_cpt_route) {
317
+			parent::_load_page_dependencies();
318
+			return;
319
+		}
320
+		// now let's do some automatic filters into the wp_system
321
+		// and we'll check to make sure the CHILD class
322
+		// automatically has the required methods in place.
323
+		// the following filters are for setting all the redirects
324
+		// on DEFAULT WP custom post type actions
325
+		// let's add a hidden input to the post-edit form
326
+		// so we know when we have to trigger our custom redirects!
327
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
328
+		add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
329
+		// inject our Admin page nav tabs...
330
+		// let's make sure the nav tabs are set if they aren't already
331
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
332
+		add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
333
+		// modify the post_updated messages array
334
+		add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
335
+		// add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
336
+		// cpts use the same format for shortlinks as posts!
337
+		add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
338
+		// This basically allows us to change the title of the "publish" metabox area
339
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
340
+		if (! empty($this->_labels['publishbox'])) {
341
+			$box_label = is_array($this->_labels['publishbox'])
342
+						 && isset($this->_labels['publishbox'][ $this->_req_action ])
343
+				? $this->_labels['publishbox'][ $this->_req_action ]
344
+				: $this->_labels['publishbox'];
345
+			add_meta_box(
346
+				'submitdiv',
347
+				$box_label,
348
+				'post_submit_meta_box',
349
+				$this->_cpt_routes[ $this->_req_action ],
350
+				'side',
351
+				'core'
352
+			);
353
+		}
354
+		// let's add page_templates metabox if this cpt added support for it.
355
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
356
+			add_meta_box(
357
+				'page_templates',
358
+				__('Page Template', 'event_espresso'),
359
+				array($this, 'page_template_meta_box'),
360
+				$this->_cpt_routes[ $this->_req_action ],
361
+				'side',
362
+				'default'
363
+			);
364
+		}
365
+		// this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
366
+		if (method_exists($this, 'extra_permalink_field_buttons')) {
367
+			add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
368
+		}
369
+		// add preview button
370
+		add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
371
+		// insert our own post_stati dropdown
372
+		add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
373
+		// This allows adding additional information to the publish post submitbox on the wp post edit form
374
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
375
+			add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
376
+		}
377
+		// This allows for adding additional stuff after the title field on the wp post edit form.
378
+		// This is also before the wp_editor for post description field.
379
+		if (method_exists($this, 'edit_form_after_title')) {
380
+			add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
381
+		}
382
+		/**
383
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
384
+		 */
385
+		add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
386
+		parent::_load_page_dependencies();
387
+		// notice we are ALSO going to load the pagenow hook set for this route
388
+		// (see _before_page_setup for the reset of the pagenow global ).
389
+		// This is for any plugins that are doing things properly
390
+		// and hooking into the load page hook for core wp cpt routes.
391
+		global $pagenow;
392
+		add_action('load-' . $pagenow, array($this, 'modify_current_screen'), 20);
393
+		do_action('load-' . $pagenow);
394
+		add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
395
+		// we route REALLY early.
396
+		try {
397
+			$this->_route_admin_request();
398
+		} catch (EE_Error $e) {
399
+			$e->get_error();
400
+		}
401
+	}
402
+
403
+
404
+	/**
405
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
406
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
407
+	 * route instead.
408
+	 *
409
+	 * @param string $good_protocol_url The escaped url.
410
+	 * @param string $original_url      The original url.
411
+	 * @param string $_context          The context sent to the esc_url method.
412
+	 * @return string possibly a new url for our route.
413
+	 */
414
+	public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
415
+	{
416
+		$routes_to_match = array(
417
+			0 => array(
418
+				'edit.php?post_type=espresso_attendees',
419
+				'admin.php?page=espresso_registrations&action=contact_list',
420
+			),
421
+			1 => array(
422
+				'edit.php?post_type=' . $this->_cpt_object->name,
423
+				'admin.php?page=' . $this->_cpt_object->name,
424
+			),
425
+		);
426
+		foreach ($routes_to_match as $route_matches) {
427
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
428
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
429
+			}
430
+		}
431
+		return $good_protocol_url;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Determine whether the current cpt supports page templates or not.
437
+	 *
438
+	 * @since %VER%
439
+	 * @param string $cpt_name The cpt slug we're checking on.
440
+	 * @return bool True supported, false not.
441
+	 * @throws InvalidArgumentException
442
+	 * @throws InvalidDataTypeException
443
+	 * @throws InvalidInterfaceException
444
+	 */
445
+	private function _supports_page_templates($cpt_name)
446
+	{
447
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
448
+		$custom_post_types = $this->loader->getShared(
449
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
450
+		);
451
+		$cpt_args = $custom_post_types->getDefinitions();
452
+		$cpt_args = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : array();
453
+		$cpt_has_support = ! empty($cpt_args['page_templates']);
454
+
455
+		// if the installed version of WP is > 4.7 we do some additional checks.
456
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
457
+			$post_templates = wp_get_theme()->get_post_templates();
458
+			// if there are $post_templates for this cpt, then we return false for this method because
459
+			// that means we aren't going to load our page template manager and leave that up to the native
460
+			// cpt template manager.
461
+			$cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
462
+		}
463
+
464
+		return $cpt_has_support;
465
+	}
466
+
467
+
468
+	/**
469
+	 * Callback for the page_templates metabox selector.
470
+	 *
471
+	 * @since %VER%
472
+	 * @return void
473
+	 */
474
+	public function page_template_meta_box()
475
+	{
476
+		global $post;
477
+		$template = '';
478
+
479
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
480
+			$page_template_count = count(get_page_templates());
481
+		} else {
482
+			$page_template_count = count(get_page_templates($post));
483
+		}
484
+
485
+		if ($page_template_count) {
486
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
487
+			$template = ! empty($page_template) ? $page_template : '';
488
+		}
489
+		?>
490 490
         <p><strong><?php _e('Template', 'event_espresso') ?></strong></p>
491 491
         <label class="screen-reader-text" for="page_template"><?php _e('Page Template', 'event_espresso') ?></label><select
492 492
         name="page_template" id="page_template">
@@ -494,478 +494,478 @@  discard block
 block discarded – undo
494 494
         <?php page_template_dropdown($template); ?>
495 495
     </select>
496 496
         <?php
497
-    }
498
-
499
-
500
-    /**
501
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
502
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
503
-     *
504
-     * @param  string $return    the current html
505
-     * @param  int    $id        the post id for the page
506
-     * @param  string $new_title What the title is
507
-     * @param  string $new_slug  what the slug is
508
-     * @return string            The new html string for the permalink area
509
-     */
510
-    public function preview_button_html($return, $id, $new_title, $new_slug)
511
-    {
512
-        $post = get_post($id);
513
-        if ('publish' !== get_post_status($post)) {
514
-            $return .= '<span_id="view-post-btn"><a target="_blank" href="'
515
-                       . get_preview_post_link($id)
516
-                       . '" class="button button-small">'
517
-                       . __('Preview', 'event_espresso')
518
-                       . '</a></span>'
519
-                       . "\n";
520
-        }
521
-        return $return;
522
-    }
523
-
524
-
525
-    /**
526
-     * add our custom post stati dropdown on the wp post page for this cpt
527
-     *
528
-     * @return void
529
-     */
530
-    public function custom_post_stati_dropdown()
531
-    {
532
-
533
-        $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
534
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
535
-            ? $statuses[ $this->_cpt_model_obj->status() ]
536
-            : '';
537
-        $template_args = array(
538
-            'cur_status'            => $this->_cpt_model_obj->status(),
539
-            'statuses'              => $statuses,
540
-            'cur_status_label'      => $cur_status_label,
541
-            'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
542
-        );
543
-        // we'll add a trash post status (WP doesn't add one for some reason)
544
-        if ($this->_cpt_model_obj->status() === 'trash') {
545
-            $template_args['cur_status_label'] = __('Trashed', 'event_espresso');
546
-            $statuses['trash'] = __('Trashed', 'event_espresso');
547
-            $template_args['statuses'] = $statuses;
548
-        }
549
-
550
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
551
-        EEH_Template::display_template($template, $template_args);
552
-    }
553
-
554
-
555
-    public function setup_autosave_hooks()
556
-    {
557
-        $this->_set_autosave_containers();
558
-        $this->_load_autosave_scripts_styles();
559
-    }
560
-
561
-
562
-    /**
563
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
564
-     * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
565
-     * for the nonce in here, but then this method looks for two things:
566
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
567
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
568
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
569
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
570
-     * template args.
571
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
572
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
573
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
574
-     *    $this->_template_args['data']['items'] = array(
575
-     *        'event-datetime-ids' => '1,2,3';
576
-     *    );
577
-     *    Keep in mind the following things:
578
-     *    - "where" index is for the input with the id as that string.
579
-     *    - "what" index is what will be used for the value of that input.
580
-     *
581
-     * @return void
582
-     * @throws EE_Error
583
-     */
584
-    public function do_extra_autosave_stuff()
585
-    {
586
-        // next let's check for the autosave nonce (we'll use _verify_nonce )
587
-        $nonce = isset($this->_req_data['autosavenonce'])
588
-            ? $this->_req_data['autosavenonce']
589
-            : null;
590
-        $this->_verify_nonce($nonce, 'autosave');
591
-        // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
592
-        if (! defined('DOING_AUTOSAVE')) {
593
-            define('DOING_AUTOSAVE', true);
594
-        }
595
-        // if we made it here then the nonce checked out.  Let's run our methods and actions
596
-        $autosave = "_ee_autosave_{$this->_current_view}";
597
-        if (method_exists($this, $autosave)) {
598
-            $this->$autosave();
599
-        } else {
600
-            $this->_template_args['success'] = true;
601
-        }
602
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
603
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
604
-        // now let's return json
605
-        $this->_return_json();
606
-    }
607
-
608
-
609
-    /**
610
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
611
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
612
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
613
-     *
614
-     * @access protected
615
-     * @return void
616
-     * @throws ReflectionException
617
-     * @throws EE_Error
618
-     */
619
-    protected function _extend_page_config_for_cpt()
620
-    {
621
-        // before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
622
-        if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
623
-            return;
624
-        }
625
-        // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
626
-        if (! empty($this->_cpt_object)) {
627
-            $this->_page_routes = array_merge(
628
-                array(
629
-                    'create_new' => '_create_new_cpt_item',
630
-                    'edit'       => '_edit_cpt_item',
631
-                ),
632
-                $this->_page_routes
633
-            );
634
-            $this->_page_config = array_merge(
635
-                array(
636
-                    'create_new' => array(
637
-                        'nav'           => array(
638
-                            'label' => $this->_cpt_object->labels->add_new_item,
639
-                            'order' => 5,
640
-                        ),
641
-                        'require_nonce' => false,
642
-                    ),
643
-                    'edit'       => array(
644
-                        'nav'           => array(
645
-                            'label'      => $this->_cpt_object->labels->edit_item,
646
-                            'order'      => 5,
647
-                            'persistent' => false,
648
-                            'url'        => '',
649
-                        ),
650
-                        'require_nonce' => false,
651
-                    ),
652
-                ),
653
-                $this->_page_config
654
-            );
655
-        }
656
-        // load the next section only if this is a matching cpt route as set in the cpt routes array.
657
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
658
-            return;
659
-        }
660
-        $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]) ? true : false;
661
-        // add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
662
-        if (empty($this->_cpt_object)) {
663
-            $msg = sprintf(
664
-                __(
665
-                    'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
666
-                    'event_espresso'
667
-                ),
668
-                $this->page_slug,
669
-                $this->_req_action,
670
-                get_class($this)
671
-            );
672
-            throw new EE_Error($msg);
673
-        }
674
-        if ($this->_cpt_route) {
675
-            $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
676
-            $this->_set_model_object($id);
677
-        }
678
-    }
679
-
680
-
681
-    /**
682
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
-     *
684
-     * @access protected
685
-     * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
686
-     * @param bool   $ignore_route_check
687
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
-     * @throws EE_Error
689
-     * @throws InvalidArgumentException
690
-     * @throws InvalidDataTypeException
691
-     * @throws InvalidInterfaceException
692
-     * @throws ReflectionException
693
-     */
694
-    protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
695
-    {
696
-        $model = null;
697
-        if (empty($this->_cpt_model_names)
698
-            || (
699
-                ! $ignore_route_check
700
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
701
-            ) || (
702
-                $this->_cpt_model_obj instanceof EE_CPT_Base
703
-                && $this->_cpt_model_obj->ID() === $id
704
-            )
705
-        ) {
706
-            // get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
707
-            return;
708
-        }
709
-        // if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
710
-        if ($ignore_route_check) {
711
-            $post_type = get_post_type($id);
712
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
713
-            $custom_post_types = $this->loader->getShared(
714
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
715
-            );
716
-            $model_names = $custom_post_types->getCustomPostTypeModelNames($post_type);
717
-            if (isset($model_names[ $post_type ])) {
718
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
719
-            }
720
-        } else {
721
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
722
-        }
723
-        if ($model instanceof EEM_Base) {
724
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
725
-        }
726
-        do_action(
727
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
728
-            $this->_cpt_model_obj,
729
-            $req_type
730
-        );
731
-    }
732
-
733
-
734
-    /**
735
-     * admin_init_global
736
-     * This runs all the code that we want executed within the WP admin_init hook.
737
-     * This method executes for ALL EE Admin pages.
738
-     *
739
-     * @access public
740
-     * @return void
741
-     */
742
-    public function admin_init_global()
743
-    {
744
-        $post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
745
-        // its possible this is a new save so let's catch that instead
746
-        $post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
747
-        $post_type = $post ? $post->post_type : false;
748
-        $current_route = isset($this->_req_data['current_route'])
749
-            ? $this->_req_data['current_route']
750
-            : 'shouldneverwork';
751
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
752
-            ? $this->_cpt_routes[ $current_route ]
753
-            : '';
754
-        add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
755
-        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
756
-        if ($post_type === $route_to_check) {
757
-            add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
758
-        }
759
-        // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
760
-        $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
761
-        if (! empty($revision)) {
762
-            $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
763
-            // doing a restore?
764
-            if (! empty($action) && $action === 'restore') {
765
-                // get post for revision
766
-                $rev_post = get_post($revision);
767
-                $rev_parent = get_post($rev_post->post_parent);
768
-                // only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
769
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
770
-                    add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
771
-                    // restores of revisions
772
-                    add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
773
-                }
774
-            }
775
-        }
776
-        // NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
777
-        if ($post_type && $post_type === $route_to_check) {
778
-            // $post_id, $post
779
-            add_action('save_post', array($this, 'insert_update'), 10, 3);
780
-            // $post_id
781
-            add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
782
-            add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
783
-            add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
784
-            add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
785
-        }
786
-    }
787
-
788
-
789
-    /**
790
-     * Callback for the WordPress trashed_post hook.
791
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
792
-     *
793
-     * @param int $post_id
794
-     * @throws EE_Error
795
-     * @throws ReflectionException
796
-     */
797
-    public function before_trash_cpt_item($post_id)
798
-    {
799
-        $this->_set_model_object($post_id, true, 'trash');
800
-        // if our cpt object isn't existent then get out immediately.
801
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
802
-            return;
803
-        }
804
-        $this->trash_cpt_item($post_id);
805
-    }
806
-
807
-
808
-    /**
809
-     * Callback for the WordPress untrashed_post hook.
810
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
811
-     *
812
-     * @param $post_id
813
-     * @throws EE_Error
814
-     * @throws ReflectionException
815
-     */
816
-    public function before_restore_cpt_item($post_id)
817
-    {
818
-        $this->_set_model_object($post_id, true, 'restore');
819
-        // if our cpt object isn't existent then get out immediately.
820
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
821
-            return;
822
-        }
823
-        $this->restore_cpt_item($post_id);
824
-    }
825
-
826
-
827
-    /**
828
-     * Callback for the WordPress after_delete_post hook.
829
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
830
-     *
831
-     * @param $post_id
832
-     * @throws EE_Error
833
-     * @throws ReflectionException
834
-     */
835
-    public function before_delete_cpt_item($post_id)
836
-    {
837
-        $this->_set_model_object($post_id, true, 'delete');
838
-        // if our cpt object isn't existent then get out immediately.
839
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
840
-            return;
841
-        }
842
-        $this->delete_cpt_item($post_id);
843
-    }
844
-
845
-
846
-    /**
847
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
848
-     * accordingly.
849
-     *
850
-     * @return void
851
-     * @throws EE_Error
852
-     * @throws InvalidArgumentException
853
-     * @throws InvalidDataTypeException
854
-     * @throws InvalidInterfaceException
855
-     * @throws ReflectionException
856
-     */
857
-    public function verify_cpt_object()
858
-    {
859
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
860
-        // verify event object
861
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
862
-            throw new EE_Error(
863
-                sprintf(
864
-                    __(
865
-                        'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
866
-                        'event_espresso'
867
-                    ),
868
-                    $label
869
-                )
870
-            );
871
-        }
872
-        // if auto-draft then throw an error
873
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
874
-            EE_Error::overwrite_errors();
875
-            EE_Error::add_error(
876
-                sprintf(
877
-                    __(
878
-                        'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
879
-                        'event_espresso'
880
-                    ),
881
-                    $label
882
-                ),
883
-                __FILE__,
884
-                __FUNCTION__,
885
-                __LINE__
886
-            );
887
-        }
888
-    }
889
-
890
-
891
-    /**
892
-     * admin_footer_scripts_global
893
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
894
-     * will apply on ALL EE_Admin pages.
895
-     *
896
-     * @access public
897
-     * @return void
898
-     */
899
-    public function admin_footer_scripts_global()
900
-    {
901
-        $this->_add_admin_page_ajax_loading_img();
902
-        $this->_add_admin_page_overlay();
903
-    }
904
-
905
-
906
-    /**
907
-     * add in any global scripts for cpt routes
908
-     *
909
-     * @return void
910
-     * @throws EE_Error
911
-     */
912
-    public function load_global_scripts_styles()
913
-    {
914
-        parent::load_global_scripts_styles();
915
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
916
-            // setup custom post status object for localize script but only if we've got a cpt object
917
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
918
-            if (! empty($statuses)) {
919
-                // get ALL statuses!
920
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
921
-                // setup object
922
-                $ee_cpt_statuses = array();
923
-                foreach ($statuses as $status => $label) {
924
-                    $ee_cpt_statuses[ $status ] = array(
925
-                        'label'      => $label,
926
-                        'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
927
-                    );
928
-                }
929
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
930
-            }
931
-        }
932
-    }
933
-
934
-
935
-    /**
936
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
937
-     * insert/updates
938
-     *
939
-     * @param int     $post_id ID of post being updated
940
-     * @param WP_Post $post    Post object from WP
941
-     * @param bool    $update  Whether this is an update or a new save.
942
-     * @return void
943
-     * @throws EE_Error
944
-     * @throws ReflectionException
945
-     */
946
-    public function insert_update($post_id, $post, $update)
947
-    {
948
-        // make sure that if this is a revision OR trash action that we don't do any updates!
949
-        if (isset($this->_req_data['action'])
950
-            && (
951
-                $this->_req_data['action'] === 'restore'
952
-                || $this->_req_data['action'] === 'trash'
953
-            )
954
-        ) {
955
-            return;
956
-        }
957
-        $this->_set_model_object($post_id, true, 'insert_update');
958
-        // if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
959
-        if ($update
960
-            && (
961
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
962
-                || $this->_cpt_model_obj->ID() !== $post_id
963
-            )
964
-        ) {
965
-            return;
966
-        }
967
-        // check for autosave and update our req_data property accordingly.
968
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
497
+	}
498
+
499
+
500
+	/**
501
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
502
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
503
+	 *
504
+	 * @param  string $return    the current html
505
+	 * @param  int    $id        the post id for the page
506
+	 * @param  string $new_title What the title is
507
+	 * @param  string $new_slug  what the slug is
508
+	 * @return string            The new html string for the permalink area
509
+	 */
510
+	public function preview_button_html($return, $id, $new_title, $new_slug)
511
+	{
512
+		$post = get_post($id);
513
+		if ('publish' !== get_post_status($post)) {
514
+			$return .= '<span_id="view-post-btn"><a target="_blank" href="'
515
+					   . get_preview_post_link($id)
516
+					   . '" class="button button-small">'
517
+					   . __('Preview', 'event_espresso')
518
+					   . '</a></span>'
519
+					   . "\n";
520
+		}
521
+		return $return;
522
+	}
523
+
524
+
525
+	/**
526
+	 * add our custom post stati dropdown on the wp post page for this cpt
527
+	 *
528
+	 * @return void
529
+	 */
530
+	public function custom_post_stati_dropdown()
531
+	{
532
+
533
+		$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
534
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
535
+			? $statuses[ $this->_cpt_model_obj->status() ]
536
+			: '';
537
+		$template_args = array(
538
+			'cur_status'            => $this->_cpt_model_obj->status(),
539
+			'statuses'              => $statuses,
540
+			'cur_status_label'      => $cur_status_label,
541
+			'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
542
+		);
543
+		// we'll add a trash post status (WP doesn't add one for some reason)
544
+		if ($this->_cpt_model_obj->status() === 'trash') {
545
+			$template_args['cur_status_label'] = __('Trashed', 'event_espresso');
546
+			$statuses['trash'] = __('Trashed', 'event_espresso');
547
+			$template_args['statuses'] = $statuses;
548
+		}
549
+
550
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
551
+		EEH_Template::display_template($template, $template_args);
552
+	}
553
+
554
+
555
+	public function setup_autosave_hooks()
556
+	{
557
+		$this->_set_autosave_containers();
558
+		$this->_load_autosave_scripts_styles();
559
+	}
560
+
561
+
562
+	/**
563
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
564
+	 * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
565
+	 * for the nonce in here, but then this method looks for two things:
566
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
567
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
568
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
569
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
570
+	 * template args.
571
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
572
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
573
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
574
+	 *    $this->_template_args['data']['items'] = array(
575
+	 *        'event-datetime-ids' => '1,2,3';
576
+	 *    );
577
+	 *    Keep in mind the following things:
578
+	 *    - "where" index is for the input with the id as that string.
579
+	 *    - "what" index is what will be used for the value of that input.
580
+	 *
581
+	 * @return void
582
+	 * @throws EE_Error
583
+	 */
584
+	public function do_extra_autosave_stuff()
585
+	{
586
+		// next let's check for the autosave nonce (we'll use _verify_nonce )
587
+		$nonce = isset($this->_req_data['autosavenonce'])
588
+			? $this->_req_data['autosavenonce']
589
+			: null;
590
+		$this->_verify_nonce($nonce, 'autosave');
591
+		// make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
592
+		if (! defined('DOING_AUTOSAVE')) {
593
+			define('DOING_AUTOSAVE', true);
594
+		}
595
+		// if we made it here then the nonce checked out.  Let's run our methods and actions
596
+		$autosave = "_ee_autosave_{$this->_current_view}";
597
+		if (method_exists($this, $autosave)) {
598
+			$this->$autosave();
599
+		} else {
600
+			$this->_template_args['success'] = true;
601
+		}
602
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
603
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
604
+		// now let's return json
605
+		$this->_return_json();
606
+	}
607
+
608
+
609
+	/**
610
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
611
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
612
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
613
+	 *
614
+	 * @access protected
615
+	 * @return void
616
+	 * @throws ReflectionException
617
+	 * @throws EE_Error
618
+	 */
619
+	protected function _extend_page_config_for_cpt()
620
+	{
621
+		// before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
622
+		if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
623
+			return;
624
+		}
625
+		// set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
626
+		if (! empty($this->_cpt_object)) {
627
+			$this->_page_routes = array_merge(
628
+				array(
629
+					'create_new' => '_create_new_cpt_item',
630
+					'edit'       => '_edit_cpt_item',
631
+				),
632
+				$this->_page_routes
633
+			);
634
+			$this->_page_config = array_merge(
635
+				array(
636
+					'create_new' => array(
637
+						'nav'           => array(
638
+							'label' => $this->_cpt_object->labels->add_new_item,
639
+							'order' => 5,
640
+						),
641
+						'require_nonce' => false,
642
+					),
643
+					'edit'       => array(
644
+						'nav'           => array(
645
+							'label'      => $this->_cpt_object->labels->edit_item,
646
+							'order'      => 5,
647
+							'persistent' => false,
648
+							'url'        => '',
649
+						),
650
+						'require_nonce' => false,
651
+					),
652
+				),
653
+				$this->_page_config
654
+			);
655
+		}
656
+		// load the next section only if this is a matching cpt route as set in the cpt routes array.
657
+		if (! isset($this->_cpt_routes[ $this->_req_action ])) {
658
+			return;
659
+		}
660
+		$this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]) ? true : false;
661
+		// add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
662
+		if (empty($this->_cpt_object)) {
663
+			$msg = sprintf(
664
+				__(
665
+					'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
666
+					'event_espresso'
667
+				),
668
+				$this->page_slug,
669
+				$this->_req_action,
670
+				get_class($this)
671
+			);
672
+			throw new EE_Error($msg);
673
+		}
674
+		if ($this->_cpt_route) {
675
+			$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
676
+			$this->_set_model_object($id);
677
+		}
678
+	}
679
+
680
+
681
+	/**
682
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
+	 *
684
+	 * @access protected
685
+	 * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
686
+	 * @param bool   $ignore_route_check
687
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
+	 * @throws EE_Error
689
+	 * @throws InvalidArgumentException
690
+	 * @throws InvalidDataTypeException
691
+	 * @throws InvalidInterfaceException
692
+	 * @throws ReflectionException
693
+	 */
694
+	protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
695
+	{
696
+		$model = null;
697
+		if (empty($this->_cpt_model_names)
698
+			|| (
699
+				! $ignore_route_check
700
+				&& ! isset($this->_cpt_routes[ $this->_req_action ])
701
+			) || (
702
+				$this->_cpt_model_obj instanceof EE_CPT_Base
703
+				&& $this->_cpt_model_obj->ID() === $id
704
+			)
705
+		) {
706
+			// get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
707
+			return;
708
+		}
709
+		// if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
710
+		if ($ignore_route_check) {
711
+			$post_type = get_post_type($id);
712
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
713
+			$custom_post_types = $this->loader->getShared(
714
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
715
+			);
716
+			$model_names = $custom_post_types->getCustomPostTypeModelNames($post_type);
717
+			if (isset($model_names[ $post_type ])) {
718
+				$model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
719
+			}
720
+		} else {
721
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
722
+		}
723
+		if ($model instanceof EEM_Base) {
724
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
725
+		}
726
+		do_action(
727
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
728
+			$this->_cpt_model_obj,
729
+			$req_type
730
+		);
731
+	}
732
+
733
+
734
+	/**
735
+	 * admin_init_global
736
+	 * This runs all the code that we want executed within the WP admin_init hook.
737
+	 * This method executes for ALL EE Admin pages.
738
+	 *
739
+	 * @access public
740
+	 * @return void
741
+	 */
742
+	public function admin_init_global()
743
+	{
744
+		$post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
745
+		// its possible this is a new save so let's catch that instead
746
+		$post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
747
+		$post_type = $post ? $post->post_type : false;
748
+		$current_route = isset($this->_req_data['current_route'])
749
+			? $this->_req_data['current_route']
750
+			: 'shouldneverwork';
751
+		$route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
752
+			? $this->_cpt_routes[ $current_route ]
753
+			: '';
754
+		add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
755
+		add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
756
+		if ($post_type === $route_to_check) {
757
+			add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
758
+		}
759
+		// now let's filter redirect if we're on a revision page and the revision is for an event CPT.
760
+		$revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
761
+		if (! empty($revision)) {
762
+			$action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
763
+			// doing a restore?
764
+			if (! empty($action) && $action === 'restore') {
765
+				// get post for revision
766
+				$rev_post = get_post($revision);
767
+				$rev_parent = get_post($rev_post->post_parent);
768
+				// only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
769
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
770
+					add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
771
+					// restores of revisions
772
+					add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
773
+				}
774
+			}
775
+		}
776
+		// NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
777
+		if ($post_type && $post_type === $route_to_check) {
778
+			// $post_id, $post
779
+			add_action('save_post', array($this, 'insert_update'), 10, 3);
780
+			// $post_id
781
+			add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
782
+			add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
783
+			add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
784
+			add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
785
+		}
786
+	}
787
+
788
+
789
+	/**
790
+	 * Callback for the WordPress trashed_post hook.
791
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
792
+	 *
793
+	 * @param int $post_id
794
+	 * @throws EE_Error
795
+	 * @throws ReflectionException
796
+	 */
797
+	public function before_trash_cpt_item($post_id)
798
+	{
799
+		$this->_set_model_object($post_id, true, 'trash');
800
+		// if our cpt object isn't existent then get out immediately.
801
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
802
+			return;
803
+		}
804
+		$this->trash_cpt_item($post_id);
805
+	}
806
+
807
+
808
+	/**
809
+	 * Callback for the WordPress untrashed_post hook.
810
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
811
+	 *
812
+	 * @param $post_id
813
+	 * @throws EE_Error
814
+	 * @throws ReflectionException
815
+	 */
816
+	public function before_restore_cpt_item($post_id)
817
+	{
818
+		$this->_set_model_object($post_id, true, 'restore');
819
+		// if our cpt object isn't existent then get out immediately.
820
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
821
+			return;
822
+		}
823
+		$this->restore_cpt_item($post_id);
824
+	}
825
+
826
+
827
+	/**
828
+	 * Callback for the WordPress after_delete_post hook.
829
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
830
+	 *
831
+	 * @param $post_id
832
+	 * @throws EE_Error
833
+	 * @throws ReflectionException
834
+	 */
835
+	public function before_delete_cpt_item($post_id)
836
+	{
837
+		$this->_set_model_object($post_id, true, 'delete');
838
+		// if our cpt object isn't existent then get out immediately.
839
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
840
+			return;
841
+		}
842
+		$this->delete_cpt_item($post_id);
843
+	}
844
+
845
+
846
+	/**
847
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
848
+	 * accordingly.
849
+	 *
850
+	 * @return void
851
+	 * @throws EE_Error
852
+	 * @throws InvalidArgumentException
853
+	 * @throws InvalidDataTypeException
854
+	 * @throws InvalidInterfaceException
855
+	 * @throws ReflectionException
856
+	 */
857
+	public function verify_cpt_object()
858
+	{
859
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
860
+		// verify event object
861
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
862
+			throw new EE_Error(
863
+				sprintf(
864
+					__(
865
+						'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
866
+						'event_espresso'
867
+					),
868
+					$label
869
+				)
870
+			);
871
+		}
872
+		// if auto-draft then throw an error
873
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
874
+			EE_Error::overwrite_errors();
875
+			EE_Error::add_error(
876
+				sprintf(
877
+					__(
878
+						'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
879
+						'event_espresso'
880
+					),
881
+					$label
882
+				),
883
+				__FILE__,
884
+				__FUNCTION__,
885
+				__LINE__
886
+			);
887
+		}
888
+	}
889
+
890
+
891
+	/**
892
+	 * admin_footer_scripts_global
893
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
894
+	 * will apply on ALL EE_Admin pages.
895
+	 *
896
+	 * @access public
897
+	 * @return void
898
+	 */
899
+	public function admin_footer_scripts_global()
900
+	{
901
+		$this->_add_admin_page_ajax_loading_img();
902
+		$this->_add_admin_page_overlay();
903
+	}
904
+
905
+
906
+	/**
907
+	 * add in any global scripts for cpt routes
908
+	 *
909
+	 * @return void
910
+	 * @throws EE_Error
911
+	 */
912
+	public function load_global_scripts_styles()
913
+	{
914
+		parent::load_global_scripts_styles();
915
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
916
+			// setup custom post status object for localize script but only if we've got a cpt object
917
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
918
+			if (! empty($statuses)) {
919
+				// get ALL statuses!
920
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
921
+				// setup object
922
+				$ee_cpt_statuses = array();
923
+				foreach ($statuses as $status => $label) {
924
+					$ee_cpt_statuses[ $status ] = array(
925
+						'label'      => $label,
926
+						'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
927
+					);
928
+				}
929
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
930
+			}
931
+		}
932
+	}
933
+
934
+
935
+	/**
936
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
937
+	 * insert/updates
938
+	 *
939
+	 * @param int     $post_id ID of post being updated
940
+	 * @param WP_Post $post    Post object from WP
941
+	 * @param bool    $update  Whether this is an update or a new save.
942
+	 * @return void
943
+	 * @throws EE_Error
944
+	 * @throws ReflectionException
945
+	 */
946
+	public function insert_update($post_id, $post, $update)
947
+	{
948
+		// make sure that if this is a revision OR trash action that we don't do any updates!
949
+		if (isset($this->_req_data['action'])
950
+			&& (
951
+				$this->_req_data['action'] === 'restore'
952
+				|| $this->_req_data['action'] === 'trash'
953
+			)
954
+		) {
955
+			return;
956
+		}
957
+		$this->_set_model_object($post_id, true, 'insert_update');
958
+		// if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
959
+		if ($update
960
+			&& (
961
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
962
+				|| $this->_cpt_model_obj->ID() !== $post_id
963
+			)
964
+		) {
965
+			return;
966
+		}
967
+		// check for autosave and update our req_data property accordingly.
968
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
969 969
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
970 970
 
971 971
                 foreach ( (array) $values as $key => $value ) {
@@ -975,537 +975,537 @@  discard block
 block discarded – undo
975 975
 
976 976
         }/**/ // TODO reactivate after autosave is implemented in 4.2
977 977
 
978
-        // take care of updating any selected page_template IF this cpt supports it.
979
-        if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
980
-            // wp version aware.
981
-            if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
982
-                $page_templates = wp_get_theme()->get_page_templates();
983
-            } else {
984
-                $post->page_template = $this->_req_data['page_template'];
985
-                $page_templates = wp_get_theme()->get_page_templates($post);
986
-            }
987
-            if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[ $this->_req_data['page_template'] ])) {
988
-                EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
989
-            } else {
990
-                update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
991
-            }
992
-        }
993
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
994
-            return;
995
-        } //TODO we'll remove this after reimplementing autosave in 4.2
996
-        $this->_insert_update_cpt_item($post_id, $post);
997
-    }
998
-
999
-
1000
-    /**
1001
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1002
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1003
-     * so we don't have to check for our CPT.
1004
-     *
1005
-     * @param  int $post_id ID of the post
1006
-     * @return void
1007
-     */
1008
-    public function dont_permanently_delete_ee_cpts($post_id)
1009
-    {
1010
-        // only do this if we're actually processing one of our CPTs
1011
-        // if our cpt object isn't existent then get out immediately.
1012
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1013
-            return;
1014
-        }
1015
-        delete_post_meta($post_id, '_wp_trash_meta_status');
1016
-        delete_post_meta($post_id, '_wp_trash_meta_time');
1017
-        // our cpts may have comments so let's take care of that too
1018
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1024
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1025
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1026
-     *
1027
-     * @param  int $post_id     ID of cpt item
1028
-     * @param  int $revision_id ID of revision being restored
1029
-     * @return void
1030
-     */
1031
-    public function restore_revision($post_id, $revision_id)
1032
-    {
1033
-        $this->_restore_cpt_item($post_id, $revision_id);
1034
-        // global action
1035
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1036
-        // class specific action so you can limit hooking into a specific page.
1037
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1038
-    }
1039
-
1040
-
1041
-    /**
1042
-     * @see restore_revision() for details
1043
-     * @param  int $post_id     ID of cpt item
1044
-     * @param  int $revision_id ID of revision for item
1045
-     * @return void
1046
-     */
1047
-    abstract protected function _restore_cpt_item($post_id, $revision_id);
1048
-
1049
-
1050
-    /**
1051
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1052
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1053
-     * To fix we have to reset the current_screen using the page_slug
1054
-     * (which is identical - or should be - to our registered_post_type id.)
1055
-     * Also, since the core WP file loads the admin_header.php for WP
1056
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1057
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1058
-     *
1059
-     * @return void
1060
-     * @throws EE_Error
1061
-     */
1062
-    public function modify_current_screen()
1063
-    {
1064
-        // ONLY do this if the current page_route IS a cpt route
1065
-        if (! $this->_cpt_route) {
1066
-            return;
1067
-        }
1068
-        // routing things REALLY early b/c this is a cpt admin page
1069
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1070
-        $this->_current_screen = get_current_screen();
1071
-        $this->_current_screen->base = 'event-espresso';
1072
-        $this->_add_help_tabs(); // we make sure we add any help tabs back in!
1073
-        /*try {
978
+		// take care of updating any selected page_template IF this cpt supports it.
979
+		if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
980
+			// wp version aware.
981
+			if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
982
+				$page_templates = wp_get_theme()->get_page_templates();
983
+			} else {
984
+				$post->page_template = $this->_req_data['page_template'];
985
+				$page_templates = wp_get_theme()->get_page_templates($post);
986
+			}
987
+			if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[ $this->_req_data['page_template'] ])) {
988
+				EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
989
+			} else {
990
+				update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
991
+			}
992
+		}
993
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
994
+			return;
995
+		} //TODO we'll remove this after reimplementing autosave in 4.2
996
+		$this->_insert_update_cpt_item($post_id, $post);
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1002
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1003
+	 * so we don't have to check for our CPT.
1004
+	 *
1005
+	 * @param  int $post_id ID of the post
1006
+	 * @return void
1007
+	 */
1008
+	public function dont_permanently_delete_ee_cpts($post_id)
1009
+	{
1010
+		// only do this if we're actually processing one of our CPTs
1011
+		// if our cpt object isn't existent then get out immediately.
1012
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1013
+			return;
1014
+		}
1015
+		delete_post_meta($post_id, '_wp_trash_meta_status');
1016
+		delete_post_meta($post_id, '_wp_trash_meta_time');
1017
+		// our cpts may have comments so let's take care of that too
1018
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1024
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1025
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1026
+	 *
1027
+	 * @param  int $post_id     ID of cpt item
1028
+	 * @param  int $revision_id ID of revision being restored
1029
+	 * @return void
1030
+	 */
1031
+	public function restore_revision($post_id, $revision_id)
1032
+	{
1033
+		$this->_restore_cpt_item($post_id, $revision_id);
1034
+		// global action
1035
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1036
+		// class specific action so you can limit hooking into a specific page.
1037
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1038
+	}
1039
+
1040
+
1041
+	/**
1042
+	 * @see restore_revision() for details
1043
+	 * @param  int $post_id     ID of cpt item
1044
+	 * @param  int $revision_id ID of revision for item
1045
+	 * @return void
1046
+	 */
1047
+	abstract protected function _restore_cpt_item($post_id, $revision_id);
1048
+
1049
+
1050
+	/**
1051
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1052
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1053
+	 * To fix we have to reset the current_screen using the page_slug
1054
+	 * (which is identical - or should be - to our registered_post_type id.)
1055
+	 * Also, since the core WP file loads the admin_header.php for WP
1056
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1057
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1058
+	 *
1059
+	 * @return void
1060
+	 * @throws EE_Error
1061
+	 */
1062
+	public function modify_current_screen()
1063
+	{
1064
+		// ONLY do this if the current page_route IS a cpt route
1065
+		if (! $this->_cpt_route) {
1066
+			return;
1067
+		}
1068
+		// routing things REALLY early b/c this is a cpt admin page
1069
+		set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1070
+		$this->_current_screen = get_current_screen();
1071
+		$this->_current_screen->base = 'event-espresso';
1072
+		$this->_add_help_tabs(); // we make sure we add any help tabs back in!
1073
+		/*try {
1074 1074
             $this->_route_admin_request();
1075 1075
         } catch ( EE_Error $e ) {
1076 1076
             $e->get_error();
1077 1077
         }/**/
1078
-    }
1079
-
1080
-
1081
-    /**
1082
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1083
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1084
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1085
-     * default to be.
1086
-     *
1087
-     * @param string $title The new title (or existing if there is no editor_title defined)
1088
-     * @return string
1089
-     */
1090
-    public function add_custom_editor_default_title($title)
1091
-    {
1092
-        return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1093
-            ? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1094
-            : $title;
1095
-    }
1096
-
1097
-
1098
-    /**
1099
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1100
-     *
1101
-     * @param string $shortlink   The already generated shortlink
1102
-     * @param int    $id          Post ID for this item
1103
-     * @param string $context     The context for the link
1104
-     * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1105
-     * @return string
1106
-     */
1107
-    public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1108
-    {
1109
-        if (! empty($id) && get_option('permalink_structure') !== '') {
1110
-            $post = get_post($id);
1111
-            if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1112
-                $shortlink = home_url('?p=' . $post->ID);
1113
-            }
1114
-        }
1115
-        return $shortlink;
1116
-    }
1117
-
1118
-
1119
-    /**
1120
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1121
-     * already run in modify_current_screen())
1122
-     *
1123
-     * @return void
1124
-     * @throws EE_Error
1125
-     * @throws ReflectionException
1126
-     */
1127
-    public function route_admin_request()
1128
-    {
1129
-        if ($this->_cpt_route) {
1130
-            return;
1131
-        }
1132
-        try {
1133
-            $this->_route_admin_request();
1134
-        } catch (EE_Error $e) {
1135
-            $e->get_error();
1136
-        }
1137
-    }
1138
-
1139
-
1140
-    /**
1141
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1142
-     *
1143
-     * @return void
1144
-     */
1145
-    public function cpt_post_form_hidden_input()
1146
-    {
1147
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1148
-        // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1149
-        echo '<div id="ee-cpt-hidden-inputs">';
1150
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1151
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1152
-        echo '</div>';
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1158
-     *
1159
-     * @param string $location Original location url
1160
-     * @param int    $status   Status for http header
1161
-     * @return string           new (or original) url to redirect to.
1162
-     * @throws EE_Error
1163
-     */
1164
-    public function revision_redirect($location, $status)
1165
-    {
1166
-        // get revision
1167
-        $rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1168
-        // can't do anything without revision so let's get out if not present
1169
-        if (empty($rev_id)) {
1170
-            return $location;
1171
-        }
1172
-        // get rev_post_data
1173
-        $rev = get_post($rev_id);
1174
-        $admin_url = $this->_admin_base_url;
1175
-        $query_args = array(
1176
-            'action'   => 'edit',
1177
-            'post'     => $rev->post_parent,
1178
-            'revision' => $rev_id,
1179
-            'message'  => 5,
1180
-        );
1181
-        $this->_process_notices($query_args, true);
1182
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1188
-     *
1189
-     * @param  string $link    the original generated link
1190
-     * @param  int    $id      post id
1191
-     * @param  string $context optional, defaults to display.  How to write the '&'
1192
-     * @return string          the link
1193
-     */
1194
-    public function modify_edit_post_link($link, $id, $context)
1195
-    {
1196
-        $post = get_post($id);
1197
-        if (! isset($this->_req_data['action'])
1198
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1199
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1200
-        ) {
1201
-            return $link;
1202
-        }
1203
-        $query_args = array(
1204
-            'action' => isset($this->_cpt_edit_routes[ $post->post_type ])
1205
-                ? $this->_cpt_edit_routes[ $post->post_type ]
1206
-                : 'edit',
1207
-            'post'   => $id,
1208
-        );
1209
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1215
-     * our routes.
1216
-     *
1217
-     * @param string $delete_link  original delete link
1218
-     * @param int    $post_id      id of cpt object
1219
-     * @param bool   $force_delete whether this is forcing a hard delete instead of trash
1220
-     * @return string new delete link
1221
-     * @throws EE_Error
1222
-     * @throws ReflectionException
1223
-     */
1224
-    public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1225
-    {
1226
-        $post = get_post($post_id);
1227
-
1228
-        if (empty($this->_req_data['action'])
1229
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1230
-            || ! $post instanceof WP_Post
1231
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1232
-        ) {
1233
-            return $delete_link;
1234
-        }
1235
-        $this->_set_model_object($post->ID, true);
1236
-
1237
-        // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1238
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1239
-
1240
-        return EE_Admin_Page::add_query_args_and_nonce(
1241
-            array(
1242
-                'page'   => $this->_req_data['page'],
1243
-                'action' => $action,
1244
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1245
-                         => $post->ID,
1246
-            ),
1247
-            admin_url()
1248
-        );
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1254
-     * so that we can hijack the default redirect locations for wp custom post types
1255
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1256
-     *
1257
-     * @param string $location This is the incoming currently set redirect location
1258
-     * @param string $post_id  This is the 'ID' value of the wp_posts table
1259
-     * @return string           the new location to redirect to
1260
-     * @throws EE_Error
1261
-     */
1262
-    public function cpt_post_location_redirect($location, $post_id)
1263
-    {
1264
-        // we DO have a match so let's setup the url
1265
-        // we have to get the post to determine our route
1266
-        $post = get_post($post_id);
1267
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1268
-        // shared query_args
1269
-        $query_args = array('action' => $edit_route, 'post' => $post_id);
1270
-        $admin_url = $this->_admin_base_url;
1271
-        if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1272
-            $status = get_post_status($post_id);
1273
-            if (isset($this->_req_data['publish'])) {
1274
-                switch ($status) {
1275
-                    case 'pending':
1276
-                        $message = 8;
1277
-                        break;
1278
-                    case 'future':
1279
-                        $message = 9;
1280
-                        break;
1281
-                    default:
1282
-                        $message = 6;
1283
-                }
1284
-            } else {
1285
-                $message = 'draft' === $status ? 10 : 1;
1286
-            }
1287
-        } elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1288
-            $message = 2;
1289
-        } elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1290
-            $message = 3;
1291
-        } elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1292
-            $message = 7;
1293
-        } else {
1294
-            $message = 4;
1295
-        }
1296
-        // change the message if the post type is not viewable on the frontend
1297
-        $this->_cpt_object = get_post_type_object($post->post_type);
1298
-        $message = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1299
-        $query_args = array_merge(array('message' => $message), $query_args);
1300
-        $this->_process_notices($query_args, true);
1301
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1302
-    }
1303
-
1304
-
1305
-    /**
1306
-     * This method is called to inject nav tabs on core WP cpt pages
1307
-     *
1308
-     * @access public
1309
-     * @return void
1310
-     * @throws EE_Error
1311
-     */
1312
-    public function inject_nav_tabs()
1313
-    {
1314
-        // can we hijack and insert the nav_tabs?
1315
-        $nav_tabs = $this->_get_main_nav_tabs();
1316
-        // first close off existing form tag
1317
-        $html = '>';
1318
-        $html .= $nav_tabs;
1319
-        // now let's handle the remaining tag ( missing ">" is CORRECT )
1320
-        $html .= '<span></span';
1321
-        echo $html;
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * This just sets up the post update messages when an update form is loaded
1327
-     *
1328
-     * @access public
1329
-     * @param  array $messages the original messages array
1330
-     * @return array           the new messages array
1331
-     */
1332
-    public function post_update_messages($messages)
1333
-    {
1334
-        global $post;
1335
-        $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1336
-        $id = empty($id) && is_object($post) ? $post->ID : null;
1337
-        /*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1078
+	}
1079
+
1080
+
1081
+	/**
1082
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1083
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1084
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1085
+	 * default to be.
1086
+	 *
1087
+	 * @param string $title The new title (or existing if there is no editor_title defined)
1088
+	 * @return string
1089
+	 */
1090
+	public function add_custom_editor_default_title($title)
1091
+	{
1092
+		return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1093
+			? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1094
+			: $title;
1095
+	}
1096
+
1097
+
1098
+	/**
1099
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1100
+	 *
1101
+	 * @param string $shortlink   The already generated shortlink
1102
+	 * @param int    $id          Post ID for this item
1103
+	 * @param string $context     The context for the link
1104
+	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1105
+	 * @return string
1106
+	 */
1107
+	public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1108
+	{
1109
+		if (! empty($id) && get_option('permalink_structure') !== '') {
1110
+			$post = get_post($id);
1111
+			if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1112
+				$shortlink = home_url('?p=' . $post->ID);
1113
+			}
1114
+		}
1115
+		return $shortlink;
1116
+	}
1117
+
1118
+
1119
+	/**
1120
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1121
+	 * already run in modify_current_screen())
1122
+	 *
1123
+	 * @return void
1124
+	 * @throws EE_Error
1125
+	 * @throws ReflectionException
1126
+	 */
1127
+	public function route_admin_request()
1128
+	{
1129
+		if ($this->_cpt_route) {
1130
+			return;
1131
+		}
1132
+		try {
1133
+			$this->_route_admin_request();
1134
+		} catch (EE_Error $e) {
1135
+			$e->get_error();
1136
+		}
1137
+	}
1138
+
1139
+
1140
+	/**
1141
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1142
+	 *
1143
+	 * @return void
1144
+	 */
1145
+	public function cpt_post_form_hidden_input()
1146
+	{
1147
+		echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1148
+		// we're also going to add the route value and the current page so we can direct autosave parsing correctly
1149
+		echo '<div id="ee-cpt-hidden-inputs">';
1150
+		echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1151
+		echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1152
+		echo '</div>';
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1158
+	 *
1159
+	 * @param string $location Original location url
1160
+	 * @param int    $status   Status for http header
1161
+	 * @return string           new (or original) url to redirect to.
1162
+	 * @throws EE_Error
1163
+	 */
1164
+	public function revision_redirect($location, $status)
1165
+	{
1166
+		// get revision
1167
+		$rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1168
+		// can't do anything without revision so let's get out if not present
1169
+		if (empty($rev_id)) {
1170
+			return $location;
1171
+		}
1172
+		// get rev_post_data
1173
+		$rev = get_post($rev_id);
1174
+		$admin_url = $this->_admin_base_url;
1175
+		$query_args = array(
1176
+			'action'   => 'edit',
1177
+			'post'     => $rev->post_parent,
1178
+			'revision' => $rev_id,
1179
+			'message'  => 5,
1180
+		);
1181
+		$this->_process_notices($query_args, true);
1182
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1188
+	 *
1189
+	 * @param  string $link    the original generated link
1190
+	 * @param  int    $id      post id
1191
+	 * @param  string $context optional, defaults to display.  How to write the '&'
1192
+	 * @return string          the link
1193
+	 */
1194
+	public function modify_edit_post_link($link, $id, $context)
1195
+	{
1196
+		$post = get_post($id);
1197
+		if (! isset($this->_req_data['action'])
1198
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1199
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1200
+		) {
1201
+			return $link;
1202
+		}
1203
+		$query_args = array(
1204
+			'action' => isset($this->_cpt_edit_routes[ $post->post_type ])
1205
+				? $this->_cpt_edit_routes[ $post->post_type ]
1206
+				: 'edit',
1207
+			'post'   => $id,
1208
+		);
1209
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1215
+	 * our routes.
1216
+	 *
1217
+	 * @param string $delete_link  original delete link
1218
+	 * @param int    $post_id      id of cpt object
1219
+	 * @param bool   $force_delete whether this is forcing a hard delete instead of trash
1220
+	 * @return string new delete link
1221
+	 * @throws EE_Error
1222
+	 * @throws ReflectionException
1223
+	 */
1224
+	public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1225
+	{
1226
+		$post = get_post($post_id);
1227
+
1228
+		if (empty($this->_req_data['action'])
1229
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1230
+			|| ! $post instanceof WP_Post
1231
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1232
+		) {
1233
+			return $delete_link;
1234
+		}
1235
+		$this->_set_model_object($post->ID, true);
1236
+
1237
+		// returns something like `trash_event` or `trash_attendee` or `trash_venue`
1238
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1239
+
1240
+		return EE_Admin_Page::add_query_args_and_nonce(
1241
+			array(
1242
+				'page'   => $this->_req_data['page'],
1243
+				'action' => $action,
1244
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1245
+						 => $post->ID,
1246
+			),
1247
+			admin_url()
1248
+		);
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1254
+	 * so that we can hijack the default redirect locations for wp custom post types
1255
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1256
+	 *
1257
+	 * @param string $location This is the incoming currently set redirect location
1258
+	 * @param string $post_id  This is the 'ID' value of the wp_posts table
1259
+	 * @return string           the new location to redirect to
1260
+	 * @throws EE_Error
1261
+	 */
1262
+	public function cpt_post_location_redirect($location, $post_id)
1263
+	{
1264
+		// we DO have a match so let's setup the url
1265
+		// we have to get the post to determine our route
1266
+		$post = get_post($post_id);
1267
+		$edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1268
+		// shared query_args
1269
+		$query_args = array('action' => $edit_route, 'post' => $post_id);
1270
+		$admin_url = $this->_admin_base_url;
1271
+		if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1272
+			$status = get_post_status($post_id);
1273
+			if (isset($this->_req_data['publish'])) {
1274
+				switch ($status) {
1275
+					case 'pending':
1276
+						$message = 8;
1277
+						break;
1278
+					case 'future':
1279
+						$message = 9;
1280
+						break;
1281
+					default:
1282
+						$message = 6;
1283
+				}
1284
+			} else {
1285
+				$message = 'draft' === $status ? 10 : 1;
1286
+			}
1287
+		} elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1288
+			$message = 2;
1289
+		} elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1290
+			$message = 3;
1291
+		} elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1292
+			$message = 7;
1293
+		} else {
1294
+			$message = 4;
1295
+		}
1296
+		// change the message if the post type is not viewable on the frontend
1297
+		$this->_cpt_object = get_post_type_object($post->post_type);
1298
+		$message = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1299
+		$query_args = array_merge(array('message' => $message), $query_args);
1300
+		$this->_process_notices($query_args, true);
1301
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1302
+	}
1303
+
1304
+
1305
+	/**
1306
+	 * This method is called to inject nav tabs on core WP cpt pages
1307
+	 *
1308
+	 * @access public
1309
+	 * @return void
1310
+	 * @throws EE_Error
1311
+	 */
1312
+	public function inject_nav_tabs()
1313
+	{
1314
+		// can we hijack and insert the nav_tabs?
1315
+		$nav_tabs = $this->_get_main_nav_tabs();
1316
+		// first close off existing form tag
1317
+		$html = '>';
1318
+		$html .= $nav_tabs;
1319
+		// now let's handle the remaining tag ( missing ">" is CORRECT )
1320
+		$html .= '<span></span';
1321
+		echo $html;
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * This just sets up the post update messages when an update form is loaded
1327
+	 *
1328
+	 * @access public
1329
+	 * @param  array $messages the original messages array
1330
+	 * @return array           the new messages array
1331
+	 */
1332
+	public function post_update_messages($messages)
1333
+	{
1334
+		global $post;
1335
+		$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1336
+		$id = empty($id) && is_object($post) ? $post->ID : null;
1337
+		/*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1338 1338
 
1339 1339
         $route_to_check = $post_type && isset( $this->_cpt_routes[$current_route]) ? $this->_cpt_routes[$current_route] : '';/**/
1340
-        $messages[ $post->post_type ] = array(
1341
-            0  => '', // Unused. Messages start at index 1.
1342
-            1  => sprintf(
1343
-                __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1344
-                $this->_cpt_object->labels->singular_name,
1345
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1346
-                '</a>'
1347
-            ),
1348
-            2  => __('Custom field updated', 'event_espresso'),
1349
-            3  => __('Custom field deleted.', 'event_espresso'),
1350
-            4  => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1351
-            5  => isset($_GET['revision']) ? sprintf(
1352
-                __('%s restored to revision from %s', 'event_espresso'),
1353
-                $this->_cpt_object->labels->singular_name,
1354
-                wp_post_revision_title((int) $_GET['revision'], false)
1355
-            )
1356
-                : false,
1357
-            6  => sprintf(
1358
-                __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1359
-                $this->_cpt_object->labels->singular_name,
1360
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1361
-                '</a>'
1362
-            ),
1363
-            7  => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1364
-            8  => sprintf(
1365
-                __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1366
-                $this->_cpt_object->labels->singular_name,
1367
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1368
-                '</a>'
1369
-            ),
1370
-            9  => sprintf(
1371
-                __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1372
-                $this->_cpt_object->labels->singular_name,
1373
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1374
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1375
-                '</a>'
1376
-            ),
1377
-            10 => sprintf(
1378
-                __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1379
-                $this->_cpt_object->labels->singular_name,
1380
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1381
-                '</a>'
1382
-            ),
1383
-        );
1384
-        return $messages;
1385
-    }
1386
-
1387
-
1388
-    /**
1389
-     * default method for the 'create_new' route for cpt admin pages.
1390
-     * For reference what to include in here, see wp-admin/post-new.php
1391
-     *
1392
-     * @access  protected
1393
-     * @return void
1394
-     */
1395
-    protected function _create_new_cpt_item()
1396
-    {
1397
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1398
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1399
-        $post_type = $this->_cpt_routes[ $this->_req_action ];
1400
-        $post_type_object = $this->_cpt_object;
1401
-        $title = $post_type_object->labels->add_new_item;
1402
-        $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1403
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1404
-        // modify the default editor title field with default title.
1405
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1406
-        $this->loadEditorTemplate(true);
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * Enqueues auto-save and loads the editor template
1412
-     *
1413
-     * @param bool $creating
1414
-     */
1415
-    private function loadEditorTemplate($creating = true)
1416
-    {
1417
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1418
-        // these vars are used by the template
1419
-        $editing = true;
1420
-        $post_ID = $post->ID;
1421
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1422
-            // only enqueue autosave when creating event (necessary to get permalink/url generated)
1423
-            // otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1424
-            if ($creating) {
1425
-                wp_enqueue_script('autosave');
1426
-            } elseif (isset($this->_cpt_routes[ $this->_req_data['action'] ])
1427
-                && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1428
-            ) {
1429
-                $create_new_action = apply_filters(
1430
-                    'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1431
-                    'create_new',
1432
-                    $this
1433
-                );
1434
-                $post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1435
-                    array(
1436
-                        'action' => $create_new_action,
1437
-                        'page'   => $this->page_slug,
1438
-                    ),
1439
-                    'admin.php'
1440
-                );
1441
-            }
1442
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1443
-        }
1444
-    }
1445
-
1446
-
1447
-    public function add_new_admin_page_global()
1448
-    {
1449
-        $admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1450
-        ?>
1340
+		$messages[ $post->post_type ] = array(
1341
+			0  => '', // Unused. Messages start at index 1.
1342
+			1  => sprintf(
1343
+				__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1344
+				$this->_cpt_object->labels->singular_name,
1345
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1346
+				'</a>'
1347
+			),
1348
+			2  => __('Custom field updated', 'event_espresso'),
1349
+			3  => __('Custom field deleted.', 'event_espresso'),
1350
+			4  => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1351
+			5  => isset($_GET['revision']) ? sprintf(
1352
+				__('%s restored to revision from %s', 'event_espresso'),
1353
+				$this->_cpt_object->labels->singular_name,
1354
+				wp_post_revision_title((int) $_GET['revision'], false)
1355
+			)
1356
+				: false,
1357
+			6  => sprintf(
1358
+				__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1359
+				$this->_cpt_object->labels->singular_name,
1360
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1361
+				'</a>'
1362
+			),
1363
+			7  => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1364
+			8  => sprintf(
1365
+				__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1366
+				$this->_cpt_object->labels->singular_name,
1367
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1368
+				'</a>'
1369
+			),
1370
+			9  => sprintf(
1371
+				__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1372
+				$this->_cpt_object->labels->singular_name,
1373
+				'<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1374
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1375
+				'</a>'
1376
+			),
1377
+			10 => sprintf(
1378
+				__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1379
+				$this->_cpt_object->labels->singular_name,
1380
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1381
+				'</a>'
1382
+			),
1383
+		);
1384
+		return $messages;
1385
+	}
1386
+
1387
+
1388
+	/**
1389
+	 * default method for the 'create_new' route for cpt admin pages.
1390
+	 * For reference what to include in here, see wp-admin/post-new.php
1391
+	 *
1392
+	 * @access  protected
1393
+	 * @return void
1394
+	 */
1395
+	protected function _create_new_cpt_item()
1396
+	{
1397
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1398
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1399
+		$post_type = $this->_cpt_routes[ $this->_req_action ];
1400
+		$post_type_object = $this->_cpt_object;
1401
+		$title = $post_type_object->labels->add_new_item;
1402
+		$post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1403
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1404
+		// modify the default editor title field with default title.
1405
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1406
+		$this->loadEditorTemplate(true);
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * Enqueues auto-save and loads the editor template
1412
+	 *
1413
+	 * @param bool $creating
1414
+	 */
1415
+	private function loadEditorTemplate($creating = true)
1416
+	{
1417
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1418
+		// these vars are used by the template
1419
+		$editing = true;
1420
+		$post_ID = $post->ID;
1421
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1422
+			// only enqueue autosave when creating event (necessary to get permalink/url generated)
1423
+			// otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1424
+			if ($creating) {
1425
+				wp_enqueue_script('autosave');
1426
+			} elseif (isset($this->_cpt_routes[ $this->_req_data['action'] ])
1427
+				&& ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1428
+			) {
1429
+				$create_new_action = apply_filters(
1430
+					'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1431
+					'create_new',
1432
+					$this
1433
+				);
1434
+				$post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1435
+					array(
1436
+						'action' => $create_new_action,
1437
+						'page'   => $this->page_slug,
1438
+					),
1439
+					'admin.php'
1440
+				);
1441
+			}
1442
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1443
+		}
1444
+	}
1445
+
1446
+
1447
+	public function add_new_admin_page_global()
1448
+	{
1449
+		$admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1450
+		?>
1451 1451
         <script type="text/javascript">
1452 1452
             adminpage = '<?php echo $admin_page; ?>';
1453 1453
         </script>
1454 1454
         <?php
1455
-    }
1456
-
1457
-
1458
-    /**
1459
-     * default method for the 'edit' route for cpt admin pages
1460
-     * For reference on what to put in here, refer to wp-admin/post.php
1461
-     *
1462
-     * @access protected
1463
-     * @return string   template for edit cpt form
1464
-     */
1465
-    protected function _edit_cpt_item()
1466
-    {
1467
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1468
-        $post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1469
-        $post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1470
-        if (empty($post)) {
1471
-            wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?', 'event_espresso'));
1472
-        }
1473
-        if (! empty($_GET['get-post-lock'])) {
1474
-            wp_set_post_lock($post_id);
1475
-            wp_redirect(get_edit_post_link($post_id, 'url'));
1476
-            exit();
1477
-        }
1478
-
1479
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1480
-        $post_type = $this->_cpt_routes[ $this->_req_action ];
1481
-        $post_type_object = $this->_cpt_object;
1482
-
1483
-        if (! wp_check_post_lock($post->ID)) {
1484
-            wp_set_post_lock($post->ID);
1485
-        }
1486
-        add_action('admin_footer', '_admin_notice_post_locked');
1487
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1488
-            wp_enqueue_script('admin-comments');
1489
-            enqueue_comment_hotkeys_js();
1490
-        }
1491
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1492
-        // modify the default editor title field with default title.
1493
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1494
-        $this->loadEditorTemplate(false);
1495
-    }
1496
-
1497
-
1498
-
1499
-    /**
1500
-     * some getters
1501
-     */
1502
-    /**
1503
-     * This returns the protected _cpt_model_obj property
1504
-     *
1505
-     * @return EE_CPT_Base
1506
-     */
1507
-    public function get_cpt_model_obj()
1508
-    {
1509
-        return $this->_cpt_model_obj;
1510
-    }
1455
+	}
1456
+
1457
+
1458
+	/**
1459
+	 * default method for the 'edit' route for cpt admin pages
1460
+	 * For reference on what to put in here, refer to wp-admin/post.php
1461
+	 *
1462
+	 * @access protected
1463
+	 * @return string   template for edit cpt form
1464
+	 */
1465
+	protected function _edit_cpt_item()
1466
+	{
1467
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1468
+		$post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1469
+		$post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1470
+		if (empty($post)) {
1471
+			wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?', 'event_espresso'));
1472
+		}
1473
+		if (! empty($_GET['get-post-lock'])) {
1474
+			wp_set_post_lock($post_id);
1475
+			wp_redirect(get_edit_post_link($post_id, 'url'));
1476
+			exit();
1477
+		}
1478
+
1479
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1480
+		$post_type = $this->_cpt_routes[ $this->_req_action ];
1481
+		$post_type_object = $this->_cpt_object;
1482
+
1483
+		if (! wp_check_post_lock($post->ID)) {
1484
+			wp_set_post_lock($post->ID);
1485
+		}
1486
+		add_action('admin_footer', '_admin_notice_post_locked');
1487
+		if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1488
+			wp_enqueue_script('admin-comments');
1489
+			enqueue_comment_hotkeys_js();
1490
+		}
1491
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1492
+		// modify the default editor title field with default title.
1493
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1494
+		$this->loadEditorTemplate(false);
1495
+	}
1496
+
1497
+
1498
+
1499
+	/**
1500
+	 * some getters
1501
+	 */
1502
+	/**
1503
+	 * This returns the protected _cpt_model_obj property
1504
+	 *
1505
+	 * @return EE_CPT_Base
1506
+	 */
1507
+	public function get_cpt_model_obj()
1508
+	{
1509
+		return $this->_cpt_model_obj;
1510
+	}
1511 1511
 }
Please login to merge, or discard this patch.
core/domain/services/assets/LegacyAccountingAssetManager.php 2 patches
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -24,113 +24,113 @@
 block discarded – undo
24 24
 class LegacyAccountingAssetManager extends AssetManager
25 25
 {
26 26
 
27
-    const JS_HANDLE_UNDERSCORE = 'underscore';
28
-
29
-    const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
30
-
31
-    const JS_HANDLE_ACCOUNTING = 'ee-accounting';
32
-
33
-
34
-    /**
35
-     * @var EE_Currency_Config $currency_config
36
-     */
37
-    protected $currency_config;
38
-
39
-    /**
40
-     * CoreAssetRegister constructor.
41
-     *
42
-     * @param AssetCollection    $assets
43
-     * @param DomainInterface    $domain
44
-     * @param Registry           $registry
45
-     * @param EE_Currency_Config $currency_config
46
-     */
47
-    public function __construct(
48
-        AssetCollection $assets,
49
-        DomainInterface $domain,
50
-        Registry $registry,
51
-        EE_Currency_Config $currency_config
52
-    ) {
53
-        $this->currency_config = $currency_config;
54
-        parent::__construct($domain, $assets, $registry);
55
-    }
56
-
57
-
58
-
59
-    /**
60
-     * @throws InvalidDataTypeException
61
-     * @throws InvalidEntityException
62
-     * @throws DuplicateCollectionIdentifierException
63
-     * @throws DomainException
64
-     */
65
-    public function addAssets()
66
-    {
67
-        $this->loadAccountingJs();
68
-    }
69
-
70
-
71
-    /**
72
-     * accounting.js for performing client-side calculations
73
-     *
74
-     * @throws DomainException
75
-     * @throws DuplicateCollectionIdentifierException
76
-     * @throws InvalidDataTypeException
77
-     * @throws InvalidEntityException
78
-     * @since $VID:$
79
-     */
80
-    private function loadAccountingJs()
81
-    {
82
-        //accounting.js library
83
-        // @link http://josscrowcroft.github.io/accounting.js/
84
-        $this->addJavascript(
85
-            LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE,
86
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
87
-            [LegacyAccountingAssetManager::JS_HANDLE_UNDERSCORE],
88
-            true,
89
-            '0.3.2'
90
-        );
91
-
92
-        $this->addJavascript(
93
-            LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
94
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
95
-            [LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE]
96
-        )
97
-             ->setInlineDataCallback(
98
-                 function () {
99
-                     wp_localize_script(
100
-                         LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
101
-                         'EE_ACCOUNTING_CFG',
102
-                         $this->getAccountingSettings()
103
-                     );
104
-                 }
105
-             );
106
-    }
107
-
108
-
109
-    /**
110
-     * Returns configuration data for the accounting-js library.
111
-     *
112
-     * @return array
113
-     * @since $VID:$
114
-     */
115
-    private function getAccountingSettings()
116
-    {
117
-        return [
118
-            'currency' => [
119
-                'symbol'    => $this->currency_config->sign,
120
-                'format'    => [
121
-                    'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
122
-                    'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
123
-                    'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
124
-                ],
125
-                'decimal'   => $this->currency_config->dec_mrk,
126
-                'thousand'  => $this->currency_config->thsnds,
127
-                'precision' => $this->currency_config->dec_plc,
128
-            ],
129
-            'number'   => [
130
-                'precision' => $this->currency_config->dec_plc,
131
-                'thousand'  => $this->currency_config->thsnds,
132
-                'decimal'   => $this->currency_config->dec_mrk,
133
-            ],
134
-        ];
135
-    }
27
+	const JS_HANDLE_UNDERSCORE = 'underscore';
28
+
29
+	const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
30
+
31
+	const JS_HANDLE_ACCOUNTING = 'ee-accounting';
32
+
33
+
34
+	/**
35
+	 * @var EE_Currency_Config $currency_config
36
+	 */
37
+	protected $currency_config;
38
+
39
+	/**
40
+	 * CoreAssetRegister constructor.
41
+	 *
42
+	 * @param AssetCollection    $assets
43
+	 * @param DomainInterface    $domain
44
+	 * @param Registry           $registry
45
+	 * @param EE_Currency_Config $currency_config
46
+	 */
47
+	public function __construct(
48
+		AssetCollection $assets,
49
+		DomainInterface $domain,
50
+		Registry $registry,
51
+		EE_Currency_Config $currency_config
52
+	) {
53
+		$this->currency_config = $currency_config;
54
+		parent::__construct($domain, $assets, $registry);
55
+	}
56
+
57
+
58
+
59
+	/**
60
+	 * @throws InvalidDataTypeException
61
+	 * @throws InvalidEntityException
62
+	 * @throws DuplicateCollectionIdentifierException
63
+	 * @throws DomainException
64
+	 */
65
+	public function addAssets()
66
+	{
67
+		$this->loadAccountingJs();
68
+	}
69
+
70
+
71
+	/**
72
+	 * accounting.js for performing client-side calculations
73
+	 *
74
+	 * @throws DomainException
75
+	 * @throws DuplicateCollectionIdentifierException
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws InvalidEntityException
78
+	 * @since $VID:$
79
+	 */
80
+	private function loadAccountingJs()
81
+	{
82
+		//accounting.js library
83
+		// @link http://josscrowcroft.github.io/accounting.js/
84
+		$this->addJavascript(
85
+			LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE,
86
+			EE_THIRD_PARTY_URL . 'accounting/accounting.js',
87
+			[LegacyAccountingAssetManager::JS_HANDLE_UNDERSCORE],
88
+			true,
89
+			'0.3.2'
90
+		);
91
+
92
+		$this->addJavascript(
93
+			LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
94
+			EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
95
+			[LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE]
96
+		)
97
+			 ->setInlineDataCallback(
98
+				 function () {
99
+					 wp_localize_script(
100
+						 LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
101
+						 'EE_ACCOUNTING_CFG',
102
+						 $this->getAccountingSettings()
103
+					 );
104
+				 }
105
+			 );
106
+	}
107
+
108
+
109
+	/**
110
+	 * Returns configuration data for the accounting-js library.
111
+	 *
112
+	 * @return array
113
+	 * @since $VID:$
114
+	 */
115
+	private function getAccountingSettings()
116
+	{
117
+		return [
118
+			'currency' => [
119
+				'symbol'    => $this->currency_config->sign,
120
+				'format'    => [
121
+					'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
122
+					'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
123
+					'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
124
+				],
125
+				'decimal'   => $this->currency_config->dec_mrk,
126
+				'thousand'  => $this->currency_config->thsnds,
127
+				'precision' => $this->currency_config->dec_plc,
128
+			],
129
+			'number'   => [
130
+				'precision' => $this->currency_config->dec_plc,
131
+				'thousand'  => $this->currency_config->thsnds,
132
+				'decimal'   => $this->currency_config->dec_mrk,
133
+			],
134
+		];
135
+	}
136 136
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
         // @link http://josscrowcroft.github.io/accounting.js/
84 84
         $this->addJavascript(
85 85
             LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE,
86
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
86
+            EE_THIRD_PARTY_URL.'accounting/accounting.js',
87 87
             [LegacyAccountingAssetManager::JS_HANDLE_UNDERSCORE],
88 88
             true,
89 89
             '0.3.2'
@@ -91,11 +91,11 @@  discard block
 block discarded – undo
91 91
 
92 92
         $this->addJavascript(
93 93
             LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
94
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
94
+            EE_GLOBAL_ASSETS_URL.'scripts/ee-accounting-config.js',
95 95
             [LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING_CORE]
96 96
         )
97 97
              ->setInlineDataCallback(
98
-                 function () {
98
+                 function() {
99 99
                      wp_localize_script(
100 100
                          LegacyAccountingAssetManager::JS_HANDLE_ACCOUNTING,
101 101
                          'EE_ACCOUNTING_CFG',
Please login to merge, or discard this patch.
core/domain/entities/routing/handlers/admin/EspressoEventsAdmin.php 1 patch
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -15,42 +15,42 @@
 block discarded – undo
15 15
 class EspressoEventsAdmin extends AdminRoute
16 16
 {
17 17
 
18
-    /**
19
-     * returns true if the current request matches this route
20
-     *
21
-     * @return bool
22
-     * @since   $VID:$
23
-     */
24
-    public function matchesCurrentRequest()
25
-    {
26
-        global $pagenow;
27
-        return $pagenow
28
-               && $pagenow === 'admin.php'
29
-               && $this->request->isAdmin()
30
-               && $this->request->getRequestParam('page') === 'espresso_events';
31
-    }
32
-
33
-
34
-    /**
35
-     * @since $VID:$
36
-     */
37
-    protected function registerDependencies()
38
-    {
39
-        $this->dependency_map->registerDependencies(
40
-            'EventEspresso\core\domain\services\admin\events\default_settings\AdvancedEditorAdminFormSection',
41
-            ['EE_Admin_Config' => EE_Dependency_Map::load_from_cache]
42
-        );
43
-    }
44
-
45
-
46
-    /**
47
-     * implements logic required to run during request
48
-     *
49
-     * @return bool
50
-     * @since   $VID:$
51
-     */
52
-    protected function requestHandler()
53
-    {
54
-        return false;
55
-    }
18
+	/**
19
+	 * returns true if the current request matches this route
20
+	 *
21
+	 * @return bool
22
+	 * @since   $VID:$
23
+	 */
24
+	public function matchesCurrentRequest()
25
+	{
26
+		global $pagenow;
27
+		return $pagenow
28
+			   && $pagenow === 'admin.php'
29
+			   && $this->request->isAdmin()
30
+			   && $this->request->getRequestParam('page') === 'espresso_events';
31
+	}
32
+
33
+
34
+	/**
35
+	 * @since $VID:$
36
+	 */
37
+	protected function registerDependencies()
38
+	{
39
+		$this->dependency_map->registerDependencies(
40
+			'EventEspresso\core\domain\services\admin\events\default_settings\AdvancedEditorAdminFormSection',
41
+			['EE_Admin_Config' => EE_Dependency_Map::load_from_cache]
42
+		);
43
+	}
44
+
45
+
46
+	/**
47
+	 * implements logic required to run during request
48
+	 *
49
+	 * @return bool
50
+	 * @since   $VID:$
51
+	 */
52
+	protected function requestHandler()
53
+	{
54
+		return false;
55
+	}
56 56
 }
Please login to merge, or discard this patch.