Completed
Branch BUG-10738-inconsistency-in-ses... (a1eed8)
by
unknown
24:27 queued 12:29
created
modules/core_rest_api/EED_Core_Rest_Api.module.php 2 patches
Indentation   +1249 added lines, -1249 removed lines patch added patch discarded remove patch
@@ -23,1256 +23,1256 @@
 block discarded – undo
23 23
 class EED_Core_Rest_Api extends \EED_Module
24 24
 {
25 25
 
26
-    const ee_api_namespace           = 'ee/v';
26
+	const ee_api_namespace           = 'ee/v';
27 27
 
28
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
29
-
30
-    const saved_routes_option_names  = 'ee_core_routes';
31
-
32
-    /**
33
-     * string used in _links response bodies to make them globally unique.
34
-     *
35
-     * @see http://v2.wp-api.org/extending/linking/
36
-     */
37
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
38
-
39
-    /**
40
-     * @var CalculatedModelFields
41
-     */
42
-    protected static $_field_calculator;
43
-
44
-
45
-
46
-    /**
47
-     * @return EED_Core_Rest_Api|EED_Module
48
-     */
49
-    public static function instance()
50
-    {
51
-        self::$_field_calculator = new CalculatedModelFields();
52
-        return parent::get_instance(__CLASS__);
53
-    }
54
-
55
-
56
-
57
-    /**
58
-     *    set_hooks - for hooking into EE Core, other modules, etc
59
-     *
60
-     * @access    public
61
-     * @return    void
62
-     */
63
-    public static function set_hooks()
64
-    {
65
-        self::set_hooks_both();
66
-    }
67
-
68
-
69
-
70
-    /**
71
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
72
-     *
73
-     * @access    public
74
-     * @return    void
75
-     */
76
-    public static function set_hooks_admin()
77
-    {
78
-        self::set_hooks_both();
79
-    }
80
-
81
-
82
-
83
-    public static function set_hooks_both()
84
-    {
85
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
86
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
87
-        add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
88
-        add_filter('rest_index',
89
-            array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
90
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
91
-    }
92
-
93
-
94
-
95
-    /**
96
-     * sets up hooks which only need to be included as part of REST API requests;
97
-     * other requests like to the frontend or admin etc don't need them
98
-     *
99
-     * @throws \EE_Error
100
-     */
101
-    public static function set_hooks_rest_api()
102
-    {
103
-        //set hooks which account for changes made to the API
104
-        EED_Core_Rest_Api::_set_hooks_for_changes();
105
-    }
106
-
107
-
108
-
109
-    /**
110
-     * public wrapper of _set_hooks_for_changes.
111
-     * Loads all the hooks which make requests to old versions of the API
112
-     * appear the same as they always did
113
-     *
114
-     * @throws EE_Error
115
-     */
116
-    public static function set_hooks_for_changes()
117
-    {
118
-        self::_set_hooks_for_changes();
119
-    }
120
-
121
-
122
-
123
-    /**
124
-     * Loads all the hooks which make requests to old versions of the API
125
-     * appear the same as they always did
126
-     *
127
-     * @throws EE_Error
128
-     */
129
-    protected static function _set_hooks_for_changes()
130
-    {
131
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
132
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
133
-            //ignore the base parent class
134
-            //and legacy named classes
135
-            if ($classname_in_namespace === 'ChangesInBase'
136
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
137
-            ) {
138
-                continue;
139
-            }
140
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
141
-            if (class_exists($full_classname)) {
142
-                $instance_of_class = new $full_classname;
143
-                if ($instance_of_class instanceof ChangesInBase) {
144
-                    $instance_of_class->setHooks();
145
-                }
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
-     */
158
-    public static function register_routes()
159
-    {
160
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
161
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
162
-                /**
163
-                 * @var array $data_for_multiple_endpoints numerically indexed array
164
-                 *                                         but can also contain route options like {
165
-                 * @type array    $schema                      {
166
-                 * @type callable $schema_callback
167
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
168
-                 * WP_REST_Request of course
169
-                 * }
170
-                 * }
171
-                 */
172
-                //when registering routes, register all the endpoints' data at the same time
173
-                $multiple_endpoint_args = array();
174
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
175
-                    /**
176
-                     * @var array     $data_for_single_endpoint {
177
-                     * @type callable $callback
178
-                     * @type string methods
179
-                     * @type array args
180
-                     * @type array _links
181
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
182
-                     * WP_REST_Request of course
183
-                     * }
184
-                     */
185
-                    //skip route options
186
-                    if (! is_numeric($endpoint_key)) {
187
-                        continue;
188
-                    }
189
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
190
-                        throw new EE_Error(
191
-                            esc_html__(
192
-                                // @codingStandardsIgnoreStart
193
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
194
-                                // @codingStandardsIgnoreEnd
195
-                                'event_espresso')
196
-                        );
197
-                    }
198
-                    $callback = $data_for_single_endpoint['callback'];
199
-                    $single_endpoint_args = array(
200
-                        'methods' => $data_for_single_endpoint['methods'],
201
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
202
-                            : array(),
203
-                    );
204
-                    if (isset($data_for_single_endpoint['_links'])) {
205
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
206
-                    }
207
-                    if (isset($data_for_single_endpoint['callback_args'])) {
208
-                        $callback_args = $data_for_single_endpoint['callback_args'];
209
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
210
-                            $callback,
211
-                            $callback_args
212
-                        ) {
213
-                            array_unshift($callback_args, $request);
214
-                            return call_user_func_array(
215
-                                $callback,
216
-                                $callback_args
217
-                            );
218
-                        };
219
-                    } else {
220
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
221
-                    }
222
-                    $multiple_endpoint_args[] = $single_endpoint_args;
223
-                }
224
-                if (isset($data_for_multiple_endpoints['schema'])) {
225
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
226
-                    $schema_callback = $schema_route_data['schema_callback'];
227
-                    $callback_args = $schema_route_data['callback_args'];
228
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
229
-                        return call_user_func_array(
230
-                            $schema_callback,
231
-                            $callback_args
232
-                        );
233
-                    };
234
-                }
235
-                register_rest_route(
236
-                    $namespace,
237
-                    $relative_route,
238
-                    $multiple_endpoint_args
239
-                );
240
-            }
241
-        }
242
-    }
243
-
244
-
245
-
246
-    /**
247
-     * Checks if there was a version change or something that merits invalidating the cached
248
-     * route data. If so, invalidates the cached route data so that it gets refreshed
249
-     * next time the WP API is used
250
-     */
251
-    public static function invalidate_cached_route_data_on_version_change()
252
-    {
253
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
254
-            EED_Core_Rest_Api::invalidate_cached_route_data();
255
-        }
256
-        foreach (EE_Registry::instance()->addons as $addon) {
257
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
258
-                EED_Core_Rest_Api::invalidate_cached_route_data();
259
-            }
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
-    /**
279
-     * Gets the EE route data
280
-     *
281
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
282
-     * @throws \EE_Error
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 = array();
291
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
292
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
293
-                $version,
294
-                $hidden_endpoints
295
-            );
296
-        }
297
-        return $ee_routes;
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     * Gets the EE route data from the wp options if it exists already,
304
-     * otherwise re-generates it and saves it to the option
305
-     *
306
-     * @param string  $version
307
-     * @param boolean $hidden_endpoints
308
-     * @return array
309
-     * @throws \EE_Error
310
-     */
311
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
312
-    {
313
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
314
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
315
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
316
-        }
317
-        return $ee_routes;
318
-    }
319
-
320
-
321
-
322
-    /**
323
-     * Saves the EE REST API route data to a wp option and returns it
324
-     *
325
-     * @param string  $version
326
-     * @param boolean $hidden_endpoints
327
-     * @return mixed|null
328
-     * @throws \EE_Error
329
-     */
330
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
331
-    {
332
-        $instance = self::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 = self::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
-    /**
354
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
355
-     * need to calculate it on every request
356
-     *
357
-     * @deprecated since version 4.9.1
358
-     * @return void
359
-     */
360
-    public static function save_ee_routes()
361
-    {
362
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
363
-            $instance = self::instance();
364
-            $routes = apply_filters(
365
-                'EED_Core_Rest_Api__save_ee_routes__routes',
366
-                array_replace_recursive(
367
-                    $instance->_register_config_routes(),
368
-                    $instance->_register_meta_routes(),
369
-                    $instance->_register_model_routes(),
370
-                    $instance->_register_rpc_routes()
371
-                )
372
-            );
373
-            update_option(self::saved_routes_option_names, $routes, true);
374
-        }
375
-    }
376
-
377
-
378
-
379
-    /**
380
-     * Gets all the route information relating to EE models
381
-     *
382
-     * @return array @see get_ee_route_data
383
-     * @deprecated since version 4.9.1
384
-     */
385
-    protected function _register_model_routes()
386
-    {
387
-        $model_routes = array();
388
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
389
-            $model_routes[EED_Core_Rest_Api::ee_api_namespace
390
-                          . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
391
-        }
392
-        return $model_routes;
393
-    }
394
-
395
-
396
-
397
-    /**
398
-     * Decides whether or not to add write endpoints for this model.
399
-     *
400
-     * Currently, this defaults to exclude all global tables and models
401
-     * which would allow inserting WP core data (we don't want to duplicate
402
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
403
-     * @param EEM_Base $model
404
-     * @return bool
405
-     */
406
-    public static function should_have_write_endpoints(EEM_Base $model)
407
-    {
408
-        if ($model->is_wp_core_model()){
409
-            return false;
410
-        }
411
-        foreach($model->get_tables() as $table){
412
-            if( $table->is_global()){
413
-                return false;
414
-            }
415
-        }
416
-        return true;
417
-    }
418
-
419
-
420
-
421
-    /**
422
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
423
-     * in this versioned namespace of EE4
424
-     * @param $version
425
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
426
-     */
427
-    public static function model_names_with_plural_routes($version){
428
-        $model_version_info = new ModelVersionInfo($version);
429
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
430
-        //let's not bother having endpoints for extra metas
431
-        unset(
432
-            $models_to_register['Extra_Meta'],
433
-            $models_to_register['Extra_Join'],
434
-            $models_to_register['Post_Meta']
435
-        );
436
-        return apply_filters(
437
-            'FHEE__EED_Core_REST_API___register_model_routes',
438
-            $models_to_register
439
-        );
440
-    }
441
-
442
-
443
-
444
-    /**
445
-     * Gets the route data for EE models in the specified version
446
-     *
447
-     * @param string  $version
448
-     * @param boolean $hidden_endpoint
449
-     * @return array
450
-     * @throws EE_Error
451
-     */
452
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
453
-    {
454
-        $model_routes = array();
455
-        $model_version_info = new ModelVersionInfo($version);
456
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
457
-            $model = \EE_Registry::instance()->load_model($model_name);
458
-            //if this isn't a valid model then let's skip iterate to the next item in the loop.
459
-            if (! $model instanceof EEM_Base) {
460
-                continue;
461
-            }
462
-            //yes we could just register one route for ALL models, but then they wouldn't show up in the index
463
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
464
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
465
-            $model_routes[$plural_model_route] = array(
466
-                array(
467
-                    'callback'        => array(
468
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
469
-                        'handleRequestGetAll',
470
-                    ),
471
-                    'callback_args'   => array($version, $model_name),
472
-                    'methods'         => WP_REST_Server::READABLE,
473
-                    'hidden_endpoint' => $hidden_endpoint,
474
-                    'args'            => $this->_get_read_query_params($model, $version),
475
-                    '_links'          => array(
476
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
477
-                    ),
478
-                ),
479
-                'schema' => array(
480
-                    'schema_callback' => array(
481
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
482
-                        'handleSchemaRequest',
483
-                    ),
484
-                    'callback_args'   => array($version, $model_name),
485
-                ),
486
-            );
487
-            $model_routes[$singular_model_route] = array(
488
-                array(
489
-                    'callback'        => array(
490
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
491
-                        'handleRequestGetOne',
492
-                    ),
493
-                    'callback_args'   => array($version, $model_name),
494
-                    'methods'         => WP_REST_Server::READABLE,
495
-                    'hidden_endpoint' => $hidden_endpoint,
496
-                    'args'            => $this->_get_response_selection_query_params($model, $version),
497
-                ),
498
-            );
499
-            if( apply_filters(
500
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
501
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
502
-                $model
503
-            )){
504
-                $model_routes[$plural_model_route][] = array(
505
-                    'callback'        => array(
506
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
507
-                        'handleRequestInsert',
508
-                    ),
509
-                    'callback_args'   => array($version, $model_name),
510
-                    'methods'         => WP_REST_Server::CREATABLE,
511
-                    'hidden_endpoint' => $hidden_endpoint,
512
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
513
-                );
514
-                $model_routes[$singular_model_route] = array_merge(
515
-                    $model_routes[$singular_model_route],
516
-                    array(
517
-                        array(
518
-                            'callback'        => array(
519
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
520
-                                'handleRequestUpdate',
521
-                            ),
522
-                            'callback_args'   => array($version, $model_name),
523
-                            'methods'         => WP_REST_Server::EDITABLE,
524
-                            'hidden_endpoint' => $hidden_endpoint,
525
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
526
-                        ),
527
-                        array(
528
-                            'callback'        => array(
529
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
530
-                                'handleRequestDelete',
531
-                            ),
532
-                            'callback_args'   => array($version, $model_name),
533
-                            'methods'         => WP_REST_Server::DELETABLE,
534
-                            'hidden_endpoint' => $hidden_endpoint,
535
-                            'args'            => $this->_get_delete_query_params($model, $version),
536
-                        )
537
-                    )
538
-                );
539
-            }
540
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
541
-
542
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
543
-                    $model,
544
-                    '(?P<id>[^\/]+)',
545
-                    $relation_obj
546
-                );
547
-                $endpoints = array(
548
-                    array(
549
-                        'callback'        => array(
550
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
551
-                            'handleRequestGetRelated',
552
-                        ),
553
-                        'callback_args'   => array($version, $model_name, $relation_name),
554
-                        'methods'         => WP_REST_Server::READABLE,
555
-                        'hidden_endpoint' => $hidden_endpoint,
556
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
557
-                    ),
558
-                );
559
-                $model_routes[$related_route] = $endpoints;
560
-            }
561
-        }
562
-        return $model_routes;
563
-    }
564
-
565
-
566
-
567
-    /**
568
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
569
-     * excluding the preceding slash.
570
-     * Eg you pass get_plural_route_to('Event') = 'events'
571
-     *
572
-     * @param EEM_Base $model
573
-     * @return string
574
-     */
575
-    public static function get_collection_route(EEM_Base $model)
576
-    {
577
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
578
-    }
579
-
580
-
581
-
582
-    /**
583
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
584
-     * excluding the preceding slash.
585
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
586
-     *
587
-     * @param EEM_Base $model eg Event or Venue
588
-     * @param string $id
589
-     * @return string
590
-     */
591
-    public static function get_entity_route($model, $id)
592
-    {
593
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
594
-    }
595
-
596
-
597
-    /**
598
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
599
-     * excluding the preceding slash.
600
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
601
-     *
602
-     * @param EEM_Base                 $model eg Event or Venue
603
-     * @param string                 $id
604
-     * @param EE_Model_Relation_Base $relation_obj
605
-     * @return string
606
-     */
607
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
608
-    {
609
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
610
-            $relation_obj->get_other_model()->get_this_model_name(),
611
-            $relation_obj
612
-        );
613
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
614
-    }
615
-
616
-
617
-
618
-    /**
619
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
620
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
621
-     * @param string $relative_route
622
-     * @param string $version
623
-     * @return string
624
-     */
625
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
626
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
627
-    }
628
-
629
-
630
-
631
-    /**
632
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
633
-     * routes that don't conform to the traditional REST CRUD-style).
634
-     *
635
-     * @deprecated since 4.9.1
636
-     */
637
-    protected function _register_rpc_routes()
638
-    {
639
-        $routes = array();
640
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
641
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
642
-                $version,
643
-                $hidden_endpoint
644
-            );
645
-        }
646
-        return $routes;
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * @param string  $version
653
-     * @param boolean $hidden_endpoint
654
-     * @return array
655
-     */
656
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
657
-    {
658
-        $this_versions_routes = array();
659
-        //checkin endpoint
660
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
661
-            array(
662
-                'callback'        => array(
663
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
664
-                    'handleRequestToggleCheckin',
665
-                ),
666
-                'methods'         => WP_REST_Server::CREATABLE,
667
-                'hidden_endpoint' => $hidden_endpoint,
668
-                'args'            => array(
669
-                    'force' => array(
670
-                        'required'    => false,
671
-                        'default'     => false,
672
-                        'description' => __(
673
-                            // @codingStandardsIgnoreStart
674
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
675
-                            // @codingStandardsIgnoreEnd
676
-                            'event_espresso'
677
-                        ),
678
-                    ),
679
-                ),
680
-                'callback_args'   => array($version),
681
-            ),
682
-        );
683
-        return apply_filters(
684
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
685
-            $this_versions_routes,
686
-            $version,
687
-            $hidden_endpoint
688
-        );
689
-    }
690
-
691
-
692
-
693
-    /**
694
-     * Gets the query params that can be used when request one or many
695
-     *
696
-     * @param EEM_Base $model
697
-     * @param string   $version
698
-     * @return array
699
-     */
700
-    protected function _get_response_selection_query_params(\EEM_Base $model, $version)
701
-    {
702
-        return apply_filters(
703
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
704
-            array(
705
-                'include'   => array(
706
-                    'required' => false,
707
-                    'default'  => '*',
708
-                    'type'     => 'string',
709
-                ),
710
-                'calculate' => array(
711
-                    'required'          => false,
712
-                    'default'           => '',
713
-                    'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
714
-                    'type'              => 'string',
715
-                    //because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
716
-                    //freaks out. We'll just validate this argument while handling the request
717
-                    'validate_callback' => null,
718
-                    'sanitize_callback' => null,
719
-                ),
720
-            ),
721
-            $model,
722
-            $version
723
-        );
724
-    }
725
-
726
-
727
-
728
-    /**
729
-     * Gets the parameters acceptable for delete requests
730
-     *
731
-     * @param \EEM_Base $model
732
-     * @param string    $version
733
-     * @return array
734
-     */
735
-    protected function _get_delete_query_params(\EEM_Base $model, $version)
736
-    {
737
-        $params_for_delete = array(
738
-            'allow_blocking' => array(
739
-                'required' => false,
740
-                'default'  => true,
741
-                'type'     => 'boolean',
742
-            ),
743
-        );
744
-        $params_for_delete['force'] = array(
745
-            'required' => false,
746
-            'default'  => false,
747
-            'type'     => 'boolean',
748
-        );
749
-        return apply_filters(
750
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
751
-            $params_for_delete,
752
-            $model,
753
-            $version
754
-        );
755
-    }
756
-
757
-
758
-
759
-    /**
760
-     * Gets info about reading query params that are acceptable
761
-     *
762
-     * @param \EEM_Base $model eg 'Event' or 'Venue'
763
-     * @param  string   $version
764
-     * @return array    describing the args acceptable when querying this model
765
-     * @throws EE_Error
766
-     */
767
-    protected function _get_read_query_params(\EEM_Base $model, $version)
768
-    {
769
-        $default_orderby = array();
770
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
771
-            $default_orderby[$key_field->get_name()] = 'ASC';
772
-        }
773
-        return array_merge(
774
-            $this->_get_response_selection_query_params($model, $version),
775
-            array(
776
-                'where'    => array(
777
-                    'required' => false,
778
-                    'default'  => array(),
779
-                    'type'     => 'object',
780
-                    //because we accept an almost infinite list of possible where conditions, WP
781
-                    // core validation and sanitization freaks out. We'll just validate this argument
782
-                    // while handling the request
783
-                    'validate_callback' => null,
784
-                    'sanitize_callback' => null,
785
-                ),
786
-                'limit'    => array(
787
-                    'required' => false,
788
-                    'default'  => EED_Core_Rest_Api::get_default_query_limit(),
789
-                    'type'     => array(
790
-                        'array',
791
-                        'string',
792
-                        'integer',
793
-                    ),
794
-                    //because we accept a variety of types, WP core validation and sanitization
795
-                    //freaks out. We'll just validate this argument while handling the request
796
-                    'validate_callback' => null,
797
-                    'sanitize_callback' => null,
798
-                ),
799
-                'order_by' => array(
800
-                    'required' => false,
801
-                    'default'  => $default_orderby,
802
-                    'type'     => array(
803
-                        'object',
804
-                        'string',
805
-                    ),//because we accept a variety of types, WP core validation and sanitization
806
-                    //freaks out. We'll just validate this argument while handling the request
807
-                    'validate_callback' => null,
808
-                    'sanitize_callback' => null,
809
-                ),
810
-                'group_by' => array(
811
-                    'required' => false,
812
-                    'default'  => null,
813
-                    'type'     => array(
814
-                        'object',
815
-                        'string',
816
-                    ),
817
-                    //because we accept  an almost infinite list of possible groupings,
818
-                    // WP core validation and sanitization
819
-                    //freaks out. We'll just validate this argument while handling the request
820
-                    'validate_callback' => null,
821
-                    'sanitize_callback' => null,
822
-                ),
823
-                'having'   => array(
824
-                    'required' => false,
825
-                    'default'  => null,
826
-                    'type'     => 'object',
827
-                    //because we accept an almost infinite list of possible where conditions, WP
828
-                    // core validation and sanitization freaks out. We'll just validate this argument
829
-                    // while handling the request
830
-                    'validate_callback' => null,
831
-                    'sanitize_callback' => null,
832
-                ),
833
-                'caps'     => array(
834
-                    'required' => false,
835
-                    'default'  => EEM_Base::caps_read,
836
-                    'type'     => 'string',
837
-                    'enum'     => array(
838
-                        EEM_Base::caps_read,
839
-                        EEM_Base::caps_read_admin,
840
-                        EEM_Base::caps_edit,
841
-                        EEM_Base::caps_delete
842
-                    )
843
-                ),
844
-            )
845
-        );
846
-    }
847
-
848
-
849
-
850
-    /**
851
-     * Gets parameter information for a model regarding writing data
852
-     *
853
-     * @param string           $model_name
854
-     * @param ModelVersionInfo $model_version_info
855
-     * @param boolean          $create                                       whether this is for request to create (in which case we need
856
-     *                                                                       all required params) or just to update (in which case we don't need those on every request)
857
-     * @return array
858
-     */
859
-    protected function _get_write_params(
860
-        $model_name,
861
-        ModelVersionInfo $model_version_info,
862
-        $create = false
863
-    ) {
864
-        $model = EE_Registry::instance()->load_model($model_name);
865
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
866
-        $args_info = array();
867
-        foreach ($fields as $field_name => $field_obj) {
868
-            if ($field_obj->is_auto_increment()) {
869
-                //totally ignore auto increment IDs
870
-                continue;
871
-            }
872
-            $arg_info = $field_obj->getSchema();
873
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
874
-            $arg_info['required'] = $required;
875
-            //remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
876
-            unset($arg_info['readonly']);
877
-            $schema_properties = $field_obj->getSchemaProperties();
878
-            if (
879
-                isset($schema_properties['raw'])
880
-                && $field_obj->getSchemaType() === 'object'
881
-            ) {
882
-                //if there's a "raw" form of this argument, use those properties instead
883
-                $arg_info = array_replace(
884
-                    $arg_info,
885
-                    $schema_properties['raw']
886
-                );
887
-            }
888
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
889
-                $field_obj,
890
-                $field_obj->get_default_value(),
891
-                $model_version_info->requestedVersion()
892
-            );
893
-            //we do our own validation and sanitization within the controller
894
-            $arg_info['sanitize_callback'] =
895
-                array(
896
-                    'EED_Core_Rest_Api',
897
-                    'default_sanitize_callback',
898
-                );
899
-            $args_info[$field_name] = $arg_info;
900
-            if ($field_obj instanceof EE_Datetime_Field) {
901
-                $gmt_arg_info = $arg_info;
902
-                $gmt_arg_info['description'] = sprintf(
903
-                    esc_html__(
904
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
905
-                        'event_espresso'
906
-                    ),
907
-                    $field_obj->get_nicename(),
908
-                    $field_name
909
-                );
910
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
911
-            }
912
-        }
913
-        return $args_info;
914
-    }
915
-
916
-
917
-
918
-    /**
919
-     * Replacement for WP API's 'rest_parse_request_arg'.
920
-     * If the value is blank but not required, don't bother validating it.
921
-     * Also, it uses our email validation instead of WP API's default.
922
-     *
923
-     * @param                 $value
924
-     * @param WP_REST_Request $request
925
-     * @param                 $param
926
-     * @return bool|true|WP_Error
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidInterfaceException
929
-     * @throws InvalidDataTypeException
930
-     */
931
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
932
-    {
933
-        $attributes = $request->get_attributes();
934
-        if (! isset($attributes['args'][$param])
935
-            || ! is_array($attributes['args'][$param])) {
936
-            $validation_result = true;
937
-        } else {
938
-            $args = $attributes['args'][$param];
939
-            if ((
940
-                    $value === ''
941
-                    || $value === null
942
-                )
943
-                && (! isset($args['required'])
944
-                    || $args['required'] === false
945
-                )
946
-            ) {
947
-                //not required and not provided? that's cool
948
-                $validation_result = true;
949
-            } elseif (isset($args['format'])
950
-                && $args['format'] === 'email'
951
-            ) {
952
-                $validation_result = true;
953
-                if (! self::_validate_email($value)) {
954
-                    $validation_result = new WP_Error(
955
-                        'rest_invalid_param',
956
-                        esc_html__(
957
-                            'The email address is not valid or does not exist.',
958
-                            'event_espresso'
959
-                        )
960
-                    );
961
-                }
962
-            } else {
963
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
964
-            }
965
-        }
966
-        if (is_wp_error($validation_result)) {
967
-            return $validation_result;
968
-        }
969
-        return rest_sanitize_request_arg($value, $request, $param);
970
-    }
971
-
972
-
973
-
974
-    /**
975
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
976
-     *
977
-     * @param $email
978
-     * @return bool
979
-     * @throws InvalidArgumentException
980
-     * @throws InvalidInterfaceException
981
-     * @throws InvalidDataTypeException
982
-     */
983
-    protected static function _validate_email($email){
984
-        try {
985
-            EmailAddressFactory::create($email);
986
-            return true;
987
-        } catch (EmailValidationException $e) {
988
-            return false;
989
-        }
990
-    }
991
-
992
-
993
-
994
-    /**
995
-     * Gets routes for the config
996
-     *
997
-     * @return array @see _register_model_routes
998
-     * @deprecated since version 4.9.1
999
-     */
1000
-    protected function _register_config_routes()
1001
-    {
1002
-        $config_routes = array();
1003
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1004
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1005
-                $version,
1006
-                $hidden_endpoint
1007
-            );
1008
-        }
1009
-        return $config_routes;
1010
-    }
1011
-
1012
-
1013
-
1014
-    /**
1015
-     * Gets routes for the config for the specified version
1016
-     *
1017
-     * @param string  $version
1018
-     * @param boolean $hidden_endpoint
1019
-     * @return array
1020
-     */
1021
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1022
-    {
1023
-        return array(
1024
-            'config'    => array(
1025
-                array(
1026
-                    'callback'        => array(
1027
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1028
-                        'handleRequest',
1029
-                    ),
1030
-                    'methods'         => WP_REST_Server::READABLE,
1031
-                    'hidden_endpoint' => $hidden_endpoint,
1032
-                    'callback_args'   => array($version),
1033
-                ),
1034
-            ),
1035
-            'site_info' => array(
1036
-                array(
1037
-                    'callback'        => array(
1038
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1039
-                        'handleRequestSiteInfo',
1040
-                    ),
1041
-                    'methods'         => WP_REST_Server::READABLE,
1042
-                    'hidden_endpoint' => $hidden_endpoint,
1043
-                    'callback_args'   => array($version),
1044
-                ),
1045
-            ),
1046
-        );
1047
-    }
1048
-
1049
-
1050
-
1051
-    /**
1052
-     * Gets the meta info routes
1053
-     *
1054
-     * @return array @see _register_model_routes
1055
-     * @deprecated since version 4.9.1
1056
-     */
1057
-    protected function _register_meta_routes()
1058
-    {
1059
-        $meta_routes = array();
1060
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1061
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1062
-                $version,
1063
-                $hidden_endpoint
1064
-            );
1065
-        }
1066
-        return $meta_routes;
1067
-    }
1068
-
1069
-
1070
-
1071
-    /**
1072
-     * @param string  $version
1073
-     * @param boolean $hidden_endpoint
1074
-     * @return array
1075
-     */
1076
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1077
-    {
1078
-        return array(
1079
-            'resources' => array(
1080
-                array(
1081
-                    'callback'        => array(
1082
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1083
-                        'handleRequestModelsMeta',
1084
-                    ),
1085
-                    'methods'         => WP_REST_Server::READABLE,
1086
-                    'hidden_endpoint' => $hidden_endpoint,
1087
-                    'callback_args'   => array($version),
1088
-                ),
1089
-            ),
1090
-        );
1091
-    }
1092
-
1093
-
1094
-
1095
-    /**
1096
-     * Tries to hide old 4.6 endpoints from the
1097
-     *
1098
-     * @param array $route_data
1099
-     * @return array
1100
-     * @throws \EE_Error
1101
-     */
1102
-    public static function hide_old_endpoints($route_data)
1103
-    {
1104
-        //allow API clients to override which endpoints get hidden, in case
1105
-        //they want to discover particular endpoints
1106
-        //also, we don't have access to the request so we have to just grab it from the superglobal
1107
-        $force_show_ee_namespace = ltrim(
1108
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1109
-            '/'
1110
-        );
1111
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1112
-            foreach ($relative_urls as $resource_name => $endpoints) {
1113
-                foreach ($endpoints as $key => $endpoint) {
1114
-                    //skip schema and other route options
1115
-                    if (! is_numeric($key)) {
1116
-                        continue;
1117
-                    }
1118
-                    //by default, hide "hidden_endpoint"s, unless the request indicates
1119
-                    //to $force_show_ee_namespace, in which case only show that one
1120
-                    //namespace's endpoints (and hide all others)
1121
-                    if (
1122
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1123
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1124
-                    ) {
1125
-                        $full_route = '/' . ltrim($namespace, '/');
1126
-                        $full_route .= '/' . ltrim($resource_name, '/');
1127
-                        unset($route_data[$full_route]);
1128
-                    }
1129
-                }
1130
-            }
1131
-        }
1132
-        return $route_data;
1133
-    }
1134
-
1135
-
1136
-
1137
-    /**
1138
-     * Returns an array describing which versions of core support serving requests for.
1139
-     * Keys are core versions' major and minor version, and values are the
1140
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1141
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1142
-     * the answers table entirely, in which case it would be very difficult for
1143
-     * it to serve 4.6-style responses.
1144
-     * Versions of core that are missing from this array are unknowns.
1145
-     * previous ver
1146
-     *
1147
-     * @return array
1148
-     */
1149
-    public static function version_compatibilities()
1150
-    {
1151
-        return apply_filters(
1152
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1153
-            array(
1154
-                '4.8.29' => '4.8.29',
1155
-                '4.8.33' => '4.8.29',
1156
-                '4.8.34' => '4.8.29',
1157
-                '4.8.36' => '4.8.29',
1158
-            )
1159
-        );
1160
-    }
1161
-
1162
-
1163
-
1164
-    /**
1165
-     * Gets the latest API version served. Eg if there
1166
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1167
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1168
-     *
1169
-     * @return string
1170
-     */
1171
-    public static function latest_rest_api_version()
1172
-    {
1173
-        $versions_served = \EED_Core_Rest_Api::versions_served();
1174
-        $versions_served_keys = array_keys($versions_served);
1175
-        return end($versions_served_keys);
1176
-    }
1177
-
1178
-
1179
-
1180
-    /**
1181
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1182
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1183
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1184
-     * We also indicate whether or not this version should be put in the index or not
1185
-     *
1186
-     * @return array keys are API version numbers (just major and minor numbers), and values
1187
-     * are whether or not they should be hidden
1188
-     */
1189
-    public static function versions_served()
1190
-    {
1191
-        $versions_served = array();
1192
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1193
-        $lowest_compatible_version = end($possibly_served_versions);
1194
-        reset($possibly_served_versions);
1195
-        $versions_served_historically = array_keys($possibly_served_versions);
1196
-        $latest_version = end($versions_served_historically);
1197
-        reset($versions_served_historically);
1198
-        //for each version of core we have ever served:
1199
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1200
-            //if it's not above the current core version, and it's compatible with the current version of core
1201
-            if ($key_versioned_endpoint === $latest_version) {
1202
-                //don't hide the latest version in the index
1203
-                $versions_served[$key_versioned_endpoint] = false;
1204
-            } elseif (
1205
-                $key_versioned_endpoint >= $lowest_compatible_version
1206
-                && $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1207
-            ) {
1208
-                //include, but hide, previous versions which are still supported
1209
-                $versions_served[$key_versioned_endpoint] = true;
1210
-            } elseif (apply_filters(
1211
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1212
-                false,
1213
-                $possibly_served_versions
1214
-            )) {
1215
-                //if a version is no longer supported, don't include it in index or list of versions served
1216
-                $versions_served[$key_versioned_endpoint] = true;
1217
-            }
1218
-        }
1219
-        return $versions_served;
1220
-    }
1221
-
1222
-
1223
-
1224
-    /**
1225
-     * Gets the major and minor version of EE core's version string
1226
-     *
1227
-     * @return string
1228
-     */
1229
-    public static function core_version()
1230
-    {
1231
-        return apply_filters(
1232
-            'FHEE__EED_Core_REST_API__core_version',
1233
-            implode(
1234
-                '.',
1235
-                array_slice(
1236
-                    explode(
1237
-                        '.',
1238
-                        espresso_version()
1239
-                    ),
1240
-                0,
1241
-                3
1242
-                )
1243
-            )
1244
-        );
1245
-    }
1246
-
1247
-
1248
-
1249
-    /**
1250
-     * Gets the default limit that should be used when querying for resources
1251
-     *
1252
-     * @return int
1253
-     */
1254
-    public static function get_default_query_limit()
1255
-    {
1256
-        //we actually don't use a const because we want folks to always use
1257
-        //this method, not the const directly
1258
-        return apply_filters(
1259
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1260
-            50
1261
-        );
1262
-    }
1263
-
1264
-
1265
-
1266
-    /**
1267
-     *    run - initial module setup
1268
-     *
1269
-     * @access    public
1270
-     * @param  WP $WP
1271
-     * @return    void
1272
-     */
1273
-    public function run($WP)
1274
-    {
1275
-    }
28
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
29
+
30
+	const saved_routes_option_names  = 'ee_core_routes';
31
+
32
+	/**
33
+	 * string used in _links response bodies to make them globally unique.
34
+	 *
35
+	 * @see http://v2.wp-api.org/extending/linking/
36
+	 */
37
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
38
+
39
+	/**
40
+	 * @var CalculatedModelFields
41
+	 */
42
+	protected static $_field_calculator;
43
+
44
+
45
+
46
+	/**
47
+	 * @return EED_Core_Rest_Api|EED_Module
48
+	 */
49
+	public static function instance()
50
+	{
51
+		self::$_field_calculator = new CalculatedModelFields();
52
+		return parent::get_instance(__CLASS__);
53
+	}
54
+
55
+
56
+
57
+	/**
58
+	 *    set_hooks - for hooking into EE Core, other modules, etc
59
+	 *
60
+	 * @access    public
61
+	 * @return    void
62
+	 */
63
+	public static function set_hooks()
64
+	{
65
+		self::set_hooks_both();
66
+	}
67
+
68
+
69
+
70
+	/**
71
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
72
+	 *
73
+	 * @access    public
74
+	 * @return    void
75
+	 */
76
+	public static function set_hooks_admin()
77
+	{
78
+		self::set_hooks_both();
79
+	}
80
+
81
+
82
+
83
+	public static function set_hooks_both()
84
+	{
85
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
86
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
87
+		add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
88
+		add_filter('rest_index',
89
+			array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex'));
90
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
91
+	}
92
+
93
+
94
+
95
+	/**
96
+	 * sets up hooks which only need to be included as part of REST API requests;
97
+	 * other requests like to the frontend or admin etc don't need them
98
+	 *
99
+	 * @throws \EE_Error
100
+	 */
101
+	public static function set_hooks_rest_api()
102
+	{
103
+		//set hooks which account for changes made to the API
104
+		EED_Core_Rest_Api::_set_hooks_for_changes();
105
+	}
106
+
107
+
108
+
109
+	/**
110
+	 * public wrapper of _set_hooks_for_changes.
111
+	 * Loads all the hooks which make requests to old versions of the API
112
+	 * appear the same as they always did
113
+	 *
114
+	 * @throws EE_Error
115
+	 */
116
+	public static function set_hooks_for_changes()
117
+	{
118
+		self::_set_hooks_for_changes();
119
+	}
120
+
121
+
122
+
123
+	/**
124
+	 * Loads all the hooks which make requests to old versions of the API
125
+	 * appear the same as they always did
126
+	 *
127
+	 * @throws EE_Error
128
+	 */
129
+	protected static function _set_hooks_for_changes()
130
+	{
131
+		$folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
132
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
133
+			//ignore the base parent class
134
+			//and legacy named classes
135
+			if ($classname_in_namespace === 'ChangesInBase'
136
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
137
+			) {
138
+				continue;
139
+			}
140
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
141
+			if (class_exists($full_classname)) {
142
+				$instance_of_class = new $full_classname;
143
+				if ($instance_of_class instanceof ChangesInBase) {
144
+					$instance_of_class->setHooks();
145
+				}
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
+	 */
158
+	public static function register_routes()
159
+	{
160
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
161
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
162
+				/**
163
+				 * @var array $data_for_multiple_endpoints numerically indexed array
164
+				 *                                         but can also contain route options like {
165
+				 * @type array    $schema                      {
166
+				 * @type callable $schema_callback
167
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
168
+				 * WP_REST_Request of course
169
+				 * }
170
+				 * }
171
+				 */
172
+				//when registering routes, register all the endpoints' data at the same time
173
+				$multiple_endpoint_args = array();
174
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
175
+					/**
176
+					 * @var array     $data_for_single_endpoint {
177
+					 * @type callable $callback
178
+					 * @type string methods
179
+					 * @type array args
180
+					 * @type array _links
181
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
182
+					 * WP_REST_Request of course
183
+					 * }
184
+					 */
185
+					//skip route options
186
+					if (! is_numeric($endpoint_key)) {
187
+						continue;
188
+					}
189
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
190
+						throw new EE_Error(
191
+							esc_html__(
192
+								// @codingStandardsIgnoreStart
193
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
194
+								// @codingStandardsIgnoreEnd
195
+								'event_espresso')
196
+						);
197
+					}
198
+					$callback = $data_for_single_endpoint['callback'];
199
+					$single_endpoint_args = array(
200
+						'methods' => $data_for_single_endpoint['methods'],
201
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
202
+							: array(),
203
+					);
204
+					if (isset($data_for_single_endpoint['_links'])) {
205
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
206
+					}
207
+					if (isset($data_for_single_endpoint['callback_args'])) {
208
+						$callback_args = $data_for_single_endpoint['callback_args'];
209
+						$single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
210
+							$callback,
211
+							$callback_args
212
+						) {
213
+							array_unshift($callback_args, $request);
214
+							return call_user_func_array(
215
+								$callback,
216
+								$callback_args
217
+							);
218
+						};
219
+					} else {
220
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
221
+					}
222
+					$multiple_endpoint_args[] = $single_endpoint_args;
223
+				}
224
+				if (isset($data_for_multiple_endpoints['schema'])) {
225
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
226
+					$schema_callback = $schema_route_data['schema_callback'];
227
+					$callback_args = $schema_route_data['callback_args'];
228
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
229
+						return call_user_func_array(
230
+							$schema_callback,
231
+							$callback_args
232
+						);
233
+					};
234
+				}
235
+				register_rest_route(
236
+					$namespace,
237
+					$relative_route,
238
+					$multiple_endpoint_args
239
+				);
240
+			}
241
+		}
242
+	}
243
+
244
+
245
+
246
+	/**
247
+	 * Checks if there was a version change or something that merits invalidating the cached
248
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
249
+	 * next time the WP API is used
250
+	 */
251
+	public static function invalidate_cached_route_data_on_version_change()
252
+	{
253
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
254
+			EED_Core_Rest_Api::invalidate_cached_route_data();
255
+		}
256
+		foreach (EE_Registry::instance()->addons as $addon) {
257
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
258
+				EED_Core_Rest_Api::invalidate_cached_route_data();
259
+			}
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
+	/**
279
+	 * Gets the EE route data
280
+	 *
281
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
282
+	 * @throws \EE_Error
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 = array();
291
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
292
+			$ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
293
+				$version,
294
+				$hidden_endpoints
295
+			);
296
+		}
297
+		return $ee_routes;
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 * Gets the EE route data from the wp options if it exists already,
304
+	 * otherwise re-generates it and saves it to the option
305
+	 *
306
+	 * @param string  $version
307
+	 * @param boolean $hidden_endpoints
308
+	 * @return array
309
+	 * @throws \EE_Error
310
+	 */
311
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
312
+	{
313
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
314
+		if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
315
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
316
+		}
317
+		return $ee_routes;
318
+	}
319
+
320
+
321
+
322
+	/**
323
+	 * Saves the EE REST API route data to a wp option and returns it
324
+	 *
325
+	 * @param string  $version
326
+	 * @param boolean $hidden_endpoints
327
+	 * @return mixed|null
328
+	 * @throws \EE_Error
329
+	 */
330
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
331
+	{
332
+		$instance = self::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 = self::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
+	/**
354
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
355
+	 * need to calculate it on every request
356
+	 *
357
+	 * @deprecated since version 4.9.1
358
+	 * @return void
359
+	 */
360
+	public static function save_ee_routes()
361
+	{
362
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
363
+			$instance = self::instance();
364
+			$routes = apply_filters(
365
+				'EED_Core_Rest_Api__save_ee_routes__routes',
366
+				array_replace_recursive(
367
+					$instance->_register_config_routes(),
368
+					$instance->_register_meta_routes(),
369
+					$instance->_register_model_routes(),
370
+					$instance->_register_rpc_routes()
371
+				)
372
+			);
373
+			update_option(self::saved_routes_option_names, $routes, true);
374
+		}
375
+	}
376
+
377
+
378
+
379
+	/**
380
+	 * Gets all the route information relating to EE models
381
+	 *
382
+	 * @return array @see get_ee_route_data
383
+	 * @deprecated since version 4.9.1
384
+	 */
385
+	protected function _register_model_routes()
386
+	{
387
+		$model_routes = array();
388
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
389
+			$model_routes[EED_Core_Rest_Api::ee_api_namespace
390
+						  . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
391
+		}
392
+		return $model_routes;
393
+	}
394
+
395
+
396
+
397
+	/**
398
+	 * Decides whether or not to add write endpoints for this model.
399
+	 *
400
+	 * Currently, this defaults to exclude all global tables and models
401
+	 * which would allow inserting WP core data (we don't want to duplicate
402
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
403
+	 * @param EEM_Base $model
404
+	 * @return bool
405
+	 */
406
+	public static function should_have_write_endpoints(EEM_Base $model)
407
+	{
408
+		if ($model->is_wp_core_model()){
409
+			return false;
410
+		}
411
+		foreach($model->get_tables() as $table){
412
+			if( $table->is_global()){
413
+				return false;
414
+			}
415
+		}
416
+		return true;
417
+	}
418
+
419
+
420
+
421
+	/**
422
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
423
+	 * in this versioned namespace of EE4
424
+	 * @param $version
425
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
426
+	 */
427
+	public static function model_names_with_plural_routes($version){
428
+		$model_version_info = new ModelVersionInfo($version);
429
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
430
+		//let's not bother having endpoints for extra metas
431
+		unset(
432
+			$models_to_register['Extra_Meta'],
433
+			$models_to_register['Extra_Join'],
434
+			$models_to_register['Post_Meta']
435
+		);
436
+		return apply_filters(
437
+			'FHEE__EED_Core_REST_API___register_model_routes',
438
+			$models_to_register
439
+		);
440
+	}
441
+
442
+
443
+
444
+	/**
445
+	 * Gets the route data for EE models in the specified version
446
+	 *
447
+	 * @param string  $version
448
+	 * @param boolean $hidden_endpoint
449
+	 * @return array
450
+	 * @throws EE_Error
451
+	 */
452
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
453
+	{
454
+		$model_routes = array();
455
+		$model_version_info = new ModelVersionInfo($version);
456
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
457
+			$model = \EE_Registry::instance()->load_model($model_name);
458
+			//if this isn't a valid model then let's skip iterate to the next item in the loop.
459
+			if (! $model instanceof EEM_Base) {
460
+				continue;
461
+			}
462
+			//yes we could just register one route for ALL models, but then they wouldn't show up in the index
463
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
464
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
465
+			$model_routes[$plural_model_route] = array(
466
+				array(
467
+					'callback'        => array(
468
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
469
+						'handleRequestGetAll',
470
+					),
471
+					'callback_args'   => array($version, $model_name),
472
+					'methods'         => WP_REST_Server::READABLE,
473
+					'hidden_endpoint' => $hidden_endpoint,
474
+					'args'            => $this->_get_read_query_params($model, $version),
475
+					'_links'          => array(
476
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
477
+					),
478
+				),
479
+				'schema' => array(
480
+					'schema_callback' => array(
481
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
482
+						'handleSchemaRequest',
483
+					),
484
+					'callback_args'   => array($version, $model_name),
485
+				),
486
+			);
487
+			$model_routes[$singular_model_route] = array(
488
+				array(
489
+					'callback'        => array(
490
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
491
+						'handleRequestGetOne',
492
+					),
493
+					'callback_args'   => array($version, $model_name),
494
+					'methods'         => WP_REST_Server::READABLE,
495
+					'hidden_endpoint' => $hidden_endpoint,
496
+					'args'            => $this->_get_response_selection_query_params($model, $version),
497
+				),
498
+			);
499
+			if( apply_filters(
500
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
501
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
502
+				$model
503
+			)){
504
+				$model_routes[$plural_model_route][] = array(
505
+					'callback'        => array(
506
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
507
+						'handleRequestInsert',
508
+					),
509
+					'callback_args'   => array($version, $model_name),
510
+					'methods'         => WP_REST_Server::CREATABLE,
511
+					'hidden_endpoint' => $hidden_endpoint,
512
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
513
+				);
514
+				$model_routes[$singular_model_route] = array_merge(
515
+					$model_routes[$singular_model_route],
516
+					array(
517
+						array(
518
+							'callback'        => array(
519
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
520
+								'handleRequestUpdate',
521
+							),
522
+							'callback_args'   => array($version, $model_name),
523
+							'methods'         => WP_REST_Server::EDITABLE,
524
+							'hidden_endpoint' => $hidden_endpoint,
525
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
526
+						),
527
+						array(
528
+							'callback'        => array(
529
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
530
+								'handleRequestDelete',
531
+							),
532
+							'callback_args'   => array($version, $model_name),
533
+							'methods'         => WP_REST_Server::DELETABLE,
534
+							'hidden_endpoint' => $hidden_endpoint,
535
+							'args'            => $this->_get_delete_query_params($model, $version),
536
+						)
537
+					)
538
+				);
539
+			}
540
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
541
+
542
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
543
+					$model,
544
+					'(?P<id>[^\/]+)',
545
+					$relation_obj
546
+				);
547
+				$endpoints = array(
548
+					array(
549
+						'callback'        => array(
550
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
551
+							'handleRequestGetRelated',
552
+						),
553
+						'callback_args'   => array($version, $model_name, $relation_name),
554
+						'methods'         => WP_REST_Server::READABLE,
555
+						'hidden_endpoint' => $hidden_endpoint,
556
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
557
+					),
558
+				);
559
+				$model_routes[$related_route] = $endpoints;
560
+			}
561
+		}
562
+		return $model_routes;
563
+	}
564
+
565
+
566
+
567
+	/**
568
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
569
+	 * excluding the preceding slash.
570
+	 * Eg you pass get_plural_route_to('Event') = 'events'
571
+	 *
572
+	 * @param EEM_Base $model
573
+	 * @return string
574
+	 */
575
+	public static function get_collection_route(EEM_Base $model)
576
+	{
577
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
578
+	}
579
+
580
+
581
+
582
+	/**
583
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
584
+	 * excluding the preceding slash.
585
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
586
+	 *
587
+	 * @param EEM_Base $model eg Event or Venue
588
+	 * @param string $id
589
+	 * @return string
590
+	 */
591
+	public static function get_entity_route($model, $id)
592
+	{
593
+		return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
594
+	}
595
+
596
+
597
+	/**
598
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
599
+	 * excluding the preceding slash.
600
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
601
+	 *
602
+	 * @param EEM_Base                 $model eg Event or Venue
603
+	 * @param string                 $id
604
+	 * @param EE_Model_Relation_Base $relation_obj
605
+	 * @return string
606
+	 */
607
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
608
+	{
609
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
610
+			$relation_obj->get_other_model()->get_this_model_name(),
611
+			$relation_obj
612
+		);
613
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
614
+	}
615
+
616
+
617
+
618
+	/**
619
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
620
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
621
+	 * @param string $relative_route
622
+	 * @param string $version
623
+	 * @return string
624
+	 */
625
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
626
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
627
+	}
628
+
629
+
630
+
631
+	/**
632
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
633
+	 * routes that don't conform to the traditional REST CRUD-style).
634
+	 *
635
+	 * @deprecated since 4.9.1
636
+	 */
637
+	protected function _register_rpc_routes()
638
+	{
639
+		$routes = array();
640
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
641
+			$routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
642
+				$version,
643
+				$hidden_endpoint
644
+			);
645
+		}
646
+		return $routes;
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * @param string  $version
653
+	 * @param boolean $hidden_endpoint
654
+	 * @return array
655
+	 */
656
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
657
+	{
658
+		$this_versions_routes = array();
659
+		//checkin endpoint
660
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
661
+			array(
662
+				'callback'        => array(
663
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
664
+					'handleRequestToggleCheckin',
665
+				),
666
+				'methods'         => WP_REST_Server::CREATABLE,
667
+				'hidden_endpoint' => $hidden_endpoint,
668
+				'args'            => array(
669
+					'force' => array(
670
+						'required'    => false,
671
+						'default'     => false,
672
+						'description' => __(
673
+							// @codingStandardsIgnoreStart
674
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
675
+							// @codingStandardsIgnoreEnd
676
+							'event_espresso'
677
+						),
678
+					),
679
+				),
680
+				'callback_args'   => array($version),
681
+			),
682
+		);
683
+		return apply_filters(
684
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
685
+			$this_versions_routes,
686
+			$version,
687
+			$hidden_endpoint
688
+		);
689
+	}
690
+
691
+
692
+
693
+	/**
694
+	 * Gets the query params that can be used when request one or many
695
+	 *
696
+	 * @param EEM_Base $model
697
+	 * @param string   $version
698
+	 * @return array
699
+	 */
700
+	protected function _get_response_selection_query_params(\EEM_Base $model, $version)
701
+	{
702
+		return apply_filters(
703
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
704
+			array(
705
+				'include'   => array(
706
+					'required' => false,
707
+					'default'  => '*',
708
+					'type'     => 'string',
709
+				),
710
+				'calculate' => array(
711
+					'required'          => false,
712
+					'default'           => '',
713
+					'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
714
+					'type'              => 'string',
715
+					//because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
716
+					//freaks out. We'll just validate this argument while handling the request
717
+					'validate_callback' => null,
718
+					'sanitize_callback' => null,
719
+				),
720
+			),
721
+			$model,
722
+			$version
723
+		);
724
+	}
725
+
726
+
727
+
728
+	/**
729
+	 * Gets the parameters acceptable for delete requests
730
+	 *
731
+	 * @param \EEM_Base $model
732
+	 * @param string    $version
733
+	 * @return array
734
+	 */
735
+	protected function _get_delete_query_params(\EEM_Base $model, $version)
736
+	{
737
+		$params_for_delete = array(
738
+			'allow_blocking' => array(
739
+				'required' => false,
740
+				'default'  => true,
741
+				'type'     => 'boolean',
742
+			),
743
+		);
744
+		$params_for_delete['force'] = array(
745
+			'required' => false,
746
+			'default'  => false,
747
+			'type'     => 'boolean',
748
+		);
749
+		return apply_filters(
750
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
751
+			$params_for_delete,
752
+			$model,
753
+			$version
754
+		);
755
+	}
756
+
757
+
758
+
759
+	/**
760
+	 * Gets info about reading query params that are acceptable
761
+	 *
762
+	 * @param \EEM_Base $model eg 'Event' or 'Venue'
763
+	 * @param  string   $version
764
+	 * @return array    describing the args acceptable when querying this model
765
+	 * @throws EE_Error
766
+	 */
767
+	protected function _get_read_query_params(\EEM_Base $model, $version)
768
+	{
769
+		$default_orderby = array();
770
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
771
+			$default_orderby[$key_field->get_name()] = 'ASC';
772
+		}
773
+		return array_merge(
774
+			$this->_get_response_selection_query_params($model, $version),
775
+			array(
776
+				'where'    => array(
777
+					'required' => false,
778
+					'default'  => array(),
779
+					'type'     => 'object',
780
+					//because we accept an almost infinite list of possible where conditions, WP
781
+					// core validation and sanitization freaks out. We'll just validate this argument
782
+					// while handling the request
783
+					'validate_callback' => null,
784
+					'sanitize_callback' => null,
785
+				),
786
+				'limit'    => array(
787
+					'required' => false,
788
+					'default'  => EED_Core_Rest_Api::get_default_query_limit(),
789
+					'type'     => array(
790
+						'array',
791
+						'string',
792
+						'integer',
793
+					),
794
+					//because we accept a variety of types, WP core validation and sanitization
795
+					//freaks out. We'll just validate this argument while handling the request
796
+					'validate_callback' => null,
797
+					'sanitize_callback' => null,
798
+				),
799
+				'order_by' => array(
800
+					'required' => false,
801
+					'default'  => $default_orderby,
802
+					'type'     => array(
803
+						'object',
804
+						'string',
805
+					),//because we accept a variety of types, WP core validation and sanitization
806
+					//freaks out. We'll just validate this argument while handling the request
807
+					'validate_callback' => null,
808
+					'sanitize_callback' => null,
809
+				),
810
+				'group_by' => array(
811
+					'required' => false,
812
+					'default'  => null,
813
+					'type'     => array(
814
+						'object',
815
+						'string',
816
+					),
817
+					//because we accept  an almost infinite list of possible groupings,
818
+					// WP core validation and sanitization
819
+					//freaks out. We'll just validate this argument while handling the request
820
+					'validate_callback' => null,
821
+					'sanitize_callback' => null,
822
+				),
823
+				'having'   => array(
824
+					'required' => false,
825
+					'default'  => null,
826
+					'type'     => 'object',
827
+					//because we accept an almost infinite list of possible where conditions, WP
828
+					// core validation and sanitization freaks out. We'll just validate this argument
829
+					// while handling the request
830
+					'validate_callback' => null,
831
+					'sanitize_callback' => null,
832
+				),
833
+				'caps'     => array(
834
+					'required' => false,
835
+					'default'  => EEM_Base::caps_read,
836
+					'type'     => 'string',
837
+					'enum'     => array(
838
+						EEM_Base::caps_read,
839
+						EEM_Base::caps_read_admin,
840
+						EEM_Base::caps_edit,
841
+						EEM_Base::caps_delete
842
+					)
843
+				),
844
+			)
845
+		);
846
+	}
847
+
848
+
849
+
850
+	/**
851
+	 * Gets parameter information for a model regarding writing data
852
+	 *
853
+	 * @param string           $model_name
854
+	 * @param ModelVersionInfo $model_version_info
855
+	 * @param boolean          $create                                       whether this is for request to create (in which case we need
856
+	 *                                                                       all required params) or just to update (in which case we don't need those on every request)
857
+	 * @return array
858
+	 */
859
+	protected function _get_write_params(
860
+		$model_name,
861
+		ModelVersionInfo $model_version_info,
862
+		$create = false
863
+	) {
864
+		$model = EE_Registry::instance()->load_model($model_name);
865
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
866
+		$args_info = array();
867
+		foreach ($fields as $field_name => $field_obj) {
868
+			if ($field_obj->is_auto_increment()) {
869
+				//totally ignore auto increment IDs
870
+				continue;
871
+			}
872
+			$arg_info = $field_obj->getSchema();
873
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
874
+			$arg_info['required'] = $required;
875
+			//remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
876
+			unset($arg_info['readonly']);
877
+			$schema_properties = $field_obj->getSchemaProperties();
878
+			if (
879
+				isset($schema_properties['raw'])
880
+				&& $field_obj->getSchemaType() === 'object'
881
+			) {
882
+				//if there's a "raw" form of this argument, use those properties instead
883
+				$arg_info = array_replace(
884
+					$arg_info,
885
+					$schema_properties['raw']
886
+				);
887
+			}
888
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
889
+				$field_obj,
890
+				$field_obj->get_default_value(),
891
+				$model_version_info->requestedVersion()
892
+			);
893
+			//we do our own validation and sanitization within the controller
894
+			$arg_info['sanitize_callback'] =
895
+				array(
896
+					'EED_Core_Rest_Api',
897
+					'default_sanitize_callback',
898
+				);
899
+			$args_info[$field_name] = $arg_info;
900
+			if ($field_obj instanceof EE_Datetime_Field) {
901
+				$gmt_arg_info = $arg_info;
902
+				$gmt_arg_info['description'] = sprintf(
903
+					esc_html__(
904
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
905
+						'event_espresso'
906
+					),
907
+					$field_obj->get_nicename(),
908
+					$field_name
909
+				);
910
+				$args_info[$field_name . '_gmt'] = $gmt_arg_info;
911
+			}
912
+		}
913
+		return $args_info;
914
+	}
915
+
916
+
917
+
918
+	/**
919
+	 * Replacement for WP API's 'rest_parse_request_arg'.
920
+	 * If the value is blank but not required, don't bother validating it.
921
+	 * Also, it uses our email validation instead of WP API's default.
922
+	 *
923
+	 * @param                 $value
924
+	 * @param WP_REST_Request $request
925
+	 * @param                 $param
926
+	 * @return bool|true|WP_Error
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidInterfaceException
929
+	 * @throws InvalidDataTypeException
930
+	 */
931
+	public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
932
+	{
933
+		$attributes = $request->get_attributes();
934
+		if (! isset($attributes['args'][$param])
935
+			|| ! is_array($attributes['args'][$param])) {
936
+			$validation_result = true;
937
+		} else {
938
+			$args = $attributes['args'][$param];
939
+			if ((
940
+					$value === ''
941
+					|| $value === null
942
+				)
943
+				&& (! isset($args['required'])
944
+					|| $args['required'] === false
945
+				)
946
+			) {
947
+				//not required and not provided? that's cool
948
+				$validation_result = true;
949
+			} elseif (isset($args['format'])
950
+				&& $args['format'] === 'email'
951
+			) {
952
+				$validation_result = true;
953
+				if (! self::_validate_email($value)) {
954
+					$validation_result = new WP_Error(
955
+						'rest_invalid_param',
956
+						esc_html__(
957
+							'The email address is not valid or does not exist.',
958
+							'event_espresso'
959
+						)
960
+					);
961
+				}
962
+			} else {
963
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
964
+			}
965
+		}
966
+		if (is_wp_error($validation_result)) {
967
+			return $validation_result;
968
+		}
969
+		return rest_sanitize_request_arg($value, $request, $param);
970
+	}
971
+
972
+
973
+
974
+	/**
975
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
976
+	 *
977
+	 * @param $email
978
+	 * @return bool
979
+	 * @throws InvalidArgumentException
980
+	 * @throws InvalidInterfaceException
981
+	 * @throws InvalidDataTypeException
982
+	 */
983
+	protected static function _validate_email($email){
984
+		try {
985
+			EmailAddressFactory::create($email);
986
+			return true;
987
+		} catch (EmailValidationException $e) {
988
+			return false;
989
+		}
990
+	}
991
+
992
+
993
+
994
+	/**
995
+	 * Gets routes for the config
996
+	 *
997
+	 * @return array @see _register_model_routes
998
+	 * @deprecated since version 4.9.1
999
+	 */
1000
+	protected function _register_config_routes()
1001
+	{
1002
+		$config_routes = array();
1003
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1004
+			$config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1005
+				$version,
1006
+				$hidden_endpoint
1007
+			);
1008
+		}
1009
+		return $config_routes;
1010
+	}
1011
+
1012
+
1013
+
1014
+	/**
1015
+	 * Gets routes for the config for the specified version
1016
+	 *
1017
+	 * @param string  $version
1018
+	 * @param boolean $hidden_endpoint
1019
+	 * @return array
1020
+	 */
1021
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1022
+	{
1023
+		return array(
1024
+			'config'    => array(
1025
+				array(
1026
+					'callback'        => array(
1027
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1028
+						'handleRequest',
1029
+					),
1030
+					'methods'         => WP_REST_Server::READABLE,
1031
+					'hidden_endpoint' => $hidden_endpoint,
1032
+					'callback_args'   => array($version),
1033
+				),
1034
+			),
1035
+			'site_info' => array(
1036
+				array(
1037
+					'callback'        => array(
1038
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1039
+						'handleRequestSiteInfo',
1040
+					),
1041
+					'methods'         => WP_REST_Server::READABLE,
1042
+					'hidden_endpoint' => $hidden_endpoint,
1043
+					'callback_args'   => array($version),
1044
+				),
1045
+			),
1046
+		);
1047
+	}
1048
+
1049
+
1050
+
1051
+	/**
1052
+	 * Gets the meta info routes
1053
+	 *
1054
+	 * @return array @see _register_model_routes
1055
+	 * @deprecated since version 4.9.1
1056
+	 */
1057
+	protected function _register_meta_routes()
1058
+	{
1059
+		$meta_routes = array();
1060
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1061
+			$meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1062
+				$version,
1063
+				$hidden_endpoint
1064
+			);
1065
+		}
1066
+		return $meta_routes;
1067
+	}
1068
+
1069
+
1070
+
1071
+	/**
1072
+	 * @param string  $version
1073
+	 * @param boolean $hidden_endpoint
1074
+	 * @return array
1075
+	 */
1076
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1077
+	{
1078
+		return array(
1079
+			'resources' => array(
1080
+				array(
1081
+					'callback'        => array(
1082
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1083
+						'handleRequestModelsMeta',
1084
+					),
1085
+					'methods'         => WP_REST_Server::READABLE,
1086
+					'hidden_endpoint' => $hidden_endpoint,
1087
+					'callback_args'   => array($version),
1088
+				),
1089
+			),
1090
+		);
1091
+	}
1092
+
1093
+
1094
+
1095
+	/**
1096
+	 * Tries to hide old 4.6 endpoints from the
1097
+	 *
1098
+	 * @param array $route_data
1099
+	 * @return array
1100
+	 * @throws \EE_Error
1101
+	 */
1102
+	public static function hide_old_endpoints($route_data)
1103
+	{
1104
+		//allow API clients to override which endpoints get hidden, in case
1105
+		//they want to discover particular endpoints
1106
+		//also, we don't have access to the request so we have to just grab it from the superglobal
1107
+		$force_show_ee_namespace = ltrim(
1108
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1109
+			'/'
1110
+		);
1111
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1112
+			foreach ($relative_urls as $resource_name => $endpoints) {
1113
+				foreach ($endpoints as $key => $endpoint) {
1114
+					//skip schema and other route options
1115
+					if (! is_numeric($key)) {
1116
+						continue;
1117
+					}
1118
+					//by default, hide "hidden_endpoint"s, unless the request indicates
1119
+					//to $force_show_ee_namespace, in which case only show that one
1120
+					//namespace's endpoints (and hide all others)
1121
+					if (
1122
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1123
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1124
+					) {
1125
+						$full_route = '/' . ltrim($namespace, '/');
1126
+						$full_route .= '/' . ltrim($resource_name, '/');
1127
+						unset($route_data[$full_route]);
1128
+					}
1129
+				}
1130
+			}
1131
+		}
1132
+		return $route_data;
1133
+	}
1134
+
1135
+
1136
+
1137
+	/**
1138
+	 * Returns an array describing which versions of core support serving requests for.
1139
+	 * Keys are core versions' major and minor version, and values are the
1140
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1141
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1142
+	 * the answers table entirely, in which case it would be very difficult for
1143
+	 * it to serve 4.6-style responses.
1144
+	 * Versions of core that are missing from this array are unknowns.
1145
+	 * previous ver
1146
+	 *
1147
+	 * @return array
1148
+	 */
1149
+	public static function version_compatibilities()
1150
+	{
1151
+		return apply_filters(
1152
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1153
+			array(
1154
+				'4.8.29' => '4.8.29',
1155
+				'4.8.33' => '4.8.29',
1156
+				'4.8.34' => '4.8.29',
1157
+				'4.8.36' => '4.8.29',
1158
+			)
1159
+		);
1160
+	}
1161
+
1162
+
1163
+
1164
+	/**
1165
+	 * Gets the latest API version served. Eg if there
1166
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1167
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1168
+	 *
1169
+	 * @return string
1170
+	 */
1171
+	public static function latest_rest_api_version()
1172
+	{
1173
+		$versions_served = \EED_Core_Rest_Api::versions_served();
1174
+		$versions_served_keys = array_keys($versions_served);
1175
+		return end($versions_served_keys);
1176
+	}
1177
+
1178
+
1179
+
1180
+	/**
1181
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1182
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1183
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1184
+	 * We also indicate whether or not this version should be put in the index or not
1185
+	 *
1186
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1187
+	 * are whether or not they should be hidden
1188
+	 */
1189
+	public static function versions_served()
1190
+	{
1191
+		$versions_served = array();
1192
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1193
+		$lowest_compatible_version = end($possibly_served_versions);
1194
+		reset($possibly_served_versions);
1195
+		$versions_served_historically = array_keys($possibly_served_versions);
1196
+		$latest_version = end($versions_served_historically);
1197
+		reset($versions_served_historically);
1198
+		//for each version of core we have ever served:
1199
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1200
+			//if it's not above the current core version, and it's compatible with the current version of core
1201
+			if ($key_versioned_endpoint === $latest_version) {
1202
+				//don't hide the latest version in the index
1203
+				$versions_served[$key_versioned_endpoint] = false;
1204
+			} elseif (
1205
+				$key_versioned_endpoint >= $lowest_compatible_version
1206
+				&& $key_versioned_endpoint < EED_Core_Rest_Api::core_version()
1207
+			) {
1208
+				//include, but hide, previous versions which are still supported
1209
+				$versions_served[$key_versioned_endpoint] = true;
1210
+			} elseif (apply_filters(
1211
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1212
+				false,
1213
+				$possibly_served_versions
1214
+			)) {
1215
+				//if a version is no longer supported, don't include it in index or list of versions served
1216
+				$versions_served[$key_versioned_endpoint] = true;
1217
+			}
1218
+		}
1219
+		return $versions_served;
1220
+	}
1221
+
1222
+
1223
+
1224
+	/**
1225
+	 * Gets the major and minor version of EE core's version string
1226
+	 *
1227
+	 * @return string
1228
+	 */
1229
+	public static function core_version()
1230
+	{
1231
+		return apply_filters(
1232
+			'FHEE__EED_Core_REST_API__core_version',
1233
+			implode(
1234
+				'.',
1235
+				array_slice(
1236
+					explode(
1237
+						'.',
1238
+						espresso_version()
1239
+					),
1240
+				0,
1241
+				3
1242
+				)
1243
+			)
1244
+		);
1245
+	}
1246
+
1247
+
1248
+
1249
+	/**
1250
+	 * Gets the default limit that should be used when querying for resources
1251
+	 *
1252
+	 * @return int
1253
+	 */
1254
+	public static function get_default_query_limit()
1255
+	{
1256
+		//we actually don't use a const because we want folks to always use
1257
+		//this method, not the const directly
1258
+		return apply_filters(
1259
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1260
+			50
1261
+		);
1262
+	}
1263
+
1264
+
1265
+
1266
+	/**
1267
+	 *    run - initial module setup
1268
+	 *
1269
+	 * @access    public
1270
+	 * @param  WP $WP
1271
+	 * @return    void
1272
+	 */
1273
+	public function run($WP)
1274
+	{
1275
+	}
1276 1276
 }
1277 1277
 
1278 1278
 // End of file EED_Core_Rest_Api.module.php
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
      */
129 129
     protected static function _set_hooks_for_changes()
130 130
     {
131
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
131
+        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES.'rest_api'.DS.'changes'), false);
132 132
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
133 133
             //ignore the base parent class
134 134
             //and legacy named classes
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
             ) {
138 138
                 continue;
139 139
             }
140
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
140
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
141 141
             if (class_exists($full_classname)) {
142 142
                 $instance_of_class = new $full_classname;
143 143
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -183,10 +183,10 @@  discard block
 block discarded – undo
183 183
                      * }
184 184
                      */
185 185
                     //skip route options
186
-                    if (! is_numeric($endpoint_key)) {
186
+                    if ( ! is_numeric($endpoint_key)) {
187 187
                         continue;
188 188
                     }
189
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
189
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
190 190
                         throw new EE_Error(
191 191
                             esc_html__(
192 192
                                 // @codingStandardsIgnoreStart
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
                     }
207 207
                     if (isset($data_for_single_endpoint['callback_args'])) {
208 208
                         $callback_args = $data_for_single_endpoint['callback_args'];
209
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
209
+                        $single_endpoint_args['callback'] = function(\WP_REST_Request $request) use (
210 210
                             $callback,
211 211
                             $callback_args
212 212
                         ) {
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
226 226
                     $schema_callback = $schema_route_data['schema_callback'];
227 227
                     $callback_args = $schema_route_data['callback_args'];
228
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
228
+                    $multiple_endpoint_args['schema'] = function() use ($schema_callback, $callback_args) {
229 229
                         return call_user_func_array(
230 230
                             $schema_callback,
231 231
                             $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 = array();
291 291
         foreach (self::versions_served() as $version => $hidden_endpoints) {
292
-            $ee_routes[self::ee_api_namespace . $version] = self::_get_ee_route_data_for_version(
292
+            $ee_routes[self::ee_api_namespace.$version] = self::_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(self::saved_routes_option_names . $version, null);
314
-        if (! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
313
+        $ee_routes = get_option(self::saved_routes_option_names.$version, null);
314
+        if ( ! $ee_routes || (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE)) {
315 315
             $ee_routes = self::_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 = self::saved_routes_option_names . $version;
342
+        $option_name = self::saved_routes_option_names.$version;
343 343
         if (get_option($option_name)) {
344 344
             update_option($option_name, $routes, true);
345 345
         } else {
@@ -405,11 +405,11 @@  discard block
 block discarded – undo
405 405
      */
406 406
     public static function should_have_write_endpoints(EEM_Base $model)
407 407
     {
408
-        if ($model->is_wp_core_model()){
408
+        if ($model->is_wp_core_model()) {
409 409
             return false;
410 410
         }
411
-        foreach($model->get_tables() as $table){
412
-            if( $table->is_global()){
411
+        foreach ($model->get_tables() as $table) {
412
+            if ($table->is_global()) {
413 413
                 return false;
414 414
             }
415 415
         }
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
      * @param $version
425 425
      * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
426 426
      */
427
-    public static function model_names_with_plural_routes($version){
427
+    public static function model_names_with_plural_routes($version) {
428 428
         $model_version_info = new ModelVersionInfo($version);
429 429
         $models_to_register = $model_version_info->modelsForRequestedVersion();
430 430
         //let's not bother having endpoints for extra metas
@@ -456,7 +456,7 @@  discard block
 block discarded – undo
456 456
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
457 457
             $model = \EE_Registry::instance()->load_model($model_name);
458 458
             //if this isn't a valid model then let's skip iterate to the next item in the loop.
459
-            if (! $model instanceof EEM_Base) {
459
+            if ( ! $model instanceof EEM_Base) {
460 460
                 continue;
461 461
             }
462 462
             //yes we could just register one route for ALL models, but then they wouldn't show up in the index
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
                     'hidden_endpoint' => $hidden_endpoint,
474 474
                     'args'            => $this->_get_read_query_params($model, $version),
475 475
                     '_links'          => array(
476
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
476
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
477 477
                     ),
478 478
                 ),
479 479
                 'schema' => array(
@@ -496,11 +496,11 @@  discard block
 block discarded – undo
496 496
                     'args'            => $this->_get_response_selection_query_params($model, $version),
497 497
                 ),
498 498
             );
499
-            if( apply_filters(
499
+            if (apply_filters(
500 500
                 'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
501 501
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
502 502
                 $model
503
-            )){
503
+            )) {
504 504
                 $model_routes[$plural_model_route][] = array(
505 505
                     'callback'        => array(
506 506
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
@@ -590,7 +590,7 @@  discard block
 block discarded – undo
590 590
      */
591 591
     public static function get_entity_route($model, $id)
592 592
     {
593
-        return EED_Core_Rest_Api::get_collection_route($model). '/' . $id;
593
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
594 594
     }
595 595
 
596 596
 
@@ -610,7 +610,7 @@  discard block
 block discarded – undo
610 610
             $relation_obj->get_other_model()->get_this_model_name(),
611 611
             $relation_obj
612 612
         );
613
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
613
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
614 614
     }
615 615
 
616 616
 
@@ -622,8 +622,8 @@  discard block
 block discarded – undo
622 622
      * @param string $version
623 623
      * @return string
624 624
      */
625
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36'){
626
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
625
+    public static function get_versioned_route_to($relative_route, $version = '4.8.36') {
626
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
627 627
     }
628 628
 
629 629
 
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
     {
639 639
         $routes = array();
640 640
         foreach (self::versions_served() as $version => $hidden_endpoint) {
641
-            $routes[self::ee_api_namespace . $version] = $this->_get_rpc_route_data_for_version(
641
+            $routes[self::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
642 642
                 $version,
643 643
                 $hidden_endpoint
644 644
             );
@@ -802,7 +802,7 @@  discard block
 block discarded – undo
802 802
                     'type'     => array(
803 803
                         'object',
804 804
                         'string',
805
-                    ),//because we accept a variety of types, WP core validation and sanitization
805
+                    ), //because we accept a variety of types, WP core validation and sanitization
806 806
                     //freaks out. We'll just validate this argument while handling the request
807 807
                     'validate_callback' => null,
808 808
                     'sanitize_callback' => null,
@@ -907,7 +907,7 @@  discard block
 block discarded – undo
907 907
                     $field_obj->get_nicename(),
908 908
                     $field_name
909 909
                 );
910
-                $args_info[$field_name . '_gmt'] = $gmt_arg_info;
910
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
911 911
             }
912 912
         }
913 913
         return $args_info;
@@ -928,10 +928,10 @@  discard block
 block discarded – undo
928 928
      * @throws InvalidInterfaceException
929 929
      * @throws InvalidDataTypeException
930 930
      */
931
-    public static function default_sanitize_callback( $value, WP_REST_Request $request, $param)
931
+    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
932 932
     {
933 933
         $attributes = $request->get_attributes();
934
-        if (! isset($attributes['args'][$param])
934
+        if ( ! isset($attributes['args'][$param])
935 935
             || ! is_array($attributes['args'][$param])) {
936 936
             $validation_result = true;
937 937
         } else {
@@ -940,7 +940,7 @@  discard block
 block discarded – undo
940 940
                     $value === ''
941 941
                     || $value === null
942 942
                 )
943
-                && (! isset($args['required'])
943
+                && ( ! isset($args['required'])
944 944
                     || $args['required'] === false
945 945
                 )
946 946
             ) {
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
                 && $args['format'] === 'email'
951 951
             ) {
952 952
                 $validation_result = true;
953
-                if (! self::_validate_email($value)) {
953
+                if ( ! self::_validate_email($value)) {
954 954
                     $validation_result = new WP_Error(
955 955
                         'rest_invalid_param',
956 956
                         esc_html__(
@@ -980,7 +980,7 @@  discard block
 block discarded – undo
980 980
      * @throws InvalidInterfaceException
981 981
      * @throws InvalidDataTypeException
982 982
      */
983
-    protected static function _validate_email($email){
983
+    protected static function _validate_email($email) {
984 984
         try {
985 985
             EmailAddressFactory::create($email);
986 986
             return true;
@@ -1001,7 +1001,7 @@  discard block
 block discarded – undo
1001 1001
     {
1002 1002
         $config_routes = array();
1003 1003
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1004
-            $config_routes[self::ee_api_namespace . $version] = $this->_get_config_route_data_for_version(
1004
+            $config_routes[self::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1005 1005
                 $version,
1006 1006
                 $hidden_endpoint
1007 1007
             );
@@ -1058,7 +1058,7 @@  discard block
 block discarded – undo
1058 1058
     {
1059 1059
         $meta_routes = array();
1060 1060
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1061
-            $meta_routes[self::ee_api_namespace . $version] = $this->_get_meta_route_data_for_version(
1061
+            $meta_routes[self::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1062 1062
                 $version,
1063 1063
                 $hidden_endpoint
1064 1064
             );
@@ -1112,7 +1112,7 @@  discard block
 block discarded – undo
1112 1112
             foreach ($relative_urls as $resource_name => $endpoints) {
1113 1113
                 foreach ($endpoints as $key => $endpoint) {
1114 1114
                     //skip schema and other route options
1115
-                    if (! is_numeric($key)) {
1115
+                    if ( ! is_numeric($key)) {
1116 1116
                         continue;
1117 1117
                     }
1118 1118
                     //by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1122,8 +1122,8 @@  discard block
 block discarded – undo
1122 1122
                         ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1123 1123
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1124 1124
                     ) {
1125
-                        $full_route = '/' . ltrim($namespace, '/');
1126
-                        $full_route .= '/' . ltrim($resource_name, '/');
1125
+                        $full_route = '/'.ltrim($namespace, '/');
1126
+                        $full_route .= '/'.ltrim($resource_name, '/');
1127 1127
                         unset($route_data[$full_route]);
1128 1128
                     }
1129 1129
                 }
Please login to merge, or discard this patch.
core/request_stack/EE_Request.core.php 2 patches
Indentation   +322 added lines, -322 removed lines patch added patch discarded remove patch
@@ -16,328 +16,328 @@
 block discarded – undo
16 16
 class EE_Request implements InterminableInterface
17 17
 {
18 18
 
19
-    /**
20
-     * $_GET parameters
21
-     *
22
-     * @var array $_get
23
-     */
24
-    private $_get;
25
-
26
-    /**
27
-     * $_POST parameters
28
-     *
29
-     * @var    array $_post
30
-     */
31
-    private $_post;
32
-
33
-    /**
34
-     * $_COOKIE parameters
35
-     *
36
-     * @var array $_cookie
37
-     */
38
-    private $_cookie;
39
-
40
-    /**
41
-     * $_REQUEST parameters
42
-     *
43
-     * @var array $_params
44
-     */
45
-    private $_params;
46
-
47
-    /**
48
-     * whether current request is for the admin but NOT via AJAX
49
-     *
50
-     * @var boolean $admin
51
-     */
52
-    public $admin = false;
53
-
54
-    /**
55
-     * whether current request is via AJAX
56
-     *
57
-     * @var boolean $ajax
58
-     */
59
-    public $ajax = false;
60
-
61
-    /**
62
-     * whether current request is via AJAX from the frontend of the site
63
-     *
64
-     * @var boolean $front_ajax
65
-     */
66
-    public $front_ajax = false;
67
-
68
-    /**
69
-     * IP address for request
70
-     *
71
-     * @var string $_ip_address
72
-     */
73
-    private $_ip_address;
74
-
75
-
76
-
77
-    /**
78
-     * class constructor
79
-     *
80
-     * @access    public
81
-     * @param array $get
82
-     * @param array $post
83
-     * @param array $cookie
84
-     */
85
-    public function __construct(array $get, array $post, array $cookie)
86
-    {
87
-        // grab request vars
88
-        $this->_get    = $get;
89
-        $this->_post   = $post;
90
-        $this->_cookie = $cookie;
91
-        $this->_params = array_merge($this->_get, $this->_post);
92
-        // AJAX ???
93
-        $this->ajax       = defined('DOING_AJAX') && DOING_AJAX;
94
-        $this->front_ajax = $this->ajax
95
-                            && $this->is_set('ee_front_ajax')
96
-                            && filter_var($this->get('ee_front_ajax'), FILTER_VALIDATE_BOOLEAN);
97
-        $this->admin      = is_admin() && ! $this->ajax;
98
-        // grab user IP
99
-        $this->_ip_address = $this->_visitor_ip();
100
-    }
101
-
102
-
103
-
104
-    /**
105
-     * @return array
106
-     */
107
-    public function get_params()
108
-    {
109
-        return $this->_get;
110
-    }
111
-
112
-
113
-
114
-    /**
115
-     * @return array
116
-     */
117
-    public function post_params()
118
-    {
119
-        return $this->_post;
120
-    }
121
-
122
-
123
-
124
-    /**
125
-     * @return array
126
-     */
127
-    public function cookie_params()
128
-    {
129
-        return $this->_cookie;
130
-    }
131
-
132
-
133
-
134
-    /**
135
-     * returns contents of $_REQUEST
136
-     *
137
-     * @return array
138
-     */
139
-    public function params()
140
-    {
141
-        return $this->_params;
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     * @param      $key
148
-     * @param      $value
149
-     * @param bool $override_ee
150
-     * @return    void
151
-     */
152
-    public function set($key, $value, $override_ee = false)
153
-    {
154
-        // don't allow "ee" to be overwritten unless explicitly instructed to do so
155
-        if (
156
-            $key !== 'ee'
157
-            || ($key === 'ee' && empty($this->_params['ee']))
158
-            || ($key === 'ee' && ! empty($this->_params['ee']) && $override_ee)
159
-        ) {
160
-            $this->_params[$key] = $value;
161
-        }
162
-    }
163
-
164
-
165
-
166
-    /**
167
-     * returns   the value for a request param if the given key exists
168
-     *
169
-     * @param       $key
170
-     * @param null  $default
171
-     * @return mixed
172
-     */
173
-    public function get($key, $default = null)
174
-    {
175
-        return $this->request_parameter_drill_down($key, $default, 'get');
176
-    }
177
-
178
-
179
-
180
-    /**
181
-     * check if param exists
182
-     *
183
-     * @param       $key
184
-     * @return bool
185
-     */
186
-    public function is_set($key)
187
-    {
188
-        return $this->request_parameter_drill_down($key);
189
-    }
190
-
191
-
192
-
193
-    /**
194
-     * the supplied key can be a simple string to represent a "top-level" request parameter
195
-     * or represent a key for a request parameter that is nested deeper within the request parameter array,
196
-     * by using square brackets to surround keys for deeper array elements.
197
-     * For example :
198
-     * if the supplied $key was: "first[second][third]"
199
-     * then this will attempt to drill down into the request parameter array to find a value.
200
-     * Given the following request parameters:
201
-     *  array(
202
-     *      'first' => array(
203
-     *          'second' => array(
204
-     *              'third' => 'has a value'
205
-     *          )
206
-     *      )
207
-     *  )
208
-     * would return true
209
-     *
210
-     * @param string $is_set_or_get
211
-     * @param        $key
212
-     * @param null   $default
213
-     * @param array  $request_params
214
-     * @return bool|mixed|null
215
-     */
216
-    private function request_parameter_drill_down(
217
-        $key,
218
-        $default = null,
219
-        $is_set_or_get = 'is_set',
220
-        array $request_params = array()
221
-    ) {
222
-        $request_params = ! empty($request_params)
223
-            ? $request_params
224
-            : $this->_params;
225
-        // does incoming key represent an array like 'first[second][third]'  ?
226
-        if (strpos($key, '[') !== false) {
227
-            // turn it into an actual array
228
-            $key  = str_replace(']', '', $key);
229
-            $keys = explode('[', $key);
230
-            $key  = array_shift($keys);
231
-            // check if top level key exists
232
-            if (isset($request_params[$key])) {
233
-                // build a new key to pass along like: 'second[third]'
234
-                // or just 'second' depending on depth of keys
235
-                $key_string = array_shift($keys);
236
-                if (! empty($keys)) {
237
-                    $key_string .= '[' . implode('][', $keys) . ']';
238
-                }
239
-                return $this->request_parameter_drill_down(
240
-                    $key_string,
241
-                    $default,
242
-                    $is_set_or_get,
243
-                    $request_params[$key]
244
-                );
245
-            }
246
-        }
247
-        if ($is_set_or_get === 'is_set') {
248
-            return isset($request_params[$key]);
249
-        }
250
-        return isset($request_params[$key])
251
-            ? $request_params[$key]
252
-            : $default;
253
-    }
254
-
255
-
256
-
257
-    /**
258
-     * remove param
259
-     *
260
-     * @param      $key
261
-     * @param bool $unset_from_global_too
262
-     */
263
-    public function un_set($key, $unset_from_global_too = false)
264
-    {
265
-        unset($this->_params[$key]);
266
-        if ($unset_from_global_too) {
267
-            unset($_REQUEST[$key]);
268
-        }
269
-    }
270
-
271
-
272
-
273
-    /**
274
-     * @return string
275
-     */
276
-    public function ip_address()
277
-    {
278
-        return $this->_ip_address;
279
-    }
280
-
281
-
282
-    /**
283
-     * @return bool
284
-     */
285
-    public function isAdmin()
286
-    {
287
-        return $this->admin;
288
-    }
289
-
290
-
291
-    /**
292
-     * @return mixed
293
-     */
294
-    public function isAjax()
295
-    {
296
-        return $this->ajax;
297
-    }
298
-
299
-
300
-    /**
301
-     * @return mixed
302
-     */
303
-    public function isFrontAjax()
304
-    {
305
-        return $this->front_ajax;
306
-    }
307
-
308
-
309
-
310
-    /**
311
-     * _visitor_ip
312
-     *    attempt to get IP address of current visitor from server
313
-     * plz see: http://stackoverflow.com/a/2031935/1475279
314
-     *
315
-     * @access public
316
-     * @return string
317
-     */
318
-    private function _visitor_ip()
319
-    {
320
-        $visitor_ip  = '0.0.0.0';
321
-        $server_keys = array(
322
-            'HTTP_CLIENT_IP',
323
-            'HTTP_X_FORWARDED_FOR',
324
-            'HTTP_X_FORWARDED',
325
-            'HTTP_X_CLUSTER_CLIENT_IP',
326
-            'HTTP_FORWARDED_FOR',
327
-            'HTTP_FORWARDED',
328
-            'REMOTE_ADDR',
329
-        );
330
-        foreach ($server_keys as $key) {
331
-            if (isset($_SERVER[$key])) {
332
-                foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
333
-                    if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
334
-                        $visitor_ip = $ip;
335
-                    }
336
-                }
337
-            }
338
-        }
339
-        return $visitor_ip;
340
-    }
19
+	/**
20
+	 * $_GET parameters
21
+	 *
22
+	 * @var array $_get
23
+	 */
24
+	private $_get;
25
+
26
+	/**
27
+	 * $_POST parameters
28
+	 *
29
+	 * @var    array $_post
30
+	 */
31
+	private $_post;
32
+
33
+	/**
34
+	 * $_COOKIE parameters
35
+	 *
36
+	 * @var array $_cookie
37
+	 */
38
+	private $_cookie;
39
+
40
+	/**
41
+	 * $_REQUEST parameters
42
+	 *
43
+	 * @var array $_params
44
+	 */
45
+	private $_params;
46
+
47
+	/**
48
+	 * whether current request is for the admin but NOT via AJAX
49
+	 *
50
+	 * @var boolean $admin
51
+	 */
52
+	public $admin = false;
53
+
54
+	/**
55
+	 * whether current request is via AJAX
56
+	 *
57
+	 * @var boolean $ajax
58
+	 */
59
+	public $ajax = false;
60
+
61
+	/**
62
+	 * whether current request is via AJAX from the frontend of the site
63
+	 *
64
+	 * @var boolean $front_ajax
65
+	 */
66
+	public $front_ajax = false;
67
+
68
+	/**
69
+	 * IP address for request
70
+	 *
71
+	 * @var string $_ip_address
72
+	 */
73
+	private $_ip_address;
74
+
75
+
76
+
77
+	/**
78
+	 * class constructor
79
+	 *
80
+	 * @access    public
81
+	 * @param array $get
82
+	 * @param array $post
83
+	 * @param array $cookie
84
+	 */
85
+	public function __construct(array $get, array $post, array $cookie)
86
+	{
87
+		// grab request vars
88
+		$this->_get    = $get;
89
+		$this->_post   = $post;
90
+		$this->_cookie = $cookie;
91
+		$this->_params = array_merge($this->_get, $this->_post);
92
+		// AJAX ???
93
+		$this->ajax       = defined('DOING_AJAX') && DOING_AJAX;
94
+		$this->front_ajax = $this->ajax
95
+							&& $this->is_set('ee_front_ajax')
96
+							&& filter_var($this->get('ee_front_ajax'), FILTER_VALIDATE_BOOLEAN);
97
+		$this->admin      = is_admin() && ! $this->ajax;
98
+		// grab user IP
99
+		$this->_ip_address = $this->_visitor_ip();
100
+	}
101
+
102
+
103
+
104
+	/**
105
+	 * @return array
106
+	 */
107
+	public function get_params()
108
+	{
109
+		return $this->_get;
110
+	}
111
+
112
+
113
+
114
+	/**
115
+	 * @return array
116
+	 */
117
+	public function post_params()
118
+	{
119
+		return $this->_post;
120
+	}
121
+
122
+
123
+
124
+	/**
125
+	 * @return array
126
+	 */
127
+	public function cookie_params()
128
+	{
129
+		return $this->_cookie;
130
+	}
131
+
132
+
133
+
134
+	/**
135
+	 * returns contents of $_REQUEST
136
+	 *
137
+	 * @return array
138
+	 */
139
+	public function params()
140
+	{
141
+		return $this->_params;
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 * @param      $key
148
+	 * @param      $value
149
+	 * @param bool $override_ee
150
+	 * @return    void
151
+	 */
152
+	public function set($key, $value, $override_ee = false)
153
+	{
154
+		// don't allow "ee" to be overwritten unless explicitly instructed to do so
155
+		if (
156
+			$key !== 'ee'
157
+			|| ($key === 'ee' && empty($this->_params['ee']))
158
+			|| ($key === 'ee' && ! empty($this->_params['ee']) && $override_ee)
159
+		) {
160
+			$this->_params[$key] = $value;
161
+		}
162
+	}
163
+
164
+
165
+
166
+	/**
167
+	 * returns   the value for a request param if the given key exists
168
+	 *
169
+	 * @param       $key
170
+	 * @param null  $default
171
+	 * @return mixed
172
+	 */
173
+	public function get($key, $default = null)
174
+	{
175
+		return $this->request_parameter_drill_down($key, $default, 'get');
176
+	}
177
+
178
+
179
+
180
+	/**
181
+	 * check if param exists
182
+	 *
183
+	 * @param       $key
184
+	 * @return bool
185
+	 */
186
+	public function is_set($key)
187
+	{
188
+		return $this->request_parameter_drill_down($key);
189
+	}
190
+
191
+
192
+
193
+	/**
194
+	 * the supplied key can be a simple string to represent a "top-level" request parameter
195
+	 * or represent a key for a request parameter that is nested deeper within the request parameter array,
196
+	 * by using square brackets to surround keys for deeper array elements.
197
+	 * For example :
198
+	 * if the supplied $key was: "first[second][third]"
199
+	 * then this will attempt to drill down into the request parameter array to find a value.
200
+	 * Given the following request parameters:
201
+	 *  array(
202
+	 *      'first' => array(
203
+	 *          'second' => array(
204
+	 *              'third' => 'has a value'
205
+	 *          )
206
+	 *      )
207
+	 *  )
208
+	 * would return true
209
+	 *
210
+	 * @param string $is_set_or_get
211
+	 * @param        $key
212
+	 * @param null   $default
213
+	 * @param array  $request_params
214
+	 * @return bool|mixed|null
215
+	 */
216
+	private function request_parameter_drill_down(
217
+		$key,
218
+		$default = null,
219
+		$is_set_or_get = 'is_set',
220
+		array $request_params = array()
221
+	) {
222
+		$request_params = ! empty($request_params)
223
+			? $request_params
224
+			: $this->_params;
225
+		// does incoming key represent an array like 'first[second][third]'  ?
226
+		if (strpos($key, '[') !== false) {
227
+			// turn it into an actual array
228
+			$key  = str_replace(']', '', $key);
229
+			$keys = explode('[', $key);
230
+			$key  = array_shift($keys);
231
+			// check if top level key exists
232
+			if (isset($request_params[$key])) {
233
+				// build a new key to pass along like: 'second[third]'
234
+				// or just 'second' depending on depth of keys
235
+				$key_string = array_shift($keys);
236
+				if (! empty($keys)) {
237
+					$key_string .= '[' . implode('][', $keys) . ']';
238
+				}
239
+				return $this->request_parameter_drill_down(
240
+					$key_string,
241
+					$default,
242
+					$is_set_or_get,
243
+					$request_params[$key]
244
+				);
245
+			}
246
+		}
247
+		if ($is_set_or_get === 'is_set') {
248
+			return isset($request_params[$key]);
249
+		}
250
+		return isset($request_params[$key])
251
+			? $request_params[$key]
252
+			: $default;
253
+	}
254
+
255
+
256
+
257
+	/**
258
+	 * remove param
259
+	 *
260
+	 * @param      $key
261
+	 * @param bool $unset_from_global_too
262
+	 */
263
+	public function un_set($key, $unset_from_global_too = false)
264
+	{
265
+		unset($this->_params[$key]);
266
+		if ($unset_from_global_too) {
267
+			unset($_REQUEST[$key]);
268
+		}
269
+	}
270
+
271
+
272
+
273
+	/**
274
+	 * @return string
275
+	 */
276
+	public function ip_address()
277
+	{
278
+		return $this->_ip_address;
279
+	}
280
+
281
+
282
+	/**
283
+	 * @return bool
284
+	 */
285
+	public function isAdmin()
286
+	{
287
+		return $this->admin;
288
+	}
289
+
290
+
291
+	/**
292
+	 * @return mixed
293
+	 */
294
+	public function isAjax()
295
+	{
296
+		return $this->ajax;
297
+	}
298
+
299
+
300
+	/**
301
+	 * @return mixed
302
+	 */
303
+	public function isFrontAjax()
304
+	{
305
+		return $this->front_ajax;
306
+	}
307
+
308
+
309
+
310
+	/**
311
+	 * _visitor_ip
312
+	 *    attempt to get IP address of current visitor from server
313
+	 * plz see: http://stackoverflow.com/a/2031935/1475279
314
+	 *
315
+	 * @access public
316
+	 * @return string
317
+	 */
318
+	private function _visitor_ip()
319
+	{
320
+		$visitor_ip  = '0.0.0.0';
321
+		$server_keys = array(
322
+			'HTTP_CLIENT_IP',
323
+			'HTTP_X_FORWARDED_FOR',
324
+			'HTTP_X_FORWARDED',
325
+			'HTTP_X_CLUSTER_CLIENT_IP',
326
+			'HTTP_FORWARDED_FOR',
327
+			'HTTP_FORWARDED',
328
+			'REMOTE_ADDR',
329
+		);
330
+		foreach ($server_keys as $key) {
331
+			if (isset($_SERVER[$key])) {
332
+				foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
333
+					if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
334
+						$visitor_ip = $ip;
335
+					}
336
+				}
337
+			}
338
+		}
339
+		return $visitor_ip;
340
+	}
341 341
 
342 342
 
343 343
 
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -233,8 +233,8 @@
 block discarded – undo
233 233
                 // build a new key to pass along like: 'second[third]'
234 234
                 // or just 'second' depending on depth of keys
235 235
                 $key_string = array_shift($keys);
236
-                if (! empty($keys)) {
237
-                    $key_string .= '[' . implode('][', $keys) . ']';
236
+                if ( ! empty($keys)) {
237
+                    $key_string .= '['.implode('][', $keys).']';
238 238
                 }
239 239
                 return $this->request_parameter_drill_down(
240 240
                     $key_string,
Please login to merge, or discard this patch.
modules/events_archive/EED_Events_Archive.module.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
 
275 275
     /**
276 276
      * @access public
277
-     * @return string
277
+     * @return boolean
278 278
      */
279 279
     public static function is_iframe()
280 280
     {
@@ -892,7 +892,7 @@  discard block
 block discarded – undo
892 892
      *    display_description
893 893
      *
894 894
      * @access    public
895
-     * @param $value
895
+     * @param integer $value
896 896
      * @return    bool
897 897
      */
898 898
     public static function display_description($value)
Please login to merge, or discard this patch.
Indentation   +1089 added lines, -1089 removed lines patch added patch discarded remove patch
@@ -17,1110 +17,1110 @@  discard block
 block discarded – undo
17 17
 class EED_Events_Archive extends EED_Module
18 18
 {
19 19
 
20
-    const EVENT_DETAILS_PRIORITY   = 100;
21
-
22
-    const EVENT_DATETIMES_PRIORITY = 110;
23
-
24
-    const EVENT_TICKETS_PRIORITY   = 120;
25
-
26
-    const EVENT_VENUES_PRIORITY    = 130;
27
-
28
-
29
-    public static $espresso_event_list_ID    = 0;
30
-
31
-    public static $espresso_grid_event_lists = array();
32
-
33
-    /**
34
-     * @type bool $using_get_the_excerpt
35
-     */
36
-    protected static $using_get_the_excerpt = false;
37
-
38
-    /**
39
-     * Used to flag when the event list is being called from an external iframe.
40
-     *
41
-     * @var bool $iframe
42
-     */
43
-    protected static $iframe = false;
44
-
45
-    /**
46
-     * @var \EventEspresso\core\libraries\iframe_display\EventListIframeEmbedButton $_iframe_embed_button
47
-     */
48
-    private static $_iframe_embed_button;
49
-
50
-    /**
51
-     * @type EE_Template_Part_Manager $template_parts
52
-     */
53
-    protected $template_parts;
54
-
55
-
56
-
57
-    /**
58
-     * @return EED_Events_Archive
59
-     */
60
-    public static function instance()
61
-    {
62
-        return parent::get_instance(__CLASS__);
63
-    }
64
-
65
-
66
-
67
-    /**
68
-     *    set_hooks - for hooking into EE Core, other modules, etc
69
-     *
70
-     * @access    public
71
-     * @return    void
72
-     */
73
-    public static function set_hooks()
74
-    {
75
-        $custom_post_types = EE_Register_CPTs::get_CPTs();
76
-        EE_Config::register_route(
77
-            $custom_post_types['espresso_events']['plural_slug'],
78
-            'Events_Archive',
79
-            'run'
80
-        );
81
-        EE_Config::register_route(
82
-            'event_list',
83
-            'Events_Archive',
84
-            'event_list'
85
-        );
86
-        EE_Config::register_route(
87
-            'iframe',
88
-            'Events_Archive',
89
-            'event_list_iframe',
90
-            'event_list'
91
-        );
92
-        add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
93
-    }
94
-
95
-
96
-
97
-    /**
98
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
99
-     *
100
-     * @access    public
101
-     * @return    void
102
-     */
103
-    public static function set_hooks_admin()
104
-    {
105
-        add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
106
-        // hook into the end of the \EE_Admin_Page::_load_page_dependencies()
107
-        // to load assets for "espresso_events" page on the "default" route (action)
108
-        add_action(
109
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
110
-            array('EED_Events_Archive', 'event_list_iframe_embed_button'),
111
-            10
112
-        );
113
-    }
114
-
115
-
116
-
117
-    /**
118
-     *    set_definitions
119
-     *
120
-     * @access    public
121
-     * @return    void
122
-     */
123
-    public static function set_definitions()
124
-    {
125
-        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets' . DS);
126
-        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)) . 'templates' . DS);
127
-    }
128
-
129
-
130
-
131
-    /**
132
-     * set up EE_Events_Archive_Config
133
-     */
134
-    protected function set_config()
135
-    {
136
-        $this->set_config_section('template_settings');
137
-        $this->set_config_class('EE_Events_Archive_Config');
138
-        $this->set_config_name('EED_Events_Archive');
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * @return EventListIframeEmbedButton
145
-     */
146
-    public static function get_iframe_embed_button()
147
-    {
148
-        if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
149
-            self::$_iframe_embed_button = new EventListIframeEmbedButton();
150
-        }
151
-        return self::$_iframe_embed_button;
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     * event_list_iframe_embed_button
158
-     *
159
-     * @return    void
160
-     * @throws \EE_Error
161
-     */
162
-    public static function event_list_iframe_embed_button()
163
-    {
164
-        $iframe_embed_button = \EED_Events_Archive::get_iframe_embed_button();
165
-        $iframe_embed_button->addEmbedButton();
166
-    }
167
-
168
-
169
-
170
-    /**
171
-     *    initialize_template_parts
172
-     *
173
-     * @access    public
174
-     * @param \EE_Events_Archive_Config $config
175
-     * @return \EE_Template_Part_Manager
176
-     */
177
-    public function initialize_template_parts(EE_Events_Archive_Config $config = null)
178
-    {
179
-        $config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
180
-        EEH_Autoloader::instance()->register_template_part_autoloaders();
181
-        $template_parts = new EE_Template_Part_Manager();
182
-        $template_parts->add_template_part(
183
-            'tickets',
184
-            __('Ticket Selector', 'event_espresso'),
185
-            'content-espresso_events-tickets.php',
186
-            $config->display_order_tickets
187
-        );
188
-        $template_parts->add_template_part(
189
-            'datetimes',
190
-            __('Dates and Times', 'event_espresso'),
191
-            'content-espresso_events-datetimes.php',
192
-            $config->display_order_datetimes
193
-        );
194
-        $template_parts->add_template_part(
195
-            'event',
196
-            __('Event Description', 'event_espresso'),
197
-            'content-espresso_events-details.php',
198
-            $config->display_order_event
199
-        );
200
-        $template_parts->add_template_part(
201
-            'venue',
202
-            __('Venue Information', 'event_espresso'),
203
-            'content-espresso_events-venues.php',
204
-            $config->display_order_venue
205
-        );
206
-        do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
207
-        return $template_parts;
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     *    run - initial module setup - this gets called by the EE_Front_Controller if the module route is found in the incoming request
214
-     *
215
-     * @access    public
216
-     * @param WP $WP
217
-     * @return    void
218
-     */
219
-    public function run($WP)
220
-    {
221
-        do_action('AHEE__EED_Events_Archive__before_run');
222
-        // ensure valid EE_Events_Archive_Config() object exists
223
-        $this->set_config();
224
-        /** @type EE_Events_Archive_Config $config */
225
-        $config = $this->config();
226
-        // load other required components
227
-        $this->load_event_list_assets();
228
-        // filter the WP posts_join, posts_where, and posts_orderby SQL clauses
229
-        //add query filters
230
-        EEH_Event_Query::add_query_filters();
231
-        // set params that will get used by the filters
232
-        EEH_Event_Query::set_query_params(
233
-            '',    // month
234
-            '',    // category
235
-            $config->display_expired_events,    // show_expired
236
-            'start_date',    // orderby
237
-            'ASC'    // sort
238
-        );
239
-        // check what template is loaded
240
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
241
-    }
242
-
243
-
244
-
245
-    /**
246
-     * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
247
-     *
248
-     * @return    void
249
-     */
250
-    public function event_list()
251
-    {
252
-        // ensure valid EE_Events_Archive_Config() object exists
253
-        $this->set_config();
254
-        // load other required components
255
-        $this->load_event_list_assets();
256
-    }
257
-
258
-
259
-
260
-    /**
261
-     * @access    public
262
-     * @return    void
263
-     * @throws \EE_Error
264
-     * @throws \DomainException
265
-     */
266
-    public function event_list_iframe()
267
-    {
268
-        \EED_Events_Archive::$iframe = true;
269
-        $event_list_iframe = new EventsArchiveIframe($this);
270
-        $event_list_iframe->display();
271
-    }
272
-
273
-
274
-
275
-    /**
276
-     * @access public
277
-     * @return string
278
-     */
279
-    public static function is_iframe()
280
-    {
281
-        return \EED_Events_Archive::$iframe;
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @access public
288
-     * @return string
289
-     */
290
-    public static function link_target()
291
-    {
292
-        return \EED_Events_Archive::$iframe ? ' target="_blank"' : '';
293
-    }
294
-
295
-
296
-
297
-    /**
298
-     *    template_include
299
-     *
300
-     * @access    public
301
-     * @param string $template
302
-     * @return    string
303
-     */
304
-    public function template_include($template = '')
305
-    {
306
-        // don't add content filter for dedicated EE child themes or private posts
307
-        if (! EEH_Template::is_espresso_theme()) {
308
-            /** @type EE_Events_Archive_Config $config */
309
-            $config = $this->config();
310
-            // add status banner ?
311
-            if ($config->display_status_banner) {
312
-                add_filter('the_title', array('EED_Events_Archive', 'the_title'), 100, 2);
313
-            }
314
-            // if NOT a custom template
315
-            if (
316
-                apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
317
-                || EE_Registry::instance()
318
-                              ->load_core('Front_Controller')
319
-                              ->get_selected_template() !== 'archive-espresso_events.php'
320
-            ) {
321
-                // don't display entry meta because the existing theme will take care of that
322
-                add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
323
-                // load functions.php file for the theme (loaded by WP if using child theme)
324
-                EEH_Template::load_espresso_theme_functions();
325
-                // because we don't know if the theme is using the_excerpt()
326
-                add_filter(
327
-                    'the_excerpt',
328
-                    array('EED_Events_Archive', 'event_details'),
329
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
330
-                );
331
-                // or the_content
332
-                add_filter(
333
-                    'the_content',
334
-                    array('EED_Events_Archive', 'event_details'),
335
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
336
-                );
337
-                // and just in case they are running get_the_excerpt() which DESTROYS things
338
-                add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
339
-                // don't display entry meta because the existing theme will take care of that
340
-                add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
341
-            }
342
-        }
343
-        return $template;
344
-    }
345
-
346
-
347
-
348
-    /**
349
-     *    get_the_excerpt - kinda hacky, but if a theme is using get_the_excerpt(), then we need to remove our filters on the_content()
350
-     *
351
-     * @access    public
352
-     * @param        string $excerpt
353
-     * @return        string
354
-     */
355
-    public static function get_the_excerpt($excerpt = '')
356
-    {
357
-        if (post_password_required()) {
358
-            return $excerpt;
359
-        }
360
-        if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
361
-            remove_filter(
362
-                'the_excerpt',
363
-                array('EED_Events_Archive', 'event_details'),
364
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
365
-            );
366
-            remove_filter(
367
-                'the_content',
368
-                array('EED_Events_Archive', 'event_details'),
369
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
370
-            );
371
-            $excerpt = EED_Events_Archive::event_details($excerpt);
372
-        } else {
373
-            EED_Events_Archive::$using_get_the_excerpt = true;
374
-            add_filter('wp_trim_excerpt', array('EED_Events_Archive', 'end_get_the_excerpt'), 999, 1);
375
-        }
376
-        return $excerpt;
377
-    }
378
-
379
-
380
-
381
-    /**
382
-     * end_get_the_excerpt
383
-     *
384
-     * @access public
385
-     * @param  string $text
386
-     * @return string
387
-     */
388
-    public static function end_get_the_excerpt($text = '')
389
-    {
390
-        EED_Events_Archive::$using_get_the_excerpt = false;
391
-        return $text;
392
-    }
393
-
394
-
395
-
396
-    /**
397
-     *    the_title
398
-     *
399
-     * @access        public
400
-     * @param        string $title
401
-     * @param        string $id
402
-     * @return        string
403
-     */
404
-    public static function the_title($title = '', $id = '')
405
-    {
406
-        global $post;
407
-        if ($post instanceof WP_Post) {
408
-            return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID) . $title : $title;
409
-        }
410
-        return $title;
411
-    }
412
-
413
-
414
-
415
-    /**
416
-     *    event_details
417
-     *
418
-     * @access    public
419
-     * @param        string $content
420
-     * @return        string
421
-     */
422
-    public static function event_details($content)
423
-    {
424
-        global $post;
425
-        static $current_post_ID = 0;
426
-        if (
427
-            $current_post_ID !== $post->ID
428
-            && $post->post_type === 'espresso_events'
429
-            && ! EED_Events_Archive::$using_get_the_excerpt
430
-            && ! post_password_required()
431
-            && (
432
-                apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
433
-                || ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
434
-            )
435
-        ) {
436
-            // Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
437
-            // Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
438
-            // BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
439
-            // We want to allow those plugins to still do their thing and have access to our content, but depending on
440
-            // how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
441
-            // so the following allows this filter to be applied multiple times, but only once for real
442
-            $current_post_ID = did_action('loop_start') ? $post->ID : 0;
443
-            if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
444
-                $content = \EED_Events_Archive::use_sortable_display_order();
445
-            } else {
446
-                $content = \EED_Events_Archive::use_filterable_display_order();
447
-            }
448
-        }
449
-        return $content;
450
-    }
451
-
452
-
453
-
454
-    /**
455
-     *    use_sortable_display_order
456
-     *
457
-     * @access    protected
458
-     * @return string
459
-     */
460
-    protected static function use_sortable_display_order()
461
-    {
462
-        // no further password checks required atm
463
-        add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
464
-        // we need to first remove this callback from being applied to the_content() or the_excerpt()
465
-        // (otherwise it will recurse and blow up the interweb)
466
-        remove_filter(
467
-            'the_excerpt',
468
-            array('EED_Events_Archive', 'event_details'),
469
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
470
-        );
471
-        remove_filter(
472
-            'the_content',
473
-            array('EED_Events_Archive', 'event_details'),
474
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
475
-        );
476
-        remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
477
-        // now add additional content depending on whether event is using the_excerpt() or the_content()
478
-        EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
479
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
480
-        $content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
481
-        // re-add our main filters (or else the next event won't have them)
482
-        add_filter(
483
-            'the_excerpt',
484
-            array('EED_Events_Archive', 'event_details'),
485
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
486
-        );
487
-        add_filter(
488
-            'the_content',
489
-            array('EED_Events_Archive', 'event_details'),
490
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
491
-        );
492
-        add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
493
-        remove_filter(
494
-            'FHEE__EED_Events_Archive__event_details__no_post_password_required',
495
-            '__return_true'
496
-        );
497
-        return $content;
498
-    }
499
-
500
-
501
-
502
-    /**
503
-     *    use_filterable_display_order
504
-     *
505
-     * @access    protected
506
-     * @return    string
507
-     */
508
-    protected static function use_filterable_display_order()
509
-    {
510
-        // we need to first remove this callback from being applied to the_content()
511
-        // (otherwise it will recurse and blow up the interweb)
512
-        remove_filter(
513
-            'the_excerpt',
514
-            array('EED_Events_Archive', 'event_details'),
515
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
516
-        );
517
-        remove_filter(
518
-            'the_content',
519
-            array('EED_Events_Archive', 'event_details'),
520
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
521
-        );
522
-        remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
523
-        //now add additional content depending on whether event is using the_excerpt() or the_content()
524
-        EED_Events_Archive::_add_additional_excerpt_filters();
525
-        EED_Events_Archive::_add_additional_content_filters();
526
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
527
-        // now load our template
528
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
529
-        // re-add our main filters (or else the next event won't have them)
530
-        add_filter(
531
-            'the_excerpt',
532
-            array('EED_Events_Archive', 'event_details'),
533
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
534
-        );
535
-        add_filter(
536
-            'the_content',
537
-            array('EED_Events_Archive', 'event_details'),
538
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
539
-        );
540
-        add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
541
-        // but remove the other filters so that they don't get applied to the next post
542
-        EED_Events_Archive::_remove_additional_events_archive_filters();
543
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
544
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
545
-        //return ! empty( $template ) ? $template : $content;
546
-        return $content;
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     *    event_datetimes - adds datetimes ABOVE content
553
-     *
554
-     * @access    public
555
-     * @param        string $content
556
-     * @return        string
557
-     */
558
-    public static function event_datetimes($content)
559
-    {
560
-        if (post_password_required()) {
561
-            return $content;
562
-        }
563
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
564
-    }
565
-
566
-
567
-
568
-    /**
569
-     *    event_tickets - adds tickets ABOVE content (which includes datetimes)
570
-     *
571
-     * @access    public
572
-     * @param        string $content
573
-     * @return        string
574
-     */
575
-    public static function event_tickets($content)
576
-    {
577
-        if (post_password_required()) {
578
-            return $content;
579
-        }
580
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     *    event_venues - adds venues BELOW content
587
-     *
588
-     * @access    public
589
-     * @param    string $content
590
-     * @return    string
591
-     */
592
-    public static function event_venue($content)
593
-    {
594
-        return EED_Events_Archive::event_venues($content);
595
-    }
596
-
597
-
598
-
599
-    /**
600
-     *    event_venues - adds venues BELOW content
601
-     *
602
-     * @access    public
603
-     * @param        string $content
604
-     * @return        string
605
-     */
606
-    public static function event_venues($content)
607
-    {
608
-        if (post_password_required()) {
609
-            return $content;
610
-        }
611
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     *    _add_additional_content_filters
618
-     *
619
-     * @access    private
620
-     * @return        void
621
-     */
622
-    private static function _add_additional_excerpt_filters()
623
-    {
624
-        add_filter(
625
-            'the_excerpt',
626
-            array('EED_Events_Archive', 'event_datetimes'),
627
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
628
-        );
629
-        add_filter(
630
-            'the_excerpt',
631
-            array('EED_Events_Archive', 'event_tickets'),
632
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
633
-        );
634
-        add_filter(
635
-            'the_excerpt',
636
-            array('EED_Events_Archive', 'event_venues'),
637
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
638
-        );
639
-    }
640
-
641
-
642
-
643
-    /**
644
-     *    _add_additional_content_filters
645
-     *
646
-     * @access    private
647
-     * @return        void
648
-     */
649
-    private static function _add_additional_content_filters()
650
-    {
651
-        add_filter(
652
-            'the_content',
653
-            array('EED_Events_Archive', 'event_datetimes'),
654
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
655
-        );
656
-        add_filter(
657
-            'the_content',
658
-            array('EED_Events_Archive', 'event_tickets'),
659
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
660
-        );
661
-        add_filter(
662
-            'the_content',
663
-            array('EED_Events_Archive', 'event_venues'),
664
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
665
-        );
666
-    }
667
-
668
-
669
-
670
-    /**
671
-     *    _remove_additional_events_archive_filters
672
-     *
673
-     * @access    private
674
-     * @return        void
675
-     */
676
-    private static function _remove_additional_events_archive_filters()
677
-    {
678
-        remove_filter(
679
-            'the_excerpt',
680
-            array('EED_Events_Archive', 'event_datetimes'),
681
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
682
-        );
683
-        remove_filter(
684
-            'the_excerpt',
685
-            array('EED_Events_Archive', 'event_tickets'),
686
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
687
-        );
688
-        remove_filter(
689
-            'the_excerpt',
690
-            array('EED_Events_Archive', 'event_venues'),
691
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
692
-        );
693
-        remove_filter(
694
-            'the_content',
695
-            array('EED_Events_Archive', 'event_datetimes'),
696
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
697
-        );
698
-        remove_filter(
699
-            'the_content',
700
-            array('EED_Events_Archive', 'event_tickets'),
701
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
702
-        );
703
-        remove_filter(
704
-            'the_content',
705
-            array('EED_Events_Archive', 'event_venues'),
706
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
707
-        );
708
-    }
709
-
710
-
711
-
712
-    /**
713
-     *    remove_all_events_archive_filters
714
-     *
715
-     * @access    public
716
-     * @return        void
717
-     */
718
-    public static function remove_all_events_archive_filters()
719
-    {
720
-        //remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
721
-        remove_filter('the_title', array('EED_Events_Archive', 'the_title'), 1);
722
-        remove_filter(
723
-            'the_excerpt',
724
-            array('EED_Events_Archive', 'event_details'),
725
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
726
-        );
727
-        remove_filter(
728
-            'the_excerpt',
729
-            array('EED_Events_Archive', 'event_datetimes'),
730
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
731
-        );
732
-        remove_filter(
733
-            'the_excerpt',
734
-            array('EED_Events_Archive', 'event_tickets'),
735
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
736
-        );
737
-        remove_filter(
738
-            'the_excerpt',
739
-            array('EED_Events_Archive', 'event_venues'),
740
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
741
-        );
742
-        remove_filter(
743
-            'the_content',
744
-            array('EED_Events_Archive', 'event_details'),
745
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
746
-        );
747
-        remove_filter(
748
-            'the_content',
749
-            array('EED_Events_Archive', 'event_datetimes'),
750
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
751
-        );
752
-        remove_filter(
753
-            'the_content',
754
-            array('EED_Events_Archive', 'event_tickets'),
755
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
756
-        );
757
-        remove_filter(
758
-            'the_content',
759
-            array('EED_Events_Archive', 'event_venues'),
760
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
761
-        );
762
-        // don't display entry meta because the existing theme will take care of that
763
-        remove_filter(
764
-            'FHEE__content_espresso_events_details_template__display_entry_meta',
765
-            '__return_false'
766
-        );
767
-    }
768
-
769
-
770
-
771
-    /**
772
-     *    load_event_list_assets
773
-     *
774
-     * @access    public
775
-     * @return    void
776
-     */
777
-    public function load_event_list_assets()
778
-    {
779
-        do_action('AHEE__EED_Events_Archive__before_load_assets');
780
-        add_filter('FHEE_load_EE_Session', '__return_true');
781
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
782
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
783
-        if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
784
-            add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
785
-        }
786
-    }
787
-
788
-
789
-
790
-    /**
791
-     *    wp_enqueue_scripts
792
-     *
793
-     * @access    public
794
-     * @return    void
795
-     */
796
-    public function wp_enqueue_scripts()
797
-    {
798
-        // get some style
799
-        if (apply_filters('FHEE_enable_default_espresso_css', false)) {
800
-            // first check uploads folder
801
-            if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . DS . 'style.css')) {
802
-                wp_register_style($this->theme, get_stylesheet_directory_uri() . $this->theme . DS . 'style.css', array('dashicons', 'espresso_default'));
803
-            } else {
804
-            }
805
-            wp_enqueue_style($this->theme);
806
-        }
807
-    }
808
-
809
-
810
-
811
-    /**
812
-     *    template_settings_form
813
-     *
814
-     * @access    public
815
-     * @static
816
-     * @return    string
817
-     */
818
-    public static function template_settings_form()
819
-    {
820
-        $template_settings = EE_Registry::instance()->CFG->template_settings;
821
-        $template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive) ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
822
-        $template_settings->EED_Events_Archive = apply_filters('FHEE__EED_Events_Archive__template_settings_form__event_list_config', $template_settings->EED_Events_Archive);
823
-        $events_archive_settings = array(
824
-            'display_status_banner'   => 0,
825
-            'display_description'     => 1,
826
-            'display_ticket_selector' => 0,
827
-            'display_datetimes'       => 1,
828
-            'display_venue'           => 0,
829
-            'display_expired_events'  => 0,
830
-        );
831
-        $events_archive_settings = array_merge($events_archive_settings, (array)$template_settings->EED_Events_Archive);
832
-        EEH_Template::display_template(EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php', $events_archive_settings);
833
-    }
834
-
835
-
836
-
837
-    /**
838
-     *    update_template_settings
839
-     *
840
-     * @access    public
841
-     * @param    EE_Template_Config $CFG
842
-     * @param    EE_Request_Handler $REQ
843
-     * @return    EE_Template_Config
844
-     */
845
-    public static function update_template_settings($CFG, $REQ)
846
-    {
847
-        $CFG->EED_Events_Archive = new EE_Events_Archive_Config();
848
-        // unless we are resetting the config...
849
-        if (! isset($REQ['EED_Events_Archive_reset_event_list_settings']) || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1) {
850
-            $CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner']) ? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
851
-            $CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description']) ? absint($REQ['EED_Events_Archive_display_description']) : 1;
852
-            $CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector']) ? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
853
-            $CFG->EED_Events_Archive->display_datetimes = isset($REQ['EED_Events_Archive_display_datetimes']) ? absint($REQ['EED_Events_Archive_display_datetimes']) : 1;
854
-            $CFG->EED_Events_Archive->display_venue = isset($REQ['EED_Events_Archive_display_venue']) ? absint($REQ['EED_Events_Archive_display_venue']) : 0;
855
-            $CFG->EED_Events_Archive->display_expired_events = isset($REQ['EED_Events_Archive_display_expired_events']) ? absint($REQ['EED_Events_Archive_display_expired_events']) : 0;
856
-        }
857
-        return $CFG;
858
-    }
859
-
860
-
861
-
862
-    /**
863
-     *    event_list_css
864
-     *
865
-     * @access    public
866
-     * @param string $extra_class
867
-     * @return    string
868
-     */
869
-    public static function event_list_css($extra_class = '')
870
-    {
871
-        $event_list_css = ! empty($extra_class) ? array($extra_class) : array();
872
-        $event_list_css[] = 'espresso-event-list-event';
873
-        return implode(' ', $event_list_css);
874
-    }
875
-
876
-
877
-
878
-    /**
879
-     *    event_categories
880
-     *
881
-     * @access    public
882
-     * @return    array
883
-     */
884
-    public static function event_categories()
885
-    {
886
-        return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
887
-    }
888
-
889
-
890
-
891
-    /**
892
-     *    display_description
893
-     *
894
-     * @access    public
895
-     * @param $value
896
-     * @return    bool
897
-     */
898
-    public static function display_description($value)
899
-    {
900
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
901
-        $display_description = isset($config->display_description) ? $config->display_description : 1;
902
-        return $display_description === $value ? true : false;
903
-    }
904
-
905
-
906
-
907
-    /**
908
-     *    display_ticket_selector
909
-     *
910
-     * @access    public
911
-     * @return    bool
912
-     */
913
-    public static function display_ticket_selector()
914
-    {
915
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
916
-        return isset($config->display_ticket_selector) && $config->display_ticket_selector ? true : false;
917
-    }
918
-
919
-
920
-
921
-    /**
922
-     *    display_venue
923
-     *
924
-     * @access    public
925
-     * @return    bool
926
-     */
927
-    public static function display_venue()
928
-    {
929
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
930
-        return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name() ? true : false;
931
-    }
932
-
933
-
934
-
935
-    /**
936
-     *    display_datetimes
937
-     *
938
-     * @access    public
939
-     * @return    bool
940
-     */
941
-    public static function display_datetimes()
942
-    {
943
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
944
-        return isset($config->display_datetimes) && $config->display_datetimes ? true : false;
945
-    }
946
-
947
-
948
-
949
-    /**
950
-     *    event_list_title
951
-     *
952
-     * @access    public
953
-     * @return    string
954
-     */
955
-    public static function event_list_title()
956
-    {
957
-        return apply_filters('FHEE__archive_espresso_events_template__upcoming_events_h1', __('Upcoming Events', 'event_espresso'));
958
-    }
959
-
960
-
961
-    // GRAVEYARD
962
-
963
-
964
-
965
-    /**
966
-     * @since 4.4.0
967
-     */
968
-    public static function _doing_it_wrong_notice($function = '')
969
-    {
970
-        EE_Error::doing_it_wrong(
971
-            __FUNCTION__,
972
-            sprintf(
973
-                __('EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s', 'event_espresso'),
974
-                $function,
975
-                '<br />',
976
-                '4.6.0'
977
-            ),
978
-            '4.4.0'
979
-        );
980
-    }
981
-
982
-
983
-
984
-    /**
985
-     * @deprecated
986
-     * @since 4.4.0
987
-     */
988
-    public function get_post_data()
989
-    {
990
-        EEH_Event_Query::set_query_params();
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     * @deprecated
997
-     * @since 4.4.0
998
-     */
999
-    public function posts_fields($SQL, WP_Query $wp_query)
1000
-    {
1001
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1002
-        return EEH_Event_Query::posts_fields($SQL, $wp_query);
1003
-    }
20
+	const EVENT_DETAILS_PRIORITY   = 100;
21
+
22
+	const EVENT_DATETIMES_PRIORITY = 110;
23
+
24
+	const EVENT_TICKETS_PRIORITY   = 120;
25
+
26
+	const EVENT_VENUES_PRIORITY    = 130;
27
+
28
+
29
+	public static $espresso_event_list_ID    = 0;
30
+
31
+	public static $espresso_grid_event_lists = array();
32
+
33
+	/**
34
+	 * @type bool $using_get_the_excerpt
35
+	 */
36
+	protected static $using_get_the_excerpt = false;
37
+
38
+	/**
39
+	 * Used to flag when the event list is being called from an external iframe.
40
+	 *
41
+	 * @var bool $iframe
42
+	 */
43
+	protected static $iframe = false;
44
+
45
+	/**
46
+	 * @var \EventEspresso\core\libraries\iframe_display\EventListIframeEmbedButton $_iframe_embed_button
47
+	 */
48
+	private static $_iframe_embed_button;
49
+
50
+	/**
51
+	 * @type EE_Template_Part_Manager $template_parts
52
+	 */
53
+	protected $template_parts;
54
+
55
+
56
+
57
+	/**
58
+	 * @return EED_Events_Archive
59
+	 */
60
+	public static function instance()
61
+	{
62
+		return parent::get_instance(__CLASS__);
63
+	}
64
+
65
+
66
+
67
+	/**
68
+	 *    set_hooks - for hooking into EE Core, other modules, etc
69
+	 *
70
+	 * @access    public
71
+	 * @return    void
72
+	 */
73
+	public static function set_hooks()
74
+	{
75
+		$custom_post_types = EE_Register_CPTs::get_CPTs();
76
+		EE_Config::register_route(
77
+			$custom_post_types['espresso_events']['plural_slug'],
78
+			'Events_Archive',
79
+			'run'
80
+		);
81
+		EE_Config::register_route(
82
+			'event_list',
83
+			'Events_Archive',
84
+			'event_list'
85
+		);
86
+		EE_Config::register_route(
87
+			'iframe',
88
+			'Events_Archive',
89
+			'event_list_iframe',
90
+			'event_list'
91
+		);
92
+		add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
93
+	}
94
+
95
+
96
+
97
+	/**
98
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
99
+	 *
100
+	 * @access    public
101
+	 * @return    void
102
+	 */
103
+	public static function set_hooks_admin()
104
+	{
105
+		add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
106
+		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
107
+		// to load assets for "espresso_events" page on the "default" route (action)
108
+		add_action(
109
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
110
+			array('EED_Events_Archive', 'event_list_iframe_embed_button'),
111
+			10
112
+		);
113
+	}
114
+
115
+
116
+
117
+	/**
118
+	 *    set_definitions
119
+	 *
120
+	 * @access    public
121
+	 * @return    void
122
+	 */
123
+	public static function set_definitions()
124
+	{
125
+		define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets' . DS);
126
+		define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)) . 'templates' . DS);
127
+	}
128
+
129
+
130
+
131
+	/**
132
+	 * set up EE_Events_Archive_Config
133
+	 */
134
+	protected function set_config()
135
+	{
136
+		$this->set_config_section('template_settings');
137
+		$this->set_config_class('EE_Events_Archive_Config');
138
+		$this->set_config_name('EED_Events_Archive');
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * @return EventListIframeEmbedButton
145
+	 */
146
+	public static function get_iframe_embed_button()
147
+	{
148
+		if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
149
+			self::$_iframe_embed_button = new EventListIframeEmbedButton();
150
+		}
151
+		return self::$_iframe_embed_button;
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 * event_list_iframe_embed_button
158
+	 *
159
+	 * @return    void
160
+	 * @throws \EE_Error
161
+	 */
162
+	public static function event_list_iframe_embed_button()
163
+	{
164
+		$iframe_embed_button = \EED_Events_Archive::get_iframe_embed_button();
165
+		$iframe_embed_button->addEmbedButton();
166
+	}
167
+
168
+
169
+
170
+	/**
171
+	 *    initialize_template_parts
172
+	 *
173
+	 * @access    public
174
+	 * @param \EE_Events_Archive_Config $config
175
+	 * @return \EE_Template_Part_Manager
176
+	 */
177
+	public function initialize_template_parts(EE_Events_Archive_Config $config = null)
178
+	{
179
+		$config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
180
+		EEH_Autoloader::instance()->register_template_part_autoloaders();
181
+		$template_parts = new EE_Template_Part_Manager();
182
+		$template_parts->add_template_part(
183
+			'tickets',
184
+			__('Ticket Selector', 'event_espresso'),
185
+			'content-espresso_events-tickets.php',
186
+			$config->display_order_tickets
187
+		);
188
+		$template_parts->add_template_part(
189
+			'datetimes',
190
+			__('Dates and Times', 'event_espresso'),
191
+			'content-espresso_events-datetimes.php',
192
+			$config->display_order_datetimes
193
+		);
194
+		$template_parts->add_template_part(
195
+			'event',
196
+			__('Event Description', 'event_espresso'),
197
+			'content-espresso_events-details.php',
198
+			$config->display_order_event
199
+		);
200
+		$template_parts->add_template_part(
201
+			'venue',
202
+			__('Venue Information', 'event_espresso'),
203
+			'content-espresso_events-venues.php',
204
+			$config->display_order_venue
205
+		);
206
+		do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
207
+		return $template_parts;
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 *    run - initial module setup - this gets called by the EE_Front_Controller if the module route is found in the incoming request
214
+	 *
215
+	 * @access    public
216
+	 * @param WP $WP
217
+	 * @return    void
218
+	 */
219
+	public function run($WP)
220
+	{
221
+		do_action('AHEE__EED_Events_Archive__before_run');
222
+		// ensure valid EE_Events_Archive_Config() object exists
223
+		$this->set_config();
224
+		/** @type EE_Events_Archive_Config $config */
225
+		$config = $this->config();
226
+		// load other required components
227
+		$this->load_event_list_assets();
228
+		// filter the WP posts_join, posts_where, and posts_orderby SQL clauses
229
+		//add query filters
230
+		EEH_Event_Query::add_query_filters();
231
+		// set params that will get used by the filters
232
+		EEH_Event_Query::set_query_params(
233
+			'',    // month
234
+			'',    // category
235
+			$config->display_expired_events,    // show_expired
236
+			'start_date',    // orderby
237
+			'ASC'    // sort
238
+		);
239
+		// check what template is loaded
240
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
241
+	}
242
+
243
+
244
+
245
+	/**
246
+	 * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
247
+	 *
248
+	 * @return    void
249
+	 */
250
+	public function event_list()
251
+	{
252
+		// ensure valid EE_Events_Archive_Config() object exists
253
+		$this->set_config();
254
+		// load other required components
255
+		$this->load_event_list_assets();
256
+	}
257
+
258
+
259
+
260
+	/**
261
+	 * @access    public
262
+	 * @return    void
263
+	 * @throws \EE_Error
264
+	 * @throws \DomainException
265
+	 */
266
+	public function event_list_iframe()
267
+	{
268
+		\EED_Events_Archive::$iframe = true;
269
+		$event_list_iframe = new EventsArchiveIframe($this);
270
+		$event_list_iframe->display();
271
+	}
272
+
273
+
274
+
275
+	/**
276
+	 * @access public
277
+	 * @return string
278
+	 */
279
+	public static function is_iframe()
280
+	{
281
+		return \EED_Events_Archive::$iframe;
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @access public
288
+	 * @return string
289
+	 */
290
+	public static function link_target()
291
+	{
292
+		return \EED_Events_Archive::$iframe ? ' target="_blank"' : '';
293
+	}
294
+
295
+
296
+
297
+	/**
298
+	 *    template_include
299
+	 *
300
+	 * @access    public
301
+	 * @param string $template
302
+	 * @return    string
303
+	 */
304
+	public function template_include($template = '')
305
+	{
306
+		// don't add content filter for dedicated EE child themes or private posts
307
+		if (! EEH_Template::is_espresso_theme()) {
308
+			/** @type EE_Events_Archive_Config $config */
309
+			$config = $this->config();
310
+			// add status banner ?
311
+			if ($config->display_status_banner) {
312
+				add_filter('the_title', array('EED_Events_Archive', 'the_title'), 100, 2);
313
+			}
314
+			// if NOT a custom template
315
+			if (
316
+				apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
317
+				|| EE_Registry::instance()
318
+							  ->load_core('Front_Controller')
319
+							  ->get_selected_template() !== 'archive-espresso_events.php'
320
+			) {
321
+				// don't display entry meta because the existing theme will take care of that
322
+				add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
323
+				// load functions.php file for the theme (loaded by WP if using child theme)
324
+				EEH_Template::load_espresso_theme_functions();
325
+				// because we don't know if the theme is using the_excerpt()
326
+				add_filter(
327
+					'the_excerpt',
328
+					array('EED_Events_Archive', 'event_details'),
329
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
330
+				);
331
+				// or the_content
332
+				add_filter(
333
+					'the_content',
334
+					array('EED_Events_Archive', 'event_details'),
335
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
336
+				);
337
+				// and just in case they are running get_the_excerpt() which DESTROYS things
338
+				add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
339
+				// don't display entry meta because the existing theme will take care of that
340
+				add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
341
+			}
342
+		}
343
+		return $template;
344
+	}
345
+
346
+
347
+
348
+	/**
349
+	 *    get_the_excerpt - kinda hacky, but if a theme is using get_the_excerpt(), then we need to remove our filters on the_content()
350
+	 *
351
+	 * @access    public
352
+	 * @param        string $excerpt
353
+	 * @return        string
354
+	 */
355
+	public static function get_the_excerpt($excerpt = '')
356
+	{
357
+		if (post_password_required()) {
358
+			return $excerpt;
359
+		}
360
+		if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
361
+			remove_filter(
362
+				'the_excerpt',
363
+				array('EED_Events_Archive', 'event_details'),
364
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
365
+			);
366
+			remove_filter(
367
+				'the_content',
368
+				array('EED_Events_Archive', 'event_details'),
369
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
370
+			);
371
+			$excerpt = EED_Events_Archive::event_details($excerpt);
372
+		} else {
373
+			EED_Events_Archive::$using_get_the_excerpt = true;
374
+			add_filter('wp_trim_excerpt', array('EED_Events_Archive', 'end_get_the_excerpt'), 999, 1);
375
+		}
376
+		return $excerpt;
377
+	}
378
+
379
+
380
+
381
+	/**
382
+	 * end_get_the_excerpt
383
+	 *
384
+	 * @access public
385
+	 * @param  string $text
386
+	 * @return string
387
+	 */
388
+	public static function end_get_the_excerpt($text = '')
389
+	{
390
+		EED_Events_Archive::$using_get_the_excerpt = false;
391
+		return $text;
392
+	}
393
+
394
+
395
+
396
+	/**
397
+	 *    the_title
398
+	 *
399
+	 * @access        public
400
+	 * @param        string $title
401
+	 * @param        string $id
402
+	 * @return        string
403
+	 */
404
+	public static function the_title($title = '', $id = '')
405
+	{
406
+		global $post;
407
+		if ($post instanceof WP_Post) {
408
+			return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID) . $title : $title;
409
+		}
410
+		return $title;
411
+	}
412
+
413
+
414
+
415
+	/**
416
+	 *    event_details
417
+	 *
418
+	 * @access    public
419
+	 * @param        string $content
420
+	 * @return        string
421
+	 */
422
+	public static function event_details($content)
423
+	{
424
+		global $post;
425
+		static $current_post_ID = 0;
426
+		if (
427
+			$current_post_ID !== $post->ID
428
+			&& $post->post_type === 'espresso_events'
429
+			&& ! EED_Events_Archive::$using_get_the_excerpt
430
+			&& ! post_password_required()
431
+			&& (
432
+				apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
433
+				|| ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
434
+			)
435
+		) {
436
+			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
437
+			// Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
438
+			// BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
439
+			// We want to allow those plugins to still do their thing and have access to our content, but depending on
440
+			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
441
+			// so the following allows this filter to be applied multiple times, but only once for real
442
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
443
+			if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
444
+				$content = \EED_Events_Archive::use_sortable_display_order();
445
+			} else {
446
+				$content = \EED_Events_Archive::use_filterable_display_order();
447
+			}
448
+		}
449
+		return $content;
450
+	}
451
+
452
+
453
+
454
+	/**
455
+	 *    use_sortable_display_order
456
+	 *
457
+	 * @access    protected
458
+	 * @return string
459
+	 */
460
+	protected static function use_sortable_display_order()
461
+	{
462
+		// no further password checks required atm
463
+		add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
464
+		// we need to first remove this callback from being applied to the_content() or the_excerpt()
465
+		// (otherwise it will recurse and blow up the interweb)
466
+		remove_filter(
467
+			'the_excerpt',
468
+			array('EED_Events_Archive', 'event_details'),
469
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
470
+		);
471
+		remove_filter(
472
+			'the_content',
473
+			array('EED_Events_Archive', 'event_details'),
474
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
475
+		);
476
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
477
+		// now add additional content depending on whether event is using the_excerpt() or the_content()
478
+		EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
479
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
480
+		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
481
+		// re-add our main filters (or else the next event won't have them)
482
+		add_filter(
483
+			'the_excerpt',
484
+			array('EED_Events_Archive', 'event_details'),
485
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
486
+		);
487
+		add_filter(
488
+			'the_content',
489
+			array('EED_Events_Archive', 'event_details'),
490
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
491
+		);
492
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
493
+		remove_filter(
494
+			'FHEE__EED_Events_Archive__event_details__no_post_password_required',
495
+			'__return_true'
496
+		);
497
+		return $content;
498
+	}
499
+
500
+
501
+
502
+	/**
503
+	 *    use_filterable_display_order
504
+	 *
505
+	 * @access    protected
506
+	 * @return    string
507
+	 */
508
+	protected static function use_filterable_display_order()
509
+	{
510
+		// we need to first remove this callback from being applied to the_content()
511
+		// (otherwise it will recurse and blow up the interweb)
512
+		remove_filter(
513
+			'the_excerpt',
514
+			array('EED_Events_Archive', 'event_details'),
515
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
516
+		);
517
+		remove_filter(
518
+			'the_content',
519
+			array('EED_Events_Archive', 'event_details'),
520
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
521
+		);
522
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
523
+		//now add additional content depending on whether event is using the_excerpt() or the_content()
524
+		EED_Events_Archive::_add_additional_excerpt_filters();
525
+		EED_Events_Archive::_add_additional_content_filters();
526
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
527
+		// now load our template
528
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
529
+		// re-add our main filters (or else the next event won't have them)
530
+		add_filter(
531
+			'the_excerpt',
532
+			array('EED_Events_Archive', 'event_details'),
533
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
534
+		);
535
+		add_filter(
536
+			'the_content',
537
+			array('EED_Events_Archive', 'event_details'),
538
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
539
+		);
540
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
541
+		// but remove the other filters so that they don't get applied to the next post
542
+		EED_Events_Archive::_remove_additional_events_archive_filters();
543
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
544
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
545
+		//return ! empty( $template ) ? $template : $content;
546
+		return $content;
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 *    event_datetimes - adds datetimes ABOVE content
553
+	 *
554
+	 * @access    public
555
+	 * @param        string $content
556
+	 * @return        string
557
+	 */
558
+	public static function event_datetimes($content)
559
+	{
560
+		if (post_password_required()) {
561
+			return $content;
562
+		}
563
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
564
+	}
565
+
566
+
567
+
568
+	/**
569
+	 *    event_tickets - adds tickets ABOVE content (which includes datetimes)
570
+	 *
571
+	 * @access    public
572
+	 * @param        string $content
573
+	 * @return        string
574
+	 */
575
+	public static function event_tickets($content)
576
+	{
577
+		if (post_password_required()) {
578
+			return $content;
579
+		}
580
+		return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 *    event_venues - adds venues BELOW content
587
+	 *
588
+	 * @access    public
589
+	 * @param    string $content
590
+	 * @return    string
591
+	 */
592
+	public static function event_venue($content)
593
+	{
594
+		return EED_Events_Archive::event_venues($content);
595
+	}
596
+
597
+
598
+
599
+	/**
600
+	 *    event_venues - adds venues BELOW content
601
+	 *
602
+	 * @access    public
603
+	 * @param        string $content
604
+	 * @return        string
605
+	 */
606
+	public static function event_venues($content)
607
+	{
608
+		if (post_password_required()) {
609
+			return $content;
610
+		}
611
+		return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 *    _add_additional_content_filters
618
+	 *
619
+	 * @access    private
620
+	 * @return        void
621
+	 */
622
+	private static function _add_additional_excerpt_filters()
623
+	{
624
+		add_filter(
625
+			'the_excerpt',
626
+			array('EED_Events_Archive', 'event_datetimes'),
627
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
628
+		);
629
+		add_filter(
630
+			'the_excerpt',
631
+			array('EED_Events_Archive', 'event_tickets'),
632
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
633
+		);
634
+		add_filter(
635
+			'the_excerpt',
636
+			array('EED_Events_Archive', 'event_venues'),
637
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
638
+		);
639
+	}
640
+
641
+
642
+
643
+	/**
644
+	 *    _add_additional_content_filters
645
+	 *
646
+	 * @access    private
647
+	 * @return        void
648
+	 */
649
+	private static function _add_additional_content_filters()
650
+	{
651
+		add_filter(
652
+			'the_content',
653
+			array('EED_Events_Archive', 'event_datetimes'),
654
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
655
+		);
656
+		add_filter(
657
+			'the_content',
658
+			array('EED_Events_Archive', 'event_tickets'),
659
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
660
+		);
661
+		add_filter(
662
+			'the_content',
663
+			array('EED_Events_Archive', 'event_venues'),
664
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
665
+		);
666
+	}
667
+
668
+
669
+
670
+	/**
671
+	 *    _remove_additional_events_archive_filters
672
+	 *
673
+	 * @access    private
674
+	 * @return        void
675
+	 */
676
+	private static function _remove_additional_events_archive_filters()
677
+	{
678
+		remove_filter(
679
+			'the_excerpt',
680
+			array('EED_Events_Archive', 'event_datetimes'),
681
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
682
+		);
683
+		remove_filter(
684
+			'the_excerpt',
685
+			array('EED_Events_Archive', 'event_tickets'),
686
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
687
+		);
688
+		remove_filter(
689
+			'the_excerpt',
690
+			array('EED_Events_Archive', 'event_venues'),
691
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
692
+		);
693
+		remove_filter(
694
+			'the_content',
695
+			array('EED_Events_Archive', 'event_datetimes'),
696
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
697
+		);
698
+		remove_filter(
699
+			'the_content',
700
+			array('EED_Events_Archive', 'event_tickets'),
701
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
702
+		);
703
+		remove_filter(
704
+			'the_content',
705
+			array('EED_Events_Archive', 'event_venues'),
706
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
707
+		);
708
+	}
709
+
710
+
711
+
712
+	/**
713
+	 *    remove_all_events_archive_filters
714
+	 *
715
+	 * @access    public
716
+	 * @return        void
717
+	 */
718
+	public static function remove_all_events_archive_filters()
719
+	{
720
+		//remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
721
+		remove_filter('the_title', array('EED_Events_Archive', 'the_title'), 1);
722
+		remove_filter(
723
+			'the_excerpt',
724
+			array('EED_Events_Archive', 'event_details'),
725
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
726
+		);
727
+		remove_filter(
728
+			'the_excerpt',
729
+			array('EED_Events_Archive', 'event_datetimes'),
730
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
731
+		);
732
+		remove_filter(
733
+			'the_excerpt',
734
+			array('EED_Events_Archive', 'event_tickets'),
735
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
736
+		);
737
+		remove_filter(
738
+			'the_excerpt',
739
+			array('EED_Events_Archive', 'event_venues'),
740
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
741
+		);
742
+		remove_filter(
743
+			'the_content',
744
+			array('EED_Events_Archive', 'event_details'),
745
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
746
+		);
747
+		remove_filter(
748
+			'the_content',
749
+			array('EED_Events_Archive', 'event_datetimes'),
750
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
751
+		);
752
+		remove_filter(
753
+			'the_content',
754
+			array('EED_Events_Archive', 'event_tickets'),
755
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
756
+		);
757
+		remove_filter(
758
+			'the_content',
759
+			array('EED_Events_Archive', 'event_venues'),
760
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
761
+		);
762
+		// don't display entry meta because the existing theme will take care of that
763
+		remove_filter(
764
+			'FHEE__content_espresso_events_details_template__display_entry_meta',
765
+			'__return_false'
766
+		);
767
+	}
768
+
769
+
770
+
771
+	/**
772
+	 *    load_event_list_assets
773
+	 *
774
+	 * @access    public
775
+	 * @return    void
776
+	 */
777
+	public function load_event_list_assets()
778
+	{
779
+		do_action('AHEE__EED_Events_Archive__before_load_assets');
780
+		add_filter('FHEE_load_EE_Session', '__return_true');
781
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
782
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
783
+		if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
784
+			add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
785
+		}
786
+	}
787
+
788
+
789
+
790
+	/**
791
+	 *    wp_enqueue_scripts
792
+	 *
793
+	 * @access    public
794
+	 * @return    void
795
+	 */
796
+	public function wp_enqueue_scripts()
797
+	{
798
+		// get some style
799
+		if (apply_filters('FHEE_enable_default_espresso_css', false)) {
800
+			// first check uploads folder
801
+			if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . DS . 'style.css')) {
802
+				wp_register_style($this->theme, get_stylesheet_directory_uri() . $this->theme . DS . 'style.css', array('dashicons', 'espresso_default'));
803
+			} else {
804
+			}
805
+			wp_enqueue_style($this->theme);
806
+		}
807
+	}
808
+
809
+
810
+
811
+	/**
812
+	 *    template_settings_form
813
+	 *
814
+	 * @access    public
815
+	 * @static
816
+	 * @return    string
817
+	 */
818
+	public static function template_settings_form()
819
+	{
820
+		$template_settings = EE_Registry::instance()->CFG->template_settings;
821
+		$template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive) ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
822
+		$template_settings->EED_Events_Archive = apply_filters('FHEE__EED_Events_Archive__template_settings_form__event_list_config', $template_settings->EED_Events_Archive);
823
+		$events_archive_settings = array(
824
+			'display_status_banner'   => 0,
825
+			'display_description'     => 1,
826
+			'display_ticket_selector' => 0,
827
+			'display_datetimes'       => 1,
828
+			'display_venue'           => 0,
829
+			'display_expired_events'  => 0,
830
+		);
831
+		$events_archive_settings = array_merge($events_archive_settings, (array)$template_settings->EED_Events_Archive);
832
+		EEH_Template::display_template(EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php', $events_archive_settings);
833
+	}
834
+
835
+
836
+
837
+	/**
838
+	 *    update_template_settings
839
+	 *
840
+	 * @access    public
841
+	 * @param    EE_Template_Config $CFG
842
+	 * @param    EE_Request_Handler $REQ
843
+	 * @return    EE_Template_Config
844
+	 */
845
+	public static function update_template_settings($CFG, $REQ)
846
+	{
847
+		$CFG->EED_Events_Archive = new EE_Events_Archive_Config();
848
+		// unless we are resetting the config...
849
+		if (! isset($REQ['EED_Events_Archive_reset_event_list_settings']) || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1) {
850
+			$CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner']) ? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
851
+			$CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description']) ? absint($REQ['EED_Events_Archive_display_description']) : 1;
852
+			$CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector']) ? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
853
+			$CFG->EED_Events_Archive->display_datetimes = isset($REQ['EED_Events_Archive_display_datetimes']) ? absint($REQ['EED_Events_Archive_display_datetimes']) : 1;
854
+			$CFG->EED_Events_Archive->display_venue = isset($REQ['EED_Events_Archive_display_venue']) ? absint($REQ['EED_Events_Archive_display_venue']) : 0;
855
+			$CFG->EED_Events_Archive->display_expired_events = isset($REQ['EED_Events_Archive_display_expired_events']) ? absint($REQ['EED_Events_Archive_display_expired_events']) : 0;
856
+		}
857
+		return $CFG;
858
+	}
859
+
860
+
861
+
862
+	/**
863
+	 *    event_list_css
864
+	 *
865
+	 * @access    public
866
+	 * @param string $extra_class
867
+	 * @return    string
868
+	 */
869
+	public static function event_list_css($extra_class = '')
870
+	{
871
+		$event_list_css = ! empty($extra_class) ? array($extra_class) : array();
872
+		$event_list_css[] = 'espresso-event-list-event';
873
+		return implode(' ', $event_list_css);
874
+	}
875
+
876
+
877
+
878
+	/**
879
+	 *    event_categories
880
+	 *
881
+	 * @access    public
882
+	 * @return    array
883
+	 */
884
+	public static function event_categories()
885
+	{
886
+		return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
887
+	}
888
+
889
+
890
+
891
+	/**
892
+	 *    display_description
893
+	 *
894
+	 * @access    public
895
+	 * @param $value
896
+	 * @return    bool
897
+	 */
898
+	public static function display_description($value)
899
+	{
900
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
901
+		$display_description = isset($config->display_description) ? $config->display_description : 1;
902
+		return $display_description === $value ? true : false;
903
+	}
904
+
905
+
906
+
907
+	/**
908
+	 *    display_ticket_selector
909
+	 *
910
+	 * @access    public
911
+	 * @return    bool
912
+	 */
913
+	public static function display_ticket_selector()
914
+	{
915
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
916
+		return isset($config->display_ticket_selector) && $config->display_ticket_selector ? true : false;
917
+	}
918
+
919
+
920
+
921
+	/**
922
+	 *    display_venue
923
+	 *
924
+	 * @access    public
925
+	 * @return    bool
926
+	 */
927
+	public static function display_venue()
928
+	{
929
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
930
+		return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name() ? true : false;
931
+	}
932
+
933
+
934
+
935
+	/**
936
+	 *    display_datetimes
937
+	 *
938
+	 * @access    public
939
+	 * @return    bool
940
+	 */
941
+	public static function display_datetimes()
942
+	{
943
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
944
+		return isset($config->display_datetimes) && $config->display_datetimes ? true : false;
945
+	}
946
+
947
+
948
+
949
+	/**
950
+	 *    event_list_title
951
+	 *
952
+	 * @access    public
953
+	 * @return    string
954
+	 */
955
+	public static function event_list_title()
956
+	{
957
+		return apply_filters('FHEE__archive_espresso_events_template__upcoming_events_h1', __('Upcoming Events', 'event_espresso'));
958
+	}
959
+
960
+
961
+	// GRAVEYARD
962
+
963
+
964
+
965
+	/**
966
+	 * @since 4.4.0
967
+	 */
968
+	public static function _doing_it_wrong_notice($function = '')
969
+	{
970
+		EE_Error::doing_it_wrong(
971
+			__FUNCTION__,
972
+			sprintf(
973
+				__('EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s', 'event_espresso'),
974
+				$function,
975
+				'<br />',
976
+				'4.6.0'
977
+			),
978
+			'4.4.0'
979
+		);
980
+	}
981
+
982
+
983
+
984
+	/**
985
+	 * @deprecated
986
+	 * @since 4.4.0
987
+	 */
988
+	public function get_post_data()
989
+	{
990
+		EEH_Event_Query::set_query_params();
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 * @deprecated
997
+	 * @since 4.4.0
998
+	 */
999
+	public function posts_fields($SQL, WP_Query $wp_query)
1000
+	{
1001
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1002
+		return EEH_Event_Query::posts_fields($SQL, $wp_query);
1003
+	}
1004 1004
 
1005
-
1006
-
1007
-    /**
1008
-     * @deprecated
1009
-     * @since 4.4.0
1010
-     */
1011
-    public static function posts_fields_sql_for_orderby($orderby_params = array())
1012
-    {
1013
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1014
-        return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
1015
-    }
1005
+
1006
+
1007
+	/**
1008
+	 * @deprecated
1009
+	 * @since 4.4.0
1010
+	 */
1011
+	public static function posts_fields_sql_for_orderby($orderby_params = array())
1012
+	{
1013
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1014
+		return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
1015
+	}
1016 1016
 
1017 1017
 
1018 1018
 
1019
-    /**
1020
-     * @deprecated
1021
-     * @since 4.4.0
1022
-     */
1023
-    public function posts_join($SQL, WP_Query $wp_query)
1024
-    {
1025
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1026
-        return EEH_Event_Query::posts_join($SQL, $wp_query);
1027
-    }
1019
+	/**
1020
+	 * @deprecated
1021
+	 * @since 4.4.0
1022
+	 */
1023
+	public function posts_join($SQL, WP_Query $wp_query)
1024
+	{
1025
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1026
+		return EEH_Event_Query::posts_join($SQL, $wp_query);
1027
+	}
1028 1028
 
1029 1029
 
1030 1030
 
1031
-    /**
1032
-     * @deprecated
1033
-     * @since 4.4.0
1034
-     */
1035
-    public static function posts_join_sql_for_terms($join_terms = null)
1036
-    {
1037
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1038
-        return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
1039
-    }
1031
+	/**
1032
+	 * @deprecated
1033
+	 * @since 4.4.0
1034
+	 */
1035
+	public static function posts_join_sql_for_terms($join_terms = null)
1036
+	{
1037
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1038
+		return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
1039
+	}
1040 1040
 
1041 1041
 
1042 1042
 
1043
-    /**
1044
-     * @deprecated
1045
-     * @since 4.4.0
1046
-     */
1047
-    public static function posts_join_for_orderby($orderby_params = array())
1048
-    {
1049
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1050
-        return EEH_Event_Query::posts_join_for_orderby($orderby_params);
1051
-    }
1043
+	/**
1044
+	 * @deprecated
1045
+	 * @since 4.4.0
1046
+	 */
1047
+	public static function posts_join_for_orderby($orderby_params = array())
1048
+	{
1049
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1050
+		return EEH_Event_Query::posts_join_for_orderby($orderby_params);
1051
+	}
1052 1052
 
1053 1053
 
1054 1054
 
1055
-    /**
1056
-     * @deprecated
1057
-     * @since 4.4.0
1058
-     */
1059
-    public function posts_where($SQL, WP_Query $wp_query)
1060
-    {
1061
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1062
-        return EEH_Event_Query::posts_where($SQL, $wp_query);
1063
-    }
1055
+	/**
1056
+	 * @deprecated
1057
+	 * @since 4.4.0
1058
+	 */
1059
+	public function posts_where($SQL, WP_Query $wp_query)
1060
+	{
1061
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1062
+		return EEH_Event_Query::posts_where($SQL, $wp_query);
1063
+	}
1064 1064
 
1065
-
1066
-
1067
-    /**
1068
-     * @deprecated
1069
-     * @since 4.4.0
1070
-     */
1071
-    public static function posts_where_sql_for_show_expired($show_expired = false)
1072
-    {
1073
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1074
-        return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1075
-    }
1065
+
1066
+
1067
+	/**
1068
+	 * @deprecated
1069
+	 * @since 4.4.0
1070
+	 */
1071
+	public static function posts_where_sql_for_show_expired($show_expired = false)
1072
+	{
1073
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1074
+		return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1075
+	}
1076 1076
 
1077 1077
 
1078 1078
 
1079
-    /**
1080
-     * @deprecated
1081
-     * @since 4.4.0
1082
-     */
1083
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1084
-    {
1085
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1086
-        return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1087
-    }
1079
+	/**
1080
+	 * @deprecated
1081
+	 * @since 4.4.0
1082
+	 */
1083
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1084
+	{
1085
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1086
+		return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1087
+	}
1088 1088
 
1089 1089
 
1090 1090
 
1091
-    /**
1092
-     * @deprecated
1093
-     * @since 4.4.0
1094
-     */
1095
-    public static function posts_where_sql_for_event_list_month($month = null)
1096
-    {
1097
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1098
-        return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1099
-    }
1091
+	/**
1092
+	 * @deprecated
1093
+	 * @since 4.4.0
1094
+	 */
1095
+	public static function posts_where_sql_for_event_list_month($month = null)
1096
+	{
1097
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1098
+		return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1099
+	}
1100 1100
 
1101 1101
 
1102 1102
 
1103
-    /**
1104
-     * @deprecated
1105
-     * @since 4.4.0
1106
-     */
1107
-    public function posts_orderby($SQL, WP_Query $wp_query)
1108
-    {
1109
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1110
-        return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1111
-    }
1103
+	/**
1104
+	 * @deprecated
1105
+	 * @since 4.4.0
1106
+	 */
1107
+	public function posts_orderby($SQL, WP_Query $wp_query)
1108
+	{
1109
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1110
+		return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1111
+	}
1112 1112
 
1113 1113
 
1114 1114
 
1115
-    /**
1116
-     * @deprecated
1117
-     * @since 4.4.0
1118
-     */
1119
-    public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
1120
-    {
1121
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1122
-        return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1123
-    }
1115
+	/**
1116
+	 * @deprecated
1117
+	 * @since 4.4.0
1118
+	 */
1119
+	public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
1120
+	{
1121
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1122
+		return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1123
+	}
1124 1124
 
1125 1125
 
1126 1126
 
@@ -1133,9 +1133,9 @@  discard block
 block discarded – undo
1133 1133
  */
1134 1134
 function espresso_get_event_list_ID()
1135 1135
 {
1136
-    EED_Events_Archive::$espresso_event_list_ID++;
1137
-    EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1138
-    return EED_Events_Archive::$espresso_event_list_ID;
1136
+	EED_Events_Archive::$espresso_event_list_ID++;
1137
+	EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1138
+	return EED_Events_Archive::$espresso_event_list_ID;
1139 1139
 }
1140 1140
 
1141 1141
 /**
@@ -1143,7 +1143,7 @@  discard block
 block discarded – undo
1143 1143
  */
1144 1144
 function espresso_event_list_title()
1145 1145
 {
1146
-    return EED_Events_Archive::event_list_title();
1146
+	return EED_Events_Archive::event_list_title();
1147 1147
 }
1148 1148
 
1149 1149
 /**
@@ -1152,7 +1152,7 @@  discard block
 block discarded – undo
1152 1152
  */
1153 1153
 function espresso_event_list_css($extra_class = '')
1154 1154
 {
1155
-    return EED_Events_Archive::event_list_css($extra_class);
1155
+	return EED_Events_Archive::event_list_css($extra_class);
1156 1156
 }
1157 1157
 
1158 1158
 /**
@@ -1160,7 +1160,7 @@  discard block
 block discarded – undo
1160 1160
  */
1161 1161
 function espresso_get_event_categories()
1162 1162
 {
1163
-    return EED_Events_Archive::event_categories();
1163
+	return EED_Events_Archive::event_categories();
1164 1164
 }
1165 1165
 
1166 1166
 /**
@@ -1168,7 +1168,7 @@  discard block
 block discarded – undo
1168 1168
  */
1169 1169
 function espresso_display_full_description_in_event_list()
1170 1170
 {
1171
-    return EED_Events_Archive::display_description(2);
1171
+	return EED_Events_Archive::display_description(2);
1172 1172
 }
1173 1173
 
1174 1174
 /**
@@ -1176,7 +1176,7 @@  discard block
 block discarded – undo
1176 1176
  */
1177 1177
 function espresso_display_excerpt_in_event_list()
1178 1178
 {
1179
-    return EED_Events_Archive::display_description(1);
1179
+	return EED_Events_Archive::display_description(1);
1180 1180
 }
1181 1181
 
1182 1182
 /**
@@ -1184,7 +1184,7 @@  discard block
 block discarded – undo
1184 1184
  */
1185 1185
 function espresso_display_ticket_selector_in_event_list()
1186 1186
 {
1187
-    return EED_Events_Archive::display_ticket_selector();
1187
+	return EED_Events_Archive::display_ticket_selector();
1188 1188
 }
1189 1189
 
1190 1190
 /**
@@ -1192,7 +1192,7 @@  discard block
 block discarded – undo
1192 1192
  */
1193 1193
 function espresso_display_venue_in_event_list()
1194 1194
 {
1195
-    return EED_Events_Archive::display_venue();
1195
+	return EED_Events_Archive::display_venue();
1196 1196
 }
1197 1197
 
1198 1198
 /**
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
  */
1201 1201
 function espresso_display_datetimes_in_event_list()
1202 1202
 {
1203
-    return EED_Events_Archive::display_datetimes();
1203
+	return EED_Events_Archive::display_datetimes();
1204 1204
 }
1205 1205
 
1206 1206
 
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -122,8 +122,8 @@  discard block
 block discarded – undo
122 122
      */
123 123
     public static function set_definitions()
124 124
     {
125
-        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets' . DS);
126
-        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)) . 'templates' . DS);
125
+        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__).'assets'.DS);
126
+        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)).'templates'.DS);
127 127
     }
128 128
 
129 129
 
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
      */
146 146
     public static function get_iframe_embed_button()
147 147
     {
148
-        if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
148
+        if ( ! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
149 149
             self::$_iframe_embed_button = new EventListIframeEmbedButton();
150 150
         }
151 151
         return self::$_iframe_embed_button;
@@ -230,10 +230,10 @@  discard block
 block discarded – undo
230 230
         EEH_Event_Query::add_query_filters();
231 231
         // set params that will get used by the filters
232 232
         EEH_Event_Query::set_query_params(
233
-            '',    // month
234
-            '',    // category
235
-            $config->display_expired_events,    // show_expired
236
-            'start_date',    // orderby
233
+            '', // month
234
+            '', // category
235
+            $config->display_expired_events, // show_expired
236
+            'start_date', // orderby
237 237
             'ASC'    // sort
238 238
         );
239 239
         // check what template is loaded
@@ -304,7 +304,7 @@  discard block
 block discarded – undo
304 304
     public function template_include($template = '')
305 305
     {
306 306
         // don't add content filter for dedicated EE child themes or private posts
307
-        if (! EEH_Template::is_espresso_theme()) {
307
+        if ( ! EEH_Template::is_espresso_theme()) {
308 308
             /** @type EE_Events_Archive_Config $config */
309 309
             $config = $this->config();
310 310
             // add status banner ?
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
     {
406 406
         global $post;
407 407
         if ($post instanceof WP_Post) {
408
-            return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID) . $title : $title;
408
+            return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID).$title : $title;
409 409
         }
410 410
         return $title;
411 411
     }
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
         if (post_password_required()) {
561 561
             return $content;
562 562
         }
563
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
563
+        return EEH_Template::locate_template('content-espresso_events-datetimes.php').$content;
564 564
     }
565 565
 
566 566
 
@@ -577,7 +577,7 @@  discard block
 block discarded – undo
577 577
         if (post_password_required()) {
578 578
             return $content;
579 579
         }
580
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
580
+        return EEH_Template::locate_template('content-espresso_events-tickets.php').$content;
581 581
     }
582 582
 
583 583
 
@@ -608,7 +608,7 @@  discard block
 block discarded – undo
608 608
         if (post_password_required()) {
609 609
             return $content;
610 610
         }
611
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
611
+        return $content.EEH_Template::locate_template('content-espresso_events-venues.php');
612 612
     }
613 613
 
614 614
 
@@ -798,8 +798,8 @@  discard block
 block discarded – undo
798 798
         // get some style
799 799
         if (apply_filters('FHEE_enable_default_espresso_css', false)) {
800 800
             // first check uploads folder
801
-            if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . DS . 'style.css')) {
802
-                wp_register_style($this->theme, get_stylesheet_directory_uri() . $this->theme . DS . 'style.css', array('dashicons', 'espresso_default'));
801
+            if (EEH_File::is_readable(get_stylesheet_directory().$this->theme.DS.'style.css')) {
802
+                wp_register_style($this->theme, get_stylesheet_directory_uri().$this->theme.DS.'style.css', array('dashicons', 'espresso_default'));
803 803
             } else {
804 804
             }
805 805
             wp_enqueue_style($this->theme);
@@ -828,8 +828,8 @@  discard block
 block discarded – undo
828 828
             'display_venue'           => 0,
829 829
             'display_expired_events'  => 0,
830 830
         );
831
-        $events_archive_settings = array_merge($events_archive_settings, (array)$template_settings->EED_Events_Archive);
832
-        EEH_Template::display_template(EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php', $events_archive_settings);
831
+        $events_archive_settings = array_merge($events_archive_settings, (array) $template_settings->EED_Events_Archive);
832
+        EEH_Template::display_template(EVENTS_ARCHIVE_TEMPLATES_PATH.'admin-event-list-settings.template.php', $events_archive_settings);
833 833
     }
834 834
 
835 835
 
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
     {
847 847
         $CFG->EED_Events_Archive = new EE_Events_Archive_Config();
848 848
         // unless we are resetting the config...
849
-        if (! isset($REQ['EED_Events_Archive_reset_event_list_settings']) || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1) {
849
+        if ( ! isset($REQ['EED_Events_Archive_reset_event_list_settings']) || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1) {
850 850
             $CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner']) ? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
851 851
             $CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description']) ? absint($REQ['EED_Events_Archive_display_description']) : 1;
852 852
             $CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector']) ? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
Please login to merge, or discard this patch.
core/EE_Capabilities.core.php 2 patches
Indentation   +1389 added lines, -1389 removed lines patch added patch discarded remove patch
@@ -18,1001 +18,1001 @@  discard block
 block discarded – undo
18 18
 final class EE_Capabilities extends EE_Base
19 19
 {
20 20
 
21
-    /**
22
-     * the name of the wp option used to store caps previously initialized
23
-     */
24
-    const option_name = 'ee_caps_initialized';
25
-
26
-    /**
27
-     * instance of EE_Capabilities object
28
-     *
29
-     * @var EE_Capabilities
30
-     */
31
-    private static $_instance;
32
-
33
-
34
-    /**
35
-     * This is a map of caps that correspond to a default WP_Role.
36
-     * Array is indexed by Role and values are ee capabilities.
37
-     *
38
-     * @since 4.5.0
39
-     *
40
-     * @var array
41
-     */
42
-    private $capabilities_map = array();
43
-
44
-    /**
45
-     * This used to hold an array of EE_Meta_Capability_Map objects
46
-     * that define the granular capabilities mapped to for a user depending on context.
47
-     *
48
-     * @var EE_Meta_Capability_Map[]
49
-     */
50
-    private $_meta_caps = array();
51
-
52
-    /**
53
-     * The internal $capabilities_map needs to be initialized before it can be used.
54
-     * This flag tracks whether that has happened or not.
55
-     * But for this to work, we need three states to indicate:
56
-     *      initialization has not occurred at all
57
-     *      initialization has started but is not complete
58
-     *      initialization is complete
59
-     * The reason this is needed is because the addCaps() method
60
-     * normally requires the $capabilities_map to be initialized,
61
-     * but is also used during the initialization process.
62
-     * So:
63
-     *      If initialized === null, init_caps() will be called before any other methods will run.
64
-     *      If initialized === false, then init_caps() is in the process of running it's logic.
65
-     *      If initialized === true, then init_caps() has completed the initialization process.
66
-     *
67
-     * @var boolean|null $initialized
68
-     */
69
-    private $initialized;
70
-
71
-    /**
72
-     * @var boolean $reset
73
-     */
74
-    private $reset = false;
75
-
76
-
77
-
78
-    /**
79
-     * singleton method used to instantiate class object
80
-     *
81
-     * @since 4.5.0
82
-     *
83
-     * @return EE_Capabilities
84
-     */
85
-    public static function instance()
86
-    {
87
-        //check if instantiated, and if not do so.
88
-        if (! self::$_instance instanceof EE_Capabilities) {
89
-            self::$_instance = new self();
90
-        }
91
-        return self::$_instance;
92
-    }
93
-
94
-
95
-
96
-    /**
97
-     * private constructor
98
-     *
99
-     * @since 4.5.0
100
-     */
101
-    private function __construct()
102
-    {
103
-    }
104
-
105
-
106
-
107
-    /**
108
-     * This delays the initialization of the capabilities class until EE_System core is loaded and ready.
109
-     *
110
-     * @param bool $reset allows for resetting the default capabilities saved on roles.  Note that this doesn't
111
-     *                    actually REMOVE any capabilities from existing roles, it just resaves defaults roles and
112
-     *                    ensures that they are up to date.
113
-     *
114
-     * @since 4.5.0
115
-     * @return bool
116
-     * @throws EE_Error
117
-     */
118
-    public function init_caps($reset = false)
119
-    {
120
-        if(! EE_Maintenance_Mode::instance()->models_can_query()){
121
-            return false;
122
-        }
123
-        $this->reset = filter_var($reset, FILTER_VALIDATE_BOOLEAN);
124
-        // if reset, then completely delete the cache option and clear the $capabilities_map property.
125
-        if ($this->reset) {
126
-            $this->initialized = null;
127
-            $this->capabilities_map = array();
128
-            delete_option(self::option_name);
129
-        }
130
-        if ($this->initialized === null) {
131
-            $this->initialized = false;
132
-            do_action(
133
-                'AHEE__EE_Capabilities__init_caps__before_initialization',
134
-                $this->reset
135
-            );
136
-            $this->addCaps($this->_init_caps_map());
137
-            $this->_set_meta_caps();
138
-            do_action(
139
-                'AHEE__EE_Capabilities__init_caps__after_initialization',
140
-                $this->capabilities_map
141
-            );
142
-            $this->initialized = true;
143
-        }
144
-        // reset $this->reset so that it's not stuck on true if init_caps() gets called again
145
-        $this->reset = false;
146
-        return true;
147
-    }
148
-
149
-
150
-
151
-
152
-    /**
153
-     * This sets the meta caps property.
154
-     *
155
-     * @since 4.5.0
156
-     * @return void
157
-     * @throws EE_Error
158
-     */
159
-    private function _set_meta_caps()
160
-    {
161
-        // get default meta caps and filter the returned array
162
-        $this->_meta_caps = apply_filters(
163
-            'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
164
-            $this->_get_default_meta_caps_array()
165
-        );
166
-        //add filter for map_meta_caps but only if models can query.
167
-        if (! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
168
-            add_filter('map_meta_cap', array($this, 'map_meta_caps'), 10, 4);
169
-        }
170
-    }
171
-
172
-
173
-
174
-    /**
175
-     * This builds and returns the default meta_caps array only once.
176
-     *
177
-     * @since  4.8.28.rc.012
178
-     * @return array
179
-     * @throws EE_Error
180
-     */
181
-    private function _get_default_meta_caps_array()
182
-    {
183
-        static $default_meta_caps = array();
184
-        // make sure we're only ever initializing the default _meta_caps array once if it's empty.
185
-        if (empty($default_meta_caps)) {
186
-            $default_meta_caps = array(
187
-                //edits
188
-                new EE_Meta_Capability_Map_Edit(
189
-                    'ee_edit_event',
190
-                    array('Event', 'ee_edit_published_events', 'ee_edit_others_events', 'ee_edit_private_events')
191
-                ),
192
-                new EE_Meta_Capability_Map_Edit(
193
-                    'ee_edit_venue',
194
-                    array('Venue', 'ee_edit_published_venues', 'ee_edit_others_venues', 'ee_edit_private_venues')
195
-                ),
196
-                new EE_Meta_Capability_Map_Edit(
197
-                    'ee_edit_registration',
198
-                    array('Registration', '', 'ee_edit_others_registrations', '')
199
-                ),
200
-                new EE_Meta_Capability_Map_Edit(
201
-                    'ee_edit_checkin',
202
-                    array('Registration', '', 'ee_edit_others_checkins', '')
203
-                ),
204
-                new EE_Meta_Capability_Map_Messages_Cap(
205
-                    'ee_edit_message',
206
-                    array('Message_Template_Group', '', 'ee_edit_others_messages', 'ee_edit_global_messages')
207
-                ),
208
-                new EE_Meta_Capability_Map_Edit(
209
-                    'ee_edit_default_ticket',
210
-                    array('Ticket', '', 'ee_edit_others_default_tickets', '')
211
-                ),
212
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
213
-                    'ee_edit_question',
214
-                    array('Question', '', '', 'ee_edit_system_questions')
215
-                ),
216
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
217
-                    'ee_edit_question_group',
218
-                    array('Question_Group', '', '', 'ee_edit_system_question_groups')
219
-                ),
220
-                new EE_Meta_Capability_Map_Edit(
221
-                    'ee_edit_payment_method',
222
-                    array('Payment_Method', '', 'ee_edit_others_payment_methods', '')
223
-                ),
224
-                //reads
225
-                new EE_Meta_Capability_Map_Read(
226
-                    'ee_read_event',
227
-                    array('Event', '', 'ee_read_others_events', 'ee_read_private_events')
228
-                ),
229
-                new EE_Meta_Capability_Map_Read(
230
-                    'ee_read_venue',
231
-                    array('Venue', '', 'ee_read_others_venues', 'ee_read_private_venues')
232
-                ),
233
-                new EE_Meta_Capability_Map_Read(
234
-                    'ee_read_registration',
235
-                    array('Registration', '', 'ee_read_others_registrations', '')
236
-                ),
237
-                new EE_Meta_Capability_Map_Read(
238
-                    'ee_read_checkin',
239
-                    array('Registration', '', 'ee_read_others_checkins', '')
240
-                ),
241
-                new EE_Meta_Capability_Map_Messages_Cap(
242
-                    'ee_read_message',
243
-                    array('Message_Template_Group', '', 'ee_read_others_messages', 'ee_read_global_messages')
244
-                ),
245
-                new EE_Meta_Capability_Map_Read(
246
-                    'ee_read_default_ticket',
247
-                    array('Ticket', '', 'ee_read_others_default_tickets', '')
248
-                ),
249
-                new EE_Meta_Capability_Map_Read(
250
-                    'ee_read_payment_method',
251
-                    array('Payment_Method', '', 'ee_read_others_payment_methods', '')
252
-                ),
253
-                //deletes
254
-                new EE_Meta_Capability_Map_Delete(
255
-                    'ee_delete_event',
256
-                    array(
257
-                        'Event',
258
-                        'ee_delete_published_events',
259
-                        'ee_delete_others_events',
260
-                        'ee_delete_private_events',
261
-                    )
262
-                ),
263
-                new EE_Meta_Capability_Map_Delete(
264
-                    'ee_delete_venue',
265
-                    array(
266
-                        'Venue',
267
-                        'ee_delete_published_venues',
268
-                        'ee_delete_others_venues',
269
-                        'ee_delete_private_venues',
270
-                    )
271
-                ),
272
-                new EE_Meta_Capability_Map_Delete(
273
-                    'ee_delete_registration',
274
-                    array('Registration', '', 'ee_delete_others_registrations', '')
275
-                ),
276
-                new EE_Meta_Capability_Map_Delete(
277
-                    'ee_delete_checkin',
278
-                    array('Registration', '', 'ee_delete_others_checkins', '')
279
-                ),
280
-                new EE_Meta_Capability_Map_Messages_Cap(
281
-                    'ee_delete_message',
282
-                    array('Message_Template_Group', '', 'ee_delete_others_messages', 'ee_delete_global_messages')
283
-                ),
284
-                new EE_Meta_Capability_Map_Delete(
285
-                    'ee_delete_default_ticket',
286
-                    array('Ticket', '', 'ee_delete_others_default_tickets', '')
287
-                ),
288
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
289
-                    'ee_delete_question',
290
-                    array('Question', '', '', 'delete_system_questions')
291
-                ),
292
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
293
-                    'ee_delete_question_group',
294
-                    array('Question_Group', '', '', 'delete_system_question_groups')
295
-                ),
296
-                new EE_Meta_Capability_Map_Delete(
297
-                    'ee_delete_payment_method',
298
-                    array('Payment_Method', '', 'ee_delete_others_payment_methods', '')
299
-                ),
300
-            );
301
-        }
302
-        return $default_meta_caps;
303
-    }
304
-
305
-
306
-
307
-    /**
308
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
309
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
310
-     *
311
-     * The actual logic is carried out by implementer classes in their definition of _map_meta_caps.
312
-     *
313
-     * @since 4.5.0
314
-     * @see   wp-includes/capabilities.php
315
-     *
316
-     * @param array  $caps    actual users capabilities
317
-     * @param string $cap     initial capability name that is being checked (the "map" key)
318
-     * @param int    $user_id The user id
319
-     * @param array  $args    Adds context to the cap. Typically the object ID.
320
-     * @return array actual users capabilities
321
-     * @throws EE_Error
322
-     */
323
-    public function map_meta_caps($caps, $cap, $user_id, $args)
324
-    {
325
-        if (did_action('AHEE__EE_System__load_espresso_addons__complete')) {
326
-            //loop through our _meta_caps array
327
-            foreach ($this->_meta_caps as $meta_map) {
328
-                if (! $meta_map instanceof EE_Meta_Capability_Map) {
329
-                    continue;
330
-                }
331
-                // don't load models if there is no object ID in the args
332
-                if (! empty($args[0])) {
333
-                    $meta_map->ensure_is_model();
334
-                }
335
-                $caps = $meta_map->map_meta_caps($caps, $cap, $user_id, $args);
336
-            }
337
-        }
338
-        return $caps;
339
-    }
340
-
341
-
342
-
343
-    /**
344
-     * This sets up and returns the initial capabilities map for Event Espresso
345
-     * Note this array is filtered.
346
-     * It is assumed that all available EE capabilities are assigned to the administrator role.
347
-     *
348
-     * @since 4.5.0
349
-     *
350
-     * @return array
351
-     */
352
-    private function _init_caps_map()
353
-    {
354
-        return apply_filters(
355
-            'FHEE__EE_Capabilities__init_caps_map__caps',
356
-            array(
357
-                'administrator'           => array(
358
-                    //basic access
359
-                    'ee_read_ee',
360
-                    //gateways
361
-                    /**
362
-                     * note that with payment method capabilities, although we've implemented
363
-                     * capability mapping which will be used for accessing payment methods owned by
364
-                     * other users.  This is not fully implemented yet in the payment method ui.
365
-                     * Currently only the "plural" caps are in active use.
366
-                     * (Specific payment method caps are in use as well).
367
-                     **/
368
-                    'ee_manage_gateways',
369
-                    'ee_read_payment_methods',
370
-                    'ee_read_others_payment_methods',
371
-                    'ee_edit_payment_methods',
372
-                    'ee_edit_others_payment_methods',
373
-                    'ee_delete_payment_methods',
374
-                    //events
375
-                    'ee_publish_events',
376
-                    'ee_read_private_events',
377
-                    'ee_read_others_events',
378
-                    'ee_read_events',
379
-                    'ee_edit_events',
380
-                    'ee_edit_published_events',
381
-                    'ee_edit_others_events',
382
-                    'ee_edit_private_events',
383
-                    'ee_delete_published_events',
384
-                    'ee_delete_private_events',
385
-                    'ee_delete_events',
386
-                    'ee_delete_others_events',
387
-                    //event categories
388
-                    'ee_manage_event_categories',
389
-                    'ee_edit_event_category',
390
-                    'ee_delete_event_category',
391
-                    'ee_assign_event_category',
392
-                    //venues
393
-                    'ee_publish_venues',
394
-                    'ee_read_venues',
395
-                    'ee_read_others_venues',
396
-                    'ee_read_private_venues',
397
-                    'ee_edit_venues',
398
-                    'ee_edit_others_venues',
399
-                    'ee_edit_published_venues',
400
-                    'ee_edit_private_venues',
401
-                    'ee_delete_venues',
402
-                    'ee_delete_others_venues',
403
-                    'ee_delete_private_venues',
404
-                    'ee_delete_published_venues',
405
-                    //venue categories
406
-                    'ee_manage_venue_categories',
407
-                    'ee_edit_venue_category',
408
-                    'ee_delete_venue_category',
409
-                    'ee_assign_venue_category',
410
-                    //contacts
411
-                    'ee_read_contacts',
412
-                    'ee_edit_contacts',
413
-                    'ee_delete_contacts',
414
-                    //registrations
415
-                    'ee_read_registrations',
416
-                    'ee_read_others_registrations',
417
-                    'ee_edit_registrations',
418
-                    'ee_edit_others_registrations',
419
-                    'ee_delete_registrations',
420
-                    //checkins
421
-                    'ee_read_others_checkins',
422
-                    'ee_read_checkins',
423
-                    'ee_edit_checkins',
424
-                    'ee_edit_others_checkins',
425
-                    'ee_delete_checkins',
426
-                    'ee_delete_others_checkins',
427
-                    //transactions && payments
428
-                    'ee_read_transaction',
429
-                    'ee_read_transactions',
430
-                    'ee_edit_payments',
431
-                    'ee_delete_payments',
432
-                    //messages
433
-                    'ee_read_messages',
434
-                    'ee_read_others_messages',
435
-                    'ee_read_global_messages',
436
-                    'ee_edit_global_messages',
437
-                    'ee_edit_messages',
438
-                    'ee_edit_others_messages',
439
-                    'ee_delete_messages',
440
-                    'ee_delete_others_messages',
441
-                    'ee_delete_global_messages',
442
-                    'ee_send_message',
443
-                    //tickets
444
-                    'ee_read_default_tickets',
445
-                    'ee_read_others_default_tickets',
446
-                    'ee_edit_default_tickets',
447
-                    'ee_edit_others_default_tickets',
448
-                    'ee_delete_default_tickets',
449
-                    'ee_delete_others_default_tickets',
450
-                    //prices
451
-                    'ee_edit_default_price',
452
-                    'ee_edit_default_prices',
453
-                    'ee_delete_default_price',
454
-                    'ee_delete_default_prices',
455
-                    'ee_edit_default_price_type',
456
-                    'ee_edit_default_price_types',
457
-                    'ee_delete_default_price_type',
458
-                    'ee_delete_default_price_types',
459
-                    'ee_read_default_prices',
460
-                    'ee_read_default_price_types',
461
-                    //registration form
462
-                    'ee_edit_questions',
463
-                    'ee_edit_system_questions',
464
-                    'ee_read_questions',
465
-                    'ee_delete_questions',
466
-                    'ee_edit_question_groups',
467
-                    'ee_read_question_groups',
468
-                    'ee_edit_system_question_groups',
469
-                    'ee_delete_question_groups',
470
-                    //event_type taxonomy
471
-                    'ee_assign_event_type',
472
-                    'ee_manage_event_types',
473
-                    'ee_edit_event_type',
474
-                    'ee_delete_event_type',
475
-                ),
476
-                'ee_events_administrator' => array(
477
-                    //core wp caps
478
-                    'read',
479
-                    'read_private_pages',
480
-                    'read_private_posts',
481
-                    'edit_users',
482
-                    'edit_posts',
483
-                    'edit_pages',
484
-                    'edit_published_posts',
485
-                    'edit_published_pages',
486
-                    'edit_private_pages',
487
-                    'edit_private_posts',
488
-                    'edit_others_posts',
489
-                    'edit_others_pages',
490
-                    'publish_posts',
491
-                    'publish_pages',
492
-                    'delete_posts',
493
-                    'delete_pages',
494
-                    'delete_private_pages',
495
-                    'delete_private_posts',
496
-                    'delete_published_pages',
497
-                    'delete_published_posts',
498
-                    'delete_others_posts',
499
-                    'delete_others_pages',
500
-                    'manage_categories',
501
-                    'manage_links',
502
-                    'moderate_comments',
503
-                    'unfiltered_html',
504
-                    'upload_files',
505
-                    'export',
506
-                    'import',
507
-                    'list_users',
508
-                    'level_1', //required if user with this role shows up in author dropdowns
509
-                    //basic ee access
510
-                    'ee_read_ee',
511
-                    //events
512
-                    'ee_publish_events',
513
-                    'ee_read_private_events',
514
-                    'ee_read_others_events',
515
-                    'ee_read_event',
516
-                    'ee_read_events',
517
-                    'ee_edit_event',
518
-                    'ee_edit_events',
519
-                    'ee_edit_published_events',
520
-                    'ee_edit_others_events',
521
-                    'ee_edit_private_events',
522
-                    'ee_delete_published_events',
523
-                    'ee_delete_private_events',
524
-                    'ee_delete_event',
525
-                    'ee_delete_events',
526
-                    'ee_delete_others_events',
527
-                    //event categories
528
-                    'ee_manage_event_categories',
529
-                    'ee_edit_event_category',
530
-                    'ee_delete_event_category',
531
-                    'ee_assign_event_category',
532
-                    //venues
533
-                    'ee_publish_venues',
534
-                    'ee_read_venue',
535
-                    'ee_read_venues',
536
-                    'ee_read_others_venues',
537
-                    'ee_read_private_venues',
538
-                    'ee_edit_venue',
539
-                    'ee_edit_venues',
540
-                    'ee_edit_others_venues',
541
-                    'ee_edit_published_venues',
542
-                    'ee_edit_private_venues',
543
-                    'ee_delete_venue',
544
-                    'ee_delete_venues',
545
-                    'ee_delete_others_venues',
546
-                    'ee_delete_private_venues',
547
-                    'ee_delete_published_venues',
548
-                    //venue categories
549
-                    'ee_manage_venue_categories',
550
-                    'ee_edit_venue_category',
551
-                    'ee_delete_venue_category',
552
-                    'ee_assign_venue_category',
553
-                    //contacts
554
-                    'ee_read_contacts',
555
-                    'ee_edit_contacts',
556
-                    'ee_delete_contacts',
557
-                    //registrations
558
-                    'ee_read_registrations',
559
-                    'ee_read_others_registrations',
560
-                    'ee_edit_registration',
561
-                    'ee_edit_registrations',
562
-                    'ee_edit_others_registrations',
563
-                    'ee_delete_registration',
564
-                    'ee_delete_registrations',
565
-                    //checkins
566
-                    'ee_read_others_checkins',
567
-                    'ee_read_checkins',
568
-                    'ee_edit_checkins',
569
-                    'ee_edit_others_checkins',
570
-                    'ee_delete_checkins',
571
-                    'ee_delete_others_checkins',
572
-                    //transactions && payments
573
-                    'ee_read_transaction',
574
-                    'ee_read_transactions',
575
-                    'ee_edit_payments',
576
-                    'ee_delete_payments',
577
-                    //messages
578
-                    'ee_read_messages',
579
-                    'ee_read_others_messages',
580
-                    'ee_read_global_messages',
581
-                    'ee_edit_global_messages',
582
-                    'ee_edit_messages',
583
-                    'ee_edit_others_messages',
584
-                    'ee_delete_messages',
585
-                    'ee_delete_others_messages',
586
-                    'ee_delete_global_messages',
587
-                    'ee_send_message',
588
-                    //tickets
589
-                    'ee_read_default_tickets',
590
-                    'ee_read_others_default_tickets',
591
-                    'ee_edit_default_tickets',
592
-                    'ee_edit_others_default_tickets',
593
-                    'ee_delete_default_tickets',
594
-                    'ee_delete_others_default_tickets',
595
-                    //prices
596
-                    'ee_edit_default_price',
597
-                    'ee_edit_default_prices',
598
-                    'ee_delete_default_price',
599
-                    'ee_delete_default_prices',
600
-                    'ee_edit_default_price_type',
601
-                    'ee_edit_default_price_types',
602
-                    'ee_delete_default_price_type',
603
-                    'ee_delete_default_price_types',
604
-                    'ee_read_default_prices',
605
-                    'ee_read_default_price_types',
606
-                    //registration form
607
-                    'ee_edit_questions',
608
-                    'ee_edit_system_questions',
609
-                    'ee_read_questions',
610
-                    'ee_delete_questions',
611
-                    'ee_edit_question_groups',
612
-                    'ee_read_question_groups',
613
-                    'ee_edit_system_question_groups',
614
-                    'ee_delete_question_groups',
615
-                    //event_type taxonomy
616
-                    'ee_assign_event_type',
617
-                    'ee_manage_event_types',
618
-                    'ee_edit_event_type',
619
-                    'ee_delete_event_type',
620
-                )
621
-            )
622
-        );
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @return bool
629
-     * @throws EE_Error
630
-     */
631
-    private function setupCapabilitiesMap()
632
-    {
633
-        // if the initialization process hasn't even started, then we need to call init_caps()
634
-        if($this->initialized === null) {
635
-            return $this->init_caps();
636
-        }
637
-        // unless resetting, get caps from db if we haven't already
638
-        $this->capabilities_map = $this->reset || ! empty($this->capabilities_map)
639
-            ? $this->capabilities_map
640
-            : get_option(self::option_name, array());
641
-        return true;
642
-    }
643
-
644
-
645
-
646
-    /**
647
-     * @param bool $update
648
-     * @return bool
649
-     */
650
-    private function updateCapabilitiesMap($update = true)
651
-    {
652
-        return $update ? update_option(self::option_name, $this->capabilities_map) : false;
653
-    }
654
-
655
-
656
-
657
-    /**
658
-     * Adds capabilities to roles.
659
-     *
660
-     * @since 4.9.42
661
-     * @param array $capabilities_to_add array of capabilities to add, indexed by roles.
662
-     *                                   Note that this should ONLY be called on activation hook
663
-     *                                   otherwise the caps will be added on every request.
664
-     * @return bool
665
-     * @throws \EE_Error
666
-     */
667
-    public function addCaps(array $capabilities_to_add)
668
-    {
669
-        // don't do anything if the capabilities map can not be initialized
670
-        if (! $this->setupCapabilitiesMap()) {
671
-            return false;
672
-        }
673
-        // and filter the array so others can get in on the fun during resets
674
-        $capabilities_to_add = apply_filters(
675
-            'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
676
-            $capabilities_to_add,
677
-            $this->reset,
678
-            $this->capabilities_map
679
-        );
680
-        $update_capabilities_map = false;
681
-        // if not reset, see what caps are new for each role. if they're new, add them.
682
-        foreach ($capabilities_to_add as $role => $caps_for_role) {
683
-            if (is_array($caps_for_role)) {
684
-                foreach ($caps_for_role as $cap) {
685
-                    if (
686
-                        ! $this->capHasBeenAddedToRole($role, $cap)
687
-                        && $this->add_cap_to_role($role, $cap, true, false)
688
-                    ) {
689
-                        $update_capabilities_map = true;
690
-                    }
691
-                }
692
-            }
693
-        }
694
-        // now let's just save the cap that has been set but only if there's been a change.
695
-        $updated = $this->updateCapabilitiesMap($update_capabilities_map);
696
-        $this->flushWpUser($updated);
697
-        do_action('AHEE__EE_Capabilities__addCaps__complete', $this->capabilities_map, $updated);
698
-        return $updated;
699
-    }
700
-
701
-
702
-
703
-    /**
704
-     * Loops through the capabilities map and removes the role caps specified by the incoming array
705
-     *
706
-     * @param array $caps_map map of capabilities to be removed (indexed by roles)
707
-     * @return bool
708
-     * @throws \EE_Error
709
-     */
710
-    public function removeCaps($caps_map)
711
-    {
712
-        // don't do anything if the capabilities map can not be initialized
713
-        if (! $this->setupCapabilitiesMap()) {
714
-            return false;
715
-        }
716
-        $update_capabilities_map = false;
717
-        foreach ($caps_map as $role => $caps_for_role) {
718
-            if (is_array($caps_for_role)) {
719
-                foreach ($caps_for_role as $cap) {
720
-                    if ($this->capHasBeenAddedToRole($role, $cap)
721
-                        && $this->remove_cap_from_role($role, $cap, false)
722
-                    ) {
723
-                        $update_capabilities_map = true;
724
-                    }
725
-                }
726
-            }
727
-        }
728
-        // maybe resave the caps
729
-        $updated = $this->updateCapabilitiesMap($update_capabilities_map);
730
-        $this->flushWpUser($updated);
731
-        return $updated;
732
-    }
733
-
734
-
735
-    /**
736
-     * This ensures that the WP User object cached on the $current_user global in WP has the latest capabilities from
737
-     * the roles on that user.
738
-     *
739
-     * @param bool $flush  Default is to flush the WP_User object.  If false, then this method effectively does nothing.
740
-     */
741
-    private function flushWpUser($flush = true)
742
-    {
743
-        if ($flush) {
744
-            $user = wp_get_current_user();
745
-            if ($user instanceof WP_User) {
746
-                $user->get_role_caps();
747
-            }
748
-        }
749
-    }
750
-
751
-
752
-
753
-    /**
754
-     * This method sets a capability on a role.  Note this should only be done on activation, or if you have something
755
-     * specific to prevent the cap from being added on every page load (adding caps are persistent to the db). Note.
756
-     * this is a wrapper for $wp_role->add_cap()
757
-     *
758
-     * @see   wp-includes/capabilities.php
759
-     * @since 4.5.0
760
-     * @param string|WP_Role $role  A WordPress role the capability is being added to
761
-     * @param string         $cap   The capability being added to the role
762
-     * @param bool           $grant Whether to grant access to this cap on this role.
763
-     * @param bool           $update_capabilities_map
764
-     * @return bool
765
-     * @throws \EE_Error
766
-     */
767
-    public function add_cap_to_role($role, $cap, $grant = true, $update_capabilities_map = true)
768
-    {
769
-        // capture incoming value for $role because we may need it to create a new WP_Role
770
-        $orig_role = $role;
771
-        $role = $role instanceof WP_Role ? $role : get_role($role);
772
-        //if the role isn't available then we create it.
773
-        if (! $role instanceof WP_Role) {
774
-            // if a plugin wants to create a specific role name then they should create the role before
775
-            // EE_Capabilities does.  Otherwise this function will create the role name from the slug:
776
-            // - removes any `ee_` namespacing from the start of the slug.
777
-            // - replaces `_` with ` ` (empty space).
778
-            // - sentence case on the resulting string.
779
-            $role_label = ucwords(str_replace(array('ee_', '_'), array('', ' '), $orig_role));
780
-            $role = add_role($orig_role, $role_label);
781
-        }
782
-        if ($role instanceof WP_Role) {
783
-            // don't do anything if the capabilities map can not be initialized
784
-            if (! $this->setupCapabilitiesMap()) {
785
-                return false;
786
-            }
787
-            if (! $this->capHasBeenAddedToRole($role->name, $cap)) {
788
-                $role->add_cap($cap, $grant);
789
-                $this->capabilities_map[ $role->name ][] = $cap;
790
-                $this->updateCapabilitiesMap($update_capabilities_map);
791
-                return true;
792
-            }
793
-        }
794
-        return false;
795
-    }
796
-
797
-
798
-
799
-    /**
800
-     * Functions similarly to add_cap_to_role except removes cap from given role.
801
-     * Wrapper for $wp_role->remove_cap()
802
-     *
803
-     * @see   wp-includes/capabilities.php
804
-     * @since 4.5.0
805
-     * @param string|WP_Role $role A WordPress role the capability is being removed from.
806
-     * @param string         $cap  The capability being removed
807
-     * @param bool           $update_capabilities_map
808
-     * @return bool
809
-     * @throws \EE_Error
810
-     */
811
-    public function remove_cap_from_role($role, $cap, $update_capabilities_map = true)
812
-    {
813
-        // don't do anything if the capabilities map can not be initialized
814
-        if (! $this->setupCapabilitiesMap()) {
815
-            return false;
816
-        }
817
-
818
-        $role = $role instanceof WP_Role ? $role : get_role($role);
819
-        if ($role instanceof WP_Role && $index = $this->capHasBeenAddedToRole($role->name, $cap, true)) {
820
-            $role->remove_cap($cap);
821
-            unset($this->capabilities_map[ $role->name ][ $index ]);
822
-            $this->updateCapabilitiesMap($update_capabilities_map);
823
-            return true;
824
-        }
825
-        return false;
826
-    }
827
-
828
-
829
-
830
-    /**
831
-     * @param string $role_name
832
-     * @param string $cap
833
-     * @param bool   $get_index
834
-     * @return bool|mixed
835
-     */
836
-    private function capHasBeenAddedToRole($role_name='', $cap='', $get_index = false)
837
-    {
838
-        if (
839
-            isset($this->capabilities_map[$role_name])
840
-            && ($index = array_search($cap, $this->capabilities_map[$role_name], true)) !== false
841
-        ) {
842
-            return $get_index ? $index : true;
843
-        }
844
-        return false;
845
-    }
846
-
847
-
848
-
849
-    /**
850
-     * Wrapper for the native WP current_user_can() method.
851
-     * This is provided as a handy method for a couple things:
852
-     * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
853
-     * write those filters wherever current_user_can is called).
854
-     * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
855
-     *
856
-     * @since 4.5.0
857
-     *
858
-     * @param string $cap     The cap being checked.
859
-     * @param string $context The context where the current_user_can is being called from.
860
-     * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
861
-     *                        filters.
862
-     *
863
-     * @return bool  Whether user can or not.
864
-     */
865
-    public function current_user_can($cap, $context, $id = 0)
866
-    {
867
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
868
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__' . $context, $cap, $id);
869
-        $filtered_cap = apply_filters(
870
-            'FHEE__EE_Capabilities__current_user_can__cap',
871
-            $filtered_cap,
872
-            $context,
873
-            $cap,
874
-            $id
875
-        );
876
-        return ! empty($id)
877
-            ? current_user_can($filtered_cap, $id)
878
-            : current_user_can($filtered_cap);
879
-    }
880
-
881
-
882
-
883
-    /**
884
-     * This is a wrapper for the WP user_can() function and follows the same style as the other wrappers in this class.
885
-     *
886
-     * @param int|WP_User $user    Either the user_id or a WP_User object
887
-     * @param string      $cap     The capability string being checked
888
-     * @param string      $context The context where the user_can is being called from (used in filters).
889
-     * @param int         $id      Optional. Id for item where user_can is being called from ( used in map_meta_cap()
890
-     *                             filters)
891
-     *
892
-     * @return bool Whether user can or not.
893
-     */
894
-    public function user_can($user, $cap, $context, $id = 0)
895
-    {
896
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
897
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__' . $context, $cap, $user, $id);
898
-        $filtered_cap = apply_filters(
899
-            'FHEE__EE_Capabilities__user_can__cap',
900
-            $filtered_cap,
901
-            $context,
902
-            $cap,
903
-            $user,
904
-            $id
905
-        );
906
-        return ! empty($id)
907
-            ? user_can($user, $filtered_cap, $id)
908
-            : user_can($user, $filtered_cap);
909
-    }
910
-
911
-
912
-
913
-    /**
914
-     * Wrapper for the native WP current_user_can_for_blog() method.
915
-     * This is provided as a handy method for a couple things:
916
-     * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
917
-     * write those filters wherever current_user_can is called).
918
-     * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
919
-     *
920
-     * @since 4.5.0
921
-     *
922
-     * @param int    $blog_id The blog id that is being checked for.
923
-     * @param string $cap     The cap being checked.
924
-     * @param string $context The context where the current_user_can is being called from.
925
-     * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
926
-     *                        filters.
927
-     *
928
-     * @return bool  Whether user can or not.
929
-     */
930
-    public function current_user_can_for_blog($blog_id, $cap, $context, $id = 0)
931
-    {
932
-        $user_can = ! empty($id)
933
-            ? current_user_can_for_blog($blog_id, $cap, $id)
934
-            : current_user_can($blog_id, $cap);
935
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
936
-        $user_can = apply_filters(
937
-            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__' . $context,
938
-            $user_can,
939
-            $blog_id,
940
-            $cap,
941
-            $id
942
-        );
943
-        $user_can = apply_filters(
944
-            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can',
945
-            $user_can,
946
-            $context,
947
-            $blog_id,
948
-            $cap,
949
-            $id
950
-        );
951
-        return $user_can;
952
-    }
953
-
954
-
955
-
956
-    /**
957
-     * This helper method just returns an array of registered EE capabilities.
958
-     *
959
-     * @since 4.5.0
960
-     * @param string $role If empty then the entire role/capability map is returned.
961
-     *                     Otherwise just the capabilities for the given role are returned.
962
-     * @return array
963
-     * @throws EE_Error
964
-     */
965
-    public function get_ee_capabilities($role = 'administrator')
966
-    {
967
-        if (! $this->initialized) {
968
-            $this->init_caps();
969
-        }
970
-        if (empty($role)) {
971
-            return $this->capabilities_map;
972
-        }
973
-        return isset($this->capabilities_map[ $role ])
974
-            ? $this->capabilities_map[ $role ]
975
-            : array();
976
-    }
977
-
978
-
979
-
980
-    /**
981
-     * @deprecated 4.9.42
982
-     * @param bool  $reset      If you need to reset Event Espresso's capabilities,
983
-     *                          then please use the init_caps() method with the "$reset" parameter set to "true"
984
-     * @param array $caps_map   Optional.
985
-     *                          Can be used to send a custom map of roles and capabilities for setting them up.
986
-     *                          Note that this should ONLY be called on activation hook or some other one-time
987
-     *                          task otherwise the caps will be added on every request.
988
-     * @return void
989
-     * @throws EE_Error
990
-     */
991
-    public function init_role_caps($reset = false, $caps_map = array())
992
-    {
993
-        // If this method is called directly and reset is set as 'true',
994
-        // then display a doing it wrong notice, because we want resets to go through init_caps()
995
-        // to guarantee that everything is set up correctly.
996
-        // This prevents the capabilities map getting reset incorrectly by direct calls to this method.
997
-        if ($reset) {
998
-            EE_Error::doing_it_wrong(
999
-                __METHOD__,
1000
-                sprintf(
1001
-                    esc_html__(
1002
-                        'The "%1$s" parameter for the "%2$s" method is deprecated. If you need to reset Event Espresso\'s capabilities, then please use the "%3$s" method with the "%1$s" parameter set to "%4$s".',
1003
-                        'event_espresso'
1004
-                    ),
1005
-                    '$reset',
1006
-                    __METHOD__ . '()',
1007
-                    'EE_Capabilities::init_caps()',
1008
-                    'true'
1009
-                ),
1010
-                '4.9.42',
1011
-                '5.0.0'
1012
-            );
1013
-        }
1014
-        $this->addCaps($caps_map);
1015
-    }
21
+	/**
22
+	 * the name of the wp option used to store caps previously initialized
23
+	 */
24
+	const option_name = 'ee_caps_initialized';
25
+
26
+	/**
27
+	 * instance of EE_Capabilities object
28
+	 *
29
+	 * @var EE_Capabilities
30
+	 */
31
+	private static $_instance;
32
+
33
+
34
+	/**
35
+	 * This is a map of caps that correspond to a default WP_Role.
36
+	 * Array is indexed by Role and values are ee capabilities.
37
+	 *
38
+	 * @since 4.5.0
39
+	 *
40
+	 * @var array
41
+	 */
42
+	private $capabilities_map = array();
43
+
44
+	/**
45
+	 * This used to hold an array of EE_Meta_Capability_Map objects
46
+	 * that define the granular capabilities mapped to for a user depending on context.
47
+	 *
48
+	 * @var EE_Meta_Capability_Map[]
49
+	 */
50
+	private $_meta_caps = array();
51
+
52
+	/**
53
+	 * The internal $capabilities_map needs to be initialized before it can be used.
54
+	 * This flag tracks whether that has happened or not.
55
+	 * But for this to work, we need three states to indicate:
56
+	 *      initialization has not occurred at all
57
+	 *      initialization has started but is not complete
58
+	 *      initialization is complete
59
+	 * The reason this is needed is because the addCaps() method
60
+	 * normally requires the $capabilities_map to be initialized,
61
+	 * but is also used during the initialization process.
62
+	 * So:
63
+	 *      If initialized === null, init_caps() will be called before any other methods will run.
64
+	 *      If initialized === false, then init_caps() is in the process of running it's logic.
65
+	 *      If initialized === true, then init_caps() has completed the initialization process.
66
+	 *
67
+	 * @var boolean|null $initialized
68
+	 */
69
+	private $initialized;
70
+
71
+	/**
72
+	 * @var boolean $reset
73
+	 */
74
+	private $reset = false;
75
+
76
+
77
+
78
+	/**
79
+	 * singleton method used to instantiate class object
80
+	 *
81
+	 * @since 4.5.0
82
+	 *
83
+	 * @return EE_Capabilities
84
+	 */
85
+	public static function instance()
86
+	{
87
+		//check if instantiated, and if not do so.
88
+		if (! self::$_instance instanceof EE_Capabilities) {
89
+			self::$_instance = new self();
90
+		}
91
+		return self::$_instance;
92
+	}
93
+
94
+
95
+
96
+	/**
97
+	 * private constructor
98
+	 *
99
+	 * @since 4.5.0
100
+	 */
101
+	private function __construct()
102
+	{
103
+	}
104
+
105
+
106
+
107
+	/**
108
+	 * This delays the initialization of the capabilities class until EE_System core is loaded and ready.
109
+	 *
110
+	 * @param bool $reset allows for resetting the default capabilities saved on roles.  Note that this doesn't
111
+	 *                    actually REMOVE any capabilities from existing roles, it just resaves defaults roles and
112
+	 *                    ensures that they are up to date.
113
+	 *
114
+	 * @since 4.5.0
115
+	 * @return bool
116
+	 * @throws EE_Error
117
+	 */
118
+	public function init_caps($reset = false)
119
+	{
120
+		if(! EE_Maintenance_Mode::instance()->models_can_query()){
121
+			return false;
122
+		}
123
+		$this->reset = filter_var($reset, FILTER_VALIDATE_BOOLEAN);
124
+		// if reset, then completely delete the cache option and clear the $capabilities_map property.
125
+		if ($this->reset) {
126
+			$this->initialized = null;
127
+			$this->capabilities_map = array();
128
+			delete_option(self::option_name);
129
+		}
130
+		if ($this->initialized === null) {
131
+			$this->initialized = false;
132
+			do_action(
133
+				'AHEE__EE_Capabilities__init_caps__before_initialization',
134
+				$this->reset
135
+			);
136
+			$this->addCaps($this->_init_caps_map());
137
+			$this->_set_meta_caps();
138
+			do_action(
139
+				'AHEE__EE_Capabilities__init_caps__after_initialization',
140
+				$this->capabilities_map
141
+			);
142
+			$this->initialized = true;
143
+		}
144
+		// reset $this->reset so that it's not stuck on true if init_caps() gets called again
145
+		$this->reset = false;
146
+		return true;
147
+	}
148
+
149
+
150
+
151
+
152
+	/**
153
+	 * This sets the meta caps property.
154
+	 *
155
+	 * @since 4.5.0
156
+	 * @return void
157
+	 * @throws EE_Error
158
+	 */
159
+	private function _set_meta_caps()
160
+	{
161
+		// get default meta caps and filter the returned array
162
+		$this->_meta_caps = apply_filters(
163
+			'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
164
+			$this->_get_default_meta_caps_array()
165
+		);
166
+		//add filter for map_meta_caps but only if models can query.
167
+		if (! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
168
+			add_filter('map_meta_cap', array($this, 'map_meta_caps'), 10, 4);
169
+		}
170
+	}
171
+
172
+
173
+
174
+	/**
175
+	 * This builds and returns the default meta_caps array only once.
176
+	 *
177
+	 * @since  4.8.28.rc.012
178
+	 * @return array
179
+	 * @throws EE_Error
180
+	 */
181
+	private function _get_default_meta_caps_array()
182
+	{
183
+		static $default_meta_caps = array();
184
+		// make sure we're only ever initializing the default _meta_caps array once if it's empty.
185
+		if (empty($default_meta_caps)) {
186
+			$default_meta_caps = array(
187
+				//edits
188
+				new EE_Meta_Capability_Map_Edit(
189
+					'ee_edit_event',
190
+					array('Event', 'ee_edit_published_events', 'ee_edit_others_events', 'ee_edit_private_events')
191
+				),
192
+				new EE_Meta_Capability_Map_Edit(
193
+					'ee_edit_venue',
194
+					array('Venue', 'ee_edit_published_venues', 'ee_edit_others_venues', 'ee_edit_private_venues')
195
+				),
196
+				new EE_Meta_Capability_Map_Edit(
197
+					'ee_edit_registration',
198
+					array('Registration', '', 'ee_edit_others_registrations', '')
199
+				),
200
+				new EE_Meta_Capability_Map_Edit(
201
+					'ee_edit_checkin',
202
+					array('Registration', '', 'ee_edit_others_checkins', '')
203
+				),
204
+				new EE_Meta_Capability_Map_Messages_Cap(
205
+					'ee_edit_message',
206
+					array('Message_Template_Group', '', 'ee_edit_others_messages', 'ee_edit_global_messages')
207
+				),
208
+				new EE_Meta_Capability_Map_Edit(
209
+					'ee_edit_default_ticket',
210
+					array('Ticket', '', 'ee_edit_others_default_tickets', '')
211
+				),
212
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
213
+					'ee_edit_question',
214
+					array('Question', '', '', 'ee_edit_system_questions')
215
+				),
216
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
217
+					'ee_edit_question_group',
218
+					array('Question_Group', '', '', 'ee_edit_system_question_groups')
219
+				),
220
+				new EE_Meta_Capability_Map_Edit(
221
+					'ee_edit_payment_method',
222
+					array('Payment_Method', '', 'ee_edit_others_payment_methods', '')
223
+				),
224
+				//reads
225
+				new EE_Meta_Capability_Map_Read(
226
+					'ee_read_event',
227
+					array('Event', '', 'ee_read_others_events', 'ee_read_private_events')
228
+				),
229
+				new EE_Meta_Capability_Map_Read(
230
+					'ee_read_venue',
231
+					array('Venue', '', 'ee_read_others_venues', 'ee_read_private_venues')
232
+				),
233
+				new EE_Meta_Capability_Map_Read(
234
+					'ee_read_registration',
235
+					array('Registration', '', 'ee_read_others_registrations', '')
236
+				),
237
+				new EE_Meta_Capability_Map_Read(
238
+					'ee_read_checkin',
239
+					array('Registration', '', 'ee_read_others_checkins', '')
240
+				),
241
+				new EE_Meta_Capability_Map_Messages_Cap(
242
+					'ee_read_message',
243
+					array('Message_Template_Group', '', 'ee_read_others_messages', 'ee_read_global_messages')
244
+				),
245
+				new EE_Meta_Capability_Map_Read(
246
+					'ee_read_default_ticket',
247
+					array('Ticket', '', 'ee_read_others_default_tickets', '')
248
+				),
249
+				new EE_Meta_Capability_Map_Read(
250
+					'ee_read_payment_method',
251
+					array('Payment_Method', '', 'ee_read_others_payment_methods', '')
252
+				),
253
+				//deletes
254
+				new EE_Meta_Capability_Map_Delete(
255
+					'ee_delete_event',
256
+					array(
257
+						'Event',
258
+						'ee_delete_published_events',
259
+						'ee_delete_others_events',
260
+						'ee_delete_private_events',
261
+					)
262
+				),
263
+				new EE_Meta_Capability_Map_Delete(
264
+					'ee_delete_venue',
265
+					array(
266
+						'Venue',
267
+						'ee_delete_published_venues',
268
+						'ee_delete_others_venues',
269
+						'ee_delete_private_venues',
270
+					)
271
+				),
272
+				new EE_Meta_Capability_Map_Delete(
273
+					'ee_delete_registration',
274
+					array('Registration', '', 'ee_delete_others_registrations', '')
275
+				),
276
+				new EE_Meta_Capability_Map_Delete(
277
+					'ee_delete_checkin',
278
+					array('Registration', '', 'ee_delete_others_checkins', '')
279
+				),
280
+				new EE_Meta_Capability_Map_Messages_Cap(
281
+					'ee_delete_message',
282
+					array('Message_Template_Group', '', 'ee_delete_others_messages', 'ee_delete_global_messages')
283
+				),
284
+				new EE_Meta_Capability_Map_Delete(
285
+					'ee_delete_default_ticket',
286
+					array('Ticket', '', 'ee_delete_others_default_tickets', '')
287
+				),
288
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
289
+					'ee_delete_question',
290
+					array('Question', '', '', 'delete_system_questions')
291
+				),
292
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
293
+					'ee_delete_question_group',
294
+					array('Question_Group', '', '', 'delete_system_question_groups')
295
+				),
296
+				new EE_Meta_Capability_Map_Delete(
297
+					'ee_delete_payment_method',
298
+					array('Payment_Method', '', 'ee_delete_others_payment_methods', '')
299
+				),
300
+			);
301
+		}
302
+		return $default_meta_caps;
303
+	}
304
+
305
+
306
+
307
+	/**
308
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
309
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
310
+	 *
311
+	 * The actual logic is carried out by implementer classes in their definition of _map_meta_caps.
312
+	 *
313
+	 * @since 4.5.0
314
+	 * @see   wp-includes/capabilities.php
315
+	 *
316
+	 * @param array  $caps    actual users capabilities
317
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
318
+	 * @param int    $user_id The user id
319
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
320
+	 * @return array actual users capabilities
321
+	 * @throws EE_Error
322
+	 */
323
+	public function map_meta_caps($caps, $cap, $user_id, $args)
324
+	{
325
+		if (did_action('AHEE__EE_System__load_espresso_addons__complete')) {
326
+			//loop through our _meta_caps array
327
+			foreach ($this->_meta_caps as $meta_map) {
328
+				if (! $meta_map instanceof EE_Meta_Capability_Map) {
329
+					continue;
330
+				}
331
+				// don't load models if there is no object ID in the args
332
+				if (! empty($args[0])) {
333
+					$meta_map->ensure_is_model();
334
+				}
335
+				$caps = $meta_map->map_meta_caps($caps, $cap, $user_id, $args);
336
+			}
337
+		}
338
+		return $caps;
339
+	}
340
+
341
+
342
+
343
+	/**
344
+	 * This sets up and returns the initial capabilities map for Event Espresso
345
+	 * Note this array is filtered.
346
+	 * It is assumed that all available EE capabilities are assigned to the administrator role.
347
+	 *
348
+	 * @since 4.5.0
349
+	 *
350
+	 * @return array
351
+	 */
352
+	private function _init_caps_map()
353
+	{
354
+		return apply_filters(
355
+			'FHEE__EE_Capabilities__init_caps_map__caps',
356
+			array(
357
+				'administrator'           => array(
358
+					//basic access
359
+					'ee_read_ee',
360
+					//gateways
361
+					/**
362
+					 * note that with payment method capabilities, although we've implemented
363
+					 * capability mapping which will be used for accessing payment methods owned by
364
+					 * other users.  This is not fully implemented yet in the payment method ui.
365
+					 * Currently only the "plural" caps are in active use.
366
+					 * (Specific payment method caps are in use as well).
367
+					 **/
368
+					'ee_manage_gateways',
369
+					'ee_read_payment_methods',
370
+					'ee_read_others_payment_methods',
371
+					'ee_edit_payment_methods',
372
+					'ee_edit_others_payment_methods',
373
+					'ee_delete_payment_methods',
374
+					//events
375
+					'ee_publish_events',
376
+					'ee_read_private_events',
377
+					'ee_read_others_events',
378
+					'ee_read_events',
379
+					'ee_edit_events',
380
+					'ee_edit_published_events',
381
+					'ee_edit_others_events',
382
+					'ee_edit_private_events',
383
+					'ee_delete_published_events',
384
+					'ee_delete_private_events',
385
+					'ee_delete_events',
386
+					'ee_delete_others_events',
387
+					//event categories
388
+					'ee_manage_event_categories',
389
+					'ee_edit_event_category',
390
+					'ee_delete_event_category',
391
+					'ee_assign_event_category',
392
+					//venues
393
+					'ee_publish_venues',
394
+					'ee_read_venues',
395
+					'ee_read_others_venues',
396
+					'ee_read_private_venues',
397
+					'ee_edit_venues',
398
+					'ee_edit_others_venues',
399
+					'ee_edit_published_venues',
400
+					'ee_edit_private_venues',
401
+					'ee_delete_venues',
402
+					'ee_delete_others_venues',
403
+					'ee_delete_private_venues',
404
+					'ee_delete_published_venues',
405
+					//venue categories
406
+					'ee_manage_venue_categories',
407
+					'ee_edit_venue_category',
408
+					'ee_delete_venue_category',
409
+					'ee_assign_venue_category',
410
+					//contacts
411
+					'ee_read_contacts',
412
+					'ee_edit_contacts',
413
+					'ee_delete_contacts',
414
+					//registrations
415
+					'ee_read_registrations',
416
+					'ee_read_others_registrations',
417
+					'ee_edit_registrations',
418
+					'ee_edit_others_registrations',
419
+					'ee_delete_registrations',
420
+					//checkins
421
+					'ee_read_others_checkins',
422
+					'ee_read_checkins',
423
+					'ee_edit_checkins',
424
+					'ee_edit_others_checkins',
425
+					'ee_delete_checkins',
426
+					'ee_delete_others_checkins',
427
+					//transactions && payments
428
+					'ee_read_transaction',
429
+					'ee_read_transactions',
430
+					'ee_edit_payments',
431
+					'ee_delete_payments',
432
+					//messages
433
+					'ee_read_messages',
434
+					'ee_read_others_messages',
435
+					'ee_read_global_messages',
436
+					'ee_edit_global_messages',
437
+					'ee_edit_messages',
438
+					'ee_edit_others_messages',
439
+					'ee_delete_messages',
440
+					'ee_delete_others_messages',
441
+					'ee_delete_global_messages',
442
+					'ee_send_message',
443
+					//tickets
444
+					'ee_read_default_tickets',
445
+					'ee_read_others_default_tickets',
446
+					'ee_edit_default_tickets',
447
+					'ee_edit_others_default_tickets',
448
+					'ee_delete_default_tickets',
449
+					'ee_delete_others_default_tickets',
450
+					//prices
451
+					'ee_edit_default_price',
452
+					'ee_edit_default_prices',
453
+					'ee_delete_default_price',
454
+					'ee_delete_default_prices',
455
+					'ee_edit_default_price_type',
456
+					'ee_edit_default_price_types',
457
+					'ee_delete_default_price_type',
458
+					'ee_delete_default_price_types',
459
+					'ee_read_default_prices',
460
+					'ee_read_default_price_types',
461
+					//registration form
462
+					'ee_edit_questions',
463
+					'ee_edit_system_questions',
464
+					'ee_read_questions',
465
+					'ee_delete_questions',
466
+					'ee_edit_question_groups',
467
+					'ee_read_question_groups',
468
+					'ee_edit_system_question_groups',
469
+					'ee_delete_question_groups',
470
+					//event_type taxonomy
471
+					'ee_assign_event_type',
472
+					'ee_manage_event_types',
473
+					'ee_edit_event_type',
474
+					'ee_delete_event_type',
475
+				),
476
+				'ee_events_administrator' => array(
477
+					//core wp caps
478
+					'read',
479
+					'read_private_pages',
480
+					'read_private_posts',
481
+					'edit_users',
482
+					'edit_posts',
483
+					'edit_pages',
484
+					'edit_published_posts',
485
+					'edit_published_pages',
486
+					'edit_private_pages',
487
+					'edit_private_posts',
488
+					'edit_others_posts',
489
+					'edit_others_pages',
490
+					'publish_posts',
491
+					'publish_pages',
492
+					'delete_posts',
493
+					'delete_pages',
494
+					'delete_private_pages',
495
+					'delete_private_posts',
496
+					'delete_published_pages',
497
+					'delete_published_posts',
498
+					'delete_others_posts',
499
+					'delete_others_pages',
500
+					'manage_categories',
501
+					'manage_links',
502
+					'moderate_comments',
503
+					'unfiltered_html',
504
+					'upload_files',
505
+					'export',
506
+					'import',
507
+					'list_users',
508
+					'level_1', //required if user with this role shows up in author dropdowns
509
+					//basic ee access
510
+					'ee_read_ee',
511
+					//events
512
+					'ee_publish_events',
513
+					'ee_read_private_events',
514
+					'ee_read_others_events',
515
+					'ee_read_event',
516
+					'ee_read_events',
517
+					'ee_edit_event',
518
+					'ee_edit_events',
519
+					'ee_edit_published_events',
520
+					'ee_edit_others_events',
521
+					'ee_edit_private_events',
522
+					'ee_delete_published_events',
523
+					'ee_delete_private_events',
524
+					'ee_delete_event',
525
+					'ee_delete_events',
526
+					'ee_delete_others_events',
527
+					//event categories
528
+					'ee_manage_event_categories',
529
+					'ee_edit_event_category',
530
+					'ee_delete_event_category',
531
+					'ee_assign_event_category',
532
+					//venues
533
+					'ee_publish_venues',
534
+					'ee_read_venue',
535
+					'ee_read_venues',
536
+					'ee_read_others_venues',
537
+					'ee_read_private_venues',
538
+					'ee_edit_venue',
539
+					'ee_edit_venues',
540
+					'ee_edit_others_venues',
541
+					'ee_edit_published_venues',
542
+					'ee_edit_private_venues',
543
+					'ee_delete_venue',
544
+					'ee_delete_venues',
545
+					'ee_delete_others_venues',
546
+					'ee_delete_private_venues',
547
+					'ee_delete_published_venues',
548
+					//venue categories
549
+					'ee_manage_venue_categories',
550
+					'ee_edit_venue_category',
551
+					'ee_delete_venue_category',
552
+					'ee_assign_venue_category',
553
+					//contacts
554
+					'ee_read_contacts',
555
+					'ee_edit_contacts',
556
+					'ee_delete_contacts',
557
+					//registrations
558
+					'ee_read_registrations',
559
+					'ee_read_others_registrations',
560
+					'ee_edit_registration',
561
+					'ee_edit_registrations',
562
+					'ee_edit_others_registrations',
563
+					'ee_delete_registration',
564
+					'ee_delete_registrations',
565
+					//checkins
566
+					'ee_read_others_checkins',
567
+					'ee_read_checkins',
568
+					'ee_edit_checkins',
569
+					'ee_edit_others_checkins',
570
+					'ee_delete_checkins',
571
+					'ee_delete_others_checkins',
572
+					//transactions && payments
573
+					'ee_read_transaction',
574
+					'ee_read_transactions',
575
+					'ee_edit_payments',
576
+					'ee_delete_payments',
577
+					//messages
578
+					'ee_read_messages',
579
+					'ee_read_others_messages',
580
+					'ee_read_global_messages',
581
+					'ee_edit_global_messages',
582
+					'ee_edit_messages',
583
+					'ee_edit_others_messages',
584
+					'ee_delete_messages',
585
+					'ee_delete_others_messages',
586
+					'ee_delete_global_messages',
587
+					'ee_send_message',
588
+					//tickets
589
+					'ee_read_default_tickets',
590
+					'ee_read_others_default_tickets',
591
+					'ee_edit_default_tickets',
592
+					'ee_edit_others_default_tickets',
593
+					'ee_delete_default_tickets',
594
+					'ee_delete_others_default_tickets',
595
+					//prices
596
+					'ee_edit_default_price',
597
+					'ee_edit_default_prices',
598
+					'ee_delete_default_price',
599
+					'ee_delete_default_prices',
600
+					'ee_edit_default_price_type',
601
+					'ee_edit_default_price_types',
602
+					'ee_delete_default_price_type',
603
+					'ee_delete_default_price_types',
604
+					'ee_read_default_prices',
605
+					'ee_read_default_price_types',
606
+					//registration form
607
+					'ee_edit_questions',
608
+					'ee_edit_system_questions',
609
+					'ee_read_questions',
610
+					'ee_delete_questions',
611
+					'ee_edit_question_groups',
612
+					'ee_read_question_groups',
613
+					'ee_edit_system_question_groups',
614
+					'ee_delete_question_groups',
615
+					//event_type taxonomy
616
+					'ee_assign_event_type',
617
+					'ee_manage_event_types',
618
+					'ee_edit_event_type',
619
+					'ee_delete_event_type',
620
+				)
621
+			)
622
+		);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @return bool
629
+	 * @throws EE_Error
630
+	 */
631
+	private function setupCapabilitiesMap()
632
+	{
633
+		// if the initialization process hasn't even started, then we need to call init_caps()
634
+		if($this->initialized === null) {
635
+			return $this->init_caps();
636
+		}
637
+		// unless resetting, get caps from db if we haven't already
638
+		$this->capabilities_map = $this->reset || ! empty($this->capabilities_map)
639
+			? $this->capabilities_map
640
+			: get_option(self::option_name, array());
641
+		return true;
642
+	}
643
+
644
+
645
+
646
+	/**
647
+	 * @param bool $update
648
+	 * @return bool
649
+	 */
650
+	private function updateCapabilitiesMap($update = true)
651
+	{
652
+		return $update ? update_option(self::option_name, $this->capabilities_map) : false;
653
+	}
654
+
655
+
656
+
657
+	/**
658
+	 * Adds capabilities to roles.
659
+	 *
660
+	 * @since 4.9.42
661
+	 * @param array $capabilities_to_add array of capabilities to add, indexed by roles.
662
+	 *                                   Note that this should ONLY be called on activation hook
663
+	 *                                   otherwise the caps will be added on every request.
664
+	 * @return bool
665
+	 * @throws \EE_Error
666
+	 */
667
+	public function addCaps(array $capabilities_to_add)
668
+	{
669
+		// don't do anything if the capabilities map can not be initialized
670
+		if (! $this->setupCapabilitiesMap()) {
671
+			return false;
672
+		}
673
+		// and filter the array so others can get in on the fun during resets
674
+		$capabilities_to_add = apply_filters(
675
+			'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
676
+			$capabilities_to_add,
677
+			$this->reset,
678
+			$this->capabilities_map
679
+		);
680
+		$update_capabilities_map = false;
681
+		// if not reset, see what caps are new for each role. if they're new, add them.
682
+		foreach ($capabilities_to_add as $role => $caps_for_role) {
683
+			if (is_array($caps_for_role)) {
684
+				foreach ($caps_for_role as $cap) {
685
+					if (
686
+						! $this->capHasBeenAddedToRole($role, $cap)
687
+						&& $this->add_cap_to_role($role, $cap, true, false)
688
+					) {
689
+						$update_capabilities_map = true;
690
+					}
691
+				}
692
+			}
693
+		}
694
+		// now let's just save the cap that has been set but only if there's been a change.
695
+		$updated = $this->updateCapabilitiesMap($update_capabilities_map);
696
+		$this->flushWpUser($updated);
697
+		do_action('AHEE__EE_Capabilities__addCaps__complete', $this->capabilities_map, $updated);
698
+		return $updated;
699
+	}
700
+
701
+
702
+
703
+	/**
704
+	 * Loops through the capabilities map and removes the role caps specified by the incoming array
705
+	 *
706
+	 * @param array $caps_map map of capabilities to be removed (indexed by roles)
707
+	 * @return bool
708
+	 * @throws \EE_Error
709
+	 */
710
+	public function removeCaps($caps_map)
711
+	{
712
+		// don't do anything if the capabilities map can not be initialized
713
+		if (! $this->setupCapabilitiesMap()) {
714
+			return false;
715
+		}
716
+		$update_capabilities_map = false;
717
+		foreach ($caps_map as $role => $caps_for_role) {
718
+			if (is_array($caps_for_role)) {
719
+				foreach ($caps_for_role as $cap) {
720
+					if ($this->capHasBeenAddedToRole($role, $cap)
721
+						&& $this->remove_cap_from_role($role, $cap, false)
722
+					) {
723
+						$update_capabilities_map = true;
724
+					}
725
+				}
726
+			}
727
+		}
728
+		// maybe resave the caps
729
+		$updated = $this->updateCapabilitiesMap($update_capabilities_map);
730
+		$this->flushWpUser($updated);
731
+		return $updated;
732
+	}
733
+
734
+
735
+	/**
736
+	 * This ensures that the WP User object cached on the $current_user global in WP has the latest capabilities from
737
+	 * the roles on that user.
738
+	 *
739
+	 * @param bool $flush  Default is to flush the WP_User object.  If false, then this method effectively does nothing.
740
+	 */
741
+	private function flushWpUser($flush = true)
742
+	{
743
+		if ($flush) {
744
+			$user = wp_get_current_user();
745
+			if ($user instanceof WP_User) {
746
+				$user->get_role_caps();
747
+			}
748
+		}
749
+	}
750
+
751
+
752
+
753
+	/**
754
+	 * This method sets a capability on a role.  Note this should only be done on activation, or if you have something
755
+	 * specific to prevent the cap from being added on every page load (adding caps are persistent to the db). Note.
756
+	 * this is a wrapper for $wp_role->add_cap()
757
+	 *
758
+	 * @see   wp-includes/capabilities.php
759
+	 * @since 4.5.0
760
+	 * @param string|WP_Role $role  A WordPress role the capability is being added to
761
+	 * @param string         $cap   The capability being added to the role
762
+	 * @param bool           $grant Whether to grant access to this cap on this role.
763
+	 * @param bool           $update_capabilities_map
764
+	 * @return bool
765
+	 * @throws \EE_Error
766
+	 */
767
+	public function add_cap_to_role($role, $cap, $grant = true, $update_capabilities_map = true)
768
+	{
769
+		// capture incoming value for $role because we may need it to create a new WP_Role
770
+		$orig_role = $role;
771
+		$role = $role instanceof WP_Role ? $role : get_role($role);
772
+		//if the role isn't available then we create it.
773
+		if (! $role instanceof WP_Role) {
774
+			// if a plugin wants to create a specific role name then they should create the role before
775
+			// EE_Capabilities does.  Otherwise this function will create the role name from the slug:
776
+			// - removes any `ee_` namespacing from the start of the slug.
777
+			// - replaces `_` with ` ` (empty space).
778
+			// - sentence case on the resulting string.
779
+			$role_label = ucwords(str_replace(array('ee_', '_'), array('', ' '), $orig_role));
780
+			$role = add_role($orig_role, $role_label);
781
+		}
782
+		if ($role instanceof WP_Role) {
783
+			// don't do anything if the capabilities map can not be initialized
784
+			if (! $this->setupCapabilitiesMap()) {
785
+				return false;
786
+			}
787
+			if (! $this->capHasBeenAddedToRole($role->name, $cap)) {
788
+				$role->add_cap($cap, $grant);
789
+				$this->capabilities_map[ $role->name ][] = $cap;
790
+				$this->updateCapabilitiesMap($update_capabilities_map);
791
+				return true;
792
+			}
793
+		}
794
+		return false;
795
+	}
796
+
797
+
798
+
799
+	/**
800
+	 * Functions similarly to add_cap_to_role except removes cap from given role.
801
+	 * Wrapper for $wp_role->remove_cap()
802
+	 *
803
+	 * @see   wp-includes/capabilities.php
804
+	 * @since 4.5.0
805
+	 * @param string|WP_Role $role A WordPress role the capability is being removed from.
806
+	 * @param string         $cap  The capability being removed
807
+	 * @param bool           $update_capabilities_map
808
+	 * @return bool
809
+	 * @throws \EE_Error
810
+	 */
811
+	public function remove_cap_from_role($role, $cap, $update_capabilities_map = true)
812
+	{
813
+		// don't do anything if the capabilities map can not be initialized
814
+		if (! $this->setupCapabilitiesMap()) {
815
+			return false;
816
+		}
817
+
818
+		$role = $role instanceof WP_Role ? $role : get_role($role);
819
+		if ($role instanceof WP_Role && $index = $this->capHasBeenAddedToRole($role->name, $cap, true)) {
820
+			$role->remove_cap($cap);
821
+			unset($this->capabilities_map[ $role->name ][ $index ]);
822
+			$this->updateCapabilitiesMap($update_capabilities_map);
823
+			return true;
824
+		}
825
+		return false;
826
+	}
827
+
828
+
829
+
830
+	/**
831
+	 * @param string $role_name
832
+	 * @param string $cap
833
+	 * @param bool   $get_index
834
+	 * @return bool|mixed
835
+	 */
836
+	private function capHasBeenAddedToRole($role_name='', $cap='', $get_index = false)
837
+	{
838
+		if (
839
+			isset($this->capabilities_map[$role_name])
840
+			&& ($index = array_search($cap, $this->capabilities_map[$role_name], true)) !== false
841
+		) {
842
+			return $get_index ? $index : true;
843
+		}
844
+		return false;
845
+	}
846
+
847
+
848
+
849
+	/**
850
+	 * Wrapper for the native WP current_user_can() method.
851
+	 * This is provided as a handy method for a couple things:
852
+	 * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
853
+	 * write those filters wherever current_user_can is called).
854
+	 * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
855
+	 *
856
+	 * @since 4.5.0
857
+	 *
858
+	 * @param string $cap     The cap being checked.
859
+	 * @param string $context The context where the current_user_can is being called from.
860
+	 * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
861
+	 *                        filters.
862
+	 *
863
+	 * @return bool  Whether user can or not.
864
+	 */
865
+	public function current_user_can($cap, $context, $id = 0)
866
+	{
867
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
868
+		$filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__' . $context, $cap, $id);
869
+		$filtered_cap = apply_filters(
870
+			'FHEE__EE_Capabilities__current_user_can__cap',
871
+			$filtered_cap,
872
+			$context,
873
+			$cap,
874
+			$id
875
+		);
876
+		return ! empty($id)
877
+			? current_user_can($filtered_cap, $id)
878
+			: current_user_can($filtered_cap);
879
+	}
880
+
881
+
882
+
883
+	/**
884
+	 * This is a wrapper for the WP user_can() function and follows the same style as the other wrappers in this class.
885
+	 *
886
+	 * @param int|WP_User $user    Either the user_id or a WP_User object
887
+	 * @param string      $cap     The capability string being checked
888
+	 * @param string      $context The context where the user_can is being called from (used in filters).
889
+	 * @param int         $id      Optional. Id for item where user_can is being called from ( used in map_meta_cap()
890
+	 *                             filters)
891
+	 *
892
+	 * @return bool Whether user can or not.
893
+	 */
894
+	public function user_can($user, $cap, $context, $id = 0)
895
+	{
896
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
897
+		$filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__' . $context, $cap, $user, $id);
898
+		$filtered_cap = apply_filters(
899
+			'FHEE__EE_Capabilities__user_can__cap',
900
+			$filtered_cap,
901
+			$context,
902
+			$cap,
903
+			$user,
904
+			$id
905
+		);
906
+		return ! empty($id)
907
+			? user_can($user, $filtered_cap, $id)
908
+			: user_can($user, $filtered_cap);
909
+	}
910
+
911
+
912
+
913
+	/**
914
+	 * Wrapper for the native WP current_user_can_for_blog() method.
915
+	 * This is provided as a handy method for a couple things:
916
+	 * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
917
+	 * write those filters wherever current_user_can is called).
918
+	 * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
919
+	 *
920
+	 * @since 4.5.0
921
+	 *
922
+	 * @param int    $blog_id The blog id that is being checked for.
923
+	 * @param string $cap     The cap being checked.
924
+	 * @param string $context The context where the current_user_can is being called from.
925
+	 * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
926
+	 *                        filters.
927
+	 *
928
+	 * @return bool  Whether user can or not.
929
+	 */
930
+	public function current_user_can_for_blog($blog_id, $cap, $context, $id = 0)
931
+	{
932
+		$user_can = ! empty($id)
933
+			? current_user_can_for_blog($blog_id, $cap, $id)
934
+			: current_user_can($blog_id, $cap);
935
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
936
+		$user_can = apply_filters(
937
+			'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__' . $context,
938
+			$user_can,
939
+			$blog_id,
940
+			$cap,
941
+			$id
942
+		);
943
+		$user_can = apply_filters(
944
+			'FHEE__EE_Capabilities__current_user_can_for_blog__user_can',
945
+			$user_can,
946
+			$context,
947
+			$blog_id,
948
+			$cap,
949
+			$id
950
+		);
951
+		return $user_can;
952
+	}
953
+
954
+
955
+
956
+	/**
957
+	 * This helper method just returns an array of registered EE capabilities.
958
+	 *
959
+	 * @since 4.5.0
960
+	 * @param string $role If empty then the entire role/capability map is returned.
961
+	 *                     Otherwise just the capabilities for the given role are returned.
962
+	 * @return array
963
+	 * @throws EE_Error
964
+	 */
965
+	public function get_ee_capabilities($role = 'administrator')
966
+	{
967
+		if (! $this->initialized) {
968
+			$this->init_caps();
969
+		}
970
+		if (empty($role)) {
971
+			return $this->capabilities_map;
972
+		}
973
+		return isset($this->capabilities_map[ $role ])
974
+			? $this->capabilities_map[ $role ]
975
+			: array();
976
+	}
977
+
978
+
979
+
980
+	/**
981
+	 * @deprecated 4.9.42
982
+	 * @param bool  $reset      If you need to reset Event Espresso's capabilities,
983
+	 *                          then please use the init_caps() method with the "$reset" parameter set to "true"
984
+	 * @param array $caps_map   Optional.
985
+	 *                          Can be used to send a custom map of roles and capabilities for setting them up.
986
+	 *                          Note that this should ONLY be called on activation hook or some other one-time
987
+	 *                          task otherwise the caps will be added on every request.
988
+	 * @return void
989
+	 * @throws EE_Error
990
+	 */
991
+	public function init_role_caps($reset = false, $caps_map = array())
992
+	{
993
+		// If this method is called directly and reset is set as 'true',
994
+		// then display a doing it wrong notice, because we want resets to go through init_caps()
995
+		// to guarantee that everything is set up correctly.
996
+		// This prevents the capabilities map getting reset incorrectly by direct calls to this method.
997
+		if ($reset) {
998
+			EE_Error::doing_it_wrong(
999
+				__METHOD__,
1000
+				sprintf(
1001
+					esc_html__(
1002
+						'The "%1$s" parameter for the "%2$s" method is deprecated. If you need to reset Event Espresso\'s capabilities, then please use the "%3$s" method with the "%1$s" parameter set to "%4$s".',
1003
+						'event_espresso'
1004
+					),
1005
+					'$reset',
1006
+					__METHOD__ . '()',
1007
+					'EE_Capabilities::init_caps()',
1008
+					'true'
1009
+				),
1010
+				'4.9.42',
1011
+				'5.0.0'
1012
+			);
1013
+		}
1014
+		$this->addCaps($caps_map);
1015
+	}
1016 1016
 
1017 1017
 
1018 1018
 
@@ -1033,142 +1033,142 @@  discard block
 block discarded – undo
1033 1033
 abstract class EE_Meta_Capability_Map
1034 1034
 {
1035 1035
 
1036
-    public $meta_cap;
1037
-
1038
-    /**
1039
-     * @var EEM_Base
1040
-     */
1041
-    protected $_model;
1042
-
1043
-    protected $_model_name;
1044
-
1045
-    public $published_cap = '';
1046
-
1047
-    public $others_cap = '';
1048
-
1049
-    public $private_cap = '';
1050
-
1051
-
1052
-    /**
1053
-     * constructor.
1054
-     * Receives the setup arguments for the map.
1055
-     *
1056
-     * @since                        4.5.0
1057
-     *
1058
-     * @param string $meta_cap   What meta capability is this mapping.
1059
-     * @param array  $map_values array {
1060
-     *                           //array of values that MUST match a count of 4.  It's okay to send an empty string for
1061
-     *                           capabilities that don't get mapped to.
1062
-     *
1063
-     * @type         $map_values [0] string A string representing the model name. Required.  String's
1064
-     *                               should always be used when Menu Maps are registered via the
1065
-     *                               plugin API as models are not allowed to be instantiated when
1066
-     *                               in maintenance mode 2 (migrations).
1067
-     * @type         $map_values [1] string represents the capability used for published. Optional.
1068
-     * @type         $map_values [2] string represents the capability used for "others". Optional.
1069
-     * @type         $map_values [3] string represents the capability used for private. Optional.
1070
-     *                               }
1071
-     * @throws EE_Error
1072
-     */
1073
-    public function __construct($meta_cap, $map_values)
1074
-    {
1075
-        $this->meta_cap = $meta_cap;
1076
-        //verify there are four args in the $map_values array;
1077
-        if (count($map_values) !== 4) {
1078
-            throw new EE_Error(
1079
-                sprintf(
1080
-                    __(
1081
-                        'Incoming $map_values array should have a count of four values in it.  This is what was given: %s',
1082
-                        'event_espresso'
1083
-                    ),
1084
-                    '<br>' . print_r($map_values, true)
1085
-                )
1086
-            );
1087
-        }
1088
-        //set properties
1089
-        $this->_model = null;
1090
-        $this->_model_name = $map_values[0];
1091
-        $this->published_cap = (string)$map_values[1];
1092
-        $this->others_cap = (string)$map_values[2];
1093
-        $this->private_cap = (string)$map_values[3];
1094
-    }
1095
-
1096
-    /**
1097
-     * Makes it so this object stops filtering caps
1098
-     */
1099
-    public function remove_filters()
1100
-    {
1101
-        remove_filter('map_meta_cap', array($this, 'map_meta_caps'), 10);
1102
-    }
1103
-
1104
-
1105
-    /**
1106
-     * This method ensures that the $model property is converted from the model name string to a proper EEM_Base class
1107
-     *
1108
-     * @since 4.5.0
1109
-     * @throws EE_Error
1110
-     *
1111
-     * @return void
1112
-     */
1113
-    public function ensure_is_model()
1114
-    {
1115
-        //is it already instantiated?
1116
-        if ($this->_model instanceof EEM_Base) {
1117
-            return;
1118
-        }
1119
-        //ensure model name is string
1120
-        $this->_model_name = (string)$this->_model_name;
1121
-        //error proof if the name has EEM in it
1122
-        $this->_model_name = str_replace('EEM', '', $this->_model_name);
1123
-        $this->_model = EE_Registry::instance()->load_model($this->_model_name);
1124
-        if (! $this->_model instanceof EEM_Base) {
1125
-            throw new EE_Error(
1126
-                sprintf(
1127
-                    __(
1128
-                        'This string passed in to %s to represent a EEM_Base model class was not able to be used to instantiate the class.   Please ensure that the string is a match for the EEM_Base model name (not including the EEM_ part). This was given: %s',
1129
-                        'event_espresso'
1130
-                    ),
1131
-                    get_class($this),
1132
-                    $this->_model
1133
-                )
1134
-            );
1135
-        }
1136
-    }
1137
-
1138
-
1139
-    /**
1140
-     *
1141
-     * @see   EE_Meta_Capability_Map::_map_meta_caps() for docs on params.
1142
-     * @since 4.6.x
1143
-     *
1144
-     * @param $caps
1145
-     * @param $cap
1146
-     * @param $user_id
1147
-     * @param $args
1148
-     *
1149
-     * @return array
1150
-     */
1151
-    public function map_meta_caps($caps, $cap, $user_id, $args)
1152
-    {
1153
-        return $this->_map_meta_caps($caps, $cap, $user_id, $args);
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1159
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1160
-     *
1161
-     * @since 4.5.0
1162
-     * @see   wp-includes/capabilities.php
1163
-     *
1164
-     * @param array  $caps    actual users capabilities
1165
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1166
-     * @param int    $user_id The user id
1167
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1168
-     *
1169
-     * @return array   actual users capabilities
1170
-     */
1171
-    abstract protected function _map_meta_caps($caps, $cap, $user_id, $args);
1036
+	public $meta_cap;
1037
+
1038
+	/**
1039
+	 * @var EEM_Base
1040
+	 */
1041
+	protected $_model;
1042
+
1043
+	protected $_model_name;
1044
+
1045
+	public $published_cap = '';
1046
+
1047
+	public $others_cap = '';
1048
+
1049
+	public $private_cap = '';
1050
+
1051
+
1052
+	/**
1053
+	 * constructor.
1054
+	 * Receives the setup arguments for the map.
1055
+	 *
1056
+	 * @since                        4.5.0
1057
+	 *
1058
+	 * @param string $meta_cap   What meta capability is this mapping.
1059
+	 * @param array  $map_values array {
1060
+	 *                           //array of values that MUST match a count of 4.  It's okay to send an empty string for
1061
+	 *                           capabilities that don't get mapped to.
1062
+	 *
1063
+	 * @type         $map_values [0] string A string representing the model name. Required.  String's
1064
+	 *                               should always be used when Menu Maps are registered via the
1065
+	 *                               plugin API as models are not allowed to be instantiated when
1066
+	 *                               in maintenance mode 2 (migrations).
1067
+	 * @type         $map_values [1] string represents the capability used for published. Optional.
1068
+	 * @type         $map_values [2] string represents the capability used for "others". Optional.
1069
+	 * @type         $map_values [3] string represents the capability used for private. Optional.
1070
+	 *                               }
1071
+	 * @throws EE_Error
1072
+	 */
1073
+	public function __construct($meta_cap, $map_values)
1074
+	{
1075
+		$this->meta_cap = $meta_cap;
1076
+		//verify there are four args in the $map_values array;
1077
+		if (count($map_values) !== 4) {
1078
+			throw new EE_Error(
1079
+				sprintf(
1080
+					__(
1081
+						'Incoming $map_values array should have a count of four values in it.  This is what was given: %s',
1082
+						'event_espresso'
1083
+					),
1084
+					'<br>' . print_r($map_values, true)
1085
+				)
1086
+			);
1087
+		}
1088
+		//set properties
1089
+		$this->_model = null;
1090
+		$this->_model_name = $map_values[0];
1091
+		$this->published_cap = (string)$map_values[1];
1092
+		$this->others_cap = (string)$map_values[2];
1093
+		$this->private_cap = (string)$map_values[3];
1094
+	}
1095
+
1096
+	/**
1097
+	 * Makes it so this object stops filtering caps
1098
+	 */
1099
+	public function remove_filters()
1100
+	{
1101
+		remove_filter('map_meta_cap', array($this, 'map_meta_caps'), 10);
1102
+	}
1103
+
1104
+
1105
+	/**
1106
+	 * This method ensures that the $model property is converted from the model name string to a proper EEM_Base class
1107
+	 *
1108
+	 * @since 4.5.0
1109
+	 * @throws EE_Error
1110
+	 *
1111
+	 * @return void
1112
+	 */
1113
+	public function ensure_is_model()
1114
+	{
1115
+		//is it already instantiated?
1116
+		if ($this->_model instanceof EEM_Base) {
1117
+			return;
1118
+		}
1119
+		//ensure model name is string
1120
+		$this->_model_name = (string)$this->_model_name;
1121
+		//error proof if the name has EEM in it
1122
+		$this->_model_name = str_replace('EEM', '', $this->_model_name);
1123
+		$this->_model = EE_Registry::instance()->load_model($this->_model_name);
1124
+		if (! $this->_model instanceof EEM_Base) {
1125
+			throw new EE_Error(
1126
+				sprintf(
1127
+					__(
1128
+						'This string passed in to %s to represent a EEM_Base model class was not able to be used to instantiate the class.   Please ensure that the string is a match for the EEM_Base model name (not including the EEM_ part). This was given: %s',
1129
+						'event_espresso'
1130
+					),
1131
+					get_class($this),
1132
+					$this->_model
1133
+				)
1134
+			);
1135
+		}
1136
+	}
1137
+
1138
+
1139
+	/**
1140
+	 *
1141
+	 * @see   EE_Meta_Capability_Map::_map_meta_caps() for docs on params.
1142
+	 * @since 4.6.x
1143
+	 *
1144
+	 * @param $caps
1145
+	 * @param $cap
1146
+	 * @param $user_id
1147
+	 * @param $args
1148
+	 *
1149
+	 * @return array
1150
+	 */
1151
+	public function map_meta_caps($caps, $cap, $user_id, $args)
1152
+	{
1153
+		return $this->_map_meta_caps($caps, $cap, $user_id, $args);
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1159
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1160
+	 *
1161
+	 * @since 4.5.0
1162
+	 * @see   wp-includes/capabilities.php
1163
+	 *
1164
+	 * @param array  $caps    actual users capabilities
1165
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1166
+	 * @param int    $user_id The user id
1167
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1168
+	 *
1169
+	 * @return array   actual users capabilities
1170
+	 */
1171
+	abstract protected function _map_meta_caps($caps, $cap, $user_id, $args);
1172 1172
 }
1173 1173
 
1174 1174
 
@@ -1184,81 +1184,81 @@  discard block
 block discarded – undo
1184 1184
 class EE_Meta_Capability_Map_Edit extends EE_Meta_Capability_Map
1185 1185
 {
1186 1186
 
1187
-    /**
1188
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1189
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1190
-     *
1191
-     * @since 4.5.0
1192
-     * @see   wp-includes/capabilities.php
1193
-     *
1194
-     * @param array  $caps    actual users capabilities
1195
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1196
-     * @param int    $user_id The user id
1197
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1198
-     *
1199
-     * @return array   actual users capabilities
1200
-     */
1201
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1202
-    {
1203
-        //only process if we're checking our mapped_cap
1204
-        if ($cap !== $this->meta_cap) {
1205
-            return $caps;
1206
-        }
1207
-
1208
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1209
-        if (($key = array_search($cap, $caps)) !== false) {
1210
-            unset($caps[$key]);
1211
-        }
1212
-
1213
-        //cast $user_id to int for later explicit comparisons
1214
-        $user_id = (int) $user_id;
1215
-
1216
-        /** @var EE_Base_Class $obj */
1217
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1218
-        //if no obj then let's just do cap
1219
-        if (! $obj instanceof EE_Base_Class) {
1220
-            $caps[] = 'do_not_allow';
1221
-            return $caps;
1222
-        }
1223
-        $caps[] = $cap . 's';
1224
-        if ($obj instanceof EE_CPT_Base) {
1225
-            //if the item author is set and the user is the author...
1226
-            if ($obj->wp_user() && $user_id === $obj->wp_user()) {
1227
-                //if obj is published...
1228
-                if ($obj->status() === 'publish') {
1229
-                    $caps[] = $this->published_cap;
1230
-                }
1231
-            } else {
1232
-                //the user is trying to edit someone else's obj
1233
-                if (! empty($this->others_cap)) {
1234
-                    $caps[] = $this->others_cap;
1235
-                }
1236
-                if (! empty($this->published_cap) && $obj->status() === 'publish') {
1237
-                    $caps[] = $this->published_cap;
1238
-                } elseif (! empty($this->private_cap) && $obj->status() === 'private') {
1239
-                    $caps[] = $this->private_cap;
1240
-                }
1241
-            }
1242
-        } else {
1243
-            //not a cpt object so handled differently
1244
-            $has_cap = false;
1245
-            try {
1246
-                $has_cap = method_exists($obj, 'wp_user')
1247
-                           && $obj->wp_user()
1248
-                           && $obj->wp_user() === $user_id;
1249
-            } catch (Exception $e) {
1250
-                if (WP_DEBUG) {
1251
-                    EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1252
-                }
1253
-            }
1254
-            if (! $has_cap) {
1255
-                if (! empty($this->others_cap)) {
1256
-                    $caps[] = $this->others_cap;
1257
-                }
1258
-            }
1259
-        }
1260
-        return $caps;
1261
-    }
1187
+	/**
1188
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1189
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1190
+	 *
1191
+	 * @since 4.5.0
1192
+	 * @see   wp-includes/capabilities.php
1193
+	 *
1194
+	 * @param array  $caps    actual users capabilities
1195
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1196
+	 * @param int    $user_id The user id
1197
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1198
+	 *
1199
+	 * @return array   actual users capabilities
1200
+	 */
1201
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1202
+	{
1203
+		//only process if we're checking our mapped_cap
1204
+		if ($cap !== $this->meta_cap) {
1205
+			return $caps;
1206
+		}
1207
+
1208
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1209
+		if (($key = array_search($cap, $caps)) !== false) {
1210
+			unset($caps[$key]);
1211
+		}
1212
+
1213
+		//cast $user_id to int for later explicit comparisons
1214
+		$user_id = (int) $user_id;
1215
+
1216
+		/** @var EE_Base_Class $obj */
1217
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1218
+		//if no obj then let's just do cap
1219
+		if (! $obj instanceof EE_Base_Class) {
1220
+			$caps[] = 'do_not_allow';
1221
+			return $caps;
1222
+		}
1223
+		$caps[] = $cap . 's';
1224
+		if ($obj instanceof EE_CPT_Base) {
1225
+			//if the item author is set and the user is the author...
1226
+			if ($obj->wp_user() && $user_id === $obj->wp_user()) {
1227
+				//if obj is published...
1228
+				if ($obj->status() === 'publish') {
1229
+					$caps[] = $this->published_cap;
1230
+				}
1231
+			} else {
1232
+				//the user is trying to edit someone else's obj
1233
+				if (! empty($this->others_cap)) {
1234
+					$caps[] = $this->others_cap;
1235
+				}
1236
+				if (! empty($this->published_cap) && $obj->status() === 'publish') {
1237
+					$caps[] = $this->published_cap;
1238
+				} elseif (! empty($this->private_cap) && $obj->status() === 'private') {
1239
+					$caps[] = $this->private_cap;
1240
+				}
1241
+			}
1242
+		} else {
1243
+			//not a cpt object so handled differently
1244
+			$has_cap = false;
1245
+			try {
1246
+				$has_cap = method_exists($obj, 'wp_user')
1247
+						   && $obj->wp_user()
1248
+						   && $obj->wp_user() === $user_id;
1249
+			} catch (Exception $e) {
1250
+				if (WP_DEBUG) {
1251
+					EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1252
+				}
1253
+			}
1254
+			if (! $has_cap) {
1255
+				if (! empty($this->others_cap)) {
1256
+					$caps[] = $this->others_cap;
1257
+				}
1258
+			}
1259
+		}
1260
+		return $caps;
1261
+	}
1262 1262
 }
1263 1263
 
1264 1264
 
@@ -1275,24 +1275,24 @@  discard block
 block discarded – undo
1275 1275
 class EE_Meta_Capability_Map_Delete extends EE_Meta_Capability_Map_Edit
1276 1276
 {
1277 1277
 
1278
-    /**
1279
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1280
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1281
-     *
1282
-     * @since 4.5.0
1283
-     * @see   wp-includes/capabilities.php
1284
-     *
1285
-     * @param array  $caps    actual users capabilities
1286
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1287
-     * @param int    $user_id The user id
1288
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1289
-     *
1290
-     * @return array   actual users capabilities
1291
-     */
1292
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1293
-    {
1294
-        return parent::_map_meta_caps($caps, $cap, $user_id, $args);
1295
-    }
1278
+	/**
1279
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1280
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1281
+	 *
1282
+	 * @since 4.5.0
1283
+	 * @see   wp-includes/capabilities.php
1284
+	 *
1285
+	 * @param array  $caps    actual users capabilities
1286
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1287
+	 * @param int    $user_id The user id
1288
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1289
+	 *
1290
+	 * @return array   actual users capabilities
1291
+	 */
1292
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1293
+	{
1294
+		return parent::_map_meta_caps($caps, $cap, $user_id, $args);
1295
+	}
1296 1296
 }
1297 1297
 
1298 1298
 
@@ -1308,85 +1308,85 @@  discard block
 block discarded – undo
1308 1308
 class EE_Meta_Capability_Map_Read extends EE_Meta_Capability_Map
1309 1309
 {
1310 1310
 
1311
-    /**
1312
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1313
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1314
-     *
1315
-     * @since 4.5.0
1316
-     * @see   wp-includes/capabilities.php
1317
-     *
1318
-     * @param array  $caps    actual users capabilities
1319
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1320
-     * @param int    $user_id The user id
1321
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1322
-     *
1323
-     * @return array   actual users capabilities
1324
-     */
1325
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1326
-    {
1327
-        //only process if we're checking our mapped cap;
1328
-        if ($cap !== $this->meta_cap) {
1329
-            return $caps;
1330
-        }
1331
-
1332
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1333
-        if (($key = array_search($cap, $caps)) !== false) {
1334
-            unset($caps[$key]);
1335
-        }
1336
-
1337
-        //cast $user_id to int for later explicit comparisons
1338
-        $user_id = (int) $user_id;
1339
-
1340
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1341
-        //if no obj then let's just do cap
1342
-        if (! $obj instanceof EE_Base_Class) {
1343
-            $caps[] = 'do_not_allow';
1344
-            return $caps;
1345
-        }
1346
-
1347
-        $caps[] = $cap . 's';
1348
-        if ($obj instanceof EE_CPT_Base) {
1349
-            $status_obj = get_post_status_object($obj->status());
1350
-            if ($status_obj->public) {
1351
-                return $caps;
1352
-            }
1353
-            //if the item author is set and the user is not the author...
1354
-            if ($obj->wp_user() && $obj->wp_user() !== $user_id) {
1355
-                if (! empty($this->others_cap)) {
1356
-                    $caps[] = $this->others_cap;
1357
-                }
1358
-            }
1359
-            //yes this means that if users created the private post, they are able to see it regardless of private cap.
1360
-            if ($status_obj->private
1361
-                && ! empty($this->private_cap)
1362
-                && $obj->wp_user() !== $user_id
1363
-            ) {
1364
-                //the user is trying to view a private object for an object they don't own.
1365
-                $caps[] = $this->private_cap;
1366
-            }
1367
-        } else {
1368
-            //not a cpt object so handled differently
1369
-            $has_cap = false;
1370
-            try {
1371
-                $has_cap = method_exists($obj, 'wp_user')
1372
-                           && $obj->wp_user()
1373
-                           && $obj->wp_user() === $user_id;
1374
-            } catch (Exception $e) {
1375
-                if (WP_DEBUG) {
1376
-                    EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1377
-                }
1378
-            }
1379
-            if (! $has_cap) {
1380
-                if (! empty($this->private_cap)) {
1381
-                    $caps[] = $this->private_cap;
1382
-                }
1383
-                if (! empty($this->others_cap)) {
1384
-                    $caps[] = $this->others_cap;
1385
-                }
1386
-            }
1387
-        }
1388
-        return $caps;
1389
-    }
1311
+	/**
1312
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1313
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1314
+	 *
1315
+	 * @since 4.5.0
1316
+	 * @see   wp-includes/capabilities.php
1317
+	 *
1318
+	 * @param array  $caps    actual users capabilities
1319
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1320
+	 * @param int    $user_id The user id
1321
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1322
+	 *
1323
+	 * @return array   actual users capabilities
1324
+	 */
1325
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1326
+	{
1327
+		//only process if we're checking our mapped cap;
1328
+		if ($cap !== $this->meta_cap) {
1329
+			return $caps;
1330
+		}
1331
+
1332
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1333
+		if (($key = array_search($cap, $caps)) !== false) {
1334
+			unset($caps[$key]);
1335
+		}
1336
+
1337
+		//cast $user_id to int for later explicit comparisons
1338
+		$user_id = (int) $user_id;
1339
+
1340
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1341
+		//if no obj then let's just do cap
1342
+		if (! $obj instanceof EE_Base_Class) {
1343
+			$caps[] = 'do_not_allow';
1344
+			return $caps;
1345
+		}
1346
+
1347
+		$caps[] = $cap . 's';
1348
+		if ($obj instanceof EE_CPT_Base) {
1349
+			$status_obj = get_post_status_object($obj->status());
1350
+			if ($status_obj->public) {
1351
+				return $caps;
1352
+			}
1353
+			//if the item author is set and the user is not the author...
1354
+			if ($obj->wp_user() && $obj->wp_user() !== $user_id) {
1355
+				if (! empty($this->others_cap)) {
1356
+					$caps[] = $this->others_cap;
1357
+				}
1358
+			}
1359
+			//yes this means that if users created the private post, they are able to see it regardless of private cap.
1360
+			if ($status_obj->private
1361
+				&& ! empty($this->private_cap)
1362
+				&& $obj->wp_user() !== $user_id
1363
+			) {
1364
+				//the user is trying to view a private object for an object they don't own.
1365
+				$caps[] = $this->private_cap;
1366
+			}
1367
+		} else {
1368
+			//not a cpt object so handled differently
1369
+			$has_cap = false;
1370
+			try {
1371
+				$has_cap = method_exists($obj, 'wp_user')
1372
+						   && $obj->wp_user()
1373
+						   && $obj->wp_user() === $user_id;
1374
+			} catch (Exception $e) {
1375
+				if (WP_DEBUG) {
1376
+					EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1377
+				}
1378
+			}
1379
+			if (! $has_cap) {
1380
+				if (! empty($this->private_cap)) {
1381
+					$caps[] = $this->private_cap;
1382
+				}
1383
+				if (! empty($this->others_cap)) {
1384
+					$caps[] = $this->others_cap;
1385
+				}
1386
+			}
1387
+		}
1388
+		return $caps;
1389
+	}
1390 1390
 }
1391 1391
 
1392 1392
 
@@ -1403,56 +1403,56 @@  discard block
 block discarded – undo
1403 1403
 class EE_Meta_Capability_Map_Messages_Cap extends EE_Meta_Capability_Map
1404 1404
 {
1405 1405
 
1406
-    /**
1407
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1408
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1409
-     *
1410
-     * @since 4.5.0
1411
-     * @see   wp-includes/capabilities.php
1412
-     *
1413
-     * @param array  $caps    actual users capabilities
1414
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1415
-     * @param int    $user_id The user id
1416
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1417
-     *
1418
-     * @return array   actual users capabilities
1419
-     */
1420
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1421
-    {
1422
-        //only process if we're checking our mapped_cap
1423
-        if ($cap !== $this->meta_cap) {
1424
-            return $caps;
1425
-        }
1426
-
1427
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1428
-        if (($key = array_search($cap, $caps)) !== false) {
1429
-            unset($caps[$key]);
1430
-        }
1431
-
1432
-        //cast $user_id to int for later explicit comparisons
1433
-        $user_id = (int) $user_id;
1434
-
1435
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1436
-        //if no obj then let's just do cap
1437
-        if (! $obj instanceof EE_Message_Template_Group) {
1438
-            $caps[] = 'do_not_allow';
1439
-            return $caps;
1440
-        }
1441
-        $caps[] = $cap . 's';
1442
-        $is_global = $obj->is_global();
1443
-        if ($obj->wp_user() && $obj->wp_user() === $user_id) {
1444
-            if ($is_global) {
1445
-                $caps[] = $this->private_cap;
1446
-            }
1447
-        } else {
1448
-            if ($is_global) {
1449
-                $caps[] = $this->private_cap;
1450
-            } else {
1451
-                $caps[] = $this->others_cap;
1452
-            }
1453
-        }
1454
-        return $caps;
1455
-    }
1406
+	/**
1407
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1408
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1409
+	 *
1410
+	 * @since 4.5.0
1411
+	 * @see   wp-includes/capabilities.php
1412
+	 *
1413
+	 * @param array  $caps    actual users capabilities
1414
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1415
+	 * @param int    $user_id The user id
1416
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1417
+	 *
1418
+	 * @return array   actual users capabilities
1419
+	 */
1420
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1421
+	{
1422
+		//only process if we're checking our mapped_cap
1423
+		if ($cap !== $this->meta_cap) {
1424
+			return $caps;
1425
+		}
1426
+
1427
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1428
+		if (($key = array_search($cap, $caps)) !== false) {
1429
+			unset($caps[$key]);
1430
+		}
1431
+
1432
+		//cast $user_id to int for later explicit comparisons
1433
+		$user_id = (int) $user_id;
1434
+
1435
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1436
+		//if no obj then let's just do cap
1437
+		if (! $obj instanceof EE_Message_Template_Group) {
1438
+			$caps[] = 'do_not_allow';
1439
+			return $caps;
1440
+		}
1441
+		$caps[] = $cap . 's';
1442
+		$is_global = $obj->is_global();
1443
+		if ($obj->wp_user() && $obj->wp_user() === $user_id) {
1444
+			if ($is_global) {
1445
+				$caps[] = $this->private_cap;
1446
+			}
1447
+		} else {
1448
+			if ($is_global) {
1449
+				$caps[] = $this->private_cap;
1450
+			} else {
1451
+				$caps[] = $this->others_cap;
1452
+			}
1453
+		}
1454
+		return $caps;
1455
+	}
1456 1456
 }
1457 1457
 
1458 1458
 
@@ -1469,40 +1469,40 @@  discard block
 block discarded – undo
1469 1469
 class EE_Meta_Capability_Map_Registration_Form_Cap extends EE_Meta_Capability_Map
1470 1470
 {
1471 1471
 
1472
-    /**
1473
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1474
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1475
-     *
1476
-     * @since 4.5.0
1477
-     * @see   wp-includes/capabilities.php
1478
-     * @param array  $caps    actual users capabilities
1479
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1480
-     * @param int    $user_id The user id
1481
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1482
-     * @return array   actual users capabilities
1483
-     */
1484
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1485
-    {
1486
-        //only process if we're checking our mapped_cap
1487
-        if ($cap !== $this->meta_cap) {
1488
-            return $caps;
1489
-        }
1490
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1491
-        if (($key = array_search($cap, $caps)) !== false) {
1492
-            unset($caps[$key]);
1493
-        }
1494
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1495
-        //if no obj then let's just do cap
1496
-        if (! $obj instanceof EE_Base_Class) {
1497
-            $caps[] = 'do_not_allow';
1498
-            return $caps;
1499
-        }
1500
-        $caps[]    = $cap . 's';
1501
-        $is_system = $obj instanceof EE_Question_Group ? $obj->system_group() : false;
1502
-        $is_system = $obj instanceof EE_Question ? $obj->is_system_question() : $is_system;
1503
-        if ($is_system) {
1504
-            $caps[] = $this->private_cap;
1505
-        }
1506
-        return $caps;
1507
-    }
1472
+	/**
1473
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1474
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1475
+	 *
1476
+	 * @since 4.5.0
1477
+	 * @see   wp-includes/capabilities.php
1478
+	 * @param array  $caps    actual users capabilities
1479
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1480
+	 * @param int    $user_id The user id
1481
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1482
+	 * @return array   actual users capabilities
1483
+	 */
1484
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1485
+	{
1486
+		//only process if we're checking our mapped_cap
1487
+		if ($cap !== $this->meta_cap) {
1488
+			return $caps;
1489
+		}
1490
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1491
+		if (($key = array_search($cap, $caps)) !== false) {
1492
+			unset($caps[$key]);
1493
+		}
1494
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1495
+		//if no obj then let's just do cap
1496
+		if (! $obj instanceof EE_Base_Class) {
1497
+			$caps[] = 'do_not_allow';
1498
+			return $caps;
1499
+		}
1500
+		$caps[]    = $cap . 's';
1501
+		$is_system = $obj instanceof EE_Question_Group ? $obj->system_group() : false;
1502
+		$is_system = $obj instanceof EE_Question ? $obj->is_system_question() : $is_system;
1503
+		if ($is_system) {
1504
+			$caps[] = $this->private_cap;
1505
+		}
1506
+		return $caps;
1507
+	}
1508 1508
 }
Please login to merge, or discard this patch.
Spacing   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
     public static function instance()
86 86
     {
87 87
         //check if instantiated, and if not do so.
88
-        if (! self::$_instance instanceof EE_Capabilities) {
88
+        if ( ! self::$_instance instanceof EE_Capabilities) {
89 89
             self::$_instance = new self();
90 90
         }
91 91
         return self::$_instance;
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
      */
118 118
     public function init_caps($reset = false)
119 119
     {
120
-        if(! EE_Maintenance_Mode::instance()->models_can_query()){
120
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
121 121
             return false;
122 122
         }
123 123
         $this->reset = filter_var($reset, FILTER_VALIDATE_BOOLEAN);
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
             $this->_get_default_meta_caps_array()
165 165
         );
166 166
         //add filter for map_meta_caps but only if models can query.
167
-        if (! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
167
+        if ( ! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
168 168
             add_filter('map_meta_cap', array($this, 'map_meta_caps'), 10, 4);
169 169
         }
170 170
     }
@@ -325,11 +325,11 @@  discard block
 block discarded – undo
325 325
         if (did_action('AHEE__EE_System__load_espresso_addons__complete')) {
326 326
             //loop through our _meta_caps array
327 327
             foreach ($this->_meta_caps as $meta_map) {
328
-                if (! $meta_map instanceof EE_Meta_Capability_Map) {
328
+                if ( ! $meta_map instanceof EE_Meta_Capability_Map) {
329 329
                     continue;
330 330
                 }
331 331
                 // don't load models if there is no object ID in the args
332
-                if (! empty($args[0])) {
332
+                if ( ! empty($args[0])) {
333 333
                     $meta_map->ensure_is_model();
334 334
                 }
335 335
                 $caps = $meta_map->map_meta_caps($caps, $cap, $user_id, $args);
@@ -631,7 +631,7 @@  discard block
 block discarded – undo
631 631
     private function setupCapabilitiesMap()
632 632
     {
633 633
         // if the initialization process hasn't even started, then we need to call init_caps()
634
-        if($this->initialized === null) {
634
+        if ($this->initialized === null) {
635 635
             return $this->init_caps();
636 636
         }
637 637
         // unless resetting, get caps from db if we haven't already
@@ -667,7 +667,7 @@  discard block
 block discarded – undo
667 667
     public function addCaps(array $capabilities_to_add)
668 668
     {
669 669
         // don't do anything if the capabilities map can not be initialized
670
-        if (! $this->setupCapabilitiesMap()) {
670
+        if ( ! $this->setupCapabilitiesMap()) {
671 671
             return false;
672 672
         }
673 673
         // and filter the array so others can get in on the fun during resets
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
     public function removeCaps($caps_map)
711 711
     {
712 712
         // don't do anything if the capabilities map can not be initialized
713
-        if (! $this->setupCapabilitiesMap()) {
713
+        if ( ! $this->setupCapabilitiesMap()) {
714 714
             return false;
715 715
         }
716 716
         $update_capabilities_map = false;
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
         $orig_role = $role;
771 771
         $role = $role instanceof WP_Role ? $role : get_role($role);
772 772
         //if the role isn't available then we create it.
773
-        if (! $role instanceof WP_Role) {
773
+        if ( ! $role instanceof WP_Role) {
774 774
             // if a plugin wants to create a specific role name then they should create the role before
775 775
             // EE_Capabilities does.  Otherwise this function will create the role name from the slug:
776 776
             // - removes any `ee_` namespacing from the start of the slug.
@@ -781,12 +781,12 @@  discard block
 block discarded – undo
781 781
         }
782 782
         if ($role instanceof WP_Role) {
783 783
             // don't do anything if the capabilities map can not be initialized
784
-            if (! $this->setupCapabilitiesMap()) {
784
+            if ( ! $this->setupCapabilitiesMap()) {
785 785
                 return false;
786 786
             }
787
-            if (! $this->capHasBeenAddedToRole($role->name, $cap)) {
787
+            if ( ! $this->capHasBeenAddedToRole($role->name, $cap)) {
788 788
                 $role->add_cap($cap, $grant);
789
-                $this->capabilities_map[ $role->name ][] = $cap;
789
+                $this->capabilities_map[$role->name][] = $cap;
790 790
                 $this->updateCapabilitiesMap($update_capabilities_map);
791 791
                 return true;
792 792
             }
@@ -811,14 +811,14 @@  discard block
 block discarded – undo
811 811
     public function remove_cap_from_role($role, $cap, $update_capabilities_map = true)
812 812
     {
813 813
         // don't do anything if the capabilities map can not be initialized
814
-        if (! $this->setupCapabilitiesMap()) {
814
+        if ( ! $this->setupCapabilitiesMap()) {
815 815
             return false;
816 816
         }
817 817
 
818 818
         $role = $role instanceof WP_Role ? $role : get_role($role);
819 819
         if ($role instanceof WP_Role && $index = $this->capHasBeenAddedToRole($role->name, $cap, true)) {
820 820
             $role->remove_cap($cap);
821
-            unset($this->capabilities_map[ $role->name ][ $index ]);
821
+            unset($this->capabilities_map[$role->name][$index]);
822 822
             $this->updateCapabilitiesMap($update_capabilities_map);
823 823
             return true;
824 824
         }
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
      * @param bool   $get_index
834 834
      * @return bool|mixed
835 835
      */
836
-    private function capHasBeenAddedToRole($role_name='', $cap='', $get_index = false)
836
+    private function capHasBeenAddedToRole($role_name = '', $cap = '', $get_index = false)
837 837
     {
838 838
         if (
839 839
             isset($this->capabilities_map[$role_name])
@@ -865,7 +865,7 @@  discard block
 block discarded – undo
865 865
     public function current_user_can($cap, $context, $id = 0)
866 866
     {
867 867
         //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
868
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__' . $context, $cap, $id);
868
+        $filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__'.$context, $cap, $id);
869 869
         $filtered_cap = apply_filters(
870 870
             'FHEE__EE_Capabilities__current_user_can__cap',
871 871
             $filtered_cap,
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
     public function user_can($user, $cap, $context, $id = 0)
895 895
     {
896 896
         //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
897
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__' . $context, $cap, $user, $id);
897
+        $filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__'.$context, $cap, $user, $id);
898 898
         $filtered_cap = apply_filters(
899 899
             'FHEE__EE_Capabilities__user_can__cap',
900 900
             $filtered_cap,
@@ -934,7 +934,7 @@  discard block
 block discarded – undo
934 934
             : current_user_can($blog_id, $cap);
935 935
         //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
936 936
         $user_can = apply_filters(
937
-            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__' . $context,
937
+            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__'.$context,
938 938
             $user_can,
939 939
             $blog_id,
940 940
             $cap,
@@ -964,14 +964,14 @@  discard block
 block discarded – undo
964 964
      */
965 965
     public function get_ee_capabilities($role = 'administrator')
966 966
     {
967
-        if (! $this->initialized) {
967
+        if ( ! $this->initialized) {
968 968
             $this->init_caps();
969 969
         }
970 970
         if (empty($role)) {
971 971
             return $this->capabilities_map;
972 972
         }
973
-        return isset($this->capabilities_map[ $role ])
974
-            ? $this->capabilities_map[ $role ]
973
+        return isset($this->capabilities_map[$role])
974
+            ? $this->capabilities_map[$role]
975 975
             : array();
976 976
     }
977 977
 
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
                         'event_espresso'
1004 1004
                     ),
1005 1005
                     '$reset',
1006
-                    __METHOD__ . '()',
1006
+                    __METHOD__.'()',
1007 1007
                     'EE_Capabilities::init_caps()',
1008 1008
                     'true'
1009 1009
                 ),
@@ -1081,16 +1081,16 @@  discard block
 block discarded – undo
1081 1081
                         'Incoming $map_values array should have a count of four values in it.  This is what was given: %s',
1082 1082
                         'event_espresso'
1083 1083
                     ),
1084
-                    '<br>' . print_r($map_values, true)
1084
+                    '<br>'.print_r($map_values, true)
1085 1085
                 )
1086 1086
             );
1087 1087
         }
1088 1088
         //set properties
1089 1089
         $this->_model = null;
1090 1090
         $this->_model_name = $map_values[0];
1091
-        $this->published_cap = (string)$map_values[1];
1092
-        $this->others_cap = (string)$map_values[2];
1093
-        $this->private_cap = (string)$map_values[3];
1091
+        $this->published_cap = (string) $map_values[1];
1092
+        $this->others_cap = (string) $map_values[2];
1093
+        $this->private_cap = (string) $map_values[3];
1094 1094
     }
1095 1095
 
1096 1096
     /**
@@ -1117,11 +1117,11 @@  discard block
 block discarded – undo
1117 1117
             return;
1118 1118
         }
1119 1119
         //ensure model name is string
1120
-        $this->_model_name = (string)$this->_model_name;
1120
+        $this->_model_name = (string) $this->_model_name;
1121 1121
         //error proof if the name has EEM in it
1122 1122
         $this->_model_name = str_replace('EEM', '', $this->_model_name);
1123 1123
         $this->_model = EE_Registry::instance()->load_model($this->_model_name);
1124
-        if (! $this->_model instanceof EEM_Base) {
1124
+        if ( ! $this->_model instanceof EEM_Base) {
1125 1125
             throw new EE_Error(
1126 1126
                 sprintf(
1127 1127
                     __(
@@ -1216,11 +1216,11 @@  discard block
 block discarded – undo
1216 1216
         /** @var EE_Base_Class $obj */
1217 1217
         $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1218 1218
         //if no obj then let's just do cap
1219
-        if (! $obj instanceof EE_Base_Class) {
1219
+        if ( ! $obj instanceof EE_Base_Class) {
1220 1220
             $caps[] = 'do_not_allow';
1221 1221
             return $caps;
1222 1222
         }
1223
-        $caps[] = $cap . 's';
1223
+        $caps[] = $cap.'s';
1224 1224
         if ($obj instanceof EE_CPT_Base) {
1225 1225
             //if the item author is set and the user is the author...
1226 1226
             if ($obj->wp_user() && $user_id === $obj->wp_user()) {
@@ -1230,12 +1230,12 @@  discard block
 block discarded – undo
1230 1230
                 }
1231 1231
             } else {
1232 1232
                 //the user is trying to edit someone else's obj
1233
-                if (! empty($this->others_cap)) {
1233
+                if ( ! empty($this->others_cap)) {
1234 1234
                     $caps[] = $this->others_cap;
1235 1235
                 }
1236
-                if (! empty($this->published_cap) && $obj->status() === 'publish') {
1236
+                if ( ! empty($this->published_cap) && $obj->status() === 'publish') {
1237 1237
                     $caps[] = $this->published_cap;
1238
-                } elseif (! empty($this->private_cap) && $obj->status() === 'private') {
1238
+                } elseif ( ! empty($this->private_cap) && $obj->status() === 'private') {
1239 1239
                     $caps[] = $this->private_cap;
1240 1240
                 }
1241 1241
             }
@@ -1251,8 +1251,8 @@  discard block
 block discarded – undo
1251 1251
                     EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1252 1252
                 }
1253 1253
             }
1254
-            if (! $has_cap) {
1255
-                if (! empty($this->others_cap)) {
1254
+            if ( ! $has_cap) {
1255
+                if ( ! empty($this->others_cap)) {
1256 1256
                     $caps[] = $this->others_cap;
1257 1257
                 }
1258 1258
             }
@@ -1339,12 +1339,12 @@  discard block
 block discarded – undo
1339 1339
 
1340 1340
         $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1341 1341
         //if no obj then let's just do cap
1342
-        if (! $obj instanceof EE_Base_Class) {
1342
+        if ( ! $obj instanceof EE_Base_Class) {
1343 1343
             $caps[] = 'do_not_allow';
1344 1344
             return $caps;
1345 1345
         }
1346 1346
 
1347
-        $caps[] = $cap . 's';
1347
+        $caps[] = $cap.'s';
1348 1348
         if ($obj instanceof EE_CPT_Base) {
1349 1349
             $status_obj = get_post_status_object($obj->status());
1350 1350
             if ($status_obj->public) {
@@ -1352,7 +1352,7 @@  discard block
 block discarded – undo
1352 1352
             }
1353 1353
             //if the item author is set and the user is not the author...
1354 1354
             if ($obj->wp_user() && $obj->wp_user() !== $user_id) {
1355
-                if (! empty($this->others_cap)) {
1355
+                if ( ! empty($this->others_cap)) {
1356 1356
                     $caps[] = $this->others_cap;
1357 1357
                 }
1358 1358
             }
@@ -1376,11 +1376,11 @@  discard block
 block discarded – undo
1376 1376
                     EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1377 1377
                 }
1378 1378
             }
1379
-            if (! $has_cap) {
1380
-                if (! empty($this->private_cap)) {
1379
+            if ( ! $has_cap) {
1380
+                if ( ! empty($this->private_cap)) {
1381 1381
                     $caps[] = $this->private_cap;
1382 1382
                 }
1383
-                if (! empty($this->others_cap)) {
1383
+                if ( ! empty($this->others_cap)) {
1384 1384
                     $caps[] = $this->others_cap;
1385 1385
                 }
1386 1386
             }
@@ -1434,11 +1434,11 @@  discard block
 block discarded – undo
1434 1434
 
1435 1435
         $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1436 1436
         //if no obj then let's just do cap
1437
-        if (! $obj instanceof EE_Message_Template_Group) {
1437
+        if ( ! $obj instanceof EE_Message_Template_Group) {
1438 1438
             $caps[] = 'do_not_allow';
1439 1439
             return $caps;
1440 1440
         }
1441
-        $caps[] = $cap . 's';
1441
+        $caps[] = $cap.'s';
1442 1442
         $is_global = $obj->is_global();
1443 1443
         if ($obj->wp_user() && $obj->wp_user() === $user_id) {
1444 1444
             if ($is_global) {
@@ -1493,11 +1493,11 @@  discard block
 block discarded – undo
1493 1493
         }
1494 1494
         $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1495 1495
         //if no obj then let's just do cap
1496
-        if (! $obj instanceof EE_Base_Class) {
1496
+        if ( ! $obj instanceof EE_Base_Class) {
1497 1497
             $caps[] = 'do_not_allow';
1498 1498
             return $caps;
1499 1499
         }
1500
-        $caps[]    = $cap . 's';
1500
+        $caps[]    = $cap.'s';
1501 1501
         $is_system = $obj instanceof EE_Question_Group ? $obj->system_group() : false;
1502 1502
         $is_system = $obj instanceof EE_Question ? $obj->is_system_question() : $is_system;
1503 1503
         if ($is_system) {
Please login to merge, or discard this patch.
core/business/EE_Registration_Processor.class.php 2 patches
Indentation   +775 added lines, -775 removed lines patch added patch discarded remove patch
@@ -27,781 +27,781 @@
 block discarded – undo
27 27
 class EE_Registration_Processor extends EE_Processor_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Registration_Processor $_instance
32
-     * @access    private
33
-     */
34
-    private static $_instance;
35
-
36
-    /**
37
-     * initial reg status at the beginning of this request.
38
-     * indexed by registration ID
39
-     *
40
-     * @var array
41
-     */
42
-    protected $_old_reg_status = array();
43
-
44
-    /**
45
-     * reg status at the end of the request after all processing.
46
-     * indexed by registration ID
47
-     *
48
-     * @var array
49
-     */
50
-    protected $_new_reg_status = array();
51
-
52
-    /**
53
-     * amounts paid at the end of the request after all processing.
54
-     * indexed by registration ID
55
-     *
56
-     * @var array
57
-     */
58
-    protected static $_amount_paid = array();
59
-
60
-    /**
61
-     * Cache of the reg final price for registrations corresponding to a ticket line item
62
-     *
63
-     * @deprecated
64
-     * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
-     */
66
-    protected $_reg_final_price_per_tkt_line_item;
67
-
68
-    /**
69
-     * @var EE_Request $request
70
-     */
71
-    protected $request;
72
-
73
-
74
-
75
-    /**
76
-     * @singleton method used to instantiate class object
77
-     * @param EE_Request|null $request
78
-     * @return EE_Registration_Processor instance
79
-     * @throws \InvalidArgumentException
80
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
-     */
83
-    public static function instance(EE_Request $request = null)
84
-    {
85
-        // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
88
-                $request = LoaderFactory::getLoader()->getShared('EE_Request');
89
-            }
90
-            self::$_instance = new self($request);
91
-        }
92
-        return self::$_instance;
93
-    }
94
-
95
-
96
-    /**
97
-     * EE_Registration_Processor constructor.
98
-     *
99
-     * @param EE_Request $request
100
-     */
101
-    public function __construct(EE_Request $request)
102
-    {
103
-        $this->request = $request;
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * @param int $REG_ID
110
-     * @return string
111
-     */
112
-    public function old_reg_status($REG_ID)
113
-    {
114
-        return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
-    }
116
-
117
-
118
-
119
-    /**
120
-     * @param int    $REG_ID
121
-     * @param string $old_reg_status
122
-     */
123
-    public function set_old_reg_status($REG_ID, $old_reg_status)
124
-    {
125
-        // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
127
-            $this->_old_reg_status[$REG_ID] = $old_reg_status;
128
-        }
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @param int $REG_ID
135
-     * @return string
136
-     */
137
-    public function new_reg_status($REG_ID)
138
-    {
139
-        return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     * @param int    $REG_ID
146
-     * @param string $new_reg_status
147
-     */
148
-    public function set_new_reg_status($REG_ID, $new_reg_status)
149
-    {
150
-        $this->_new_reg_status[$REG_ID] = $new_reg_status;
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * reg_status_updated
157
-     *
158
-     * @param int $REG_ID
159
-     * @return bool
160
-     */
161
-    public function reg_status_updated($REG_ID)
162
-    {
163
-        return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * @param EE_Registration $registration
170
-     * @throws EE_Error
171
-     * @throws EntityNotFoundException
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     * @throws RuntimeException
177
-     */
178
-    public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
-    {
180
-        $this->toggle_incomplete_registration_status_to_default($registration, false);
181
-        $this->toggle_registration_status_for_default_approved_events($registration, false);
182
-        $this->toggle_registration_status_if_no_monies_owing($registration, false);
183
-        $registration->save();
184
-        // trigger notifications
185
-        $this->trigger_registration_update_notifications($registration);
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     *    manually_update_registration_status
192
-     *
193
-     * @access public
194
-     * @param EE_Registration $registration
195
-     * @param string          $new_reg_status
196
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
-     *                              to client code
198
-     * @return bool
199
-     * @throws EE_Error
200
-     * @throws EntityNotFoundException
201
-     * @throws InvalidArgumentException
202
-     * @throws InvalidDataTypeException
203
-     * @throws InvalidInterfaceException
204
-     * @throws ReflectionException
205
-     * @throws RuntimeException
206
-     */
207
-    public function manually_update_registration_status(
208
-        EE_Registration $registration,
209
-        $new_reg_status = '',
210
-        $save = true
211
-    ) {
212
-        // set initial REG_Status
213
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
-        // set incoming REG_Status
215
-        $this->set_new_reg_status($registration->ID(), $new_reg_status);
216
-        // toggle reg status but only if it has changed and the user can do so
217
-        if (
218
-            $this->reg_status_updated($registration->ID())
219
-            && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
221
-                || EE_Registry::instance()->CAP->current_user_can(
222
-                    'ee_edit_registration',
223
-                    'toggle_registration_status',
224
-                    $registration->ID()
225
-                )
226
-            )
227
-        ) {
228
-            // change status to new value
229
-            $updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
-            if ($updated && $save) {
231
-                $registration->save();
232
-            }
233
-            return true;
234
-        }
235
-        return false;
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     *    toggle_incomplete_registration_status_to_default
242
-     *        changes any incomplete registrations to either the event or global default registration status
243
-     *
244
-     * @access public
245
-     * @param EE_Registration $registration
246
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
-     *                              to client code
248
-     * @param Context|null    $context
249
-     * @return void
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws ReflectionException
253
-     * @throws RuntimeException
254
-     * @throws EntityNotFoundException
255
-     * @throws InvalidDataTypeException
256
-     * @throws InvalidInterfaceException
257
-     */
258
-    public function toggle_incomplete_registration_status_to_default(
259
-        EE_Registration $registration,
260
-        $save = true,
261
-        Context $context = null
262
-    ) {
263
-        $existing_reg_status = $registration->status_ID();
264
-        // set initial REG_Status
265
-        $this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
-        // is the registration currently incomplete ?
267
-        if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
-            // grab default reg status for the event, if set
269
-            $event_default_registration_status = $registration->event()->default_registration_status();
270
-            // if no default reg status is set for the event, then use the global value
271
-            $STS_ID = ! empty($event_default_registration_status)
272
-                ? $event_default_registration_status
273
-                : EE_Registry::instance()->CFG->registration->default_STS_ID;
274
-            // if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
-            $STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
-                : $STS_ID;
277
-            // set incoming REG_Status
278
-            $this->set_new_reg_status($registration->ID(), $STS_ID);
279
-            $registration->set_status($STS_ID, false, $context);
280
-            if ($save) {
281
-                $registration->save();
282
-            }
283
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
285
-                // otherwise, send out notifications
286
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
-            }
288
-            // DEBUG LOG
289
-            //$this->log(
290
-            //	__CLASS__, __FUNCTION__, __LINE__,
291
-            //	$registration->transaction(),
292
-            //	array(
293
-            //		'IPN'                   => EE_Processor_Base::$IPN,
294
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
-            //	)
296
-            //);
297
-        }
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     *    toggle_registration_status_for_default_approved_events
304
-     *
305
-     * @access public
306
-     * @param EE_Registration $registration
307
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
-     *                              to client code
309
-     * @return bool
310
-     * @throws EE_Error
311
-     * @throws EntityNotFoundException
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     * @throws RuntimeException
317
-     */
318
-    public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
-    {
320
-        $reg_status = $registration->status_ID();
321
-        // set initial REG_Status
322
-        $this->set_old_reg_status($registration->ID(), $reg_status);
323
-        // if not already, toggle reg status to approved IF the event default reg status is approved
324
-        // ( as long as the registration wasn't cancelled or declined at some point )
325
-        if (
326
-            $reg_status !== EEM_Registration::status_id_cancelled
327
-            && $reg_status
328
-               !== EEM_Registration::status_id_declined
329
-            && $reg_status !== EEM_Registration::status_id_approved
330
-            && $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
-        ) {
332
-            // set incoming REG_Status
333
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
-            // toggle status to approved
335
-            $registration->set_status(EEM_Registration::status_id_approved);
336
-            if ($save) {
337
-                $registration->save();
338
-            }
339
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
341
-                // otherwise, send out notifications
342
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
-            }
344
-            // DEBUG LOG
345
-            //$this->log(
346
-            //	__CLASS__, __FUNCTION__, __LINE__,
347
-            //	$registration->transaction(),
348
-            //	array(
349
-            //		'IPN'                   => EE_Processor_Base::$IPN,
350
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
-            //	)
352
-            //);
353
-            return true;
354
-        }
355
-        return false;
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     *    toggle_registration_statuses_if_no_monies_owing
362
-     *
363
-     * @access public
364
-     * @param EE_Registration $registration
365
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
-     *                              to client code
367
-     * @param array           $additional_details
368
-     * @return bool
369
-     * @throws EE_Error
370
-     * @throws EntityNotFoundException
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     * @throws RuntimeException
376
-     */
377
-    public function toggle_registration_status_if_no_monies_owing(
378
-        EE_Registration $registration,
379
-        $save = true,
380
-        array $additional_details = array()
381
-    ) {
382
-        // set initial REG_Status
383
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
-        // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
-                      && $additional_details['payment_updates']
387
-                      && $additional_details['last_payment'] instanceof EE_Payment
388
-            ? $additional_details['last_payment']
389
-            : null;
390
-        $total_paid = array_sum(self::$_amount_paid);
391
-        // toggle reg status to approved IF
392
-        if (
393
-            // REG status is pending payment
394
-            $registration->status_ID() === EEM_Registration::status_id_pending_payment
395
-            // AND no monies are owing
396
-            && (
397
-                (
398
-                    $registration->transaction()->is_completed()
399
-                    || $registration->transaction()->is_overpaid()
400
-                    || $registration->transaction()->is_free()
401
-                    || apply_filters(
402
-                        'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
-                        false,
404
-                        $registration
405
-                    )
406
-                )
407
-                || (
408
-                    $payment instanceof EE_Payment && $payment->is_approved()
409
-                    && // this specific registration has not yet been paid for
410
-                    ! isset(self::$_amount_paid[$registration->ID()])
411
-                    && // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
-                    $payment->amount() - $total_paid >= $registration->final_price()
413
-                )
414
-            )
415
-        ) {
416
-            // mark as paid
417
-            self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
-            // track new REG_Status
419
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
-            // toggle status to approved
421
-            $registration->set_status(EEM_Registration::status_id_approved);
422
-            if ($save) {
423
-                $registration->save();
424
-            }
425
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
427
-                // otherwise, send out notifications
428
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
-            }
430
-            // DEBUG LOG
431
-            //$this->log(
432
-            //	__CLASS__, __FUNCTION__, __LINE__,
433
-            //	$registration->transaction(),
434
-            //	array(
435
-            //		'IPN'                   => EE_Processor_Base::$IPN,
436
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
-            //	)
438
-            //);
439
-            return true;
440
-        }
441
-        return false;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     *    registration_status_changed
448
-     *
449
-     * @access public
450
-     * @param EE_Registration $registration
451
-     * @param array           $additional_details
452
-     * @return void
453
-     */
454
-    public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
-    {
456
-        try {
457
-            if (! $registration instanceof EE_Registration) {
458
-                throw new EE_Error(
459
-                    esc_html__('An invalid registration was received.', 'event_espresso')
460
-                );
461
-            }
462
-            // EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
-            // EEH_Debug_Tools::log(
464
-            // 	__CLASS__,
465
-            // 	__FUNCTION__,
466
-            // 	__LINE__,
467
-            // 	array( $registration->transaction(), $additional_details ),
468
-            // 	false,
469
-            // 	'EE_Transaction: ' . $registration->transaction()->ID()
470
-            // );
471
-            if (! $registration->is_primary_registrant()) {
472
-                return;
473
-            }
474
-            do_action(
475
-                'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
-                $registration,
477
-                $additional_details
478
-            );
479
-        } catch (Exception $e) {
480
-            EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
-        }
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
-     *
489
-     * @param EE_Registration $registration
490
-     * @param array           $additional_details
491
-     * @return bool
492
-     * @throws EE_Error
493
-     * @throws EntityNotFoundException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidDataTypeException
496
-     * @throws InvalidInterfaceException
497
-     * @throws ReflectionException
498
-     * @throws RuntimeException
499
-     */
500
-    public function update_registration_after_checkout_or_payment(
501
-        EE_Registration $registration,
502
-        array $additional_details = array()
503
-    ) {
504
-        // set initial REG_Status
505
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
-        // if the registration status gets updated, then save the registration
507
-        if (
508
-            $this->toggle_registration_status_for_default_approved_events($registration, false)
509
-            || $this->toggle_registration_status_if_no_monies_owing(
510
-                $registration,
511
-                false,
512
-                $additional_details
513
-            )
514
-        ) {
515
-            $registration->save();
516
-        }
517
-        // set new  REG_Status
518
-        $this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
-        return $this->reg_status_updated($registration->ID())
520
-               && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     * Updates the registration' final prices based on the current line item tree (taking into account
527
-     * discounts, taxes, and other line items unrelated to tickets.)
528
-     *
529
-     * @param EE_Transaction $transaction
530
-     * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
-     * @return void
532
-     * @throws EE_Error
533
-     * @throws InvalidArgumentException
534
-     * @throws InvalidDataTypeException
535
-     * @throws InvalidInterfaceException
536
-     * @throws RuntimeException
537
-     */
538
-    public function update_registration_final_prices($transaction, $save_regs = true)
539
-    {
540
-        $reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
-            $transaction->total_line_item()
542
-        );
543
-        foreach ($transaction->registrations() as $registration) {
544
-            /** @var EE_Line_Item $line_item */
545
-            $line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
-            if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
-                $registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
-                if ($save_regs) {
549
-                    $registration->save();
550
-                }
551
-            }
552
-        }
553
-        //and make sure there's no rounding problem
554
-        $this->fix_reg_final_price_rounding_issue($transaction);
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Makes sure there is no rounding errors for the REG_final_prices.
561
-     * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
-     * they will each be for $0.99333333, which gets rounded to $1 again.
563
-     * So the transaction total will be $2.99, but each registration will be for $1,
564
-     * so if each registrant paid individually they will have overpaid by $0.01.
565
-     * So in order to overcome this, we check for any difference, and if there is a difference
566
-     * we just grab one registrant at random and make them responsible for it.
567
-     * This should be used after setting REG_final_prices (it's done automatically as part of
568
-     * EE_Registration_Processor::update_registration_final_prices())
569
-     *
570
-     * @param EE_Transaction $transaction
571
-     * @return bool success verifying that there is NO difference after this method is done
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     */
577
-    public function fix_reg_final_price_rounding_issue($transaction)
578
-    {
579
-        $reg_final_price_sum = EEM_Registration::instance()->sum(
580
-            array(
581
-                array(
582
-                    'TXN_ID' => $transaction->ID(),
583
-                ),
584
-            ),
585
-            'REG_final_price'
586
-        );
587
-        $diff = $transaction->total() - $reg_final_price_sum;
588
-        //ok then, just grab one of the registrations
589
-        if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
591
-                array(
592
-                    array(
593
-                        'TXN_ID' => $transaction->ID(),
594
-                    ),
595
-                )
596
-            );
597
-            return $a_reg instanceof EE_Registration
598
-                ? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
-                : false;
600
-        }
601
-        return true;
602
-    }
603
-
604
-
605
-
606
-    /**
607
-     * update_registration_after_being_canceled_or_declined
608
-     *
609
-     * @param EE_Registration $registration
610
-     * @param array           $closed_reg_statuses
611
-     * @param bool            $update_reg
612
-     * @return bool
613
-     * @throws EE_Error
614
-     * @throws RuntimeException
615
-     */
616
-    public function update_registration_after_being_canceled_or_declined(
617
-        EE_Registration $registration,
618
-        array $closed_reg_statuses = array(),
619
-        $update_reg = true
620
-    ) {
621
-        // these reg statuses should not be considered in any calculations involving monies owing
622
-        $closed_reg_statuses = ! empty($closed_reg_statuses)
623
-            ? $closed_reg_statuses
624
-            : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
-            return false;
627
-        }
628
-        // release a reserved ticket by decrementing ticket and datetime reserved values
629
-        $registration->release_reserved_ticket(true);
630
-        $registration->set_final_price(0);
631
-        if ($update_reg) {
632
-            $registration->save();
633
-        }
634
-        return true;
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     * update_canceled_or_declined_registration_after_being_reinstated
641
-     *
642
-     * @param EE_Registration $registration
643
-     * @param array           $closed_reg_statuses
644
-     * @param bool            $update_reg
645
-     * @return bool
646
-     * @throws EE_Error
647
-     * @throws RuntimeException
648
-     */
649
-    public function update_canceled_or_declined_registration_after_being_reinstated(
650
-        EE_Registration $registration,
651
-        array $closed_reg_statuses = array(),
652
-        $update_reg = true
653
-    ) {
654
-        // these reg statuses should not be considered in any calculations involving monies owing
655
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
-            : EEM_Registration::closed_reg_statuses();
657
-        if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
-            return false;
659
-        }
660
-        $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
662
-            throw new EE_Error(
663
-                sprintf(
664
-                    esc_html__(
665
-                        'The Ticket for Registration %1$d was not found or is invalid.',
666
-                        'event_espresso'
667
-                    ),
668
-                    $registration->ticket_ID()
669
-                )
670
-            );
671
-        }
672
-        $registration->set_final_price($ticket->price());
673
-        if ($update_reg) {
674
-            $registration->save();
675
-        }
676
-        return true;
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * generate_ONE_registration_from_line_item
683
-     * Although a ticket line item may have a quantity greater than 1,
684
-     * this method will ONLY CREATE ONE REGISTRATION !!!
685
-     * Regardless of the ticket line item quantity.
686
-     * This means that any code calling this method is responsible for ensuring
687
-     * that the final registration count matches the ticket line item quantity.
688
-     * This was done to make it easier to match the number of registrations
689
-     * to the number of tickets in the cart, when the cart has been edited
690
-     * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
-     * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
-     *
693
-     * @deprecated
694
-     * @since 4.9.1
695
-     * @param EE_Line_Item    $line_item
696
-     * @param \EE_Transaction $transaction
697
-     * @param int             $att_nmbr
698
-     * @param int             $total_ticket_count
699
-     * @return EE_Registration | null
700
-     * @throws \OutOfRangeException
701
-     * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
-     * @throws \EE_Error
703
-     */
704
-    public function generate_ONE_registration_from_line_item(
705
-        EE_Line_Item $line_item,
706
-        EE_Transaction $transaction,
707
-        $att_nmbr = 1,
708
-        $total_ticket_count = 1
709
-    ) {
710
-        EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
712
-            sprintf(
713
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
-                '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
-            ),
716
-            '4.9.1',
717
-            '5.0.0'
718
-        );
719
-        // grab the related ticket object for this line_item
720
-        $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
722
-            EE_Error::add_error(
723
-                sprintf(
724
-                    esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
-                    $line_item->ID()
726
-                ),
727
-                __FILE__,
728
-                __FUNCTION__,
729
-                __LINE__
730
-            );
731
-            return null;
732
-        }
733
-        $registration_service = new CreateRegistrationService();
734
-        // then generate a new registration from that
735
-        return $registration_service->create(
736
-            $ticket->get_related_event(),
737
-            $transaction,
738
-            $ticket,
739
-            $line_item,
740
-            $att_nmbr,
741
-            $total_ticket_count
742
-        );
743
-    }
744
-
745
-
746
-
747
-    /**
748
-     * generates reg_url_link
749
-     *
750
-     * @deprecated
751
-     * @since 4.9.1
752
-     * @param int                   $att_nmbr
753
-     * @param EE_Line_Item | string $item
754
-     * @return string
755
-     * @throws InvalidArgumentException
756
-     */
757
-    public function generate_reg_url_link($att_nmbr, $item)
758
-    {
759
-        EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
761
-            sprintf(
762
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
-                'EventEspresso\core\domain\entities\RegUrlLink'
764
-            ),
765
-            '4.9.1',
766
-            '5.0.0'
767
-        );
768
-        return new RegUrlLink($att_nmbr, $item);
769
-    }
770
-
771
-
772
-
773
-    /**
774
-     * generates reg code
775
-     *
776
-     * @deprecated
777
-     * @since 4.9.1
778
-     * @param EE_Registration $registration
779
-     * @return string
780
-     * @throws EE_Error
781
-     * @throws EntityNotFoundException
782
-     * @throws InvalidArgumentException
783
-     */
784
-    public function generate_reg_code(EE_Registration $registration)
785
-    {
786
-        EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
788
-            sprintf(
789
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
-                'EventEspresso\core\domain\entities\RegCode'
791
-            ),
792
-            '4.9.1',
793
-            '5.0.0'
794
-        );
795
-        return apply_filters(
796
-            'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
-            new RegCode(
798
-                RegUrlLink::fromRegistration($registration),
799
-                $registration->transaction(),
800
-                $registration->ticket()
801
-            ),
802
-            $registration
803
-        );
804
-    }
30
+	/**
31
+	 * @var EE_Registration_Processor $_instance
32
+	 * @access    private
33
+	 */
34
+	private static $_instance;
35
+
36
+	/**
37
+	 * initial reg status at the beginning of this request.
38
+	 * indexed by registration ID
39
+	 *
40
+	 * @var array
41
+	 */
42
+	protected $_old_reg_status = array();
43
+
44
+	/**
45
+	 * reg status at the end of the request after all processing.
46
+	 * indexed by registration ID
47
+	 *
48
+	 * @var array
49
+	 */
50
+	protected $_new_reg_status = array();
51
+
52
+	/**
53
+	 * amounts paid at the end of the request after all processing.
54
+	 * indexed by registration ID
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected static $_amount_paid = array();
59
+
60
+	/**
61
+	 * Cache of the reg final price for registrations corresponding to a ticket line item
62
+	 *
63
+	 * @deprecated
64
+	 * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
+	 */
66
+	protected $_reg_final_price_per_tkt_line_item;
67
+
68
+	/**
69
+	 * @var EE_Request $request
70
+	 */
71
+	protected $request;
72
+
73
+
74
+
75
+	/**
76
+	 * @singleton method used to instantiate class object
77
+	 * @param EE_Request|null $request
78
+	 * @return EE_Registration_Processor instance
79
+	 * @throws \InvalidArgumentException
80
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
+	 */
83
+	public static function instance(EE_Request $request = null)
84
+	{
85
+		// check if class object is instantiated
86
+		if (! self::$_instance instanceof EE_Registration_Processor) {
87
+			if(! $request instanceof EE_Request) {
88
+				$request = LoaderFactory::getLoader()->getShared('EE_Request');
89
+			}
90
+			self::$_instance = new self($request);
91
+		}
92
+		return self::$_instance;
93
+	}
94
+
95
+
96
+	/**
97
+	 * EE_Registration_Processor constructor.
98
+	 *
99
+	 * @param EE_Request $request
100
+	 */
101
+	public function __construct(EE_Request $request)
102
+	{
103
+		$this->request = $request;
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * @param int $REG_ID
110
+	 * @return string
111
+	 */
112
+	public function old_reg_status($REG_ID)
113
+	{
114
+		return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
+	}
116
+
117
+
118
+
119
+	/**
120
+	 * @param int    $REG_ID
121
+	 * @param string $old_reg_status
122
+	 */
123
+	public function set_old_reg_status($REG_ID, $old_reg_status)
124
+	{
125
+		// only set the first time
126
+		if (! isset($this->_old_reg_status[$REG_ID])) {
127
+			$this->_old_reg_status[$REG_ID] = $old_reg_status;
128
+		}
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @param int $REG_ID
135
+	 * @return string
136
+	 */
137
+	public function new_reg_status($REG_ID)
138
+	{
139
+		return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 * @param int    $REG_ID
146
+	 * @param string $new_reg_status
147
+	 */
148
+	public function set_new_reg_status($REG_ID, $new_reg_status)
149
+	{
150
+		$this->_new_reg_status[$REG_ID] = $new_reg_status;
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * reg_status_updated
157
+	 *
158
+	 * @param int $REG_ID
159
+	 * @return bool
160
+	 */
161
+	public function reg_status_updated($REG_ID)
162
+	{
163
+		return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * @param EE_Registration $registration
170
+	 * @throws EE_Error
171
+	 * @throws EntityNotFoundException
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 * @throws RuntimeException
177
+	 */
178
+	public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
+	{
180
+		$this->toggle_incomplete_registration_status_to_default($registration, false);
181
+		$this->toggle_registration_status_for_default_approved_events($registration, false);
182
+		$this->toggle_registration_status_if_no_monies_owing($registration, false);
183
+		$registration->save();
184
+		// trigger notifications
185
+		$this->trigger_registration_update_notifications($registration);
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 *    manually_update_registration_status
192
+	 *
193
+	 * @access public
194
+	 * @param EE_Registration $registration
195
+	 * @param string          $new_reg_status
196
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
+	 *                              to client code
198
+	 * @return bool
199
+	 * @throws EE_Error
200
+	 * @throws EntityNotFoundException
201
+	 * @throws InvalidArgumentException
202
+	 * @throws InvalidDataTypeException
203
+	 * @throws InvalidInterfaceException
204
+	 * @throws ReflectionException
205
+	 * @throws RuntimeException
206
+	 */
207
+	public function manually_update_registration_status(
208
+		EE_Registration $registration,
209
+		$new_reg_status = '',
210
+		$save = true
211
+	) {
212
+		// set initial REG_Status
213
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
+		// set incoming REG_Status
215
+		$this->set_new_reg_status($registration->ID(), $new_reg_status);
216
+		// toggle reg status but only if it has changed and the user can do so
217
+		if (
218
+			$this->reg_status_updated($registration->ID())
219
+			&& (
220
+				(! $this->request->isAdmin() || $this->request->isFrontAjax())
221
+				|| EE_Registry::instance()->CAP->current_user_can(
222
+					'ee_edit_registration',
223
+					'toggle_registration_status',
224
+					$registration->ID()
225
+				)
226
+			)
227
+		) {
228
+			// change status to new value
229
+			$updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
+			if ($updated && $save) {
231
+				$registration->save();
232
+			}
233
+			return true;
234
+		}
235
+		return false;
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 *    toggle_incomplete_registration_status_to_default
242
+	 *        changes any incomplete registrations to either the event or global default registration status
243
+	 *
244
+	 * @access public
245
+	 * @param EE_Registration $registration
246
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
+	 *                              to client code
248
+	 * @param Context|null    $context
249
+	 * @return void
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws ReflectionException
253
+	 * @throws RuntimeException
254
+	 * @throws EntityNotFoundException
255
+	 * @throws InvalidDataTypeException
256
+	 * @throws InvalidInterfaceException
257
+	 */
258
+	public function toggle_incomplete_registration_status_to_default(
259
+		EE_Registration $registration,
260
+		$save = true,
261
+		Context $context = null
262
+	) {
263
+		$existing_reg_status = $registration->status_ID();
264
+		// set initial REG_Status
265
+		$this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
+		// is the registration currently incomplete ?
267
+		if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
+			// grab default reg status for the event, if set
269
+			$event_default_registration_status = $registration->event()->default_registration_status();
270
+			// if no default reg status is set for the event, then use the global value
271
+			$STS_ID = ! empty($event_default_registration_status)
272
+				? $event_default_registration_status
273
+				: EE_Registry::instance()->CFG->registration->default_STS_ID;
274
+			// if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
+			$STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
+				: $STS_ID;
277
+			// set incoming REG_Status
278
+			$this->set_new_reg_status($registration->ID(), $STS_ID);
279
+			$registration->set_status($STS_ID, false, $context);
280
+			if ($save) {
281
+				$registration->save();
282
+			}
283
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
+			if (! EE_Processor_Base::$IPN) {
285
+				// otherwise, send out notifications
286
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
+			}
288
+			// DEBUG LOG
289
+			//$this->log(
290
+			//	__CLASS__, __FUNCTION__, __LINE__,
291
+			//	$registration->transaction(),
292
+			//	array(
293
+			//		'IPN'                   => EE_Processor_Base::$IPN,
294
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
+			//	)
296
+			//);
297
+		}
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 *    toggle_registration_status_for_default_approved_events
304
+	 *
305
+	 * @access public
306
+	 * @param EE_Registration $registration
307
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
+	 *                              to client code
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 * @throws EntityNotFoundException
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 * @throws RuntimeException
317
+	 */
318
+	public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
+	{
320
+		$reg_status = $registration->status_ID();
321
+		// set initial REG_Status
322
+		$this->set_old_reg_status($registration->ID(), $reg_status);
323
+		// if not already, toggle reg status to approved IF the event default reg status is approved
324
+		// ( as long as the registration wasn't cancelled or declined at some point )
325
+		if (
326
+			$reg_status !== EEM_Registration::status_id_cancelled
327
+			&& $reg_status
328
+			   !== EEM_Registration::status_id_declined
329
+			&& $reg_status !== EEM_Registration::status_id_approved
330
+			&& $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
+		) {
332
+			// set incoming REG_Status
333
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
+			// toggle status to approved
335
+			$registration->set_status(EEM_Registration::status_id_approved);
336
+			if ($save) {
337
+				$registration->save();
338
+			}
339
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
+			if (! EE_Processor_Base::$IPN) {
341
+				// otherwise, send out notifications
342
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
+			}
344
+			// DEBUG LOG
345
+			//$this->log(
346
+			//	__CLASS__, __FUNCTION__, __LINE__,
347
+			//	$registration->transaction(),
348
+			//	array(
349
+			//		'IPN'                   => EE_Processor_Base::$IPN,
350
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
+			//	)
352
+			//);
353
+			return true;
354
+		}
355
+		return false;
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 *    toggle_registration_statuses_if_no_monies_owing
362
+	 *
363
+	 * @access public
364
+	 * @param EE_Registration $registration
365
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
+	 *                              to client code
367
+	 * @param array           $additional_details
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 * @throws EntityNotFoundException
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function toggle_registration_status_if_no_monies_owing(
378
+		EE_Registration $registration,
379
+		$save = true,
380
+		array $additional_details = array()
381
+	) {
382
+		// set initial REG_Status
383
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
+		// was a payment just made ?
385
+		$payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
+					  && $additional_details['payment_updates']
387
+					  && $additional_details['last_payment'] instanceof EE_Payment
388
+			? $additional_details['last_payment']
389
+			: null;
390
+		$total_paid = array_sum(self::$_amount_paid);
391
+		// toggle reg status to approved IF
392
+		if (
393
+			// REG status is pending payment
394
+			$registration->status_ID() === EEM_Registration::status_id_pending_payment
395
+			// AND no monies are owing
396
+			&& (
397
+				(
398
+					$registration->transaction()->is_completed()
399
+					|| $registration->transaction()->is_overpaid()
400
+					|| $registration->transaction()->is_free()
401
+					|| apply_filters(
402
+						'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
+						false,
404
+						$registration
405
+					)
406
+				)
407
+				|| (
408
+					$payment instanceof EE_Payment && $payment->is_approved()
409
+					&& // this specific registration has not yet been paid for
410
+					! isset(self::$_amount_paid[$registration->ID()])
411
+					&& // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
+					$payment->amount() - $total_paid >= $registration->final_price()
413
+				)
414
+			)
415
+		) {
416
+			// mark as paid
417
+			self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
+			// track new REG_Status
419
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
+			// toggle status to approved
421
+			$registration->set_status(EEM_Registration::status_id_approved);
422
+			if ($save) {
423
+				$registration->save();
424
+			}
425
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
+			if (! EE_Processor_Base::$IPN) {
427
+				// otherwise, send out notifications
428
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
+			}
430
+			// DEBUG LOG
431
+			//$this->log(
432
+			//	__CLASS__, __FUNCTION__, __LINE__,
433
+			//	$registration->transaction(),
434
+			//	array(
435
+			//		'IPN'                   => EE_Processor_Base::$IPN,
436
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
+			//	)
438
+			//);
439
+			return true;
440
+		}
441
+		return false;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 *    registration_status_changed
448
+	 *
449
+	 * @access public
450
+	 * @param EE_Registration $registration
451
+	 * @param array           $additional_details
452
+	 * @return void
453
+	 */
454
+	public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
+	{
456
+		try {
457
+			if (! $registration instanceof EE_Registration) {
458
+				throw new EE_Error(
459
+					esc_html__('An invalid registration was received.', 'event_espresso')
460
+				);
461
+			}
462
+			// EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
+			// EEH_Debug_Tools::log(
464
+			// 	__CLASS__,
465
+			// 	__FUNCTION__,
466
+			// 	__LINE__,
467
+			// 	array( $registration->transaction(), $additional_details ),
468
+			// 	false,
469
+			// 	'EE_Transaction: ' . $registration->transaction()->ID()
470
+			// );
471
+			if (! $registration->is_primary_registrant()) {
472
+				return;
473
+			}
474
+			do_action(
475
+				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
+				$registration,
477
+				$additional_details
478
+			);
479
+		} catch (Exception $e) {
480
+			EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
+		}
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
+	 *
489
+	 * @param EE_Registration $registration
490
+	 * @param array           $additional_details
491
+	 * @return bool
492
+	 * @throws EE_Error
493
+	 * @throws EntityNotFoundException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws InvalidInterfaceException
497
+	 * @throws ReflectionException
498
+	 * @throws RuntimeException
499
+	 */
500
+	public function update_registration_after_checkout_or_payment(
501
+		EE_Registration $registration,
502
+		array $additional_details = array()
503
+	) {
504
+		// set initial REG_Status
505
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
+		// if the registration status gets updated, then save the registration
507
+		if (
508
+			$this->toggle_registration_status_for_default_approved_events($registration, false)
509
+			|| $this->toggle_registration_status_if_no_monies_owing(
510
+				$registration,
511
+				false,
512
+				$additional_details
513
+			)
514
+		) {
515
+			$registration->save();
516
+		}
517
+		// set new  REG_Status
518
+		$this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
+		return $this->reg_status_updated($registration->ID())
520
+			   && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 * Updates the registration' final prices based on the current line item tree (taking into account
527
+	 * discounts, taxes, and other line items unrelated to tickets.)
528
+	 *
529
+	 * @param EE_Transaction $transaction
530
+	 * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
+	 * @return void
532
+	 * @throws EE_Error
533
+	 * @throws InvalidArgumentException
534
+	 * @throws InvalidDataTypeException
535
+	 * @throws InvalidInterfaceException
536
+	 * @throws RuntimeException
537
+	 */
538
+	public function update_registration_final_prices($transaction, $save_regs = true)
539
+	{
540
+		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
+			$transaction->total_line_item()
542
+		);
543
+		foreach ($transaction->registrations() as $registration) {
544
+			/** @var EE_Line_Item $line_item */
545
+			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
+			if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
+				$registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
+				if ($save_regs) {
549
+					$registration->save();
550
+				}
551
+			}
552
+		}
553
+		//and make sure there's no rounding problem
554
+		$this->fix_reg_final_price_rounding_issue($transaction);
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Makes sure there is no rounding errors for the REG_final_prices.
561
+	 * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
+	 * they will each be for $0.99333333, which gets rounded to $1 again.
563
+	 * So the transaction total will be $2.99, but each registration will be for $1,
564
+	 * so if each registrant paid individually they will have overpaid by $0.01.
565
+	 * So in order to overcome this, we check for any difference, and if there is a difference
566
+	 * we just grab one registrant at random and make them responsible for it.
567
+	 * This should be used after setting REG_final_prices (it's done automatically as part of
568
+	 * EE_Registration_Processor::update_registration_final_prices())
569
+	 *
570
+	 * @param EE_Transaction $transaction
571
+	 * @return bool success verifying that there is NO difference after this method is done
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 */
577
+	public function fix_reg_final_price_rounding_issue($transaction)
578
+	{
579
+		$reg_final_price_sum = EEM_Registration::instance()->sum(
580
+			array(
581
+				array(
582
+					'TXN_ID' => $transaction->ID(),
583
+				),
584
+			),
585
+			'REG_final_price'
586
+		);
587
+		$diff = $transaction->total() - $reg_final_price_sum;
588
+		//ok then, just grab one of the registrations
589
+		if ($diff !== 0) {
590
+			$a_reg   = EEM_Registration::instance()->get_one(
591
+				array(
592
+					array(
593
+						'TXN_ID' => $transaction->ID(),
594
+					),
595
+				)
596
+			);
597
+			return $a_reg instanceof EE_Registration
598
+				? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
+				: false;
600
+		}
601
+		return true;
602
+	}
603
+
604
+
605
+
606
+	/**
607
+	 * update_registration_after_being_canceled_or_declined
608
+	 *
609
+	 * @param EE_Registration $registration
610
+	 * @param array           $closed_reg_statuses
611
+	 * @param bool            $update_reg
612
+	 * @return bool
613
+	 * @throws EE_Error
614
+	 * @throws RuntimeException
615
+	 */
616
+	public function update_registration_after_being_canceled_or_declined(
617
+		EE_Registration $registration,
618
+		array $closed_reg_statuses = array(),
619
+		$update_reg = true
620
+	) {
621
+		// these reg statuses should not be considered in any calculations involving monies owing
622
+		$closed_reg_statuses = ! empty($closed_reg_statuses)
623
+			? $closed_reg_statuses
624
+			: EEM_Registration::closed_reg_statuses();
625
+		if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
+			return false;
627
+		}
628
+		// release a reserved ticket by decrementing ticket and datetime reserved values
629
+		$registration->release_reserved_ticket(true);
630
+		$registration->set_final_price(0);
631
+		if ($update_reg) {
632
+			$registration->save();
633
+		}
634
+		return true;
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 * update_canceled_or_declined_registration_after_being_reinstated
641
+	 *
642
+	 * @param EE_Registration $registration
643
+	 * @param array           $closed_reg_statuses
644
+	 * @param bool            $update_reg
645
+	 * @return bool
646
+	 * @throws EE_Error
647
+	 * @throws RuntimeException
648
+	 */
649
+	public function update_canceled_or_declined_registration_after_being_reinstated(
650
+		EE_Registration $registration,
651
+		array $closed_reg_statuses = array(),
652
+		$update_reg = true
653
+	) {
654
+		// these reg statuses should not be considered in any calculations involving monies owing
655
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
+			: EEM_Registration::closed_reg_statuses();
657
+		if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
+			return false;
659
+		}
660
+		$ticket = $registration->ticket();
661
+		if (! $ticket instanceof EE_Ticket) {
662
+			throw new EE_Error(
663
+				sprintf(
664
+					esc_html__(
665
+						'The Ticket for Registration %1$d was not found or is invalid.',
666
+						'event_espresso'
667
+					),
668
+					$registration->ticket_ID()
669
+				)
670
+			);
671
+		}
672
+		$registration->set_final_price($ticket->price());
673
+		if ($update_reg) {
674
+			$registration->save();
675
+		}
676
+		return true;
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * generate_ONE_registration_from_line_item
683
+	 * Although a ticket line item may have a quantity greater than 1,
684
+	 * this method will ONLY CREATE ONE REGISTRATION !!!
685
+	 * Regardless of the ticket line item quantity.
686
+	 * This means that any code calling this method is responsible for ensuring
687
+	 * that the final registration count matches the ticket line item quantity.
688
+	 * This was done to make it easier to match the number of registrations
689
+	 * to the number of tickets in the cart, when the cart has been edited
690
+	 * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
+	 * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
+	 *
693
+	 * @deprecated
694
+	 * @since 4.9.1
695
+	 * @param EE_Line_Item    $line_item
696
+	 * @param \EE_Transaction $transaction
697
+	 * @param int             $att_nmbr
698
+	 * @param int             $total_ticket_count
699
+	 * @return EE_Registration | null
700
+	 * @throws \OutOfRangeException
701
+	 * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
+	 * @throws \EE_Error
703
+	 */
704
+	public function generate_ONE_registration_from_line_item(
705
+		EE_Line_Item $line_item,
706
+		EE_Transaction $transaction,
707
+		$att_nmbr = 1,
708
+		$total_ticket_count = 1
709
+	) {
710
+		EE_Error::doing_it_wrong(
711
+			__CLASS__ . '::' . __FUNCTION__,
712
+			sprintf(
713
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
+				'\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
+			),
716
+			'4.9.1',
717
+			'5.0.0'
718
+		);
719
+		// grab the related ticket object for this line_item
720
+		$ticket = $line_item->ticket();
721
+		if (! $ticket instanceof EE_Ticket) {
722
+			EE_Error::add_error(
723
+				sprintf(
724
+					esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
+					$line_item->ID()
726
+				),
727
+				__FILE__,
728
+				__FUNCTION__,
729
+				__LINE__
730
+			);
731
+			return null;
732
+		}
733
+		$registration_service = new CreateRegistrationService();
734
+		// then generate a new registration from that
735
+		return $registration_service->create(
736
+			$ticket->get_related_event(),
737
+			$transaction,
738
+			$ticket,
739
+			$line_item,
740
+			$att_nmbr,
741
+			$total_ticket_count
742
+		);
743
+	}
744
+
745
+
746
+
747
+	/**
748
+	 * generates reg_url_link
749
+	 *
750
+	 * @deprecated
751
+	 * @since 4.9.1
752
+	 * @param int                   $att_nmbr
753
+	 * @param EE_Line_Item | string $item
754
+	 * @return string
755
+	 * @throws InvalidArgumentException
756
+	 */
757
+	public function generate_reg_url_link($att_nmbr, $item)
758
+	{
759
+		EE_Error::doing_it_wrong(
760
+			__CLASS__ . '::' . __FUNCTION__,
761
+			sprintf(
762
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
+				'EventEspresso\core\domain\entities\RegUrlLink'
764
+			),
765
+			'4.9.1',
766
+			'5.0.0'
767
+		);
768
+		return new RegUrlLink($att_nmbr, $item);
769
+	}
770
+
771
+
772
+
773
+	/**
774
+	 * generates reg code
775
+	 *
776
+	 * @deprecated
777
+	 * @since 4.9.1
778
+	 * @param EE_Registration $registration
779
+	 * @return string
780
+	 * @throws EE_Error
781
+	 * @throws EntityNotFoundException
782
+	 * @throws InvalidArgumentException
783
+	 */
784
+	public function generate_reg_code(EE_Registration $registration)
785
+	{
786
+		EE_Error::doing_it_wrong(
787
+			__CLASS__ . '::' . __FUNCTION__,
788
+			sprintf(
789
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
+				'EventEspresso\core\domain\entities\RegCode'
791
+			),
792
+			'4.9.1',
793
+			'5.0.0'
794
+		);
795
+		return apply_filters(
796
+			'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
+			new RegCode(
798
+				RegUrlLink::fromRegistration($registration),
799
+				$registration->transaction(),
800
+				$registration->ticket()
801
+			),
802
+			$registration
803
+		);
804
+	}
805 805
 
806 806
 
807 807
 
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -83,8 +83,8 @@  discard block
 block discarded – undo
83 83
     public static function instance(EE_Request $request = null)
84 84
     {
85 85
         // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
86
+        if ( ! self::$_instance instanceof EE_Registration_Processor) {
87
+            if ( ! $request instanceof EE_Request) {
88 88
                 $request = LoaderFactory::getLoader()->getShared('EE_Request');
89 89
             }
90 90
             self::$_instance = new self($request);
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
     public function set_old_reg_status($REG_ID, $old_reg_status)
124 124
     {
125 125
         // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
126
+        if ( ! isset($this->_old_reg_status[$REG_ID])) {
127 127
             $this->_old_reg_status[$REG_ID] = $old_reg_status;
128 128
         }
129 129
     }
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
         if (
218 218
             $this->reg_status_updated($registration->ID())
219 219
             && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
220
+                ( ! $this->request->isAdmin() || $this->request->isFrontAjax())
221 221
                 || EE_Registry::instance()->CAP->current_user_can(
222 222
                     'ee_edit_registration',
223 223
                     'toggle_registration_status',
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
                 $registration->save();
282 282
             }
283 283
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
284
+            if ( ! EE_Processor_Base::$IPN) {
285 285
                 // otherwise, send out notifications
286 286
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287 287
             }
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
                 $registration->save();
338 338
             }
339 339
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
340
+            if ( ! EE_Processor_Base::$IPN) {
341 341
                 // otherwise, send out notifications
342 342
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343 343
             }
@@ -382,7 +382,7 @@  discard block
 block discarded – undo
382 382
         // set initial REG_Status
383 383
         $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384 384
         // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
385
+        $payment = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386 386
                       && $additional_details['payment_updates']
387 387
                       && $additional_details['last_payment'] instanceof EE_Payment
388 388
             ? $additional_details['last_payment']
@@ -423,7 +423,7 @@  discard block
 block discarded – undo
423 423
                 $registration->save();
424 424
             }
425 425
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
426
+            if ( ! EE_Processor_Base::$IPN) {
427 427
                 // otherwise, send out notifications
428 428
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429 429
             }
@@ -454,7 +454,7 @@  discard block
 block discarded – undo
454 454
     public function trigger_registration_update_notifications($registration, array $additional_details = array())
455 455
     {
456 456
         try {
457
-            if (! $registration instanceof EE_Registration) {
457
+            if ( ! $registration instanceof EE_Registration) {
458 458
                 throw new EE_Error(
459 459
                     esc_html__('An invalid registration was received.', 'event_espresso')
460 460
                 );
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
             // 	false,
469 469
             // 	'EE_Transaction: ' . $registration->transaction()->ID()
470 470
             // );
471
-            if (! $registration->is_primary_registrant()) {
471
+            if ( ! $registration->is_primary_registrant()) {
472 472
                 return;
473 473
             }
474 474
             do_action(
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
         $diff = $transaction->total() - $reg_final_price_sum;
588 588
         //ok then, just grab one of the registrations
589 589
         if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
590
+            $a_reg = EEM_Registration::instance()->get_one(
591 591
                 array(
592 592
                     array(
593 593
                         'TXN_ID' => $transaction->ID(),
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
         $closed_reg_statuses = ! empty($closed_reg_statuses)
623 623
             ? $closed_reg_statuses
624 624
             : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
625
+        if ( ! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626 626
             return false;
627 627
         }
628 628
         // release a reserved ticket by decrementing ticket and datetime reserved values
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
             return false;
659 659
         }
660 660
         $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
661
+        if ( ! $ticket instanceof EE_Ticket) {
662 662
             throw new EE_Error(
663 663
                 sprintf(
664 664
                     esc_html__(
@@ -708,7 +708,7 @@  discard block
 block discarded – undo
708 708
         $total_ticket_count = 1
709 709
     ) {
710 710
         EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
711
+            __CLASS__.'::'.__FUNCTION__,
712 712
             sprintf(
713 713
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714 714
                 '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
         );
719 719
         // grab the related ticket object for this line_item
720 720
         $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
721
+        if ( ! $ticket instanceof EE_Ticket) {
722 722
             EE_Error::add_error(
723 723
                 sprintf(
724 724
                     esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
@@ -757,7 +757,7 @@  discard block
 block discarded – undo
757 757
     public function generate_reg_url_link($att_nmbr, $item)
758 758
     {
759 759
         EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
760
+            __CLASS__.'::'.__FUNCTION__,
761 761
             sprintf(
762 762
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763 763
                 'EventEspresso\core\domain\entities\RegUrlLink'
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
     public function generate_reg_code(EE_Registration $registration)
785 785
     {
786 786
         EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
787
+            __CLASS__.'::'.__FUNCTION__,
788 788
             sprintf(
789 789
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790 790
                 'EventEspresso\core\domain\entities\RegCode'
Please login to merge, or discard this patch.
core/services/cache/PostRelatedCacheManager.php 2 patches
Indentation   +120 added lines, -120 removed lines patch added patch discarded remove patch
@@ -17,126 +17,126 @@
 block discarded – undo
17 17
 class PostRelatedCacheManager extends BasicCacheManager
18 18
 {
19 19
 
20
-    /**
21
-     * @type string
22
-     */
23
-    const POST_CACHE_PREFIX = 'ee_cache_post_';
24
-
25
-    /**
26
-     * wp-option option_name for tracking post related cache
27
-     *
28
-     * @type string
29
-     */
30
-    const POST_CACHE_OPTIONS_KEY = 'ee_post_cache';
31
-
32
-
33
-
34
-    /**
35
-     * PostRelatedCacheManager constructor.
36
-     *
37
-     * @param CacheStorageInterface      $cache_storage
38
-     */
39
-    public function __construct(CacheStorageInterface $cache_storage)
40
-    {
41
-        parent::__construct($cache_storage);
42
-        add_action('save_post', array($this, 'clearPostRelatedCache'));
43
-    }
44
-
45
-
46
-
47
-    /**
48
-     * returns a string that will be prepended to all cache identifiers
49
-     *
50
-     * @return string
51
-     */
52
-    public function cachePrefix()
53
-    {
54
-        return PostRelatedCacheManager::POST_CACHE_PREFIX;
55
-    }
56
-
57
-
58
-    /**
59
-     * @return array
60
-     */
61
-    protected function getPostRelatedCache()
62
-    {
63
-        $post_related_cache = get_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, array());
64
-        // verify that cached data was not truncated or corrupted and no longer an array
65
-        if (! is_array($post_related_cache))  {
66
-            // uh-oh... let's get rid of any transients using our cache prefix
67
-            $this->clear(PostRelatedCacheManager::CACHE_PREFIX);
68
-            // then update the post related cache tracking option
69
-            $post_related_cache = array();
70
-            $this->updatePostRelatedCache($post_related_cache);
71
-        }
72
-        return $post_related_cache;
73
-    }
74
-
75
-
76
-    /**
77
-     * @param array $post_related_cache
78
-     */
79
-    protected function updatePostRelatedCache(array $post_related_cache = array())
80
-    {
81
-        update_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, $post_related_cache);
82
-    }
83
-
84
-
85
-    /**
86
-     * If you are caching content that pertains to a Post of any type,
87
-     * then it is recommended to pass the post id and cache id prefix to this method
88
-     * so that it can be added to the post related cache tracking.
89
-     * Then, whenever that post is updated, the cache will automatically be deleted,
90
-     * which helps to ensure that outdated cache content will not be served
91
-     *
92
-     * @param int    $post_ID    [required]
93
-     * @param string $id_prefix  [required] Appended to all cache IDs. Can be helpful in finding specific cache types.
94
-     *                           May also be helpful to include an additional specific identifier,
95
-     *                           such as a post ID as part of the $id_prefix so that individual caches
96
-     *                           can be found and/or cleared. ex: "venue-28", or "shortcode-156".
97
-     *                           BasicCacheManager::CACHE_PREFIX will also be prepended to the cache id.
98
-     */
99
-    public function clearPostRelatedCacheOnUpdate($post_ID, $id_prefix)
100
-    {
101
-        $post_related_cache = $this->getPostRelatedCache();
102
-        // if post is not already being tracked
103
-        if ( ! isset($post_related_cache[$post_ID])) {
104
-            // add array to add cache ids to
105
-            $post_related_cache[$post_ID] = array();
106
-        }
107
-        if( ! in_array($id_prefix, $post_related_cache[$post_ID], true)) {
108
-            // add cache id to be tracked
109
-            $post_related_cache[$post_ID][] = $id_prefix;
110
-            $this->updatePostRelatedCache($post_related_cache);
111
-        }
112
-    }
113
-
114
-
115
-
116
-    /**
117
-     * callback hooked into the WordPress "save_post" action
118
-     * deletes any cache content associated with the post
119
-     *
120
-     * @param int $post_ID [required]
121
-     */
122
-    public function clearPostRelatedCache($post_ID)
123
-    {
124
-        $post_related_cache = $this->getPostRelatedCache();
125
-        // if post is not being tracked
126
-        if ( ! isset($post_related_cache[$post_ID])) {
127
-            // let's clean up some of the duplicate IDs that were getting added
128
-            foreach ($post_related_cache as $other_post_ID => $cache_IDs) {
129
-                //remove duplicates
130
-                $post_related_cache[$other_post_ID] = array_unique($post_related_cache[$other_post_ID]);
131
-            }
132
-            $this->updatePostRelatedCache($post_related_cache);
133
-            return;
134
-        }
135
-        // get cache id prefixes for post, and delete their corresponding transients
136
-        $this->clear($post_related_cache[$post_ID]);
137
-        unset($post_related_cache[$post_ID]);
138
-        $this->updatePostRelatedCache($post_related_cache);
139
-    }
20
+	/**
21
+	 * @type string
22
+	 */
23
+	const POST_CACHE_PREFIX = 'ee_cache_post_';
24
+
25
+	/**
26
+	 * wp-option option_name for tracking post related cache
27
+	 *
28
+	 * @type string
29
+	 */
30
+	const POST_CACHE_OPTIONS_KEY = 'ee_post_cache';
31
+
32
+
33
+
34
+	/**
35
+	 * PostRelatedCacheManager constructor.
36
+	 *
37
+	 * @param CacheStorageInterface      $cache_storage
38
+	 */
39
+	public function __construct(CacheStorageInterface $cache_storage)
40
+	{
41
+		parent::__construct($cache_storage);
42
+		add_action('save_post', array($this, 'clearPostRelatedCache'));
43
+	}
44
+
45
+
46
+
47
+	/**
48
+	 * returns a string that will be prepended to all cache identifiers
49
+	 *
50
+	 * @return string
51
+	 */
52
+	public function cachePrefix()
53
+	{
54
+		return PostRelatedCacheManager::POST_CACHE_PREFIX;
55
+	}
56
+
57
+
58
+	/**
59
+	 * @return array
60
+	 */
61
+	protected function getPostRelatedCache()
62
+	{
63
+		$post_related_cache = get_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, array());
64
+		// verify that cached data was not truncated or corrupted and no longer an array
65
+		if (! is_array($post_related_cache))  {
66
+			// uh-oh... let's get rid of any transients using our cache prefix
67
+			$this->clear(PostRelatedCacheManager::CACHE_PREFIX);
68
+			// then update the post related cache tracking option
69
+			$post_related_cache = array();
70
+			$this->updatePostRelatedCache($post_related_cache);
71
+		}
72
+		return $post_related_cache;
73
+	}
74
+
75
+
76
+	/**
77
+	 * @param array $post_related_cache
78
+	 */
79
+	protected function updatePostRelatedCache(array $post_related_cache = array())
80
+	{
81
+		update_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, $post_related_cache);
82
+	}
83
+
84
+
85
+	/**
86
+	 * If you are caching content that pertains to a Post of any type,
87
+	 * then it is recommended to pass the post id and cache id prefix to this method
88
+	 * so that it can be added to the post related cache tracking.
89
+	 * Then, whenever that post is updated, the cache will automatically be deleted,
90
+	 * which helps to ensure that outdated cache content will not be served
91
+	 *
92
+	 * @param int    $post_ID    [required]
93
+	 * @param string $id_prefix  [required] Appended to all cache IDs. Can be helpful in finding specific cache types.
94
+	 *                           May also be helpful to include an additional specific identifier,
95
+	 *                           such as a post ID as part of the $id_prefix so that individual caches
96
+	 *                           can be found and/or cleared. ex: "venue-28", or "shortcode-156".
97
+	 *                           BasicCacheManager::CACHE_PREFIX will also be prepended to the cache id.
98
+	 */
99
+	public function clearPostRelatedCacheOnUpdate($post_ID, $id_prefix)
100
+	{
101
+		$post_related_cache = $this->getPostRelatedCache();
102
+		// if post is not already being tracked
103
+		if ( ! isset($post_related_cache[$post_ID])) {
104
+			// add array to add cache ids to
105
+			$post_related_cache[$post_ID] = array();
106
+		}
107
+		if( ! in_array($id_prefix, $post_related_cache[$post_ID], true)) {
108
+			// add cache id to be tracked
109
+			$post_related_cache[$post_ID][] = $id_prefix;
110
+			$this->updatePostRelatedCache($post_related_cache);
111
+		}
112
+	}
113
+
114
+
115
+
116
+	/**
117
+	 * callback hooked into the WordPress "save_post" action
118
+	 * deletes any cache content associated with the post
119
+	 *
120
+	 * @param int $post_ID [required]
121
+	 */
122
+	public function clearPostRelatedCache($post_ID)
123
+	{
124
+		$post_related_cache = $this->getPostRelatedCache();
125
+		// if post is not being tracked
126
+		if ( ! isset($post_related_cache[$post_ID])) {
127
+			// let's clean up some of the duplicate IDs that were getting added
128
+			foreach ($post_related_cache as $other_post_ID => $cache_IDs) {
129
+				//remove duplicates
130
+				$post_related_cache[$other_post_ID] = array_unique($post_related_cache[$other_post_ID]);
131
+			}
132
+			$this->updatePostRelatedCache($post_related_cache);
133
+			return;
134
+		}
135
+		// get cache id prefixes for post, and delete their corresponding transients
136
+		$this->clear($post_related_cache[$post_ID]);
137
+		unset($post_related_cache[$post_ID]);
138
+		$this->updatePostRelatedCache($post_related_cache);
139
+	}
140 140
 
141 141
 
142 142
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
     {
63 63
         $post_related_cache = get_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, array());
64 64
         // verify that cached data was not truncated or corrupted and no longer an array
65
-        if (! is_array($post_related_cache))  {
65
+        if ( ! is_array($post_related_cache)) {
66 66
             // uh-oh... let's get rid of any transients using our cache prefix
67 67
             $this->clear(PostRelatedCacheManager::CACHE_PREFIX);
68 68
             // then update the post related cache tracking option
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
             // add array to add cache ids to
105 105
             $post_related_cache[$post_ID] = array();
106 106
         }
107
-        if( ! in_array($id_prefix, $post_related_cache[$post_ID], true)) {
107
+        if ( ! in_array($id_prefix, $post_related_cache[$post_ID], true)) {
108 108
             // add cache id to be tracked
109 109
             $post_related_cache[$post_ID][] = $id_prefix;
110 110
             $this->updatePostRelatedCache($post_related_cache);
Please login to merge, or discard this patch.
core/services/cache/TransientCacheStorage.php 1 patch
Indentation   +355 added lines, -355 removed lines patch added patch discarded remove patch
@@ -19,361 +19,361 @@
 block discarded – undo
19 19
 class TransientCacheStorage implements CacheStorageInterface
20 20
 {
21 21
 
22
-    /**
23
-     * wp-option option_name for tracking transients
24
-     *
25
-     * @type string
26
-     */
27
-    const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
28
-
29
-    /**
30
-     * @var int $current_time
31
-     */
32
-    private $current_time;
33
-
34
-    /**
35
-     * how often to perform transient cleanup
36
-     *
37
-     * @var string $transient_cleanup_frequency
38
-     */
39
-    private $transient_cleanup_frequency;
40
-
41
-    /**
42
-     * options for how often to perform transient cleanup
43
-     *
44
-     * @var array $transient_cleanup_frequency_options
45
-     */
46
-    private $transient_cleanup_frequency_options = array();
47
-
48
-    /**
49
-     * @var array $transients
50
-     */
51
-    private $transients;
52
-
53
-
54
-
55
-    /**
56
-     * TransientCacheStorage constructor.
57
-     */
58
-    public function __construct()
59
-    {
60
-        $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
61
-        // round current time down to closest 5 minutes to simplify scheduling
62
-        $this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
63
-        $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
64
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
65
-            add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
66
-        }
67
-    }
68
-
69
-
70
-
71
-    /**
72
-     * Sets how often transient cleanup occurs
73
-     *
74
-     * @return string
75
-     */
76
-    private function setTransientCleanupFrequency()
77
-    {
78
-        // sets how often transients are cleaned up
79
-        $this->transient_cleanup_frequency_options = apply_filters(
80
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
81
-            array(
82
-                'off',
83
-                '15-minutes',
84
-                'hour',
85
-                '12-hours',
86
-                'day',
87
-            )
88
-        );
89
-        $transient_cleanup_frequency = apply_filters(
90
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule',
91
-            'hour'
92
-        );
93
-        return in_array(
94
-            $transient_cleanup_frequency,
95
-            $this->transient_cleanup_frequency_options,
96
-            true
97
-        )
98
-            ? $transient_cleanup_frequency
99
-            : 'hour';
100
-    }
101
-
102
-
103
-
104
-    /**
105
-     * we need to be able to round timestamps off to match the set transient cleanup frequency
106
-     * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
107
-     * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
108
-     * during the next scheduled cleanup after its expiration.
109
-     * We also round off the current time timestamp to the closest 5 minutes
110
-     * just to make the timestamps a little easier to round which helps with debugging.
111
-     *
112
-     * @param int    $timestamp [required]
113
-     * @param string $cleanup_frequency
114
-     * @param bool   $round_up
115
-     * @return int
116
-     */
117
-    private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
118
-    {
119
-        $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
120
-        // in order to round the time to the closest xx minutes (or hours),
121
-        // we take the minutes (or hours) portion of the timestamp and divide it by xx,
122
-        // round down to a whole number, then multiply by xx to bring us almost back up to where we were
123
-        // why round down ? so the minutes (or hours) don't go over 60 (or 24)
124
-        // and bump the hour, which could bump the day, which could bump the month, etc,
125
-        // which would be bad because we don't always want to round up,
126
-        // but when we do we can easily achieve that by simply adding the desired offset,
127
-        $minutes = '00';
128
-        $hours = 'H';
129
-        switch ($cleanup_frequency) {
130
-            case '5-minutes' :
131
-                $minutes = floor((int)date('i', $timestamp) / 5) * 5;
132
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
133
-                $offset = MINUTE_IN_SECONDS * 5;
134
-                break;
135
-            case '15-minutes' :
136
-                $minutes = floor((int)date('i', $timestamp) / 15) * 15;
137
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
138
-                $offset = MINUTE_IN_SECONDS * 15;
139
-                break;
140
-            case '12-hours' :
141
-                $hours = floor((int)date('H', $timestamp) / 12) * 12;
142
-                $hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
143
-                $offset = HOUR_IN_SECONDS * 12;
144
-                break;
145
-            case 'day' :
146
-                $hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
147
-                $offset = DAY_IN_SECONDS;
148
-                break;
149
-            case 'hour' :
150
-            default :
151
-                $offset = HOUR_IN_SECONDS;
152
-                break;
153
-        }
154
-        $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
155
-        $rounded_timestamp += $round_up ? $offset : 0;
156
-        return apply_filters(
157
-            'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
158
-            $rounded_timestamp,
159
-            $timestamp,
160
-            $cleanup_frequency,
161
-            $round_up
162
-        );
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * Saves supplied data to a transient
169
-     * if an expiration is set, then it automatically schedules the transient for cleanup
170
-     *
171
-     * @param string $transient_key [required]
172
-     * @param string $data          [required]
173
-     * @param int    $expiration    number of seconds until the cache expires
174
-     * @return bool
175
-     */
176
-    public function add($transient_key, $data, $expiration = 0)
177
-    {
178
-        $expiration = (int)abs($expiration);
179
-        $saved = set_transient($transient_key, $data, $expiration);
180
-        if ($saved && $expiration) {
181
-            $this->scheduleTransientCleanup($transient_key, $expiration);
182
-        }
183
-        return $saved;
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * retrieves transient data
190
-     * automatically triggers early cache refresh for standard cache items
191
-     * in order to avoid cache stampedes on busy sites.
192
-     * For non-standard cache items like PHP Session data where early refreshing is not wanted,
193
-     * the $standard_cache parameter should be set to false when retrieving data
194
-     *
195
-     * @param string $transient_key [required]
196
-     * @param bool   $standard_cache
197
-     * @return mixed|null
198
-     */
199
-    public function get($transient_key, $standard_cache = true)
200
-    {
201
-        // to avoid cache stampedes (AKA:dogpiles) for standard cache items,
202
-        // check if known cache expires within the next minute,
203
-        // and if so, remove it from our tracking and and return nothing.
204
-        // this should trigger the cache content to be regenerated during this request,
205
-        // while allowing any following requests to still access the existing cache
206
-        // until it gets replaced with the refreshed content
207
-        if (
208
-            $standard_cache
209
-            && isset($this->transients[$transient_key])
210
-            && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS
211
-        ) {
212
-            unset($this->transients[$transient_key]);
213
-            $this->updateTransients();
214
-            return null;
215
-        }
216
-        $content = get_transient($transient_key);
217
-        return $content !== false ? $content : null;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * delete a single transient and remove tracking
224
-     *
225
-     * @param string $transient_key [required] full or partial transient key to be deleted
226
-     */
227
-    public function delete($transient_key)
228
-    {
229
-        $this->deleteMany(array($transient_key));
230
-    }
231
-
232
-
233
-
234
-    /**
235
-     * delete multiple transients and remove tracking
236
-     *
237
-     * @param array $transient_keys [required] array of full or partial transient keys to be deleted
238
-     */
239
-    public function deleteMany(array $transient_keys)
240
-    {
241
-        $full_transient_keys = array();
242
-        foreach ($this->transients as $transient_key => $expiration) {
243
-            foreach ($transient_keys as $transient_key_to_delete) {
244
-                if (strpos($transient_key, $transient_key_to_delete) !== false) {
245
-                    $full_transient_keys[] = $transient_key;
246
-                }
247
-            }
248
-        }
249
-        if ($this->deleteTransientKeys($full_transient_keys)) {
250
-            $this->updateTransients();
251
-        }
252
-    }
253
-
254
-
255
-
256
-    /**
257
-     * sorts transients numerically by timestamp
258
-     * then saves the transient schedule to a WP option
259
-     */
260
-    private function updateTransients()
261
-    {
262
-        asort($this->transients, SORT_NUMERIC);
263
-        update_option(
264
-            TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
265
-            $this->transients
266
-        );
267
-    }
268
-
269
-
270
-
271
-    /**
272
-     * schedules a transient for cleanup by adding it to the transient tracking
273
-     *
274
-     * @param string $transient_key [required]
275
-     * @param int    $expiration    [required]
276
-     */
277
-    private function scheduleTransientCleanup($transient_key, $expiration)
278
-    {
279
-        // make sure a valid future timestamp is set
280
-        $expiration += $expiration < time() ? time() : 0;
281
-        // and round to the closest 15 minutes
282
-        $expiration = $this->roundTimestamp($expiration);
283
-        // save transients to clear using their ID as the key to avoid duplicates
284
-        $this->transients[$transient_key] = $expiration;
285
-        $this->updateTransients();
286
-    }
287
-
288
-
289
-
290
-    /**
291
-     * Since our tracked transients are sorted by their timestamps
292
-     * we can grab the first transient and see when it is scheduled for cleanup.
293
-     * If that timestamp is less than or equal to the current time,
294
-     * then cleanup is triggered
295
-     */
296
-    public function checkTransientCleanupSchedule()
297
-    {
298
-        if (empty($this->transients)) {
299
-            return;
300
-        }
301
-        // when do we run the next cleanup job?
302
-        reset($this->transients);
303
-        $next_scheduled_cleanup = current($this->transients);
304
-        // if the next cleanup job is scheduled for the current hour
305
-        if ($next_scheduled_cleanup <= $this->current_time) {
306
-            if ($this->cleanupExpiredTransients()) {
307
-                $this->updateTransients();
308
-            }
309
-        }
310
-    }
311
-
312
-
313
-
314
-    /**
315
-     * loops through the array of tracked transients,
316
-     * compiles a list of those that have expired, and sends that list off for deletion.
317
-     * Also removes any bad records from the transients array
318
-     *
319
-     * @return bool
320
-     */
321
-    private function cleanupExpiredTransients()
322
-    {
323
-        $update = false;
324
-        // filter the query limit. Set to 0 to turn off garbage collection
325
-        $limit = (int)abs(
326
-            apply_filters(
327
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
328
-                50
329
-            )
330
-        );
331
-        // non-zero LIMIT means take out the trash
332
-        if ($limit) {
333
-            $transient_keys = array();
334
-            foreach ($this->transients as $transient_key => $expiration) {
335
-                if ($expiration > $this->current_time) {
336
-                    continue;
337
-                }
338
-                if ( ! $expiration || ! $transient_key) {
339
-                    unset($this->transients[$transient_key]);
340
-                    $update = true;
341
-                    continue;
342
-                }
343
-                $transient_keys[] = $transient_key;
344
-            }
345
-            // delete expired keys, but maintain value of $update if nothing is deleted
346
-            $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
347
-            do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
348
-        }
349
-        return $update;
350
-    }
351
-
352
-
353
-
354
-    /**
355
-     * calls delete_transient() on each transient key provided, up to the specified limit
356
-     *
357
-     * @param array $transient_keys [required]
358
-     * @param int   $limit
359
-     * @return bool
360
-     */
361
-    private function deleteTransientKeys(array $transient_keys, $limit = 50)
362
-    {
363
-        if (empty($transient_keys)) {
364
-            return false;
365
-        }
366
-        $counter = 0;
367
-        foreach ($transient_keys as $transient_key) {
368
-            if($counter === $limit){
369
-                break;
370
-            }
371
-            delete_transient($transient_key);
372
-            unset($this->transients[$transient_key]);
373
-            $counter++;
374
-        }
375
-        return $counter > 0;
376
-    }
22
+	/**
23
+	 * wp-option option_name for tracking transients
24
+	 *
25
+	 * @type string
26
+	 */
27
+	const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
28
+
29
+	/**
30
+	 * @var int $current_time
31
+	 */
32
+	private $current_time;
33
+
34
+	/**
35
+	 * how often to perform transient cleanup
36
+	 *
37
+	 * @var string $transient_cleanup_frequency
38
+	 */
39
+	private $transient_cleanup_frequency;
40
+
41
+	/**
42
+	 * options for how often to perform transient cleanup
43
+	 *
44
+	 * @var array $transient_cleanup_frequency_options
45
+	 */
46
+	private $transient_cleanup_frequency_options = array();
47
+
48
+	/**
49
+	 * @var array $transients
50
+	 */
51
+	private $transients;
52
+
53
+
54
+
55
+	/**
56
+	 * TransientCacheStorage constructor.
57
+	 */
58
+	public function __construct()
59
+	{
60
+		$this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
61
+		// round current time down to closest 5 minutes to simplify scheduling
62
+		$this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
63
+		$this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
64
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
65
+			add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
66
+		}
67
+	}
68
+
69
+
70
+
71
+	/**
72
+	 * Sets how often transient cleanup occurs
73
+	 *
74
+	 * @return string
75
+	 */
76
+	private function setTransientCleanupFrequency()
77
+	{
78
+		// sets how often transients are cleaned up
79
+		$this->transient_cleanup_frequency_options = apply_filters(
80
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
81
+			array(
82
+				'off',
83
+				'15-minutes',
84
+				'hour',
85
+				'12-hours',
86
+				'day',
87
+			)
88
+		);
89
+		$transient_cleanup_frequency = apply_filters(
90
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule',
91
+			'hour'
92
+		);
93
+		return in_array(
94
+			$transient_cleanup_frequency,
95
+			$this->transient_cleanup_frequency_options,
96
+			true
97
+		)
98
+			? $transient_cleanup_frequency
99
+			: 'hour';
100
+	}
101
+
102
+
103
+
104
+	/**
105
+	 * we need to be able to round timestamps off to match the set transient cleanup frequency
106
+	 * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
107
+	 * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
108
+	 * during the next scheduled cleanup after its expiration.
109
+	 * We also round off the current time timestamp to the closest 5 minutes
110
+	 * just to make the timestamps a little easier to round which helps with debugging.
111
+	 *
112
+	 * @param int    $timestamp [required]
113
+	 * @param string $cleanup_frequency
114
+	 * @param bool   $round_up
115
+	 * @return int
116
+	 */
117
+	private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
118
+	{
119
+		$cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
120
+		// in order to round the time to the closest xx minutes (or hours),
121
+		// we take the minutes (or hours) portion of the timestamp and divide it by xx,
122
+		// round down to a whole number, then multiply by xx to bring us almost back up to where we were
123
+		// why round down ? so the minutes (or hours) don't go over 60 (or 24)
124
+		// and bump the hour, which could bump the day, which could bump the month, etc,
125
+		// which would be bad because we don't always want to round up,
126
+		// but when we do we can easily achieve that by simply adding the desired offset,
127
+		$minutes = '00';
128
+		$hours = 'H';
129
+		switch ($cleanup_frequency) {
130
+			case '5-minutes' :
131
+				$minutes = floor((int)date('i', $timestamp) / 5) * 5;
132
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
133
+				$offset = MINUTE_IN_SECONDS * 5;
134
+				break;
135
+			case '15-minutes' :
136
+				$minutes = floor((int)date('i', $timestamp) / 15) * 15;
137
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
138
+				$offset = MINUTE_IN_SECONDS * 15;
139
+				break;
140
+			case '12-hours' :
141
+				$hours = floor((int)date('H', $timestamp) / 12) * 12;
142
+				$hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
143
+				$offset = HOUR_IN_SECONDS * 12;
144
+				break;
145
+			case 'day' :
146
+				$hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
147
+				$offset = DAY_IN_SECONDS;
148
+				break;
149
+			case 'hour' :
150
+			default :
151
+				$offset = HOUR_IN_SECONDS;
152
+				break;
153
+		}
154
+		$rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
155
+		$rounded_timestamp += $round_up ? $offset : 0;
156
+		return apply_filters(
157
+			'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
158
+			$rounded_timestamp,
159
+			$timestamp,
160
+			$cleanup_frequency,
161
+			$round_up
162
+		);
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * Saves supplied data to a transient
169
+	 * if an expiration is set, then it automatically schedules the transient for cleanup
170
+	 *
171
+	 * @param string $transient_key [required]
172
+	 * @param string $data          [required]
173
+	 * @param int    $expiration    number of seconds until the cache expires
174
+	 * @return bool
175
+	 */
176
+	public function add($transient_key, $data, $expiration = 0)
177
+	{
178
+		$expiration = (int)abs($expiration);
179
+		$saved = set_transient($transient_key, $data, $expiration);
180
+		if ($saved && $expiration) {
181
+			$this->scheduleTransientCleanup($transient_key, $expiration);
182
+		}
183
+		return $saved;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * retrieves transient data
190
+	 * automatically triggers early cache refresh for standard cache items
191
+	 * in order to avoid cache stampedes on busy sites.
192
+	 * For non-standard cache items like PHP Session data where early refreshing is not wanted,
193
+	 * the $standard_cache parameter should be set to false when retrieving data
194
+	 *
195
+	 * @param string $transient_key [required]
196
+	 * @param bool   $standard_cache
197
+	 * @return mixed|null
198
+	 */
199
+	public function get($transient_key, $standard_cache = true)
200
+	{
201
+		// to avoid cache stampedes (AKA:dogpiles) for standard cache items,
202
+		// check if known cache expires within the next minute,
203
+		// and if so, remove it from our tracking and and return nothing.
204
+		// this should trigger the cache content to be regenerated during this request,
205
+		// while allowing any following requests to still access the existing cache
206
+		// until it gets replaced with the refreshed content
207
+		if (
208
+			$standard_cache
209
+			&& isset($this->transients[$transient_key])
210
+			&& $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS
211
+		) {
212
+			unset($this->transients[$transient_key]);
213
+			$this->updateTransients();
214
+			return null;
215
+		}
216
+		$content = get_transient($transient_key);
217
+		return $content !== false ? $content : null;
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * delete a single transient and remove tracking
224
+	 *
225
+	 * @param string $transient_key [required] full or partial transient key to be deleted
226
+	 */
227
+	public function delete($transient_key)
228
+	{
229
+		$this->deleteMany(array($transient_key));
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * delete multiple transients and remove tracking
236
+	 *
237
+	 * @param array $transient_keys [required] array of full or partial transient keys to be deleted
238
+	 */
239
+	public function deleteMany(array $transient_keys)
240
+	{
241
+		$full_transient_keys = array();
242
+		foreach ($this->transients as $transient_key => $expiration) {
243
+			foreach ($transient_keys as $transient_key_to_delete) {
244
+				if (strpos($transient_key, $transient_key_to_delete) !== false) {
245
+					$full_transient_keys[] = $transient_key;
246
+				}
247
+			}
248
+		}
249
+		if ($this->deleteTransientKeys($full_transient_keys)) {
250
+			$this->updateTransients();
251
+		}
252
+	}
253
+
254
+
255
+
256
+	/**
257
+	 * sorts transients numerically by timestamp
258
+	 * then saves the transient schedule to a WP option
259
+	 */
260
+	private function updateTransients()
261
+	{
262
+		asort($this->transients, SORT_NUMERIC);
263
+		update_option(
264
+			TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
265
+			$this->transients
266
+		);
267
+	}
268
+
269
+
270
+
271
+	/**
272
+	 * schedules a transient for cleanup by adding it to the transient tracking
273
+	 *
274
+	 * @param string $transient_key [required]
275
+	 * @param int    $expiration    [required]
276
+	 */
277
+	private function scheduleTransientCleanup($transient_key, $expiration)
278
+	{
279
+		// make sure a valid future timestamp is set
280
+		$expiration += $expiration < time() ? time() : 0;
281
+		// and round to the closest 15 minutes
282
+		$expiration = $this->roundTimestamp($expiration);
283
+		// save transients to clear using their ID as the key to avoid duplicates
284
+		$this->transients[$transient_key] = $expiration;
285
+		$this->updateTransients();
286
+	}
287
+
288
+
289
+
290
+	/**
291
+	 * Since our tracked transients are sorted by their timestamps
292
+	 * we can grab the first transient and see when it is scheduled for cleanup.
293
+	 * If that timestamp is less than or equal to the current time,
294
+	 * then cleanup is triggered
295
+	 */
296
+	public function checkTransientCleanupSchedule()
297
+	{
298
+		if (empty($this->transients)) {
299
+			return;
300
+		}
301
+		// when do we run the next cleanup job?
302
+		reset($this->transients);
303
+		$next_scheduled_cleanup = current($this->transients);
304
+		// if the next cleanup job is scheduled for the current hour
305
+		if ($next_scheduled_cleanup <= $this->current_time) {
306
+			if ($this->cleanupExpiredTransients()) {
307
+				$this->updateTransients();
308
+			}
309
+		}
310
+	}
311
+
312
+
313
+
314
+	/**
315
+	 * loops through the array of tracked transients,
316
+	 * compiles a list of those that have expired, and sends that list off for deletion.
317
+	 * Also removes any bad records from the transients array
318
+	 *
319
+	 * @return bool
320
+	 */
321
+	private function cleanupExpiredTransients()
322
+	{
323
+		$update = false;
324
+		// filter the query limit. Set to 0 to turn off garbage collection
325
+		$limit = (int)abs(
326
+			apply_filters(
327
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
328
+				50
329
+			)
330
+		);
331
+		// non-zero LIMIT means take out the trash
332
+		if ($limit) {
333
+			$transient_keys = array();
334
+			foreach ($this->transients as $transient_key => $expiration) {
335
+				if ($expiration > $this->current_time) {
336
+					continue;
337
+				}
338
+				if ( ! $expiration || ! $transient_key) {
339
+					unset($this->transients[$transient_key]);
340
+					$update = true;
341
+					continue;
342
+				}
343
+				$transient_keys[] = $transient_key;
344
+			}
345
+			// delete expired keys, but maintain value of $update if nothing is deleted
346
+			$update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
347
+			do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
348
+		}
349
+		return $update;
350
+	}
351
+
352
+
353
+
354
+	/**
355
+	 * calls delete_transient() on each transient key provided, up to the specified limit
356
+	 *
357
+	 * @param array $transient_keys [required]
358
+	 * @param int   $limit
359
+	 * @return bool
360
+	 */
361
+	private function deleteTransientKeys(array $transient_keys, $limit = 50)
362
+	{
363
+		if (empty($transient_keys)) {
364
+			return false;
365
+		}
366
+		$counter = 0;
367
+		foreach ($transient_keys as $transient_key) {
368
+			if($counter === $limit){
369
+				break;
370
+			}
371
+			delete_transient($transient_key);
372
+			unset($this->transients[$transient_key]);
373
+			$counter++;
374
+		}
375
+		return $counter > 0;
376
+	}
377 377
 
378 378
 
379 379
 }
Please login to merge, or discard this patch.
payment_methods/Paypal_Express/EEG_Paypal_Express.gateway.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -20,8 +20,8 @@
 block discarded – undo
20 20
      * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
21 21
      * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
22 22
      * @param $string
23
-     * @param $start
24
-     * @param $length
23
+     * @param integer $start
24
+     * @param integer $length
25 25
      * @return bool|string
26 26
      */
27 27
     function mb_strcut($string, $start, $length = null)
Please login to merge, or discard this patch.
Indentation   +599 added lines, -599 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('NO direct script access allowed');
2
+	exit('NO direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -16,608 +16,608 @@  discard block
 block discarded – undo
16 16
  */
17 17
 //Quickfix to address https://events.codebasehq.com/projects/event-espresso/tickets/11089 ASAP
18 18
 if (! function_exists('mb_strcut')) {
19
-    /**
20
-     * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
21
-     * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
22
-     * @param $string
23
-     * @param $start
24
-     * @param $length
25
-     * @return bool|string
26
-     */
27
-    function mb_strcut($string, $start, $length = null)
28
-    {
29
-        return mb_substr($string, $start, $length);
30
-    }
19
+	/**
20
+	 * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
21
+	 * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
22
+	 * @param $string
23
+	 * @param $start
24
+	 * @param $length
25
+	 * @return bool|string
26
+	 */
27
+	function mb_strcut($string, $start, $length = null)
28
+	{
29
+		return mb_substr($string, $start, $length);
30
+	}
31 31
 }
32 32
 class EEG_Paypal_Express extends EE_Offsite_Gateway
33 33
 {
34 34
 
35
-    /**
36
-     * Merchant API Username.
37
-     *
38
-     * @var string
39
-     */
40
-    protected $_api_username;
41
-
42
-    /**
43
-     * Merchant API Password.
44
-     *
45
-     * @var string
46
-     */
47
-    protected $_api_password;
48
-
49
-    /**
50
-     * API Signature.
51
-     *
52
-     * @var string
53
-     */
54
-    protected $_api_signature;
55
-
56
-    /**
57
-     * Request Shipping address on PP checkout page.
58
-     *
59
-     * @var string
60
-     */
61
-    protected $_request_shipping_addr;
62
-
63
-    /**
64
-     * Business/personal logo.
65
-     *
66
-     * @var string
67
-     */
68
-    protected $_image_url;
69
-
70
-    /**
71
-     * gateway URL variable
72
-     *
73
-     * @var string
74
-     */
75
-    protected $_base_gateway_url = '';
76
-
77
-
78
-
79
-    /**
80
-     * EEG_Paypal_Express constructor.
81
-     */
82
-    public function __construct()
83
-    {
84
-        $this->_currencies_supported = array(
85
-            'USD',
86
-            'AUD',
87
-            'BRL',
88
-            'CAD',
89
-            'CZK',
90
-            'DKK',
91
-            'EUR',
92
-            'HKD',
93
-            'HUF',
94
-            'ILS',
95
-            'JPY',
96
-            'MYR',
97
-            'MXN',
98
-            'NOK',
99
-            'NZD',
100
-            'PHP',
101
-            'PLN',
102
-            'GBP',
103
-            'RUB',
104
-            'SGD',
105
-            'SEK',
106
-            'CHF',
107
-            'TWD',
108
-            'THB',
109
-            'TRY',
110
-        );
111
-        parent::__construct();
112
-    }
113
-
114
-
115
-
116
-    /**
117
-     * Sets the gateway URL variable based on whether debug mode is enabled or not.
118
-     *
119
-     * @param array $settings_array
120
-     */
121
-    public function set_settings($settings_array)
122
-    {
123
-        parent::set_settings($settings_array);
124
-        // Redirect URL.
125
-        $this->_base_gateway_url = $this->_debug_mode
126
-            ? 'https://api-3t.sandbox.paypal.com/nvp'
127
-            : 'https://api-3t.paypal.com/nvp';
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * @param EEI_Payment $payment
134
-     * @param array       $billing_info
135
-     * @param string      $return_url
136
-     * @param string      $notify_url
137
-     * @param string      $cancel_url
138
-     * @return \EE_Payment|\EEI_Payment
139
-     * @throws \EE_Error
140
-     */
141
-    public function set_redirection_info(
142
-        $payment,
143
-        $billing_info = array(),
144
-        $return_url = null,
145
-        $notify_url = null,
146
-        $cancel_url = null
147
-    ) {
148
-        if (! $payment instanceof EEI_Payment) {
149
-            $payment->set_gateway_response(
150
-                esc_html__(
151
-                    'Error. No associated payment was found.',
152
-                    'event_espresso'
153
-                )
154
-            );
155
-            $payment->set_status($this->_pay_model->failed_status());
156
-            return $payment;
157
-        }
158
-        $transaction = $payment->transaction();
159
-        if (! $transaction instanceof EEI_Transaction) {
160
-            $payment->set_gateway_response(
161
-                esc_html__(
162
-                    'Could not process this payment because it has no associated transaction.',
163
-                    'event_espresso'
164
-                )
165
-            );
166
-            $payment->set_status($this->_pay_model->failed_status());
167
-            return $payment;
168
-        }
169
-        $order_description = mb_strcut($this->_format_order_description($payment), 0, 127);
170
-        $primary_registration = $transaction->primary_registration();
171
-        $primary_attendee = $primary_registration instanceof EE_Registration
172
-            ? $primary_registration->attendee()
173
-            : false;
174
-        $locale = explode('-', get_bloginfo('language'));
175
-        // Gather request parameters.
176
-        $token_request_dtls = array(
177
-            'METHOD'                         => 'SetExpressCheckout',
178
-            'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
179
-            'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
180
-            'PAYMENTREQUEST_0_DESC'          => $order_description,
181
-            'RETURNURL'                      => $return_url,
182
-            'CANCELURL'                      => $cancel_url,
183
-            'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
184
-            // Buyer does not need to create a PayPal account to check out.
185
-            // This is referred to as PayPal Account Optional.
186
-            'SOLUTIONTYPE'                   => 'Sole',
187
-            //EE will blow up if you change this
188
-            'BUTTONSOURCE'                   => 'EventEspresso_SP',
189
-            // Locale of the pages displayed by PayPal during Express Checkout.
190
-            'LOCALECODE'                     => $locale[1]
191
-        );
192
-        // Show itemized list.
193
-        if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) {
194
-            $item_num = 0;
195
-            $itemized_sum = 0;
196
-            $total_line_items = $transaction->total_line_item();
197
-            // Go through each item in the list.
198
-            foreach ($total_line_items->get_items() as $line_item) {
199
-                if ($line_item instanceof EE_Line_Item) {
200
-                    // PayPal doesn't like line items with 0.00 amount, so we may skip those.
201
-                    if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
202
-                        continue;
203
-                    }
204
-                    $unit_price = $line_item->unit_price();
205
-                    $line_item_quantity = $line_item->quantity();
206
-                    // This is a discount.
207
-                    if ($line_item->is_percent()) {
208
-                        $unit_price = $line_item->total();
209
-                        $line_item_quantity = 1;
210
-                    }
211
-                    // Item Name.
212
-                    $token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
213
-                        $this->_format_line_item_name($line_item, $payment),
214
-                        0,
215
-                        127
216
-                    );
217
-                    // Item description.
218
-                    $token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = mb_strcut(
219
-                        $this->_format_line_item_desc($line_item, $payment),
220
-                        0,
221
-                        127
222
-                    );
223
-                    // Cost of individual item.
224
-                    $token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency($unit_price);
225
-                    // Item Number.
226
-                    $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
227
-                    // Item quantity.
228
-                    $token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = $line_item_quantity;
229
-                    // Digital item is sold.
230
-                    $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
231
-                    $itemized_sum += $line_item->total();
232
-                    ++$item_num;
233
-                }
234
-            }
235
-            // Item's sales S/H and tax amount.
236
-            $token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $total_line_items->get_items_total();
237
-            $token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = $total_line_items->get_total_tax();
238
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
239
-            $token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
240
-            $itemized_sum_diff_from_txn_total = round(
241
-                $transaction->total() - $itemized_sum - $total_line_items->get_total_tax(),
242
-                2
243
-            );
244
-            // If we were not able to recognize some item like promotion, surcharge or cancellation,
245
-            // add the difference as an extra line item.
246
-            if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
247
-                // Item Name.
248
-                $token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
249
-                    esc_html__(
250
-                        'Other (promotion/surcharge/cancellation)',
251
-                        'event_espresso'
252
-                    ),
253
-                    0,
254
-                    127
255
-                );
256
-                // Item description.
257
-                $token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = '';
258
-                // Cost of individual item.
259
-                $token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency(
260
-                    $itemized_sum_diff_from_txn_total
261
-                );
262
-                // Item Number.
263
-                $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
264
-                // Item quantity.
265
-                $token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = 1;
266
-                // Digital item is sold.
267
-                $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
268
-                $item_num++;
269
-            }
270
-        } else {
271
-            // Just one Item.
272
-            // Item Name.
273
-            $token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = mb_strcut(
274
-                $this->_format_partial_payment_line_item_name($payment),
275
-                0,
276
-                127
277
-            );
278
-            // Item description.
279
-            $token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = mb_strcut(
280
-                $this->_format_partial_payment_line_item_desc($payment),
281
-                0,
282
-                127
283
-            );
284
-            // Cost of individual item.
285
-            $token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency($payment->amount());
286
-            // Item Number.
287
-            $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
288
-            // Item quantity.
289
-            $token_request_dtls['L_PAYMENTREQUEST_0_QTY0'] = 1;
290
-            // Digital item is sold.
291
-            $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
292
-            // Item's sales S/H and tax amount.
293
-            $token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency($payment->amount());
294
-            $token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = '0';
295
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
296
-            $token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
297
-        }
298
-        // Automatically filling out shipping and contact information.
299
-        if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
300
-            //  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
301
-            $token_request_dtls['NOSHIPPING'] = '2';
302
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
303
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
304
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
305
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTATE'] = $primary_attendee->state_abbrev();
306
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $primary_attendee->country_ID();
307
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
308
-            $token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
309
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
310
-        } elseif (! $this->_request_shipping_addr) {
311
-            // Do not request shipping details on the PP Checkout page.
312
-            $token_request_dtls['NOSHIPPING'] = '1';
313
-            $token_request_dtls['REQCONFIRMSHIPPING'] = '0';
314
-        }
315
-        // Used a business/personal logo on the PayPal page.
316
-        if (! empty($this->_image_url)) {
317
-            $token_request_dtls['LOGOIMG'] = $this->_image_url;
318
-        }
319
-        $token_request_dtls = apply_filters(
320
-            'FHEE__EEG_Paypal_Express__set_redirection_info__arguments',
321
-            $token_request_dtls,
322
-            $this
323
-        );
324
-        // Request PayPal token.
325
-        $token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
326
-        $token_rstatus = $this->_ppExpress_check_response($token_request_response);
327
-        $response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args']))
328
-            ? $token_rstatus['args']
329
-            : array();
330
-        if ($token_rstatus['status']) {
331
-            // We got the Token so we may continue with the payment and redirect the client.
332
-            $payment->set_details($response_args);
333
-            $gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
334
-            $payment->set_redirect_url(
335
-                $gateway_url
336
-                . '/checkoutnow?useraction=commit&cmd=_express-checkout&token='
337
-                . $response_args['TOKEN']
338
-            );
339
-        } else {
340
-            if (isset($response_args['L_ERRORCODE'])) {
341
-                $payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']);
342
-            } else {
343
-                $payment->set_gateway_response(
344
-                    esc_html__(
345
-                        'Error occurred while trying to setup the Express Checkout.',
346
-                        'event_espresso'
347
-                    )
348
-                );
349
-            }
350
-            $payment->set_details($response_args);
351
-            $payment->set_status($this->_pay_model->failed_status());
352
-        }
353
-        return $payment;
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * @param array           $update_info {
360
-     * @type string           $gateway_txn_id
361
-     * @type string status an EEMI_Payment status
362
-     *                                     }
363
-     * @param EEI_Transaction $transaction
364
-     * @return EEI_Payment
365
-     */
366
-    public function handle_payment_update($update_info, $transaction)
367
-    {
368
-        $payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null;
369
-        if ($payment instanceof EEI_Payment) {
370
-            $this->log(array('Return from Authorization' => $update_info), $payment);
371
-            $transaction = $payment->transaction();
372
-            if (! $transaction instanceof EEI_Transaction) {
373
-                $payment->set_gateway_response(
374
-                    esc_html__(
375
-                        'Could not process this payment because it has no associated transaction.',
376
-                        'event_espresso'
377
-                    )
378
-                );
379
-                $payment->set_status($this->_pay_model->failed_status());
380
-                return $payment;
381
-            }
382
-            $primary_registrant = $transaction->primary_registration();
383
-            $payment_details = $payment->details();
384
-            // Check if we still have the token.
385
-            if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
386
-                $payment->set_status($this->_pay_model->failed_status());
387
-                return $payment;
388
-            }
389
-            $cdetails_request_dtls = array(
390
-                'METHOD' => 'GetExpressCheckoutDetails',
391
-                'TOKEN'  => $payment_details['TOKEN'],
392
-            );
393
-            // Request Customer Details.
394
-            $cdetails_request_response = $this->_ppExpress_request(
395
-                $cdetails_request_dtls,
396
-                'Customer Details',
397
-                $payment
398
-            );
399
-            $cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
400
-            $cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']))
401
-                ? $cdetails_rstatus['args']
402
-                : array();
403
-            if ($cdetails_rstatus['status']) {
404
-                // We got the PayerID so now we can Complete the transaction.
405
-                $docheckout_request_dtls = array(
406
-                    'METHOD'                         => 'DoExpressCheckoutPayment',
407
-                    'PAYERID'                        => $cdata_response_args['PAYERID'],
408
-                    'TOKEN'                          => $payment_details['TOKEN'],
409
-                    'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
410
-                    'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
411
-                    'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
412
-                    //EE will blow up if you change this
413
-                    'BUTTONSOURCE'                   => 'EventEspresso_SP',
414
-                );
415
-                // Payment Checkout/Capture.
416
-                $docheckout_request_response = $this->_ppExpress_request(
417
-                    $docheckout_request_dtls,
418
-                    'Do Payment',
419
-                    $payment
420
-                );
421
-                $docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
422
-                $docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']))
423
-                    ? $docheckout_rstatus['args']
424
-                    : array();
425
-                if ($docheckout_rstatus['status']) {
426
-                    // All is well, payment approved.
427
-                    $primary_registration_code = $primary_registrant instanceof EE_Registration ?
428
-                        $primary_registrant->reg_code()
429
-                        : '';
430
-                    $payment->set_extra_accntng($primary_registration_code);
431
-                    $payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT'])
432
-                        ? (float)$docheckout_response_args['PAYMENTINFO_0_AMT']
433
-                        : 0);
434
-                    $payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'])
435
-                        ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']
436
-                        : null);
437
-                    $payment->set_details($cdata_response_args);
438
-                    $payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK'])
439
-                        ? $docheckout_response_args['PAYMENTINFO_0_ACK']
440
-                        : '');
441
-                    $payment->set_status($this->_pay_model->approved_status());
442
-                } else {
443
-                    if (isset($docheckout_response_args['L_ERRORCODE'])) {
444
-                        $payment->set_gateway_response(
445
-                            $docheckout_response_args['L_ERRORCODE']
446
-                            . '; '
447
-                            . $docheckout_response_args['L_SHORTMESSAGE']
448
-                        );
449
-                    } else {
450
-                        $payment->set_gateway_response(
451
-                            esc_html__(
452
-                                'Error occurred while trying to Capture the funds.',
453
-                                'event_espresso'
454
-                            )
455
-                        );
456
-                    }
457
-                    $payment->set_details($docheckout_response_args);
458
-                    $payment->set_status($this->_pay_model->declined_status());
459
-                }
460
-            } else {
461
-                if (isset($cdata_response_args['L_ERRORCODE'])) {
462
-                    $payment->set_gateway_response(
463
-                        $cdata_response_args['L_ERRORCODE']
464
-                        . '; '
465
-                        . $cdata_response_args['L_SHORTMESSAGE']
466
-                    );
467
-                } else {
468
-                    $payment->set_gateway_response(
469
-                        esc_html__(
470
-                            'Error occurred while trying to get payment Details from PayPal.',
471
-                            'event_espresso'
472
-                        )
473
-                    );
474
-                }
475
-                $payment->set_details($cdata_response_args);
476
-                $payment->set_status($this->_pay_model->failed_status());
477
-            }
478
-        } else {
479
-            $payment->set_gateway_response(
480
-                esc_html__(
481
-                    'Error occurred while trying to process the payment.',
482
-                    'event_espresso'
483
-                )
484
-            );
485
-            $payment->set_status($this->_pay_model->failed_status());
486
-        }
487
-        return $payment;
488
-    }
489
-
490
-
491
-
492
-    /**
493
-     *  Make the Express checkout request.
494
-     *
495
-     * @param array       $request_params
496
-     * @param string      $request_text
497
-     * @param EEI_Payment $payment
498
-     * @return mixed
499
-     */
500
-    public function _ppExpress_request($request_params, $request_text, $payment)
501
-    {
502
-        $request_dtls = array(
503
-            'VERSION'   => '204.0',
504
-            'USER'      => urlencode($this->_api_username),
505
-            'PWD'       => urlencode($this->_api_password),
506
-            'SIGNATURE' => urlencode($this->_api_signature),
507
-        );
508
-        $dtls = array_merge($request_dtls, $request_params);
509
-        $this->_log_clean_request($dtls, $payment, $request_text . ' Request');
510
-        // Request Customer Details.
511
-        $request_response = wp_remote_post(
512
-            $this->_base_gateway_url,
513
-            array(
514
-                'method'      => 'POST',
515
-                'timeout'     => 45,
516
-                'httpversion' => '1.1',
517
-                'cookies'     => array(),
518
-                'headers'     => array(),
519
-                'body'        => http_build_query($dtls),
520
-            )
521
-        );
522
-        // Log the response.
523
-        $this->log(array($request_text . ' Response' => $request_response), $payment);
524
-        return $request_response;
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     *  Check the response status.
531
-     *
532
-     * @param mixed $request_response
533
-     * @return array
534
-     */
535
-    public function _ppExpress_check_response($request_response)
536
-    {
537
-        if (is_wp_error($request_response) || empty($request_response['body'])) {
538
-            // If we got here then there was an error in this request.
539
-            return array('status' => false, 'args' => $request_response);
540
-        }
541
-        $response_args = array();
542
-        parse_str(urldecode($request_response['body']), $response_args);
543
-        if (! isset($response_args['ACK'])) {
544
-            return array('status' => false, 'args' => $request_response);
545
-        }
546
-        if (
547
-            (
548
-                isset($response_args['PAYERID'])
549
-                || isset($response_args['TOKEN'])
550
-                || isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
551
-                || (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
552
-            )
553
-            && in_array($response_args['ACK'], array('Success', 'SuccessWithWarning'), true)
554
-        ) {
555
-            // Response status OK, return response parameters for further processing.
556
-            return array('status' => true, 'args' => $response_args);
557
-        }
558
-        $errors = $this->_get_errors($response_args);
559
-        return array('status' => false, 'args' => $errors);
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     *  Log a "Cleared" request.
566
-     *
567
-     * @param array       $request
568
-     * @param EEI_Payment $payment
569
-     * @param string      $info
570
-     * @return void
571
-     */
572
-    private function _log_clean_request($request, $payment, $info)
573
-    {
574
-        $cleaned_request_data = $request;
575
-        unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']);
576
-        $this->log(array($info => $cleaned_request_data), $payment);
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     *  Get error from the response data.
583
-     *
584
-     * @param array $data_array
585
-     * @return array
586
-     */
587
-    private function _get_errors($data_array)
588
-    {
589
-        $errors = array();
590
-        $n = 0;
591
-        while (isset($data_array["L_ERRORCODE{$n}"])) {
592
-            $l_error_code = isset($data_array["L_ERRORCODE{$n}"])
593
-                ? $data_array["L_ERRORCODE{$n}"]
594
-                : '';
595
-            $l_severity_code = isset($data_array["L_SEVERITYCODE{$n}"])
596
-                ? $data_array["L_SEVERITYCODE{$n}"]
597
-                : '';
598
-            $l_short_message = isset($data_array["L_SHORTMESSAGE{$n}"])
599
-                ? $data_array["L_SHORTMESSAGE{$n}"]
600
-                : '';
601
-            $l_long_message = isset($data_array["L_LONGMESSAGE{$n}"])
602
-                ? $data_array["L_LONGMESSAGE{$n}"]
603
-                : '';
604
-            if ($n === 0) {
605
-                $errors = array(
606
-                    'L_ERRORCODE'    => $l_error_code,
607
-                    'L_SHORTMESSAGE' => $l_short_message,
608
-                    'L_LONGMESSAGE'  => $l_long_message,
609
-                    'L_SEVERITYCODE' => $l_severity_code,
610
-                );
611
-            } else {
612
-                $errors['L_ERRORCODE'] .= ', ' . $l_error_code;
613
-                $errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
614
-                $errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
615
-                $errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
616
-            }
617
-            $n++;
618
-        }
619
-        return $errors;
620
-    }
35
+	/**
36
+	 * Merchant API Username.
37
+	 *
38
+	 * @var string
39
+	 */
40
+	protected $_api_username;
41
+
42
+	/**
43
+	 * Merchant API Password.
44
+	 *
45
+	 * @var string
46
+	 */
47
+	protected $_api_password;
48
+
49
+	/**
50
+	 * API Signature.
51
+	 *
52
+	 * @var string
53
+	 */
54
+	protected $_api_signature;
55
+
56
+	/**
57
+	 * Request Shipping address on PP checkout page.
58
+	 *
59
+	 * @var string
60
+	 */
61
+	protected $_request_shipping_addr;
62
+
63
+	/**
64
+	 * Business/personal logo.
65
+	 *
66
+	 * @var string
67
+	 */
68
+	protected $_image_url;
69
+
70
+	/**
71
+	 * gateway URL variable
72
+	 *
73
+	 * @var string
74
+	 */
75
+	protected $_base_gateway_url = '';
76
+
77
+
78
+
79
+	/**
80
+	 * EEG_Paypal_Express constructor.
81
+	 */
82
+	public function __construct()
83
+	{
84
+		$this->_currencies_supported = array(
85
+			'USD',
86
+			'AUD',
87
+			'BRL',
88
+			'CAD',
89
+			'CZK',
90
+			'DKK',
91
+			'EUR',
92
+			'HKD',
93
+			'HUF',
94
+			'ILS',
95
+			'JPY',
96
+			'MYR',
97
+			'MXN',
98
+			'NOK',
99
+			'NZD',
100
+			'PHP',
101
+			'PLN',
102
+			'GBP',
103
+			'RUB',
104
+			'SGD',
105
+			'SEK',
106
+			'CHF',
107
+			'TWD',
108
+			'THB',
109
+			'TRY',
110
+		);
111
+		parent::__construct();
112
+	}
113
+
114
+
115
+
116
+	/**
117
+	 * Sets the gateway URL variable based on whether debug mode is enabled or not.
118
+	 *
119
+	 * @param array $settings_array
120
+	 */
121
+	public function set_settings($settings_array)
122
+	{
123
+		parent::set_settings($settings_array);
124
+		// Redirect URL.
125
+		$this->_base_gateway_url = $this->_debug_mode
126
+			? 'https://api-3t.sandbox.paypal.com/nvp'
127
+			: 'https://api-3t.paypal.com/nvp';
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * @param EEI_Payment $payment
134
+	 * @param array       $billing_info
135
+	 * @param string      $return_url
136
+	 * @param string      $notify_url
137
+	 * @param string      $cancel_url
138
+	 * @return \EE_Payment|\EEI_Payment
139
+	 * @throws \EE_Error
140
+	 */
141
+	public function set_redirection_info(
142
+		$payment,
143
+		$billing_info = array(),
144
+		$return_url = null,
145
+		$notify_url = null,
146
+		$cancel_url = null
147
+	) {
148
+		if (! $payment instanceof EEI_Payment) {
149
+			$payment->set_gateway_response(
150
+				esc_html__(
151
+					'Error. No associated payment was found.',
152
+					'event_espresso'
153
+				)
154
+			);
155
+			$payment->set_status($this->_pay_model->failed_status());
156
+			return $payment;
157
+		}
158
+		$transaction = $payment->transaction();
159
+		if (! $transaction instanceof EEI_Transaction) {
160
+			$payment->set_gateway_response(
161
+				esc_html__(
162
+					'Could not process this payment because it has no associated transaction.',
163
+					'event_espresso'
164
+				)
165
+			);
166
+			$payment->set_status($this->_pay_model->failed_status());
167
+			return $payment;
168
+		}
169
+		$order_description = mb_strcut($this->_format_order_description($payment), 0, 127);
170
+		$primary_registration = $transaction->primary_registration();
171
+		$primary_attendee = $primary_registration instanceof EE_Registration
172
+			? $primary_registration->attendee()
173
+			: false;
174
+		$locale = explode('-', get_bloginfo('language'));
175
+		// Gather request parameters.
176
+		$token_request_dtls = array(
177
+			'METHOD'                         => 'SetExpressCheckout',
178
+			'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
179
+			'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
180
+			'PAYMENTREQUEST_0_DESC'          => $order_description,
181
+			'RETURNURL'                      => $return_url,
182
+			'CANCELURL'                      => $cancel_url,
183
+			'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
184
+			// Buyer does not need to create a PayPal account to check out.
185
+			// This is referred to as PayPal Account Optional.
186
+			'SOLUTIONTYPE'                   => 'Sole',
187
+			//EE will blow up if you change this
188
+			'BUTTONSOURCE'                   => 'EventEspresso_SP',
189
+			// Locale of the pages displayed by PayPal during Express Checkout.
190
+			'LOCALECODE'                     => $locale[1]
191
+		);
192
+		// Show itemized list.
193
+		if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) {
194
+			$item_num = 0;
195
+			$itemized_sum = 0;
196
+			$total_line_items = $transaction->total_line_item();
197
+			// Go through each item in the list.
198
+			foreach ($total_line_items->get_items() as $line_item) {
199
+				if ($line_item instanceof EE_Line_Item) {
200
+					// PayPal doesn't like line items with 0.00 amount, so we may skip those.
201
+					if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
202
+						continue;
203
+					}
204
+					$unit_price = $line_item->unit_price();
205
+					$line_item_quantity = $line_item->quantity();
206
+					// This is a discount.
207
+					if ($line_item->is_percent()) {
208
+						$unit_price = $line_item->total();
209
+						$line_item_quantity = 1;
210
+					}
211
+					// Item Name.
212
+					$token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
213
+						$this->_format_line_item_name($line_item, $payment),
214
+						0,
215
+						127
216
+					);
217
+					// Item description.
218
+					$token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = mb_strcut(
219
+						$this->_format_line_item_desc($line_item, $payment),
220
+						0,
221
+						127
222
+					);
223
+					// Cost of individual item.
224
+					$token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency($unit_price);
225
+					// Item Number.
226
+					$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
227
+					// Item quantity.
228
+					$token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = $line_item_quantity;
229
+					// Digital item is sold.
230
+					$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
231
+					$itemized_sum += $line_item->total();
232
+					++$item_num;
233
+				}
234
+			}
235
+			// Item's sales S/H and tax amount.
236
+			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $total_line_items->get_items_total();
237
+			$token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = $total_line_items->get_total_tax();
238
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
239
+			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
240
+			$itemized_sum_diff_from_txn_total = round(
241
+				$transaction->total() - $itemized_sum - $total_line_items->get_total_tax(),
242
+				2
243
+			);
244
+			// If we were not able to recognize some item like promotion, surcharge or cancellation,
245
+			// add the difference as an extra line item.
246
+			if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
247
+				// Item Name.
248
+				$token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
249
+					esc_html__(
250
+						'Other (promotion/surcharge/cancellation)',
251
+						'event_espresso'
252
+					),
253
+					0,
254
+					127
255
+				);
256
+				// Item description.
257
+				$token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = '';
258
+				// Cost of individual item.
259
+				$token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency(
260
+					$itemized_sum_diff_from_txn_total
261
+				);
262
+				// Item Number.
263
+				$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
264
+				// Item quantity.
265
+				$token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = 1;
266
+				// Digital item is sold.
267
+				$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
268
+				$item_num++;
269
+			}
270
+		} else {
271
+			// Just one Item.
272
+			// Item Name.
273
+			$token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = mb_strcut(
274
+				$this->_format_partial_payment_line_item_name($payment),
275
+				0,
276
+				127
277
+			);
278
+			// Item description.
279
+			$token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = mb_strcut(
280
+				$this->_format_partial_payment_line_item_desc($payment),
281
+				0,
282
+				127
283
+			);
284
+			// Cost of individual item.
285
+			$token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency($payment->amount());
286
+			// Item Number.
287
+			$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
288
+			// Item quantity.
289
+			$token_request_dtls['L_PAYMENTREQUEST_0_QTY0'] = 1;
290
+			// Digital item is sold.
291
+			$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
292
+			// Item's sales S/H and tax amount.
293
+			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency($payment->amount());
294
+			$token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = '0';
295
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
296
+			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
297
+		}
298
+		// Automatically filling out shipping and contact information.
299
+		if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
300
+			//  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
301
+			$token_request_dtls['NOSHIPPING'] = '2';
302
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
303
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
304
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
305
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTATE'] = $primary_attendee->state_abbrev();
306
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $primary_attendee->country_ID();
307
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
308
+			$token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
309
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
310
+		} elseif (! $this->_request_shipping_addr) {
311
+			// Do not request shipping details on the PP Checkout page.
312
+			$token_request_dtls['NOSHIPPING'] = '1';
313
+			$token_request_dtls['REQCONFIRMSHIPPING'] = '0';
314
+		}
315
+		// Used a business/personal logo on the PayPal page.
316
+		if (! empty($this->_image_url)) {
317
+			$token_request_dtls['LOGOIMG'] = $this->_image_url;
318
+		}
319
+		$token_request_dtls = apply_filters(
320
+			'FHEE__EEG_Paypal_Express__set_redirection_info__arguments',
321
+			$token_request_dtls,
322
+			$this
323
+		);
324
+		// Request PayPal token.
325
+		$token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
326
+		$token_rstatus = $this->_ppExpress_check_response($token_request_response);
327
+		$response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args']))
328
+			? $token_rstatus['args']
329
+			: array();
330
+		if ($token_rstatus['status']) {
331
+			// We got the Token so we may continue with the payment and redirect the client.
332
+			$payment->set_details($response_args);
333
+			$gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
334
+			$payment->set_redirect_url(
335
+				$gateway_url
336
+				. '/checkoutnow?useraction=commit&cmd=_express-checkout&token='
337
+				. $response_args['TOKEN']
338
+			);
339
+		} else {
340
+			if (isset($response_args['L_ERRORCODE'])) {
341
+				$payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']);
342
+			} else {
343
+				$payment->set_gateway_response(
344
+					esc_html__(
345
+						'Error occurred while trying to setup the Express Checkout.',
346
+						'event_espresso'
347
+					)
348
+				);
349
+			}
350
+			$payment->set_details($response_args);
351
+			$payment->set_status($this->_pay_model->failed_status());
352
+		}
353
+		return $payment;
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * @param array           $update_info {
360
+	 * @type string           $gateway_txn_id
361
+	 * @type string status an EEMI_Payment status
362
+	 *                                     }
363
+	 * @param EEI_Transaction $transaction
364
+	 * @return EEI_Payment
365
+	 */
366
+	public function handle_payment_update($update_info, $transaction)
367
+	{
368
+		$payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null;
369
+		if ($payment instanceof EEI_Payment) {
370
+			$this->log(array('Return from Authorization' => $update_info), $payment);
371
+			$transaction = $payment->transaction();
372
+			if (! $transaction instanceof EEI_Transaction) {
373
+				$payment->set_gateway_response(
374
+					esc_html__(
375
+						'Could not process this payment because it has no associated transaction.',
376
+						'event_espresso'
377
+					)
378
+				);
379
+				$payment->set_status($this->_pay_model->failed_status());
380
+				return $payment;
381
+			}
382
+			$primary_registrant = $transaction->primary_registration();
383
+			$payment_details = $payment->details();
384
+			// Check if we still have the token.
385
+			if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
386
+				$payment->set_status($this->_pay_model->failed_status());
387
+				return $payment;
388
+			}
389
+			$cdetails_request_dtls = array(
390
+				'METHOD' => 'GetExpressCheckoutDetails',
391
+				'TOKEN'  => $payment_details['TOKEN'],
392
+			);
393
+			// Request Customer Details.
394
+			$cdetails_request_response = $this->_ppExpress_request(
395
+				$cdetails_request_dtls,
396
+				'Customer Details',
397
+				$payment
398
+			);
399
+			$cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
400
+			$cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']))
401
+				? $cdetails_rstatus['args']
402
+				: array();
403
+			if ($cdetails_rstatus['status']) {
404
+				// We got the PayerID so now we can Complete the transaction.
405
+				$docheckout_request_dtls = array(
406
+					'METHOD'                         => 'DoExpressCheckoutPayment',
407
+					'PAYERID'                        => $cdata_response_args['PAYERID'],
408
+					'TOKEN'                          => $payment_details['TOKEN'],
409
+					'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
410
+					'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
411
+					'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
412
+					//EE will blow up if you change this
413
+					'BUTTONSOURCE'                   => 'EventEspresso_SP',
414
+				);
415
+				// Payment Checkout/Capture.
416
+				$docheckout_request_response = $this->_ppExpress_request(
417
+					$docheckout_request_dtls,
418
+					'Do Payment',
419
+					$payment
420
+				);
421
+				$docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
422
+				$docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']))
423
+					? $docheckout_rstatus['args']
424
+					: array();
425
+				if ($docheckout_rstatus['status']) {
426
+					// All is well, payment approved.
427
+					$primary_registration_code = $primary_registrant instanceof EE_Registration ?
428
+						$primary_registrant->reg_code()
429
+						: '';
430
+					$payment->set_extra_accntng($primary_registration_code);
431
+					$payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT'])
432
+						? (float)$docheckout_response_args['PAYMENTINFO_0_AMT']
433
+						: 0);
434
+					$payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'])
435
+						? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']
436
+						: null);
437
+					$payment->set_details($cdata_response_args);
438
+					$payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK'])
439
+						? $docheckout_response_args['PAYMENTINFO_0_ACK']
440
+						: '');
441
+					$payment->set_status($this->_pay_model->approved_status());
442
+				} else {
443
+					if (isset($docheckout_response_args['L_ERRORCODE'])) {
444
+						$payment->set_gateway_response(
445
+							$docheckout_response_args['L_ERRORCODE']
446
+							. '; '
447
+							. $docheckout_response_args['L_SHORTMESSAGE']
448
+						);
449
+					} else {
450
+						$payment->set_gateway_response(
451
+							esc_html__(
452
+								'Error occurred while trying to Capture the funds.',
453
+								'event_espresso'
454
+							)
455
+						);
456
+					}
457
+					$payment->set_details($docheckout_response_args);
458
+					$payment->set_status($this->_pay_model->declined_status());
459
+				}
460
+			} else {
461
+				if (isset($cdata_response_args['L_ERRORCODE'])) {
462
+					$payment->set_gateway_response(
463
+						$cdata_response_args['L_ERRORCODE']
464
+						. '; '
465
+						. $cdata_response_args['L_SHORTMESSAGE']
466
+					);
467
+				} else {
468
+					$payment->set_gateway_response(
469
+						esc_html__(
470
+							'Error occurred while trying to get payment Details from PayPal.',
471
+							'event_espresso'
472
+						)
473
+					);
474
+				}
475
+				$payment->set_details($cdata_response_args);
476
+				$payment->set_status($this->_pay_model->failed_status());
477
+			}
478
+		} else {
479
+			$payment->set_gateway_response(
480
+				esc_html__(
481
+					'Error occurred while trying to process the payment.',
482
+					'event_espresso'
483
+				)
484
+			);
485
+			$payment->set_status($this->_pay_model->failed_status());
486
+		}
487
+		return $payment;
488
+	}
489
+
490
+
491
+
492
+	/**
493
+	 *  Make the Express checkout request.
494
+	 *
495
+	 * @param array       $request_params
496
+	 * @param string      $request_text
497
+	 * @param EEI_Payment $payment
498
+	 * @return mixed
499
+	 */
500
+	public function _ppExpress_request($request_params, $request_text, $payment)
501
+	{
502
+		$request_dtls = array(
503
+			'VERSION'   => '204.0',
504
+			'USER'      => urlencode($this->_api_username),
505
+			'PWD'       => urlencode($this->_api_password),
506
+			'SIGNATURE' => urlencode($this->_api_signature),
507
+		);
508
+		$dtls = array_merge($request_dtls, $request_params);
509
+		$this->_log_clean_request($dtls, $payment, $request_text . ' Request');
510
+		// Request Customer Details.
511
+		$request_response = wp_remote_post(
512
+			$this->_base_gateway_url,
513
+			array(
514
+				'method'      => 'POST',
515
+				'timeout'     => 45,
516
+				'httpversion' => '1.1',
517
+				'cookies'     => array(),
518
+				'headers'     => array(),
519
+				'body'        => http_build_query($dtls),
520
+			)
521
+		);
522
+		// Log the response.
523
+		$this->log(array($request_text . ' Response' => $request_response), $payment);
524
+		return $request_response;
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 *  Check the response status.
531
+	 *
532
+	 * @param mixed $request_response
533
+	 * @return array
534
+	 */
535
+	public function _ppExpress_check_response($request_response)
536
+	{
537
+		if (is_wp_error($request_response) || empty($request_response['body'])) {
538
+			// If we got here then there was an error in this request.
539
+			return array('status' => false, 'args' => $request_response);
540
+		}
541
+		$response_args = array();
542
+		parse_str(urldecode($request_response['body']), $response_args);
543
+		if (! isset($response_args['ACK'])) {
544
+			return array('status' => false, 'args' => $request_response);
545
+		}
546
+		if (
547
+			(
548
+				isset($response_args['PAYERID'])
549
+				|| isset($response_args['TOKEN'])
550
+				|| isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
551
+				|| (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
552
+			)
553
+			&& in_array($response_args['ACK'], array('Success', 'SuccessWithWarning'), true)
554
+		) {
555
+			// Response status OK, return response parameters for further processing.
556
+			return array('status' => true, 'args' => $response_args);
557
+		}
558
+		$errors = $this->_get_errors($response_args);
559
+		return array('status' => false, 'args' => $errors);
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 *  Log a "Cleared" request.
566
+	 *
567
+	 * @param array       $request
568
+	 * @param EEI_Payment $payment
569
+	 * @param string      $info
570
+	 * @return void
571
+	 */
572
+	private function _log_clean_request($request, $payment, $info)
573
+	{
574
+		$cleaned_request_data = $request;
575
+		unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']);
576
+		$this->log(array($info => $cleaned_request_data), $payment);
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 *  Get error from the response data.
583
+	 *
584
+	 * @param array $data_array
585
+	 * @return array
586
+	 */
587
+	private function _get_errors($data_array)
588
+	{
589
+		$errors = array();
590
+		$n = 0;
591
+		while (isset($data_array["L_ERRORCODE{$n}"])) {
592
+			$l_error_code = isset($data_array["L_ERRORCODE{$n}"])
593
+				? $data_array["L_ERRORCODE{$n}"]
594
+				: '';
595
+			$l_severity_code = isset($data_array["L_SEVERITYCODE{$n}"])
596
+				? $data_array["L_SEVERITYCODE{$n}"]
597
+				: '';
598
+			$l_short_message = isset($data_array["L_SHORTMESSAGE{$n}"])
599
+				? $data_array["L_SHORTMESSAGE{$n}"]
600
+				: '';
601
+			$l_long_message = isset($data_array["L_LONGMESSAGE{$n}"])
602
+				? $data_array["L_LONGMESSAGE{$n}"]
603
+				: '';
604
+			if ($n === 0) {
605
+				$errors = array(
606
+					'L_ERRORCODE'    => $l_error_code,
607
+					'L_SHORTMESSAGE' => $l_short_message,
608
+					'L_LONGMESSAGE'  => $l_long_message,
609
+					'L_SEVERITYCODE' => $l_severity_code,
610
+				);
611
+			} else {
612
+				$errors['L_ERRORCODE'] .= ', ' . $l_error_code;
613
+				$errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
614
+				$errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
615
+				$errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
616
+			}
617
+			$n++;
618
+		}
619
+		return $errors;
620
+	}
621 621
 
622 622
 }
623 623
 // End of file EEG_Paypal_Express.gateway.php
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('NO direct script access allowed');
3 3
 }
4 4
 
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
  * ----------------------------------------------
16 16
  */
17 17
 //Quickfix to address https://events.codebasehq.com/projects/event-espresso/tickets/11089 ASAP
18
-if (! function_exists('mb_strcut')) {
18
+if ( ! function_exists('mb_strcut')) {
19 19
     /**
20 20
      * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
21 21
      * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
         $notify_url = null,
146 146
         $cancel_url = null
147 147
     ) {
148
-        if (! $payment instanceof EEI_Payment) {
148
+        if ( ! $payment instanceof EEI_Payment) {
149 149
             $payment->set_gateway_response(
150 150
                 esc_html__(
151 151
                     'Error. No associated payment was found.',
@@ -156,7 +156,7 @@  discard block
 block discarded – undo
156 156
             return $payment;
157 157
         }
158 158
         $transaction = $payment->transaction();
159
-        if (! $transaction instanceof EEI_Transaction) {
159
+        if ( ! $transaction instanceof EEI_Transaction) {
160 160
             $payment->set_gateway_response(
161 161
                 esc_html__(
162 162
                     'Could not process this payment because it has no associated transaction.',
@@ -209,25 +209,25 @@  discard block
 block discarded – undo
209 209
                         $line_item_quantity = 1;
210 210
                     }
211 211
                     // Item Name.
212
-                    $token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
212
+                    $token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = mb_strcut(
213 213
                         $this->_format_line_item_name($line_item, $payment),
214 214
                         0,
215 215
                         127
216 216
                     );
217 217
                     // Item description.
218
-                    $token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = mb_strcut(
218
+                    $token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = mb_strcut(
219 219
                         $this->_format_line_item_desc($line_item, $payment),
220 220
                         0,
221 221
                         127
222 222
                     );
223 223
                     // Cost of individual item.
224
-                    $token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency($unit_price);
224
+                    $token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency($unit_price);
225 225
                     // Item Number.
226
-                    $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
226
+                    $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
227 227
                     // Item quantity.
228
-                    $token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = $line_item_quantity;
228
+                    $token_request_dtls['L_PAYMENTREQUEST_0_QTY'.$item_num] = $line_item_quantity;
229 229
                     // Digital item is sold.
230
-                    $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
230
+                    $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY'.$item_num] = 'Physical';
231 231
                     $itemized_sum += $line_item->total();
232 232
                     ++$item_num;
233 233
                 }
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
             // add the difference as an extra line item.
246 246
             if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
247 247
                 // Item Name.
248
-                $token_request_dtls['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut(
248
+                $token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = mb_strcut(
249 249
                     esc_html__(
250 250
                         'Other (promotion/surcharge/cancellation)',
251 251
                         'event_espresso'
@@ -254,17 +254,17 @@  discard block
 block discarded – undo
254 254
                     127
255 255
                 );
256 256
                 // Item description.
257
-                $token_request_dtls['L_PAYMENTREQUEST_0_DESC' . $item_num] = '';
257
+                $token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = '';
258 258
                 // Cost of individual item.
259
-                $token_request_dtls['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency(
259
+                $token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency(
260 260
                     $itemized_sum_diff_from_txn_total
261 261
                 );
262 262
                 // Item Number.
263
-                $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1;
263
+                $token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
264 264
                 // Item quantity.
265
-                $token_request_dtls['L_PAYMENTREQUEST_0_QTY' . $item_num] = 1;
265
+                $token_request_dtls['L_PAYMENTREQUEST_0_QTY'.$item_num] = 1;
266 266
                 // Digital item is sold.
267
-                $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical';
267
+                $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY'.$item_num] = 'Physical';
268 268
                 $item_num++;
269 269
             }
270 270
         } else {
@@ -307,13 +307,13 @@  discard block
 block discarded – undo
307 307
             $token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
308 308
             $token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
309 309
             $token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
310
-        } elseif (! $this->_request_shipping_addr) {
310
+        } elseif ( ! $this->_request_shipping_addr) {
311 311
             // Do not request shipping details on the PP Checkout page.
312 312
             $token_request_dtls['NOSHIPPING'] = '1';
313 313
             $token_request_dtls['REQCONFIRMSHIPPING'] = '0';
314 314
         }
315 315
         // Used a business/personal logo on the PayPal page.
316
-        if (! empty($this->_image_url)) {
316
+        if ( ! empty($this->_image_url)) {
317 317
             $token_request_dtls['LOGOIMG'] = $this->_image_url;
318 318
         }
319 319
         $token_request_dtls = apply_filters(
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
             );
339 339
         } else {
340 340
             if (isset($response_args['L_ERRORCODE'])) {
341
-                $payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']);
341
+                $payment->set_gateway_response($response_args['L_ERRORCODE'].'; '.$response_args['L_SHORTMESSAGE']);
342 342
             } else {
343 343
                 $payment->set_gateway_response(
344 344
                     esc_html__(
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
         if ($payment instanceof EEI_Payment) {
370 370
             $this->log(array('Return from Authorization' => $update_info), $payment);
371 371
             $transaction = $payment->transaction();
372
-            if (! $transaction instanceof EEI_Transaction) {
372
+            if ( ! $transaction instanceof EEI_Transaction) {
373 373
                 $payment->set_gateway_response(
374 374
                     esc_html__(
375 375
                         'Could not process this payment because it has no associated transaction.',
@@ -382,7 +382,7 @@  discard block
 block discarded – undo
382 382
             $primary_registrant = $transaction->primary_registration();
383 383
             $payment_details = $payment->details();
384 384
             // Check if we still have the token.
385
-            if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
385
+            if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
386 386
                 $payment->set_status($this->_pay_model->failed_status());
387 387
                 return $payment;
388 388
             }
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
                         : '';
430 430
                     $payment->set_extra_accntng($primary_registration_code);
431 431
                     $payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT'])
432
-                        ? (float)$docheckout_response_args['PAYMENTINFO_0_AMT']
432
+                        ? (float) $docheckout_response_args['PAYMENTINFO_0_AMT']
433 433
                         : 0);
434 434
                     $payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'])
435 435
                         ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
             'SIGNATURE' => urlencode($this->_api_signature),
507 507
         );
508 508
         $dtls = array_merge($request_dtls, $request_params);
509
-        $this->_log_clean_request($dtls, $payment, $request_text . ' Request');
509
+        $this->_log_clean_request($dtls, $payment, $request_text.' Request');
510 510
         // Request Customer Details.
511 511
         $request_response = wp_remote_post(
512 512
             $this->_base_gateway_url,
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
             )
521 521
         );
522 522
         // Log the response.
523
-        $this->log(array($request_text . ' Response' => $request_response), $payment);
523
+        $this->log(array($request_text.' Response' => $request_response), $payment);
524 524
         return $request_response;
525 525
     }
526 526
 
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
         }
541 541
         $response_args = array();
542 542
         parse_str(urldecode($request_response['body']), $response_args);
543
-        if (! isset($response_args['ACK'])) {
543
+        if ( ! isset($response_args['ACK'])) {
544 544
             return array('status' => false, 'args' => $request_response);
545 545
         }
546 546
         if (
@@ -609,10 +609,10 @@  discard block
 block discarded – undo
609 609
                     'L_SEVERITYCODE' => $l_severity_code,
610 610
                 );
611 611
             } else {
612
-                $errors['L_ERRORCODE'] .= ', ' . $l_error_code;
613
-                $errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
614
-                $errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
615
-                $errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
612
+                $errors['L_ERRORCODE'] .= ', '.$l_error_code;
613
+                $errors['L_SHORTMESSAGE'] .= ', '.$l_short_message;
614
+                $errors['L_LONGMESSAGE'] .= ', '.$l_long_message;
615
+                $errors['L_SEVERITYCODE'] .= ', '.$l_severity_code;
616 616
             }
617 617
             $n++;
618 618
         }
Please login to merge, or discard this patch.
acceptance_tests/Helpers/EventsAdmin.php 1 patch
Indentation   +124 added lines, -124 removed lines patch added patch discarded remove patch
@@ -14,128 +14,128 @@
 block discarded – undo
14 14
 trait EventsAdmin
15 15
 {
16 16
 
17
-    /**
18
-     * @param string $additional_params
19
-     */
20
-    public function amOnDefaultEventsListTablePage($additional_params = '')
21
-    {
22
-        $this->actor()->amOnAdminPage(EventsPage::defaultEventsListTableUrl($additional_params));
23
-    }
24
-
25
-
26
-    /**
27
-     * Triggers the publishing of the Event.
28
-     */
29
-    public function publishEvent()
30
-    {
31
-        $this->actor()->click(EventsPage::EVENT_EDITOR_PUBLISH_BUTTON_SELECTOR);
32
-    }
33
-
34
-
35
-    /**
36
-     * Triggers saving the Event.
37
-     */
38
-    public function saveEvent()
39
-    {
40
-        $this->actor()->click(EventsPage::EVENT_EDITOR_SAVE_BUTTON_SELECTOR);
41
-    }
42
-
43
-
44
-    /**
45
-     * Navigates the actor to the event list table page and will attempt to edit the event for the given title.
46
-     * First this will search using the given title and then attempt to edit from the results of the search.
47
-     *
48
-     * Assumes actor is already logged in.
49
-     * @param $event_title
50
-     */
51
-    public function amEditingTheEventWithTitle($event_title)
52
-    {
53
-        $this->amOnDefaultEventsListTablePage();
54
-        $this->actor()->fillField(EventsPage::EVENT_LIST_TABLE_SEARCH_INPUT_SELECTOR, $event_title);
55
-        $this->actor()->click(CoreAdmin::LIST_TABLE_SEARCH_SUBMIT_SELECTOR);
56
-        $this->actor()->waitForText($event_title, 15);
57
-        $this->actor()->click(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title));
58
-    }
59
-
60
-
61
-    /**
62
-     * Navigates the user to the single event page (frontend view) for the given event title via clicking the "View"
63
-     * link for the event in the event list table.
64
-     * Assumes the actor is already logged in and on the Event list table page.
65
-     *
66
-     * @param string $event_title
67
-     */
68
-    public function amOnEventPageAfterClickingViewLinkInListTableForEvent($event_title)
69
-    {
70
-        $this->actor()->moveMouseOver(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title));
71
-        $this->actor()->click(EventsPage::eventListTableEventTitleViewLinkSelectorForTitle($event_title));
72
-    }
73
-
74
-
75
-    /**
76
-     * Used to retrieve the event id for the event via the list table and for the given event.
77
-     * @param string $event_title
78
-     */
79
-    public function observeEventIdInListTableForEvent($event_title)
80
-    {
81
-        return $this->actor()->observeValueFromInputAt(EventsPage::eventListTableEventIdSelectorForTitle($event_title));
82
-    }
83
-
84
-
85
-    /**
86
-     * This performs the click action on the gear icon that triggers the advanced settings view state.
87
-     * Assumes the actor is already logged in and editing an event.
88
-     *
89
-     * @param int $row_number  What ticket row to toggle open/close.
90
-     */
91
-    public function toggleAdvancedSettingsViewForTicketRow($row_number = 1)
92
-    {
93
-        $this->actor()->click(EventsPage::eventEditorTicketAdvancedDetailsSelector($row_number));
94
-    }
95
-
96
-
97
-    /**
98
-     * Toggles the TKT_is_taxable checkbox for the ticket in the given row.
99
-     * Assumes the actor is already logged in and editing an event and that the advanced settings view state for that
100
-     * ticket is "open".
101
-     *
102
-     * @param int $row_number  What ticket row to toggle the checkbox for.
103
-     */
104
-    public function toggleTicketIsTaxableForTicketRow($row_number = 1)
105
-    {
106
-        $this->actor()->click(EventsPage::eventEditorTicketTaxableCheckboxSelector($row_number));
107
-    }
108
-
109
-
110
-    /**
111
-     * Use to change the default registration status for the event.
112
-     * Assumes the view is already on the event editor.
113
-     * @param $registration_status
114
-     */
115
-    public function changeDefaultRegistrationStatusTo($registration_status)
116
-    {
117
-        $this->actor()->selectOption(
118
-            EventsPage::EVENT_EDITOR_DEFAULT_REGISTRATION_STATUS_FIELD_SELECTOR,
119
-            $registration_status
120
-        );
121
-    }
122
-
123
-
124
-    /**
125
-     * Use this from the context of the event editor to select the given custom template for a given message type and
126
-     * messenger.
127
-     *
128
-     * @param string $message_type_label  The visible label for the message type (eg Registration Approved)
129
-     * @param string $messenger_slug      The slug for the messenger (eg 'email')
130
-     * @param string $custom_template_label The visible label in the select input for the custom template you want
131
-     *                                      selected.
132
-     */
133
-    public function selectCustomTemplateFor($message_type_label, $messenger_slug, $custom_template_label)
134
-    {
135
-        $this->actor()->click(EventsPage::eventEditorNotificationsMetaBoxMessengerTabSelector($messenger_slug));
136
-        $this->actor()->selectOption(
137
-            EventsPage::eventEditorNotificationsMetaBoxSelectSelectorForMessageType($message_type_label),
138
-            $custom_template_label
139
-        );
140
-    }
17
+	/**
18
+	 * @param string $additional_params
19
+	 */
20
+	public function amOnDefaultEventsListTablePage($additional_params = '')
21
+	{
22
+		$this->actor()->amOnAdminPage(EventsPage::defaultEventsListTableUrl($additional_params));
23
+	}
24
+
25
+
26
+	/**
27
+	 * Triggers the publishing of the Event.
28
+	 */
29
+	public function publishEvent()
30
+	{
31
+		$this->actor()->click(EventsPage::EVENT_EDITOR_PUBLISH_BUTTON_SELECTOR);
32
+	}
33
+
34
+
35
+	/**
36
+	 * Triggers saving the Event.
37
+	 */
38
+	public function saveEvent()
39
+	{
40
+		$this->actor()->click(EventsPage::EVENT_EDITOR_SAVE_BUTTON_SELECTOR);
41
+	}
42
+
43
+
44
+	/**
45
+	 * Navigates the actor to the event list table page and will attempt to edit the event for the given title.
46
+	 * First this will search using the given title and then attempt to edit from the results of the search.
47
+	 *
48
+	 * Assumes actor is already logged in.
49
+	 * @param $event_title
50
+	 */
51
+	public function amEditingTheEventWithTitle($event_title)
52
+	{
53
+		$this->amOnDefaultEventsListTablePage();
54
+		$this->actor()->fillField(EventsPage::EVENT_LIST_TABLE_SEARCH_INPUT_SELECTOR, $event_title);
55
+		$this->actor()->click(CoreAdmin::LIST_TABLE_SEARCH_SUBMIT_SELECTOR);
56
+		$this->actor()->waitForText($event_title, 15);
57
+		$this->actor()->click(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title));
58
+	}
59
+
60
+
61
+	/**
62
+	 * Navigates the user to the single event page (frontend view) for the given event title via clicking the "View"
63
+	 * link for the event in the event list table.
64
+	 * Assumes the actor is already logged in and on the Event list table page.
65
+	 *
66
+	 * @param string $event_title
67
+	 */
68
+	public function amOnEventPageAfterClickingViewLinkInListTableForEvent($event_title)
69
+	{
70
+		$this->actor()->moveMouseOver(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title));
71
+		$this->actor()->click(EventsPage::eventListTableEventTitleViewLinkSelectorForTitle($event_title));
72
+	}
73
+
74
+
75
+	/**
76
+	 * Used to retrieve the event id for the event via the list table and for the given event.
77
+	 * @param string $event_title
78
+	 */
79
+	public function observeEventIdInListTableForEvent($event_title)
80
+	{
81
+		return $this->actor()->observeValueFromInputAt(EventsPage::eventListTableEventIdSelectorForTitle($event_title));
82
+	}
83
+
84
+
85
+	/**
86
+	 * This performs the click action on the gear icon that triggers the advanced settings view state.
87
+	 * Assumes the actor is already logged in and editing an event.
88
+	 *
89
+	 * @param int $row_number  What ticket row to toggle open/close.
90
+	 */
91
+	public function toggleAdvancedSettingsViewForTicketRow($row_number = 1)
92
+	{
93
+		$this->actor()->click(EventsPage::eventEditorTicketAdvancedDetailsSelector($row_number));
94
+	}
95
+
96
+
97
+	/**
98
+	 * Toggles the TKT_is_taxable checkbox for the ticket in the given row.
99
+	 * Assumes the actor is already logged in and editing an event and that the advanced settings view state for that
100
+	 * ticket is "open".
101
+	 *
102
+	 * @param int $row_number  What ticket row to toggle the checkbox for.
103
+	 */
104
+	public function toggleTicketIsTaxableForTicketRow($row_number = 1)
105
+	{
106
+		$this->actor()->click(EventsPage::eventEditorTicketTaxableCheckboxSelector($row_number));
107
+	}
108
+
109
+
110
+	/**
111
+	 * Use to change the default registration status for the event.
112
+	 * Assumes the view is already on the event editor.
113
+	 * @param $registration_status
114
+	 */
115
+	public function changeDefaultRegistrationStatusTo($registration_status)
116
+	{
117
+		$this->actor()->selectOption(
118
+			EventsPage::EVENT_EDITOR_DEFAULT_REGISTRATION_STATUS_FIELD_SELECTOR,
119
+			$registration_status
120
+		);
121
+	}
122
+
123
+
124
+	/**
125
+	 * Use this from the context of the event editor to select the given custom template for a given message type and
126
+	 * messenger.
127
+	 *
128
+	 * @param string $message_type_label  The visible label for the message type (eg Registration Approved)
129
+	 * @param string $messenger_slug      The slug for the messenger (eg 'email')
130
+	 * @param string $custom_template_label The visible label in the select input for the custom template you want
131
+	 *                                      selected.
132
+	 */
133
+	public function selectCustomTemplateFor($message_type_label, $messenger_slug, $custom_template_label)
134
+	{
135
+		$this->actor()->click(EventsPage::eventEditorNotificationsMetaBoxMessengerTabSelector($messenger_slug));
136
+		$this->actor()->selectOption(
137
+			EventsPage::eventEditorNotificationsMetaBoxSelectSelectorForMessageType($message_type_label),
138
+			$custom_template_label
139
+		);
140
+	}
141 141
 }
142 142
\ No newline at end of file
Please login to merge, or discard this patch.