Completed
Branch EDTR/master (6bd139)
by
unknown
35:03 queued 26:41
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   +1357 added lines, -1357 removed lines patch added patch discarded remove patch
@@ -22,1361 +22,1361 @@
 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(
568
-                            $model,
569
-                            $relation_obj->get_other_model(),
570
-                            $version
571
-                        ),
572
-                    ],
573
-                    [
574
-                        'callback'        => [
575
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
576
-                            'handleRequestRemoveRelation',
577
-                        ],
578
-                        'callback_args'   => [$version, $model_name, $relation_name],
579
-                        'methods'         => WP_REST_Server::DELETABLE,
580
-                        'hidden_endpoint' => $hidden_endpoint,
581
-                        'args'            => [],
582
-                    ],
583
-                ];
584
-            }
585
-        }
586
-        return $model_routes;
587
-    }
588
-
589
-
590
-    /**
591
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
592
-     * excluding the preceding slash.
593
-     * Eg you pass get_plural_route_to('Event') = 'events'
594
-     *
595
-     * @param EEM_Base $model
596
-     * @return string
597
-     */
598
-    public static function get_collection_route(EEM_Base $model)
599
-    {
600
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
601
-    }
602
-
603
-
604
-    /**
605
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
606
-     * excluding the preceding slash.
607
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
608
-     *
609
-     * @param EEM_Base $model eg Event or Venue
610
-     * @param string   $id
611
-     * @return string
612
-     */
613
-    public static function get_entity_route($model, $id)
614
-    {
615
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
616
-    }
617
-
618
-
619
-    /**
620
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
621
-     * excluding the preceding slash.
622
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
623
-     *
624
-     * @param EEM_Base               $model eg Event or Venue
625
-     * @param string                 $id
626
-     * @param EE_Model_Relation_Base $relation_obj
627
-     * @return string
628
-     */
629
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
630
-    {
631
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
632
-            $relation_obj->get_other_model()->get_this_model_name(),
633
-            $relation_obj
634
-        );
635
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
636
-    }
637
-
638
-
639
-    /**
640
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
641
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
642
-     *
643
-     * @param string $relative_route
644
-     * @param string $version
645
-     * @return string
646
-     */
647
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
648
-    {
649
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
650
-    }
651
-
652
-
653
-    /**
654
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
655
-     * routes that don't conform to the traditional REST CRUD-style).
656
-     *
657
-     * @deprecated since 4.9.1
658
-     */
659
-    protected function _register_rpc_routes()
660
-    {
661
-        $routes = [];
662
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
663
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
664
-                $version,
665
-                $hidden_endpoint
666
-            );
667
-        }
668
-        return $routes;
669
-    }
670
-
671
-
672
-    /**
673
-     * @param string  $version
674
-     * @param boolean $hidden_endpoint
675
-     * @return array
676
-     */
677
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
678
-    {
679
-        $this_versions_routes = [];
680
-        // checkin endpoint
681
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
682
-            [
683
-                'callback'        => [
684
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
685
-                    'handleRequestToggleCheckin',
686
-                ],
687
-                'methods'         => WP_REST_Server::CREATABLE,
688
-                'hidden_endpoint' => $hidden_endpoint,
689
-                'args'            => [
690
-                    'force' => [
691
-                        'required'    => false,
692
-                        'default'     => false,
693
-                        'description' => __(
694
-                        // @codingStandardsIgnoreStart
695
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
696
-                            // @codingStandardsIgnoreEnd
697
-                            'event_espresso'
698
-                        ),
699
-                    ],
700
-                ],
701
-                'callback_args'   => [$version],
702
-            ],
703
-        ];
704
-        return apply_filters(
705
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
706
-            $this_versions_routes,
707
-            $version,
708
-            $hidden_endpoint
709
-        );
710
-    }
711
-
712
-
713
-    /**
714
-     * Gets the query params that can be used when request one or many
715
-     *
716
-     * @param EEM_Base $model
717
-     * @param string   $version
718
-     * @return array
719
-     */
720
-    protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
721
-    {
722
-        $query_params = [
723
-            'include'   => [
724
-                'required' => false,
725
-                'default'  => '*',
726
-                'type'     => 'string',
727
-            ],
728
-            'calculate' => [
729
-                'required'          => false,
730
-                'default'           => '',
731
-                'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
732
-                'type'              => 'string',
733
-                // because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
734
-                // freaks out. We'll just validate this argument while handling the request
735
-                'validate_callback' => null,
736
-                'sanitize_callback' => null,
737
-            ],
738
-            'password'  => [
739
-                'required' => false,
740
-                'default'  => '',
741
-                'type'     => 'string',
742
-            ],
743
-        ];
744
-        return apply_filters(
745
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
746
-            $query_params,
747
-            $model,
748
-            $version
749
-        );
750
-    }
751
-
752
-
753
-    /**
754
-     * Gets the parameters acceptable for delete requests
755
-     *
756
-     * @param EEM_Base $model
757
-     * @param string   $version
758
-     * @return array
759
-     */
760
-    protected function _get_delete_query_params(EEM_Base $model, $version)
761
-    {
762
-        $params_for_delete = [
763
-            'allow_blocking' => [
764
-                'required' => false,
765
-                'default'  => true,
766
-                'type'     => 'boolean',
767
-            ],
768
-        ];
769
-        $params_for_delete['force'] = [
770
-            'required' => false,
771
-            'default'  => false,
772
-            'type'     => 'boolean',
773
-        ];
774
-        return apply_filters(
775
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
776
-            $params_for_delete,
777
-            $model,
778
-            $version
779
-        );
780
-    }
781
-
782
-
783
-    /**
784
-     * @param EEM_Base $source_model
785
-     * @param EEM_Base $related_model
786
-     * @param          $version
787
-     * @return array
788
-     * @throws EE_Error
789
-     * @since $VID:$
790
-     */
791
-    protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
792
-    {
793
-        // if they're related through a HABTM relation, check for any non-FKs
794
-        $all_relation_settings = $source_model->relation_settings();
795
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
796
-        $params = [];
797
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
798
-            foreach ($relation_settings->getNonKeyFields() as $field) {
799
-                /* @var $field EE_Model_Field_Base */
800
-                $params[ $field->get_name() ] = [
801
-                    'required'          => ! $field->is_nullable(),
802
-                    'default'           => ModelDataTranslator::prepareFieldValueForJson(
803
-                        $field,
804
-                        $field->get_default_value(),
805
-                        $version
806
-                    ),
807
-                    'type'              => $field->getSchemaType(),
808
-                    'validate_callback' => null,
809
-                    'sanitize_callback' => null,
810
-                ];
811
-            }
812
-        }
813
-        return $params;
814
-    }
815
-
816
-
817
-    /**
818
-     * Gets info about reading query params that are acceptable
819
-     *
820
-     * @param EEM_Base $model eg 'Event' or 'Venue'
821
-     * @param string   $version
822
-     * @return array    describing the args acceptable when querying this model
823
-     * @throws EE_Error
824
-     */
825
-    protected function _get_read_query_params(EEM_Base $model, $version)
826
-    {
827
-        $default_orderby = [];
828
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
829
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
830
-        }
831
-        return array_merge(
832
-            $this->_get_response_selection_query_params($model, $version),
833
-            [
834
-                'where'    => [
835
-                    'required'          => false,
836
-                    'default'           => [],
837
-                    'type'              => 'object',
838
-                    // because we accept an almost infinite list of possible where conditions, WP
839
-                    // core validation and sanitization freaks out. We'll just validate this argument
840
-                    // while handling the request
841
-                    'validate_callback' => null,
842
-                    'sanitize_callback' => null,
843
-                ],
844
-                'limit'    => [
845
-                    'required'          => false,
846
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
847
-                    'type'              => [
848
-                        'array',
849
-                        'string',
850
-                        'integer',
851
-                    ],
852
-                    // because we accept a variety of types, WP core validation and sanitization
853
-                    // freaks out. We'll just validate this argument while handling the request
854
-                    'validate_callback' => null,
855
-                    'sanitize_callback' => null,
856
-                ],
857
-                'order_by' => [
858
-                    'required'          => false,
859
-                    'default'           => $default_orderby,
860
-                    'type'              => [
861
-                        'object',
862
-                        'string',
863
-                    ],// because we accept a variety of types, WP core validation and sanitization
864
-                    // freaks out. We'll just validate this argument while handling the request
865
-                    'validate_callback' => null,
866
-                    'sanitize_callback' => null,
867
-                ],
868
-                'group_by' => [
869
-                    'required'          => false,
870
-                    'default'           => null,
871
-                    'type'              => [
872
-                        'object',
873
-                        'string',
874
-                    ],
875
-                    // because we accept  an almost infinite list of possible groupings,
876
-                    // WP core validation and sanitization
877
-                    // freaks out. We'll just validate this argument while handling the request
878
-                    'validate_callback' => null,
879
-                    'sanitize_callback' => null,
880
-                ],
881
-                'having'   => [
882
-                    'required'          => false,
883
-                    'default'           => null,
884
-                    'type'              => 'object',
885
-                    // because we accept an almost infinite list of possible where conditions, WP
886
-                    // core validation and sanitization freaks out. We'll just validate this argument
887
-                    // while handling the request
888
-                    'validate_callback' => null,
889
-                    'sanitize_callback' => null,
890
-                ],
891
-                'caps'     => [
892
-                    'required' => false,
893
-                    'default'  => EEM_Base::caps_read,
894
-                    'type'     => 'string',
895
-                    'enum'     => [
896
-                        EEM_Base::caps_read,
897
-                        EEM_Base::caps_read_admin,
898
-                        EEM_Base::caps_edit,
899
-                        EEM_Base::caps_delete,
900
-                    ],
901
-                ],
902
-            ]
903
-        );
904
-    }
905
-
906
-
907
-    /**
908
-     * Gets parameter information for a model regarding writing data
909
-     *
910
-     * @param string           $model_name
911
-     * @param ModelVersionInfo $model_version_info
912
-     * @param boolean          $create                                       whether this is for request to create (in
913
-     *                                                                       which case we need all required params) or
914
-     *                                                                       just to update (in which case we don't
915
-     *                                                                       need those on every request)
916
-     * @return array
917
-     * @throws EE_Error
918
-     * @throws ReflectionException
919
-     */
920
-    protected function _get_write_params(
921
-        $model_name,
922
-        ModelVersionInfo $model_version_info,
923
-        $create = false
924
-    ) {
925
-        $model = EE_Registry::instance()->load_model($model_name);
926
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
927
-
928
-        // we do our own validation and sanitization within the controller
929
-        $sanitize_callback = function_exists('rest_validate_value_from_schema')
930
-            ? ['EED_Core_Rest_Api', 'default_sanitize_callback']
931
-            : null;
932
-        $args_info = [];
933
-        foreach ($fields as $field_name => $field_obj) {
934
-            if ($field_obj->is_auto_increment()) {
935
-                // totally ignore auto increment IDs
936
-                continue;
937
-            }
938
-            $arg_info = $field_obj->getSchema();
939
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
940
-            $arg_info['required'] = $required;
941
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
942
-            unset($arg_info['readonly']);
943
-            $schema_properties = $field_obj->getSchemaProperties();
944
-            if (isset($schema_properties['raw'])
945
-                && $field_obj->getSchemaType() === 'object'
946
-            ) {
947
-                // if there's a "raw" form of this argument, use those properties instead
948
-                $arg_info = array_replace(
949
-                    $arg_info,
950
-                    $schema_properties['raw']
951
-                );
952
-            }
953
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
954
-                $field_obj,
955
-                $field_obj->get_default_value(),
956
-                $model_version_info->requestedVersion()
957
-            );
958
-            $arg_info['sanitize_callback'] = $sanitize_callback;
959
-            $args_info[ $field_name ] = $arg_info;
960
-            if ($field_obj instanceof EE_Datetime_Field) {
961
-                $gmt_arg_info = $arg_info;
962
-                $gmt_arg_info['description'] = sprintf(
963
-                    esc_html__(
964
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
965
-                        'event_espresso'
966
-                    ),
967
-                    $field_obj->get_nicename(),
968
-                    $field_name
969
-                );
970
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
971
-            }
972
-        }
973
-        return $args_info;
974
-    }
975
-
976
-
977
-    /**
978
-     * Replacement for WP API's 'rest_parse_request_arg'.
979
-     * If the value is blank but not required, don't bother validating it.
980
-     * Also, it uses our email validation instead of WP API's default.
981
-     *
982
-     * @param                 $value
983
-     * @param WP_REST_Request $request
984
-     * @param                 $param
985
-     * @return bool|true|WP_Error
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidInterfaceException
988
-     * @throws InvalidDataTypeException
989
-     */
990
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
991
-    {
992
-        $attributes = $request->get_attributes();
993
-        if (! isset($attributes['args'][ $param ])
994
-            || ! is_array($attributes['args'][ $param ])) {
995
-            $validation_result = true;
996
-        } else {
997
-            $args = $attributes['args'][ $param ];
998
-            if ((
999
-                    $value === ''
1000
-                    || $value === null
1001
-                )
1002
-                && (! isset($args['required'])
1003
-                    || $args['required'] === false
1004
-                )
1005
-            ) {
1006
-                // not required and not provided? that's cool
1007
-                $validation_result = true;
1008
-            } elseif (isset($args['format'])
1009
-                      && $args['format'] === 'email'
1010
-            ) {
1011
-                $validation_result = true;
1012
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1013
-                    $validation_result = new WP_Error(
1014
-                        'rest_invalid_param',
1015
-                        esc_html__(
1016
-                            'The email address is not valid or does not exist.',
1017
-                            'event_espresso'
1018
-                        )
1019
-                    );
1020
-                }
1021
-            } else {
1022
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
1023
-            }
1024
-        }
1025
-        if (is_wp_error($validation_result)) {
1026
-            return $validation_result;
1027
-        }
1028
-        return rest_sanitize_request_arg($value, $request, $param);
1029
-    }
1030
-
1031
-
1032
-    /**
1033
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1034
-     *
1035
-     * @param $email
1036
-     * @return bool
1037
-     * @throws InvalidArgumentException
1038
-     * @throws InvalidInterfaceException
1039
-     * @throws InvalidDataTypeException
1040
-     */
1041
-    protected static function _validate_email($email)
1042
-    {
1043
-        try {
1044
-            EmailAddressFactory::create($email);
1045
-            return true;
1046
-        } catch (EmailValidationException $e) {
1047
-            return false;
1048
-        }
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * Gets routes for the config
1054
-     *
1055
-     * @return array @see _register_model_routes
1056
-     * @deprecated since version 4.9.1
1057
-     */
1058
-    protected function _register_config_routes()
1059
-    {
1060
-        $config_routes = [];
1061
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1062
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1063
-                $version,
1064
-                $hidden_endpoint
1065
-            );
1066
-        }
1067
-        return $config_routes;
1068
-    }
1069
-
1070
-
1071
-    /**
1072
-     * Gets routes for the config for the specified version
1073
-     *
1074
-     * @param string  $version
1075
-     * @param boolean $hidden_endpoint
1076
-     * @return array
1077
-     */
1078
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1079
-    {
1080
-        return [
1081
-            'config'    => [
1082
-                [
1083
-                    'callback'        => [
1084
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1085
-                        'handleRequest',
1086
-                    ],
1087
-                    'methods'         => WP_REST_Server::READABLE,
1088
-                    'hidden_endpoint' => $hidden_endpoint,
1089
-                    'callback_args'   => [$version],
1090
-                ],
1091
-            ],
1092
-            'site_info' => [
1093
-                [
1094
-                    'callback'        => [
1095
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1096
-                        'handleRequestSiteInfo',
1097
-                    ],
1098
-                    'methods'         => WP_REST_Server::READABLE,
1099
-                    'hidden_endpoint' => $hidden_endpoint,
1100
-                    'callback_args'   => [$version],
1101
-                ],
1102
-            ],
1103
-        ];
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * Gets the meta info routes
1109
-     *
1110
-     * @return array @see _register_model_routes
1111
-     * @deprecated since version 4.9.1
1112
-     */
1113
-    protected function _register_meta_routes()
1114
-    {
1115
-        $meta_routes = [];
1116
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1117
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1118
-                $version,
1119
-                $hidden_endpoint
1120
-            );
1121
-        }
1122
-        return $meta_routes;
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * @param string  $version
1128
-     * @param boolean $hidden_endpoint
1129
-     * @return array
1130
-     */
1131
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1132
-    {
1133
-        return [
1134
-            'resources' => [
1135
-                [
1136
-                    'callback'        => [
1137
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1138
-                        'handleRequestModelsMeta',
1139
-                    ],
1140
-                    'methods'         => WP_REST_Server::READABLE,
1141
-                    'hidden_endpoint' => $hidden_endpoint,
1142
-                    'callback_args'   => [$version],
1143
-                ],
1144
-            ],
1145
-        ];
1146
-    }
1147
-
1148
-
1149
-    /**
1150
-     * Tries to hide old 4.6 endpoints from the
1151
-     *
1152
-     * @param array $route_data
1153
-     * @return array
1154
-     * @throws EE_Error
1155
-     * @throws ReflectionException
1156
-     */
1157
-    public static function hide_old_endpoints($route_data)
1158
-    {
1159
-        // allow API clients to override which endpoints get hidden, in case
1160
-        // they want to discover particular endpoints
1161
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1162
-        $force_show_ee_namespace = ltrim(
1163
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1164
-            '/'
1165
-        );
1166
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1167
-            foreach ($relative_urls as $resource_name => $endpoints) {
1168
-                foreach ($endpoints as $key => $endpoint) {
1169
-                    // skip schema and other route options
1170
-                    if (! is_numeric($key)) {
1171
-                        continue;
1172
-                    }
1173
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1174
-                    // to $force_show_ee_namespace, in which case only show that one
1175
-                    // namespace's endpoints (and hide all others)
1176
-                    if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1177
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1178
-                    ) {
1179
-                        $full_route = '/' . ltrim($namespace, '/');
1180
-                        $full_route .= '/' . ltrim($resource_name, '/');
1181
-                        unset($route_data[ $full_route ]);
1182
-                    }
1183
-                }
1184
-            }
1185
-        }
1186
-        return $route_data;
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * Returns an array describing which versions of core support serving requests for.
1192
-     * Keys are core versions' major and minor version, and values are the
1193
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1194
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1195
-     * the answers table entirely, in which case it would be very difficult for
1196
-     * it to serve 4.6-style responses.
1197
-     * Versions of core that are missing from this array are unknowns.
1198
-     * previous ver
1199
-     *
1200
-     * @return array
1201
-     */
1202
-    public static function version_compatibilities()
1203
-    {
1204
-        return apply_filters(
1205
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1206
-            [
1207
-                '4.8.29' => '4.8.29',
1208
-                '4.8.33' => '4.8.29',
1209
-                '4.8.34' => '4.8.29',
1210
-                '4.8.36' => '4.8.29',
1211
-            ]
1212
-        );
1213
-    }
1214
-
1215
-
1216
-    /**
1217
-     * Gets the latest API version served. Eg if there
1218
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1219
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1220
-     *
1221
-     * @return string
1222
-     */
1223
-    public static function latest_rest_api_version()
1224
-    {
1225
-        $versions_served = EED_Core_Rest_Api::versions_served();
1226
-        $versions_served_keys = array_keys($versions_served);
1227
-        return end($versions_served_keys);
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1233
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1234
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1235
-     * We also indicate whether or not this version should be put in the index or not
1236
-     *
1237
-     * @return array keys are API version numbers (just major and minor numbers), and values
1238
-     * are whether or not they should be hidden
1239
-     */
1240
-    public static function versions_served()
1241
-    {
1242
-        $versions_served = [];
1243
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1244
-        $lowest_compatible_version = end($possibly_served_versions);
1245
-        reset($possibly_served_versions);
1246
-        $versions_served_historically = array_keys($possibly_served_versions);
1247
-        $latest_version = end($versions_served_historically);
1248
-        reset($versions_served_historically);
1249
-        // for each version of core we have ever served:
1250
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1251
-            // if it's not above the current core version, and it's compatible with the current version of core
1252
-
1253
-            if ($key_versioned_endpoint === $latest_version) {
1254
-                // don't hide the latest version in the index
1255
-                $versions_served[ $key_versioned_endpoint ] = false;
1256
-            } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1257
-                      && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1258
-            ) {
1259
-                // include, but hide, previous versions which are still supported
1260
-                $versions_served[ $key_versioned_endpoint ] = true;
1261
-            } elseif (apply_filters(
1262
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1263
-                false,
1264
-                $possibly_served_versions
1265
-            )) {
1266
-                // if a version is no longer supported, don't include it in index or list of versions served
1267
-                $versions_served[ $key_versioned_endpoint ] = true;
1268
-            }
1269
-        }
1270
-        return $versions_served;
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * Gets the major and minor version of EE core's version string
1276
-     *
1277
-     * @return string
1278
-     */
1279
-    public static function core_version()
1280
-    {
1281
-        return apply_filters(
1282
-            'FHEE__EED_Core_REST_API__core_version',
1283
-            implode(
1284
-                '.',
1285
-                array_slice(
1286
-                    explode(
1287
-                        '.',
1288
-                        espresso_version()
1289
-                    ),
1290
-                    0,
1291
-                    3
1292
-                )
1293
-            )
1294
-        );
1295
-    }
1296
-
1297
-
1298
-    /**
1299
-     * Gets the default limit that should be used when querying for resources
1300
-     *
1301
-     * @return int
1302
-     */
1303
-    public static function get_default_query_limit()
1304
-    {
1305
-        // we actually don't use a const because we want folks to always use
1306
-        // this method, not the const directly
1307
-        return apply_filters(
1308
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1309
-            50
1310
-        );
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * @param string $version api version string (i.e. '4.8.36')
1316
-     * @return array
1317
-     */
1318
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1319
-    {
1320
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1321
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1322
-        $collection_routes = [];
1323
-        foreach ($model_names as $model_name => $model_class_name) {
1324
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1325
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1326
-        }
1327
-        return $collection_routes;
1328
-    }
1329
-
1330
-
1331
-    /**
1332
-     * Returns an array of primary key names indexed by model names.
1333
-     *
1334
-     * @param string $version
1335
-     * @return array
1336
-     */
1337
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1338
-    {
1339
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1340
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1341
-        $primary_key_items = [];
1342
-        foreach ($model_names as $model_name => $model_class_name) {
1343
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1344
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1345
-                if (count($primary_keys) > 1) {
1346
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1347
-                } else {
1348
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1349
-                }
1350
-            }
1351
-        }
1352
-        return $primary_key_items;
1353
-    }
1354
-
1355
-
1356
-    /**
1357
-     * Determines the EE REST API debug mode is activated, or not.
1358
-     *
1359
-     * @return bool
1360
-     * @since 4.9.76.p
1361
-     */
1362
-    public static function debugMode()
1363
-    {
1364
-        static $debug_mode = null; // could be class prop
1365
-        if ($debug_mode === null) {
1366
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1367
-        }
1368
-        return $debug_mode;
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     *    run - initial module setup
1374
-     *
1375
-     * @access    public
1376
-     * @param WP $WP
1377
-     * @return    void
1378
-     */
1379
-    public function run($WP)
1380
-    {
1381
-    }
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(
568
+							$model,
569
+							$relation_obj->get_other_model(),
570
+							$version
571
+						),
572
+					],
573
+					[
574
+						'callback'        => [
575
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
576
+							'handleRequestRemoveRelation',
577
+						],
578
+						'callback_args'   => [$version, $model_name, $relation_name],
579
+						'methods'         => WP_REST_Server::DELETABLE,
580
+						'hidden_endpoint' => $hidden_endpoint,
581
+						'args'            => [],
582
+					],
583
+				];
584
+			}
585
+		}
586
+		return $model_routes;
587
+	}
588
+
589
+
590
+	/**
591
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
592
+	 * excluding the preceding slash.
593
+	 * Eg you pass get_plural_route_to('Event') = 'events'
594
+	 *
595
+	 * @param EEM_Base $model
596
+	 * @return string
597
+	 */
598
+	public static function get_collection_route(EEM_Base $model)
599
+	{
600
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
601
+	}
602
+
603
+
604
+	/**
605
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
606
+	 * excluding the preceding slash.
607
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
608
+	 *
609
+	 * @param EEM_Base $model eg Event or Venue
610
+	 * @param string   $id
611
+	 * @return string
612
+	 */
613
+	public static function get_entity_route($model, $id)
614
+	{
615
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
616
+	}
617
+
618
+
619
+	/**
620
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
621
+	 * excluding the preceding slash.
622
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
623
+	 *
624
+	 * @param EEM_Base               $model eg Event or Venue
625
+	 * @param string                 $id
626
+	 * @param EE_Model_Relation_Base $relation_obj
627
+	 * @return string
628
+	 */
629
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
630
+	{
631
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
632
+			$relation_obj->get_other_model()->get_this_model_name(),
633
+			$relation_obj
634
+		);
635
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
636
+	}
637
+
638
+
639
+	/**
640
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
641
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
642
+	 *
643
+	 * @param string $relative_route
644
+	 * @param string $version
645
+	 * @return string
646
+	 */
647
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
648
+	{
649
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
650
+	}
651
+
652
+
653
+	/**
654
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
655
+	 * routes that don't conform to the traditional REST CRUD-style).
656
+	 *
657
+	 * @deprecated since 4.9.1
658
+	 */
659
+	protected function _register_rpc_routes()
660
+	{
661
+		$routes = [];
662
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
663
+			$routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
664
+				$version,
665
+				$hidden_endpoint
666
+			);
667
+		}
668
+		return $routes;
669
+	}
670
+
671
+
672
+	/**
673
+	 * @param string  $version
674
+	 * @param boolean $hidden_endpoint
675
+	 * @return array
676
+	 */
677
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
678
+	{
679
+		$this_versions_routes = [];
680
+		// checkin endpoint
681
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
682
+			[
683
+				'callback'        => [
684
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
685
+					'handleRequestToggleCheckin',
686
+				],
687
+				'methods'         => WP_REST_Server::CREATABLE,
688
+				'hidden_endpoint' => $hidden_endpoint,
689
+				'args'            => [
690
+					'force' => [
691
+						'required'    => false,
692
+						'default'     => false,
693
+						'description' => __(
694
+						// @codingStandardsIgnoreStart
695
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
696
+							// @codingStandardsIgnoreEnd
697
+							'event_espresso'
698
+						),
699
+					],
700
+				],
701
+				'callback_args'   => [$version],
702
+			],
703
+		];
704
+		return apply_filters(
705
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
706
+			$this_versions_routes,
707
+			$version,
708
+			$hidden_endpoint
709
+		);
710
+	}
711
+
712
+
713
+	/**
714
+	 * Gets the query params that can be used when request one or many
715
+	 *
716
+	 * @param EEM_Base $model
717
+	 * @param string   $version
718
+	 * @return array
719
+	 */
720
+	protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
721
+	{
722
+		$query_params = [
723
+			'include'   => [
724
+				'required' => false,
725
+				'default'  => '*',
726
+				'type'     => 'string',
727
+			],
728
+			'calculate' => [
729
+				'required'          => false,
730
+				'default'           => '',
731
+				'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
732
+				'type'              => 'string',
733
+				// because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
734
+				// freaks out. We'll just validate this argument while handling the request
735
+				'validate_callback' => null,
736
+				'sanitize_callback' => null,
737
+			],
738
+			'password'  => [
739
+				'required' => false,
740
+				'default'  => '',
741
+				'type'     => 'string',
742
+			],
743
+		];
744
+		return apply_filters(
745
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
746
+			$query_params,
747
+			$model,
748
+			$version
749
+		);
750
+	}
751
+
752
+
753
+	/**
754
+	 * Gets the parameters acceptable for delete requests
755
+	 *
756
+	 * @param EEM_Base $model
757
+	 * @param string   $version
758
+	 * @return array
759
+	 */
760
+	protected function _get_delete_query_params(EEM_Base $model, $version)
761
+	{
762
+		$params_for_delete = [
763
+			'allow_blocking' => [
764
+				'required' => false,
765
+				'default'  => true,
766
+				'type'     => 'boolean',
767
+			],
768
+		];
769
+		$params_for_delete['force'] = [
770
+			'required' => false,
771
+			'default'  => false,
772
+			'type'     => 'boolean',
773
+		];
774
+		return apply_filters(
775
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
776
+			$params_for_delete,
777
+			$model,
778
+			$version
779
+		);
780
+	}
781
+
782
+
783
+	/**
784
+	 * @param EEM_Base $source_model
785
+	 * @param EEM_Base $related_model
786
+	 * @param          $version
787
+	 * @return array
788
+	 * @throws EE_Error
789
+	 * @since $VID:$
790
+	 */
791
+	protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
792
+	{
793
+		// if they're related through a HABTM relation, check for any non-FKs
794
+		$all_relation_settings = $source_model->relation_settings();
795
+		$relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
796
+		$params = [];
797
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
798
+			foreach ($relation_settings->getNonKeyFields() as $field) {
799
+				/* @var $field EE_Model_Field_Base */
800
+				$params[ $field->get_name() ] = [
801
+					'required'          => ! $field->is_nullable(),
802
+					'default'           => ModelDataTranslator::prepareFieldValueForJson(
803
+						$field,
804
+						$field->get_default_value(),
805
+						$version
806
+					),
807
+					'type'              => $field->getSchemaType(),
808
+					'validate_callback' => null,
809
+					'sanitize_callback' => null,
810
+				];
811
+			}
812
+		}
813
+		return $params;
814
+	}
815
+
816
+
817
+	/**
818
+	 * Gets info about reading query params that are acceptable
819
+	 *
820
+	 * @param EEM_Base $model eg 'Event' or 'Venue'
821
+	 * @param string   $version
822
+	 * @return array    describing the args acceptable when querying this model
823
+	 * @throws EE_Error
824
+	 */
825
+	protected function _get_read_query_params(EEM_Base $model, $version)
826
+	{
827
+		$default_orderby = [];
828
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
829
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
830
+		}
831
+		return array_merge(
832
+			$this->_get_response_selection_query_params($model, $version),
833
+			[
834
+				'where'    => [
835
+					'required'          => false,
836
+					'default'           => [],
837
+					'type'              => 'object',
838
+					// because we accept an almost infinite list of possible where conditions, WP
839
+					// core validation and sanitization freaks out. We'll just validate this argument
840
+					// while handling the request
841
+					'validate_callback' => null,
842
+					'sanitize_callback' => null,
843
+				],
844
+				'limit'    => [
845
+					'required'          => false,
846
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
847
+					'type'              => [
848
+						'array',
849
+						'string',
850
+						'integer',
851
+					],
852
+					// because we accept a variety of types, WP core validation and sanitization
853
+					// freaks out. We'll just validate this argument while handling the request
854
+					'validate_callback' => null,
855
+					'sanitize_callback' => null,
856
+				],
857
+				'order_by' => [
858
+					'required'          => false,
859
+					'default'           => $default_orderby,
860
+					'type'              => [
861
+						'object',
862
+						'string',
863
+					],// because we accept a variety of types, WP core validation and sanitization
864
+					// freaks out. We'll just validate this argument while handling the request
865
+					'validate_callback' => null,
866
+					'sanitize_callback' => null,
867
+				],
868
+				'group_by' => [
869
+					'required'          => false,
870
+					'default'           => null,
871
+					'type'              => [
872
+						'object',
873
+						'string',
874
+					],
875
+					// because we accept  an almost infinite list of possible groupings,
876
+					// WP core validation and sanitization
877
+					// freaks out. We'll just validate this argument while handling the request
878
+					'validate_callback' => null,
879
+					'sanitize_callback' => null,
880
+				],
881
+				'having'   => [
882
+					'required'          => false,
883
+					'default'           => null,
884
+					'type'              => 'object',
885
+					// because we accept an almost infinite list of possible where conditions, WP
886
+					// core validation and sanitization freaks out. We'll just validate this argument
887
+					// while handling the request
888
+					'validate_callback' => null,
889
+					'sanitize_callback' => null,
890
+				],
891
+				'caps'     => [
892
+					'required' => false,
893
+					'default'  => EEM_Base::caps_read,
894
+					'type'     => 'string',
895
+					'enum'     => [
896
+						EEM_Base::caps_read,
897
+						EEM_Base::caps_read_admin,
898
+						EEM_Base::caps_edit,
899
+						EEM_Base::caps_delete,
900
+					],
901
+				],
902
+			]
903
+		);
904
+	}
905
+
906
+
907
+	/**
908
+	 * Gets parameter information for a model regarding writing data
909
+	 *
910
+	 * @param string           $model_name
911
+	 * @param ModelVersionInfo $model_version_info
912
+	 * @param boolean          $create                                       whether this is for request to create (in
913
+	 *                                                                       which case we need all required params) or
914
+	 *                                                                       just to update (in which case we don't
915
+	 *                                                                       need those on every request)
916
+	 * @return array
917
+	 * @throws EE_Error
918
+	 * @throws ReflectionException
919
+	 */
920
+	protected function _get_write_params(
921
+		$model_name,
922
+		ModelVersionInfo $model_version_info,
923
+		$create = false
924
+	) {
925
+		$model = EE_Registry::instance()->load_model($model_name);
926
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
927
+
928
+		// we do our own validation and sanitization within the controller
929
+		$sanitize_callback = function_exists('rest_validate_value_from_schema')
930
+			? ['EED_Core_Rest_Api', 'default_sanitize_callback']
931
+			: null;
932
+		$args_info = [];
933
+		foreach ($fields as $field_name => $field_obj) {
934
+			if ($field_obj->is_auto_increment()) {
935
+				// totally ignore auto increment IDs
936
+				continue;
937
+			}
938
+			$arg_info = $field_obj->getSchema();
939
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
940
+			$arg_info['required'] = $required;
941
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
942
+			unset($arg_info['readonly']);
943
+			$schema_properties = $field_obj->getSchemaProperties();
944
+			if (isset($schema_properties['raw'])
945
+				&& $field_obj->getSchemaType() === 'object'
946
+			) {
947
+				// if there's a "raw" form of this argument, use those properties instead
948
+				$arg_info = array_replace(
949
+					$arg_info,
950
+					$schema_properties['raw']
951
+				);
952
+			}
953
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
954
+				$field_obj,
955
+				$field_obj->get_default_value(),
956
+				$model_version_info->requestedVersion()
957
+			);
958
+			$arg_info['sanitize_callback'] = $sanitize_callback;
959
+			$args_info[ $field_name ] = $arg_info;
960
+			if ($field_obj instanceof EE_Datetime_Field) {
961
+				$gmt_arg_info = $arg_info;
962
+				$gmt_arg_info['description'] = sprintf(
963
+					esc_html__(
964
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
965
+						'event_espresso'
966
+					),
967
+					$field_obj->get_nicename(),
968
+					$field_name
969
+				);
970
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
971
+			}
972
+		}
973
+		return $args_info;
974
+	}
975
+
976
+
977
+	/**
978
+	 * Replacement for WP API's 'rest_parse_request_arg'.
979
+	 * If the value is blank but not required, don't bother validating it.
980
+	 * Also, it uses our email validation instead of WP API's default.
981
+	 *
982
+	 * @param                 $value
983
+	 * @param WP_REST_Request $request
984
+	 * @param                 $param
985
+	 * @return bool|true|WP_Error
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidInterfaceException
988
+	 * @throws InvalidDataTypeException
989
+	 */
990
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
991
+	{
992
+		$attributes = $request->get_attributes();
993
+		if (! isset($attributes['args'][ $param ])
994
+			|| ! is_array($attributes['args'][ $param ])) {
995
+			$validation_result = true;
996
+		} else {
997
+			$args = $attributes['args'][ $param ];
998
+			if ((
999
+					$value === ''
1000
+					|| $value === null
1001
+				)
1002
+				&& (! isset($args['required'])
1003
+					|| $args['required'] === false
1004
+				)
1005
+			) {
1006
+				// not required and not provided? that's cool
1007
+				$validation_result = true;
1008
+			} elseif (isset($args['format'])
1009
+					  && $args['format'] === 'email'
1010
+			) {
1011
+				$validation_result = true;
1012
+				if (! EED_Core_Rest_Api::_validate_email($value)) {
1013
+					$validation_result = new WP_Error(
1014
+						'rest_invalid_param',
1015
+						esc_html__(
1016
+							'The email address is not valid or does not exist.',
1017
+							'event_espresso'
1018
+						)
1019
+					);
1020
+				}
1021
+			} else {
1022
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
1023
+			}
1024
+		}
1025
+		if (is_wp_error($validation_result)) {
1026
+			return $validation_result;
1027
+		}
1028
+		return rest_sanitize_request_arg($value, $request, $param);
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1034
+	 *
1035
+	 * @param $email
1036
+	 * @return bool
1037
+	 * @throws InvalidArgumentException
1038
+	 * @throws InvalidInterfaceException
1039
+	 * @throws InvalidDataTypeException
1040
+	 */
1041
+	protected static function _validate_email($email)
1042
+	{
1043
+		try {
1044
+			EmailAddressFactory::create($email);
1045
+			return true;
1046
+		} catch (EmailValidationException $e) {
1047
+			return false;
1048
+		}
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * Gets routes for the config
1054
+	 *
1055
+	 * @return array @see _register_model_routes
1056
+	 * @deprecated since version 4.9.1
1057
+	 */
1058
+	protected function _register_config_routes()
1059
+	{
1060
+		$config_routes = [];
1061
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1062
+			$config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1063
+				$version,
1064
+				$hidden_endpoint
1065
+			);
1066
+		}
1067
+		return $config_routes;
1068
+	}
1069
+
1070
+
1071
+	/**
1072
+	 * Gets routes for the config for the specified version
1073
+	 *
1074
+	 * @param string  $version
1075
+	 * @param boolean $hidden_endpoint
1076
+	 * @return array
1077
+	 */
1078
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1079
+	{
1080
+		return [
1081
+			'config'    => [
1082
+				[
1083
+					'callback'        => [
1084
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1085
+						'handleRequest',
1086
+					],
1087
+					'methods'         => WP_REST_Server::READABLE,
1088
+					'hidden_endpoint' => $hidden_endpoint,
1089
+					'callback_args'   => [$version],
1090
+				],
1091
+			],
1092
+			'site_info' => [
1093
+				[
1094
+					'callback'        => [
1095
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1096
+						'handleRequestSiteInfo',
1097
+					],
1098
+					'methods'         => WP_REST_Server::READABLE,
1099
+					'hidden_endpoint' => $hidden_endpoint,
1100
+					'callback_args'   => [$version],
1101
+				],
1102
+			],
1103
+		];
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * Gets the meta info routes
1109
+	 *
1110
+	 * @return array @see _register_model_routes
1111
+	 * @deprecated since version 4.9.1
1112
+	 */
1113
+	protected function _register_meta_routes()
1114
+	{
1115
+		$meta_routes = [];
1116
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1117
+			$meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1118
+				$version,
1119
+				$hidden_endpoint
1120
+			);
1121
+		}
1122
+		return $meta_routes;
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * @param string  $version
1128
+	 * @param boolean $hidden_endpoint
1129
+	 * @return array
1130
+	 */
1131
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1132
+	{
1133
+		return [
1134
+			'resources' => [
1135
+				[
1136
+					'callback'        => [
1137
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1138
+						'handleRequestModelsMeta',
1139
+					],
1140
+					'methods'         => WP_REST_Server::READABLE,
1141
+					'hidden_endpoint' => $hidden_endpoint,
1142
+					'callback_args'   => [$version],
1143
+				],
1144
+			],
1145
+		];
1146
+	}
1147
+
1148
+
1149
+	/**
1150
+	 * Tries to hide old 4.6 endpoints from the
1151
+	 *
1152
+	 * @param array $route_data
1153
+	 * @return array
1154
+	 * @throws EE_Error
1155
+	 * @throws ReflectionException
1156
+	 */
1157
+	public static function hide_old_endpoints($route_data)
1158
+	{
1159
+		// allow API clients to override which endpoints get hidden, in case
1160
+		// they want to discover particular endpoints
1161
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1162
+		$force_show_ee_namespace = ltrim(
1163
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1164
+			'/'
1165
+		);
1166
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1167
+			foreach ($relative_urls as $resource_name => $endpoints) {
1168
+				foreach ($endpoints as $key => $endpoint) {
1169
+					// skip schema and other route options
1170
+					if (! is_numeric($key)) {
1171
+						continue;
1172
+					}
1173
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1174
+					// to $force_show_ee_namespace, in which case only show that one
1175
+					// namespace's endpoints (and hide all others)
1176
+					if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1177
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1178
+					) {
1179
+						$full_route = '/' . ltrim($namespace, '/');
1180
+						$full_route .= '/' . ltrim($resource_name, '/');
1181
+						unset($route_data[ $full_route ]);
1182
+					}
1183
+				}
1184
+			}
1185
+		}
1186
+		return $route_data;
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * Returns an array describing which versions of core support serving requests for.
1192
+	 * Keys are core versions' major and minor version, and values are the
1193
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1194
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1195
+	 * the answers table entirely, in which case it would be very difficult for
1196
+	 * it to serve 4.6-style responses.
1197
+	 * Versions of core that are missing from this array are unknowns.
1198
+	 * previous ver
1199
+	 *
1200
+	 * @return array
1201
+	 */
1202
+	public static function version_compatibilities()
1203
+	{
1204
+		return apply_filters(
1205
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1206
+			[
1207
+				'4.8.29' => '4.8.29',
1208
+				'4.8.33' => '4.8.29',
1209
+				'4.8.34' => '4.8.29',
1210
+				'4.8.36' => '4.8.29',
1211
+			]
1212
+		);
1213
+	}
1214
+
1215
+
1216
+	/**
1217
+	 * Gets the latest API version served. Eg if there
1218
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1219
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1220
+	 *
1221
+	 * @return string
1222
+	 */
1223
+	public static function latest_rest_api_version()
1224
+	{
1225
+		$versions_served = EED_Core_Rest_Api::versions_served();
1226
+		$versions_served_keys = array_keys($versions_served);
1227
+		return end($versions_served_keys);
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1233
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1234
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1235
+	 * We also indicate whether or not this version should be put in the index or not
1236
+	 *
1237
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1238
+	 * are whether or not they should be hidden
1239
+	 */
1240
+	public static function versions_served()
1241
+	{
1242
+		$versions_served = [];
1243
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1244
+		$lowest_compatible_version = end($possibly_served_versions);
1245
+		reset($possibly_served_versions);
1246
+		$versions_served_historically = array_keys($possibly_served_versions);
1247
+		$latest_version = end($versions_served_historically);
1248
+		reset($versions_served_historically);
1249
+		// for each version of core we have ever served:
1250
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1251
+			// if it's not above the current core version, and it's compatible with the current version of core
1252
+
1253
+			if ($key_versioned_endpoint === $latest_version) {
1254
+				// don't hide the latest version in the index
1255
+				$versions_served[ $key_versioned_endpoint ] = false;
1256
+			} elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1257
+					  && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1258
+			) {
1259
+				// include, but hide, previous versions which are still supported
1260
+				$versions_served[ $key_versioned_endpoint ] = true;
1261
+			} elseif (apply_filters(
1262
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1263
+				false,
1264
+				$possibly_served_versions
1265
+			)) {
1266
+				// if a version is no longer supported, don't include it in index or list of versions served
1267
+				$versions_served[ $key_versioned_endpoint ] = true;
1268
+			}
1269
+		}
1270
+		return $versions_served;
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * Gets the major and minor version of EE core's version string
1276
+	 *
1277
+	 * @return string
1278
+	 */
1279
+	public static function core_version()
1280
+	{
1281
+		return apply_filters(
1282
+			'FHEE__EED_Core_REST_API__core_version',
1283
+			implode(
1284
+				'.',
1285
+				array_slice(
1286
+					explode(
1287
+						'.',
1288
+						espresso_version()
1289
+					),
1290
+					0,
1291
+					3
1292
+				)
1293
+			)
1294
+		);
1295
+	}
1296
+
1297
+
1298
+	/**
1299
+	 * Gets the default limit that should be used when querying for resources
1300
+	 *
1301
+	 * @return int
1302
+	 */
1303
+	public static function get_default_query_limit()
1304
+	{
1305
+		// we actually don't use a const because we want folks to always use
1306
+		// this method, not the const directly
1307
+		return apply_filters(
1308
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1309
+			50
1310
+		);
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * @param string $version api version string (i.e. '4.8.36')
1316
+	 * @return array
1317
+	 */
1318
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1319
+	{
1320
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1321
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1322
+		$collection_routes = [];
1323
+		foreach ($model_names as $model_name => $model_class_name) {
1324
+			$collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1325
+															. EEH_Inflector::pluralize_and_lower($model_name);
1326
+		}
1327
+		return $collection_routes;
1328
+	}
1329
+
1330
+
1331
+	/**
1332
+	 * Returns an array of primary key names indexed by model names.
1333
+	 *
1334
+	 * @param string $version
1335
+	 * @return array
1336
+	 */
1337
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1338
+	{
1339
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1340
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1341
+		$primary_key_items = [];
1342
+		foreach ($model_names as $model_name => $model_class_name) {
1343
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1344
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1345
+				if (count($primary_keys) > 1) {
1346
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1347
+				} else {
1348
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1349
+				}
1350
+			}
1351
+		}
1352
+		return $primary_key_items;
1353
+	}
1354
+
1355
+
1356
+	/**
1357
+	 * Determines the EE REST API debug mode is activated, or not.
1358
+	 *
1359
+	 * @return bool
1360
+	 * @since 4.9.76.p
1361
+	 */
1362
+	public static function debugMode()
1363
+	{
1364
+		static $debug_mode = null; // could be class prop
1365
+		if ($debug_mode === null) {
1366
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1367
+		}
1368
+		return $debug_mode;
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 *    run - initial module setup
1374
+	 *
1375
+	 * @access    public
1376
+	 * @param WP $WP
1377
+	 * @return    void
1378
+	 */
1379
+	public function run($WP)
1380
+	{
1381
+	}
1382 1382
 }
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',
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
      */
613 613
     public static function get_entity_route($model, $id)
614 614
     {
615
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
615
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
616 616
     }
617 617
 
618 618
 
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
             $relation_obj->get_other_model()->get_this_model_name(),
633 633
             $relation_obj
634 634
         );
635
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
635
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
636 636
     }
637 637
 
638 638
 
@@ -646,7 +646,7 @@  discard block
 block discarded – undo
646 646
      */
647 647
     public static function get_versioned_route_to($relative_route, $version = '4.8.36')
648 648
     {
649
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
649
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
650 650
     }
651 651
 
652 652
 
@@ -660,7 +660,7 @@  discard block
 block discarded – undo
660 660
     {
661 661
         $routes = [];
662 662
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
663
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
663
+            $routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
664 664
                 $version,
665 665
                 $hidden_endpoint
666 666
             );
@@ -792,12 +792,12 @@  discard block
 block discarded – undo
792 792
     {
793 793
         // if they're related through a HABTM relation, check for any non-FKs
794 794
         $all_relation_settings = $source_model->relation_settings();
795
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
795
+        $relation_settings = $all_relation_settings[$related_model->get_this_model_name()];
796 796
         $params = [];
797 797
         if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
798 798
             foreach ($relation_settings->getNonKeyFields() as $field) {
799 799
                 /* @var $field EE_Model_Field_Base */
800
-                $params[ $field->get_name() ] = [
800
+                $params[$field->get_name()] = [
801 801
                     'required'          => ! $field->is_nullable(),
802 802
                     'default'           => ModelDataTranslator::prepareFieldValueForJson(
803 803
                         $field,
@@ -826,7 +826,7 @@  discard block
 block discarded – undo
826 826
     {
827 827
         $default_orderby = [];
828 828
         foreach ($model->get_combined_primary_key_fields() as $key_field) {
829
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
829
+            $default_orderby[$key_field->get_name()] = 'ASC';
830 830
         }
831 831
         return array_merge(
832 832
             $this->_get_response_selection_query_params($model, $version),
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
                     'type'              => [
861 861
                         'object',
862 862
                         'string',
863
-                    ],// because we accept a variety of types, WP core validation and sanitization
863
+                    ], // because we accept a variety of types, WP core validation and sanitization
864 864
                     // freaks out. We'll just validate this argument while handling the request
865 865
                     'validate_callback' => null,
866 866
                     'sanitize_callback' => null,
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
                 $model_version_info->requestedVersion()
957 957
             );
958 958
             $arg_info['sanitize_callback'] = $sanitize_callback;
959
-            $args_info[ $field_name ] = $arg_info;
959
+            $args_info[$field_name] = $arg_info;
960 960
             if ($field_obj instanceof EE_Datetime_Field) {
961 961
                 $gmt_arg_info = $arg_info;
962 962
                 $gmt_arg_info['description'] = sprintf(
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
                     $field_obj->get_nicename(),
968 968
                     $field_name
969 969
                 );
970
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
970
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
971 971
             }
972 972
         }
973 973
         return $args_info;
@@ -990,16 +990,16 @@  discard block
 block discarded – undo
990 990
     public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
991 991
     {
992 992
         $attributes = $request->get_attributes();
993
-        if (! isset($attributes['args'][ $param ])
994
-            || ! is_array($attributes['args'][ $param ])) {
993
+        if ( ! isset($attributes['args'][$param])
994
+            || ! is_array($attributes['args'][$param])) {
995 995
             $validation_result = true;
996 996
         } else {
997
-            $args = $attributes['args'][ $param ];
997
+            $args = $attributes['args'][$param];
998 998
             if ((
999 999
                     $value === ''
1000 1000
                     || $value === null
1001 1001
                 )
1002
-                && (! isset($args['required'])
1002
+                && ( ! isset($args['required'])
1003 1003
                     || $args['required'] === false
1004 1004
                 )
1005 1005
             ) {
@@ -1009,7 +1009,7 @@  discard block
 block discarded – undo
1009 1009
                       && $args['format'] === 'email'
1010 1010
             ) {
1011 1011
                 $validation_result = true;
1012
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1012
+                if ( ! EED_Core_Rest_Api::_validate_email($value)) {
1013 1013
                     $validation_result = new WP_Error(
1014 1014
                         'rest_invalid_param',
1015 1015
                         esc_html__(
@@ -1059,7 +1059,7 @@  discard block
 block discarded – undo
1059 1059
     {
1060 1060
         $config_routes = [];
1061 1061
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1062
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1062
+            $config_routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1063 1063
                 $version,
1064 1064
                 $hidden_endpoint
1065 1065
             );
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
     {
1115 1115
         $meta_routes = [];
1116 1116
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1117
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1117
+            $meta_routes[EED_Core_Rest_Api::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1118 1118
                 $version,
1119 1119
                 $hidden_endpoint
1120 1120
             );
@@ -1167,7 +1167,7 @@  discard block
 block discarded – undo
1167 1167
             foreach ($relative_urls as $resource_name => $endpoints) {
1168 1168
                 foreach ($endpoints as $key => $endpoint) {
1169 1169
                     // skip schema and other route options
1170
-                    if (! is_numeric($key)) {
1170
+                    if ( ! is_numeric($key)) {
1171 1171
                         continue;
1172 1172
                     }
1173 1173
                     // by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1176,9 +1176,9 @@  discard block
 block discarded – undo
1176 1176
                     if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1177 1177
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1178 1178
                     ) {
1179
-                        $full_route = '/' . ltrim($namespace, '/');
1180
-                        $full_route .= '/' . ltrim($resource_name, '/');
1181
-                        unset($route_data[ $full_route ]);
1179
+                        $full_route = '/'.ltrim($namespace, '/');
1180
+                        $full_route .= '/'.ltrim($resource_name, '/');
1181
+                        unset($route_data[$full_route]);
1182 1182
                     }
1183 1183
                 }
1184 1184
             }
@@ -1252,19 +1252,19 @@  discard block
 block discarded – undo
1252 1252
 
1253 1253
             if ($key_versioned_endpoint === $latest_version) {
1254 1254
                 // don't hide the latest version in the index
1255
-                $versions_served[ $key_versioned_endpoint ] = false;
1255
+                $versions_served[$key_versioned_endpoint] = false;
1256 1256
             } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1257 1257
                       && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1258 1258
             ) {
1259 1259
                 // include, but hide, previous versions which are still supported
1260
-                $versions_served[ $key_versioned_endpoint ] = true;
1260
+                $versions_served[$key_versioned_endpoint] = true;
1261 1261
             } elseif (apply_filters(
1262 1262
                 'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1263 1263
                 false,
1264 1264
                 $possibly_served_versions
1265 1265
             )) {
1266 1266
                 // if a version is no longer supported, don't include it in index or list of versions served
1267
-                $versions_served[ $key_versioned_endpoint ] = true;
1267
+                $versions_served[$key_versioned_endpoint] = true;
1268 1268
             }
1269 1269
         }
1270 1270
         return $versions_served;
@@ -1321,7 +1321,7 @@  discard block
 block discarded – undo
1321 1321
         $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1322 1322
         $collection_routes = [];
1323 1323
         foreach ($model_names as $model_name => $model_class_name) {
1324
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1324
+            $collection_routes[strtolower($model_name)] = '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'
1325 1325
                                                             . EEH_Inflector::pluralize_and_lower($model_name);
1326 1326
         }
1327 1327
         return $collection_routes;
@@ -1343,9 +1343,9 @@  discard block
 block discarded – undo
1343 1343
             $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1344 1344
             foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1345 1345
                 if (count($primary_keys) > 1) {
1346
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1346
+                    $primary_key_items[strtolower($model_name)][] = $primary_key_name;
1347 1347
                 } else {
1348
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1348
+                    $primary_key_items[strtolower($model_name)] = $primary_key_name;
1349 1349
                 }
1350 1350
             }
1351 1351
         }
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
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.
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
-    protected $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
+	protected $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.
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   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -19,81 +19,81 @@
 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
-    {
41
-        $this->loader = $loader;
42
-        $this->routes = $routes;
43
-    }
33
+	/**
34
+	 * RouteHandler constructor.
35
+	 *
36
+	 * @param LoaderInterface  $loader
37
+	 * @param RouteCollection $routes
38
+	 */
39
+	public function __construct(LoaderInterface $loader, RouteCollection $routes)
40
+	{
41
+		$this->loader = $loader;
42
+		$this->routes = $routes;
43
+	}
44 44
 
45 45
 
46
-    /**
47
-     * @param string $fqcn   Fully Qualified Class Name for Route
48
-     * @param bool   $handle if true [default] will immediately call RouteInterface::handleRequest()
49
-     * @throws Exception
50
-     * @since $VID:$
51
-     */
52
-    public function addRoute($fqcn, $handle = true)
53
-    {
54
-        try {
55
-            $route = $this->loader->getShared($fqcn);
56
-            if (! $route instanceof RouteInterface) {
57
-                throw new InvalidClassException(
58
-                    sprintf(
59
-                        esc_html__(
60
-                            'The supplied FQCN (%1$s) must be an instance of RouteInterface.',
61
-                            'event_espresso'
62
-                        ),
63
-                        $fqcn
64
-                    )
65
-                );
66
-            }
67
-            $this->routes->add($route);
68
-            if ($handle) {
69
-                $route->handleRequest();
70
-            }
71
-        } catch (Exception $exception) {
72
-            new ExceptionStackTraceDisplay($exception);
73
-        }
74
-    }
46
+	/**
47
+	 * @param string $fqcn   Fully Qualified Class Name for Route
48
+	 * @param bool   $handle if true [default] will immediately call RouteInterface::handleRequest()
49
+	 * @throws Exception
50
+	 * @since $VID:$
51
+	 */
52
+	public function addRoute($fqcn, $handle = true)
53
+	{
54
+		try {
55
+			$route = $this->loader->getShared($fqcn);
56
+			if (! $route instanceof RouteInterface) {
57
+				throw new InvalidClassException(
58
+					sprintf(
59
+						esc_html__(
60
+							'The supplied FQCN (%1$s) must be an instance of RouteInterface.',
61
+							'event_espresso'
62
+						),
63
+						$fqcn
64
+					)
65
+				);
66
+			}
67
+			$this->routes->add($route);
68
+			if ($handle) {
69
+				$route->handleRequest();
70
+			}
71
+		} catch (Exception $exception) {
72
+			new ExceptionStackTraceDisplay($exception);
73
+		}
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * finds and returns all Routes that have yet to be handled
79
-     *
80
-     * @return RouteInterface[]
81
-     */
82
-    public function getRoutesForCurrentRequest()
83
-    {
84
-        return $this->routes->getRoutesForCurrentRequest();
85
-    }
77
+	/**
78
+	 * finds and returns all Routes that have yet to be handled
79
+	 *
80
+	 * @return RouteInterface[]
81
+	 */
82
+	public function getRoutesForCurrentRequest()
83
+	{
84
+		return $this->routes->getRoutesForCurrentRequest();
85
+	}
86 86
 
87 87
 
88
-    /**
89
-     * calls RouteInterface::handleRequest() on all Routes that
90
-     *      - match current request
91
-     *      - have yet to be handled
92
-     *
93
-     * @return void
94
-     */
95
-    public function handleRoutesForCurrentRequest()
96
-    {
97
-        $this->routes->handleRoutesForCurrentRequest();
98
-    }
88
+	/**
89
+	 * calls RouteInterface::handleRequest() on all Routes that
90
+	 *      - match current request
91
+	 *      - have yet to be handled
92
+	 *
93
+	 * @return void
94
+	 */
95
+	public function handleRoutesForCurrentRequest()
96
+	{
97
+		$this->routes->handleRoutesForCurrentRequest();
98
+	}
99 99
 }
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.