Completed
Branch master (44537d)
by
unknown
14:30 queued 10:03
created
core/helpers/EEH_File.helper.php 2 patches
Indentation   +911 added lines, -911 removed lines patch added patch discarded remove patch
@@ -24,915 +24,915 @@
 block discarded – undo
24 24
  */
25 25
 class EEH_File extends EEH_Base implements EEHI_File
26 26
 {
27
-    /**
28
-     * @var string $_credentials_form
29
-     */
30
-    private static $_credentials_form;
31
-
32
-    /**
33
-     * @var WP_Filesystem_Base $_wp_filesystem
34
-     */
35
-    protected static $_wp_filesystem;
36
-
37
-
38
-    /**
39
-     * @param string $filepath      the filepath we want to work in. If its in the
40
-     *                              wp uploads directory, we'll want to just use the filesystem directly.
41
-     *                              If not provided, we have to assume its not in the uploads directory
42
-     * @return WP_Filesystem_Base
43
-     */
44
-    private static function _get_wp_filesystem(string $filepath = ''): WP_Filesystem_Base
45
-    {
46
-        if (
47
-            apply_filters(
48
-                'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct',
49
-                $filepath && EEH_File::is_in_uploads_folder($filepath),
50
-                $filepath
51
-            )
52
-        ) {
53
-            return EEH_File::loadAlternateWpFileSystem();
54
-        }
55
-        return EEH_File::loadWpFileSystem();
56
-    }
57
-
58
-
59
-    /**
60
-     * @return WP_Filesystem_Base
61
-     */
62
-    private static function loadAlternateWpFileSystem(): WP_Filesystem_Base
63
-    {
64
-        if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
65
-            require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
66
-            $wp_filesystem_file = apply_filters(
67
-                'filesystem_method_file',
68
-                ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php',
69
-                'direct'
70
-            );
71
-            // added the following validation logic
72
-            // because we allow the filesystem filepath to be filtered,
73
-            // and are loading whatever file the path pointed to,
74
-            // but we were not validating things in any way :scream_emoji:
75
-            $valid_wp_filesystem_types = [
76
-                'direct'     => 'WP_Filesystem_Direct',
77
-                'ftpext'     => 'WP_Filesystem_FTPext',
78
-                'ftpsockets' => 'WP_Filesystem_ftpsockets',
79
-                'ssh2'       => 'WP_Filesystem_SSH2',
80
-            ];
81
-            $valid                     = false;
82
-            $wp_filesystem_class       = '';
83
-            foreach ($valid_wp_filesystem_types as $method => $filesystem_class) {
84
-                // if file path matches for one of valid types, then toggle $valid to true
85
-                if (strpos($wp_filesystem_file, $method) > 0) {
86
-                    $valid               = true;
87
-                    $wp_filesystem_class = $filesystem_class;
88
-                }
89
-            }
90
-            if (! $valid || ! file_exists($wp_filesystem_file)) {
91
-                EE_Error::add_error(
92
-                    sprintf(
93
-                        esc_html__(
94
-                            'The supplied WP Filesystem filepath "%1$s" is either missing or invalid.',
95
-                            'event_espresso'
96
-                        ),
97
-                        $wp_filesystem_file
98
-                    ),
99
-                    __FILE__,
100
-                    __FUNCTION__,
101
-                    __LINE__
102
-                );
103
-            }
104
-            // check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
105
-            if (! defined('FS_CHMOD_DIR')) {
106
-                define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
107
-            }
108
-            if (! defined('FS_CHMOD_FILE')) {
109
-                define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
110
-            }
111
-            require_once($wp_filesystem_file);
112
-            EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
113
-        }
114
-        return EEH_File::$_wp_filesystem;
115
-    }
116
-
117
-
118
-    /**
119
-     * @return WP_Filesystem_Base
120
-     */
121
-    private static function loadWpFileSystem(): WP_Filesystem_Base
122
-    {
123
-        global $wp_filesystem;
124
-        // no filesystem setup ???
125
-        if (! $wp_filesystem instanceof WP_Filesystem_Base) {
126
-            // if some eager beaver's just trying to get in there too early...
127
-            // let them do it, because we are one of those eager beavers! :P
128
-            /**
129
-             * more explanations are probably merited.
130
-             * http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
131
-             * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
132
-             * is setup to mostly happen on 'init', and refactoring to have it happen on
133
-             * 'wp_loaded' is too much work on a BETA milestone.
134
-             * So this fix is expected to work if the WP files are owned by the server user,
135
-             * but probably not if the user needs to enter their FTP credentials to modify files
136
-             * and there may be troubles if the WP files are owned by a different user
137
-             * than the server user. But both of these issues should exist in 4.4 and earlier too
138
-             */
139
-            // if (false && ! did_action('wp_loaded')) {
140
-            //     $msg = esc_html__(
141
-            //             'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
142
-            //             'event_espresso'
143
-            //         );
144
-            //     if (WP_DEBUG) {
145
-            //         $msg .= '<br />' . esc_html__(
146
-            //             'The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.',
147
-            //             'event_espresso'
148
-            //         );
149
-            //     }
150
-            //     EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
151
-            // }
152
-            // should be loaded if we are past the wp_loaded hook...
153
-            if (! function_exists('WP_Filesystem') || ! function_exists('submit_button')) {
154
-                require_once(ABSPATH . 'wp-admin/includes/file.php');
155
-                require_once(ABSPATH . 'wp-admin/includes/template.php');
156
-            }
157
-            // turn on output buffering so that we can capture the credentials form
158
-            ob_start();
159
-            $credentials = request_filesystem_credentials(false);
160
-            // store credentials form for the time being
161
-            EEH_File::$_credentials_form = ob_get_clean();
162
-            // if credentials do NOT exist
163
-            if ($credentials === false) {
164
-                add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
165
-                EE_Error::add_error(
166
-                    esc_html__(
167
-                        'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
168
-                        'event_espresso'
169
-                    ),
170
-                    __FILE__,
171
-                    __FUNCTION__,
172
-                    __LINE__
173
-                );
174
-            }
175
-            // basically check for direct or previously configured access
176
-            if (
177
-                ! WP_Filesystem($credentials)
178
-                && is_wp_error($wp_filesystem->errors)
179
-                && $wp_filesystem->errors->get_error_code()
180
-            ) {
181
-                add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
182
-                EE_Error::add_error(
183
-                    sprintf(
184
-                        esc_html__('WP Filesystem Error: $1%s', 'event_espresso'),
185
-                        $wp_filesystem->errors->get_error_message()
186
-                    ),
187
-                    __FILE__,
188
-                    __FUNCTION__,
189
-                    __LINE__
190
-                );
191
-            }
192
-        }
193
-        return $wp_filesystem;
194
-    }
195
-
196
-
197
-    /**
198
-     * display_request_filesystem_credentials_form
199
-     */
200
-    public static function display_request_filesystem_credentials_form()
201
-    {
202
-        if (! empty(EEH_File::$_credentials_form)) {
203
-            echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
204
-        }
205
-    }
206
-
207
-
208
-    /**
209
-     *    verify_filepath_and_permissions
210
-     *    checks that a file is readable and has sufficient file permissions set to access
211
-     *
212
-     * @access public
213
-     * @param string $full_file_path - full server path to the folder or file
214
-     * @param string $file_name      - name of file if checking a file
215
-     * @param string $file_ext       - file extension (ie: "php") if checking a file
216
-     * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
217
-     * @return bool
218
-     */
219
-    public static function verify_filepath_and_permissions(
220
-        string $full_file_path = '',
221
-        string $file_name = '',
222
-        string $file_ext = '',
223
-        string $type_of_file = ''
224
-    ): bool {
225
-        // load WP_Filesystem and set file permissions
226
-        $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
-        if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
-            $file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
230
-            $file_name .= ! empty($file_ext) ? ' file' : ' folder';
231
-            $msg       = sprintf(
232
-                esc_html__(
233
-                    'The requested %1$s could not be found or is not readable, possibly due to an incorrect filepath, or incorrect file permissions.%2$s',
234
-                    'event_espresso'
235
-                ),
236
-                $file_name,
237
-                '<br />'
238
-            );
239
-            if (EEH_File::exists($full_file_path)) {
240
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, $type_of_file);
241
-            } else {
242
-                // no file permissions means the file was not found
243
-                $msg .= sprintf(
244
-                    esc_html__('Please ensure the following path is correct: "%s".', 'event_espresso'),
245
-                    $full_file_path
246
-                );
247
-            }
248
-            if (defined('WP_DEBUG') && WP_DEBUG) {
249
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
250
-            }
251
-            return false;
252
-        }
253
-        return true;
254
-    }
255
-
256
-
257
-    /**
258
-     * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a
259
-     * file or folder
260
-     *
261
-     * @access private
262
-     * @param string $full_file_path - full server path to the folder or file
263
-     * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
264
-     * @return string
265
-     */
266
-    private static function _permissions_error_for_unreadable_filepath(
267
-        string $full_file_path = '',
268
-        string $type_of_file = ''
269
-    ): string {
270
-        // load WP_Filesystem and set file permissions
271
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
272
-        // check file permissions
273
-        $perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
274
-        if ($perms) {
275
-            // file permissions exist, but way be set incorrectly
276
-            $type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
277
-            $type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
278
-            return ' ' . sprintf(
279
-                esc_html__(
280
-                    'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
281
-                    'event_espresso'
282
-                ),
283
-                $type_of_file,
284
-                $perms
285
-            );
286
-        } else {
287
-            // file exists but file permissions could not be read ?!?!
288
-            return ' ' . sprintf(
289
-                esc_html__(
290
-                    'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
291
-                    'event_espresso'
292
-                ),
293
-                $full_file_path
294
-            );
295
-        }
296
-    }
297
-
298
-
299
-    /**
300
-     * ensure_folder_exists_and_is_writable
301
-     * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
302
-     * Also ensures all the parent folders exist, and if not tries to create them.
303
-     * Also, if this function creates the folder, adds a .htaccess file and index.html file
304
-     *
305
-     * @param string $folder
306
-     * @return bool false if folder isn't writable; true if it exists and is writeable,
307
-     */
308
-    public static function ensure_folder_exists_and_is_writable(string $folder = ''): bool
309
-    {
310
-        if (empty($folder)) {
311
-            return false;
312
-        }
313
-        // remove ending /
314
-        $folder        = EEH_File::standardise_directory_separators(rtrim($folder, '/\\'));
315
-        $parent_folder = EEH_File::get_parent_folder($folder);
316
-        // add / to folder
317
-        $folder        = EEH_File::end_with_directory_separator($folder);
318
-        $wp_filesystem = EEH_File::_get_wp_filesystem($folder);
319
-        $remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
320
-        if (! $wp_filesystem->is_dir($remote_dir)) {
321
-            // ok so it doesn't exist. Does its parent? Can we write to it?
322
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
323
-                return false;
324
-            }
325
-            if (! EEH_File::verify_is_writable($parent_folder)) {
326
-                return false;
327
-            }
328
-            if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
329
-                if (defined('WP_DEBUG') && WP_DEBUG) {
330
-                    $msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
331
-                    $msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
332
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
333
-                }
334
-                return false;
335
-            }
336
-            EEH_File::add_index_file($folder);
337
-        } elseif (! EEH_File::verify_is_writable($folder)) {
338
-            return false;
339
-        }
340
-        return true;
341
-    }
342
-
343
-
344
-    /**
345
-     * verify_is_writable - checks if a file or folder is writable
346
-     *
347
-     * @param string $full_path      - full server path to file or folder
348
-     * @param string $file_or_folder - whether checking a file or folder
349
-     * @return bool
350
-     */
351
-    public static function verify_is_writable(string $full_path = '', string $file_or_folder = 'folder'): bool
352
-    {
353
-        // load WP_Filesystem and set file permissions
354
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_path);
355
-        $full_path     = EEH_File::standardise_directory_separators($full_path);
356
-        $remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
357
-        $remote_path   = rtrim($remote_path, '/\\');
358
-        if (! $wp_filesystem->is_writable($remote_path)) {
359
-            if (defined('WP_DEBUG') && WP_DEBUG) {
360
-                $msg = sprintf(esc_html__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
361
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
362
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
363
-            }
364
-            return false;
365
-        }
366
-        return true;
367
-    }
368
-
369
-
370
-    /**
371
-     * ensure_file_exists_and_is_writable
372
-     * ensures that a file exists and is writable, will attempt to create file if it does not exist.
373
-     * Also ensures all the parent folders exist, and if not tries to create them.
374
-     *
375
-     * @param string $full_file_path
376
-     * @return bool
377
-     */
378
-    public static function ensure_file_exists_and_is_writable(string $full_file_path = ''): bool
379
-    {
380
-        // load WP_Filesystem and set file permissions
381
-        $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
382
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
383
-        $parent_folder  = EEH_File::get_parent_folder($full_file_path);
384
-        if (! EEH_File::exists($full_file_path)) {
385
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
386
-                return false;
387
-            }
388
-            if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
389
-                if (defined('WP_DEBUG') && WP_DEBUG) {
390
-                    $msg = sprintf(esc_html__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
391
-                    $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
392
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
393
-                }
394
-                return false;
395
-            }
396
-        }
397
-        if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
398
-            return false;
399
-        }
400
-        return true;
401
-    }
402
-
403
-
404
-    /**
405
-     * Gets the parent folder. If provided with file, gets the folder that contains it.
406
-     * If provided a folder, gets its parent folder.
407
-     *
408
-     * @param string $file_or_folder_path
409
-     * @return string parent folder, ENDING with a directory separator
410
-     */
411
-    public static function get_parent_folder(string $file_or_folder_path): string
412
-    {
413
-        // find the last /, ignoring a / on the very end
414
-        // eg if given "/var/something/somewhere/", we want to get "somewhere"'s
415
-        // parent folder, "/var/something/"
416
-        $ds = strlen($file_or_folder_path) > 1
417
-            ? strrpos($file_or_folder_path, '/', -2)
418
-            : strlen($file_or_folder_path);
419
-        return substr($file_or_folder_path, 0, $ds + 1);
420
-    }
421
-
422
-
423
-    /**
424
-     * get_file_contents
425
-     *
426
-     * @param string $full_file_path
427
-     * @return string
428
-     */
429
-    public static function get_file_contents(string $full_file_path = ''): string
430
-    {
431
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
432
-        if (
433
-            EEH_File::verify_filepath_and_permissions(
434
-                $full_file_path,
435
-                EEH_File::get_filename_from_filepath($full_file_path),
436
-                EEH_File::get_file_extension($full_file_path)
437
-            )
438
-        ) {
439
-            // load WP_Filesystem and set file permissions
440
-            $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
441
-            return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
442
-        }
443
-        return '';
444
-    }
445
-
446
-
447
-    /**
448
-     * write_file
449
-     *
450
-     * @param string $full_file_path
451
-     * @param string $file_contents - the content to be written to the file
452
-     * @param string $file_type
453
-     * @return bool
454
-     */
455
-    public static function write_to_file(
456
-        string $full_file_path = '',
457
-        string $file_contents = '',
458
-        string $file_type = ''
459
-    ): bool {
460
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
461
-        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
462
-        $folder         = EEH_File::remove_filename_from_filepath($full_file_path);
463
-        if (! EEH_File::verify_is_writable($folder)) {
464
-            if (defined('WP_DEBUG') && WP_DEBUG) {
465
-                $msg = sprintf(
466
-                    esc_html__('The %1$sfile located at "%2$s" is not writable.', 'event_espresso'),
467
-                    $file_type,
468
-                    $full_file_path
469
-                );
470
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
471
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
472
-            }
473
-            return false;
474
-        }
475
-        // load WP_Filesystem and set file permissions
476
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
477
-        // write the file
478
-        if (
479
-            ! $wp_filesystem->put_contents(
480
-                EEH_File::convert_local_filepath_to_remote_filepath($full_file_path),
481
-                $file_contents
482
-            )
483
-        ) {
484
-            if (defined('WP_DEBUG') && WP_DEBUG) {
485
-                $msg = sprintf(
486
-                    esc_html__('The %1$sfile located at "%2$s" could not be written to.', 'event_espresso'),
487
-                    $file_type,
488
-                    $full_file_path
489
-                );
490
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, 'f');
491
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
492
-            }
493
-            return false;
494
-        }
495
-        return true;
496
-    }
497
-
498
-
499
-    /**
500
-     * Wrapper for WP_Filesystem_Base::delete
501
-     *
502
-     * @param string         $filepath
503
-     * @param boolean        $recursive
504
-     * @param boolean|string $type 'd' for directory, 'f' for file
505
-     * @return boolean
506
-     */
507
-    public static function delete(string $filepath, bool $recursive = false, $type = false): bool
508
-    {
509
-        $wp_filesystem = EEH_File::_get_wp_filesystem($filepath);
510
-        return $wp_filesystem->delete($filepath, $recursive, $type);
511
-    }
512
-
513
-
514
-    /**
515
-     * exists
516
-     * checks if a file exists using the WP filesystem
517
-     *
518
-     * @param string $full_file_path
519
-     * @return bool
520
-     */
521
-    public static function exists(string $full_file_path = ''): bool
522
-    {
523
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
524
-        return $wp_filesystem->exists(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
525
-    }
526
-
527
-
528
-    /**
529
-     * is_readable
530
-     * checks if a file is_readable using the WP filesystem
531
-     *
532
-     * @param string $full_file_path
533
-     * @return bool
534
-     */
535
-    public static function is_readable(string $full_file_path = ''): bool
536
-    {
537
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
538
-        return $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
539
-    }
540
-
541
-
542
-    /**
543
-     * remove_filename_from_filepath
544
-     * given a full path to a file including the filename itself, this removes  the filename and returns the path, up
545
-     * to, but NOT including the filename OR slash
546
-     *
547
-     * @param string $full_file_path
548
-     * @return string
549
-     */
550
-    public static function remove_filename_from_filepath(string $full_file_path = ''): string
551
-    {
552
-        return pathinfo($full_file_path, PATHINFO_DIRNAME);
553
-    }
554
-
555
-
556
-    /**
557
-     * get_filename_from_filepath. Arguably the same as basename()
558
-     *
559
-     * @param string $full_file_path
560
-     * @return string
561
-     */
562
-    public static function get_filename_from_filepath(string $full_file_path = ''): string
563
-    {
564
-        return pathinfo($full_file_path, PATHINFO_BASENAME);
565
-    }
566
-
567
-
568
-    /**
569
-     * get_file_extension
570
-     *
571
-     * @param string $full_file_path
572
-     * @return string
573
-     */
574
-    public static function get_file_extension(string $full_file_path = ''): string
575
-    {
576
-        return pathinfo($full_file_path, PATHINFO_EXTENSION);
577
-    }
578
-
579
-
580
-    /**
581
-     * add_htaccess_deny_from_all so the web server cannot access this folder
582
-     *
583
-     * @param string $folder
584
-     * @return bool
585
-     */
586
-    public static function add_htaccess_deny_from_all(string $folder = ''): bool
587
-    {
588
-        $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
589
-        if (! EEH_File::exists($folder . '.htaccess')) {
590
-            if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
591
-                return false;
592
-            }
593
-        }
594
-
595
-        return true;
596
-    }
597
-
598
-
599
-    /**
600
-     * Adds an index file to this folder, so folks can't list all the file's contents
601
-     *
602
-     * @param string $folder
603
-     * @return boolean
604
-     */
605
-    public static function add_index_file(string $folder): bool
606
-    {
607
-        $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
608
-        if (! EEH_File::exists($folder . 'index.php')) {
609
-            if (
610
-                ! EEH_File::write_to_file(
611
-                    $folder . 'index.php',
612
-                    'You are not permitted to read from this folder',
613
-                    '.php'
614
-                )
615
-            ) {
616
-                return false;
617
-            }
618
-        }
619
-        return true;
620
-    }
621
-
622
-
623
-    /**
624
-     * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
625
-     * extract that classname.
626
-     *
627
-     * @param string $file_path
628
-     * @return string
629
-     */
630
-    public static function get_classname_from_filepath_with_standard_filename(string $file_path): string
631
-    {
632
-        // extract file from path
633
-        $filename = basename($file_path);
634
-        // now remove the first period and everything after
635
-        $pos_of_first_period = strpos($filename, '.');
636
-        return substr($filename, 0, $pos_of_first_period);
637
-    }
638
-
639
-
640
-    /**
641
-     * standardise_directory_separators
642
-     *  convert all directory separators in a file path.
643
-     *
644
-     * @param string $file_path
645
-     * @param bool   $rtrim will remove trailing backslash
646
-     * @return string
647
-     */
648
-    public static function standardise_directory_separators(string $file_path, bool $rtrim = false): string
649
-    {
650
-        $file_path = $rtrim ? rtrim($file_path, '/\\') : $file_path;
651
-        return str_replace(['\\', '/'], '/', $file_path);
652
-    }
653
-
654
-
655
-    /**
656
-     * end_with_directory_separator
657
-     *  ensures that file path ends with '/'
658
-     *
659
-     * @param string $file_path
660
-     * @return string
661
-     */
662
-    public static function end_with_directory_separator(string $file_path): string
663
-    {
664
-        return rtrim($file_path, '/\\') . '/';
665
-    }
666
-
667
-
668
-    /**
669
-     * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
670
-     *
671
-     * @param string $file_path
672
-     * @return string
673
-     */
674
-    public static function standardise_and_end_with_directory_separator(string $file_path): string
675
-    {
676
-        return self::end_with_directory_separator(self::standardise_directory_separators($file_path));
677
-    }
678
-
679
-
680
-    /**
681
-     * takes the folder name (with or without trailing slash) and finds the files it in,
682
-     * and what the class's name inside of each should be.
683
-     *
684
-     * @param array   $folder_paths
685
-     * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
686
-     *                                   if FALSE (Default), returned array will be indexed by the filenames minus
687
-     *                                   extensions. Set it TRUE if you know there are files in the directory with the
688
-     *                                   same name but different extensions
689
-     * @return array if $index_numerically == TRUE keys are numeric ,
690
-     *                                   if $index_numerically == FALSE (Default) keys are what the class names SHOULD
691
-     *                                   be; and values are their file paths
692
-     */
693
-    public static function get_contents_of_folders(array $folder_paths = [], bool $index_numerically = false): array
694
-    {
695
-        $class_to_folder_path = [];
696
-        foreach ($folder_paths as $folder_path) {
697
-            $folder_path = self::standardise_and_end_with_directory_separator($folder_path);
698
-            // load WP_Filesystem and set file permissions
699
-            $files_in_folder      = glob($folder_path . '*.php');
700
-            $class_to_folder_path = [];
701
-            if ($files_in_folder) {
702
-                foreach ($files_in_folder as $file_path) {
703
-                    // only add files, not folders
704
-                    if (! is_dir($file_path)) {
705
-                        if ($index_numerically) {
706
-                            $class_to_folder_path[] = $file_path;
707
-                        } else {
708
-                            $classname                          =
709
-                                self::get_classname_from_filepath_with_standard_filename($file_path);
710
-                            $class_to_folder_path[ $classname ] = $file_path;
711
-                        }
712
-                    }
713
-                }
714
-            }
715
-        }
716
-        return $class_to_folder_path;
717
-    }
718
-
719
-
720
-    /**
721
-     * Copies a file. Mostly a wrapper of WP_Filesystem::copy
722
-     *
723
-     * @param string  $source_file
724
-     * @param string  $destination_file
725
-     * @param boolean $overwrite
726
-     * @return boolean success
727
-     */
728
-    public static function copy(string $source_file, string $destination_file, bool $overwrite = false): bool
729
-    {
730
-        $source_file      = EEH_File::validateFileForCopyOrMove($source_file);
731
-        $destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
732
-        if (! $source_file || ! $destination_file) {
733
-            return false;
734
-        }
735
-        // load WP_Filesystem and set file permissions
736
-        $wp_filesystem = EEH_File::_get_wp_filesystem($destination_file);
737
-        // write the file
738
-        $copied = $wp_filesystem->copy(
739
-            EEH_File::convert_local_filepath_to_remote_filepath($source_file),
740
-            EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
741
-            $overwrite
742
-        );
743
-        if (! $copied) {
744
-            if (defined('WP_DEBUG') && WP_DEBUG) {
745
-                $msg = sprintf(
746
-                    esc_html__(
747
-                        'Attempted writing to file %1$s, but could not, probably because of permissions issues',
748
-                        'event_espresso'
749
-                    ),
750
-                    $source_file
751
-                );
752
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($source_file, 'f');
753
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
754
-            }
755
-            return false;
756
-        }
757
-        return true;
758
-    }
759
-
760
-
761
-    /**
762
-     * Reports whether or not the filepath is in the EE uploads folder or not
763
-     *
764
-     * @param string $filepath
765
-     * @return boolean
766
-     */
767
-    public static function is_in_uploads_folder(string $filepath): bool
768
-    {
769
-        $uploads = wp_upload_dir();
770
-        return strpos($filepath, $uploads['basedir']) === 0;
771
-    }
772
-
773
-
774
-    /**
775
-     * Given a "local" filepath (what you probably thought was the only filepath),
776
-     * converts it into a "remote" filepath (the filepath the currently-in-use
777
-     * $wp_filesystem needs to use access the folder or file).
778
-     * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
779
-     *
780
-     * @param string $local_filepath the filepath to the folder/file locally
781
-     * @return string the remote filepath (eg the filepath the filesystem method, eg
782
-     *                               ftp or ssh, will use to access the folder
783
-     */
784
-    public static function convert_local_filepath_to_remote_filepath(string $local_filepath): string
785
-    {
786
-        $wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
787
-        return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
788
-    }
789
-
790
-
791
-    /**
792
-     * wrapper for WP_Filesystem::chmod()
793
-     *
794
-     * @param string    $file      Path to the file.
795
-     * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
796
-     *                             0755 for directories. Default false.
797
-     * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
798
-     *                             Default false.
799
-     * @return bool True on success, false on failure.
800
-     */
801
-    public static function chmod(string $file, $mode = false, bool $recursive = false): bool
802
-    {
803
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
804
-        return $wp_filesystem->chmod($file, $mode, $recursive);
805
-    }
806
-
807
-
808
-    /**
809
-     * wrapper for WP_Filesystem::getchmod()
810
-     *
811
-     * @param string $file Path to the file.
812
-     * @return string Mode of the file (the last 3 digits).
813
-     */
814
-    public static function permissions(string $file): string
815
-    {
816
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
817
-        return $wp_filesystem->getchmod($file);
818
-    }
819
-
820
-
821
-    /**
822
-     * wrapper for WP_Filesystem::owner()
823
-     *
824
-     * @param string $file Path to the file.
825
-     * @return string|false Username of the owner on success, false on failure.
826
-     */
827
-    public static function owner(string $file)
828
-    {
829
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
830
-        return $wp_filesystem->owner($file);
831
-    }
832
-
833
-
834
-    /**
835
-     * wrapper for WP_Filesystem::group()
836
-     *
837
-     * @param string $file Path to the file.
838
-     * @return string|false The group on success, false on failure.
839
-     */
840
-    public static function group(string $file)
841
-    {
842
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
843
-        return $wp_filesystem->group($file);
844
-    }
845
-
846
-
847
-    /**
848
-     * wrapper for WP_Filesystem::move()
849
-     *
850
-     * @param string $source      Path to the source file.
851
-     * @param string $destination Path to the destination file.
852
-     * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
853
-     *                            Default false.
854
-     * @return bool True on success, false on failure.
855
-     */
856
-    public static function move(string $source, string $destination, bool $overwrite = false): bool
857
-    {
858
-        // throw new RuntimeException("source: {$source} && destination: {$destination}");
859
-        $source      = EEH_File::validateFileForCopyOrMove($source);
860
-        $destination = EEH_File::validateFolderForCopyOrMove($destination);
861
-        if (! $source || ! $destination) {
862
-            return false;
863
-        }
864
-        $wp_filesystem = EEH_File::_get_wp_filesystem($source);
865
-        if ($wp_filesystem->move($source, $destination, $overwrite)) {
866
-            return true;
867
-        }
868
-        if (defined('WP_DEBUG') && WP_DEBUG) {
869
-            $file        = EEH_File::convert_local_filepath_to_remote_filepath($source);
870
-            $owner       = EEH_File::owner($file);
871
-            $group       = EEH_File::group($file);
872
-            $permissions = EEH_File::permissions($file);
873
-            EE_Error::add_error(
874
-                sprintf(
875
-                    esc_html__(
876
-                        'Unable to move the file "%1$s" to new location (possible permissions errors). The existing "owner:group permissions" for the file are: "%2$s"',
877
-                        'event_espresso'
878
-                    ),
879
-                    $destination,
880
-                    "{$owner}:{$group} $permissions"
881
-                ),
882
-                __FILE__,
883
-                __FUNCTION__,
884
-                __LINE__
885
-            );
886
-        }
887
-        return false;
888
-    }
889
-
890
-
891
-    /**
892
-     * @param string $source_file
893
-     * @return string
894
-     */
895
-    private static function validateFileForCopyOrMove(string $source_file): string
896
-    {
897
-        $full_source_path = EEH_File::standardise_directory_separators($source_file);
898
-        if (! EEH_File::exists($full_source_path)) {
899
-            if (defined('WP_DEBUG') && WP_DEBUG) {
900
-                $msg =
901
-                    sprintf(
902
-                        esc_html__('The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso'),
903
-                        '',
904
-                        $full_source_path
905
-                    );
906
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_source_path);
907
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
908
-            }
909
-            return '';
910
-        }
911
-        return $full_source_path;
912
-    }
913
-
914
-
915
-    /**
916
-     * @param string $destination_file
917
-     * @return string
918
-     */
919
-    private static function validateFolderForCopyOrMove(string $destination_file): string
920
-    {
921
-        $full_dest_path = EEH_File::standardise_directory_separators($destination_file);
922
-        $folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
923
-        EEH_File::ensure_folder_exists_and_is_writable($folder);
924
-        if (! EEH_File::verify_is_writable($folder)) {
925
-            if (defined('WP_DEBUG') && WP_DEBUG) {
926
-                $msg = sprintf(
927
-                    esc_html__('The file located at "%2$s" is not writable.', 'event_espresso'),
928
-                    '',
929
-                    $full_dest_path
930
-                );
931
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_dest_path);
932
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
933
-            }
934
-            return '';
935
-        }
936
-        return $full_dest_path;
937
-    }
27
+	/**
28
+	 * @var string $_credentials_form
29
+	 */
30
+	private static $_credentials_form;
31
+
32
+	/**
33
+	 * @var WP_Filesystem_Base $_wp_filesystem
34
+	 */
35
+	protected static $_wp_filesystem;
36
+
37
+
38
+	/**
39
+	 * @param string $filepath      the filepath we want to work in. If its in the
40
+	 *                              wp uploads directory, we'll want to just use the filesystem directly.
41
+	 *                              If not provided, we have to assume its not in the uploads directory
42
+	 * @return WP_Filesystem_Base
43
+	 */
44
+	private static function _get_wp_filesystem(string $filepath = ''): WP_Filesystem_Base
45
+	{
46
+		if (
47
+			apply_filters(
48
+				'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct',
49
+				$filepath && EEH_File::is_in_uploads_folder($filepath),
50
+				$filepath
51
+			)
52
+		) {
53
+			return EEH_File::loadAlternateWpFileSystem();
54
+		}
55
+		return EEH_File::loadWpFileSystem();
56
+	}
57
+
58
+
59
+	/**
60
+	 * @return WP_Filesystem_Base
61
+	 */
62
+	private static function loadAlternateWpFileSystem(): WP_Filesystem_Base
63
+	{
64
+		if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
65
+			require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
66
+			$wp_filesystem_file = apply_filters(
67
+				'filesystem_method_file',
68
+				ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php',
69
+				'direct'
70
+			);
71
+			// added the following validation logic
72
+			// because we allow the filesystem filepath to be filtered,
73
+			// and are loading whatever file the path pointed to,
74
+			// but we were not validating things in any way :scream_emoji:
75
+			$valid_wp_filesystem_types = [
76
+				'direct'     => 'WP_Filesystem_Direct',
77
+				'ftpext'     => 'WP_Filesystem_FTPext',
78
+				'ftpsockets' => 'WP_Filesystem_ftpsockets',
79
+				'ssh2'       => 'WP_Filesystem_SSH2',
80
+			];
81
+			$valid                     = false;
82
+			$wp_filesystem_class       = '';
83
+			foreach ($valid_wp_filesystem_types as $method => $filesystem_class) {
84
+				// if file path matches for one of valid types, then toggle $valid to true
85
+				if (strpos($wp_filesystem_file, $method) > 0) {
86
+					$valid               = true;
87
+					$wp_filesystem_class = $filesystem_class;
88
+				}
89
+			}
90
+			if (! $valid || ! file_exists($wp_filesystem_file)) {
91
+				EE_Error::add_error(
92
+					sprintf(
93
+						esc_html__(
94
+							'The supplied WP Filesystem filepath "%1$s" is either missing or invalid.',
95
+							'event_espresso'
96
+						),
97
+						$wp_filesystem_file
98
+					),
99
+					__FILE__,
100
+					__FUNCTION__,
101
+					__LINE__
102
+				);
103
+			}
104
+			// check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
105
+			if (! defined('FS_CHMOD_DIR')) {
106
+				define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
107
+			}
108
+			if (! defined('FS_CHMOD_FILE')) {
109
+				define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
110
+			}
111
+			require_once($wp_filesystem_file);
112
+			EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
113
+		}
114
+		return EEH_File::$_wp_filesystem;
115
+	}
116
+
117
+
118
+	/**
119
+	 * @return WP_Filesystem_Base
120
+	 */
121
+	private static function loadWpFileSystem(): WP_Filesystem_Base
122
+	{
123
+		global $wp_filesystem;
124
+		// no filesystem setup ???
125
+		if (! $wp_filesystem instanceof WP_Filesystem_Base) {
126
+			// if some eager beaver's just trying to get in there too early...
127
+			// let them do it, because we are one of those eager beavers! :P
128
+			/**
129
+			 * more explanations are probably merited.
130
+			 * http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
131
+			 * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
132
+			 * is setup to mostly happen on 'init', and refactoring to have it happen on
133
+			 * 'wp_loaded' is too much work on a BETA milestone.
134
+			 * So this fix is expected to work if the WP files are owned by the server user,
135
+			 * but probably not if the user needs to enter their FTP credentials to modify files
136
+			 * and there may be troubles if the WP files are owned by a different user
137
+			 * than the server user. But both of these issues should exist in 4.4 and earlier too
138
+			 */
139
+			// if (false && ! did_action('wp_loaded')) {
140
+			//     $msg = esc_html__(
141
+			//             'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
142
+			//             'event_espresso'
143
+			//         );
144
+			//     if (WP_DEBUG) {
145
+			//         $msg .= '<br />' . esc_html__(
146
+			//             'The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.',
147
+			//             'event_espresso'
148
+			//         );
149
+			//     }
150
+			//     EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
151
+			// }
152
+			// should be loaded if we are past the wp_loaded hook...
153
+			if (! function_exists('WP_Filesystem') || ! function_exists('submit_button')) {
154
+				require_once(ABSPATH . 'wp-admin/includes/file.php');
155
+				require_once(ABSPATH . 'wp-admin/includes/template.php');
156
+			}
157
+			// turn on output buffering so that we can capture the credentials form
158
+			ob_start();
159
+			$credentials = request_filesystem_credentials(false);
160
+			// store credentials form for the time being
161
+			EEH_File::$_credentials_form = ob_get_clean();
162
+			// if credentials do NOT exist
163
+			if ($credentials === false) {
164
+				add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
165
+				EE_Error::add_error(
166
+					esc_html__(
167
+						'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
168
+						'event_espresso'
169
+					),
170
+					__FILE__,
171
+					__FUNCTION__,
172
+					__LINE__
173
+				);
174
+			}
175
+			// basically check for direct or previously configured access
176
+			if (
177
+				! WP_Filesystem($credentials)
178
+				&& is_wp_error($wp_filesystem->errors)
179
+				&& $wp_filesystem->errors->get_error_code()
180
+			) {
181
+				add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
182
+				EE_Error::add_error(
183
+					sprintf(
184
+						esc_html__('WP Filesystem Error: $1%s', 'event_espresso'),
185
+						$wp_filesystem->errors->get_error_message()
186
+					),
187
+					__FILE__,
188
+					__FUNCTION__,
189
+					__LINE__
190
+				);
191
+			}
192
+		}
193
+		return $wp_filesystem;
194
+	}
195
+
196
+
197
+	/**
198
+	 * display_request_filesystem_credentials_form
199
+	 */
200
+	public static function display_request_filesystem_credentials_form()
201
+	{
202
+		if (! empty(EEH_File::$_credentials_form)) {
203
+			echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
204
+		}
205
+	}
206
+
207
+
208
+	/**
209
+	 *    verify_filepath_and_permissions
210
+	 *    checks that a file is readable and has sufficient file permissions set to access
211
+	 *
212
+	 * @access public
213
+	 * @param string $full_file_path - full server path to the folder or file
214
+	 * @param string $file_name      - name of file if checking a file
215
+	 * @param string $file_ext       - file extension (ie: "php") if checking a file
216
+	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
217
+	 * @return bool
218
+	 */
219
+	public static function verify_filepath_and_permissions(
220
+		string $full_file_path = '',
221
+		string $file_name = '',
222
+		string $file_ext = '',
223
+		string $type_of_file = ''
224
+	): bool {
225
+		// load WP_Filesystem and set file permissions
226
+		$wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
+		if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
+			$file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
230
+			$file_name .= ! empty($file_ext) ? ' file' : ' folder';
231
+			$msg       = sprintf(
232
+				esc_html__(
233
+					'The requested %1$s could not be found or is not readable, possibly due to an incorrect filepath, or incorrect file permissions.%2$s',
234
+					'event_espresso'
235
+				),
236
+				$file_name,
237
+				'<br />'
238
+			);
239
+			if (EEH_File::exists($full_file_path)) {
240
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, $type_of_file);
241
+			} else {
242
+				// no file permissions means the file was not found
243
+				$msg .= sprintf(
244
+					esc_html__('Please ensure the following path is correct: "%s".', 'event_espresso'),
245
+					$full_file_path
246
+				);
247
+			}
248
+			if (defined('WP_DEBUG') && WP_DEBUG) {
249
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
250
+			}
251
+			return false;
252
+		}
253
+		return true;
254
+	}
255
+
256
+
257
+	/**
258
+	 * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a
259
+	 * file or folder
260
+	 *
261
+	 * @access private
262
+	 * @param string $full_file_path - full server path to the folder or file
263
+	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
264
+	 * @return string
265
+	 */
266
+	private static function _permissions_error_for_unreadable_filepath(
267
+		string $full_file_path = '',
268
+		string $type_of_file = ''
269
+	): string {
270
+		// load WP_Filesystem and set file permissions
271
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
272
+		// check file permissions
273
+		$perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
274
+		if ($perms) {
275
+			// file permissions exist, but way be set incorrectly
276
+			$type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
277
+			$type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
278
+			return ' ' . sprintf(
279
+				esc_html__(
280
+					'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
281
+					'event_espresso'
282
+				),
283
+				$type_of_file,
284
+				$perms
285
+			);
286
+		} else {
287
+			// file exists but file permissions could not be read ?!?!
288
+			return ' ' . sprintf(
289
+				esc_html__(
290
+					'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
291
+					'event_espresso'
292
+				),
293
+				$full_file_path
294
+			);
295
+		}
296
+	}
297
+
298
+
299
+	/**
300
+	 * ensure_folder_exists_and_is_writable
301
+	 * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
302
+	 * Also ensures all the parent folders exist, and if not tries to create them.
303
+	 * Also, if this function creates the folder, adds a .htaccess file and index.html file
304
+	 *
305
+	 * @param string $folder
306
+	 * @return bool false if folder isn't writable; true if it exists and is writeable,
307
+	 */
308
+	public static function ensure_folder_exists_and_is_writable(string $folder = ''): bool
309
+	{
310
+		if (empty($folder)) {
311
+			return false;
312
+		}
313
+		// remove ending /
314
+		$folder        = EEH_File::standardise_directory_separators(rtrim($folder, '/\\'));
315
+		$parent_folder = EEH_File::get_parent_folder($folder);
316
+		// add / to folder
317
+		$folder        = EEH_File::end_with_directory_separator($folder);
318
+		$wp_filesystem = EEH_File::_get_wp_filesystem($folder);
319
+		$remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
320
+		if (! $wp_filesystem->is_dir($remote_dir)) {
321
+			// ok so it doesn't exist. Does its parent? Can we write to it?
322
+			if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
323
+				return false;
324
+			}
325
+			if (! EEH_File::verify_is_writable($parent_folder)) {
326
+				return false;
327
+			}
328
+			if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
329
+				if (defined('WP_DEBUG') && WP_DEBUG) {
330
+					$msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
331
+					$msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
332
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
333
+				}
334
+				return false;
335
+			}
336
+			EEH_File::add_index_file($folder);
337
+		} elseif (! EEH_File::verify_is_writable($folder)) {
338
+			return false;
339
+		}
340
+		return true;
341
+	}
342
+
343
+
344
+	/**
345
+	 * verify_is_writable - checks if a file or folder is writable
346
+	 *
347
+	 * @param string $full_path      - full server path to file or folder
348
+	 * @param string $file_or_folder - whether checking a file or folder
349
+	 * @return bool
350
+	 */
351
+	public static function verify_is_writable(string $full_path = '', string $file_or_folder = 'folder'): bool
352
+	{
353
+		// load WP_Filesystem and set file permissions
354
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_path);
355
+		$full_path     = EEH_File::standardise_directory_separators($full_path);
356
+		$remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
357
+		$remote_path   = rtrim($remote_path, '/\\');
358
+		if (! $wp_filesystem->is_writable($remote_path)) {
359
+			if (defined('WP_DEBUG') && WP_DEBUG) {
360
+				$msg = sprintf(esc_html__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
361
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
362
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
363
+			}
364
+			return false;
365
+		}
366
+		return true;
367
+	}
368
+
369
+
370
+	/**
371
+	 * ensure_file_exists_and_is_writable
372
+	 * ensures that a file exists and is writable, will attempt to create file if it does not exist.
373
+	 * Also ensures all the parent folders exist, and if not tries to create them.
374
+	 *
375
+	 * @param string $full_file_path
376
+	 * @return bool
377
+	 */
378
+	public static function ensure_file_exists_and_is_writable(string $full_file_path = ''): bool
379
+	{
380
+		// load WP_Filesystem and set file permissions
381
+		$wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
382
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
383
+		$parent_folder  = EEH_File::get_parent_folder($full_file_path);
384
+		if (! EEH_File::exists($full_file_path)) {
385
+			if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
386
+				return false;
387
+			}
388
+			if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
389
+				if (defined('WP_DEBUG') && WP_DEBUG) {
390
+					$msg = sprintf(esc_html__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
391
+					$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
392
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
393
+				}
394
+				return false;
395
+			}
396
+		}
397
+		if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
398
+			return false;
399
+		}
400
+		return true;
401
+	}
402
+
403
+
404
+	/**
405
+	 * Gets the parent folder. If provided with file, gets the folder that contains it.
406
+	 * If provided a folder, gets its parent folder.
407
+	 *
408
+	 * @param string $file_or_folder_path
409
+	 * @return string parent folder, ENDING with a directory separator
410
+	 */
411
+	public static function get_parent_folder(string $file_or_folder_path): string
412
+	{
413
+		// find the last /, ignoring a / on the very end
414
+		// eg if given "/var/something/somewhere/", we want to get "somewhere"'s
415
+		// parent folder, "/var/something/"
416
+		$ds = strlen($file_or_folder_path) > 1
417
+			? strrpos($file_or_folder_path, '/', -2)
418
+			: strlen($file_or_folder_path);
419
+		return substr($file_or_folder_path, 0, $ds + 1);
420
+	}
421
+
422
+
423
+	/**
424
+	 * get_file_contents
425
+	 *
426
+	 * @param string $full_file_path
427
+	 * @return string
428
+	 */
429
+	public static function get_file_contents(string $full_file_path = ''): string
430
+	{
431
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
432
+		if (
433
+			EEH_File::verify_filepath_and_permissions(
434
+				$full_file_path,
435
+				EEH_File::get_filename_from_filepath($full_file_path),
436
+				EEH_File::get_file_extension($full_file_path)
437
+			)
438
+		) {
439
+			// load WP_Filesystem and set file permissions
440
+			$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
441
+			return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
442
+		}
443
+		return '';
444
+	}
445
+
446
+
447
+	/**
448
+	 * write_file
449
+	 *
450
+	 * @param string $full_file_path
451
+	 * @param string $file_contents - the content to be written to the file
452
+	 * @param string $file_type
453
+	 * @return bool
454
+	 */
455
+	public static function write_to_file(
456
+		string $full_file_path = '',
457
+		string $file_contents = '',
458
+		string $file_type = ''
459
+	): bool {
460
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
461
+		$file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
462
+		$folder         = EEH_File::remove_filename_from_filepath($full_file_path);
463
+		if (! EEH_File::verify_is_writable($folder)) {
464
+			if (defined('WP_DEBUG') && WP_DEBUG) {
465
+				$msg = sprintf(
466
+					esc_html__('The %1$sfile located at "%2$s" is not writable.', 'event_espresso'),
467
+					$file_type,
468
+					$full_file_path
469
+				);
470
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
471
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
472
+			}
473
+			return false;
474
+		}
475
+		// load WP_Filesystem and set file permissions
476
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
477
+		// write the file
478
+		if (
479
+			! $wp_filesystem->put_contents(
480
+				EEH_File::convert_local_filepath_to_remote_filepath($full_file_path),
481
+				$file_contents
482
+			)
483
+		) {
484
+			if (defined('WP_DEBUG') && WP_DEBUG) {
485
+				$msg = sprintf(
486
+					esc_html__('The %1$sfile located at "%2$s" could not be written to.', 'event_espresso'),
487
+					$file_type,
488
+					$full_file_path
489
+				);
490
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, 'f');
491
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
492
+			}
493
+			return false;
494
+		}
495
+		return true;
496
+	}
497
+
498
+
499
+	/**
500
+	 * Wrapper for WP_Filesystem_Base::delete
501
+	 *
502
+	 * @param string         $filepath
503
+	 * @param boolean        $recursive
504
+	 * @param boolean|string $type 'd' for directory, 'f' for file
505
+	 * @return boolean
506
+	 */
507
+	public static function delete(string $filepath, bool $recursive = false, $type = false): bool
508
+	{
509
+		$wp_filesystem = EEH_File::_get_wp_filesystem($filepath);
510
+		return $wp_filesystem->delete($filepath, $recursive, $type);
511
+	}
512
+
513
+
514
+	/**
515
+	 * exists
516
+	 * checks if a file exists using the WP filesystem
517
+	 *
518
+	 * @param string $full_file_path
519
+	 * @return bool
520
+	 */
521
+	public static function exists(string $full_file_path = ''): bool
522
+	{
523
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
524
+		return $wp_filesystem->exists(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
525
+	}
526
+
527
+
528
+	/**
529
+	 * is_readable
530
+	 * checks if a file is_readable using the WP filesystem
531
+	 *
532
+	 * @param string $full_file_path
533
+	 * @return bool
534
+	 */
535
+	public static function is_readable(string $full_file_path = ''): bool
536
+	{
537
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
538
+		return $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
539
+	}
540
+
541
+
542
+	/**
543
+	 * remove_filename_from_filepath
544
+	 * given a full path to a file including the filename itself, this removes  the filename and returns the path, up
545
+	 * to, but NOT including the filename OR slash
546
+	 *
547
+	 * @param string $full_file_path
548
+	 * @return string
549
+	 */
550
+	public static function remove_filename_from_filepath(string $full_file_path = ''): string
551
+	{
552
+		return pathinfo($full_file_path, PATHINFO_DIRNAME);
553
+	}
554
+
555
+
556
+	/**
557
+	 * get_filename_from_filepath. Arguably the same as basename()
558
+	 *
559
+	 * @param string $full_file_path
560
+	 * @return string
561
+	 */
562
+	public static function get_filename_from_filepath(string $full_file_path = ''): string
563
+	{
564
+		return pathinfo($full_file_path, PATHINFO_BASENAME);
565
+	}
566
+
567
+
568
+	/**
569
+	 * get_file_extension
570
+	 *
571
+	 * @param string $full_file_path
572
+	 * @return string
573
+	 */
574
+	public static function get_file_extension(string $full_file_path = ''): string
575
+	{
576
+		return pathinfo($full_file_path, PATHINFO_EXTENSION);
577
+	}
578
+
579
+
580
+	/**
581
+	 * add_htaccess_deny_from_all so the web server cannot access this folder
582
+	 *
583
+	 * @param string $folder
584
+	 * @return bool
585
+	 */
586
+	public static function add_htaccess_deny_from_all(string $folder = ''): bool
587
+	{
588
+		$folder = EEH_File::standardise_and_end_with_directory_separator($folder);
589
+		if (! EEH_File::exists($folder . '.htaccess')) {
590
+			if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
591
+				return false;
592
+			}
593
+		}
594
+
595
+		return true;
596
+	}
597
+
598
+
599
+	/**
600
+	 * Adds an index file to this folder, so folks can't list all the file's contents
601
+	 *
602
+	 * @param string $folder
603
+	 * @return boolean
604
+	 */
605
+	public static function add_index_file(string $folder): bool
606
+	{
607
+		$folder = EEH_File::standardise_and_end_with_directory_separator($folder);
608
+		if (! EEH_File::exists($folder . 'index.php')) {
609
+			if (
610
+				! EEH_File::write_to_file(
611
+					$folder . 'index.php',
612
+					'You are not permitted to read from this folder',
613
+					'.php'
614
+				)
615
+			) {
616
+				return false;
617
+			}
618
+		}
619
+		return true;
620
+	}
621
+
622
+
623
+	/**
624
+	 * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
625
+	 * extract that classname.
626
+	 *
627
+	 * @param string $file_path
628
+	 * @return string
629
+	 */
630
+	public static function get_classname_from_filepath_with_standard_filename(string $file_path): string
631
+	{
632
+		// extract file from path
633
+		$filename = basename($file_path);
634
+		// now remove the first period and everything after
635
+		$pos_of_first_period = strpos($filename, '.');
636
+		return substr($filename, 0, $pos_of_first_period);
637
+	}
638
+
639
+
640
+	/**
641
+	 * standardise_directory_separators
642
+	 *  convert all directory separators in a file path.
643
+	 *
644
+	 * @param string $file_path
645
+	 * @param bool   $rtrim will remove trailing backslash
646
+	 * @return string
647
+	 */
648
+	public static function standardise_directory_separators(string $file_path, bool $rtrim = false): string
649
+	{
650
+		$file_path = $rtrim ? rtrim($file_path, '/\\') : $file_path;
651
+		return str_replace(['\\', '/'], '/', $file_path);
652
+	}
653
+
654
+
655
+	/**
656
+	 * end_with_directory_separator
657
+	 *  ensures that file path ends with '/'
658
+	 *
659
+	 * @param string $file_path
660
+	 * @return string
661
+	 */
662
+	public static function end_with_directory_separator(string $file_path): string
663
+	{
664
+		return rtrim($file_path, '/\\') . '/';
665
+	}
666
+
667
+
668
+	/**
669
+	 * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
670
+	 *
671
+	 * @param string $file_path
672
+	 * @return string
673
+	 */
674
+	public static function standardise_and_end_with_directory_separator(string $file_path): string
675
+	{
676
+		return self::end_with_directory_separator(self::standardise_directory_separators($file_path));
677
+	}
678
+
679
+
680
+	/**
681
+	 * takes the folder name (with or without trailing slash) and finds the files it in,
682
+	 * and what the class's name inside of each should be.
683
+	 *
684
+	 * @param array   $folder_paths
685
+	 * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
686
+	 *                                   if FALSE (Default), returned array will be indexed by the filenames minus
687
+	 *                                   extensions. Set it TRUE if you know there are files in the directory with the
688
+	 *                                   same name but different extensions
689
+	 * @return array if $index_numerically == TRUE keys are numeric ,
690
+	 *                                   if $index_numerically == FALSE (Default) keys are what the class names SHOULD
691
+	 *                                   be; and values are their file paths
692
+	 */
693
+	public static function get_contents_of_folders(array $folder_paths = [], bool $index_numerically = false): array
694
+	{
695
+		$class_to_folder_path = [];
696
+		foreach ($folder_paths as $folder_path) {
697
+			$folder_path = self::standardise_and_end_with_directory_separator($folder_path);
698
+			// load WP_Filesystem and set file permissions
699
+			$files_in_folder      = glob($folder_path . '*.php');
700
+			$class_to_folder_path = [];
701
+			if ($files_in_folder) {
702
+				foreach ($files_in_folder as $file_path) {
703
+					// only add files, not folders
704
+					if (! is_dir($file_path)) {
705
+						if ($index_numerically) {
706
+							$class_to_folder_path[] = $file_path;
707
+						} else {
708
+							$classname                          =
709
+								self::get_classname_from_filepath_with_standard_filename($file_path);
710
+							$class_to_folder_path[ $classname ] = $file_path;
711
+						}
712
+					}
713
+				}
714
+			}
715
+		}
716
+		return $class_to_folder_path;
717
+	}
718
+
719
+
720
+	/**
721
+	 * Copies a file. Mostly a wrapper of WP_Filesystem::copy
722
+	 *
723
+	 * @param string  $source_file
724
+	 * @param string  $destination_file
725
+	 * @param boolean $overwrite
726
+	 * @return boolean success
727
+	 */
728
+	public static function copy(string $source_file, string $destination_file, bool $overwrite = false): bool
729
+	{
730
+		$source_file      = EEH_File::validateFileForCopyOrMove($source_file);
731
+		$destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
732
+		if (! $source_file || ! $destination_file) {
733
+			return false;
734
+		}
735
+		// load WP_Filesystem and set file permissions
736
+		$wp_filesystem = EEH_File::_get_wp_filesystem($destination_file);
737
+		// write the file
738
+		$copied = $wp_filesystem->copy(
739
+			EEH_File::convert_local_filepath_to_remote_filepath($source_file),
740
+			EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
741
+			$overwrite
742
+		);
743
+		if (! $copied) {
744
+			if (defined('WP_DEBUG') && WP_DEBUG) {
745
+				$msg = sprintf(
746
+					esc_html__(
747
+						'Attempted writing to file %1$s, but could not, probably because of permissions issues',
748
+						'event_espresso'
749
+					),
750
+					$source_file
751
+				);
752
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($source_file, 'f');
753
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
754
+			}
755
+			return false;
756
+		}
757
+		return true;
758
+	}
759
+
760
+
761
+	/**
762
+	 * Reports whether or not the filepath is in the EE uploads folder or not
763
+	 *
764
+	 * @param string $filepath
765
+	 * @return boolean
766
+	 */
767
+	public static function is_in_uploads_folder(string $filepath): bool
768
+	{
769
+		$uploads = wp_upload_dir();
770
+		return strpos($filepath, $uploads['basedir']) === 0;
771
+	}
772
+
773
+
774
+	/**
775
+	 * Given a "local" filepath (what you probably thought was the only filepath),
776
+	 * converts it into a "remote" filepath (the filepath the currently-in-use
777
+	 * $wp_filesystem needs to use access the folder or file).
778
+	 * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
779
+	 *
780
+	 * @param string $local_filepath the filepath to the folder/file locally
781
+	 * @return string the remote filepath (eg the filepath the filesystem method, eg
782
+	 *                               ftp or ssh, will use to access the folder
783
+	 */
784
+	public static function convert_local_filepath_to_remote_filepath(string $local_filepath): string
785
+	{
786
+		$wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
787
+		return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
788
+	}
789
+
790
+
791
+	/**
792
+	 * wrapper for WP_Filesystem::chmod()
793
+	 *
794
+	 * @param string    $file      Path to the file.
795
+	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
796
+	 *                             0755 for directories. Default false.
797
+	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
798
+	 *                             Default false.
799
+	 * @return bool True on success, false on failure.
800
+	 */
801
+	public static function chmod(string $file, $mode = false, bool $recursive = false): bool
802
+	{
803
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
804
+		return $wp_filesystem->chmod($file, $mode, $recursive);
805
+	}
806
+
807
+
808
+	/**
809
+	 * wrapper for WP_Filesystem::getchmod()
810
+	 *
811
+	 * @param string $file Path to the file.
812
+	 * @return string Mode of the file (the last 3 digits).
813
+	 */
814
+	public static function permissions(string $file): string
815
+	{
816
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
817
+		return $wp_filesystem->getchmod($file);
818
+	}
819
+
820
+
821
+	/**
822
+	 * wrapper for WP_Filesystem::owner()
823
+	 *
824
+	 * @param string $file Path to the file.
825
+	 * @return string|false Username of the owner on success, false on failure.
826
+	 */
827
+	public static function owner(string $file)
828
+	{
829
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
830
+		return $wp_filesystem->owner($file);
831
+	}
832
+
833
+
834
+	/**
835
+	 * wrapper for WP_Filesystem::group()
836
+	 *
837
+	 * @param string $file Path to the file.
838
+	 * @return string|false The group on success, false on failure.
839
+	 */
840
+	public static function group(string $file)
841
+	{
842
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
843
+		return $wp_filesystem->group($file);
844
+	}
845
+
846
+
847
+	/**
848
+	 * wrapper for WP_Filesystem::move()
849
+	 *
850
+	 * @param string $source      Path to the source file.
851
+	 * @param string $destination Path to the destination file.
852
+	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
853
+	 *                            Default false.
854
+	 * @return bool True on success, false on failure.
855
+	 */
856
+	public static function move(string $source, string $destination, bool $overwrite = false): bool
857
+	{
858
+		// throw new RuntimeException("source: {$source} && destination: {$destination}");
859
+		$source      = EEH_File::validateFileForCopyOrMove($source);
860
+		$destination = EEH_File::validateFolderForCopyOrMove($destination);
861
+		if (! $source || ! $destination) {
862
+			return false;
863
+		}
864
+		$wp_filesystem = EEH_File::_get_wp_filesystem($source);
865
+		if ($wp_filesystem->move($source, $destination, $overwrite)) {
866
+			return true;
867
+		}
868
+		if (defined('WP_DEBUG') && WP_DEBUG) {
869
+			$file        = EEH_File::convert_local_filepath_to_remote_filepath($source);
870
+			$owner       = EEH_File::owner($file);
871
+			$group       = EEH_File::group($file);
872
+			$permissions = EEH_File::permissions($file);
873
+			EE_Error::add_error(
874
+				sprintf(
875
+					esc_html__(
876
+						'Unable to move the file "%1$s" to new location (possible permissions errors). The existing "owner:group permissions" for the file are: "%2$s"',
877
+						'event_espresso'
878
+					),
879
+					$destination,
880
+					"{$owner}:{$group} $permissions"
881
+				),
882
+				__FILE__,
883
+				__FUNCTION__,
884
+				__LINE__
885
+			);
886
+		}
887
+		return false;
888
+	}
889
+
890
+
891
+	/**
892
+	 * @param string $source_file
893
+	 * @return string
894
+	 */
895
+	private static function validateFileForCopyOrMove(string $source_file): string
896
+	{
897
+		$full_source_path = EEH_File::standardise_directory_separators($source_file);
898
+		if (! EEH_File::exists($full_source_path)) {
899
+			if (defined('WP_DEBUG') && WP_DEBUG) {
900
+				$msg =
901
+					sprintf(
902
+						esc_html__('The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso'),
903
+						'',
904
+						$full_source_path
905
+					);
906
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_source_path);
907
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
908
+			}
909
+			return '';
910
+		}
911
+		return $full_source_path;
912
+	}
913
+
914
+
915
+	/**
916
+	 * @param string $destination_file
917
+	 * @return string
918
+	 */
919
+	private static function validateFolderForCopyOrMove(string $destination_file): string
920
+	{
921
+		$full_dest_path = EEH_File::standardise_directory_separators($destination_file);
922
+		$folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
923
+		EEH_File::ensure_folder_exists_and_is_writable($folder);
924
+		if (! EEH_File::verify_is_writable($folder)) {
925
+			if (defined('WP_DEBUG') && WP_DEBUG) {
926
+				$msg = sprintf(
927
+					esc_html__('The file located at "%2$s" is not writable.', 'event_espresso'),
928
+					'',
929
+					$full_dest_path
930
+				);
931
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_dest_path);
932
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
933
+			}
934
+			return '';
935
+		}
936
+		return $full_dest_path;
937
+	}
938 938
 }
Please login to merge, or discard this patch.
Spacing   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -61,11 +61,11 @@  discard block
 block discarded – undo
61 61
      */
62 62
     private static function loadAlternateWpFileSystem(): WP_Filesystem_Base
63 63
     {
64
-        if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
65
-            require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
64
+        if ( ! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
65
+            require_once(ABSPATH.'wp-admin/includes/class-wp-filesystem-base.php');
66 66
             $wp_filesystem_file = apply_filters(
67 67
                 'filesystem_method_file',
68
-                ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php',
68
+                ABSPATH.'wp-admin/includes/class-wp-filesystem-direct.php',
69 69
                 'direct'
70 70
             );
71 71
             // added the following validation logic
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
                     $wp_filesystem_class = $filesystem_class;
88 88
                 }
89 89
             }
90
-            if (! $valid || ! file_exists($wp_filesystem_file)) {
90
+            if ( ! $valid || ! file_exists($wp_filesystem_file)) {
91 91
                 EE_Error::add_error(
92 92
                     sprintf(
93 93
                         esc_html__(
@@ -102,11 +102,11 @@  discard block
 block discarded – undo
102 102
                 );
103 103
             }
104 104
             // check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
105
-            if (! defined('FS_CHMOD_DIR')) {
105
+            if ( ! defined('FS_CHMOD_DIR')) {
106 106
                 define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
107 107
             }
108
-            if (! defined('FS_CHMOD_FILE')) {
109
-                define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
108
+            if ( ! defined('FS_CHMOD_FILE')) {
109
+                define('FS_CHMOD_FILE', (fileperms(ABSPATH.'index.php') & 0775 | 0644));
110 110
             }
111 111
             require_once($wp_filesystem_file);
112 112
             EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
     {
123 123
         global $wp_filesystem;
124 124
         // no filesystem setup ???
125
-        if (! $wp_filesystem instanceof WP_Filesystem_Base) {
125
+        if ( ! $wp_filesystem instanceof WP_Filesystem_Base) {
126 126
             // if some eager beaver's just trying to get in there too early...
127 127
             // let them do it, because we are one of those eager beavers! :P
128 128
             /**
@@ -150,9 +150,9 @@  discard block
 block discarded – undo
150 150
             //     EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
151 151
             // }
152 152
             // should be loaded if we are past the wp_loaded hook...
153
-            if (! function_exists('WP_Filesystem') || ! function_exists('submit_button')) {
154
-                require_once(ABSPATH . 'wp-admin/includes/file.php');
155
-                require_once(ABSPATH . 'wp-admin/includes/template.php');
153
+            if ( ! function_exists('WP_Filesystem') || ! function_exists('submit_button')) {
154
+                require_once(ABSPATH.'wp-admin/includes/file.php');
155
+                require_once(ABSPATH.'wp-admin/includes/template.php');
156 156
             }
157 157
             // turn on output buffering so that we can capture the credentials form
158 158
             ob_start();
@@ -199,8 +199,8 @@  discard block
 block discarded – undo
199 199
      */
200 200
     public static function display_request_filesystem_credentials_form()
201 201
     {
202
-        if (! empty(EEH_File::$_credentials_form)) {
203
-            echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
202
+        if ( ! empty(EEH_File::$_credentials_form)) {
203
+            echo '<div class="updated espresso-notices-attention"><p>'.EEH_File::$_credentials_form.'</p></div>';
204 204
         }
205 205
     }
206 206
 
@@ -225,8 +225,8 @@  discard block
 block discarded – undo
225 225
         // load WP_Filesystem and set file permissions
226 226
         $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227 227
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
-        if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
-            $file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
228
+        if ( ! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
+            $file_name = ! empty($type_of_file) ? $file_name.' '.$type_of_file : $file_name;
230 230
             $file_name .= ! empty($file_ext) ? ' file' : ' folder';
231 231
             $msg       = sprintf(
232 232
                 esc_html__(
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
                 );
247 247
             }
248 248
             if (defined('WP_DEBUG') && WP_DEBUG) {
249
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
249
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
250 250
             }
251 251
             return false;
252 252
         }
@@ -273,9 +273,9 @@  discard block
 block discarded – undo
273 273
         $perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
274 274
         if ($perms) {
275 275
             // file permissions exist, but way be set incorrectly
276
-            $type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
276
+            $type_of_file = ! empty($type_of_file) ? $type_of_file.' ' : '';
277 277
             $type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
278
-            return ' ' . sprintf(
278
+            return ' '.sprintf(
279 279
                 esc_html__(
280 280
                     'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
281 281
                     'event_espresso'
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
             );
286 286
         } else {
287 287
             // file exists but file permissions could not be read ?!?!
288
-            return ' ' . sprintf(
288
+            return ' '.sprintf(
289 289
                 esc_html__(
290 290
                     'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
291 291
                     'event_espresso'
@@ -317,15 +317,15 @@  discard block
 block discarded – undo
317 317
         $folder        = EEH_File::end_with_directory_separator($folder);
318 318
         $wp_filesystem = EEH_File::_get_wp_filesystem($folder);
319 319
         $remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
320
-        if (! $wp_filesystem->is_dir($remote_dir)) {
320
+        if ( ! $wp_filesystem->is_dir($remote_dir)) {
321 321
             // ok so it doesn't exist. Does its parent? Can we write to it?
322
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
322
+            if ( ! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
323 323
                 return false;
324 324
             }
325
-            if (! EEH_File::verify_is_writable($parent_folder)) {
325
+            if ( ! EEH_File::verify_is_writable($parent_folder)) {
326 326
                 return false;
327 327
             }
328
-            if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
328
+            if ( ! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
329 329
                 if (defined('WP_DEBUG') && WP_DEBUG) {
330 330
                     $msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
331 331
                     $msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
                 return false;
335 335
             }
336 336
             EEH_File::add_index_file($folder);
337
-        } elseif (! EEH_File::verify_is_writable($folder)) {
337
+        } elseif ( ! EEH_File::verify_is_writable($folder)) {
338 338
             return false;
339 339
         }
340 340
         return true;
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
         $full_path     = EEH_File::standardise_directory_separators($full_path);
356 356
         $remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
357 357
         $remote_path   = rtrim($remote_path, '/\\');
358
-        if (! $wp_filesystem->is_writable($remote_path)) {
358
+        if ( ! $wp_filesystem->is_writable($remote_path)) {
359 359
             if (defined('WP_DEBUG') && WP_DEBUG) {
360 360
                 $msg = sprintf(esc_html__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
361 361
                 $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
@@ -381,11 +381,11 @@  discard block
 block discarded – undo
381 381
         $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
382 382
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
383 383
         $parent_folder  = EEH_File::get_parent_folder($full_file_path);
384
-        if (! EEH_File::exists($full_file_path)) {
385
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
384
+        if ( ! EEH_File::exists($full_file_path)) {
385
+            if ( ! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
386 386
                 return false;
387 387
             }
388
-            if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
388
+            if ( ! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
389 389
                 if (defined('WP_DEBUG') && WP_DEBUG) {
390 390
                     $msg = sprintf(esc_html__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
391 391
                     $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
                 return false;
395 395
             }
396 396
         }
397
-        if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
397
+        if ( ! EEH_File::verify_is_writable($full_file_path, 'file')) {
398 398
             return false;
399 399
         }
400 400
         return true;
@@ -458,9 +458,9 @@  discard block
 block discarded – undo
458 458
         string $file_type = ''
459 459
     ): bool {
460 460
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
461
-        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
461
+        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ').' ' : '';
462 462
         $folder         = EEH_File::remove_filename_from_filepath($full_file_path);
463
-        if (! EEH_File::verify_is_writable($folder)) {
463
+        if ( ! EEH_File::verify_is_writable($folder)) {
464 464
             if (defined('WP_DEBUG') && WP_DEBUG) {
465 465
                 $msg = sprintf(
466 466
                     esc_html__('The %1$sfile located at "%2$s" is not writable.', 'event_espresso'),
@@ -586,8 +586,8 @@  discard block
 block discarded – undo
586 586
     public static function add_htaccess_deny_from_all(string $folder = ''): bool
587 587
     {
588 588
         $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
589
-        if (! EEH_File::exists($folder . '.htaccess')) {
590
-            if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
589
+        if ( ! EEH_File::exists($folder.'.htaccess')) {
590
+            if ( ! EEH_File::write_to_file($folder.'.htaccess', 'deny from all', '.htaccess')) {
591 591
                 return false;
592 592
             }
593 593
         }
@@ -605,10 +605,10 @@  discard block
 block discarded – undo
605 605
     public static function add_index_file(string $folder): bool
606 606
     {
607 607
         $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
608
-        if (! EEH_File::exists($folder . 'index.php')) {
608
+        if ( ! EEH_File::exists($folder.'index.php')) {
609 609
             if (
610 610
                 ! EEH_File::write_to_file(
611
-                    $folder . 'index.php',
611
+                    $folder.'index.php',
612 612
                     'You are not permitted to read from this folder',
613 613
                     '.php'
614 614
                 )
@@ -661,7 +661,7 @@  discard block
 block discarded – undo
661 661
      */
662 662
     public static function end_with_directory_separator(string $file_path): string
663 663
     {
664
-        return rtrim($file_path, '/\\') . '/';
664
+        return rtrim($file_path, '/\\').'/';
665 665
     }
666 666
 
667 667
 
@@ -696,18 +696,18 @@  discard block
 block discarded – undo
696 696
         foreach ($folder_paths as $folder_path) {
697 697
             $folder_path = self::standardise_and_end_with_directory_separator($folder_path);
698 698
             // load WP_Filesystem and set file permissions
699
-            $files_in_folder      = glob($folder_path . '*.php');
699
+            $files_in_folder      = glob($folder_path.'*.php');
700 700
             $class_to_folder_path = [];
701 701
             if ($files_in_folder) {
702 702
                 foreach ($files_in_folder as $file_path) {
703 703
                     // only add files, not folders
704
-                    if (! is_dir($file_path)) {
704
+                    if ( ! is_dir($file_path)) {
705 705
                         if ($index_numerically) {
706 706
                             $class_to_folder_path[] = $file_path;
707 707
                         } else {
708 708
                             $classname                          =
709 709
                                 self::get_classname_from_filepath_with_standard_filename($file_path);
710
-                            $class_to_folder_path[ $classname ] = $file_path;
710
+                            $class_to_folder_path[$classname] = $file_path;
711 711
                         }
712 712
                     }
713 713
                 }
@@ -729,7 +729,7 @@  discard block
 block discarded – undo
729 729
     {
730 730
         $source_file      = EEH_File::validateFileForCopyOrMove($source_file);
731 731
         $destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
732
-        if (! $source_file || ! $destination_file) {
732
+        if ( ! $source_file || ! $destination_file) {
733 733
             return false;
734 734
         }
735 735
         // load WP_Filesystem and set file permissions
@@ -740,7 +740,7 @@  discard block
 block discarded – undo
740 740
             EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
741 741
             $overwrite
742 742
         );
743
-        if (! $copied) {
743
+        if ( ! $copied) {
744 744
             if (defined('WP_DEBUG') && WP_DEBUG) {
745 745
                 $msg = sprintf(
746 746
                     esc_html__(
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
     public static function convert_local_filepath_to_remote_filepath(string $local_filepath): string
785 785
     {
786 786
         $wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
787
-        return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
787
+        return str_replace(WP_CONTENT_DIR.'/', $wp_filesystem->wp_content_dir(), $local_filepath);
788 788
     }
789 789
 
790 790
 
@@ -858,7 +858,7 @@  discard block
 block discarded – undo
858 858
         // throw new RuntimeException("source: {$source} && destination: {$destination}");
859 859
         $source      = EEH_File::validateFileForCopyOrMove($source);
860 860
         $destination = EEH_File::validateFolderForCopyOrMove($destination);
861
-        if (! $source || ! $destination) {
861
+        if ( ! $source || ! $destination) {
862 862
             return false;
863 863
         }
864 864
         $wp_filesystem = EEH_File::_get_wp_filesystem($source);
@@ -895,7 +895,7 @@  discard block
 block discarded – undo
895 895
     private static function validateFileForCopyOrMove(string $source_file): string
896 896
     {
897 897
         $full_source_path = EEH_File::standardise_directory_separators($source_file);
898
-        if (! EEH_File::exists($full_source_path)) {
898
+        if ( ! EEH_File::exists($full_source_path)) {
899 899
             if (defined('WP_DEBUG') && WP_DEBUG) {
900 900
                 $msg =
901 901
                     sprintf(
@@ -921,7 +921,7 @@  discard block
 block discarded – undo
921 921
         $full_dest_path = EEH_File::standardise_directory_separators($destination_file);
922 922
         $folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
923 923
         EEH_File::ensure_folder_exists_and_is_writable($folder);
924
-        if (! EEH_File::verify_is_writable($folder)) {
924
+        if ( ! EEH_File::verify_is_writable($folder)) {
925 925
             if (defined('WP_DEBUG') && WP_DEBUG) {
926 926
                 $msg = sprintf(
927 927
                     esc_html__('The file located at "%2$s" is not writable.', 'event_espresso'),
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1741 added lines, -1741 removed lines patch added patch discarded remove patch
@@ -22,1745 +22,1745 @@
 block discarded – undo
22 22
  */
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25
-    /**
26
-     * @var EE_Registry $_instance
27
-     */
28
-    private static $_instance;
29
-
30
-    /**
31
-     * @var EE_Dependency_Map $_dependency_map
32
-     */
33
-    protected $_dependency_map;
34
-
35
-    /**
36
-     * @var Mirror
37
-     */
38
-    private $mirror;
39
-
40
-    /**
41
-     * @var ClassInterfaceCache $class_cache
42
-     */
43
-    private $class_cache;
44
-
45
-    /**
46
-     * @var array $_class_abbreviations
47
-     */
48
-    protected $_class_abbreviations = [];
49
-
50
-    /**
51
-     * @var CommandBusInterface $BUS
52
-     */
53
-    public $BUS;
54
-
55
-    /**
56
-     * @var EE_Cart $CART
57
-     */
58
-    public $CART;
59
-
60
-    /**
61
-     * @var EE_Config $CFG
62
-     */
63
-    public $CFG;
64
-
65
-    /**
66
-     * @var EE_Network_Config $NET_CFG
67
-     */
68
-    public $NET_CFG;
69
-
70
-    /**
71
-     * RegistryContainer for storing library classes in
72
-     *
73
-     * @var RegistryContainer $LIB
74
-     */
75
-    public $LIB;
76
-
77
-    /**
78
-     * @var EE_Request_Handler $REQ
79
-     * @deprecated 4.10.14.p
80
-     */
81
-    public $REQ;
82
-
83
-    /**
84
-     * @var EE_Session $SSN
85
-     */
86
-    public $SSN;
87
-
88
-    /**
89
-     * @since 4.5.0
90
-     * @var EE_Capabilities $CAP
91
-     */
92
-    public $CAP;
93
-
94
-    /**
95
-     * @since 4.9.0
96
-     * @var EE_Message_Resource_Manager $MRM
97
-     */
98
-    public $MRM;
99
-
100
-    /**
101
-     * @var Registry $AssetsRegistry
102
-     */
103
-    public $AssetsRegistry;
104
-
105
-    /**
106
-     * RegistryContainer for holding addons which have registered themselves to work with EE core
107
-     *
108
-     * @var RegistryContainer|EE_Addon[] $addons
109
-     */
110
-    public $addons;
111
-
112
-    /**
113
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
-     *
115
-     * @var EEM_Base[] $models
116
-     */
117
-    public $models = [];
118
-
119
-    /**
120
-     * @var RegistryContainer|EED_Module[] $modules
121
-     */
122
-    public $modules;
123
-
124
-    /**
125
-     * @var RegistryContainer|EES_Shortcode[] $shortcodes
126
-     */
127
-    public $shortcodes;
128
-
129
-    /**
130
-     * @var RegistryContainer|WP_Widget[] $widgets
131
-     */
132
-    public $widgets;
133
-
134
-    /**
135
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
-     * classnames (eg "EEM_Event")
139
-     *
140
-     * @var array $non_abstract_db_models
141
-     */
142
-    public $non_abstract_db_models = [];
143
-
144
-    /**
145
-     * internationalization for JS strings
146
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
-     *    in js file:  var translatedString = eei18n.string_key;
148
-     *
149
-     * @var array $i18n_js_strings
150
-     */
151
-    public static $i18n_js_strings = [];
152
-
153
-    /**
154
-     * $main_file - path to espresso.php
155
-     *
156
-     * @var array $main_file
157
-     */
158
-    public $main_file;
159
-
160
-    /**
161
-     * array of ReflectionClass objects where the key is the class name
162
-     *
163
-     * @deprecated 4.9.62.p
164
-     * @var ReflectionClass[] $_reflectors
165
-     */
166
-    public $_reflectors;
167
-
168
-    /**
169
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
-     *
171
-     * @var boolean $_cache_on
172
-     */
173
-    protected $_cache_on = true;
174
-
175
-    /**
176
-     * @var ObjectIdentifier
177
-     */
178
-    private $object_identifier;
179
-
180
-
181
-    /**
182
-     * @singleton method used to instantiate class object
183
-     * @param EE_Dependency_Map|null   $dependency_map
184
-     * @param Mirror|null              $mirror
185
-     * @param ClassInterfaceCache|null $class_cache
186
-     * @param ObjectIdentifier|null    $object_identifier
187
-     * @return EE_Registry instance
188
-     */
189
-    public static function instance(
190
-        EE_Dependency_Map $dependency_map = null,
191
-        Mirror $mirror = null,
192
-        ClassInterfaceCache $class_cache = null,
193
-        ObjectIdentifier $object_identifier = null
194
-    ): EE_Registry {
195
-        // check if class object is instantiated
196
-        if (
197
-            ! self::$_instance instanceof EE_Registry
198
-            && $dependency_map instanceof EE_Dependency_Map
199
-            && $mirror instanceof Mirror
200
-            && $class_cache instanceof ClassInterfaceCache
201
-            && $object_identifier instanceof ObjectIdentifier
202
-        ) {
203
-            self::$_instance = new self(
204
-                $dependency_map,
205
-                $mirror,
206
-                $class_cache,
207
-                $object_identifier
208
-            );
209
-        }
210
-        return self::$_instance;
211
-    }
212
-
213
-
214
-    /**
215
-     * protected constructor to prevent direct creation
216
-     *
217
-     * @Constructor
218
-     * @param EE_Dependency_Map   $dependency_map
219
-     * @param Mirror              $mirror
220
-     * @param ClassInterfaceCache $class_cache
221
-     * @param ObjectIdentifier    $object_identifier
222
-     */
223
-    protected function __construct(
224
-        EE_Dependency_Map $dependency_map,
225
-        Mirror $mirror,
226
-        ClassInterfaceCache $class_cache,
227
-        ObjectIdentifier $object_identifier
228
-    ) {
229
-        $this->_dependency_map   = $dependency_map;
230
-        $this->mirror            = $mirror;
231
-        $this->class_cache       = $class_cache;
232
-        $this->object_identifier = $object_identifier;
233
-        // $registry_container = new RegistryContainer();
234
-        $this->LIB        = new RegistryContainer();
235
-        $this->addons     = new RegistryContainer();
236
-        $this->modules    = new RegistryContainer();
237
-        $this->shortcodes = new RegistryContainer();
238
-        $this->widgets    = new RegistryContainer();
239
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
240
-    }
241
-
242
-
243
-    /**
244
-     * initialize
245
-     *
246
-     * @throws OutOfBoundsException
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidInterfaceException
249
-     * @throws InvalidDataTypeException
250
-     * @throws EE_Error
251
-     * @throws ReflectionException
252
-     */
253
-    public function initialize()
254
-    {
255
-        $this->_class_abbreviations = apply_filters(
256
-            'FHEE__EE_Registry____construct___class_abbreviations',
257
-            [
258
-                'EE_Config'                                       => 'CFG',
259
-                'EE_Session'                                      => 'SSN',
260
-                'EE_Capabilities'                                 => 'CAP',
261
-                'EE_Cart'                                         => 'CART',
262
-                'EE_Network_Config'                               => 'NET_CFG',
263
-                'EE_Request_Handler'                              => 'REQ',
264
-                'EE_Message_Resource_Manager'                     => 'MRM',
265
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
266
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
267
-            ]
268
-        );
269
-        $this->load_core('Base', [], true);
270
-        // add our request and response objects to the cache
271
-        $request_loader = $this->_dependency_map->class_loader(
272
-            'EventEspresso\core\services\request\Request'
273
-        );
274
-        $this->_set_cached_class(
275
-            $request_loader(),
276
-            'EventEspresso\core\services\request\Request'
277
-        );
278
-        $response_loader = $this->_dependency_map->class_loader(
279
-            'EventEspresso\core\services\request\Response'
280
-        );
281
-        $this->_set_cached_class(
282
-            $response_loader(),
283
-            'EventEspresso\core\services\request\Response'
284
-        );
285
-        add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
286
-    }
287
-
288
-
289
-    /**
290
-     * @return void
291
-     */
292
-    public function init()
293
-    {
294
-        // Get current page protocol
295
-        $protocol = is_ssl() ? 'https://' : 'http://';
296
-        // Output admin-ajax.php URL with same protocol as current page
297
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
298
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
299
-    }
300
-
301
-
302
-    /**
303
-     * @return array
304
-     */
305
-    public static function sanitize_i18n_js_strings(): array
306
-    {
307
-        $i18n_js_strings = (array) self::$i18n_js_strings;
308
-        foreach ($i18n_js_strings as $key => $value) {
309
-            if (is_scalar($value)) {
310
-                $i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
-            }
312
-        }
313
-        return $i18n_js_strings;
314
-    }
315
-
316
-
317
-    /**
318
-     * localize_i18n_js_strings
319
-     *
320
-     * @return string
321
-     */
322
-    public static function localize_i18n_js_strings(): string
323
-    {
324
-        $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
325
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
326
-    }
327
-
328
-
329
-    /**
330
-     * @param mixed string | EED_Module $module
331
-     * @throws OutOfBoundsException
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidInterfaceException
334
-     * @throws InvalidDataTypeException
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    public function add_module($module)
339
-    {
340
-        if ($module instanceof EED_Module) {
341
-            $module_class = get_class($module);
342
-            $this->modules->add($module_class, $module);
343
-        } else {
344
-            if (! class_exists('EE_Module_Request_Router', false)) {
345
-                $this->load_core('Module_Request_Router');
346
-            }
347
-            EE_Module_Request_Router::module_factory($module);
348
-        }
349
-    }
350
-
351
-
352
-    /**
353
-     * @param string $module_name
354
-     * @return mixed EED_Module | NULL
355
-     */
356
-    public function get_module(string $module_name = '')
357
-    {
358
-        return $this->modules->get($module_name);
359
-    }
360
-
361
-
362
-    /**
363
-     * loads core classes - must be singletons
364
-     *
365
-     * @param string $class_name - simple class name ie: session
366
-     * @param mixed  $arguments
367
-     * @param bool   $load_only
368
-     * @return bool|null|object
369
-     * @throws InvalidInterfaceException
370
-     * @throws InvalidDataTypeException
371
-     * @throws EE_Error
372
-     * @throws ReflectionException
373
-     * @throws InvalidArgumentException
374
-     */
375
-    public function load_core(string $class_name, $arguments = [], bool $load_only = false)
376
-    {
377
-        $core_paths = (array) apply_filters(
378
-            'FHEE__EE_Registry__load_core__core_paths',
379
-            [
380
-                EE_CORE,
381
-                EE_ADMIN,
382
-                EE_CPTS,
383
-                EE_CORE . 'CPTs/',
384
-                EE_CORE . 'data_migration_scripts/',
385
-                EE_CORE . 'request_stack/',
386
-                EE_CORE . 'middleware/',
387
-            ]
388
-        );
389
-        // retrieve instantiated class
390
-        return $this->_load(
391
-            $core_paths,
392
-            'EE_',
393
-            $class_name,
394
-            'core',
395
-            $arguments,
396
-            false,
397
-            true,
398
-            $load_only
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * loads service classes
405
-     *
406
-     * @param string $class_name - simple class name ie: session
407
-     * @param mixed  $arguments
408
-     * @param bool   $load_only
409
-     * @return bool|null|object
410
-     * @throws InvalidInterfaceException
411
-     * @throws InvalidDataTypeException
412
-     * @throws EE_Error
413
-     * @throws ReflectionException
414
-     * @throws InvalidArgumentException
415
-     * @deprecated  4.10.33.p
416
-     */
417
-    public function load_service(string $class_name, $arguments = [], bool $load_only = false)
418
-    {
419
-        $service_paths = (array) apply_filters(
420
-            'FHEE__EE_Registry__load_service__service_paths',
421
-            [
422
-                EE_CORE . 'services/',
423
-            ]
424
-        );
425
-        // retrieve instantiated class
426
-        return $this->_load(
427
-            $service_paths,
428
-            'EE_',
429
-            $class_name,
430
-            'class',
431
-            $arguments,
432
-            false,
433
-            true,
434
-            $load_only
435
-        );
436
-    }
437
-
438
-
439
-    /**
440
-     * loads data_migration_scripts
441
-     *
442
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
443
-     * @param mixed  $arguments
444
-     * @return bool|null|object
445
-     * @throws InvalidInterfaceException
446
-     * @throws InvalidDataTypeException
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     * @throws InvalidArgumentException
450
-     */
451
-    public function load_dms(string $class_name, $arguments = [])
452
-    {
453
-        // retrieve instantiated class
454
-        return $this->_load(
455
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
456
-            'EE_DMS_',
457
-            $class_name,
458
-            'dms',
459
-            $arguments,
460
-            false,
461
-            false
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * loads object creating classes - must be singletons
468
-     *
469
-     * @param string $class_name - simple class name ie: attendee
470
-     * @param mixed  $arguments  - an array of arguments to pass to the class
471
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
472
-     *                           instantiate
473
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
474
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
475
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
476
-     *                           (default)
477
-     * @return EE_Base_Class|object|bool|null
478
-     * @throws InvalidInterfaceException
479
-     * @throws InvalidDataTypeException
480
-     * @throws EE_Error
481
-     * @throws ReflectionException
482
-     * @throws InvalidArgumentException
483
-     */
484
-    public function load_class(
485
-        string $class_name,
486
-        $arguments = [],
487
-        bool $from_db = false,
488
-        bool $cache = true,
489
-        bool $load_only = false
490
-    ) {
491
-        $paths = (array) apply_filters(
492
-            'FHEE__EE_Registry__load_class__paths',
493
-            [
494
-                EE_CORE,
495
-                EE_CLASSES,
496
-                EE_BUSINESS,
497
-            ]
498
-        );
499
-        // retrieve instantiated class
500
-        return $this->_load(
501
-            $paths,
502
-            'EE_',
503
-            $class_name,
504
-            'class',
505
-            $arguments,
506
-            $from_db,
507
-            $cache,
508
-            $load_only
509
-        );
510
-    }
511
-
512
-
513
-    /**
514
-     * loads helper classes - must be singletons
515
-     *
516
-     * @param string $class_name - simple class name ie: price
517
-     * @param mixed  $arguments
518
-     * @param bool   $load_only
519
-     * @return bool|null|object
520
-     * @throws InvalidInterfaceException
521
-     * @throws InvalidDataTypeException
522
-     * @throws EE_Error
523
-     * @throws ReflectionException
524
-     * @throws InvalidArgumentException
525
-     */
526
-    public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
527
-    {
528
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
529
-        $helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
530
-        // retrieve instantiated class
531
-        return $this->_load(
532
-            $helper_paths,
533
-            'EEH_',
534
-            $class_name,
535
-            'helper',
536
-            $arguments,
537
-            false,
538
-            true,
539
-            $load_only
540
-        );
541
-    }
542
-
543
-
544
-    /**
545
-     * loads core classes - must be singletons
546
-     *
547
-     * @param string $class_name - simple class name ie: session
548
-     * @param mixed  $arguments
549
-     * @param bool   $load_only
550
-     * @param bool   $cache      whether to cache the object or not.
551
-     * @return bool|null|object
552
-     * @throws InvalidInterfaceException
553
-     * @throws InvalidDataTypeException
554
-     * @throws EE_Error
555
-     * @throws ReflectionException
556
-     * @throws InvalidArgumentException
557
-     */
558
-    public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
559
-    {
560
-        $paths = [
561
-            EE_LIBRARIES,
562
-            EE_LIBRARIES . 'messages/',
563
-            EE_LIBRARIES . 'shortcodes/',
564
-            EE_LIBRARIES . 'qtips/',
565
-            EE_LIBRARIES . 'payment_methods/',
566
-        ];
567
-        // retrieve instantiated class
568
-        return $this->_load(
569
-            $paths,
570
-            'EE_',
571
-            $class_name,
572
-            'lib',
573
-            $arguments,
574
-            false,
575
-            $cache,
576
-            $load_only
577
-        );
578
-    }
579
-
580
-
581
-    /**
582
-     * loads model classes - must be singletons
583
-     *
584
-     * @param string $class_name - simple class name ie: price
585
-     * @param mixed  $arguments
586
-     * @param bool   $load_only
587
-     * @return bool|null|object
588
-     * @throws InvalidInterfaceException
589
-     * @throws InvalidDataTypeException
590
-     * @throws EE_Error
591
-     * @throws ReflectionException
592
-     * @throws InvalidArgumentException
593
-     */
594
-    public function load_model(string $class_name, $arguments = [], bool $load_only = false)
595
-    {
596
-        $paths = (array) apply_filters(
597
-            'FHEE__EE_Registry__load_model__paths',
598
-            [
599
-                EE_MODELS,
600
-                EE_CORE,
601
-            ]
602
-        );
603
-        // retrieve instantiated class
604
-        return $this->_load(
605
-            $paths,
606
-            'EEM_',
607
-            $class_name,
608
-            'model',
609
-            $arguments,
610
-            false,
611
-            true,
612
-            $load_only
613
-        );
614
-    }
615
-
616
-
617
-    /**
618
-     * loads model classes - must be singletons
619
-     *
620
-     * @param string $class_name - simple class name ie: price
621
-     * @param mixed  $arguments
622
-     * @param bool   $load_only
623
-     * @return bool|null|object
624
-     * @throws InvalidInterfaceException
625
-     * @throws InvalidDataTypeException
626
-     * @throws EE_Error
627
-     * @throws ReflectionException
628
-     * @throws InvalidArgumentException
629
-     * @deprecated  4.10.33.p
630
-     */
631
-    public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
632
-    {
633
-        $paths = [
634
-            EE_MODELS . 'fields/',
635
-            EE_MODELS . 'helpers/',
636
-            EE_MODELS . 'relations/',
637
-            EE_MODELS . 'strategies/',
638
-        ];
639
-        // retrieve instantiated class
640
-        return $this->_load(
641
-            $paths,
642
-            'EE_',
643
-            $class_name,
644
-            '',
645
-            $arguments,
646
-            false,
647
-            true,
648
-            $load_only
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * Determines if $model_name is the name of an actual EE model.
655
-     *
656
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
657
-     * @return boolean
658
-     */
659
-    public function is_model_name(string $model_name): bool
660
-    {
661
-        return isset($this->models[ $model_name ]);
662
-    }
663
-
664
-
665
-    /**
666
-     * generic class loader
667
-     *
668
-     * @param string $path_to_file - directory path to file location, not including filename
669
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
670
-     * @param string $type         - file type - core? class? helper? model?
671
-     * @param mixed  $arguments
672
-     * @param bool   $load_only
673
-     * @return bool|null|object
674
-     * @throws InvalidInterfaceException
675
-     * @throws InvalidDataTypeException
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     * @throws InvalidArgumentException
679
-     */
680
-    public function load_file(
681
-        string $path_to_file,
682
-        string $file_name,
683
-        string $type = '',
684
-        $arguments = [],
685
-        bool $load_only = true
686
-    ) {
687
-        // retrieve instantiated class
688
-        return $this->_load(
689
-            (array) $path_to_file,
690
-            '',
691
-            $file_name,
692
-            $type,
693
-            $arguments,
694
-            false,
695
-            true,
696
-            $load_only
697
-        );
698
-    }
699
-
700
-
701
-    /**
702
-     * @param string $path_to_file - directory path to file location, not including filename
703
-     * @param string $class_name   - full class name  ie:  My_Class
704
-     * @param string $type         - file type - core? class? helper? model?
705
-     * @param mixed  $arguments
706
-     * @param bool   $load_only
707
-     * @return bool|null|object
708
-     * @throws InvalidInterfaceException
709
-     * @throws InvalidDataTypeException
710
-     * @throws EE_Error
711
-     * @throws ReflectionException
712
-     * @throws InvalidArgumentException
713
-     * @deprecated  4.10.33.p
714
-     */
715
-    public function load_addon(
716
-        string $path_to_file,
717
-        string $class_name,
718
-        string $type = 'class',
719
-        $arguments = [],
720
-        bool $load_only = false
721
-    ) {
722
-        // retrieve instantiated class
723
-        return $this->_load(
724
-            (array) $path_to_file,
725
-            'addon',
726
-            $class_name,
727
-            $type,
728
-            $arguments,
729
-            false,
730
-            true,
731
-            $load_only
732
-        );
733
-    }
734
-
735
-
736
-    /**
737
-     * instantiates, caches, and automatically resolves dependencies
738
-     * for classes that use a Fully Qualified Class Name.
739
-     * if the class is not capable of being loaded using PSR-4 autoloading,
740
-     * then you need to use one of the existing load_*() methods
741
-     * which can resolve the classname and filepath from the passed arguments
742
-     *
743
-     * @param string      $class_name Fully Qualified Class Name
744
-     * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
745
-     * @param bool        $cache      whether to cache the instantiated object for reuse
746
-     * @param bool        $from_db    some classes are instantiated from the db
747
-     *                                and thus call a different method to instantiate
748
-     * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
749
-     * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
750
-     * @return bool|null|mixed     null = failure to load or instantiate class object.
751
-     *                                object = class loaded and instantiated successfully.
752
-     *                                bool = fail or success when $load_only is true
753
-     * @throws InvalidInterfaceException
754
-     * @throws InvalidDataTypeException
755
-     * @throws EE_Error
756
-     * @throws ReflectionException
757
-     * @throws InvalidArgumentException
758
-     */
759
-    public function create(
760
-        string $class_name = '',
761
-        array $arguments = [],
762
-        bool $cache = false,
763
-        bool $from_db = false,
764
-        bool $load_only = false,
765
-        bool $addon = false
766
-    ) {
767
-        $class_name   = ltrim($class_name, '\\');
768
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
769
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
770
-        // if a non-FQCN was passed, then
771
-        // verifyClassExists() might return an object
772
-        // or it could return null if the class just could not be found anywhere
773
-        if ($class_exists instanceof $class_name || $class_exists === null) {
774
-            // either way, return the results
775
-            return $class_exists;
776
-        }
777
-        $class_name = $class_exists;
778
-        // if we're only loading the class and it already exists, then let's just return true immediately
779
-        if ($load_only) {
780
-            return true;
781
-        }
782
-        $addon = $addon ? 'addon' : '';
783
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
784
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
785
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
786
-        if ($this->_cache_on && $cache) {
787
-            // return object if it's already cached
788
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
789
-            if ($cached_class !== null) {
790
-                return $cached_class;
791
-            }
792
-        }                                                           // obtain the loader method from the dependency map
793
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
794
-        if ($loader instanceof Closure) {
795
-            $class_obj = $loader($arguments);
796
-        } else {
797
-            if ($loader && method_exists($this, $loader)) {
798
-                $class_obj = $this->{$loader}($class_name, $arguments);
799
-            } else {
800
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
801
-            }
802
-        }
803
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
804
-            // save it for later... kinda like gum  { : $
805
-            $this->_set_cached_class(
806
-                $class_obj,
807
-                $class_name,
808
-                $addon,
809
-                $from_db,
810
-                $arguments
811
-            );
812
-        }
813
-        $this->_cache_on = true;
814
-        return $class_obj;
815
-    }
816
-
817
-
818
-    /**
819
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
820
-     *
821
-     * @param string|mixed $class_name
822
-     * @param array        $arguments
823
-     * @param int          $attempt
824
-     * @return mixed
825
-     */
826
-    private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
827
-    {
828
-        if (is_object($class_name) || class_exists($class_name)) {
829
-            return $class_name;
830
-        }
831
-        switch ($attempt) {
832
-            case 1:
833
-                // if it's a FQCN then maybe the class is registered with a preceding \
834
-                $class_name = strpos($class_name, '\\') !== false
835
-                    ? '\\' . ltrim($class_name, '\\')
836
-                    : $class_name;
837
-                break;
838
-            case 2:
839
-                //
840
-                $loader = $this->_dependency_map->class_loader($class_name);
841
-                if ($loader && method_exists($this, $loader)) {
842
-                    return $this->{$loader}($class_name, $arguments);
843
-                }
844
-                break;
845
-            case 3:
846
-            default:
847
-                return null;
848
-        }
849
-        $attempt++;
850
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
851
-    }
852
-
853
-
854
-    /**
855
-     * instantiates, caches, and injects dependencies for classes
856
-     *
857
-     * @param array  $file_paths         an array of paths to folders to look in
858
-     * @param string $class_prefix       EE  or EEM or... ???
859
-     * @param string $class_name         $class name
860
-     * @param string $type               file type - core? class? helper? model?
861
-     * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
862
-     * @param bool   $from_db            some classes are instantiated from the db
863
-     *                                   and thus call a different method to instantiate
864
-     * @param bool   $cache              whether to cache the instantiated object for reuse
865
-     * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
866
-     * @return bool|null|object          null   = failure to load or instantiate class object.
867
-     *                                   object = class loaded and instantiated successfully.
868
-     *                                   bool   = fail or success when $load_only is true
869
-     * @throws EE_Error
870
-     * @throws ReflectionException
871
-     * @throws InvalidInterfaceException
872
-     * @throws InvalidDataTypeException
873
-     * @throws InvalidArgumentException
874
-     */
875
-    protected function _load(
876
-        array $file_paths = [],
877
-        string $class_prefix = 'EE_',
878
-        string $class_name = '',
879
-        string $type = 'class',
880
-        array $arguments = [],
881
-        bool $from_db = false,
882
-        bool $cache = true,
883
-        bool $load_only = false
884
-    ) {
885
-        $class_name = ltrim($class_name, '\\');
886
-        // strip php file extension
887
-        $class_name = str_replace('.php', '', trim($class_name));
888
-        // does the class have a prefix ?
889
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
890
-            // make sure $class_prefix is uppercase
891
-            $class_prefix = strtoupper(trim($class_prefix));
892
-            // add class prefix ONCE!!!
893
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
894
-        }
895
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
896
-        $class_exists = class_exists($class_name, false);
897
-        // if we're only loading the class and it already exists, then let's just return true immediately
898
-        if ($load_only && $class_exists) {
899
-            return true;
900
-        }
901
-        $arguments = is_array($arguments) ? $arguments : [$arguments];
902
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
903
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
904
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
905
-        if ($this->_cache_on && $cache && ! $load_only) {
906
-            // return object if it's already cached
907
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
908
-            if ($cached_class !== null) {
909
-                return $cached_class;
910
-            }
911
-        }
912
-        // if the class doesn't already exist.. then we need to try and find the file and load it
913
-        if (! $class_exists) {
914
-            // get full path to file
915
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
916
-            // load the file
917
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
918
-            // if we are only loading a file but NOT instantiating an object
919
-            // then return boolean for whether class was loaded or not
920
-            if ($load_only) {
921
-                return $loaded;
922
-            }
923
-            // if an object was expected but loading failed, then return nothing
924
-            if (! $loaded) {
925
-                return null;
926
-            }
927
-        }
928
-        // instantiate the requested object
929
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
930
-        if ($this->_cache_on && $cache) {
931
-            // save it for later... kinda like gum  { : $
932
-            $this->_set_cached_class(
933
-                $class_obj,
934
-                $class_name,
935
-                $class_prefix,
936
-                $from_db,
937
-                $arguments
938
-            );
939
-        }
940
-        $this->_cache_on = true;
941
-        return $class_obj;
942
-    }
943
-
944
-
945
-    /**
946
-     * @param string $class_name
947
-     * @param string $default have to specify something, but not anything that will conflict
948
-     * @return mixed|string
949
-     */
950
-    protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
951
-    {
952
-        return $this->_class_abbreviations[ $class_name ] ?? $default;
953
-    }
954
-
955
-
956
-    /**
957
-     * attempts to find a cached version of the requested class
958
-     * by looking in the following places:
959
-     *        $this->{$class_abbreviation}            ie:    $this->CART
960
-     *        $this->{$class_name}                        ie:    $this->Some_Class
961
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
962
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
963
-     *
964
-     * @param string $class_name
965
-     * @param string $class_prefix
966
-     * @param array  $arguments
967
-     * @return mixed
968
-     */
969
-    protected function _get_cached_class(
970
-        string $class_name,
971
-        string $class_prefix = '',
972
-        array $arguments = []
973
-    ) {
974
-        if ($class_name === 'EE_Registry') {
975
-            return $this;
976
-        }
977
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
978
-        // check if class has already been loaded, and return it if it has been
979
-        if (isset($this->{$class_abbreviation})) {
980
-            return $this->{$class_abbreviation};
981
-        }
982
-        $class_name = str_replace('\\', '_', $class_name);
983
-        if (isset($this->{$class_name})) {
984
-            return $this->{$class_name};
985
-        }
986
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
987
-            return $this->addons->get($class_name);
988
-        }
989
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
990
-        if ($this->LIB->has($object_identifier)) {
991
-            return $this->LIB->get($object_identifier);
992
-        }
993
-        foreach ($this->LIB as $key => $object) {
994
-            if (
995
-                // request does not contain new arguments and therefore no args identifier
996
-                ! $this->object_identifier->hasArguments($object_identifier)
997
-                // but previously cached class with args was found
998
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
999
-            ) {
1000
-                return $object;
1001
-            }
1002
-        }
1003
-        return null;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * removes a cached version of the requested class
1009
-     *
1010
-     * @param string  $class_name
1011
-     * @param boolean $addon
1012
-     * @param array   $arguments
1013
-     * @return boolean
1014
-     */
1015
-    public function clear_cached_class(
1016
-        string $class_name,
1017
-        bool $addon = false,
1018
-        array $arguments = []
1019
-    ): bool {
1020
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
1021
-        // check if class has already been loaded, and return it if it has been
1022
-        if (isset($this->{$class_abbreviation})) {
1023
-            $this->{$class_abbreviation} = null;
1024
-            return true;
1025
-        }
1026
-        $class_name = str_replace('\\', '_', $class_name);
1027
-        if (isset($this->{$class_name})) {
1028
-            $this->{$class_name} = null;
1029
-            return true;
1030
-        }
1031
-        if ($addon && $this->addons->has($class_name)) {
1032
-            $this->addons->remove($class_name);
1033
-            return true;
1034
-        }
1035
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1036
-        if ($this->LIB->has($class_name)) {
1037
-            $this->LIB->remove($class_name);
1038
-            return true;
1039
-        }
1040
-        return false;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * _set_cached_class
1046
-     * attempts to cache the instantiated class locally
1047
-     * in one of the following places, in the following order:
1048
-     *        $this->{class_abbreviation}   ie:    $this->CART
1049
-     *        $this->{$class_name}          ie:    $this->Some_Class
1050
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1051
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1052
-     *
1053
-     * @param object $class_obj
1054
-     * @param string $class_name
1055
-     * @param string $class_prefix
1056
-     * @param bool   $from_db
1057
-     * @param array  $arguments
1058
-     * @return void
1059
-     */
1060
-    protected function _set_cached_class(
1061
-        $class_obj,
1062
-        string $class_name,
1063
-        string $class_prefix = '',
1064
-        bool $from_db = false,
1065
-        array $arguments = []
1066
-    ) {
1067
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1068
-            return;
1069
-        }
1070
-        // return newly instantiated class
1071
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1072
-        if ($class_abbreviation) {
1073
-            $this->{$class_abbreviation} = $class_obj;
1074
-            return;
1075
-        }
1076
-        $class_name = str_replace('\\', '_', $class_name);
1077
-        if (property_exists($this, $class_name)) {
1078
-            $this->{$class_name} = $class_obj;
1079
-            return;
1080
-        }
1081
-        if ($class_prefix === 'addon') {
1082
-            $this->addons->add($class_name, $class_obj);
1083
-            return;
1084
-        }
1085
-        if (! $from_db) {
1086
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1087
-            $this->LIB->add($class_name, $class_obj);
1088
-        }
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * attempts to find a full valid filepath for the requested class.
1094
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1095
-     * then returns that path if the target file has been found and is readable
1096
-     *
1097
-     * @param string $class_name
1098
-     * @param string $type
1099
-     * @param array  $file_paths
1100
-     * @return string | bool
1101
-     */
1102
-    protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1103
-    {
1104
-        // make sure $file_paths is an array
1105
-        $file_paths = is_array($file_paths)
1106
-            ? $file_paths
1107
-            : [$file_paths];
1108
-        // cycle thru paths
1109
-        foreach ($file_paths as $key => $file_path) {
1110
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1111
-            $file_path = $file_path
1112
-                ? str_replace(['/', '\\'], '/', $file_path)
1113
-                : EE_CLASSES;
1114
-            // prep file type
1115
-            $type = ! empty($type)
1116
-                ? trim($type, '.') . '.'
1117
-                : '';
1118
-            // build full file path
1119
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1120
-            // does the file exist and can be read ?
1121
-            if (is_readable($file_paths[ $key ])) {
1122
-                return $file_paths[ $key ];
1123
-            }
1124
-        }
1125
-        return false;
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * basically just performs a require_once()
1131
-     * but with some error handling
1132
-     *
1133
-     * @param string $path
1134
-     * @param string $class_name
1135
-     * @param string $type
1136
-     * @param array  $file_paths
1137
-     * @return bool
1138
-     * @throws EE_Error
1139
-     * @throws ReflectionException
1140
-     */
1141
-    protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1142
-    {
1143
-        $this->resolve_legacy_class_parent($class_name);
1144
-        // don't give up! you gotta...
1145
-        try {
1146
-            // does the file exist and can it be read ?
1147
-            if (! $path) {
1148
-                // just in case the file has already been autoloaded,
1149
-                // but discrepancies in the naming schema are preventing it from
1150
-                // being loaded via one of the EE_Registry::load_*() methods,
1151
-                // then let's try one last hail mary before throwing an exception
1152
-                // and call class_exists() again, but with autoloading turned ON
1153
-                if (class_exists($class_name)) {
1154
-                    return true;
1155
-                }
1156
-                // so sorry, can't find the file
1157
-                throw new EE_Error(
1158
-                    sprintf(
1159
-                        esc_html__(
1160
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1161
-                            'event_espresso'
1162
-                        ),
1163
-                        trim($type, '.'),
1164
-                        $class_name,
1165
-                        '<br />' . implode(',<br />', $file_paths)
1166
-                    )
1167
-                );
1168
-            }
1169
-            // get the file
1170
-            require_once($path);
1171
-            // if the class isn't already declared somewhere
1172
-            if (class_exists($class_name, false) === false) {
1173
-                // so sorry, not a class
1174
-                throw new EE_Error(
1175
-                    sprintf(
1176
-                        esc_html__(
1177
-                            'The %s file %s does not appear to contain the %s Class.',
1178
-                            'event_espresso'
1179
-                        ),
1180
-                        $type,
1181
-                        $path,
1182
-                        $class_name
1183
-                    )
1184
-                );
1185
-            }
1186
-        } catch (EE_Error $e) {
1187
-            $e->get_error();
1188
-            return false;
1189
-        }
1190
-        return true;
1191
-    }
1192
-
1193
-
1194
-    /**
1195
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1196
-     * before their class declaration in order to ensure that the parent class was loaded.
1197
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1198
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1199
-     *
1200
-     * @param string $class_name
1201
-     */
1202
-    protected function resolve_legacy_class_parent(string $class_name = '')
1203
-    {
1204
-        try {
1205
-            $legacy_parent_class_map = [
1206
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1207
-            ];
1208
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1209
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1210
-            }
1211
-        } catch (Exception $exception) {
1212
-        }
1213
-    }
1214
-
1215
-
1216
-    /**
1217
-     * _create_object
1218
-     * Attempts to instantiate the requested class via any of the
1219
-     * commonly used instantiation methods employed throughout EE.
1220
-     * The priority for instantiation is as follows:
1221
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1222
-     *        - model objects via their 'new_instance_from_db' method
1223
-     *        - model objects via their 'new_instance' method
1224
-     *        - "singleton" classes" via their 'instance' method
1225
-     *    - standard instantiable classes via their __constructor
1226
-     * Prior to instantiation, if the classname exists in the dependency_map,
1227
-     * then the constructor for the requested class will be examined to determine
1228
-     * if any dependencies exist, and if they can be injected.
1229
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1230
-     *
1231
-     * @param string $class_name
1232
-     * @param array  $arguments
1233
-     * @param string $type
1234
-     * @param bool   $from_db
1235
-     * @return null|object|bool
1236
-     * @throws InvalidArgumentException
1237
-     * @throws InvalidInterfaceException
1238
-     * @throws EE_Error
1239
-     * @throws ReflectionException
1240
-     * @throws InvalidDataTypeException
1241
-     */
1242
-    protected function _create_object(
1243
-        string $class_name,
1244
-        array $arguments = [],
1245
-        string $type = '',
1246
-        bool $from_db = false
1247
-    ) {
1248
-        // create reflection
1249
-        $reflector = $this->mirror->getReflectionClass($class_name);
1250
-        // make sure arguments are an array
1251
-        $arguments = is_array($arguments)
1252
-            ? $arguments
1253
-            : [$arguments];
1254
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1255
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1256
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1257
-            ? $arguments
1258
-            : [$arguments];
1259
-        // attempt to inject dependencies ?
1260
-        if ($this->_dependency_map->has($class_name)) {
1261
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1262
-        }
1263
-        // instantiate the class if possible
1264
-        if ($reflector->isAbstract()) {
1265
-            // nothing to instantiate, loading file was enough
1266
-            // does not throw an exception so $instantiation_mode is unused
1267
-            // $instantiation_mode = "1) no constructor abstract class";
1268
-            return true;
1269
-        }
1270
-        if (
1271
-            empty($arguments)
1272
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1273
-            && $reflector->isInstantiable()
1274
-        ) {
1275
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1276
-            // $instantiation_mode = "2) no constructor but instantiable";
1277
-            return $reflector->newInstance();
1278
-        }
1279
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1280
-            // $instantiation_mode = "3) new_instance_from_db()";
1281
-            return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1282
-        }
1283
-        if (method_exists($class_name, 'new_instance')) {
1284
-            // $instantiation_mode = "4) new_instance()";
1285
-            return call_user_func_array([$class_name, 'new_instance'], $arguments);
1286
-        }
1287
-        if (method_exists($class_name, 'instance')) {
1288
-            // $instantiation_mode = "5) instance()";
1289
-            return call_user_func_array([$class_name, 'instance'], $arguments);
1290
-        }
1291
-        if ($reflector->isInstantiable()) {
1292
-            $args_passed_count = count($arguments);
1293
-            $args_required_count = count($this->mirror->getRequiredParameters($class_name));
1294
-            if ($args_passed_count < $args_required_count) {
1295
-                throw new RuntimeException(
1296
-                    sprintf(
1297
-                        __(
1298
-                            'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1299
-                            'event_espresso'
1300
-                        ),
1301
-                        $class_name,
1302
-                        $args_required_count,
1303
-                        $args_passed_count
1304
-                    )
1305
-                );
1306
-            }
1307
-            // $instantiation_mode = "6) constructor";
1308
-            return $reflector->newInstanceArgs($arguments);
1309
-        }
1310
-        // heh ? something's not right !
1311
-        throw new EE_Error(
1312
-            sprintf(
1313
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1314
-                $type,
1315
-                $class_name
1316
-            )
1317
-        );
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1323
-     * @param array $array
1324
-     * @return bool
1325
-     */
1326
-    protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1327
-    {
1328
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
1329
-    }
1330
-
1331
-
1332
-    /**
1333
-     * _resolve_dependencies
1334
-     * examines the constructor for the requested class to determine
1335
-     * if any dependencies exist, and if they can be injected.
1336
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1337
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1338
-     * For example:
1339
-     *        if attempting to load a class "Foo" with the following constructor:
1340
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1341
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1342
-     *        but only IF they are NOT already present in the incoming arguments array,
1343
-     *        and the correct classes can be loaded
1344
-     *
1345
-     * @param ReflectionClass $reflector
1346
-     * @param string          $class_name
1347
-     * @param array           $arguments
1348
-     * @return array
1349
-     * @throws InvalidArgumentException
1350
-     * @throws InvalidDataTypeException
1351
-     * @throws InvalidInterfaceException
1352
-     * @throws ReflectionException
1353
-     */
1354
-    protected function _resolve_dependencies(
1355
-        ReflectionClass $reflector,
1356
-        string $class_name,
1357
-        array $arguments = []
1358
-    ): array {
1359
-        // let's examine the constructor
1360
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1361
-        // whu? huh? nothing?
1362
-        if (! $constructor) {
1363
-            return $arguments;
1364
-        }
1365
-        // get constructor parameters
1366
-        $params = $this->mirror->getParametersFromReflection($reflector);
1367
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1368
-        $argument_keys = array_keys($arguments);
1369
-        // now loop thru all the constructors' expected parameters
1370
-        foreach ($params as $index => $param) {
1371
-            try {
1372
-                // is this a dependency for a specific class ?
1373
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1374
-            } catch (ReflectionException $exception) {
1375
-                // uh-oh... most likely a legacy class that has not been autoloaded
1376
-                // let's try to derive the classname from what we have now
1377
-                // and hope that the property var name is close to the class name
1378
-                $param_class = $param->getName();
1379
-                $param_class = str_replace('_', ' ', $param_class);
1380
-                $param_class = ucwords($param_class);
1381
-                $param_class = str_replace(' ', '_', $param_class);
1382
-            }
1383
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1384
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1385
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1386
-                : $param_class;
1387
-            if (
1388
-                // param is not even a class
1389
-                ($param_class === null || $this->parameterIsPrimitive($param_class))
1390
-                // and something already exists in the incoming arguments for this param
1391
-                && array_key_exists($index, $argument_keys)
1392
-                && isset($arguments[ $argument_keys[ $index ] ])
1393
-            ) {
1394
-                // so let's skip this argument and move on to the next
1395
-                continue;
1396
-            }
1397
-            // parameter is type hinted as a class
1398
-            if ($param_class !== null) {
1399
-                // parameter exists as an incoming argument, AND it's the correct class
1400
-                if (
1401
-                    array_key_exists($index, $argument_keys)
1402
-                    && isset($arguments[ $argument_keys[ $index ] ])
1403
-                    && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1404
-                ) {
1405
-                    // skip this argument and move on to the next
1406
-                    continue;
1407
-                }
1408
-                // parameter should be injected
1409
-                if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1410
-                    $arguments = $this->_resolve_dependency(
1411
-                        $class_name,
1412
-                        $param_class,
1413
-                        $arguments,
1414
-                        $index
1415
-                    );
1416
-                }
1417
-            }
1418
-            if (empty($arguments[ $index ])) {
1419
-                $default_value = $this->mirror->getParameterDefaultValue(
1420
-                    $param,
1421
-                    $class_name,
1422
-                    $index
1423
-                );
1424
-                // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1425
-                $arguments[ $index ] = $default_value === null
1426
-                                       && isset($arguments[ $index ])
1427
-                                       && is_array($arguments[ $index ])
1428
-                    ? $arguments[ $index ]
1429
-                    : $default_value;
1430
-            }
1431
-        }
1432
-        return $arguments;
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * @param string $class_name
1438
-     * @param string $param_class
1439
-     * @param array  $arguments
1440
-     * @param mixed  $index
1441
-     * @return array
1442
-     * @throws InvalidArgumentException
1443
-     * @throws InvalidInterfaceException
1444
-     * @throws InvalidDataTypeException
1445
-     */
1446
-    protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1447
-    {
1448
-        $dependency = null;
1449
-        // should dependency be loaded from cache ?
1450
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1451
-            $class_name,
1452
-            $param_class
1453
-        );
1454
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1455
-        // we might have a dependency...
1456
-        // let's MAYBE try and find it in our cache if that's what's been requested
1457
-        $cached_class = $cache_on
1458
-            ? $this->_get_cached_class($param_class)
1459
-            : null;
1460
-        // and grab it if it exists
1461
-        if ($cached_class instanceof $param_class) {
1462
-            $dependency = $cached_class;
1463
-        } elseif ($param_class !== $class_name) {
1464
-            // obtain the loader method from the dependency map
1465
-            $loader = $this->_dependency_map->class_loader($param_class);
1466
-            // is loader a custom closure ?
1467
-            if ($loader instanceof Closure) {
1468
-                $dependency = $loader($arguments);
1469
-            } else {
1470
-                // set the cache on property for the recursive loading call
1471
-                $this->_cache_on = $cache_on;
1472
-                // if not, then let's try and load it via the registry
1473
-                if ($loader && method_exists($this, $loader)) {
1474
-                    $dependency = $this->{$loader}($param_class);
1475
-                } else {
1476
-                    $dependency = LoaderFactory::getLoader()->load(
1477
-                        $param_class,
1478
-                        [],
1479
-                        $cache_on
1480
-                    );
1481
-                }
1482
-            }
1483
-        }
1484
-        // did we successfully find the correct dependency ?
1485
-        if ($dependency instanceof $param_class) {
1486
-            // then let's inject it into the incoming array of arguments at the correct location
1487
-            $arguments[ $index ] = $dependency;
1488
-        }
1489
-        return $arguments;
1490
-    }
1491
-
1492
-
1493
-    /**
1494
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1495
-     *
1496
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1497
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1498
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1499
-     * @param array  $arguments
1500
-     * @return object
1501
-     */
1502
-    public static function factory(string $classname, array $arguments = [])
1503
-    {
1504
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1505
-        if ($loader instanceof Closure) {
1506
-            return $loader($arguments);
1507
-        }
1508
-        if (method_exists(self::instance(), $loader)) {
1509
-            return self::instance()->{$loader}($classname, $arguments);
1510
-        }
1511
-        return null;
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     * Gets the addon by its class name
1517
-     *
1518
-     * @param string $class_name
1519
-     * @return EE_Addon
1520
-     */
1521
-    public function getAddon(string $class_name): ?EE_Addon
1522
-    {
1523
-        $class_name = str_replace('\\', '_', $class_name);
1524
-        return $this->addons->{$class_name} ?? null;
1525
-    }
1526
-
1527
-
1528
-    /**
1529
-     * removes the addon from the internal cache
1530
-     *
1531
-     * @param string $class_name
1532
-     * @return void
1533
-     */
1534
-    public function removeAddon(string $class_name)
1535
-    {
1536
-        $class_name = str_replace('\\', '_', $class_name);
1537
-        $this->addons->remove($class_name);
1538
-    }
1539
-
1540
-
1541
-    /**
1542
-     * Gets the addon by its name/slug (not classname. For that, just
1543
-     * use the get_addon() method above
1544
-     *
1545
-     * @param string $name
1546
-     * @return EE_Addon
1547
-     */
1548
-    public function get_addon_by_name(string $name): ?EE_Addon
1549
-    {
1550
-        foreach ($this->addons as $addon) {
1551
-            if ($addon->name() === $name) {
1552
-                return $addon;
1553
-            }
1554
-        }
1555
-        return null;
1556
-    }
1557
-
1558
-
1559
-    /**
1560
-     * Gets an array of all the registered addons, where the keys are their names.
1561
-     * (ie, what each returns for their name() function)
1562
-     * They're already available on EE_Registry::instance()->addons as properties,
1563
-     * where each property's name is the addon's classname,
1564
-     * So if you just want to get the addon by classname,
1565
-     * OR use the get_addon() method above.
1566
-     * PLEASE  NOTE:
1567
-     * addons with Fully Qualified Class Names
1568
-     * have had the namespace separators converted to underscores,
1569
-     * so a classname like Fully\Qualified\ClassName
1570
-     * would have been converted to Fully_Qualified_ClassName
1571
-     *
1572
-     * @return EE_Addon[] where the KEYS are the addon's name()
1573
-     */
1574
-    public function get_addons_by_name(): array
1575
-    {
1576
-        $addons = [];
1577
-        foreach ($this->addons as $addon) {
1578
-            $addons[ $addon->name() ] = $addon;
1579
-        }
1580
-        return $addons;
1581
-    }
1582
-
1583
-
1584
-    /**
1585
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1586
-     * a stale copy of it around
1587
-     *
1588
-     * @param string $model_name
1589
-     * @return EEM_Base
1590
-     * @throws EE_Error
1591
-     * @throws ReflectionException
1592
-     */
1593
-    public function reset_model(string $model_name): ?EEM_Base
1594
-    {
1595
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1596
-            ? "EEM_$model_name"
1597
-            : $model_name;
1598
-        if (! $this->LIB->has($model_class_name)) {
1599
-            return null;
1600
-        }
1601
-        $model = $this->LIB->get($model_class_name);
1602
-        if (! $model instanceof EEM_Base) {
1603
-            return null;
1604
-        }
1605
-        // get that model reset it and make sure we nuke the old reference to it
1606
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1607
-            $this->LIB->remove($model_class_name);
1608
-            $this->LIB->add($model_class_name, $model->reset());
1609
-        } else {
1610
-            throw new EE_Error(
1611
-                sprintf(
1612
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1613
-                    $model_name
1614
-                )
1615
-            );
1616
-        }
1617
-        return $model;
1618
-    }
1619
-
1620
-
1621
-    /**
1622
-     * Resets the registry.
1623
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1624
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1625
-     * - $_dependency_map
1626
-     * - $_class_abbreviations
1627
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1628
-     * - $REQ:  Still on the same request so no need to change.
1629
-     * - $CAP: There is no site specific state in the EE_Capability class.
1630
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1631
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1632
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1633
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1634
-     *             switch or on the restore.
1635
-     * - $modules
1636
-     * - $shortcodes
1637
-     * - $widgets
1638
-     *
1639
-     * @param boolean $hard             [deprecated]
1640
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1641
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1642
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1643
-     * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1644
-     *                                  client
1645
-     *                                  code instead can just change the model context to a different blog id if
1646
-     *                                  necessary
1647
-     * @return EE_Registry
1648
-     * @throws EE_Error
1649
-     * @throws ReflectionException
1650
-     */
1651
-    public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1652
-    {
1653
-        $instance            = self::instance();
1654
-        $instance->_cache_on = true;
1655
-        // reset some "special" classes
1656
-        EEH_Activation::reset();
1657
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1658
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1659
-        $instance->CART = null;
1660
-        $instance->MRM = null;
1661
-        // messages reset
1662
-        EED_Messages::reset();
1663
-        // handle of objects cached on LIB
1664
-        foreach (['LIB', 'modules'] as $cache) {
1665
-            foreach ($instance->{$cache} as $class_name => $class) {
1666
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1667
-                    unset($instance->{$cache}->{$class_name});
1668
-                }
1669
-            }
1670
-        }
1671
-        return $instance;
1672
-    }
1673
-
1674
-
1675
-    /**
1676
-     * if passed object implements ResettableInterface, then call it's reset() method
1677
-     * if passed object implements InterminableInterface, then return false,
1678
-     * to indicate that it should NOT be cleared from the Registry cache
1679
-     *
1680
-     * @param      $object
1681
-     * @param bool $reset_models
1682
-     * @return bool returns true if cached object should be unset
1683
-     * @throws EE_Error
1684
-     * @throws ReflectionException
1685
-     */
1686
-    private static function _reset_and_unset_object($object, bool $reset_models): bool
1687
-    {
1688
-        if (! is_object($object)) {
1689
-            // don't unset anything that's not an object
1690
-            return false;
1691
-        }
1692
-        if ($object instanceof EED_Module) {
1693
-            $object::reset();
1694
-            // don't unset modules
1695
-            return false;
1696
-        }
1697
-        if ($object instanceof ResettableInterface) {
1698
-            if ($object instanceof EEM_Base) {
1699
-                if ($reset_models) {
1700
-                    $object->reset();
1701
-                    return true;
1702
-                }
1703
-                return false;
1704
-            }
1705
-            $object->reset();
1706
-            return true;
1707
-        }
1708
-        if (! $object instanceof InterminableInterface) {
1709
-            return true;
1710
-        }
1711
-        return false;
1712
-    }
1713
-
1714
-
1715
-    /**
1716
-     * Gets all the custom post type models defined
1717
-     *
1718
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1719
-     */
1720
-    public function cpt_models(): array
1721
-    {
1722
-        $cpt_models = [];
1723
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1724
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1725
-                $cpt_models[ $short_name ] = $classname;
1726
-            }
1727
-        }
1728
-        return $cpt_models;
1729
-    }
1730
-
1731
-
1732
-    /**
1733
-     * @return EE_Config
1734
-     */
1735
-    public static function CFG(): EE_Config
1736
-    {
1737
-        return self::instance()->CFG;
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * @param string $class_name
1743
-     * @return ReflectionClass
1744
-     * @throws ReflectionException
1745
-     * @throws InvalidDataTypeException
1746
-     * @deprecated 4.9.62.p
1747
-     */
1748
-    public function get_ReflectionClass(string $class_name): ReflectionClass
1749
-    {
1750
-        return $this->mirror->getReflectionClass($class_name);
1751
-    }
1752
-
1753
-    private function parameterIsPrimitive(?string $param_class): bool
1754
-    {
1755
-        return in_array(
1756
-            $param_class,
1757
-            [
1758
-                'array',
1759
-                'bool',
1760
-                'float',
1761
-                'int',
1762
-                'string',
1763
-            ]
1764
-        );
1765
-    }
25
+	/**
26
+	 * @var EE_Registry $_instance
27
+	 */
28
+	private static $_instance;
29
+
30
+	/**
31
+	 * @var EE_Dependency_Map $_dependency_map
32
+	 */
33
+	protected $_dependency_map;
34
+
35
+	/**
36
+	 * @var Mirror
37
+	 */
38
+	private $mirror;
39
+
40
+	/**
41
+	 * @var ClassInterfaceCache $class_cache
42
+	 */
43
+	private $class_cache;
44
+
45
+	/**
46
+	 * @var array $_class_abbreviations
47
+	 */
48
+	protected $_class_abbreviations = [];
49
+
50
+	/**
51
+	 * @var CommandBusInterface $BUS
52
+	 */
53
+	public $BUS;
54
+
55
+	/**
56
+	 * @var EE_Cart $CART
57
+	 */
58
+	public $CART;
59
+
60
+	/**
61
+	 * @var EE_Config $CFG
62
+	 */
63
+	public $CFG;
64
+
65
+	/**
66
+	 * @var EE_Network_Config $NET_CFG
67
+	 */
68
+	public $NET_CFG;
69
+
70
+	/**
71
+	 * RegistryContainer for storing library classes in
72
+	 *
73
+	 * @var RegistryContainer $LIB
74
+	 */
75
+	public $LIB;
76
+
77
+	/**
78
+	 * @var EE_Request_Handler $REQ
79
+	 * @deprecated 4.10.14.p
80
+	 */
81
+	public $REQ;
82
+
83
+	/**
84
+	 * @var EE_Session $SSN
85
+	 */
86
+	public $SSN;
87
+
88
+	/**
89
+	 * @since 4.5.0
90
+	 * @var EE_Capabilities $CAP
91
+	 */
92
+	public $CAP;
93
+
94
+	/**
95
+	 * @since 4.9.0
96
+	 * @var EE_Message_Resource_Manager $MRM
97
+	 */
98
+	public $MRM;
99
+
100
+	/**
101
+	 * @var Registry $AssetsRegistry
102
+	 */
103
+	public $AssetsRegistry;
104
+
105
+	/**
106
+	 * RegistryContainer for holding addons which have registered themselves to work with EE core
107
+	 *
108
+	 * @var RegistryContainer|EE_Addon[] $addons
109
+	 */
110
+	public $addons;
111
+
112
+	/**
113
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
+	 *
115
+	 * @var EEM_Base[] $models
116
+	 */
117
+	public $models = [];
118
+
119
+	/**
120
+	 * @var RegistryContainer|EED_Module[] $modules
121
+	 */
122
+	public $modules;
123
+
124
+	/**
125
+	 * @var RegistryContainer|EES_Shortcode[] $shortcodes
126
+	 */
127
+	public $shortcodes;
128
+
129
+	/**
130
+	 * @var RegistryContainer|WP_Widget[] $widgets
131
+	 */
132
+	public $widgets;
133
+
134
+	/**
135
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
+	 * classnames (eg "EEM_Event")
139
+	 *
140
+	 * @var array $non_abstract_db_models
141
+	 */
142
+	public $non_abstract_db_models = [];
143
+
144
+	/**
145
+	 * internationalization for JS strings
146
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
+	 *    in js file:  var translatedString = eei18n.string_key;
148
+	 *
149
+	 * @var array $i18n_js_strings
150
+	 */
151
+	public static $i18n_js_strings = [];
152
+
153
+	/**
154
+	 * $main_file - path to espresso.php
155
+	 *
156
+	 * @var array $main_file
157
+	 */
158
+	public $main_file;
159
+
160
+	/**
161
+	 * array of ReflectionClass objects where the key is the class name
162
+	 *
163
+	 * @deprecated 4.9.62.p
164
+	 * @var ReflectionClass[] $_reflectors
165
+	 */
166
+	public $_reflectors;
167
+
168
+	/**
169
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
+	 *
171
+	 * @var boolean $_cache_on
172
+	 */
173
+	protected $_cache_on = true;
174
+
175
+	/**
176
+	 * @var ObjectIdentifier
177
+	 */
178
+	private $object_identifier;
179
+
180
+
181
+	/**
182
+	 * @singleton method used to instantiate class object
183
+	 * @param EE_Dependency_Map|null   $dependency_map
184
+	 * @param Mirror|null              $mirror
185
+	 * @param ClassInterfaceCache|null $class_cache
186
+	 * @param ObjectIdentifier|null    $object_identifier
187
+	 * @return EE_Registry instance
188
+	 */
189
+	public static function instance(
190
+		EE_Dependency_Map $dependency_map = null,
191
+		Mirror $mirror = null,
192
+		ClassInterfaceCache $class_cache = null,
193
+		ObjectIdentifier $object_identifier = null
194
+	): EE_Registry {
195
+		// check if class object is instantiated
196
+		if (
197
+			! self::$_instance instanceof EE_Registry
198
+			&& $dependency_map instanceof EE_Dependency_Map
199
+			&& $mirror instanceof Mirror
200
+			&& $class_cache instanceof ClassInterfaceCache
201
+			&& $object_identifier instanceof ObjectIdentifier
202
+		) {
203
+			self::$_instance = new self(
204
+				$dependency_map,
205
+				$mirror,
206
+				$class_cache,
207
+				$object_identifier
208
+			);
209
+		}
210
+		return self::$_instance;
211
+	}
212
+
213
+
214
+	/**
215
+	 * protected constructor to prevent direct creation
216
+	 *
217
+	 * @Constructor
218
+	 * @param EE_Dependency_Map   $dependency_map
219
+	 * @param Mirror              $mirror
220
+	 * @param ClassInterfaceCache $class_cache
221
+	 * @param ObjectIdentifier    $object_identifier
222
+	 */
223
+	protected function __construct(
224
+		EE_Dependency_Map $dependency_map,
225
+		Mirror $mirror,
226
+		ClassInterfaceCache $class_cache,
227
+		ObjectIdentifier $object_identifier
228
+	) {
229
+		$this->_dependency_map   = $dependency_map;
230
+		$this->mirror            = $mirror;
231
+		$this->class_cache       = $class_cache;
232
+		$this->object_identifier = $object_identifier;
233
+		// $registry_container = new RegistryContainer();
234
+		$this->LIB        = new RegistryContainer();
235
+		$this->addons     = new RegistryContainer();
236
+		$this->modules    = new RegistryContainer();
237
+		$this->shortcodes = new RegistryContainer();
238
+		$this->widgets    = new RegistryContainer();
239
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
240
+	}
241
+
242
+
243
+	/**
244
+	 * initialize
245
+	 *
246
+	 * @throws OutOfBoundsException
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidInterfaceException
249
+	 * @throws InvalidDataTypeException
250
+	 * @throws EE_Error
251
+	 * @throws ReflectionException
252
+	 */
253
+	public function initialize()
254
+	{
255
+		$this->_class_abbreviations = apply_filters(
256
+			'FHEE__EE_Registry____construct___class_abbreviations',
257
+			[
258
+				'EE_Config'                                       => 'CFG',
259
+				'EE_Session'                                      => 'SSN',
260
+				'EE_Capabilities'                                 => 'CAP',
261
+				'EE_Cart'                                         => 'CART',
262
+				'EE_Network_Config'                               => 'NET_CFG',
263
+				'EE_Request_Handler'                              => 'REQ',
264
+				'EE_Message_Resource_Manager'                     => 'MRM',
265
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
266
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
267
+			]
268
+		);
269
+		$this->load_core('Base', [], true);
270
+		// add our request and response objects to the cache
271
+		$request_loader = $this->_dependency_map->class_loader(
272
+			'EventEspresso\core\services\request\Request'
273
+		);
274
+		$this->_set_cached_class(
275
+			$request_loader(),
276
+			'EventEspresso\core\services\request\Request'
277
+		);
278
+		$response_loader = $this->_dependency_map->class_loader(
279
+			'EventEspresso\core\services\request\Response'
280
+		);
281
+		$this->_set_cached_class(
282
+			$response_loader(),
283
+			'EventEspresso\core\services\request\Response'
284
+		);
285
+		add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
286
+	}
287
+
288
+
289
+	/**
290
+	 * @return void
291
+	 */
292
+	public function init()
293
+	{
294
+		// Get current page protocol
295
+		$protocol = is_ssl() ? 'https://' : 'http://';
296
+		// Output admin-ajax.php URL with same protocol as current page
297
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
298
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
299
+	}
300
+
301
+
302
+	/**
303
+	 * @return array
304
+	 */
305
+	public static function sanitize_i18n_js_strings(): array
306
+	{
307
+		$i18n_js_strings = (array) self::$i18n_js_strings;
308
+		foreach ($i18n_js_strings as $key => $value) {
309
+			if (is_scalar($value)) {
310
+				$i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
+			}
312
+		}
313
+		return $i18n_js_strings;
314
+	}
315
+
316
+
317
+	/**
318
+	 * localize_i18n_js_strings
319
+	 *
320
+	 * @return string
321
+	 */
322
+	public static function localize_i18n_js_strings(): string
323
+	{
324
+		$i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
325
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
326
+	}
327
+
328
+
329
+	/**
330
+	 * @param mixed string | EED_Module $module
331
+	 * @throws OutOfBoundsException
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidInterfaceException
334
+	 * @throws InvalidDataTypeException
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	public function add_module($module)
339
+	{
340
+		if ($module instanceof EED_Module) {
341
+			$module_class = get_class($module);
342
+			$this->modules->add($module_class, $module);
343
+		} else {
344
+			if (! class_exists('EE_Module_Request_Router', false)) {
345
+				$this->load_core('Module_Request_Router');
346
+			}
347
+			EE_Module_Request_Router::module_factory($module);
348
+		}
349
+	}
350
+
351
+
352
+	/**
353
+	 * @param string $module_name
354
+	 * @return mixed EED_Module | NULL
355
+	 */
356
+	public function get_module(string $module_name = '')
357
+	{
358
+		return $this->modules->get($module_name);
359
+	}
360
+
361
+
362
+	/**
363
+	 * loads core classes - must be singletons
364
+	 *
365
+	 * @param string $class_name - simple class name ie: session
366
+	 * @param mixed  $arguments
367
+	 * @param bool   $load_only
368
+	 * @return bool|null|object
369
+	 * @throws InvalidInterfaceException
370
+	 * @throws InvalidDataTypeException
371
+	 * @throws EE_Error
372
+	 * @throws ReflectionException
373
+	 * @throws InvalidArgumentException
374
+	 */
375
+	public function load_core(string $class_name, $arguments = [], bool $load_only = false)
376
+	{
377
+		$core_paths = (array) apply_filters(
378
+			'FHEE__EE_Registry__load_core__core_paths',
379
+			[
380
+				EE_CORE,
381
+				EE_ADMIN,
382
+				EE_CPTS,
383
+				EE_CORE . 'CPTs/',
384
+				EE_CORE . 'data_migration_scripts/',
385
+				EE_CORE . 'request_stack/',
386
+				EE_CORE . 'middleware/',
387
+			]
388
+		);
389
+		// retrieve instantiated class
390
+		return $this->_load(
391
+			$core_paths,
392
+			'EE_',
393
+			$class_name,
394
+			'core',
395
+			$arguments,
396
+			false,
397
+			true,
398
+			$load_only
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * loads service classes
405
+	 *
406
+	 * @param string $class_name - simple class name ie: session
407
+	 * @param mixed  $arguments
408
+	 * @param bool   $load_only
409
+	 * @return bool|null|object
410
+	 * @throws InvalidInterfaceException
411
+	 * @throws InvalidDataTypeException
412
+	 * @throws EE_Error
413
+	 * @throws ReflectionException
414
+	 * @throws InvalidArgumentException
415
+	 * @deprecated  4.10.33.p
416
+	 */
417
+	public function load_service(string $class_name, $arguments = [], bool $load_only = false)
418
+	{
419
+		$service_paths = (array) apply_filters(
420
+			'FHEE__EE_Registry__load_service__service_paths',
421
+			[
422
+				EE_CORE . 'services/',
423
+			]
424
+		);
425
+		// retrieve instantiated class
426
+		return $this->_load(
427
+			$service_paths,
428
+			'EE_',
429
+			$class_name,
430
+			'class',
431
+			$arguments,
432
+			false,
433
+			true,
434
+			$load_only
435
+		);
436
+	}
437
+
438
+
439
+	/**
440
+	 * loads data_migration_scripts
441
+	 *
442
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
443
+	 * @param mixed  $arguments
444
+	 * @return bool|null|object
445
+	 * @throws InvalidInterfaceException
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 * @throws InvalidArgumentException
450
+	 */
451
+	public function load_dms(string $class_name, $arguments = [])
452
+	{
453
+		// retrieve instantiated class
454
+		return $this->_load(
455
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
456
+			'EE_DMS_',
457
+			$class_name,
458
+			'dms',
459
+			$arguments,
460
+			false,
461
+			false
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * loads object creating classes - must be singletons
468
+	 *
469
+	 * @param string $class_name - simple class name ie: attendee
470
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
471
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
472
+	 *                           instantiate
473
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
474
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
475
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
476
+	 *                           (default)
477
+	 * @return EE_Base_Class|object|bool|null
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws EE_Error
481
+	 * @throws ReflectionException
482
+	 * @throws InvalidArgumentException
483
+	 */
484
+	public function load_class(
485
+		string $class_name,
486
+		$arguments = [],
487
+		bool $from_db = false,
488
+		bool $cache = true,
489
+		bool $load_only = false
490
+	) {
491
+		$paths = (array) apply_filters(
492
+			'FHEE__EE_Registry__load_class__paths',
493
+			[
494
+				EE_CORE,
495
+				EE_CLASSES,
496
+				EE_BUSINESS,
497
+			]
498
+		);
499
+		// retrieve instantiated class
500
+		return $this->_load(
501
+			$paths,
502
+			'EE_',
503
+			$class_name,
504
+			'class',
505
+			$arguments,
506
+			$from_db,
507
+			$cache,
508
+			$load_only
509
+		);
510
+	}
511
+
512
+
513
+	/**
514
+	 * loads helper classes - must be singletons
515
+	 *
516
+	 * @param string $class_name - simple class name ie: price
517
+	 * @param mixed  $arguments
518
+	 * @param bool   $load_only
519
+	 * @return bool|null|object
520
+	 * @throws InvalidInterfaceException
521
+	 * @throws InvalidDataTypeException
522
+	 * @throws EE_Error
523
+	 * @throws ReflectionException
524
+	 * @throws InvalidArgumentException
525
+	 */
526
+	public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
527
+	{
528
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
529
+		$helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
530
+		// retrieve instantiated class
531
+		return $this->_load(
532
+			$helper_paths,
533
+			'EEH_',
534
+			$class_name,
535
+			'helper',
536
+			$arguments,
537
+			false,
538
+			true,
539
+			$load_only
540
+		);
541
+	}
542
+
543
+
544
+	/**
545
+	 * loads core classes - must be singletons
546
+	 *
547
+	 * @param string $class_name - simple class name ie: session
548
+	 * @param mixed  $arguments
549
+	 * @param bool   $load_only
550
+	 * @param bool   $cache      whether to cache the object or not.
551
+	 * @return bool|null|object
552
+	 * @throws InvalidInterfaceException
553
+	 * @throws InvalidDataTypeException
554
+	 * @throws EE_Error
555
+	 * @throws ReflectionException
556
+	 * @throws InvalidArgumentException
557
+	 */
558
+	public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
559
+	{
560
+		$paths = [
561
+			EE_LIBRARIES,
562
+			EE_LIBRARIES . 'messages/',
563
+			EE_LIBRARIES . 'shortcodes/',
564
+			EE_LIBRARIES . 'qtips/',
565
+			EE_LIBRARIES . 'payment_methods/',
566
+		];
567
+		// retrieve instantiated class
568
+		return $this->_load(
569
+			$paths,
570
+			'EE_',
571
+			$class_name,
572
+			'lib',
573
+			$arguments,
574
+			false,
575
+			$cache,
576
+			$load_only
577
+		);
578
+	}
579
+
580
+
581
+	/**
582
+	 * loads model classes - must be singletons
583
+	 *
584
+	 * @param string $class_name - simple class name ie: price
585
+	 * @param mixed  $arguments
586
+	 * @param bool   $load_only
587
+	 * @return bool|null|object
588
+	 * @throws InvalidInterfaceException
589
+	 * @throws InvalidDataTypeException
590
+	 * @throws EE_Error
591
+	 * @throws ReflectionException
592
+	 * @throws InvalidArgumentException
593
+	 */
594
+	public function load_model(string $class_name, $arguments = [], bool $load_only = false)
595
+	{
596
+		$paths = (array) apply_filters(
597
+			'FHEE__EE_Registry__load_model__paths',
598
+			[
599
+				EE_MODELS,
600
+				EE_CORE,
601
+			]
602
+		);
603
+		// retrieve instantiated class
604
+		return $this->_load(
605
+			$paths,
606
+			'EEM_',
607
+			$class_name,
608
+			'model',
609
+			$arguments,
610
+			false,
611
+			true,
612
+			$load_only
613
+		);
614
+	}
615
+
616
+
617
+	/**
618
+	 * loads model classes - must be singletons
619
+	 *
620
+	 * @param string $class_name - simple class name ie: price
621
+	 * @param mixed  $arguments
622
+	 * @param bool   $load_only
623
+	 * @return bool|null|object
624
+	 * @throws InvalidInterfaceException
625
+	 * @throws InvalidDataTypeException
626
+	 * @throws EE_Error
627
+	 * @throws ReflectionException
628
+	 * @throws InvalidArgumentException
629
+	 * @deprecated  4.10.33.p
630
+	 */
631
+	public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
632
+	{
633
+		$paths = [
634
+			EE_MODELS . 'fields/',
635
+			EE_MODELS . 'helpers/',
636
+			EE_MODELS . 'relations/',
637
+			EE_MODELS . 'strategies/',
638
+		];
639
+		// retrieve instantiated class
640
+		return $this->_load(
641
+			$paths,
642
+			'EE_',
643
+			$class_name,
644
+			'',
645
+			$arguments,
646
+			false,
647
+			true,
648
+			$load_only
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * Determines if $model_name is the name of an actual EE model.
655
+	 *
656
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
657
+	 * @return boolean
658
+	 */
659
+	public function is_model_name(string $model_name): bool
660
+	{
661
+		return isset($this->models[ $model_name ]);
662
+	}
663
+
664
+
665
+	/**
666
+	 * generic class loader
667
+	 *
668
+	 * @param string $path_to_file - directory path to file location, not including filename
669
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
670
+	 * @param string $type         - file type - core? class? helper? model?
671
+	 * @param mixed  $arguments
672
+	 * @param bool   $load_only
673
+	 * @return bool|null|object
674
+	 * @throws InvalidInterfaceException
675
+	 * @throws InvalidDataTypeException
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 * @throws InvalidArgumentException
679
+	 */
680
+	public function load_file(
681
+		string $path_to_file,
682
+		string $file_name,
683
+		string $type = '',
684
+		$arguments = [],
685
+		bool $load_only = true
686
+	) {
687
+		// retrieve instantiated class
688
+		return $this->_load(
689
+			(array) $path_to_file,
690
+			'',
691
+			$file_name,
692
+			$type,
693
+			$arguments,
694
+			false,
695
+			true,
696
+			$load_only
697
+		);
698
+	}
699
+
700
+
701
+	/**
702
+	 * @param string $path_to_file - directory path to file location, not including filename
703
+	 * @param string $class_name   - full class name  ie:  My_Class
704
+	 * @param string $type         - file type - core? class? helper? model?
705
+	 * @param mixed  $arguments
706
+	 * @param bool   $load_only
707
+	 * @return bool|null|object
708
+	 * @throws InvalidInterfaceException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws EE_Error
711
+	 * @throws ReflectionException
712
+	 * @throws InvalidArgumentException
713
+	 * @deprecated  4.10.33.p
714
+	 */
715
+	public function load_addon(
716
+		string $path_to_file,
717
+		string $class_name,
718
+		string $type = 'class',
719
+		$arguments = [],
720
+		bool $load_only = false
721
+	) {
722
+		// retrieve instantiated class
723
+		return $this->_load(
724
+			(array) $path_to_file,
725
+			'addon',
726
+			$class_name,
727
+			$type,
728
+			$arguments,
729
+			false,
730
+			true,
731
+			$load_only
732
+		);
733
+	}
734
+
735
+
736
+	/**
737
+	 * instantiates, caches, and automatically resolves dependencies
738
+	 * for classes that use a Fully Qualified Class Name.
739
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
740
+	 * then you need to use one of the existing load_*() methods
741
+	 * which can resolve the classname and filepath from the passed arguments
742
+	 *
743
+	 * @param string      $class_name Fully Qualified Class Name
744
+	 * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
745
+	 * @param bool        $cache      whether to cache the instantiated object for reuse
746
+	 * @param bool        $from_db    some classes are instantiated from the db
747
+	 *                                and thus call a different method to instantiate
748
+	 * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
749
+	 * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
750
+	 * @return bool|null|mixed     null = failure to load or instantiate class object.
751
+	 *                                object = class loaded and instantiated successfully.
752
+	 *                                bool = fail or success when $load_only is true
753
+	 * @throws InvalidInterfaceException
754
+	 * @throws InvalidDataTypeException
755
+	 * @throws EE_Error
756
+	 * @throws ReflectionException
757
+	 * @throws InvalidArgumentException
758
+	 */
759
+	public function create(
760
+		string $class_name = '',
761
+		array $arguments = [],
762
+		bool $cache = false,
763
+		bool $from_db = false,
764
+		bool $load_only = false,
765
+		bool $addon = false
766
+	) {
767
+		$class_name   = ltrim($class_name, '\\');
768
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
769
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
770
+		// if a non-FQCN was passed, then
771
+		// verifyClassExists() might return an object
772
+		// or it could return null if the class just could not be found anywhere
773
+		if ($class_exists instanceof $class_name || $class_exists === null) {
774
+			// either way, return the results
775
+			return $class_exists;
776
+		}
777
+		$class_name = $class_exists;
778
+		// if we're only loading the class and it already exists, then let's just return true immediately
779
+		if ($load_only) {
780
+			return true;
781
+		}
782
+		$addon = $addon ? 'addon' : '';
783
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
784
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
785
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
786
+		if ($this->_cache_on && $cache) {
787
+			// return object if it's already cached
788
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
789
+			if ($cached_class !== null) {
790
+				return $cached_class;
791
+			}
792
+		}                                                           // obtain the loader method from the dependency map
793
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
794
+		if ($loader instanceof Closure) {
795
+			$class_obj = $loader($arguments);
796
+		} else {
797
+			if ($loader && method_exists($this, $loader)) {
798
+				$class_obj = $this->{$loader}($class_name, $arguments);
799
+			} else {
800
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
801
+			}
802
+		}
803
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
804
+			// save it for later... kinda like gum  { : $
805
+			$this->_set_cached_class(
806
+				$class_obj,
807
+				$class_name,
808
+				$addon,
809
+				$from_db,
810
+				$arguments
811
+			);
812
+		}
813
+		$this->_cache_on = true;
814
+		return $class_obj;
815
+	}
816
+
817
+
818
+	/**
819
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
820
+	 *
821
+	 * @param string|mixed $class_name
822
+	 * @param array        $arguments
823
+	 * @param int          $attempt
824
+	 * @return mixed
825
+	 */
826
+	private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
827
+	{
828
+		if (is_object($class_name) || class_exists($class_name)) {
829
+			return $class_name;
830
+		}
831
+		switch ($attempt) {
832
+			case 1:
833
+				// if it's a FQCN then maybe the class is registered with a preceding \
834
+				$class_name = strpos($class_name, '\\') !== false
835
+					? '\\' . ltrim($class_name, '\\')
836
+					: $class_name;
837
+				break;
838
+			case 2:
839
+				//
840
+				$loader = $this->_dependency_map->class_loader($class_name);
841
+				if ($loader && method_exists($this, $loader)) {
842
+					return $this->{$loader}($class_name, $arguments);
843
+				}
844
+				break;
845
+			case 3:
846
+			default:
847
+				return null;
848
+		}
849
+		$attempt++;
850
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
851
+	}
852
+
853
+
854
+	/**
855
+	 * instantiates, caches, and injects dependencies for classes
856
+	 *
857
+	 * @param array  $file_paths         an array of paths to folders to look in
858
+	 * @param string $class_prefix       EE  or EEM or... ???
859
+	 * @param string $class_name         $class name
860
+	 * @param string $type               file type - core? class? helper? model?
861
+	 * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
862
+	 * @param bool   $from_db            some classes are instantiated from the db
863
+	 *                                   and thus call a different method to instantiate
864
+	 * @param bool   $cache              whether to cache the instantiated object for reuse
865
+	 * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
866
+	 * @return bool|null|object          null   = failure to load or instantiate class object.
867
+	 *                                   object = class loaded and instantiated successfully.
868
+	 *                                   bool   = fail or success when $load_only is true
869
+	 * @throws EE_Error
870
+	 * @throws ReflectionException
871
+	 * @throws InvalidInterfaceException
872
+	 * @throws InvalidDataTypeException
873
+	 * @throws InvalidArgumentException
874
+	 */
875
+	protected function _load(
876
+		array $file_paths = [],
877
+		string $class_prefix = 'EE_',
878
+		string $class_name = '',
879
+		string $type = 'class',
880
+		array $arguments = [],
881
+		bool $from_db = false,
882
+		bool $cache = true,
883
+		bool $load_only = false
884
+	) {
885
+		$class_name = ltrim($class_name, '\\');
886
+		// strip php file extension
887
+		$class_name = str_replace('.php', '', trim($class_name));
888
+		// does the class have a prefix ?
889
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
890
+			// make sure $class_prefix is uppercase
891
+			$class_prefix = strtoupper(trim($class_prefix));
892
+			// add class prefix ONCE!!!
893
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
894
+		}
895
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
896
+		$class_exists = class_exists($class_name, false);
897
+		// if we're only loading the class and it already exists, then let's just return true immediately
898
+		if ($load_only && $class_exists) {
899
+			return true;
900
+		}
901
+		$arguments = is_array($arguments) ? $arguments : [$arguments];
902
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
903
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
904
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
905
+		if ($this->_cache_on && $cache && ! $load_only) {
906
+			// return object if it's already cached
907
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
908
+			if ($cached_class !== null) {
909
+				return $cached_class;
910
+			}
911
+		}
912
+		// if the class doesn't already exist.. then we need to try and find the file and load it
913
+		if (! $class_exists) {
914
+			// get full path to file
915
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
916
+			// load the file
917
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
918
+			// if we are only loading a file but NOT instantiating an object
919
+			// then return boolean for whether class was loaded or not
920
+			if ($load_only) {
921
+				return $loaded;
922
+			}
923
+			// if an object was expected but loading failed, then return nothing
924
+			if (! $loaded) {
925
+				return null;
926
+			}
927
+		}
928
+		// instantiate the requested object
929
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
930
+		if ($this->_cache_on && $cache) {
931
+			// save it for later... kinda like gum  { : $
932
+			$this->_set_cached_class(
933
+				$class_obj,
934
+				$class_name,
935
+				$class_prefix,
936
+				$from_db,
937
+				$arguments
938
+			);
939
+		}
940
+		$this->_cache_on = true;
941
+		return $class_obj;
942
+	}
943
+
944
+
945
+	/**
946
+	 * @param string $class_name
947
+	 * @param string $default have to specify something, but not anything that will conflict
948
+	 * @return mixed|string
949
+	 */
950
+	protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
951
+	{
952
+		return $this->_class_abbreviations[ $class_name ] ?? $default;
953
+	}
954
+
955
+
956
+	/**
957
+	 * attempts to find a cached version of the requested class
958
+	 * by looking in the following places:
959
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
960
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
961
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
962
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
963
+	 *
964
+	 * @param string $class_name
965
+	 * @param string $class_prefix
966
+	 * @param array  $arguments
967
+	 * @return mixed
968
+	 */
969
+	protected function _get_cached_class(
970
+		string $class_name,
971
+		string $class_prefix = '',
972
+		array $arguments = []
973
+	) {
974
+		if ($class_name === 'EE_Registry') {
975
+			return $this;
976
+		}
977
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
978
+		// check if class has already been loaded, and return it if it has been
979
+		if (isset($this->{$class_abbreviation})) {
980
+			return $this->{$class_abbreviation};
981
+		}
982
+		$class_name = str_replace('\\', '_', $class_name);
983
+		if (isset($this->{$class_name})) {
984
+			return $this->{$class_name};
985
+		}
986
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
987
+			return $this->addons->get($class_name);
988
+		}
989
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
990
+		if ($this->LIB->has($object_identifier)) {
991
+			return $this->LIB->get($object_identifier);
992
+		}
993
+		foreach ($this->LIB as $key => $object) {
994
+			if (
995
+				// request does not contain new arguments and therefore no args identifier
996
+				! $this->object_identifier->hasArguments($object_identifier)
997
+				// but previously cached class with args was found
998
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
999
+			) {
1000
+				return $object;
1001
+			}
1002
+		}
1003
+		return null;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * removes a cached version of the requested class
1009
+	 *
1010
+	 * @param string  $class_name
1011
+	 * @param boolean $addon
1012
+	 * @param array   $arguments
1013
+	 * @return boolean
1014
+	 */
1015
+	public function clear_cached_class(
1016
+		string $class_name,
1017
+		bool $addon = false,
1018
+		array $arguments = []
1019
+	): bool {
1020
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
1021
+		// check if class has already been loaded, and return it if it has been
1022
+		if (isset($this->{$class_abbreviation})) {
1023
+			$this->{$class_abbreviation} = null;
1024
+			return true;
1025
+		}
1026
+		$class_name = str_replace('\\', '_', $class_name);
1027
+		if (isset($this->{$class_name})) {
1028
+			$this->{$class_name} = null;
1029
+			return true;
1030
+		}
1031
+		if ($addon && $this->addons->has($class_name)) {
1032
+			$this->addons->remove($class_name);
1033
+			return true;
1034
+		}
1035
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1036
+		if ($this->LIB->has($class_name)) {
1037
+			$this->LIB->remove($class_name);
1038
+			return true;
1039
+		}
1040
+		return false;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * _set_cached_class
1046
+	 * attempts to cache the instantiated class locally
1047
+	 * in one of the following places, in the following order:
1048
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1049
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1050
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1051
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1052
+	 *
1053
+	 * @param object $class_obj
1054
+	 * @param string $class_name
1055
+	 * @param string $class_prefix
1056
+	 * @param bool   $from_db
1057
+	 * @param array  $arguments
1058
+	 * @return void
1059
+	 */
1060
+	protected function _set_cached_class(
1061
+		$class_obj,
1062
+		string $class_name,
1063
+		string $class_prefix = '',
1064
+		bool $from_db = false,
1065
+		array $arguments = []
1066
+	) {
1067
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1068
+			return;
1069
+		}
1070
+		// return newly instantiated class
1071
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1072
+		if ($class_abbreviation) {
1073
+			$this->{$class_abbreviation} = $class_obj;
1074
+			return;
1075
+		}
1076
+		$class_name = str_replace('\\', '_', $class_name);
1077
+		if (property_exists($this, $class_name)) {
1078
+			$this->{$class_name} = $class_obj;
1079
+			return;
1080
+		}
1081
+		if ($class_prefix === 'addon') {
1082
+			$this->addons->add($class_name, $class_obj);
1083
+			return;
1084
+		}
1085
+		if (! $from_db) {
1086
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1087
+			$this->LIB->add($class_name, $class_obj);
1088
+		}
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * attempts to find a full valid filepath for the requested class.
1094
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1095
+	 * then returns that path if the target file has been found and is readable
1096
+	 *
1097
+	 * @param string $class_name
1098
+	 * @param string $type
1099
+	 * @param array  $file_paths
1100
+	 * @return string | bool
1101
+	 */
1102
+	protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1103
+	{
1104
+		// make sure $file_paths is an array
1105
+		$file_paths = is_array($file_paths)
1106
+			? $file_paths
1107
+			: [$file_paths];
1108
+		// cycle thru paths
1109
+		foreach ($file_paths as $key => $file_path) {
1110
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1111
+			$file_path = $file_path
1112
+				? str_replace(['/', '\\'], '/', $file_path)
1113
+				: EE_CLASSES;
1114
+			// prep file type
1115
+			$type = ! empty($type)
1116
+				? trim($type, '.') . '.'
1117
+				: '';
1118
+			// build full file path
1119
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1120
+			// does the file exist and can be read ?
1121
+			if (is_readable($file_paths[ $key ])) {
1122
+				return $file_paths[ $key ];
1123
+			}
1124
+		}
1125
+		return false;
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * basically just performs a require_once()
1131
+	 * but with some error handling
1132
+	 *
1133
+	 * @param string $path
1134
+	 * @param string $class_name
1135
+	 * @param string $type
1136
+	 * @param array  $file_paths
1137
+	 * @return bool
1138
+	 * @throws EE_Error
1139
+	 * @throws ReflectionException
1140
+	 */
1141
+	protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1142
+	{
1143
+		$this->resolve_legacy_class_parent($class_name);
1144
+		// don't give up! you gotta...
1145
+		try {
1146
+			// does the file exist and can it be read ?
1147
+			if (! $path) {
1148
+				// just in case the file has already been autoloaded,
1149
+				// but discrepancies in the naming schema are preventing it from
1150
+				// being loaded via one of the EE_Registry::load_*() methods,
1151
+				// then let's try one last hail mary before throwing an exception
1152
+				// and call class_exists() again, but with autoloading turned ON
1153
+				if (class_exists($class_name)) {
1154
+					return true;
1155
+				}
1156
+				// so sorry, can't find the file
1157
+				throw new EE_Error(
1158
+					sprintf(
1159
+						esc_html__(
1160
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1161
+							'event_espresso'
1162
+						),
1163
+						trim($type, '.'),
1164
+						$class_name,
1165
+						'<br />' . implode(',<br />', $file_paths)
1166
+					)
1167
+				);
1168
+			}
1169
+			// get the file
1170
+			require_once($path);
1171
+			// if the class isn't already declared somewhere
1172
+			if (class_exists($class_name, false) === false) {
1173
+				// so sorry, not a class
1174
+				throw new EE_Error(
1175
+					sprintf(
1176
+						esc_html__(
1177
+							'The %s file %s does not appear to contain the %s Class.',
1178
+							'event_espresso'
1179
+						),
1180
+						$type,
1181
+						$path,
1182
+						$class_name
1183
+					)
1184
+				);
1185
+			}
1186
+		} catch (EE_Error $e) {
1187
+			$e->get_error();
1188
+			return false;
1189
+		}
1190
+		return true;
1191
+	}
1192
+
1193
+
1194
+	/**
1195
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1196
+	 * before their class declaration in order to ensure that the parent class was loaded.
1197
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1198
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1199
+	 *
1200
+	 * @param string $class_name
1201
+	 */
1202
+	protected function resolve_legacy_class_parent(string $class_name = '')
1203
+	{
1204
+		try {
1205
+			$legacy_parent_class_map = [
1206
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1207
+			];
1208
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1209
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1210
+			}
1211
+		} catch (Exception $exception) {
1212
+		}
1213
+	}
1214
+
1215
+
1216
+	/**
1217
+	 * _create_object
1218
+	 * Attempts to instantiate the requested class via any of the
1219
+	 * commonly used instantiation methods employed throughout EE.
1220
+	 * The priority for instantiation is as follows:
1221
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1222
+	 *        - model objects via their 'new_instance_from_db' method
1223
+	 *        - model objects via their 'new_instance' method
1224
+	 *        - "singleton" classes" via their 'instance' method
1225
+	 *    - standard instantiable classes via their __constructor
1226
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1227
+	 * then the constructor for the requested class will be examined to determine
1228
+	 * if any dependencies exist, and if they can be injected.
1229
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1230
+	 *
1231
+	 * @param string $class_name
1232
+	 * @param array  $arguments
1233
+	 * @param string $type
1234
+	 * @param bool   $from_db
1235
+	 * @return null|object|bool
1236
+	 * @throws InvalidArgumentException
1237
+	 * @throws InvalidInterfaceException
1238
+	 * @throws EE_Error
1239
+	 * @throws ReflectionException
1240
+	 * @throws InvalidDataTypeException
1241
+	 */
1242
+	protected function _create_object(
1243
+		string $class_name,
1244
+		array $arguments = [],
1245
+		string $type = '',
1246
+		bool $from_db = false
1247
+	) {
1248
+		// create reflection
1249
+		$reflector = $this->mirror->getReflectionClass($class_name);
1250
+		// make sure arguments are an array
1251
+		$arguments = is_array($arguments)
1252
+			? $arguments
1253
+			: [$arguments];
1254
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1255
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1256
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1257
+			? $arguments
1258
+			: [$arguments];
1259
+		// attempt to inject dependencies ?
1260
+		if ($this->_dependency_map->has($class_name)) {
1261
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1262
+		}
1263
+		// instantiate the class if possible
1264
+		if ($reflector->isAbstract()) {
1265
+			// nothing to instantiate, loading file was enough
1266
+			// does not throw an exception so $instantiation_mode is unused
1267
+			// $instantiation_mode = "1) no constructor abstract class";
1268
+			return true;
1269
+		}
1270
+		if (
1271
+			empty($arguments)
1272
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1273
+			&& $reflector->isInstantiable()
1274
+		) {
1275
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1276
+			// $instantiation_mode = "2) no constructor but instantiable";
1277
+			return $reflector->newInstance();
1278
+		}
1279
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1280
+			// $instantiation_mode = "3) new_instance_from_db()";
1281
+			return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1282
+		}
1283
+		if (method_exists($class_name, 'new_instance')) {
1284
+			// $instantiation_mode = "4) new_instance()";
1285
+			return call_user_func_array([$class_name, 'new_instance'], $arguments);
1286
+		}
1287
+		if (method_exists($class_name, 'instance')) {
1288
+			// $instantiation_mode = "5) instance()";
1289
+			return call_user_func_array([$class_name, 'instance'], $arguments);
1290
+		}
1291
+		if ($reflector->isInstantiable()) {
1292
+			$args_passed_count = count($arguments);
1293
+			$args_required_count = count($this->mirror->getRequiredParameters($class_name));
1294
+			if ($args_passed_count < $args_required_count) {
1295
+				throw new RuntimeException(
1296
+					sprintf(
1297
+						__(
1298
+							'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1299
+							'event_espresso'
1300
+						),
1301
+						$class_name,
1302
+						$args_required_count,
1303
+						$args_passed_count
1304
+					)
1305
+				);
1306
+			}
1307
+			// $instantiation_mode = "6) constructor";
1308
+			return $reflector->newInstanceArgs($arguments);
1309
+		}
1310
+		// heh ? something's not right !
1311
+		throw new EE_Error(
1312
+			sprintf(
1313
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1314
+				$type,
1315
+				$class_name
1316
+			)
1317
+		);
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1323
+	 * @param array $array
1324
+	 * @return bool
1325
+	 */
1326
+	protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1327
+	{
1328
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
1329
+	}
1330
+
1331
+
1332
+	/**
1333
+	 * _resolve_dependencies
1334
+	 * examines the constructor for the requested class to determine
1335
+	 * if any dependencies exist, and if they can be injected.
1336
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1337
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1338
+	 * For example:
1339
+	 *        if attempting to load a class "Foo" with the following constructor:
1340
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1341
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1342
+	 *        but only IF they are NOT already present in the incoming arguments array,
1343
+	 *        and the correct classes can be loaded
1344
+	 *
1345
+	 * @param ReflectionClass $reflector
1346
+	 * @param string          $class_name
1347
+	 * @param array           $arguments
1348
+	 * @return array
1349
+	 * @throws InvalidArgumentException
1350
+	 * @throws InvalidDataTypeException
1351
+	 * @throws InvalidInterfaceException
1352
+	 * @throws ReflectionException
1353
+	 */
1354
+	protected function _resolve_dependencies(
1355
+		ReflectionClass $reflector,
1356
+		string $class_name,
1357
+		array $arguments = []
1358
+	): array {
1359
+		// let's examine the constructor
1360
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1361
+		// whu? huh? nothing?
1362
+		if (! $constructor) {
1363
+			return $arguments;
1364
+		}
1365
+		// get constructor parameters
1366
+		$params = $this->mirror->getParametersFromReflection($reflector);
1367
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1368
+		$argument_keys = array_keys($arguments);
1369
+		// now loop thru all the constructors' expected parameters
1370
+		foreach ($params as $index => $param) {
1371
+			try {
1372
+				// is this a dependency for a specific class ?
1373
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1374
+			} catch (ReflectionException $exception) {
1375
+				// uh-oh... most likely a legacy class that has not been autoloaded
1376
+				// let's try to derive the classname from what we have now
1377
+				// and hope that the property var name is close to the class name
1378
+				$param_class = $param->getName();
1379
+				$param_class = str_replace('_', ' ', $param_class);
1380
+				$param_class = ucwords($param_class);
1381
+				$param_class = str_replace(' ', '_', $param_class);
1382
+			}
1383
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1384
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1385
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1386
+				: $param_class;
1387
+			if (
1388
+				// param is not even a class
1389
+				($param_class === null || $this->parameterIsPrimitive($param_class))
1390
+				// and something already exists in the incoming arguments for this param
1391
+				&& array_key_exists($index, $argument_keys)
1392
+				&& isset($arguments[ $argument_keys[ $index ] ])
1393
+			) {
1394
+				// so let's skip this argument and move on to the next
1395
+				continue;
1396
+			}
1397
+			// parameter is type hinted as a class
1398
+			if ($param_class !== null) {
1399
+				// parameter exists as an incoming argument, AND it's the correct class
1400
+				if (
1401
+					array_key_exists($index, $argument_keys)
1402
+					&& isset($arguments[ $argument_keys[ $index ] ])
1403
+					&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1404
+				) {
1405
+					// skip this argument and move on to the next
1406
+					continue;
1407
+				}
1408
+				// parameter should be injected
1409
+				if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1410
+					$arguments = $this->_resolve_dependency(
1411
+						$class_name,
1412
+						$param_class,
1413
+						$arguments,
1414
+						$index
1415
+					);
1416
+				}
1417
+			}
1418
+			if (empty($arguments[ $index ])) {
1419
+				$default_value = $this->mirror->getParameterDefaultValue(
1420
+					$param,
1421
+					$class_name,
1422
+					$index
1423
+				);
1424
+				// if there's no default value, and the incoming argument is an array (albeit empty), then use that
1425
+				$arguments[ $index ] = $default_value === null
1426
+									   && isset($arguments[ $index ])
1427
+									   && is_array($arguments[ $index ])
1428
+					? $arguments[ $index ]
1429
+					: $default_value;
1430
+			}
1431
+		}
1432
+		return $arguments;
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * @param string $class_name
1438
+	 * @param string $param_class
1439
+	 * @param array  $arguments
1440
+	 * @param mixed  $index
1441
+	 * @return array
1442
+	 * @throws InvalidArgumentException
1443
+	 * @throws InvalidInterfaceException
1444
+	 * @throws InvalidDataTypeException
1445
+	 */
1446
+	protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1447
+	{
1448
+		$dependency = null;
1449
+		// should dependency be loaded from cache ?
1450
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1451
+			$class_name,
1452
+			$param_class
1453
+		);
1454
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1455
+		// we might have a dependency...
1456
+		// let's MAYBE try and find it in our cache if that's what's been requested
1457
+		$cached_class = $cache_on
1458
+			? $this->_get_cached_class($param_class)
1459
+			: null;
1460
+		// and grab it if it exists
1461
+		if ($cached_class instanceof $param_class) {
1462
+			$dependency = $cached_class;
1463
+		} elseif ($param_class !== $class_name) {
1464
+			// obtain the loader method from the dependency map
1465
+			$loader = $this->_dependency_map->class_loader($param_class);
1466
+			// is loader a custom closure ?
1467
+			if ($loader instanceof Closure) {
1468
+				$dependency = $loader($arguments);
1469
+			} else {
1470
+				// set the cache on property for the recursive loading call
1471
+				$this->_cache_on = $cache_on;
1472
+				// if not, then let's try and load it via the registry
1473
+				if ($loader && method_exists($this, $loader)) {
1474
+					$dependency = $this->{$loader}($param_class);
1475
+				} else {
1476
+					$dependency = LoaderFactory::getLoader()->load(
1477
+						$param_class,
1478
+						[],
1479
+						$cache_on
1480
+					);
1481
+				}
1482
+			}
1483
+		}
1484
+		// did we successfully find the correct dependency ?
1485
+		if ($dependency instanceof $param_class) {
1486
+			// then let's inject it into the incoming array of arguments at the correct location
1487
+			$arguments[ $index ] = $dependency;
1488
+		}
1489
+		return $arguments;
1490
+	}
1491
+
1492
+
1493
+	/**
1494
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1495
+	 *
1496
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1497
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1498
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1499
+	 * @param array  $arguments
1500
+	 * @return object
1501
+	 */
1502
+	public static function factory(string $classname, array $arguments = [])
1503
+	{
1504
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1505
+		if ($loader instanceof Closure) {
1506
+			return $loader($arguments);
1507
+		}
1508
+		if (method_exists(self::instance(), $loader)) {
1509
+			return self::instance()->{$loader}($classname, $arguments);
1510
+		}
1511
+		return null;
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 * Gets the addon by its class name
1517
+	 *
1518
+	 * @param string $class_name
1519
+	 * @return EE_Addon
1520
+	 */
1521
+	public function getAddon(string $class_name): ?EE_Addon
1522
+	{
1523
+		$class_name = str_replace('\\', '_', $class_name);
1524
+		return $this->addons->{$class_name} ?? null;
1525
+	}
1526
+
1527
+
1528
+	/**
1529
+	 * removes the addon from the internal cache
1530
+	 *
1531
+	 * @param string $class_name
1532
+	 * @return void
1533
+	 */
1534
+	public function removeAddon(string $class_name)
1535
+	{
1536
+		$class_name = str_replace('\\', '_', $class_name);
1537
+		$this->addons->remove($class_name);
1538
+	}
1539
+
1540
+
1541
+	/**
1542
+	 * Gets the addon by its name/slug (not classname. For that, just
1543
+	 * use the get_addon() method above
1544
+	 *
1545
+	 * @param string $name
1546
+	 * @return EE_Addon
1547
+	 */
1548
+	public function get_addon_by_name(string $name): ?EE_Addon
1549
+	{
1550
+		foreach ($this->addons as $addon) {
1551
+			if ($addon->name() === $name) {
1552
+				return $addon;
1553
+			}
1554
+		}
1555
+		return null;
1556
+	}
1557
+
1558
+
1559
+	/**
1560
+	 * Gets an array of all the registered addons, where the keys are their names.
1561
+	 * (ie, what each returns for their name() function)
1562
+	 * They're already available on EE_Registry::instance()->addons as properties,
1563
+	 * where each property's name is the addon's classname,
1564
+	 * So if you just want to get the addon by classname,
1565
+	 * OR use the get_addon() method above.
1566
+	 * PLEASE  NOTE:
1567
+	 * addons with Fully Qualified Class Names
1568
+	 * have had the namespace separators converted to underscores,
1569
+	 * so a classname like Fully\Qualified\ClassName
1570
+	 * would have been converted to Fully_Qualified_ClassName
1571
+	 *
1572
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1573
+	 */
1574
+	public function get_addons_by_name(): array
1575
+	{
1576
+		$addons = [];
1577
+		foreach ($this->addons as $addon) {
1578
+			$addons[ $addon->name() ] = $addon;
1579
+		}
1580
+		return $addons;
1581
+	}
1582
+
1583
+
1584
+	/**
1585
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1586
+	 * a stale copy of it around
1587
+	 *
1588
+	 * @param string $model_name
1589
+	 * @return EEM_Base
1590
+	 * @throws EE_Error
1591
+	 * @throws ReflectionException
1592
+	 */
1593
+	public function reset_model(string $model_name): ?EEM_Base
1594
+	{
1595
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1596
+			? "EEM_$model_name"
1597
+			: $model_name;
1598
+		if (! $this->LIB->has($model_class_name)) {
1599
+			return null;
1600
+		}
1601
+		$model = $this->LIB->get($model_class_name);
1602
+		if (! $model instanceof EEM_Base) {
1603
+			return null;
1604
+		}
1605
+		// get that model reset it and make sure we nuke the old reference to it
1606
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1607
+			$this->LIB->remove($model_class_name);
1608
+			$this->LIB->add($model_class_name, $model->reset());
1609
+		} else {
1610
+			throw new EE_Error(
1611
+				sprintf(
1612
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1613
+					$model_name
1614
+				)
1615
+			);
1616
+		}
1617
+		return $model;
1618
+	}
1619
+
1620
+
1621
+	/**
1622
+	 * Resets the registry.
1623
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1624
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1625
+	 * - $_dependency_map
1626
+	 * - $_class_abbreviations
1627
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1628
+	 * - $REQ:  Still on the same request so no need to change.
1629
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1630
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1631
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1632
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1633
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1634
+	 *             switch or on the restore.
1635
+	 * - $modules
1636
+	 * - $shortcodes
1637
+	 * - $widgets
1638
+	 *
1639
+	 * @param boolean $hard             [deprecated]
1640
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1641
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1642
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1643
+	 * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1644
+	 *                                  client
1645
+	 *                                  code instead can just change the model context to a different blog id if
1646
+	 *                                  necessary
1647
+	 * @return EE_Registry
1648
+	 * @throws EE_Error
1649
+	 * @throws ReflectionException
1650
+	 */
1651
+	public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1652
+	{
1653
+		$instance            = self::instance();
1654
+		$instance->_cache_on = true;
1655
+		// reset some "special" classes
1656
+		EEH_Activation::reset();
1657
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1658
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1659
+		$instance->CART = null;
1660
+		$instance->MRM = null;
1661
+		// messages reset
1662
+		EED_Messages::reset();
1663
+		// handle of objects cached on LIB
1664
+		foreach (['LIB', 'modules'] as $cache) {
1665
+			foreach ($instance->{$cache} as $class_name => $class) {
1666
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1667
+					unset($instance->{$cache}->{$class_name});
1668
+				}
1669
+			}
1670
+		}
1671
+		return $instance;
1672
+	}
1673
+
1674
+
1675
+	/**
1676
+	 * if passed object implements ResettableInterface, then call it's reset() method
1677
+	 * if passed object implements InterminableInterface, then return false,
1678
+	 * to indicate that it should NOT be cleared from the Registry cache
1679
+	 *
1680
+	 * @param      $object
1681
+	 * @param bool $reset_models
1682
+	 * @return bool returns true if cached object should be unset
1683
+	 * @throws EE_Error
1684
+	 * @throws ReflectionException
1685
+	 */
1686
+	private static function _reset_and_unset_object($object, bool $reset_models): bool
1687
+	{
1688
+		if (! is_object($object)) {
1689
+			// don't unset anything that's not an object
1690
+			return false;
1691
+		}
1692
+		if ($object instanceof EED_Module) {
1693
+			$object::reset();
1694
+			// don't unset modules
1695
+			return false;
1696
+		}
1697
+		if ($object instanceof ResettableInterface) {
1698
+			if ($object instanceof EEM_Base) {
1699
+				if ($reset_models) {
1700
+					$object->reset();
1701
+					return true;
1702
+				}
1703
+				return false;
1704
+			}
1705
+			$object->reset();
1706
+			return true;
1707
+		}
1708
+		if (! $object instanceof InterminableInterface) {
1709
+			return true;
1710
+		}
1711
+		return false;
1712
+	}
1713
+
1714
+
1715
+	/**
1716
+	 * Gets all the custom post type models defined
1717
+	 *
1718
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1719
+	 */
1720
+	public function cpt_models(): array
1721
+	{
1722
+		$cpt_models = [];
1723
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1724
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1725
+				$cpt_models[ $short_name ] = $classname;
1726
+			}
1727
+		}
1728
+		return $cpt_models;
1729
+	}
1730
+
1731
+
1732
+	/**
1733
+	 * @return EE_Config
1734
+	 */
1735
+	public static function CFG(): EE_Config
1736
+	{
1737
+		return self::instance()->CFG;
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * @param string $class_name
1743
+	 * @return ReflectionClass
1744
+	 * @throws ReflectionException
1745
+	 * @throws InvalidDataTypeException
1746
+	 * @deprecated 4.9.62.p
1747
+	 */
1748
+	public function get_ReflectionClass(string $class_name): ReflectionClass
1749
+	{
1750
+		return $this->mirror->getReflectionClass($class_name);
1751
+	}
1752
+
1753
+	private function parameterIsPrimitive(?string $param_class): bool
1754
+	{
1755
+		return in_array(
1756
+			$param_class,
1757
+			[
1758
+				'array',
1759
+				'bool',
1760
+				'float',
1761
+				'int',
1762
+				'string',
1763
+			]
1764
+		);
1765
+	}
1766 1766
 }
Please login to merge, or discard this patch.
core/EE_Encryption.core.php 1 patch
Indentation   +578 added lines, -578 removed lines patch added patch discarded remove patch
@@ -25,582 +25,582 @@
 block discarded – undo
25 25
  */
26 26
 class EE_Encryption implements InterminableInterface
27 27
 {
28
-    /**
29
-     * key used for saving the encryption key to the wp_options table
30
-     */
31
-    const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
32
-
33
-    /**
34
-     * the OPENSSL cipher method used
35
-     */
36
-    const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
37
-
38
-    /**
39
-     * WP "options_name" used to store a verified available cipher method
40
-     */
41
-    const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
42
-
43
-    /**
44
-     * the OPENSSL digest method used
45
-     */
46
-    const OPENSSL_DIGEST_METHOD = 'sha512';
47
-
48
-    /**
49
-     * separates the encrypted text from the initialization vector
50
-     */
51
-    const OPENSSL_IV_DELIMITER = ':iv:';
52
-
53
-    /**
54
-     * appended to text encrypted using the acme encryption
55
-     */
56
-    const ACME_ENCRYPTION_FLAG = '::ae';
57
-
58
-
59
-    /**
60
-     * instance of the EE_Encryption object
61
-     */
62
-    protected static $_instance;
63
-
64
-    /**
65
-     * @var string $_encryption_key
66
-     */
67
-    protected $_encryption_key;
68
-
69
-    /**
70
-     * @var string $cipher_method
71
-     */
72
-    private $cipher_method = '';
73
-
74
-    /**
75
-     * @var array $cipher_methods
76
-     */
77
-    private $cipher_methods = [];
78
-
79
-    /**
80
-     * @var array $digest_methods
81
-     */
82
-    private $digest_methods = [];
83
-
84
-    /**
85
-     * @var boolean $_use_openssl_encrypt
86
-     */
87
-    protected $_use_openssl_encrypt = false;
88
-
89
-    /**
90
-     * @var boolean $_use_base64_encode
91
-     */
92
-    protected $_use_base64_encode = false;
93
-
94
-
95
-    /**
96
-     * protected constructor to prevent direct creation
97
-     */
98
-    protected function __construct()
99
-    {
100
-        if (! defined('ESPRESSO_ENCRYPT')) {
101
-            define('ESPRESSO_ENCRYPT', true);
102
-        }
103
-        if (extension_loaded('openssl')) {
104
-            $this->_use_openssl_encrypt = true;
105
-        }
106
-        if (function_exists('base64_encode')) {
107
-            $this->_use_base64_encode = true;
108
-        }
109
-        EE_Error::doing_it_wrong(__METHOD__, esc_html__('Usage is deprecated.', 'event_espresso'), '5.0.8.p');
110
-    }
111
-
112
-
113
-    /**
114
-     * singleton method used to instantiate class object
115
-     *
116
-     * @return EE_Encryption
117
-     */
118
-    public static function instance()
119
-    {
120
-        // check if class object is instantiated
121
-        if (! EE_Encryption::$_instance instanceof EE_Encryption) {
122
-            EE_Encryption::$_instance = new self();
123
-        }
124
-        return EE_Encryption::$_instance;
125
-    }
126
-
127
-
128
-    /**
129
-     * get encryption key
130
-     *
131
-     * @return string
132
-     */
133
-    public function get_encryption_key()
134
-    {
135
-        // if encryption key has not been set
136
-        if (empty($this->_encryption_key)) {
137
-            // retrieve encryption_key from db
138
-            $this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
139
-            // WHAT?? No encryption_key in the db ??
140
-            if ($this->_encryption_key === '') {
141
-                // let's make one. And md5 it to make it just the right size for a key
142
-                $new_key = md5($this->generate_random_string());
143
-                // now save it to the db for later
144
-                add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
145
-                // here's the key - FINALLY !
146
-                $this->_encryption_key = $new_key;
147
-            }
148
-        }
149
-        return $this->_encryption_key;
150
-    }
151
-
152
-
153
-    /**
154
-     * encrypts data
155
-     *
156
-     * @param string $text_string - the text to be encrypted
157
-     * @return string
158
-     * @throws RuntimeException
159
-     */
160
-    public function encrypt($text_string = '')
161
-    {
162
-        // you give me nothing??? GET OUT !
163
-        if (empty($text_string)) {
164
-            return $text_string;
165
-        }
166
-        if ($this->_use_openssl_encrypt) {
167
-            $encrypted_text = $this->openssl_encrypt($text_string);
168
-        } else {
169
-            $encrypted_text = $this->acme_encrypt($text_string);
170
-        }
171
-        return $encrypted_text;
172
-    }
173
-
174
-
175
-    /**
176
-     * decrypts data
177
-     *
178
-     * @param string $encrypted_text - the text to be decrypted
179
-     * @return string
180
-     * @throws RuntimeException
181
-     */
182
-    public function decrypt($encrypted_text = '')
183
-    {
184
-        // you give me nothing??? GET OUT !
185
-        if (empty($encrypted_text)) {
186
-            return $encrypted_text;
187
-        }
188
-        // if PHP's mcrypt functions are installed then we'll use them
189
-        if ($this->_use_openssl_encrypt) {
190
-            $decrypted_text = $this->openssl_decrypt($encrypted_text);
191
-        } else {
192
-            $decrypted_text = $this->acme_decrypt($encrypted_text);
193
-        }
194
-        return $decrypted_text;
195
-    }
196
-
197
-
198
-    /**
199
-     * encodes string with PHP's base64 encoding
200
-     *
201
-     * @see http://php.net/manual/en/function.base64-encode.php
202
-     * @param string $text_string the text to be encoded
203
-     * @return string
204
-     */
205
-    public function base64_string_encode($text_string = '')
206
-    {
207
-        // you give me nothing??? GET OUT !
208
-        if (empty($text_string) || ! $this->_use_base64_encode) {
209
-            return $text_string;
210
-        }
211
-        // encode
212
-        return base64_encode($text_string);
213
-    }
214
-
215
-
216
-    /**
217
-     * decodes string that has been encoded with PHP's base64 encoding
218
-     *
219
-     * @see http://php.net/manual/en/function.base64-encode.php
220
-     * @param string $encoded_string the text to be decoded
221
-     * @return string
222
-     * @throws RuntimeException
223
-     */
224
-    public function base64_string_decode($encoded_string = '')
225
-    {
226
-        // you give me nothing??? GET OUT !
227
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
228
-            return $encoded_string;
229
-        }
230
-        // decode
231
-        $decoded_string = base64_decode($encoded_string);
232
-        if ($decoded_string === false) {
233
-            throw new RuntimeException(
234
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
235
-            );
236
-        }
237
-        return $decoded_string;
238
-    }
239
-
240
-
241
-    /**
242
-     * encodes  url string with PHP's base64 encoding
243
-     *
244
-     * @see http://php.net/manual/en/function.base64-encode.php
245
-     * @param string $text_string the text to be encoded
246
-     * @return string
247
-     */
248
-    public function base64_url_encode($text_string = '')
249
-    {
250
-        // you give me nothing??? GET OUT !
251
-        if (empty($text_string) || ! $this->_use_base64_encode) {
252
-            return $text_string;
253
-        }
254
-        // encode
255
-        $encoded_string = base64_encode($text_string);
256
-        // remove chars to make encoding more URL friendly
257
-        return strtr($encoded_string, '+/=', '-_,');
258
-    }
259
-
260
-
261
-    /**
262
-     * decodes  url string that has been encoded with PHP's base64 encoding
263
-     *
264
-     * @see http://php.net/manual/en/function.base64-encode.php
265
-     * @param string $encoded_string the text to be decoded
266
-     * @return string
267
-     * @throws RuntimeException
268
-     */
269
-    public function base64_url_decode($encoded_string = '')
270
-    {
271
-        // replace previously removed characters
272
-        $encoded_string = strtr($encoded_string, '-_,', '+/=');
273
-        // you give me nothing??? GET OUT !
274
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
275
-            return $encoded_string;
276
-        }
277
-        // decode
278
-        $decoded_string = base64_decode($encoded_string);
279
-        if ($decoded_string === false) {
280
-            throw new RuntimeException(
281
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
282
-            );
283
-        }
284
-        return $decoded_string;
285
-    }
286
-
287
-
288
-    /**
289
-     * encrypts data using PHP's openssl functions
290
-     *
291
-     * @param string $text_string the text to be encrypted
292
-     * @param string $cipher_method
293
-     * @param string $encryption_key
294
-     * @return string
295
-     * @throws RuntimeException
296
-     */
297
-    protected function openssl_encrypt(
298
-        $text_string = '',
299
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
300
-        $encryption_key = ''
301
-    ) {
302
-        // you give me nothing??? GET OUT !
303
-        if (empty($text_string)) {
304
-            return $text_string;
305
-        }
306
-        $this->cipher_method = $this->getCipherMethod($cipher_method);
307
-        // get initialization vector size
308
-        $iv_size = openssl_cipher_iv_length($this->cipher_method);
309
-        // generate initialization vector.
310
-        // The second parameter ("crypto_strong") is passed by reference,
311
-        // and is used to determines if the algorithm used was "cryptographically strong"
312
-        // openssl_random_pseudo_bytes() will toggle it to either true or false
313
-        $iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
314
-        if ($iv === false || $is_strong === false) {
315
-            throw new RuntimeException(
316
-                esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
317
-            );
318
-        }
319
-        // encrypt it
320
-        $encrypted_text = openssl_encrypt(
321
-            $text_string,
322
-            $this->cipher_method,
323
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
324
-            0,
325
-            $iv
326
-        );
327
-        // append the initialization vector
328
-        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
329
-        // trim and maybe encode
330
-        return $this->_use_base64_encode
331
-            ? trim(base64_encode($encrypted_text))
332
-            : trim($encrypted_text);
333
-    }
334
-
335
-
336
-    /**
337
-     * Returns a cipher method that has been verified to work.
338
-     * First checks if the cached cipher has been set already and if so, returns that.
339
-     * Then tests the incoming default and returns that if it's good.
340
-     * If not, then it retrieves the previously tested and saved cipher method.
341
-     * But if that doesn't exist, then calls getAvailableCipherMethod()
342
-     * to see what is available on the server, and returns the results.
343
-     *
344
-     * @param string $cipher_method
345
-     * @return string
346
-     * @throws RuntimeException
347
-     */
348
-    protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
349
-    {
350
-        if ($this->cipher_method !== '') {
351
-            return $this->cipher_method;
352
-        }
353
-        // verify that the default cipher method can produce an initialization vector
354
-        if (openssl_cipher_iv_length($cipher_method) === false) {
355
-            // nope? okay let's get what we found in the past to work
356
-            $cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
357
-            // oops... haven't tested available cipher methods yet
358
-            if ($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
359
-                $cipher_method = $this->getAvailableCipherMethod($cipher_method);
360
-            }
361
-        }
362
-        return $cipher_method;
363
-    }
364
-
365
-
366
-    /**
367
-     * @param string $cipher_method
368
-     * @return string
369
-     * @throws \RuntimeException
370
-     */
371
-    protected function getAvailableCipherMethod($cipher_method)
372
-    {
373
-        // verify that the incoming cipher method can produce an initialization vector
374
-        if (openssl_cipher_iv_length($cipher_method) === false) {
375
-            // nope? then check the next cipher in the list of available cipher methods
376
-            $cipher_method = next($this->cipher_methods);
377
-            // what? there's no list? then generate that list and cache it,
378
-            if (empty($this->cipher_methods)) {
379
-                $this->cipher_methods = openssl_get_cipher_methods();
380
-                // then grab the first item from the list
381
-                $cipher_method = reset($this->cipher_methods);
382
-            }
383
-            if ($cipher_method === false) {
384
-                throw new RuntimeException(
385
-                    esc_html__(
386
-                        'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
387
-                        'event_espresso'
388
-                    )
389
-                );
390
-            }
391
-            // verify that the next cipher method works
392
-            return $this->getAvailableCipherMethod($cipher_method);
393
-        }
394
-        // if we've gotten this far, then we found an available cipher method that works
395
-        // so save that for next time
396
-        update_option(
397
-            EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
398
-            $cipher_method
399
-        );
400
-        return $cipher_method;
401
-    }
402
-
403
-
404
-    /**
405
-     * decrypts data that has been encrypted with PHP's openssl functions
406
-     *
407
-     * @param string $encrypted_text the text to be decrypted
408
-     * @param string $cipher_method
409
-     * @param string $encryption_key
410
-     * @return string
411
-     * @throws RuntimeException
412
-     */
413
-    protected function openssl_decrypt(
414
-        $encrypted_text = '',
415
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
416
-        $encryption_key = ''
417
-    ) {
418
-        // you give me nothing??? GET OUT !
419
-        if (empty($encrypted_text)) {
420
-            return $encrypted_text;
421
-        }
422
-        // decode
423
-        $encrypted_text       = $this->valid_base_64($encrypted_text)
424
-            ? $this->base64_url_decode($encrypted_text)
425
-            : $encrypted_text;
426
-        $encrypted_components = explode(
427
-            EE_Encryption::OPENSSL_IV_DELIMITER,
428
-            $encrypted_text,
429
-            2
430
-        );
431
-        // decrypt it
432
-        $decrypted_text = openssl_decrypt(
433
-            $encrypted_components[0],
434
-            $this->getCipherMethod($cipher_method),
435
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
436
-            0,
437
-            $encrypted_components[1]
438
-        );
439
-        $decrypted_text = trim($decrypted_text);
440
-        return $decrypted_text;
441
-    }
442
-
443
-
444
-    /**
445
-     * Computes the digest hash value using the specified digest method.
446
-     * If that digest method fails to produce a valid hash value,
447
-     * then we'll grab the next digest method and recursively try again until something works.
448
-     *
449
-     * @param string $digest_method
450
-     * @param string $encryption_key
451
-     * @return string
452
-     * @throws RuntimeException
453
-     */
454
-    protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = '')
455
-    {
456
-        $encryption_key    = $encryption_key !== ''
457
-            ? $encryption_key
458
-            : $this->get_encryption_key();
459
-        $digest_hash_value = openssl_digest($encryption_key, $digest_method);
460
-        if ($digest_hash_value === false) {
461
-            return $this->getDigestHashValue($this->getDigestMethod());
462
-        }
463
-        return $digest_hash_value;
464
-    }
465
-
466
-
467
-    /**
468
-     * Returns the NEXT element in the $digest_methods array.
469
-     * If the $digest_methods array is empty, then we populate it
470
-     * with the available values returned from openssl_get_md_methods().
471
-     *
472
-     * @return string
473
-     * @throws \RuntimeException
474
-     */
475
-    protected function getDigestMethod()
476
-    {
477
-        $digest_method = prev($this->digest_methods);
478
-        if (empty($this->digest_methods)) {
479
-            $this->digest_methods = openssl_get_md_methods();
480
-            $digest_method        = end($this->digest_methods);
481
-        }
482
-        if ($digest_method === false) {
483
-            throw new RuntimeException(
484
-                esc_html__(
485
-                    'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
486
-                    'event_espresso'
487
-                )
488
-            );
489
-        }
490
-        return $digest_method;
491
-    }
492
-
493
-
494
-    /**
495
-     * encrypts data for acme servers that didn't bother to install PHP mcrypt
496
-     *
497
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
498
-     * @param string $text_string the text to be decrypted
499
-     * @return string
500
-     */
501
-    protected function acme_encrypt($text_string = '')
502
-    {
503
-        // you give me nothing??? GET OUT !
504
-        if (empty($text_string)) {
505
-            return $text_string;
506
-        }
507
-        $key_bits    = str_split(
508
-            str_pad(
509
-                '',
510
-                strlen($text_string),
511
-                $this->get_encryption_key(),
512
-                STR_PAD_RIGHT
513
-            )
514
-        );
515
-        $string_bits = str_split($text_string);
516
-        foreach ($string_bits as $k => $v) {
517
-            $temp              = ord($v) + ord($key_bits[ $k ]);
518
-            $string_bits[ $k ] = chr($temp > 255 ? ($temp - 256) : $temp);
519
-        }
520
-        $encrypted_text = implode('', $string_bits);
521
-        $encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
522
-        return $this->_use_base64_encode
523
-            ? base64_encode($encrypted_text)
524
-            : $encrypted_text;
525
-    }
526
-
527
-
528
-    /**
529
-     * decrypts data for acme servers that didn't bother to install PHP mcrypt
530
-     *
531
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
532
-     * @param string $encrypted_text the text to be decrypted
533
-     * @return string
534
-     * @throws RuntimeException
535
-     */
536
-    protected function acme_decrypt($encrypted_text = '')
537
-    {
538
-        // you give me nothing??? GET OUT !
539
-        if (empty($encrypted_text)) {
540
-            return $encrypted_text;
541
-        }
542
-        // decode the data ?
543
-        $encrypted_text = $this->valid_base_64($encrypted_text)
544
-            ? $this->base64_url_decode($encrypted_text)
545
-            : $encrypted_text;
546
-        $encrypted_text = substr($encrypted_text, 0, -4);
547
-        $key_bits       = str_split(
548
-            str_pad(
549
-                '',
550
-                strlen($encrypted_text),
551
-                $this->get_encryption_key(),
552
-                STR_PAD_RIGHT
553
-            )
554
-        );
555
-        $string_bits    = str_split($encrypted_text);
556
-        foreach ($string_bits as $k => $v) {
557
-            $temp              = ord($v) - ord($key_bits[ $k ]);
558
-            $string_bits[ $k ] = chr($temp < 0 ? ($temp + 256) : $temp);
559
-        }
560
-        return implode('', $string_bits);
561
-    }
562
-
563
-
564
-    /**
565
-     * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
566
-     * @param $string
567
-     * @return bool
568
-     */
569
-    protected function valid_base_64($string)
570
-    {
571
-        // ensure data is a string
572
-        if (! is_string($string) || ! $this->_use_base64_encode) {
573
-            return false;
574
-        }
575
-        $decoded = base64_decode($string, true);
576
-        // Check if there is no invalid character in string
577
-        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
578
-            return false;
579
-        }
580
-        // Decode the string in strict mode and send the response
581
-        if (! base64_decode($string, true)) {
582
-            return false;
583
-        }
584
-        // Encode and compare it to original one
585
-        return base64_encode($decoded) === $string;
586
-    }
587
-
588
-
589
-    /**
590
-     * generate random string
591
-     *
592
-     * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
593
-     * @param int $length number of characters for random string
594
-     * @return string
595
-     */
596
-    public function generate_random_string($length = 40)
597
-    {
598
-        $iterations    = ceil($length / 40);
599
-        $random_string = '';
600
-        for ($i = 0; $i < $iterations; $i++) {
601
-            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
602
-        }
603
-        $random_string = substr($random_string, 0, $length);
604
-        return $random_string;
605
-    }
28
+	/**
29
+	 * key used for saving the encryption key to the wp_options table
30
+	 */
31
+	const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
32
+
33
+	/**
34
+	 * the OPENSSL cipher method used
35
+	 */
36
+	const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
37
+
38
+	/**
39
+	 * WP "options_name" used to store a verified available cipher method
40
+	 */
41
+	const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
42
+
43
+	/**
44
+	 * the OPENSSL digest method used
45
+	 */
46
+	const OPENSSL_DIGEST_METHOD = 'sha512';
47
+
48
+	/**
49
+	 * separates the encrypted text from the initialization vector
50
+	 */
51
+	const OPENSSL_IV_DELIMITER = ':iv:';
52
+
53
+	/**
54
+	 * appended to text encrypted using the acme encryption
55
+	 */
56
+	const ACME_ENCRYPTION_FLAG = '::ae';
57
+
58
+
59
+	/**
60
+	 * instance of the EE_Encryption object
61
+	 */
62
+	protected static $_instance;
63
+
64
+	/**
65
+	 * @var string $_encryption_key
66
+	 */
67
+	protected $_encryption_key;
68
+
69
+	/**
70
+	 * @var string $cipher_method
71
+	 */
72
+	private $cipher_method = '';
73
+
74
+	/**
75
+	 * @var array $cipher_methods
76
+	 */
77
+	private $cipher_methods = [];
78
+
79
+	/**
80
+	 * @var array $digest_methods
81
+	 */
82
+	private $digest_methods = [];
83
+
84
+	/**
85
+	 * @var boolean $_use_openssl_encrypt
86
+	 */
87
+	protected $_use_openssl_encrypt = false;
88
+
89
+	/**
90
+	 * @var boolean $_use_base64_encode
91
+	 */
92
+	protected $_use_base64_encode = false;
93
+
94
+
95
+	/**
96
+	 * protected constructor to prevent direct creation
97
+	 */
98
+	protected function __construct()
99
+	{
100
+		if (! defined('ESPRESSO_ENCRYPT')) {
101
+			define('ESPRESSO_ENCRYPT', true);
102
+		}
103
+		if (extension_loaded('openssl')) {
104
+			$this->_use_openssl_encrypt = true;
105
+		}
106
+		if (function_exists('base64_encode')) {
107
+			$this->_use_base64_encode = true;
108
+		}
109
+		EE_Error::doing_it_wrong(__METHOD__, esc_html__('Usage is deprecated.', 'event_espresso'), '5.0.8.p');
110
+	}
111
+
112
+
113
+	/**
114
+	 * singleton method used to instantiate class object
115
+	 *
116
+	 * @return EE_Encryption
117
+	 */
118
+	public static function instance()
119
+	{
120
+		// check if class object is instantiated
121
+		if (! EE_Encryption::$_instance instanceof EE_Encryption) {
122
+			EE_Encryption::$_instance = new self();
123
+		}
124
+		return EE_Encryption::$_instance;
125
+	}
126
+
127
+
128
+	/**
129
+	 * get encryption key
130
+	 *
131
+	 * @return string
132
+	 */
133
+	public function get_encryption_key()
134
+	{
135
+		// if encryption key has not been set
136
+		if (empty($this->_encryption_key)) {
137
+			// retrieve encryption_key from db
138
+			$this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
139
+			// WHAT?? No encryption_key in the db ??
140
+			if ($this->_encryption_key === '') {
141
+				// let's make one. And md5 it to make it just the right size for a key
142
+				$new_key = md5($this->generate_random_string());
143
+				// now save it to the db for later
144
+				add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
145
+				// here's the key - FINALLY !
146
+				$this->_encryption_key = $new_key;
147
+			}
148
+		}
149
+		return $this->_encryption_key;
150
+	}
151
+
152
+
153
+	/**
154
+	 * encrypts data
155
+	 *
156
+	 * @param string $text_string - the text to be encrypted
157
+	 * @return string
158
+	 * @throws RuntimeException
159
+	 */
160
+	public function encrypt($text_string = '')
161
+	{
162
+		// you give me nothing??? GET OUT !
163
+		if (empty($text_string)) {
164
+			return $text_string;
165
+		}
166
+		if ($this->_use_openssl_encrypt) {
167
+			$encrypted_text = $this->openssl_encrypt($text_string);
168
+		} else {
169
+			$encrypted_text = $this->acme_encrypt($text_string);
170
+		}
171
+		return $encrypted_text;
172
+	}
173
+
174
+
175
+	/**
176
+	 * decrypts data
177
+	 *
178
+	 * @param string $encrypted_text - the text to be decrypted
179
+	 * @return string
180
+	 * @throws RuntimeException
181
+	 */
182
+	public function decrypt($encrypted_text = '')
183
+	{
184
+		// you give me nothing??? GET OUT !
185
+		if (empty($encrypted_text)) {
186
+			return $encrypted_text;
187
+		}
188
+		// if PHP's mcrypt functions are installed then we'll use them
189
+		if ($this->_use_openssl_encrypt) {
190
+			$decrypted_text = $this->openssl_decrypt($encrypted_text);
191
+		} else {
192
+			$decrypted_text = $this->acme_decrypt($encrypted_text);
193
+		}
194
+		return $decrypted_text;
195
+	}
196
+
197
+
198
+	/**
199
+	 * encodes string with PHP's base64 encoding
200
+	 *
201
+	 * @see http://php.net/manual/en/function.base64-encode.php
202
+	 * @param string $text_string the text to be encoded
203
+	 * @return string
204
+	 */
205
+	public function base64_string_encode($text_string = '')
206
+	{
207
+		// you give me nothing??? GET OUT !
208
+		if (empty($text_string) || ! $this->_use_base64_encode) {
209
+			return $text_string;
210
+		}
211
+		// encode
212
+		return base64_encode($text_string);
213
+	}
214
+
215
+
216
+	/**
217
+	 * decodes string that has been encoded with PHP's base64 encoding
218
+	 *
219
+	 * @see http://php.net/manual/en/function.base64-encode.php
220
+	 * @param string $encoded_string the text to be decoded
221
+	 * @return string
222
+	 * @throws RuntimeException
223
+	 */
224
+	public function base64_string_decode($encoded_string = '')
225
+	{
226
+		// you give me nothing??? GET OUT !
227
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
228
+			return $encoded_string;
229
+		}
230
+		// decode
231
+		$decoded_string = base64_decode($encoded_string);
232
+		if ($decoded_string === false) {
233
+			throw new RuntimeException(
234
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
235
+			);
236
+		}
237
+		return $decoded_string;
238
+	}
239
+
240
+
241
+	/**
242
+	 * encodes  url string with PHP's base64 encoding
243
+	 *
244
+	 * @see http://php.net/manual/en/function.base64-encode.php
245
+	 * @param string $text_string the text to be encoded
246
+	 * @return string
247
+	 */
248
+	public function base64_url_encode($text_string = '')
249
+	{
250
+		// you give me nothing??? GET OUT !
251
+		if (empty($text_string) || ! $this->_use_base64_encode) {
252
+			return $text_string;
253
+		}
254
+		// encode
255
+		$encoded_string = base64_encode($text_string);
256
+		// remove chars to make encoding more URL friendly
257
+		return strtr($encoded_string, '+/=', '-_,');
258
+	}
259
+
260
+
261
+	/**
262
+	 * decodes  url string that has been encoded with PHP's base64 encoding
263
+	 *
264
+	 * @see http://php.net/manual/en/function.base64-encode.php
265
+	 * @param string $encoded_string the text to be decoded
266
+	 * @return string
267
+	 * @throws RuntimeException
268
+	 */
269
+	public function base64_url_decode($encoded_string = '')
270
+	{
271
+		// replace previously removed characters
272
+		$encoded_string = strtr($encoded_string, '-_,', '+/=');
273
+		// you give me nothing??? GET OUT !
274
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
275
+			return $encoded_string;
276
+		}
277
+		// decode
278
+		$decoded_string = base64_decode($encoded_string);
279
+		if ($decoded_string === false) {
280
+			throw new RuntimeException(
281
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
282
+			);
283
+		}
284
+		return $decoded_string;
285
+	}
286
+
287
+
288
+	/**
289
+	 * encrypts data using PHP's openssl functions
290
+	 *
291
+	 * @param string $text_string the text to be encrypted
292
+	 * @param string $cipher_method
293
+	 * @param string $encryption_key
294
+	 * @return string
295
+	 * @throws RuntimeException
296
+	 */
297
+	protected function openssl_encrypt(
298
+		$text_string = '',
299
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
300
+		$encryption_key = ''
301
+	) {
302
+		// you give me nothing??? GET OUT !
303
+		if (empty($text_string)) {
304
+			return $text_string;
305
+		}
306
+		$this->cipher_method = $this->getCipherMethod($cipher_method);
307
+		// get initialization vector size
308
+		$iv_size = openssl_cipher_iv_length($this->cipher_method);
309
+		// generate initialization vector.
310
+		// The second parameter ("crypto_strong") is passed by reference,
311
+		// and is used to determines if the algorithm used was "cryptographically strong"
312
+		// openssl_random_pseudo_bytes() will toggle it to either true or false
313
+		$iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
314
+		if ($iv === false || $is_strong === false) {
315
+			throw new RuntimeException(
316
+				esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
317
+			);
318
+		}
319
+		// encrypt it
320
+		$encrypted_text = openssl_encrypt(
321
+			$text_string,
322
+			$this->cipher_method,
323
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
324
+			0,
325
+			$iv
326
+		);
327
+		// append the initialization vector
328
+		$encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
329
+		// trim and maybe encode
330
+		return $this->_use_base64_encode
331
+			? trim(base64_encode($encrypted_text))
332
+			: trim($encrypted_text);
333
+	}
334
+
335
+
336
+	/**
337
+	 * Returns a cipher method that has been verified to work.
338
+	 * First checks if the cached cipher has been set already and if so, returns that.
339
+	 * Then tests the incoming default and returns that if it's good.
340
+	 * If not, then it retrieves the previously tested and saved cipher method.
341
+	 * But if that doesn't exist, then calls getAvailableCipherMethod()
342
+	 * to see what is available on the server, and returns the results.
343
+	 *
344
+	 * @param string $cipher_method
345
+	 * @return string
346
+	 * @throws RuntimeException
347
+	 */
348
+	protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
349
+	{
350
+		if ($this->cipher_method !== '') {
351
+			return $this->cipher_method;
352
+		}
353
+		// verify that the default cipher method can produce an initialization vector
354
+		if (openssl_cipher_iv_length($cipher_method) === false) {
355
+			// nope? okay let's get what we found in the past to work
356
+			$cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
357
+			// oops... haven't tested available cipher methods yet
358
+			if ($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
359
+				$cipher_method = $this->getAvailableCipherMethod($cipher_method);
360
+			}
361
+		}
362
+		return $cipher_method;
363
+	}
364
+
365
+
366
+	/**
367
+	 * @param string $cipher_method
368
+	 * @return string
369
+	 * @throws \RuntimeException
370
+	 */
371
+	protected function getAvailableCipherMethod($cipher_method)
372
+	{
373
+		// verify that the incoming cipher method can produce an initialization vector
374
+		if (openssl_cipher_iv_length($cipher_method) === false) {
375
+			// nope? then check the next cipher in the list of available cipher methods
376
+			$cipher_method = next($this->cipher_methods);
377
+			// what? there's no list? then generate that list and cache it,
378
+			if (empty($this->cipher_methods)) {
379
+				$this->cipher_methods = openssl_get_cipher_methods();
380
+				// then grab the first item from the list
381
+				$cipher_method = reset($this->cipher_methods);
382
+			}
383
+			if ($cipher_method === false) {
384
+				throw new RuntimeException(
385
+					esc_html__(
386
+						'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
387
+						'event_espresso'
388
+					)
389
+				);
390
+			}
391
+			// verify that the next cipher method works
392
+			return $this->getAvailableCipherMethod($cipher_method);
393
+		}
394
+		// if we've gotten this far, then we found an available cipher method that works
395
+		// so save that for next time
396
+		update_option(
397
+			EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
398
+			$cipher_method
399
+		);
400
+		return $cipher_method;
401
+	}
402
+
403
+
404
+	/**
405
+	 * decrypts data that has been encrypted with PHP's openssl functions
406
+	 *
407
+	 * @param string $encrypted_text the text to be decrypted
408
+	 * @param string $cipher_method
409
+	 * @param string $encryption_key
410
+	 * @return string
411
+	 * @throws RuntimeException
412
+	 */
413
+	protected function openssl_decrypt(
414
+		$encrypted_text = '',
415
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
416
+		$encryption_key = ''
417
+	) {
418
+		// you give me nothing??? GET OUT !
419
+		if (empty($encrypted_text)) {
420
+			return $encrypted_text;
421
+		}
422
+		// decode
423
+		$encrypted_text       = $this->valid_base_64($encrypted_text)
424
+			? $this->base64_url_decode($encrypted_text)
425
+			: $encrypted_text;
426
+		$encrypted_components = explode(
427
+			EE_Encryption::OPENSSL_IV_DELIMITER,
428
+			$encrypted_text,
429
+			2
430
+		);
431
+		// decrypt it
432
+		$decrypted_text = openssl_decrypt(
433
+			$encrypted_components[0],
434
+			$this->getCipherMethod($cipher_method),
435
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
436
+			0,
437
+			$encrypted_components[1]
438
+		);
439
+		$decrypted_text = trim($decrypted_text);
440
+		return $decrypted_text;
441
+	}
442
+
443
+
444
+	/**
445
+	 * Computes the digest hash value using the specified digest method.
446
+	 * If that digest method fails to produce a valid hash value,
447
+	 * then we'll grab the next digest method and recursively try again until something works.
448
+	 *
449
+	 * @param string $digest_method
450
+	 * @param string $encryption_key
451
+	 * @return string
452
+	 * @throws RuntimeException
453
+	 */
454
+	protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = '')
455
+	{
456
+		$encryption_key    = $encryption_key !== ''
457
+			? $encryption_key
458
+			: $this->get_encryption_key();
459
+		$digest_hash_value = openssl_digest($encryption_key, $digest_method);
460
+		if ($digest_hash_value === false) {
461
+			return $this->getDigestHashValue($this->getDigestMethod());
462
+		}
463
+		return $digest_hash_value;
464
+	}
465
+
466
+
467
+	/**
468
+	 * Returns the NEXT element in the $digest_methods array.
469
+	 * If the $digest_methods array is empty, then we populate it
470
+	 * with the available values returned from openssl_get_md_methods().
471
+	 *
472
+	 * @return string
473
+	 * @throws \RuntimeException
474
+	 */
475
+	protected function getDigestMethod()
476
+	{
477
+		$digest_method = prev($this->digest_methods);
478
+		if (empty($this->digest_methods)) {
479
+			$this->digest_methods = openssl_get_md_methods();
480
+			$digest_method        = end($this->digest_methods);
481
+		}
482
+		if ($digest_method === false) {
483
+			throw new RuntimeException(
484
+				esc_html__(
485
+					'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
486
+					'event_espresso'
487
+				)
488
+			);
489
+		}
490
+		return $digest_method;
491
+	}
492
+
493
+
494
+	/**
495
+	 * encrypts data for acme servers that didn't bother to install PHP mcrypt
496
+	 *
497
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
498
+	 * @param string $text_string the text to be decrypted
499
+	 * @return string
500
+	 */
501
+	protected function acme_encrypt($text_string = '')
502
+	{
503
+		// you give me nothing??? GET OUT !
504
+		if (empty($text_string)) {
505
+			return $text_string;
506
+		}
507
+		$key_bits    = str_split(
508
+			str_pad(
509
+				'',
510
+				strlen($text_string),
511
+				$this->get_encryption_key(),
512
+				STR_PAD_RIGHT
513
+			)
514
+		);
515
+		$string_bits = str_split($text_string);
516
+		foreach ($string_bits as $k => $v) {
517
+			$temp              = ord($v) + ord($key_bits[ $k ]);
518
+			$string_bits[ $k ] = chr($temp > 255 ? ($temp - 256) : $temp);
519
+		}
520
+		$encrypted_text = implode('', $string_bits);
521
+		$encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
522
+		return $this->_use_base64_encode
523
+			? base64_encode($encrypted_text)
524
+			: $encrypted_text;
525
+	}
526
+
527
+
528
+	/**
529
+	 * decrypts data for acme servers that didn't bother to install PHP mcrypt
530
+	 *
531
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
532
+	 * @param string $encrypted_text the text to be decrypted
533
+	 * @return string
534
+	 * @throws RuntimeException
535
+	 */
536
+	protected function acme_decrypt($encrypted_text = '')
537
+	{
538
+		// you give me nothing??? GET OUT !
539
+		if (empty($encrypted_text)) {
540
+			return $encrypted_text;
541
+		}
542
+		// decode the data ?
543
+		$encrypted_text = $this->valid_base_64($encrypted_text)
544
+			? $this->base64_url_decode($encrypted_text)
545
+			: $encrypted_text;
546
+		$encrypted_text = substr($encrypted_text, 0, -4);
547
+		$key_bits       = str_split(
548
+			str_pad(
549
+				'',
550
+				strlen($encrypted_text),
551
+				$this->get_encryption_key(),
552
+				STR_PAD_RIGHT
553
+			)
554
+		);
555
+		$string_bits    = str_split($encrypted_text);
556
+		foreach ($string_bits as $k => $v) {
557
+			$temp              = ord($v) - ord($key_bits[ $k ]);
558
+			$string_bits[ $k ] = chr($temp < 0 ? ($temp + 256) : $temp);
559
+		}
560
+		return implode('', $string_bits);
561
+	}
562
+
563
+
564
+	/**
565
+	 * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
566
+	 * @param $string
567
+	 * @return bool
568
+	 */
569
+	protected function valid_base_64($string)
570
+	{
571
+		// ensure data is a string
572
+		if (! is_string($string) || ! $this->_use_base64_encode) {
573
+			return false;
574
+		}
575
+		$decoded = base64_decode($string, true);
576
+		// Check if there is no invalid character in string
577
+		if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
578
+			return false;
579
+		}
580
+		// Decode the string in strict mode and send the response
581
+		if (! base64_decode($string, true)) {
582
+			return false;
583
+		}
584
+		// Encode and compare it to original one
585
+		return base64_encode($decoded) === $string;
586
+	}
587
+
588
+
589
+	/**
590
+	 * generate random string
591
+	 *
592
+	 * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
593
+	 * @param int $length number of characters for random string
594
+	 * @return string
595
+	 */
596
+	public function generate_random_string($length = 40)
597
+	{
598
+		$iterations    = ceil($length / 40);
599
+		$random_string = '';
600
+		for ($i = 0; $i < $iterations; $i++) {
601
+			$random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
602
+		}
603
+		$random_string = substr($random_string, 0, $length);
604
+		return $random_string;
605
+	}
606 606
 }
Please login to merge, or discard this patch.
core/EE_Error.core.php 2 patches
Indentation   +1134 added lines, -1134 removed lines patch added patch discarded remove patch
@@ -18,245 +18,245 @@  discard block
 block discarded – undo
18 18
  */
19 19
 class EE_Error extends Exception
20 20
 {
21
-    const OPTIONS_KEY_NOTICES = 'ee_notices';
22
-
23
-    /**
24
-     *    stores details for all exception
25
-     *
26
-     * @var array
27
-     */
28
-    private static $_all_exceptions = [];
29
-
30
-    /**
31
-     *    tracks number of errors
32
-     *
33
-     * @var int
34
-     */
35
-    private static $_error_count = 0;
36
-
37
-    /**
38
-     * @var array $_espresso_notices
39
-     */
40
-    private static $_espresso_notices = ['success' => false, 'errors' => false, 'attention' => false];
41
-
42
-
43
-    /**
44
-     * @override default exception handling
45
-     * @param string         $message
46
-     * @param int            $code
47
-     * @param Exception|null $previous
48
-     */
49
-    public function __construct($message, $code = 0, Exception $previous = null)
50
-    {
51
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
52
-            parent::__construct($message, $code);
53
-        } else {
54
-            parent::__construct($message, $code, $previous);
55
-        }
56
-    }
57
-
58
-
59
-    /**
60
-     *    error_handler
61
-     *
62
-     * @param int  $code
63
-     * @param string $message
64
-     * @param string $file
65
-     * @param int|string $line
66
-     * @return void
67
-     */
68
-    public static function error_handler(int $code, string $message, string $file, $line)
69
-    {
70
-        $type    = EE_Error::error_type($code);
71
-        $site    = site_url();
72
-        $to      = strpos($site, 'eventespresso.com')
73
-            ? '[email protected]'
74
-            : get_option('admin_email');
75
-        $subject = "$type $message in " . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
76
-        $msg     = EE_Error::_format_error($type, $message, $file, $line);
77
-        if (function_exists('wp_mail')) {
78
-            add_filter('wp_mail_content_type', ['EE_Error', 'set_content_type']);
79
-            wp_mail($to, $subject, $msg);
80
-        }
81
-        echo '<div id="message" class="espresso-notices error"><p>';
82
-        echo wp_kses($type . ': ' . $message . '<br />' . $file . ' line ' . $line, AllowedTags::getWithFormTags());
83
-        echo '<br /></p></div>';
84
-    }
85
-
86
-
87
-    /**
88
-     * error_type
89
-     * http://www.php.net/manual/en/errorfunc.constants.php#109430
90
-     *
91
-     * @param int $code
92
-     * @return string
93
-     */
94
-    public static function error_type(int $code): string
95
-    {
96
-        switch ($code) {
97
-            case E_ERROR: // 1 //
98
-                return 'E_ERROR';
99
-            case E_WARNING: // 2 //
100
-                return 'E_WARNING';
101
-            case E_PARSE: // 4 //
102
-                return 'E_PARSE';
103
-            case E_NOTICE: // 8 //
104
-                return 'E_NOTICE';
105
-            case E_CORE_ERROR: // 16 //
106
-                return 'E_CORE_ERROR';
107
-            case E_CORE_WARNING: // 32 //
108
-                return 'E_CORE_WARNING';
109
-            case E_COMPILE_ERROR: // 64 //
110
-                return 'E_COMPILE_ERROR';
111
-            case E_COMPILE_WARNING: // 128 //
112
-                return 'E_COMPILE_WARNING';
113
-            case E_USER_ERROR: // 256 //
114
-                return 'E_USER_ERROR';
115
-            case E_USER_WARNING: // 512 //
116
-                return 'E_USER_WARNING';
117
-            case E_USER_NOTICE: // 1024 //
118
-                return 'E_USER_NOTICE';
119
-            case E_STRICT: // 2048 //
120
-                return 'E_STRICT';
121
-            case E_RECOVERABLE_ERROR: // 4096 //
122
-                return 'E_RECOVERABLE_ERROR';
123
-            case E_DEPRECATED: // 8192 //
124
-                return 'E_DEPRECATED';
125
-            case E_USER_DEPRECATED: // 16384 //
126
-                return 'E_USER_DEPRECATED';
127
-            case E_ALL: // 16384 //
128
-                return 'E_ALL';
129
-        }
130
-        return '';
131
-    }
132
-
133
-
134
-    /**
135
-     *    fatal_error_handler
136
-     *
137
-     * @return void
138
-     */
139
-    public static function fatal_error_handler()
140
-    {
141
-        $last_error = error_get_last();
142
-        if ($last_error['type'] === E_ERROR) {
143
-            EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
144
-        }
145
-    }
146
-
147
-
148
-    /**
149
-     * _format_error
150
-     *
151
-     * @param $code
152
-     * @param $message
153
-     * @param $file
154
-     * @param $line
155
-     * @return string
156
-     */
157
-    private static function _format_error($code, $message, $file, $line): string
158
-    {
159
-        $html =
160
-            "<table><thead><th>Item</th><th>Details</th></thead><tbody>";
161
-        $html .= "<tr><td><b>Code</b></td><td>$code</td></tr>";
162
-        $html .= "<tr><td><b>Error</b></td><td>$message</td></tr>";
163
-        $html .= "<tr><td><b>File</b></td><td>$file</td></tr>";
164
-        $html .= "<tr><td><b>Line</b></td><td>$line</td></tr>";
165
-        $html .= '</tbody></table>';
166
-        return $html;
167
-    }
168
-
169
-
170
-    /**
171
-     * set_content_type
172
-     *
173
-     * @param $content_type
174
-     * @return string
175
-     */
176
-    public static function set_content_type($content_type): string
177
-    {
178
-        return 'text/html';
179
-    }
180
-
181
-
182
-    /**
183
-     * @return void
184
-     * @throws EE_Error
185
-     * @throws ReflectionException
186
-     */
187
-    public function get_error()
188
-    {
189
-        if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
190
-            throw $this;
191
-        }
192
-        // get separate user and developer messages if they exist
193
-        $msg      = explode('||', $this->getMessage());
194
-        $user_msg = $msg[0];
195
-        $dev_msg  = $msg[1] ?? $msg[0];
196
-        $msg      = WP_DEBUG ? $dev_msg : $user_msg;
197
-        // add details to _all_exceptions array
198
-        $x_time                                     = time();
199
-        self::$_all_exceptions[ $x_time ]['name']   = get_class($this);
200
-        self::$_all_exceptions[ $x_time ]['file']   = $this->getFile();
201
-        self::$_all_exceptions[ $x_time ]['line']   = $this->getLine();
202
-        self::$_all_exceptions[ $x_time ]['msg']    = $msg;
203
-        self::$_all_exceptions[ $x_time ]['code']   = $this->getCode();
204
-        self::$_all_exceptions[ $x_time ]['trace']  = $this->getTrace();
205
-        self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
206
-        self::$_error_count++;
207
-        // add_action( 'shutdown', array( $this, 'display_errors' ));
208
-        $this->display_errors();
209
-    }
210
-
211
-
212
-    /**
213
-     * @param bool   $check_stored
214
-     * @param string $type_to_check
215
-     * @return bool
216
-     * @throws InvalidInterfaceException
217
-     * @throws InvalidArgumentException
218
-     * @throws InvalidDataTypeException
219
-     */
220
-    public static function has_error(bool $check_stored = false, string $type_to_check = 'errors'): bool
221
-    {
222
-        $has_error = isset(self::$_espresso_notices[ $type_to_check ])
223
-                     && ! empty(self::$_espresso_notices[ $type_to_check ]);
224
-        if ($check_stored && ! $has_error) {
225
-            $notices = EE_Error::getStoredNotices();
226
-            foreach ($notices as $type => $notice) {
227
-                if ($type === $type_to_check && $notice) {
228
-                    return true;
229
-                }
230
-            }
231
-        }
232
-        return $has_error;
233
-    }
234
-
235
-
236
-    /**
237
-     * @echo string
238
-     * @throws ReflectionException
239
-     */
240
-    public function display_errors()
241
-    {
242
-        $trace_details = '';
243
-        $output = '
21
+	const OPTIONS_KEY_NOTICES = 'ee_notices';
22
+
23
+	/**
24
+	 *    stores details for all exception
25
+	 *
26
+	 * @var array
27
+	 */
28
+	private static $_all_exceptions = [];
29
+
30
+	/**
31
+	 *    tracks number of errors
32
+	 *
33
+	 * @var int
34
+	 */
35
+	private static $_error_count = 0;
36
+
37
+	/**
38
+	 * @var array $_espresso_notices
39
+	 */
40
+	private static $_espresso_notices = ['success' => false, 'errors' => false, 'attention' => false];
41
+
42
+
43
+	/**
44
+	 * @override default exception handling
45
+	 * @param string         $message
46
+	 * @param int            $code
47
+	 * @param Exception|null $previous
48
+	 */
49
+	public function __construct($message, $code = 0, Exception $previous = null)
50
+	{
51
+		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
52
+			parent::__construct($message, $code);
53
+		} else {
54
+			parent::__construct($message, $code, $previous);
55
+		}
56
+	}
57
+
58
+
59
+	/**
60
+	 *    error_handler
61
+	 *
62
+	 * @param int  $code
63
+	 * @param string $message
64
+	 * @param string $file
65
+	 * @param int|string $line
66
+	 * @return void
67
+	 */
68
+	public static function error_handler(int $code, string $message, string $file, $line)
69
+	{
70
+		$type    = EE_Error::error_type($code);
71
+		$site    = site_url();
72
+		$to      = strpos($site, 'eventespresso.com')
73
+			? '[email protected]'
74
+			: get_option('admin_email');
75
+		$subject = "$type $message in " . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
76
+		$msg     = EE_Error::_format_error($type, $message, $file, $line);
77
+		if (function_exists('wp_mail')) {
78
+			add_filter('wp_mail_content_type', ['EE_Error', 'set_content_type']);
79
+			wp_mail($to, $subject, $msg);
80
+		}
81
+		echo '<div id="message" class="espresso-notices error"><p>';
82
+		echo wp_kses($type . ': ' . $message . '<br />' . $file . ' line ' . $line, AllowedTags::getWithFormTags());
83
+		echo '<br /></p></div>';
84
+	}
85
+
86
+
87
+	/**
88
+	 * error_type
89
+	 * http://www.php.net/manual/en/errorfunc.constants.php#109430
90
+	 *
91
+	 * @param int $code
92
+	 * @return string
93
+	 */
94
+	public static function error_type(int $code): string
95
+	{
96
+		switch ($code) {
97
+			case E_ERROR: // 1 //
98
+				return 'E_ERROR';
99
+			case E_WARNING: // 2 //
100
+				return 'E_WARNING';
101
+			case E_PARSE: // 4 //
102
+				return 'E_PARSE';
103
+			case E_NOTICE: // 8 //
104
+				return 'E_NOTICE';
105
+			case E_CORE_ERROR: // 16 //
106
+				return 'E_CORE_ERROR';
107
+			case E_CORE_WARNING: // 32 //
108
+				return 'E_CORE_WARNING';
109
+			case E_COMPILE_ERROR: // 64 //
110
+				return 'E_COMPILE_ERROR';
111
+			case E_COMPILE_WARNING: // 128 //
112
+				return 'E_COMPILE_WARNING';
113
+			case E_USER_ERROR: // 256 //
114
+				return 'E_USER_ERROR';
115
+			case E_USER_WARNING: // 512 //
116
+				return 'E_USER_WARNING';
117
+			case E_USER_NOTICE: // 1024 //
118
+				return 'E_USER_NOTICE';
119
+			case E_STRICT: // 2048 //
120
+				return 'E_STRICT';
121
+			case E_RECOVERABLE_ERROR: // 4096 //
122
+				return 'E_RECOVERABLE_ERROR';
123
+			case E_DEPRECATED: // 8192 //
124
+				return 'E_DEPRECATED';
125
+			case E_USER_DEPRECATED: // 16384 //
126
+				return 'E_USER_DEPRECATED';
127
+			case E_ALL: // 16384 //
128
+				return 'E_ALL';
129
+		}
130
+		return '';
131
+	}
132
+
133
+
134
+	/**
135
+	 *    fatal_error_handler
136
+	 *
137
+	 * @return void
138
+	 */
139
+	public static function fatal_error_handler()
140
+	{
141
+		$last_error = error_get_last();
142
+		if ($last_error['type'] === E_ERROR) {
143
+			EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
144
+		}
145
+	}
146
+
147
+
148
+	/**
149
+	 * _format_error
150
+	 *
151
+	 * @param $code
152
+	 * @param $message
153
+	 * @param $file
154
+	 * @param $line
155
+	 * @return string
156
+	 */
157
+	private static function _format_error($code, $message, $file, $line): string
158
+	{
159
+		$html =
160
+			"<table><thead><th>Item</th><th>Details</th></thead><tbody>";
161
+		$html .= "<tr><td><b>Code</b></td><td>$code</td></tr>";
162
+		$html .= "<tr><td><b>Error</b></td><td>$message</td></tr>";
163
+		$html .= "<tr><td><b>File</b></td><td>$file</td></tr>";
164
+		$html .= "<tr><td><b>Line</b></td><td>$line</td></tr>";
165
+		$html .= '</tbody></table>';
166
+		return $html;
167
+	}
168
+
169
+
170
+	/**
171
+	 * set_content_type
172
+	 *
173
+	 * @param $content_type
174
+	 * @return string
175
+	 */
176
+	public static function set_content_type($content_type): string
177
+	{
178
+		return 'text/html';
179
+	}
180
+
181
+
182
+	/**
183
+	 * @return void
184
+	 * @throws EE_Error
185
+	 * @throws ReflectionException
186
+	 */
187
+	public function get_error()
188
+	{
189
+		if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
190
+			throw $this;
191
+		}
192
+		// get separate user and developer messages if they exist
193
+		$msg      = explode('||', $this->getMessage());
194
+		$user_msg = $msg[0];
195
+		$dev_msg  = $msg[1] ?? $msg[0];
196
+		$msg      = WP_DEBUG ? $dev_msg : $user_msg;
197
+		// add details to _all_exceptions array
198
+		$x_time                                     = time();
199
+		self::$_all_exceptions[ $x_time ]['name']   = get_class($this);
200
+		self::$_all_exceptions[ $x_time ]['file']   = $this->getFile();
201
+		self::$_all_exceptions[ $x_time ]['line']   = $this->getLine();
202
+		self::$_all_exceptions[ $x_time ]['msg']    = $msg;
203
+		self::$_all_exceptions[ $x_time ]['code']   = $this->getCode();
204
+		self::$_all_exceptions[ $x_time ]['trace']  = $this->getTrace();
205
+		self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
206
+		self::$_error_count++;
207
+		// add_action( 'shutdown', array( $this, 'display_errors' ));
208
+		$this->display_errors();
209
+	}
210
+
211
+
212
+	/**
213
+	 * @param bool   $check_stored
214
+	 * @param string $type_to_check
215
+	 * @return bool
216
+	 * @throws InvalidInterfaceException
217
+	 * @throws InvalidArgumentException
218
+	 * @throws InvalidDataTypeException
219
+	 */
220
+	public static function has_error(bool $check_stored = false, string $type_to_check = 'errors'): bool
221
+	{
222
+		$has_error = isset(self::$_espresso_notices[ $type_to_check ])
223
+					 && ! empty(self::$_espresso_notices[ $type_to_check ]);
224
+		if ($check_stored && ! $has_error) {
225
+			$notices = EE_Error::getStoredNotices();
226
+			foreach ($notices as $type => $notice) {
227
+				if ($type === $type_to_check && $notice) {
228
+					return true;
229
+				}
230
+			}
231
+		}
232
+		return $has_error;
233
+	}
234
+
235
+
236
+	/**
237
+	 * @echo string
238
+	 * @throws ReflectionException
239
+	 */
240
+	public function display_errors()
241
+	{
242
+		$trace_details = '';
243
+		$output = '
244 244
         <div id="ee-error-message" class="error">';
245
-        if (! WP_DEBUG) {
246
-            $output .= '
245
+		if (! WP_DEBUG) {
246
+			$output .= '
247 247
 	        <p>';
248
-        }
249
-        // cycle thru errors
250
-        foreach (self::$_all_exceptions as $time => $ex) {
251
-            $error_code = '';
252
-            // process trace info
253
-            if (empty($ex['trace'])) {
254
-                $trace_details .= esc_html__(
255
-                    'Sorry, but no trace information was available for this exception.',
256
-                    'event_espresso'
257
-                );
258
-            } else {
259
-                $trace_details .= '
248
+		}
249
+		// cycle thru errors
250
+		foreach (self::$_all_exceptions as $time => $ex) {
251
+			$error_code = '';
252
+			// process trace info
253
+			if (empty($ex['trace'])) {
254
+				$trace_details .= esc_html__(
255
+					'Sorry, but no trace information was available for this exception.',
256
+					'event_espresso'
257
+				);
258
+			} else {
259
+				$trace_details .= '
260 260
 			<div id="ee-trace-details">
261 261
 			<table>
262 262
 				<tr>
@@ -266,43 +266,43 @@  discard block
 block discarded – undo
266 266
 					<th scope="col">Class</th>
267 267
 					<th scope="col">Method( arguments )</th>
268 268
 				</tr>';
269
-                $last_on_stack = count($ex['trace']) - 1;
270
-                // reverse array so that stack is in proper chronological order
271
-                $sorted_trace = array_reverse($ex['trace']);
272
-                foreach ($sorted_trace as $number => $trace) {
273
-                    $file     = $trace['file'] ?? '';
274
-                    $class    = $trace['class'] ?? '';
275
-                    $type     = $trace['type'] ?? '';
276
-                    $function = $trace['function'] ?? '';
277
-                    $args     = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
278
-                    $line     = $trace['line'] ?? '';
279
-                    $zebra    = ($number % 2) ? ' odd' : '';
280
-                    if (empty($file) && ! empty($class)) {
281
-                        $a    = new ReflectionClass($class);
282
-                        $file = $a->getFileName();
283
-                        if (empty($line) && ! empty($function)) {
284
-                            try {
285
-                                // if $function is a closure, this throws an exception
286
-                                $b    = new ReflectionMethod($class, $function);
287
-                                $line = $b->getStartLine();
288
-                            } catch (Exception $closure_exception) {
289
-                                $line = 'unknown';
290
-                            }
291
-                        }
292
-                    }
293
-                    if ($number === $last_on_stack) {
294
-                        $file       = $ex['file'] !== '' ? $ex['file'] : $file;
295
-                        $line       = $ex['line'] !== '' ? $ex['line'] : $line;
296
-                        $error_code = self::generate_error_code($file, $trace['function'], $line);
297
-                    }
298
-                    $number_display   = ! empty($number) ? $number : '&nbsp;';
299
-                    $line_display     = ! empty($line) ? $line : '&nbsp;';
300
-                    $file_display     = ! empty($file) ? $file : '&nbsp;';
301
-                    $class_display    = ! empty($class) ? $class : '&nbsp;';
302
-                    $type_display     = ! empty($type) ? $type : '&nbsp;';
303
-                    $function_display = ! empty($function) ? $function : '&nbsp;';
304
-                    $args_display     = ! empty($args) ? '( ' . $args . ' )' : '';
305
-                    $trace_details    .= '
269
+				$last_on_stack = count($ex['trace']) - 1;
270
+				// reverse array so that stack is in proper chronological order
271
+				$sorted_trace = array_reverse($ex['trace']);
272
+				foreach ($sorted_trace as $number => $trace) {
273
+					$file     = $trace['file'] ?? '';
274
+					$class    = $trace['class'] ?? '';
275
+					$type     = $trace['type'] ?? '';
276
+					$function = $trace['function'] ?? '';
277
+					$args     = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
278
+					$line     = $trace['line'] ?? '';
279
+					$zebra    = ($number % 2) ? ' odd' : '';
280
+					if (empty($file) && ! empty($class)) {
281
+						$a    = new ReflectionClass($class);
282
+						$file = $a->getFileName();
283
+						if (empty($line) && ! empty($function)) {
284
+							try {
285
+								// if $function is a closure, this throws an exception
286
+								$b    = new ReflectionMethod($class, $function);
287
+								$line = $b->getStartLine();
288
+							} catch (Exception $closure_exception) {
289
+								$line = 'unknown';
290
+							}
291
+						}
292
+					}
293
+					if ($number === $last_on_stack) {
294
+						$file       = $ex['file'] !== '' ? $ex['file'] : $file;
295
+						$line       = $ex['line'] !== '' ? $ex['line'] : $line;
296
+						$error_code = self::generate_error_code($file, $trace['function'], $line);
297
+					}
298
+					$number_display   = ! empty($number) ? $number : '&nbsp;';
299
+					$line_display     = ! empty($line) ? $line : '&nbsp;';
300
+					$file_display     = ! empty($file) ? $file : '&nbsp;';
301
+					$class_display    = ! empty($class) ? $class : '&nbsp;';
302
+					$type_display     = ! empty($type) ? $type : '&nbsp;';
303
+					$function_display = ! empty($function) ? $function : '&nbsp;';
304
+					$args_display     = ! empty($args) ? '( ' . $args . ' )' : '';
305
+					$trace_details    .= '
306 306
 					<tr>
307 307
 						<td class="' . $zebra . '">' . $number_display . '</td>
308 308
 						<td class="' . $zebra . '">' . $line_display . '</td>
@@ -310,645 +310,645 @@  discard block
 block discarded – undo
310 310
 						<td class="' . $zebra . '">' . $class_display . '</td>
311 311
 						<td class="' . $zebra . '">' . $type_display . $function_display . $args_display . '</td>
312 312
 					</tr>';
313
-                }
314
-                $trace_details .= '
313
+				}
314
+				$trace_details .= '
315 315
 			 </table>
316 316
 			</div>';
317
-            }
318
-            $ex['code'] = $ex['code'] ?: $error_code;
319
-            // add generic non-identifying messages for non-privileged users
320
-            if (! WP_DEBUG) {
321
-                $output .= '<span class="ee-error-user-msg-spn">'
322
-                           . trim($ex['msg'])
323
-                           . '</span> &nbsp; <sup>'
324
-                           . $ex['code']
325
-                           . '</sup><br />';
326
-            } else {
327
-                // or helpful developer messages if debugging is on
328
-                $output .= '
317
+			}
318
+			$ex['code'] = $ex['code'] ?: $error_code;
319
+			// add generic non-identifying messages for non-privileged users
320
+			if (! WP_DEBUG) {
321
+				$output .= '<span class="ee-error-user-msg-spn">'
322
+						   . trim($ex['msg'])
323
+						   . '</span> &nbsp; <sup>'
324
+						   . $ex['code']
325
+						   . '</sup><br />';
326
+			} else {
327
+				// or helpful developer messages if debugging is on
328
+				$output .= '
329 329
 		<div class="ee-error-dev-msg-dv">
330 330
 			<p class="ee-error-dev-msg-pg">
331 331
 				<strong class="ee-error-dev-msg-str">An '
332
-                           . $ex['name']
333
-                           . ' exception was thrown!</strong>  &nbsp; <span>code: '
334
-                           . $ex['code']
335
-                           . '</span><br />
332
+						   . $ex['name']
333
+						   . ' exception was thrown!</strong>  &nbsp; <span>code: '
334
+						   . $ex['code']
335
+						   . '</span><br />
336 336
 				<span class="big-text">"'
337
-                           . trim($ex['msg'])
338
-                           . '"</span><br/>
337
+						   . trim($ex['msg'])
338
+						   . '"</span><br/>
339 339
 				<a id="display-ee-error-trace-'
340
-                           . self::$_error_count
341
-                           . $time
342
-                           . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
343
-                           . self::$_error_count
344
-                           . $time
345
-                           . '">
340
+						   . self::$_error_count
341
+						   . $time
342
+						   . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
343
+						   . self::$_error_count
344
+						   . $time
345
+						   . '">
346 346
 					'
347
-                           . esc_html__('click to view backtrace and class/method details', 'event_espresso')
348
-                           . '
347
+						   . esc_html__('click to view backtrace and class/method details', 'event_espresso')
348
+						   . '
349 349
 				</a><br />
350 350
 				<span class="small-text lt-grey-text">'
351
-                           . $ex['file']
352
-                           . ' &nbsp; ( line no: '
353
-                           . $ex['line']
354
-                           . ' )</span>
351
+						   . $ex['file']
352
+						   . ' &nbsp; ( line no: '
353
+						   . $ex['line']
354
+						   . ' )</span>
355 355
 			</p>
356 356
 			<div id="ee-error-trace-'
357
-                           . self::$_error_count
358
-                           . $time
359
-                           . '-dv" class="ee-error-trace-dv" style="display: none;">
357
+						   . self::$_error_count
358
+						   . $time
359
+						   . '-dv" class="ee-error-trace-dv" style="display: none;">
360 360
 				'
361
-                           . $trace_details;
362
-                if (! empty($class)) {
363
-                    $output .= '
361
+						   . $trace_details;
362
+				if (! empty($class)) {
363
+					$output .= '
364 364
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
365 365
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
366 366
 						<h3>Class Details</h3>';
367
-                    $a      = new ReflectionClass($class);
368
-                    $output .= '
367
+					$a      = new ReflectionClass($class);
368
+					$output .= '
369 369
 						<pre>' . $a . '</pre>
370 370
 					</div>
371 371
 				</div>';
372
-                }
373
-                $output .= '
372
+				}
373
+				$output .= '
374 374
 			</div>
375 375
 		</div>
376 376
 		<br />';
377
-            }
378
-            $this->write_to_error_log($time, $ex);
379
-        }
380
-        // remove last linebreak
381
-        $output = substr($output, 0, -6);
382
-        if (! WP_DEBUG) {
383
-            $output .= '
377
+			}
378
+			$this->write_to_error_log($time, $ex);
379
+		}
380
+		// remove last linebreak
381
+		$output = substr($output, 0, -6);
382
+		if (! WP_DEBUG) {
383
+			$output .= '
384 384
 	        </p>';
385
-        }
386
-        $output .= '
385
+		}
386
+		$output .= '
387 387
         </div>';
388
-        $output .= self::_print_scripts(true);
389
-        if (defined('DOING_AJAX')) {
390
-            echo wp_json_encode(['error' => $output]);
391
-            exit();
392
-        }
393
-        echo wp_kses($output, AllowedTags::getWithFormTags());
394
-        die();
395
-    }
396
-
397
-
398
-    /**
399
-     *    generate string from exception trace args
400
-     *
401
-     * @param array $arguments
402
-     * @param bool  $array
403
-     * @return string
404
-     */
405
-    private function _convert_args_to_string(array $arguments = [], bool $array = false): string
406
-    {
407
-        $arg_string = '';
408
-        if (! empty($arguments)) {
409
-            $args = [];
410
-            foreach ($arguments as $arg) {
411
-                if (! empty($arg)) {
412
-                    if (is_string($arg)) {
413
-                        $args[] = " '" . $arg . "'";
414
-                    } elseif (is_array($arg)) {
415
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
416
-                    } elseif (is_bool($arg)) {
417
-                        $args[] = $arg ? ' TRUE' : ' FALSE';
418
-                    } elseif (is_object($arg)) {
419
-                        $args[] = ' OBJECT ' . get_class($arg);
420
-                    } elseif (is_resource($arg)) {
421
-                        $args[] = get_resource_type($arg);
422
-                    } else {
423
-                        $args[] = $arg;
424
-                    }
425
-                } else {
426
-                    $args[] = ' NULL';
427
-                }
428
-            }
429
-            $arg_string = implode(', ', $args);
430
-        }
431
-        if ($array) {
432
-            $arg_string .= ' )';
433
-        }
434
-        return $arg_string;
435
-    }
436
-
437
-
438
-    /**
439
-     *    add error message
440
-     *
441
-     * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
442
-     *                            separate messages for user || dev
443
-     * @param string $file        the file that the error occurred in - just use __FILE__
444
-     * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
445
-     * @param int|string $line        the line number where the error occurred - just use __LINE__
446
-     * @return        void
447
-     */
448
-    public static function add_error(string $msg, string $file, string $func, $line)
449
-    {
450
-        self::_add_notice('errors', $msg, $file, $func, $line);
451
-        self::$_error_count++;
452
-    }
453
-
454
-
455
-    /**
456
-     * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
457
-     * adds an error
458
-     *
459
-     * @param string $msg
460
-     * @param string $file
461
-     * @param string $func
462
-     * @param int|string $line
463
-     * @throws EE_Error
464
-     */
465
-    public static function throw_exception_if_debugging(
466
-        string $msg = '',
467
-        string $file = '',
468
-        string $func = '',
469
-        $line = ''
470
-    ) {
471
-        if (WP_DEBUG) {
472
-            throw new EE_Error($msg);
473
-        }
474
-        EE_Error::add_error($msg, $file, $func, $line);
475
-    }
476
-
477
-
478
-    /**
479
-     *    add success message
480
-     *
481
-     * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
482
-     *                            separate messages for user || dev
483
-     * @param string $file        the file that the error occurred in - just use __FILE__
484
-     * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
485
-     * @param int|string $line        the line number where the error occurred - just use __LINE__
486
-     * @return void
487
-     */
488
-    public static function add_success(string $msg = '', string $file = '', string $func = '', $line = '')
489
-    {
490
-        self::_add_notice('success', $msg, $file, $func, $line);
491
-    }
492
-
493
-
494
-    /**
495
-     *    add attention message
496
-     *
497
-     * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
498
-     *                            separate messages for user || dev
499
-     * @param string $file        the file that the error occurred in - just use __FILE__
500
-     * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
501
-     * @param int|string $line        the line number where the error occurred - just use __LINE__
502
-     * @return        void
503
-     */
504
-    public static function add_attention(string $msg = '', string $file = '', string $func = '', $line = '')
505
-    {
506
-        self::_add_notice('attention', $msg, $file, $func, $line);
507
-    }
508
-
509
-
510
-    /**
511
-     * @param string $type whether the message is for a success or error notification
512
-     * @param string $msg  the message to display to users or developers
513
-     *                     - adding a double pipe || (OR) creates separate messages for user || dev
514
-     * @param string $file the file that the error occurred in - just use __FILE__
515
-     * @param string $func the function/method that the error occurred in - just use __FUNCTION__
516
-     * @param int|string $line the line number where the error occurred - just use __LINE__
517
-     * @return void
518
-     */
519
-    private static function _add_notice(
520
-        string $type = 'success',
521
-        string $msg = '',
522
-        string $file = '',
523
-        string $func = '',
524
-        $line = ''
525
-    ) {
526
-        if (empty($msg)) {
527
-            EE_Error::doing_it_wrong(
528
-                'EE_Error::add_' . $type . '()',
529
-                sprintf(
530
-                    esc_html__(
531
-                        'Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
532
-                        'event_espresso'
533
-                    ),
534
-                    $type,
535
-                    $file,
536
-                    $line
537
-                ),
538
-                EVENT_ESPRESSO_VERSION
539
-            );
540
-        }
541
-        if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
542
-            EE_Error::doing_it_wrong(
543
-                'EE_Error::add_error()',
544
-                esc_html__(
545
-                    'You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
546
-                    'event_espresso'
547
-                ),
548
-                EVENT_ESPRESSO_VERSION
549
-            );
550
-        }
551
-        // get separate user and developer messages if they exist
552
-        $msg      = explode('||', $msg);
553
-        $user_msg = $msg[0];
554
-        $dev_msg  = $msg[1] ?? $msg[0];
555
-        /**
556
-         * Do an action so other code can be triggered when a notice is created
557
-         *
558
-         * @param string $type     can be 'errors', 'attention', or 'success'
559
-         * @param string $user_msg message displayed to user when WP_DEBUG is off
560
-         * @param string $user_msg message displayed to user when WP_DEBUG is on
561
-         * @param string $file     file where error was generated
562
-         * @param string $func     function where error was generated
563
-         * @param int|string $line     line where error was generated
564
-         */
565
-        do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
566
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
567
-        // add notice if message exists
568
-        if (! empty($msg)) {
569
-            // get error code
570
-            $notice_code = EE_Error::generate_error_code($file, $func, $line);
571
-            if (WP_DEBUG && $type === 'errors') {
572
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
573
-            }
574
-
575
-            if (! is_array(self::$_espresso_notices[ $type ]) || ! array_key_exists($type, self::$_espresso_notices)) {
576
-                self::$_espresso_notices[ $type ] = [];
577
-            }
578
-
579
-            // add notice. Index by code if it's not blank
580
-            if ($notice_code) {
581
-                self::$_espresso_notices[ $type ][ $notice_code ] = $msg;
582
-            } else {
583
-                self::$_espresso_notices[ $type ][] = $msg;
584
-            }
585
-            add_action('wp_footer', ['EE_Error', 'enqueue_error_scripts'], 1);
586
-        }
587
-    }
588
-
589
-
590
-    /**
591
-     * in some case it may be necessary to overwrite the existing success messages
592
-     *
593
-     * @return        void
594
-     */
595
-    public static function overwrite_success()
596
-    {
597
-        self::$_espresso_notices['success'] = [];
598
-    }
599
-
600
-
601
-    /**
602
-     * in some case it may be necessary to overwrite the existing attention messages
603
-     *
604
-     * @return void
605
-     */
606
-    public static function overwrite_attention()
607
-    {
608
-        self::$_espresso_notices['attention'] = [];
609
-    }
610
-
611
-
612
-    /**
613
-     * in some case it may be necessary to overwrite the existing error messages
614
-     *
615
-     * @return void
616
-     */
617
-    public static function overwrite_errors()
618
-    {
619
-        self::$_espresso_notices['errors'] = [];
620
-    }
621
-
622
-
623
-    /**
624
-     * @return void
625
-     */
626
-    public static function reset_notices()
627
-    {
628
-        self::$_espresso_notices['success']   = [];
629
-        self::$_espresso_notices['attention'] = [];
630
-        self::$_espresso_notices['errors']    = [];
631
-    }
632
-
633
-
634
-    /**
635
-     * @return int
636
-     */
637
-    public static function has_notices(): int
638
-    {
639
-        $has_notices = 0;
640
-        // check for success messages
641
-        $has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
642
-            ? 3
643
-            : $has_notices;
644
-        // check for attention messages
645
-        $has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
646
-            ? 2
647
-            : $has_notices;
648
-        // check for error messages
649
-        return self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
650
-            ? 1
651
-            : $has_notices;
652
-    }
653
-
654
-
655
-    /**
656
-     * This simply returns non formatted error notices as they were sent into the EE_Error object.
657
-     *
658
-     * @return array
659
-     * @since 4.9.0
660
-     */
661
-    public static function get_vanilla_notices(): array
662
-    {
663
-        return [
664
-            'success'   => self::$_espresso_notices['success'] ?? [],
665
-            'attention' => self::$_espresso_notices['attention'] ?? [],
666
-            'errors'    => self::$_espresso_notices['errors'] ?? [],
667
-        ];
668
-    }
669
-
670
-
671
-    /**
672
-     * @return array
673
-     * @throws InvalidArgumentException
674
-     * @throws InvalidDataTypeException
675
-     * @throws InvalidInterfaceException
676
-     */
677
-    public static function getStoredNotices(): array
678
-    {
679
-        if ($user_id = get_current_user_id()) {
680
-            // get notices for logged in user
681
-            $notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
682
-            return is_array($notices) ? $notices : [];
683
-        }
684
-        if (EE_Session::isLoadedAndActive()) {
685
-            // get notices for user currently engaged in a session
686
-            $session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
687
-            return is_array($session_data) ? $session_data : [];
688
-        }
689
-        // get global notices and hope they apply to the current site visitor
690
-        $notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, []);
691
-        return is_array($notices) ? $notices : [];
692
-    }
693
-
694
-
695
-    /**
696
-     * @param array $notices
697
-     * @return bool
698
-     * @throws InvalidArgumentException
699
-     * @throws InvalidDataTypeException
700
-     * @throws InvalidInterfaceException
701
-     */
702
-    public static function storeNotices(array $notices): bool
703
-    {
704
-        if ($user_id = get_current_user_id()) {
705
-            // store notices for logged in user
706
-            return (bool) update_user_option(
707
-                $user_id,
708
-                EE_Error::OPTIONS_KEY_NOTICES,
709
-                $notices
710
-            );
711
-        }
712
-        if (EE_Session::isLoadedAndActive()) {
713
-            // store notices for user currently engaged in a session
714
-            return EE_Session::instance()->set_session_data(
715
-                [EE_Error::OPTIONS_KEY_NOTICES => $notices]
716
-            );
717
-        }
718
-        // store global notices and hope they apply to the same site visitor on the next request
719
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
720
-    }
721
-
722
-
723
-    /**
724
-     * @return bool
725
-     * @throws InvalidArgumentException
726
-     * @throws InvalidDataTypeException
727
-     * @throws InvalidInterfaceException
728
-     */
729
-    public static function clearNotices(): bool
730
-    {
731
-        if ($user_id = get_current_user_id()) {
732
-            // clear notices for logged in user
733
-            return (bool) update_user_option(
734
-                $user_id,
735
-                EE_Error::OPTIONS_KEY_NOTICES,
736
-                []
737
-            );
738
-        }
739
-        if (EE_Session::isLoadedAndActive()) {
740
-            // clear notices for user currently engaged in a session
741
-            return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
742
-        }
743
-        // clear global notices and hope none belonged to some for some other site visitor
744
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, []);
745
-    }
746
-
747
-
748
-    /**
749
-     * saves notices to the db for retrieval on next request
750
-     *
751
-     * @return void
752
-     * @throws InvalidArgumentException
753
-     * @throws InvalidDataTypeException
754
-     * @throws InvalidInterfaceException
755
-     */
756
-    public static function stashNoticesBeforeRedirect()
757
-    {
758
-        EE_Error::get_notices(false, true);
759
-    }
760
-
761
-
762
-    /**
763
-     * compile all error or success messages into one string
764
-     *
765
-     * @param boolean $format_output            whether or not to format the messages for display in the WP admin
766
-     * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
767
-     *                                          - ONLY do this just before redirecting
768
-     * @param bool $remove_empty             whether or not to unset empty messages
769
-     * @return array|string
770
-     * @throws InvalidArgumentException
771
-     * @throws InvalidDataTypeException
772
-     * @throws InvalidInterfaceException
773
-     * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
774
-     */
775
-    public static function get_notices(
776
-        bool $format_output = true,
777
-        bool $save_to_transient = false,
778
-        bool $remove_empty = true
779
-    ) {
780
-        $success_messages   = '';
781
-        $attention_messages = '';
782
-        $error_messages     = '';
783
-        /** @var RequestInterface $request */
784
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
785
-        // either save notices to the db
786
-        if ($save_to_transient || $request->requestParamIsSet('activate-selected')) {
787
-            self::$_espresso_notices = array_merge(
788
-                EE_Error::getStoredNotices(),
789
-                self::$_espresso_notices
790
-            );
791
-            EE_Error::storeNotices(self::$_espresso_notices);
792
-            return [];
793
-        }
794
-        $print_scripts = EE_Error::combineExistingAndNewNotices();
795
-        // check for success messages
796
-        if (! empty(self::$_espresso_notices['success'])) {
797
-            // combine messages
798
-            $success_messages .= implode('<br />', self::$_espresso_notices['success']);
799
-            $print_scripts    = true;
800
-        }
801
-        // check for attention messages
802
-        if (! empty(self::$_espresso_notices['attention'])) {
803
-            // combine messages
804
-            $attention_messages .= implode('<br />', self::$_espresso_notices['attention']);
805
-            $print_scripts      = true;
806
-        }
807
-        // check for error messages
808
-        if (! empty(self::$_espresso_notices['errors'])) {
809
-            $error_messages .= count(self::$_espresso_notices['errors']) > 1
810
-                ? esc_html__('The following errors have occurred:', 'event_espresso')
811
-                : esc_html__('An error has occurred:', 'event_espresso');
812
-            // combine messages
813
-            $error_messages .= '<br />' . implode('<br />', self::$_espresso_notices['errors']);
814
-            $print_scripts  = true;
815
-        }
816
-        if ($format_output) {
817
-            $notices = EE_Error::formatNoticesOutput(
818
-                $success_messages,
819
-                $attention_messages,
820
-                $error_messages
821
-            );
822
-        } else {
823
-            $notices = [
824
-                'success'   => $success_messages,
825
-                'attention' => $attention_messages,
826
-                'errors'    => $error_messages,
827
-            ];
828
-            if ($remove_empty) {
829
-                // remove empty notices
830
-                foreach ($notices as $type => $notice) {
831
-                    if (empty($notice)) {
832
-                        unset($notices[ $type ]);
833
-                    }
834
-                }
835
-            }
836
-        }
837
-        if ($print_scripts) {
838
-            self::_print_scripts();
839
-        }
840
-        return $notices;
841
-    }
842
-
843
-
844
-    /**
845
-     * @return bool
846
-     * @throws InvalidArgumentException
847
-     * @throws InvalidDataTypeException
848
-     * @throws InvalidInterfaceException
849
-     */
850
-    private static function combineExistingAndNewNotices(): bool
851
-    {
852
-        $print_scripts = false;
853
-        // grab any notices that have been previously saved
854
-        $notices = EE_Error::getStoredNotices();
855
-        if (! empty($notices)) {
856
-            foreach ($notices as $type => $notice) {
857
-                if (is_array($notice) && ! empty($notice)) {
858
-                    // make sure that existing notice type is an array
859
-                    self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
860
-                                                        && ! empty(self::$_espresso_notices[ $type ])
861
-                        ? self::$_espresso_notices[ $type ]
862
-                        : [];
863
-                    // add newly created notices to existing ones
864
-                    self::$_espresso_notices[ $type ] += $notice;
865
-                    $print_scripts                    = true;
866
-                }
867
-            }
868
-            // now clear any stored notices
869
-            EE_Error::clearNotices();
870
-        }
871
-        return $print_scripts;
872
-    }
873
-
874
-
875
-    /**
876
-     * @param string $success_messages
877
-     * @param string $attention_messages
878
-     * @param string $error_messages
879
-     * @return string
880
-     */
881
-    private static function formatNoticesOutput(
882
-        string $success_messages,
883
-        string $attention_messages,
884
-        string $error_messages
885
-    ): string {
886
-        $notices = '<div id="espresso-notices">';
887
-        $close   = is_admin()
888
-            ? ''
889
-            : '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
890
-        if ($success_messages !== '') {
891
-            $css_id    = is_admin() ? 'ee-success-message' : 'espresso-notices-success';
892
-            $css_class = is_admin() ? 'updated fade ee-status-outline ee-status-bg--success' : 'success fade-away';
893
-            // showMessage( $success_messages );
894
-            $notices .= '<div id="' . $css_id . '" '
895
-                        . 'class="espresso-notices ' . $css_class . '" '
896
-                        . 'style="display:none;">'
897
-                        . '<p>' . $success_messages . '</p>'
898
-                        . $close
899
-                        . '</div>';
900
-        }
901
-        if ($attention_messages !== '') {
902
-            $css_id    = is_admin()  ? 'ee-attention-message' : 'espresso-notices-attention';
903
-            $css_class = is_admin()
904
-                ? 'notice notice-info ee-notices-attention ee-status-outline ee-status-bg--attention'
905
-                : 'attention fade-away';
906
-            // showMessage( $error_messages, TRUE );
907
-            $notices .= '<div id="' . $css_id . '" '
908
-                        . 'class="espresso-notices ' . $css_class . '" '
909
-                        . 'style="display:none;">'
910
-                        . '<p>' . $attention_messages . '</p>'
911
-                        . $close
912
-                        . '</div>';
913
-        }
914
-        if ($error_messages !== '') {
915
-            $css_id    = is_admin() ? 'ee-error-message' : 'espresso-notices-error';
916
-            $css_class = is_admin()
917
-                ? 'error ee-status-outline ee-status-bg--error'
918
-                : 'error fade-away';
919
-            // showMessage( $error_messages, TRUE );
920
-            $notices .= '<div id="' . $css_id . '" '
921
-                        . 'class="espresso-notices ' . $css_class . '" '
922
-                        . 'style="display:none;">'
923
-                        . '<p>' . $error_messages . '</p>'
924
-                        . $close
925
-                        . '</div>';
926
-        }
927
-        $notices .= '</div>';
928
-        return $notices;
929
-    }
930
-
931
-
932
-    /**
933
-     * _print_scripts
934
-     *
935
-     * @param bool $force_print
936
-     * @return    string
937
-     */
938
-    private static function _print_scripts(bool $force_print = false): string
939
-    {
940
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
941
-            if (wp_script_is('ee_error_js', 'registered')) {
942
-                wp_enqueue_style('espresso_default');
943
-                wp_enqueue_style('espresso_custom_css');
944
-                wp_enqueue_script('ee_error_js');
945
-            }
946
-            if (wp_script_is('ee_error_js')) {
947
-                wp_localize_script('ee_error_js', 'ee_settings', ['wp_debug' => WP_DEBUG]);
948
-                return '';
949
-            }
950
-        } else {
951
-            return '
388
+		$output .= self::_print_scripts(true);
389
+		if (defined('DOING_AJAX')) {
390
+			echo wp_json_encode(['error' => $output]);
391
+			exit();
392
+		}
393
+		echo wp_kses($output, AllowedTags::getWithFormTags());
394
+		die();
395
+	}
396
+
397
+
398
+	/**
399
+	 *    generate string from exception trace args
400
+	 *
401
+	 * @param array $arguments
402
+	 * @param bool  $array
403
+	 * @return string
404
+	 */
405
+	private function _convert_args_to_string(array $arguments = [], bool $array = false): string
406
+	{
407
+		$arg_string = '';
408
+		if (! empty($arguments)) {
409
+			$args = [];
410
+			foreach ($arguments as $arg) {
411
+				if (! empty($arg)) {
412
+					if (is_string($arg)) {
413
+						$args[] = " '" . $arg . "'";
414
+					} elseif (is_array($arg)) {
415
+						$args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
416
+					} elseif (is_bool($arg)) {
417
+						$args[] = $arg ? ' TRUE' : ' FALSE';
418
+					} elseif (is_object($arg)) {
419
+						$args[] = ' OBJECT ' . get_class($arg);
420
+					} elseif (is_resource($arg)) {
421
+						$args[] = get_resource_type($arg);
422
+					} else {
423
+						$args[] = $arg;
424
+					}
425
+				} else {
426
+					$args[] = ' NULL';
427
+				}
428
+			}
429
+			$arg_string = implode(', ', $args);
430
+		}
431
+		if ($array) {
432
+			$arg_string .= ' )';
433
+		}
434
+		return $arg_string;
435
+	}
436
+
437
+
438
+	/**
439
+	 *    add error message
440
+	 *
441
+	 * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
442
+	 *                            separate messages for user || dev
443
+	 * @param string $file        the file that the error occurred in - just use __FILE__
444
+	 * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
445
+	 * @param int|string $line        the line number where the error occurred - just use __LINE__
446
+	 * @return        void
447
+	 */
448
+	public static function add_error(string $msg, string $file, string $func, $line)
449
+	{
450
+		self::_add_notice('errors', $msg, $file, $func, $line);
451
+		self::$_error_count++;
452
+	}
453
+
454
+
455
+	/**
456
+	 * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
457
+	 * adds an error
458
+	 *
459
+	 * @param string $msg
460
+	 * @param string $file
461
+	 * @param string $func
462
+	 * @param int|string $line
463
+	 * @throws EE_Error
464
+	 */
465
+	public static function throw_exception_if_debugging(
466
+		string $msg = '',
467
+		string $file = '',
468
+		string $func = '',
469
+		$line = ''
470
+	) {
471
+		if (WP_DEBUG) {
472
+			throw new EE_Error($msg);
473
+		}
474
+		EE_Error::add_error($msg, $file, $func, $line);
475
+	}
476
+
477
+
478
+	/**
479
+	 *    add success message
480
+	 *
481
+	 * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
482
+	 *                            separate messages for user || dev
483
+	 * @param string $file        the file that the error occurred in - just use __FILE__
484
+	 * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
485
+	 * @param int|string $line        the line number where the error occurred - just use __LINE__
486
+	 * @return void
487
+	 */
488
+	public static function add_success(string $msg = '', string $file = '', string $func = '', $line = '')
489
+	{
490
+		self::_add_notice('success', $msg, $file, $func, $line);
491
+	}
492
+
493
+
494
+	/**
495
+	 *    add attention message
496
+	 *
497
+	 * @param string $msg         the message to display to users or developers - adding a double pipe || (OR) creates
498
+	 *                            separate messages for user || dev
499
+	 * @param string $file        the file that the error occurred in - just use __FILE__
500
+	 * @param string $func        the function/method that the error occurred in - just use __FUNCTION__
501
+	 * @param int|string $line        the line number where the error occurred - just use __LINE__
502
+	 * @return        void
503
+	 */
504
+	public static function add_attention(string $msg = '', string $file = '', string $func = '', $line = '')
505
+	{
506
+		self::_add_notice('attention', $msg, $file, $func, $line);
507
+	}
508
+
509
+
510
+	/**
511
+	 * @param string $type whether the message is for a success or error notification
512
+	 * @param string $msg  the message to display to users or developers
513
+	 *                     - adding a double pipe || (OR) creates separate messages for user || dev
514
+	 * @param string $file the file that the error occurred in - just use __FILE__
515
+	 * @param string $func the function/method that the error occurred in - just use __FUNCTION__
516
+	 * @param int|string $line the line number where the error occurred - just use __LINE__
517
+	 * @return void
518
+	 */
519
+	private static function _add_notice(
520
+		string $type = 'success',
521
+		string $msg = '',
522
+		string $file = '',
523
+		string $func = '',
524
+		$line = ''
525
+	) {
526
+		if (empty($msg)) {
527
+			EE_Error::doing_it_wrong(
528
+				'EE_Error::add_' . $type . '()',
529
+				sprintf(
530
+					esc_html__(
531
+						'Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
532
+						'event_espresso'
533
+					),
534
+					$type,
535
+					$file,
536
+					$line
537
+				),
538
+				EVENT_ESPRESSO_VERSION
539
+			);
540
+		}
541
+		if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
542
+			EE_Error::doing_it_wrong(
543
+				'EE_Error::add_error()',
544
+				esc_html__(
545
+					'You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
546
+					'event_espresso'
547
+				),
548
+				EVENT_ESPRESSO_VERSION
549
+			);
550
+		}
551
+		// get separate user and developer messages if they exist
552
+		$msg      = explode('||', $msg);
553
+		$user_msg = $msg[0];
554
+		$dev_msg  = $msg[1] ?? $msg[0];
555
+		/**
556
+		 * Do an action so other code can be triggered when a notice is created
557
+		 *
558
+		 * @param string $type     can be 'errors', 'attention', or 'success'
559
+		 * @param string $user_msg message displayed to user when WP_DEBUG is off
560
+		 * @param string $user_msg message displayed to user when WP_DEBUG is on
561
+		 * @param string $file     file where error was generated
562
+		 * @param string $func     function where error was generated
563
+		 * @param int|string $line     line where error was generated
564
+		 */
565
+		do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
566
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
567
+		// add notice if message exists
568
+		if (! empty($msg)) {
569
+			// get error code
570
+			$notice_code = EE_Error::generate_error_code($file, $func, $line);
571
+			if (WP_DEBUG && $type === 'errors') {
572
+				$msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
573
+			}
574
+
575
+			if (! is_array(self::$_espresso_notices[ $type ]) || ! array_key_exists($type, self::$_espresso_notices)) {
576
+				self::$_espresso_notices[ $type ] = [];
577
+			}
578
+
579
+			// add notice. Index by code if it's not blank
580
+			if ($notice_code) {
581
+				self::$_espresso_notices[ $type ][ $notice_code ] = $msg;
582
+			} else {
583
+				self::$_espresso_notices[ $type ][] = $msg;
584
+			}
585
+			add_action('wp_footer', ['EE_Error', 'enqueue_error_scripts'], 1);
586
+		}
587
+	}
588
+
589
+
590
+	/**
591
+	 * in some case it may be necessary to overwrite the existing success messages
592
+	 *
593
+	 * @return        void
594
+	 */
595
+	public static function overwrite_success()
596
+	{
597
+		self::$_espresso_notices['success'] = [];
598
+	}
599
+
600
+
601
+	/**
602
+	 * in some case it may be necessary to overwrite the existing attention messages
603
+	 *
604
+	 * @return void
605
+	 */
606
+	public static function overwrite_attention()
607
+	{
608
+		self::$_espresso_notices['attention'] = [];
609
+	}
610
+
611
+
612
+	/**
613
+	 * in some case it may be necessary to overwrite the existing error messages
614
+	 *
615
+	 * @return void
616
+	 */
617
+	public static function overwrite_errors()
618
+	{
619
+		self::$_espresso_notices['errors'] = [];
620
+	}
621
+
622
+
623
+	/**
624
+	 * @return void
625
+	 */
626
+	public static function reset_notices()
627
+	{
628
+		self::$_espresso_notices['success']   = [];
629
+		self::$_espresso_notices['attention'] = [];
630
+		self::$_espresso_notices['errors']    = [];
631
+	}
632
+
633
+
634
+	/**
635
+	 * @return int
636
+	 */
637
+	public static function has_notices(): int
638
+	{
639
+		$has_notices = 0;
640
+		// check for success messages
641
+		$has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
642
+			? 3
643
+			: $has_notices;
644
+		// check for attention messages
645
+		$has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
646
+			? 2
647
+			: $has_notices;
648
+		// check for error messages
649
+		return self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
650
+			? 1
651
+			: $has_notices;
652
+	}
653
+
654
+
655
+	/**
656
+	 * This simply returns non formatted error notices as they were sent into the EE_Error object.
657
+	 *
658
+	 * @return array
659
+	 * @since 4.9.0
660
+	 */
661
+	public static function get_vanilla_notices(): array
662
+	{
663
+		return [
664
+			'success'   => self::$_espresso_notices['success'] ?? [],
665
+			'attention' => self::$_espresso_notices['attention'] ?? [],
666
+			'errors'    => self::$_espresso_notices['errors'] ?? [],
667
+		];
668
+	}
669
+
670
+
671
+	/**
672
+	 * @return array
673
+	 * @throws InvalidArgumentException
674
+	 * @throws InvalidDataTypeException
675
+	 * @throws InvalidInterfaceException
676
+	 */
677
+	public static function getStoredNotices(): array
678
+	{
679
+		if ($user_id = get_current_user_id()) {
680
+			// get notices for logged in user
681
+			$notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
682
+			return is_array($notices) ? $notices : [];
683
+		}
684
+		if (EE_Session::isLoadedAndActive()) {
685
+			// get notices for user currently engaged in a session
686
+			$session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
687
+			return is_array($session_data) ? $session_data : [];
688
+		}
689
+		// get global notices and hope they apply to the current site visitor
690
+		$notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, []);
691
+		return is_array($notices) ? $notices : [];
692
+	}
693
+
694
+
695
+	/**
696
+	 * @param array $notices
697
+	 * @return bool
698
+	 * @throws InvalidArgumentException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws InvalidInterfaceException
701
+	 */
702
+	public static function storeNotices(array $notices): bool
703
+	{
704
+		if ($user_id = get_current_user_id()) {
705
+			// store notices for logged in user
706
+			return (bool) update_user_option(
707
+				$user_id,
708
+				EE_Error::OPTIONS_KEY_NOTICES,
709
+				$notices
710
+			);
711
+		}
712
+		if (EE_Session::isLoadedAndActive()) {
713
+			// store notices for user currently engaged in a session
714
+			return EE_Session::instance()->set_session_data(
715
+				[EE_Error::OPTIONS_KEY_NOTICES => $notices]
716
+			);
717
+		}
718
+		// store global notices and hope they apply to the same site visitor on the next request
719
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
720
+	}
721
+
722
+
723
+	/**
724
+	 * @return bool
725
+	 * @throws InvalidArgumentException
726
+	 * @throws InvalidDataTypeException
727
+	 * @throws InvalidInterfaceException
728
+	 */
729
+	public static function clearNotices(): bool
730
+	{
731
+		if ($user_id = get_current_user_id()) {
732
+			// clear notices for logged in user
733
+			return (bool) update_user_option(
734
+				$user_id,
735
+				EE_Error::OPTIONS_KEY_NOTICES,
736
+				[]
737
+			);
738
+		}
739
+		if (EE_Session::isLoadedAndActive()) {
740
+			// clear notices for user currently engaged in a session
741
+			return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
742
+		}
743
+		// clear global notices and hope none belonged to some for some other site visitor
744
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, []);
745
+	}
746
+
747
+
748
+	/**
749
+	 * saves notices to the db for retrieval on next request
750
+	 *
751
+	 * @return void
752
+	 * @throws InvalidArgumentException
753
+	 * @throws InvalidDataTypeException
754
+	 * @throws InvalidInterfaceException
755
+	 */
756
+	public static function stashNoticesBeforeRedirect()
757
+	{
758
+		EE_Error::get_notices(false, true);
759
+	}
760
+
761
+
762
+	/**
763
+	 * compile all error or success messages into one string
764
+	 *
765
+	 * @param boolean $format_output            whether or not to format the messages for display in the WP admin
766
+	 * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
767
+	 *                                          - ONLY do this just before redirecting
768
+	 * @param bool $remove_empty             whether or not to unset empty messages
769
+	 * @return array|string
770
+	 * @throws InvalidArgumentException
771
+	 * @throws InvalidDataTypeException
772
+	 * @throws InvalidInterfaceException
773
+	 * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
774
+	 */
775
+	public static function get_notices(
776
+		bool $format_output = true,
777
+		bool $save_to_transient = false,
778
+		bool $remove_empty = true
779
+	) {
780
+		$success_messages   = '';
781
+		$attention_messages = '';
782
+		$error_messages     = '';
783
+		/** @var RequestInterface $request */
784
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
785
+		// either save notices to the db
786
+		if ($save_to_transient || $request->requestParamIsSet('activate-selected')) {
787
+			self::$_espresso_notices = array_merge(
788
+				EE_Error::getStoredNotices(),
789
+				self::$_espresso_notices
790
+			);
791
+			EE_Error::storeNotices(self::$_espresso_notices);
792
+			return [];
793
+		}
794
+		$print_scripts = EE_Error::combineExistingAndNewNotices();
795
+		// check for success messages
796
+		if (! empty(self::$_espresso_notices['success'])) {
797
+			// combine messages
798
+			$success_messages .= implode('<br />', self::$_espresso_notices['success']);
799
+			$print_scripts    = true;
800
+		}
801
+		// check for attention messages
802
+		if (! empty(self::$_espresso_notices['attention'])) {
803
+			// combine messages
804
+			$attention_messages .= implode('<br />', self::$_espresso_notices['attention']);
805
+			$print_scripts      = true;
806
+		}
807
+		// check for error messages
808
+		if (! empty(self::$_espresso_notices['errors'])) {
809
+			$error_messages .= count(self::$_espresso_notices['errors']) > 1
810
+				? esc_html__('The following errors have occurred:', 'event_espresso')
811
+				: esc_html__('An error has occurred:', 'event_espresso');
812
+			// combine messages
813
+			$error_messages .= '<br />' . implode('<br />', self::$_espresso_notices['errors']);
814
+			$print_scripts  = true;
815
+		}
816
+		if ($format_output) {
817
+			$notices = EE_Error::formatNoticesOutput(
818
+				$success_messages,
819
+				$attention_messages,
820
+				$error_messages
821
+			);
822
+		} else {
823
+			$notices = [
824
+				'success'   => $success_messages,
825
+				'attention' => $attention_messages,
826
+				'errors'    => $error_messages,
827
+			];
828
+			if ($remove_empty) {
829
+				// remove empty notices
830
+				foreach ($notices as $type => $notice) {
831
+					if (empty($notice)) {
832
+						unset($notices[ $type ]);
833
+					}
834
+				}
835
+			}
836
+		}
837
+		if ($print_scripts) {
838
+			self::_print_scripts();
839
+		}
840
+		return $notices;
841
+	}
842
+
843
+
844
+	/**
845
+	 * @return bool
846
+	 * @throws InvalidArgumentException
847
+	 * @throws InvalidDataTypeException
848
+	 * @throws InvalidInterfaceException
849
+	 */
850
+	private static function combineExistingAndNewNotices(): bool
851
+	{
852
+		$print_scripts = false;
853
+		// grab any notices that have been previously saved
854
+		$notices = EE_Error::getStoredNotices();
855
+		if (! empty($notices)) {
856
+			foreach ($notices as $type => $notice) {
857
+				if (is_array($notice) && ! empty($notice)) {
858
+					// make sure that existing notice type is an array
859
+					self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
860
+														&& ! empty(self::$_espresso_notices[ $type ])
861
+						? self::$_espresso_notices[ $type ]
862
+						: [];
863
+					// add newly created notices to existing ones
864
+					self::$_espresso_notices[ $type ] += $notice;
865
+					$print_scripts                    = true;
866
+				}
867
+			}
868
+			// now clear any stored notices
869
+			EE_Error::clearNotices();
870
+		}
871
+		return $print_scripts;
872
+	}
873
+
874
+
875
+	/**
876
+	 * @param string $success_messages
877
+	 * @param string $attention_messages
878
+	 * @param string $error_messages
879
+	 * @return string
880
+	 */
881
+	private static function formatNoticesOutput(
882
+		string $success_messages,
883
+		string $attention_messages,
884
+		string $error_messages
885
+	): string {
886
+		$notices = '<div id="espresso-notices">';
887
+		$close   = is_admin()
888
+			? ''
889
+			: '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
890
+		if ($success_messages !== '') {
891
+			$css_id    = is_admin() ? 'ee-success-message' : 'espresso-notices-success';
892
+			$css_class = is_admin() ? 'updated fade ee-status-outline ee-status-bg--success' : 'success fade-away';
893
+			// showMessage( $success_messages );
894
+			$notices .= '<div id="' . $css_id . '" '
895
+						. 'class="espresso-notices ' . $css_class . '" '
896
+						. 'style="display:none;">'
897
+						. '<p>' . $success_messages . '</p>'
898
+						. $close
899
+						. '</div>';
900
+		}
901
+		if ($attention_messages !== '') {
902
+			$css_id    = is_admin()  ? 'ee-attention-message' : 'espresso-notices-attention';
903
+			$css_class = is_admin()
904
+				? 'notice notice-info ee-notices-attention ee-status-outline ee-status-bg--attention'
905
+				: 'attention fade-away';
906
+			// showMessage( $error_messages, TRUE );
907
+			$notices .= '<div id="' . $css_id . '" '
908
+						. 'class="espresso-notices ' . $css_class . '" '
909
+						. 'style="display:none;">'
910
+						. '<p>' . $attention_messages . '</p>'
911
+						. $close
912
+						. '</div>';
913
+		}
914
+		if ($error_messages !== '') {
915
+			$css_id    = is_admin() ? 'ee-error-message' : 'espresso-notices-error';
916
+			$css_class = is_admin()
917
+				? 'error ee-status-outline ee-status-bg--error'
918
+				: 'error fade-away';
919
+			// showMessage( $error_messages, TRUE );
920
+			$notices .= '<div id="' . $css_id . '" '
921
+						. 'class="espresso-notices ' . $css_class . '" '
922
+						. 'style="display:none;">'
923
+						. '<p>' . $error_messages . '</p>'
924
+						. $close
925
+						. '</div>';
926
+		}
927
+		$notices .= '</div>';
928
+		return $notices;
929
+	}
930
+
931
+
932
+	/**
933
+	 * _print_scripts
934
+	 *
935
+	 * @param bool $force_print
936
+	 * @return    string
937
+	 */
938
+	private static function _print_scripts(bool $force_print = false): string
939
+	{
940
+		if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
941
+			if (wp_script_is('ee_error_js', 'registered')) {
942
+				wp_enqueue_style('espresso_default');
943
+				wp_enqueue_style('espresso_custom_css');
944
+				wp_enqueue_script('ee_error_js');
945
+			}
946
+			if (wp_script_is('ee_error_js')) {
947
+				wp_localize_script('ee_error_js', 'ee_settings', ['wp_debug' => WP_DEBUG]);
948
+				return '';
949
+			}
950
+		} else {
951
+			return '
952 952
 <script>
953 953
 /* <![CDATA[ */
954 954
 const ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
@@ -958,233 +958,233 @@  discard block
 block discarded – undo
958 958
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
959 959
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
960 960
 ';
961
-        }
962
-        return '';
963
-    }
964
-
965
-
966
-    /**
967
-     * @return void
968
-     */
969
-    public static function enqueue_error_scripts()
970
-    {
971
-        self::_print_scripts();
972
-    }
973
-
974
-
975
-    /**
976
-     * create error code from filepath, function name,
977
-     * and line number where exception or error was thrown
978
-     *
979
-     * @param string $file
980
-     * @param string $func
981
-     * @param int|string $line
982
-     * @return string
983
-     */
984
-    public static function generate_error_code(string $file = '', string $func = '', $line = ''): string
985
-    {
986
-        $file       = explode('.', basename($file));
987
-        $error_code = ! empty($file[0]) ? $file[0] : '';
988
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
989
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
990
-        return $error_code;
991
-    }
992
-
993
-
994
-    /**
995
-     * write exception details to log file
996
-     * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
997
-     *
998
-     * @param int   $time
999
-     * @param array $ex
1000
-     * @param bool  $clear
1001
-     * @return void
1002
-     */
1003
-    public function write_to_error_log(int $time = 0, array $ex = [], bool $clear = false)
1004
-    {
1005
-        if (empty($ex)) {
1006
-            return;
1007
-        }
1008
-        if (! $time) {
1009
-            $time = time();
1010
-        }
1011
-        $exception_log = '----------------------------------------------------------------------------------------'
1012
-                         . PHP_EOL;
1013
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1014
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1015
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1016
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1017
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1018
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1019
-        $exception_log .= $ex['string'] . PHP_EOL;
1020
-        $exception_log .= '----------------------------------------------------------------------------------------'
1021
-                          . PHP_EOL;
1022
-        try {
1023
-            error_log($exception_log);
1024
-        } catch (Exception $e) {
1025
-            EE_Error::add_error(
1026
-                sprintf(
1027
-                    esc_html__(
1028
-                        'Event Espresso error logging could not be setup because: %s',
1029
-                        'event_espresso'
1030
-                    ),
1031
-                    $e->getMessage()
1032
-                ),
1033
-                __FILE__,
1034
-                __FUNCTION__,
1035
-                __LINE__
1036
-            );
1037
-        }
1038
-    }
1039
-
1040
-
1041
-    /**
1042
-     * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1043
-     * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1044
-     * but the code execution is done in a manner that could lead to unexpected results
1045
-     * (i.e. running to early, or too late in WP or EE loading process).
1046
-     * A good test for knowing whether to use this method is:
1047
-     * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1048
-     * Yes -> use EE_Error::add_error() or throw new EE_Error()
1049
-     * 2. If this is loaded before something else, it won't break anything,
1050
-     * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1051
-     *
1052
-     * @param string   $function     The function that was called
1053
-     * @param string   $message      A message explaining what has been done incorrectly
1054
-     * @param string   $version      The version of Event Espresso where the error was added
1055
-     * @param string   $applies_when a version string for when you want the doing_it_wrong notice to begin appearing
1056
-     *                               for a deprecated function. This allows deprecation to occur during one version,
1057
-     *                               but not have any notices appear until a later version. This allows developers
1058
-     *                               extra time to update their code before notices appear.
1059
-     * @param int|null $error_type
1060
-     * @uses   constant WP_DEBUG test if wp_debug is on or not
1061
-     */
1062
-    public static function doing_it_wrong(
1063
-        string $function,
1064
-        string $message,
1065
-        string $version,
1066
-        string $applies_when = '',
1067
-        int $error_type = null
1068
-    ) {
1069
-        if (defined('WP_DEBUG') && WP_DEBUG) {
1070
-            EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1071
-        }
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * Like get_notices, but returns an array of all the notices of the given type.
1077
-     *
1078
-     * @return array {
1079
-     * @type array $success   all the success messages
1080
-     * @type array $errors    all the error messages
1081
-     * @type array $attention all the attention messages
1082
-     * }
1083
-     */
1084
-    public static function get_raw_notices(): array
1085
-    {
1086
-        return self::$_espresso_notices;
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1092
-     * @param string $pan_message  the message to be stored persistently until dismissed
1093
-     * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1094
-     * @return void
1095
-     * @throws InvalidDataTypeException
1096
-     * @deprecated 4.9.27
1097
-     */
1098
-    public static function add_persistent_admin_notice(
1099
-        string $pan_name = '',
1100
-        string $pan_message = '',
1101
-        bool $force_update = false
1102
-    ) {
1103
-        new PersistentAdminNotice(
1104
-            $pan_name,
1105
-            $pan_message,
1106
-            $force_update
1107
-        );
1108
-        EE_Error::doing_it_wrong(
1109
-            __METHOD__,
1110
-            sprintf(
1111
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1112
-                '\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1113
-            ),
1114
-            '4.9.27'
1115
-        );
1116
-    }
1117
-
1118
-
1119
-    /**
1120
-     * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1121
-     * @param bool   $purge
1122
-     * @param bool   $return
1123
-     * @throws DomainException
1124
-     * @throws InvalidInterfaceException
1125
-     * @throws InvalidDataTypeException
1126
-     * @throws ServiceNotFoundException
1127
-     * @throws InvalidArgumentException
1128
-     * @deprecated 4.9.27
1129
-     */
1130
-    public static function dismiss_persistent_admin_notice(
1131
-        string $pan_name = '',
1132
-        bool $purge = false,
1133
-        bool $return = false
1134
-    ) {
1135
-        /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1136
-        $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1137
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1138
-        );
1139
-        $persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1140
-        EE_Error::doing_it_wrong(
1141
-            __METHOD__,
1142
-            sprintf(
1143
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1144
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1145
-            ),
1146
-            '4.9.27'
1147
-        );
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * @param string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1153
-     * @param string $pan_message the message to be stored persistently until dismissed
1154
-     * @param string $return_url  URL to go back to after nag notice is dismissed
1155
-     * @deprecated 4.9.27
1156
-     */
1157
-    public static function display_persistent_admin_notices(
1158
-        string $pan_name = '',
1159
-        string $pan_message = '',
1160
-        string $return_url = ''
1161
-    ) {
1162
-        EE_Error::doing_it_wrong(
1163
-            __METHOD__,
1164
-            sprintf(
1165
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1166
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1167
-            ),
1168
-            '4.9.27'
1169
-        );
1170
-    }
1171
-
1172
-
1173
-    /**
1174
-     * @param string $return_url
1175
-     * @deprecated 4.9.27
1176
-     */
1177
-    public static function get_persistent_admin_notices(string $return_url = '')
1178
-    {
1179
-        EE_Error::doing_it_wrong(
1180
-            __METHOD__,
1181
-            sprintf(
1182
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1183
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1184
-            ),
1185
-            '4.9.27'
1186
-        );
1187
-    }
961
+		}
962
+		return '';
963
+	}
964
+
965
+
966
+	/**
967
+	 * @return void
968
+	 */
969
+	public static function enqueue_error_scripts()
970
+	{
971
+		self::_print_scripts();
972
+	}
973
+
974
+
975
+	/**
976
+	 * create error code from filepath, function name,
977
+	 * and line number where exception or error was thrown
978
+	 *
979
+	 * @param string $file
980
+	 * @param string $func
981
+	 * @param int|string $line
982
+	 * @return string
983
+	 */
984
+	public static function generate_error_code(string $file = '', string $func = '', $line = ''): string
985
+	{
986
+		$file       = explode('.', basename($file));
987
+		$error_code = ! empty($file[0]) ? $file[0] : '';
988
+		$error_code .= ! empty($func) ? ' - ' . $func : '';
989
+		$error_code .= ! empty($line) ? ' - ' . $line : '';
990
+		return $error_code;
991
+	}
992
+
993
+
994
+	/**
995
+	 * write exception details to log file
996
+	 * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
997
+	 *
998
+	 * @param int   $time
999
+	 * @param array $ex
1000
+	 * @param bool  $clear
1001
+	 * @return void
1002
+	 */
1003
+	public function write_to_error_log(int $time = 0, array $ex = [], bool $clear = false)
1004
+	{
1005
+		if (empty($ex)) {
1006
+			return;
1007
+		}
1008
+		if (! $time) {
1009
+			$time = time();
1010
+		}
1011
+		$exception_log = '----------------------------------------------------------------------------------------'
1012
+						 . PHP_EOL;
1013
+		$exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1014
+		$exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1015
+		$exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1016
+		$exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1017
+		$exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1018
+		$exception_log .= 'Stack trace: ' . PHP_EOL;
1019
+		$exception_log .= $ex['string'] . PHP_EOL;
1020
+		$exception_log .= '----------------------------------------------------------------------------------------'
1021
+						  . PHP_EOL;
1022
+		try {
1023
+			error_log($exception_log);
1024
+		} catch (Exception $e) {
1025
+			EE_Error::add_error(
1026
+				sprintf(
1027
+					esc_html__(
1028
+						'Event Espresso error logging could not be setup because: %s',
1029
+						'event_espresso'
1030
+					),
1031
+					$e->getMessage()
1032
+				),
1033
+				__FILE__,
1034
+				__FUNCTION__,
1035
+				__LINE__
1036
+			);
1037
+		}
1038
+	}
1039
+
1040
+
1041
+	/**
1042
+	 * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1043
+	 * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1044
+	 * but the code execution is done in a manner that could lead to unexpected results
1045
+	 * (i.e. running to early, or too late in WP or EE loading process).
1046
+	 * A good test for knowing whether to use this method is:
1047
+	 * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1048
+	 * Yes -> use EE_Error::add_error() or throw new EE_Error()
1049
+	 * 2. If this is loaded before something else, it won't break anything,
1050
+	 * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1051
+	 *
1052
+	 * @param string   $function     The function that was called
1053
+	 * @param string   $message      A message explaining what has been done incorrectly
1054
+	 * @param string   $version      The version of Event Espresso where the error was added
1055
+	 * @param string   $applies_when a version string for when you want the doing_it_wrong notice to begin appearing
1056
+	 *                               for a deprecated function. This allows deprecation to occur during one version,
1057
+	 *                               but not have any notices appear until a later version. This allows developers
1058
+	 *                               extra time to update their code before notices appear.
1059
+	 * @param int|null $error_type
1060
+	 * @uses   constant WP_DEBUG test if wp_debug is on or not
1061
+	 */
1062
+	public static function doing_it_wrong(
1063
+		string $function,
1064
+		string $message,
1065
+		string $version,
1066
+		string $applies_when = '',
1067
+		int $error_type = null
1068
+	) {
1069
+		if (defined('WP_DEBUG') && WP_DEBUG) {
1070
+			EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1071
+		}
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * Like get_notices, but returns an array of all the notices of the given type.
1077
+	 *
1078
+	 * @return array {
1079
+	 * @type array $success   all the success messages
1080
+	 * @type array $errors    all the error messages
1081
+	 * @type array $attention all the attention messages
1082
+	 * }
1083
+	 */
1084
+	public static function get_raw_notices(): array
1085
+	{
1086
+		return self::$_espresso_notices;
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1092
+	 * @param string $pan_message  the message to be stored persistently until dismissed
1093
+	 * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1094
+	 * @return void
1095
+	 * @throws InvalidDataTypeException
1096
+	 * @deprecated 4.9.27
1097
+	 */
1098
+	public static function add_persistent_admin_notice(
1099
+		string $pan_name = '',
1100
+		string $pan_message = '',
1101
+		bool $force_update = false
1102
+	) {
1103
+		new PersistentAdminNotice(
1104
+			$pan_name,
1105
+			$pan_message,
1106
+			$force_update
1107
+		);
1108
+		EE_Error::doing_it_wrong(
1109
+			__METHOD__,
1110
+			sprintf(
1111
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1112
+				'\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1113
+			),
1114
+			'4.9.27'
1115
+		);
1116
+	}
1117
+
1118
+
1119
+	/**
1120
+	 * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1121
+	 * @param bool   $purge
1122
+	 * @param bool   $return
1123
+	 * @throws DomainException
1124
+	 * @throws InvalidInterfaceException
1125
+	 * @throws InvalidDataTypeException
1126
+	 * @throws ServiceNotFoundException
1127
+	 * @throws InvalidArgumentException
1128
+	 * @deprecated 4.9.27
1129
+	 */
1130
+	public static function dismiss_persistent_admin_notice(
1131
+		string $pan_name = '',
1132
+		bool $purge = false,
1133
+		bool $return = false
1134
+	) {
1135
+		/** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1136
+		$persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1137
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1138
+		);
1139
+		$persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1140
+		EE_Error::doing_it_wrong(
1141
+			__METHOD__,
1142
+			sprintf(
1143
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1144
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1145
+			),
1146
+			'4.9.27'
1147
+		);
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * @param string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1153
+	 * @param string $pan_message the message to be stored persistently until dismissed
1154
+	 * @param string $return_url  URL to go back to after nag notice is dismissed
1155
+	 * @deprecated 4.9.27
1156
+	 */
1157
+	public static function display_persistent_admin_notices(
1158
+		string $pan_name = '',
1159
+		string $pan_message = '',
1160
+		string $return_url = ''
1161
+	) {
1162
+		EE_Error::doing_it_wrong(
1163
+			__METHOD__,
1164
+			sprintf(
1165
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1166
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1167
+			),
1168
+			'4.9.27'
1169
+		);
1170
+	}
1171
+
1172
+
1173
+	/**
1174
+	 * @param string $return_url
1175
+	 * @deprecated 4.9.27
1176
+	 */
1177
+	public static function get_persistent_admin_notices(string $return_url = '')
1178
+	{
1179
+		EE_Error::doing_it_wrong(
1180
+			__METHOD__,
1181
+			sprintf(
1182
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1183
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1184
+			),
1185
+			'4.9.27'
1186
+		);
1187
+	}
1188 1188
 }
1189 1189
 
1190 1190
 // end of Class EE_Exceptions
@@ -1197,29 +1197,29 @@  discard block
 block discarded – undo
1197 1197
  */
1198 1198
 function espresso_error_enqueue_scripts()
1199 1199
 {
1200
-    // js for error handling
1201
-    if (! wp_script_is('espresso_core', 'registered')) {
1202
-        wp_register_script(
1203
-            'espresso_core',
1204
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1205
-            ['jquery'],
1206
-            EVENT_ESPRESSO_VERSION
1207
-        );
1208
-    }
1209
-    wp_register_script(
1210
-        'ee_error_js',
1211
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1212
-        ['espresso_core'],
1213
-        EVENT_ESPRESSO_VERSION
1214
-    );
1215
-    wp_localize_script('ee_error_js', 'ee_settings', ['wp_debug' => WP_DEBUG]);
1200
+	// js for error handling
1201
+	if (! wp_script_is('espresso_core', 'registered')) {
1202
+		wp_register_script(
1203
+			'espresso_core',
1204
+			EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1205
+			['jquery'],
1206
+			EVENT_ESPRESSO_VERSION
1207
+		);
1208
+	}
1209
+	wp_register_script(
1210
+		'ee_error_js',
1211
+		EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1212
+		['espresso_core'],
1213
+		EVENT_ESPRESSO_VERSION
1214
+	);
1215
+	wp_localize_script('ee_error_js', 'ee_settings', ['wp_debug' => WP_DEBUG]);
1216 1216
 }
1217 1217
 
1218 1218
 
1219 1219
 if (is_admin()) {
1220
-    add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1220
+	add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1221 1221
 } else {
1222
-    add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1222
+	add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1223 1223
 }
1224 1224
 
1225 1225
 
Please login to merge, or discard this patch.
Spacing   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -72,14 +72,14 @@  discard block
 block discarded – undo
72 72
         $to      = strpos($site, 'eventespresso.com')
73 73
             ? '[email protected]'
74 74
             : get_option('admin_email');
75
-        $subject = "$type $message in " . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
75
+        $subject = "$type $message in ".EVENT_ESPRESSO_VERSION.' on '.site_url();
76 76
         $msg     = EE_Error::_format_error($type, $message, $file, $line);
77 77
         if (function_exists('wp_mail')) {
78 78
             add_filter('wp_mail_content_type', ['EE_Error', 'set_content_type']);
79 79
             wp_mail($to, $subject, $msg);
80 80
         }
81 81
         echo '<div id="message" class="espresso-notices error"><p>';
82
-        echo wp_kses($type . ': ' . $message . '<br />' . $file . ' line ' . $line, AllowedTags::getWithFormTags());
82
+        echo wp_kses($type.': '.$message.'<br />'.$file.' line '.$line, AllowedTags::getWithFormTags());
83 83
         echo '<br /></p></div>';
84 84
     }
85 85
 
@@ -196,13 +196,13 @@  discard block
 block discarded – undo
196 196
         $msg      = WP_DEBUG ? $dev_msg : $user_msg;
197 197
         // add details to _all_exceptions array
198 198
         $x_time                                     = time();
199
-        self::$_all_exceptions[ $x_time ]['name']   = get_class($this);
200
-        self::$_all_exceptions[ $x_time ]['file']   = $this->getFile();
201
-        self::$_all_exceptions[ $x_time ]['line']   = $this->getLine();
202
-        self::$_all_exceptions[ $x_time ]['msg']    = $msg;
203
-        self::$_all_exceptions[ $x_time ]['code']   = $this->getCode();
204
-        self::$_all_exceptions[ $x_time ]['trace']  = $this->getTrace();
205
-        self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
199
+        self::$_all_exceptions[$x_time]['name']   = get_class($this);
200
+        self::$_all_exceptions[$x_time]['file']   = $this->getFile();
201
+        self::$_all_exceptions[$x_time]['line']   = $this->getLine();
202
+        self::$_all_exceptions[$x_time]['msg']    = $msg;
203
+        self::$_all_exceptions[$x_time]['code']   = $this->getCode();
204
+        self::$_all_exceptions[$x_time]['trace']  = $this->getTrace();
205
+        self::$_all_exceptions[$x_time]['string'] = $this->getTraceAsString();
206 206
         self::$_error_count++;
207 207
         // add_action( 'shutdown', array( $this, 'display_errors' ));
208 208
         $this->display_errors();
@@ -219,8 +219,8 @@  discard block
 block discarded – undo
219 219
      */
220 220
     public static function has_error(bool $check_stored = false, string $type_to_check = 'errors'): bool
221 221
     {
222
-        $has_error = isset(self::$_espresso_notices[ $type_to_check ])
223
-                     && ! empty(self::$_espresso_notices[ $type_to_check ]);
222
+        $has_error = isset(self::$_espresso_notices[$type_to_check])
223
+                     && ! empty(self::$_espresso_notices[$type_to_check]);
224 224
         if ($check_stored && ! $has_error) {
225 225
             $notices = EE_Error::getStoredNotices();
226 226
             foreach ($notices as $type => $notice) {
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
         $trace_details = '';
243 243
         $output = '
244 244
         <div id="ee-error-message" class="error">';
245
-        if (! WP_DEBUG) {
245
+        if ( ! WP_DEBUG) {
246 246
             $output .= '
247 247
 	        <p>';
248 248
         }
@@ -301,14 +301,14 @@  discard block
 block discarded – undo
301 301
                     $class_display    = ! empty($class) ? $class : '&nbsp;';
302 302
                     $type_display     = ! empty($type) ? $type : '&nbsp;';
303 303
                     $function_display = ! empty($function) ? $function : '&nbsp;';
304
-                    $args_display     = ! empty($args) ? '( ' . $args . ' )' : '';
305
-                    $trace_details    .= '
304
+                    $args_display     = ! empty($args) ? '( '.$args.' )' : '';
305
+                    $trace_details .= '
306 306
 					<tr>
307
-						<td class="' . $zebra . '">' . $number_display . '</td>
308
-						<td class="' . $zebra . '">' . $line_display . '</td>
309
-						<td class="' . $zebra . '">' . $file_display . '</td>
310
-						<td class="' . $zebra . '">' . $class_display . '</td>
311
-						<td class="' . $zebra . '">' . $type_display . $function_display . $args_display . '</td>
307
+						<td class="' . $zebra.'">'.$number_display.'</td>
308
+						<td class="' . $zebra.'">'.$line_display.'</td>
309
+						<td class="' . $zebra.'">'.$file_display.'</td>
310
+						<td class="' . $zebra.'">'.$class_display.'</td>
311
+						<td class="' . $zebra.'">'.$type_display.$function_display.$args_display.'</td>
312 312
 					</tr>';
313 313
                 }
314 314
                 $trace_details .= '
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
             }
318 318
             $ex['code'] = $ex['code'] ?: $error_code;
319 319
             // add generic non-identifying messages for non-privileged users
320
-            if (! WP_DEBUG) {
320
+            if ( ! WP_DEBUG) {
321 321
                 $output .= '<span class="ee-error-user-msg-spn">'
322 322
                            . trim($ex['msg'])
323 323
                            . '</span> &nbsp; <sup>'
@@ -359,14 +359,14 @@  discard block
 block discarded – undo
359 359
                            . '-dv" class="ee-error-trace-dv" style="display: none;">
360 360
 				'
361 361
                            . $trace_details;
362
-                if (! empty($class)) {
362
+                if ( ! empty($class)) {
363 363
                     $output .= '
364 364
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
365 365
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
366 366
 						<h3>Class Details</h3>';
367
-                    $a      = new ReflectionClass($class);
367
+                    $a = new ReflectionClass($class);
368 368
                     $output .= '
369
-						<pre>' . $a . '</pre>
369
+						<pre>' . $a.'</pre>
370 370
 					</div>
371 371
 				</div>';
372 372
                 }
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
         }
380 380
         // remove last linebreak
381 381
         $output = substr($output, 0, -6);
382
-        if (! WP_DEBUG) {
382
+        if ( ! WP_DEBUG) {
383 383
             $output .= '
384 384
 	        </p>';
385 385
         }
@@ -405,18 +405,18 @@  discard block
 block discarded – undo
405 405
     private function _convert_args_to_string(array $arguments = [], bool $array = false): string
406 406
     {
407 407
         $arg_string = '';
408
-        if (! empty($arguments)) {
408
+        if ( ! empty($arguments)) {
409 409
             $args = [];
410 410
             foreach ($arguments as $arg) {
411
-                if (! empty($arg)) {
411
+                if ( ! empty($arg)) {
412 412
                     if (is_string($arg)) {
413
-                        $args[] = " '" . $arg . "'";
413
+                        $args[] = " '".$arg."'";
414 414
                     } elseif (is_array($arg)) {
415
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
415
+                        $args[] = 'ARRAY('.$this->_convert_args_to_string($arg, true);
416 416
                     } elseif (is_bool($arg)) {
417 417
                         $args[] = $arg ? ' TRUE' : ' FALSE';
418 418
                     } elseif (is_object($arg)) {
419
-                        $args[] = ' OBJECT ' . get_class($arg);
419
+                        $args[] = ' OBJECT '.get_class($arg);
420 420
                     } elseif (is_resource($arg)) {
421 421
                         $args[] = get_resource_type($arg);
422 422
                     } else {
@@ -525,7 +525,7 @@  discard block
 block discarded – undo
525 525
     ) {
526 526
         if (empty($msg)) {
527 527
             EE_Error::doing_it_wrong(
528
-                'EE_Error::add_' . $type . '()',
528
+                'EE_Error::add_'.$type.'()',
529 529
                 sprintf(
530 530
                     esc_html__(
531 531
                         'Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
@@ -565,22 +565,22 @@  discard block
 block discarded – undo
565 565
         do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
566 566
         $msg = WP_DEBUG ? $dev_msg : $user_msg;
567 567
         // add notice if message exists
568
-        if (! empty($msg)) {
568
+        if ( ! empty($msg)) {
569 569
             // get error code
570 570
             $notice_code = EE_Error::generate_error_code($file, $func, $line);
571 571
             if (WP_DEBUG && $type === 'errors') {
572
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
572
+                $msg .= '<br/><span class="tiny-text">'.$notice_code.'</span>';
573 573
             }
574 574
 
575
-            if (! is_array(self::$_espresso_notices[ $type ]) || ! array_key_exists($type, self::$_espresso_notices)) {
576
-                self::$_espresso_notices[ $type ] = [];
575
+            if ( ! is_array(self::$_espresso_notices[$type]) || ! array_key_exists($type, self::$_espresso_notices)) {
576
+                self::$_espresso_notices[$type] = [];
577 577
             }
578 578
 
579 579
             // add notice. Index by code if it's not blank
580 580
             if ($notice_code) {
581
-                self::$_espresso_notices[ $type ][ $notice_code ] = $msg;
581
+                self::$_espresso_notices[$type][$notice_code] = $msg;
582 582
             } else {
583
-                self::$_espresso_notices[ $type ][] = $msg;
583
+                self::$_espresso_notices[$type][] = $msg;
584 584
             }
585 585
             add_action('wp_footer', ['EE_Error', 'enqueue_error_scripts'], 1);
586 586
         }
@@ -793,25 +793,25 @@  discard block
 block discarded – undo
793 793
         }
794 794
         $print_scripts = EE_Error::combineExistingAndNewNotices();
795 795
         // check for success messages
796
-        if (! empty(self::$_espresso_notices['success'])) {
796
+        if ( ! empty(self::$_espresso_notices['success'])) {
797 797
             // combine messages
798 798
             $success_messages .= implode('<br />', self::$_espresso_notices['success']);
799
-            $print_scripts    = true;
799
+            $print_scripts = true;
800 800
         }
801 801
         // check for attention messages
802
-        if (! empty(self::$_espresso_notices['attention'])) {
802
+        if ( ! empty(self::$_espresso_notices['attention'])) {
803 803
             // combine messages
804 804
             $attention_messages .= implode('<br />', self::$_espresso_notices['attention']);
805
-            $print_scripts      = true;
805
+            $print_scripts = true;
806 806
         }
807 807
         // check for error messages
808
-        if (! empty(self::$_espresso_notices['errors'])) {
808
+        if ( ! empty(self::$_espresso_notices['errors'])) {
809 809
             $error_messages .= count(self::$_espresso_notices['errors']) > 1
810 810
                 ? esc_html__('The following errors have occurred:', 'event_espresso')
811 811
                 : esc_html__('An error has occurred:', 'event_espresso');
812 812
             // combine messages
813
-            $error_messages .= '<br />' . implode('<br />', self::$_espresso_notices['errors']);
814
-            $print_scripts  = true;
813
+            $error_messages .= '<br />'.implode('<br />', self::$_espresso_notices['errors']);
814
+            $print_scripts = true;
815 815
         }
816 816
         if ($format_output) {
817 817
             $notices = EE_Error::formatNoticesOutput(
@@ -829,7 +829,7 @@  discard block
 block discarded – undo
829 829
                 // remove empty notices
830 830
                 foreach ($notices as $type => $notice) {
831 831
                     if (empty($notice)) {
832
-                        unset($notices[ $type ]);
832
+                        unset($notices[$type]);
833 833
                     }
834 834
                 }
835 835
             }
@@ -852,17 +852,17 @@  discard block
 block discarded – undo
852 852
         $print_scripts = false;
853 853
         // grab any notices that have been previously saved
854 854
         $notices = EE_Error::getStoredNotices();
855
-        if (! empty($notices)) {
855
+        if ( ! empty($notices)) {
856 856
             foreach ($notices as $type => $notice) {
857 857
                 if (is_array($notice) && ! empty($notice)) {
858 858
                     // make sure that existing notice type is an array
859
-                    self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
860
-                                                        && ! empty(self::$_espresso_notices[ $type ])
861
-                        ? self::$_espresso_notices[ $type ]
859
+                    self::$_espresso_notices[$type] = is_array(self::$_espresso_notices[$type])
860
+                                                        && ! empty(self::$_espresso_notices[$type])
861
+                        ? self::$_espresso_notices[$type]
862 862
                         : [];
863 863
                     // add newly created notices to existing ones
864
-                    self::$_espresso_notices[ $type ] += $notice;
865
-                    $print_scripts                    = true;
864
+                    self::$_espresso_notices[$type] += $notice;
865
+                    $print_scripts = true;
866 866
                 }
867 867
             }
868 868
             // now clear any stored notices
@@ -891,23 +891,23 @@  discard block
 block discarded – undo
891 891
             $css_id    = is_admin() ? 'ee-success-message' : 'espresso-notices-success';
892 892
             $css_class = is_admin() ? 'updated fade ee-status-outline ee-status-bg--success' : 'success fade-away';
893 893
             // showMessage( $success_messages );
894
-            $notices .= '<div id="' . $css_id . '" '
895
-                        . 'class="espresso-notices ' . $css_class . '" '
894
+            $notices .= '<div id="'.$css_id.'" '
895
+                        . 'class="espresso-notices '.$css_class.'" '
896 896
                         . 'style="display:none;">'
897
-                        . '<p>' . $success_messages . '</p>'
897
+                        . '<p>'.$success_messages.'</p>'
898 898
                         . $close
899 899
                         . '</div>';
900 900
         }
901 901
         if ($attention_messages !== '') {
902
-            $css_id    = is_admin()  ? 'ee-attention-message' : 'espresso-notices-attention';
902
+            $css_id    = is_admin() ? 'ee-attention-message' : 'espresso-notices-attention';
903 903
             $css_class = is_admin()
904 904
                 ? 'notice notice-info ee-notices-attention ee-status-outline ee-status-bg--attention'
905 905
                 : 'attention fade-away';
906 906
             // showMessage( $error_messages, TRUE );
907
-            $notices .= '<div id="' . $css_id . '" '
908
-                        . 'class="espresso-notices ' . $css_class . '" '
907
+            $notices .= '<div id="'.$css_id.'" '
908
+                        . 'class="espresso-notices '.$css_class.'" '
909 909
                         . 'style="display:none;">'
910
-                        . '<p>' . $attention_messages . '</p>'
910
+                        . '<p>'.$attention_messages.'</p>'
911 911
                         . $close
912 912
                         . '</div>';
913 913
         }
@@ -917,10 +917,10 @@  discard block
 block discarded – undo
917 917
                 ? 'error ee-status-outline ee-status-bg--error'
918 918
                 : 'error fade-away';
919 919
             // showMessage( $error_messages, TRUE );
920
-            $notices .= '<div id="' . $css_id . '" '
921
-                        . 'class="espresso-notices ' . $css_class . '" '
920
+            $notices .= '<div id="'.$css_id.'" '
921
+                        . 'class="espresso-notices '.$css_class.'" '
922 922
                         . 'style="display:none;">'
923
-                        . '<p>' . $error_messages . '</p>'
923
+                        . '<p>'.$error_messages.'</p>'
924 924
                         . $close
925 925
                         . '</div>';
926 926
         }
@@ -937,7 +937,7 @@  discard block
 block discarded – undo
937 937
      */
938 938
     private static function _print_scripts(bool $force_print = false): string
939 939
     {
940
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
940
+        if ( ! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
941 941
             if (wp_script_is('ee_error_js', 'registered')) {
942 942
                 wp_enqueue_style('espresso_default');
943 943
                 wp_enqueue_style('espresso_custom_css');
@@ -951,12 +951,12 @@  discard block
 block discarded – undo
951 951
             return '
952 952
 <script>
953 953
 /* <![CDATA[ */
954
-const ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
954
+const ee_settings = {"wp_debug":"' . WP_DEBUG.'"};
955 955
 /* ]]> */
956 956
 </script>
957
-<script src="' . includes_url() . 'js/jquery/jquery.js" type="text/javascript"></script>
958
-<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
959
-<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
957
+<script src="' . includes_url().'js/jquery/jquery.js" type="text/javascript"></script>
958
+<script src="' . EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js'.'?ver='.espresso_version().'" type="text/javascript"></script>
959
+<script src="' . EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js'.'?ver='.espresso_version().'" type="text/javascript"></script>
960 960
 ';
961 961
         }
962 962
         return '';
@@ -985,8 +985,8 @@  discard block
 block discarded – undo
985 985
     {
986 986
         $file       = explode('.', basename($file));
987 987
         $error_code = ! empty($file[0]) ? $file[0] : '';
988
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
989
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
988
+        $error_code .= ! empty($func) ? ' - '.$func : '';
989
+        $error_code .= ! empty($line) ? ' - '.$line : '';
990 990
         return $error_code;
991 991
     }
992 992
 
@@ -1005,18 +1005,18 @@  discard block
 block discarded – undo
1005 1005
         if (empty($ex)) {
1006 1006
             return;
1007 1007
         }
1008
-        if (! $time) {
1008
+        if ( ! $time) {
1009 1009
             $time = time();
1010 1010
         }
1011 1011
         $exception_log = '----------------------------------------------------------------------------------------'
1012 1012
                          . PHP_EOL;
1013
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1014
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1015
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1016
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1017
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1018
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1019
-        $exception_log .= $ex['string'] . PHP_EOL;
1013
+        $exception_log .= '['.date('Y-m-d H:i:s', $time).']  Exception Details'.PHP_EOL;
1014
+        $exception_log .= 'Message: '.$ex['msg'].PHP_EOL;
1015
+        $exception_log .= 'Code: '.$ex['code'].PHP_EOL;
1016
+        $exception_log .= 'File: '.$ex['file'].PHP_EOL;
1017
+        $exception_log .= 'Line No: '.$ex['line'].PHP_EOL;
1018
+        $exception_log .= 'Stack trace: '.PHP_EOL;
1019
+        $exception_log .= $ex['string'].PHP_EOL;
1020 1020
         $exception_log .= '----------------------------------------------------------------------------------------'
1021 1021
                           . PHP_EOL;
1022 1022
         try {
@@ -1198,17 +1198,17 @@  discard block
 block discarded – undo
1198 1198
 function espresso_error_enqueue_scripts()
1199 1199
 {
1200 1200
     // js for error handling
1201
-    if (! wp_script_is('espresso_core', 'registered')) {
1201
+    if ( ! wp_script_is('espresso_core', 'registered')) {
1202 1202
         wp_register_script(
1203 1203
             'espresso_core',
1204
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1204
+            EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js',
1205 1205
             ['jquery'],
1206 1206
             EVENT_ESPRESSO_VERSION
1207 1207
         );
1208 1208
     }
1209 1209
     wp_register_script(
1210 1210
         'ee_error_js',
1211
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1211
+        EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js',
1212 1212
         ['espresso_core'],
1213 1213
         EVENT_ESPRESSO_VERSION
1214 1214
     );
Please login to merge, or discard this patch.
core/exceptions/EntityNotFoundException.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -16,34 +16,34 @@
 block discarded – undo
16 16
  */
17 17
 class EntityNotFoundException extends UnexpectedValueException
18 18
 {
19
-    /**
20
-     * EntityNotFoundException constructor
21
-     *
22
-     * @param string         $identifier_type the name of the identifier used (ie: ID, Name, etc)
23
-     * @param string         $identifier      the actual data value used to retrieve the entity
24
-     * @param string         $message
25
-     * @param int            $code
26
-     * @param Exception|null $previous
27
-     */
28
-    #[\ReturnTypeWillChange]
29
-    public function __construct(
30
-        string $identifier_type,
31
-        string $identifier,
32
-        string $message = '',
33
-        int $code = 0,
34
-        Exception $previous =
35
-        null
36
-    ) {
37
-        if (empty($message)) {
38
-            $message = sprintf(
39
-                esc_html__(
40
-                    'The requested entity with %1$s="%2$s" was not found.',
41
-                    'event_espresso'
42
-                ),
43
-                $identifier_type,
44
-                $identifier
45
-            );
46
-        }
47
-        parent::__construct($message, $code, $previous);
48
-    }
19
+	/**
20
+	 * EntityNotFoundException constructor
21
+	 *
22
+	 * @param string         $identifier_type the name of the identifier used (ie: ID, Name, etc)
23
+	 * @param string         $identifier      the actual data value used to retrieve the entity
24
+	 * @param string         $message
25
+	 * @param int            $code
26
+	 * @param Exception|null $previous
27
+	 */
28
+	#[\ReturnTypeWillChange]
29
+	public function __construct(
30
+		string $identifier_type,
31
+		string $identifier,
32
+		string $message = '',
33
+		int $code = 0,
34
+		Exception $previous =
35
+		null
36
+	) {
37
+		if (empty($message)) {
38
+			$message = sprintf(
39
+				esc_html__(
40
+					'The requested entity with %1$s="%2$s" was not found.',
41
+					'event_espresso'
42
+				),
43
+				$identifier_type,
44
+				$identifier
45
+			);
46
+		}
47
+		parent::__construct($message, $code, $previous);
48
+	}
49 49
 }
Please login to merge, or discard this patch.
core/EE_Config.core.php 2 patches
Indentation   +3192 added lines, -3192 removed lines patch added patch discarded remove patch
@@ -18,1515 +18,1515 @@  discard block
 block discarded – undo
18 18
  */
19 19
 final class EE_Config implements ResettableInterface
20 20
 {
21
-    const OPTION_NAME = 'ee_config';
22
-
23
-    const LOG_NAME = 'ee_config_log';
24
-
25
-    const LOG_LENGTH = 100;
26
-
27
-    const ADDON_OPTION_NAMES = 'ee_config_option_names';
28
-
29
-    /**
30
-     *    instance of the EE_Config object
31
-     *
32
-     * @var    EE_Config $_instance
33
-     * @access    private
34
-     */
35
-    private static $_instance;
36
-
37
-    /**
38
-     * @var boolean $_logging_enabled
39
-     */
40
-    private static $_logging_enabled = false;
41
-
42
-    /**
43
-     * @var LegacyShortcodesManager $legacy_shortcodes_manager
44
-     */
45
-    private $legacy_shortcodes_manager;
46
-
47
-    /**
48
-     * An StdClass whose property names are addon slugs,
49
-     * and values are their config classes
50
-     *
51
-     * @var StdClass
52
-     */
53
-    public $addons;
54
-
55
-    /**
56
-     * @var EE_Admin_Config
57
-     */
58
-    public $admin;
59
-
60
-    /**
61
-     * @var EE_Core_Config
62
-     */
63
-    public $core;
64
-
65
-    /**
66
-     * @var EE_Currency_Config
67
-     */
68
-    public $currency;
69
-
70
-    /**
71
-     * @var EE_Organization_Config
72
-     */
73
-    public $organization;
74
-
75
-    /**
76
-     * @var EE_Registration_Config
77
-     */
78
-    public $registration;
79
-
80
-    /**
81
-     * @var EE_Template_Config
82
-     */
83
-    public $template_settings;
84
-
85
-    /**
86
-     * Holds EE environment values.
87
-     *
88
-     * @var EE_Environment_Config
89
-     */
90
-    public $environment;
91
-
92
-    /**
93
-     * settings pertaining to Google maps
94
-     *
95
-     * @var EE_Map_Config
96
-     */
97
-    public $map_settings;
98
-
99
-    /**
100
-     * settings pertaining to Taxes
101
-     *
102
-     * @var EE_Tax_Config
103
-     */
104
-    public $tax_settings;
105
-
106
-    /**
107
-     * Settings pertaining to global messages settings.
108
-     *
109
-     * @var EE_Messages_Config
110
-     */
111
-    public $messages;
112
-
113
-    /**
114
-     * @deprecated
115
-     * @var EE_Gateway_Config
116
-     */
117
-    public $gateway;
118
-
119
-    /**
120
-     * @var array
121
-     */
122
-    private $_addon_option_names = array();
123
-
124
-    /**
125
-     * @var array
126
-     */
127
-    private static $_module_route_map = array();
128
-
129
-    /**
130
-     * @var array
131
-     */
132
-    private static $_module_forward_map = array();
133
-
134
-    /**
135
-     * @var array
136
-     */
137
-    private static $_module_view_map = array();
138
-
139
-    /**
140
-     * @var bool
141
-     */
142
-    private static $initialized = false;
143
-
144
-
145
-    /**
146
-     * @singleton method used to instantiate class object
147
-     * @access    public
148
-     * @return EE_Config instance
149
-     */
150
-    public static function instance()
151
-    {
152
-        // check if class object is instantiated, and instantiated properly
153
-        if (! self::$_instance instanceof EE_Config) {
154
-            self::$_instance = new self();
155
-        }
156
-        return self::$_instance;
157
-    }
158
-
159
-
160
-    /**
161
-     * Resets the config
162
-     *
163
-     * @param bool    $hard_reset    if TRUE, sets EE_CONFig back to its original settings in the database. If FALSE
164
-     *                               (default) leaves the database alone, and merely resets the EE_Config object to
165
-     *                               reflect its state in the database
166
-     * @param boolean $reinstantiate if TRUE (default) call instance() and return it. Otherwise, just leave
167
-     *                               $_instance as NULL. Useful in case you want to forget about the old instance on
168
-     *                               EE_Config, but might not be ready to instantiate EE_Config currently (eg if the
169
-     *                               site was put into maintenance mode)
170
-     * @return EE_Config
171
-     */
172
-    public static function reset($hard_reset = false, $reinstantiate = true)
173
-    {
174
-        if (self::$_instance instanceof EE_Config) {
175
-            if ($hard_reset) {
176
-                self::$_instance->legacy_shortcodes_manager = null;
177
-                self::$_instance->_addon_option_names = array();
178
-                self::$_instance->_initialize_config();
179
-                self::$_instance->update_espresso_config();
180
-            }
181
-            self::$_instance->update_addon_option_names();
182
-        }
183
-        self::$_instance = null;
184
-        self::$initialized = false;
185
-        // we don't need to reset the static properties imo because those should
186
-        // only change when a module is added or removed. Currently we don't
187
-        // support removing a module during a request when it previously existed
188
-        if ($reinstantiate) {
189
-            return self::instance();
190
-        } else {
191
-            return null;
192
-        }
193
-    }
194
-
195
-
196
-    private function __construct()
197
-    {
198
-        if (self::$initialized) {
199
-            return;
200
-        }
201
-        self::$initialized = true;
202
-        do_action('AHEE__EE_Config__construct__begin', $this);
203
-        EE_Config::$_logging_enabled = apply_filters('FHEE__EE_Config___construct__logging_enabled', false);
204
-        // setup empty config classes
205
-        $this->_initialize_config();
206
-        // load existing EE site settings
207
-        $this->_load_core_config();
208
-        // confirm everything loaded correctly and set filtered defaults if not
209
-        $this->_verify_config();
210
-        //  register shortcodes and modules
211
-        add_action(
212
-            'AHEE__EE_System__register_shortcodes_modules_and_widgets',
213
-            [$this, 'register_shortcodes_and_modules'],
214
-            999
215
-        );
216
-        //  initialize shortcodes and modules
217
-        add_action('AHEE__EE_System__core_loaded_and_ready', [$this, 'initialize_shortcodes_and_modules']);
218
-        // register widgets
219
-        add_action('widgets_init', [$this, 'widgets_init'], 10);
220
-        // shutdown
221
-        add_action('shutdown', [$this, 'shutdown'], 10);
222
-        // construct__end hook
223
-        do_action('AHEE__EE_Config__construct__end', $this);
224
-        // hardcoded hack
225
-        $this->template_settings->current_espresso_theme = 'Espresso_Arabica_2014';
226
-    }
227
-
228
-
229
-    /**
230
-     * @return boolean
231
-     */
232
-    public static function logging_enabled()
233
-    {
234
-        return self::$_logging_enabled;
235
-    }
236
-
237
-
238
-    /**
239
-     * use to get the current theme if needed from static context
240
-     *
241
-     * @return string current theme set.
242
-     */
243
-    public static function get_current_theme()
244
-    {
245
-        return self::$_instance->template_settings->current_espresso_theme ?? 'Espresso_Arabica_2014';
246
-    }
247
-
248
-
249
-    /**
250
-     *        _initialize_config
251
-     *
252
-     * @access private
253
-     * @return void
254
-     */
255
-    private function _initialize_config()
256
-    {
257
-        EE_Config::trim_log();
258
-        // set defaults
259
-        $this->_addon_option_names = get_option(EE_Config::ADDON_OPTION_NAMES, array());
260
-        $this->addons = new stdClass();
261
-        // set _module_route_map
262
-        EE_Config::$_module_route_map = array();
263
-        // set _module_forward_map
264
-        EE_Config::$_module_forward_map = array();
265
-        // set _module_view_map
266
-        EE_Config::$_module_view_map = array();
267
-    }
268
-
269
-
270
-    /**
271
-     *        load core plugin configuration
272
-     *
273
-     * @access private
274
-     * @return void
275
-     */
276
-    private function _load_core_config()
277
-    {
278
-        // load_core_config__start hook
279
-        do_action('AHEE__EE_Config___load_core_config__start', $this);
280
-        $espresso_config = (array) $this->get_espresso_config();
281
-        // need to move the "addons" element to the end of the config array
282
-        // in case an addon config references one of the other config classes
283
-        $addons = $espresso_config['addons'] ?? new StdClass();
284
-        unset($espresso_config['addons']);
285
-        $espresso_config['addons'] = $addons;
286
-        foreach ($espresso_config as $config => $settings) {
287
-            // load_core_config__start hook
288
-            $settings = apply_filters(
289
-                'FHEE__EE_Config___load_core_config__config_settings',
290
-                $settings,
291
-                $config,
292
-                $this
293
-            );
294
-            if (is_object($settings) && property_exists($this, $config)) {
295
-                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
296
-                // call configs populate method to ensure any defaults are set for empty values.
297
-                if (method_exists($settings, 'populate')) {
298
-                    $this->{$config}->populate();
299
-                }
300
-                if (method_exists($settings, 'do_hooks')) {
301
-                    $this->{$config}->do_hooks();
302
-                }
303
-            }
304
-        }
305
-        if (apply_filters('FHEE__EE_Config___load_core_config__update_espresso_config', false)) {
306
-            $this->update_espresso_config();
307
-        }
308
-        // load_core_config__end hook
309
-        do_action('AHEE__EE_Config___load_core_config__end', $this);
310
-    }
311
-
312
-
313
-    /**
314
-     *    _verify_config
315
-     *
316
-     * @access    protected
317
-     * @return    void
318
-     */
319
-    protected function _verify_config()
320
-    {
321
-        $this->core = $this->core instanceof EE_Core_Config
322
-            ? $this->core
323
-            : new EE_Core_Config();
324
-        $this->core = apply_filters('FHEE__EE_Config___initialize_config__core', $this->core);
325
-        $this->organization = $this->organization instanceof EE_Organization_Config
326
-            ? $this->organization
327
-            : new EE_Organization_Config();
328
-        $this->organization = apply_filters(
329
-            'FHEE__EE_Config___initialize_config__organization',
330
-            $this->organization
331
-        );
332
-        $this->currency = $this->currency instanceof EE_Currency_Config
333
-            ? $this->currency
334
-            : new EE_Currency_Config();
335
-        $this->currency = apply_filters('FHEE__EE_Config___initialize_config__currency', $this->currency);
336
-        $this->registration = $this->registration instanceof EE_Registration_Config
337
-            ? $this->registration
338
-            : new EE_Registration_Config();
339
-        $this->registration = apply_filters(
340
-            'FHEE__EE_Config___initialize_config__registration',
341
-            $this->registration
342
-        );
343
-        $this->admin = $this->admin instanceof EE_Admin_Config
344
-            ? $this->admin
345
-            : new EE_Admin_Config();
346
-        $this->admin = apply_filters('FHEE__EE_Config___initialize_config__admin', $this->admin);
347
-        $this->template_settings = $this->template_settings instanceof EE_Template_Config
348
-            ? $this->template_settings
349
-            : new EE_Template_Config();
350
-        $this->template_settings = apply_filters(
351
-            'FHEE__EE_Config___initialize_config__template_settings',
352
-            $this->template_settings
353
-        );
354
-        $this->map_settings = $this->map_settings instanceof EE_Map_Config
355
-            ? $this->map_settings
356
-            : new EE_Map_Config();
357
-        $this->map_settings = apply_filters(
358
-            'FHEE__EE_Config___initialize_config__map_settings',
359
-            $this->map_settings
360
-        );
361
-        $this->environment = $this->environment instanceof EE_Environment_Config
362
-            ? $this->environment
363
-            : new EE_Environment_Config();
364
-        $this->environment = apply_filters(
365
-            'FHEE__EE_Config___initialize_config__environment',
366
-            $this->environment
367
-        );
368
-        $this->tax_settings = $this->tax_settings instanceof EE_Tax_Config
369
-            ? $this->tax_settings
370
-            : new EE_Tax_Config();
371
-        $this->tax_settings = apply_filters(
372
-            'FHEE__EE_Config___initialize_config__tax_settings',
373
-            $this->tax_settings
374
-        );
375
-        $this->messages = apply_filters('FHEE__EE_Config__initialize_config__messages', $this->messages);
376
-        $this->messages = $this->messages instanceof EE_Messages_Config
377
-            ? $this->messages
378
-            : new EE_Messages_Config();
379
-        $this->gateway = $this->gateway instanceof EE_Gateway_Config
380
-            ? $this->gateway
381
-            : new EE_Gateway_Config();
382
-        $this->gateway = apply_filters('FHEE__EE_Config___initialize_config__gateway', $this->gateway);
383
-        $this->legacy_shortcodes_manager = null;
384
-    }
385
-
386
-
387
-    /**
388
-     *    get_espresso_config
389
-     *
390
-     * @access    public
391
-     * @return    array of espresso config stuff
392
-     */
393
-    public function get_espresso_config()
394
-    {
395
-        // grab espresso configuration
396
-        return apply_filters(
397
-            'FHEE__EE_Config__get_espresso_config__CFG',
398
-            get_option(EE_Config::OPTION_NAME, array())
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     *    double_check_config_comparison
405
-     *
406
-     * @access    public
407
-     * @param string $option
408
-     * @param        $old_value
409
-     * @param        $value
410
-     */
411
-    public function double_check_config_comparison($option, $old_value, $value)
412
-    {
413
-        // make sure we're checking the ee config
414
-        if ($option === EE_Config::OPTION_NAME) {
415
-            // run a loose comparison of the old value against the new value for type and properties,
416
-            // but NOT exact instance like WP update_option does (ie: NOT type safe comparison)
417
-            if ($value != $old_value) {
418
-                // if they are NOT the same, then remove the hook,
419
-                // which means the subsequent update results will be based solely on the update query results
420
-                // the reason we do this is because, as stated above,
421
-                // WP update_option performs an exact instance comparison (===) on any update values passed to it
422
-                // this happens PRIOR to serialization and any subsequent update.
423
-                // If values are found to match their previous old value,
424
-                // then WP bails before performing any update.
425
-                // Since we are passing the EE_Config object, it is comparing the EXACT instance of the saved version
426
-                // it just pulled from the db, with the one being passed to it (which will not match).
427
-                // HOWEVER, once the object is serialized and passed off to MySQL to update,
428
-                // MySQL MAY ALSO NOT perform the update because
429
-                // the string it sees in the db looks the same as the new one it has been passed!!!
430
-                // This results in the query returning an "affected rows" value of ZERO,
431
-                // which gets returned immediately by WP update_option and looks like an error.
432
-                remove_action('update_option', array($this, 'check_config_updated'));
433
-            }
434
-        }
435
-    }
436
-
437
-
438
-    /**
439
-     *    update_espresso_config
440
-     *
441
-     * @access   public
442
-     */
443
-    protected function _reset_espresso_addon_config()
444
-    {
445
-        $this->_addon_option_names = array();
446
-        foreach ($this->addons as $addon_name => $addon_config_obj) {
447
-            $addon_config_obj = maybe_unserialize($addon_config_obj);
448
-            if ($addon_config_obj instanceof EE_Config_Base) {
449
-                $this->update_config('addons', $addon_name, $addon_config_obj, false);
450
-            }
451
-            $this->addons->{$addon_name} = null;
452
-        }
453
-    }
454
-
455
-
456
-    /**
457
-     *    update_espresso_config
458
-     *
459
-     * @access   public
460
-     * @param   bool $add_success
461
-     * @param   bool $add_error
462
-     * @return   bool
463
-     */
464
-    public function update_espresso_config($add_success = false, $add_error = true)
465
-    {
466
-        // don't allow config updates during WP heartbeats
467
-        /** @var RequestInterface $request */
468
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
469
-        if ($request->isWordPressHeartbeat()) {
470
-            return false;
471
-        }
472
-        // commented out the following re: https://events.codebasehq.com/projects/event-espresso/tickets/8197
473
-        // $clone = clone( self::$_instance );
474
-        // self::$_instance = NULL;
475
-        do_action('AHEE__EE_Config__update_espresso_config__begin', $this);
476
-        $this->_reset_espresso_addon_config();
477
-        // hook into update_option because that happens AFTER the ( $value === $old_value ) conditional
478
-        // but BEFORE the actual update occurs
479
-        add_action('update_option', array($this, 'double_check_config_comparison'), 1, 3);
480
-        // don't want to persist legacy_shortcodes_manager, but don't want to lose it either
481
-        $legacy_shortcodes_manager = $this->legacy_shortcodes_manager;
482
-        $this->legacy_shortcodes_manager = null;
483
-        // now update "ee_config"
484
-        $saved = update_option(EE_Config::OPTION_NAME, $this);
485
-        $this->legacy_shortcodes_manager = $legacy_shortcodes_manager;
486
-        EE_Config::log(EE_Config::OPTION_NAME);
487
-        // if not saved... check if the hook we just added still exists;
488
-        // if it does, it means one of two things:
489
-        // that update_option bailed at the($value === $old_value) conditional,
490
-        // or...
491
-        // the db update query returned 0 rows affected
492
-        // (probably because the data  value was the same from it's perspective)
493
-        // so the existence of the hook means that a negative result from update_option is NOT an error,
494
-        // but just means no update occurred, so don't display an error to the user.
495
-        // BUT... if update_option returns FALSE, AND the hook is missing,
496
-        // then it means that something truly went wrong
497
-        $saved = ! $saved ? has_action('update_option', array($this, 'double_check_config_comparison')) : $saved;
498
-        // remove our action since we don't want it in the system anymore
499
-        remove_action('update_option', array($this, 'double_check_config_comparison'), 1);
500
-        do_action('AHEE__EE_Config__update_espresso_config__end', $this, $saved);
501
-        // self::$_instance = $clone;
502
-        // unset( $clone );
503
-        // if config remains the same or was updated successfully
504
-        if ($saved) {
505
-            if ($add_success) {
506
-                EE_Error::add_success(
507
-                    esc_html__('The Event Espresso Configuration Settings have been successfully updated.', 'event_espresso'),
508
-                    __FILE__,
509
-                    __FUNCTION__,
510
-                    __LINE__
511
-                );
512
-            }
513
-            return true;
514
-        } else {
515
-            if ($add_error) {
516
-                EE_Error::add_error(
517
-                    esc_html__('The Event Espresso Configuration Settings were not updated.', 'event_espresso'),
518
-                    __FILE__,
519
-                    __FUNCTION__,
520
-                    __LINE__
521
-                );
522
-            }
523
-            return false;
524
-        }
525
-    }
526
-
527
-
528
-    /**
529
-     *    _verify_config_params
530
-     *
531
-     * @access    private
532
-     * @param    string         $section
533
-     * @param    string         $name
534
-     * @param    string         $config_class
535
-     * @param    EE_Config_Base $config_obj
536
-     * @param    array          $tests_to_run
537
-     * @param    bool           $display_errors
538
-     * @return    bool    TRUE on success, FALSE on fail
539
-     */
540
-    private function _verify_config_params(
541
-        $section = '',
542
-        $name = '',
543
-        $config_class = '',
544
-        $config_obj = null,
545
-        $tests_to_run = array(1, 2, 3, 4, 5, 6, 7, 8),
546
-        $display_errors = true
547
-    ) {
548
-        try {
549
-            foreach ($tests_to_run as $test) {
550
-                switch ($test) {
551
-                    // TEST #1 : check that section was set
552
-                    case 1:
553
-                        if (empty($section)) {
554
-                            if ($display_errors) {
555
-                                throw new EE_Error(
556
-                                    sprintf(
557
-                                        esc_html__(
558
-                                            'No configuration section has been provided while attempting to save "%s".',
559
-                                            'event_espresso'
560
-                                        ),
561
-                                        $config_class
562
-                                    )
563
-                                );
564
-                            }
565
-                            return false;
566
-                        }
567
-                        break;
568
-                    // TEST #2 : check that settings section exists
569
-                    case 2:
570
-                        if (! isset($this->{$section})) {
571
-                            if ($display_errors) {
572
-                                throw new EE_Error(
573
-                                    sprintf(
574
-                                        esc_html__('The "%s" configuration section does not exist.', 'event_espresso'),
575
-                                        $section
576
-                                    )
577
-                                );
578
-                            }
579
-                            return false;
580
-                        }
581
-                        break;
582
-                    // TEST #3 : check that section is the proper format
583
-                    case 3:
584
-                        if (
585
-                            ! ($this->{$section} instanceof EE_Config_Base || $this->{$section} instanceof stdClass)
586
-                        ) {
587
-                            if ($display_errors) {
588
-                                throw new EE_Error(
589
-                                    sprintf(
590
-                                        esc_html__(
591
-                                            'The "%s" configuration settings have not been formatted correctly.',
592
-                                            'event_espresso'
593
-                                        ),
594
-                                        $section
595
-                                    )
596
-                                );
597
-                            }
598
-                            return false;
599
-                        }
600
-                        break;
601
-                    // TEST #4 : check that config section name has been set
602
-                    case 4:
603
-                        if (empty($name)) {
604
-                            if ($display_errors) {
605
-                                throw new EE_Error(
606
-                                    esc_html__(
607
-                                        'No name has been provided for the specific configuration section.',
608
-                                        'event_espresso'
609
-                                    )
610
-                                );
611
-                            }
612
-                            return false;
613
-                        }
614
-                        break;
615
-                    // TEST #5 : check that a config class name has been set
616
-                    case 5:
617
-                        if (empty($config_class)) {
618
-                            if ($display_errors) {
619
-                                throw new EE_Error(
620
-                                    esc_html__(
621
-                                        'No class name has been provided for the specific configuration section.',
622
-                                        'event_espresso'
623
-                                    )
624
-                                );
625
-                            }
626
-                            return false;
627
-                        }
628
-                        break;
629
-                    // TEST #6 : verify config class is accessible
630
-                    case 6:
631
-                        if (! class_exists($config_class)) {
632
-                            if ($display_errors) {
633
-                                throw new EE_Error(
634
-                                    sprintf(
635
-                                        esc_html__(
636
-                                            'The "%s" class does not exist. Please ensure that an autoloader has been set for it.',
637
-                                            'event_espresso'
638
-                                        ),
639
-                                        $config_class
640
-                                    )
641
-                                );
642
-                            }
643
-                            return false;
644
-                        }
645
-                        break;
646
-                    // TEST #7 : check that config has even been set
647
-                    case 7:
648
-                        if (! isset($this->{$section}->{$name})) {
649
-                            if ($display_errors) {
650
-                                throw new EE_Error(
651
-                                    sprintf(
652
-                                        esc_html__('No configuration has been set for "%1$s->%2$s".', 'event_espresso'),
653
-                                        $section,
654
-                                        $name
655
-                                    )
656
-                                );
657
-                            }
658
-                            return false;
659
-                        } else {
660
-                            // and make sure it's not serialized
661
-                            $this->{$section}->{$name} = maybe_unserialize($this->{$section}->{$name});
662
-                        }
663
-                        break;
664
-                    // TEST #8 : check that config is the requested type
665
-                    case 8:
666
-                        if (! $this->{$section}->{$name} instanceof $config_class) {
667
-                            if ($display_errors) {
668
-                                throw new EE_Error(
669
-                                    sprintf(
670
-                                        esc_html__(
671
-                                            'The configuration for "%1$s->%2$s" is not of the "%3$s" class.',
672
-                                            'event_espresso'
673
-                                        ),
674
-                                        $section,
675
-                                        $name,
676
-                                        $config_class
677
-                                    )
678
-                                );
679
-                            }
680
-                            return false;
681
-                        }
682
-                        break;
683
-                    // TEST #9 : verify config object
684
-                    case 9:
685
-                        if (! $config_obj instanceof EE_Config_Base) {
686
-                            if ($display_errors) {
687
-                                throw new EE_Error(
688
-                                    sprintf(
689
-                                        esc_html__('The "%s" class is not an instance of EE_Config_Base.', 'event_espresso'),
690
-                                        print_r($config_obj, true)
691
-                                    )
692
-                                );
693
-                            }
694
-                            return false;
695
-                        }
696
-                        break;
697
-                }
698
-            }
699
-        } catch (EE_Error $e) {
700
-            $e->get_error();
701
-        }
702
-        // you have successfully run the gauntlet
703
-        return true;
704
-    }
705
-
706
-
707
-    /**
708
-     *    _generate_config_option_name
709
-     *
710
-     * @access        protected
711
-     * @param        string $section
712
-     * @param        string $name
713
-     * @return        string
714
-     */
715
-    private function _generate_config_option_name($section = '', $name = '')
716
-    {
717
-        return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
718
-    }
719
-
720
-
721
-    /**
722
-     *    _set_config_class
723
-     * ensures that a config class is set, either from a passed config class or one generated from the config name
724
-     *
725
-     * @access    private
726
-     * @param    string $config_class
727
-     * @param    string $name
728
-     * @return    string
729
-     */
730
-    private function _set_config_class($config_class = '', $name = '')
731
-    {
732
-        return ! empty($config_class)
733
-            ? $config_class
734
-            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
735
-    }
736
-
737
-
738
-    /**
739
-     * @param string              $section
740
-     * @param string              $name
741
-     * @param string              $config_class
742
-     * @param EE_Config_Base|null $config_obj
743
-     * @return EE_Config_Base
744
-     */
745
-    public function set_config(
746
-        string $section = '',
747
-        string $name = '',
748
-        string $config_class = '',
749
-        EE_Config_Base $config_obj = null
750
-    ): ?EE_Config_Base {
751
-        // ensure config class is set to something
752
-        $config_class = $this->_set_config_class($config_class, $name);
753
-        // run tests 1-4, 6, and 7 to verify all config params are set and valid
754
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
755
-            return null;
756
-        }
757
-        $config_option_name = $this->_generate_config_option_name($section, $name);
758
-        // if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
759
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
760
-            $this->_addon_option_names[ $config_option_name ] = $config_class;
761
-            $this->update_addon_option_names();
762
-        }
763
-        // verify the incoming config object but suppress errors
764
-        if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
765
-            $config_obj = new $config_class();
766
-        }
767
-        if (get_option($config_option_name)) {
768
-            EE_Config::log($config_option_name);
769
-            try {
770
-                update_option($config_option_name, $config_obj);
771
-            } catch (Exception $exception) {
772
-                throw new DomainException(
773
-                    sprintf(
774
-                        esc_html__(
775
-                            'The following exception occurred while attempting to update the "%1$s" class for config section "%2$s->%3$s": %4$s',
776
-                            'event_espresso'
777
-                        ),
778
-                        $config_class,
779
-                        $section,
780
-                        $name,
781
-                        $exception->getMessage()
782
-                    )
783
-                );
784
-            }
785
-            $this->{$section}->{$name} = $config_obj;
786
-            return $this->{$section}->{$name};
787
-        } else {
788
-            // create a wp-option for this config
789
-            if (add_option($config_option_name, $config_obj, '', 'no')) {
790
-                $this->{$section}->{$name} = maybe_unserialize($config_obj);
791
-                return $this->{$section}->{$name};
792
-            } else {
793
-                EE_Error::add_error(
794
-                    sprintf(esc_html__('The "%s" could not be saved to the database.', 'event_espresso'), $config_class),
795
-                    __FILE__,
796
-                    __FUNCTION__,
797
-                    __LINE__
798
-                );
799
-                return null;
800
-            }
801
-        }
802
-    }
803
-
804
-
805
-    /**
806
-     *    update_config
807
-     * Important: the config object must ALREADY be set, otherwise this will produce an error.
808
-     *
809
-     * @access    public
810
-     * @param    string                $section
811
-     * @param    string                $name
812
-     * @param    EE_Config_Base|string $config_obj
813
-     * @param    bool                  $throw_errors
814
-     * @return    bool
815
-     */
816
-    public function update_config($section = '', $name = '', $config_obj = '', $throw_errors = true)
817
-    {
818
-        // don't allow config updates during WP heartbeats
819
-        /** @var RequestInterface $request */
820
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
821
-        if ($request->isWordPressHeartbeat()) {
822
-            return false;
823
-        }
824
-        $config_obj = maybe_unserialize($config_obj);
825
-        // get class name of the incoming object
826
-        $config_class = get_class($config_obj);
827
-        // run tests 1-5 and 9 to verify config
828
-        if (
829
-            ! $this->_verify_config_params(
830
-                $section,
831
-                $name,
832
-                $config_class,
833
-                $config_obj,
834
-                array(1, 2, 3, 4, 7, 9)
835
-            )
836
-        ) {
837
-            return false;
838
-        }
839
-        $config_option_name = $this->_generate_config_option_name($section, $name);
840
-        // check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
841
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
842
-            // save new config to db
843
-            if ($this->set_config($section, $name, $config_class, $config_obj)) {
844
-                return true;
845
-            }
846
-        } else {
847
-            // first check if the record already exists
848
-            $existing_config = get_option($config_option_name);
849
-            $config_obj = serialize($config_obj);
850
-            // just return if db record is already up to date (NOT type safe comparison)
851
-            if ($existing_config == $config_obj) {
852
-                $this->{$section}->{$name} = $config_obj;
853
-                return true;
854
-            } elseif (update_option($config_option_name, $config_obj)) {
855
-                EE_Config::log($config_option_name);
856
-                // update wp-option for this config class
857
-                $this->{$section}->{$name} = $config_obj;
858
-                return true;
859
-            } elseif ($throw_errors) {
860
-                EE_Error::add_error(
861
-                    sprintf(
862
-                        esc_html__(
863
-                            'The "%1$s" object stored at"%2$s" was not successfully updated in the database.',
864
-                            'event_espresso'
865
-                        ),
866
-                        $config_class,
867
-                        'EE_Config->' . $section . '->' . $name
868
-                    ),
869
-                    __FILE__,
870
-                    __FUNCTION__,
871
-                    __LINE__
872
-                );
873
-            }
874
-        }
875
-        return false;
876
-    }
877
-
878
-
879
-    /**
880
-     *    get_config
881
-     *
882
-     * @access    public
883
-     * @param    string $section
884
-     * @param    string $name
885
-     * @param    string $config_class
886
-     * @return    mixed EE_Config_Base | NULL
887
-     */
888
-    public function get_config($section = '', $name = '', $config_class = '')
889
-    {
890
-        // ensure config class is set to something
891
-        $config_class = $this->_set_config_class($config_class, $name);
892
-        // run tests 1-4, 6 and 7 to verify that all params have been set
893
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
894
-            return null;
895
-        }
896
-        // now test if the requested config object exists, but suppress errors
897
-        if ($this->_verify_config_params($section, $name, $config_class, null, array(7, 8), false)) {
898
-            // config already exists, so pass it back
899
-            return $this->{$section}->{$name};
900
-        }
901
-        // load config option from db if it exists
902
-        $config_obj = $this->get_config_option($this->_generate_config_option_name($section, $name));
903
-        // verify the newly retrieved config object, but suppress errors
904
-        if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
905
-            // config is good, so set it and pass it back
906
-            $this->{$section}->{$name} = $config_obj;
907
-            return $this->{$section}->{$name};
908
-        }
909
-        // oops! $config_obj is not already set and does not exist in the db, so create a new one
910
-        $config_obj = $this->set_config($section, $name, $config_class);
911
-        // verify the newly created config object
912
-        if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9))) {
913
-            return $this->{$section}->{$name};
914
-        } else {
915
-            EE_Error::add_error(
916
-                sprintf(esc_html__('The "%s" could not be retrieved from the database.', 'event_espresso'), $config_class),
917
-                __FILE__,
918
-                __FUNCTION__,
919
-                __LINE__
920
-            );
921
-        }
922
-        return null;
923
-    }
924
-
925
-
926
-    /**
927
-     *    get_config_option
928
-     *
929
-     * @access    public
930
-     * @param    string $config_option_name
931
-     * @return    mixed EE_Config_Base | FALSE
932
-     */
933
-    public function get_config_option($config_option_name = '')
934
-    {
935
-        // retrieve the wp-option for this config class.
936
-        $config_option = maybe_unserialize(get_option($config_option_name, array()));
937
-        if (empty($config_option)) {
938
-            EE_Config::log($config_option_name . '-NOT-FOUND');
939
-        }
940
-        return $config_option;
941
-    }
942
-
943
-
944
-    /**
945
-     * log
946
-     *
947
-     * @param string $config_option_name
948
-     */
949
-    public static function log($config_option_name = '')
950
-    {
951
-        if (EE_Config::logging_enabled() && ! empty($config_option_name)) {
952
-            $config_log = get_option(EE_Config::LOG_NAME, array());
953
-            /** @var RequestParams $request */
954
-            $request = LoaderFactory::getLoader()->getShared(RequestParams::class);
955
-            $config_log[ (string) microtime(true) ] = array(
956
-                'config_name' => $config_option_name,
957
-                'request'     => $request->requestParams(),
958
-            );
959
-            update_option(EE_Config::LOG_NAME, $config_log);
960
-        }
961
-    }
962
-
963
-
964
-    /**
965
-     * trim_log
966
-     * reduces the size of the config log to the length specified by EE_Config::LOG_LENGTH
967
-     */
968
-    public static function trim_log()
969
-    {
970
-        if (! EE_Config::logging_enabled()) {
971
-            return;
972
-        }
973
-        $config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
974
-        $log_length = count($config_log);
975
-        if ($log_length > EE_Config::LOG_LENGTH) {
976
-            ksort($config_log);
977
-            $config_log = array_slice($config_log, $log_length - EE_Config::LOG_LENGTH, null, true);
978
-            update_option(EE_Config::LOG_NAME, $config_log);
979
-        }
980
-    }
981
-
982
-
983
-    /**
984
-     *    get_page_for_posts
985
-     *    if the wp-option "show_on_front" is set to "page", then this is the post_name for the post set in the
986
-     *    wp-option "page_for_posts", or "posts" if no page is selected
987
-     *
988
-     * @access    public
989
-     * @return    string
990
-     */
991
-    public static function get_page_for_posts()
992
-    {
993
-        $page_for_posts = get_option('page_for_posts');
994
-        if (! $page_for_posts) {
995
-            return 'posts';
996
-        }
997
-        global $wpdb;
998
-        $SQL = "SELECT post_name from $wpdb->posts WHERE post_type='posts' OR post_type='page' AND post_status='publish' AND ID=%d";
999
-        return $wpdb->get_var($wpdb->prepare($SQL, $page_for_posts));
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     *    register_shortcodes_and_modules.
1005
-     *    At this point, it's too early to tell if we're maintenance mode or not.
1006
-     *    In fact, this is where we give modules a chance to let core know they exist
1007
-     *    so they can help trigger maintenance mode if it's needed
1008
-     *
1009
-     * @access    public
1010
-     * @return    void
1011
-     */
1012
-    public function register_shortcodes_and_modules()
1013
-    {
1014
-        // allow modules to set hooks for the rest of the system
1015
-        EE_Registry::instance()->modules = $this->_register_modules();
1016
-    }
1017
-
1018
-
1019
-    /**
1020
-     *    initialize_shortcodes_and_modules
1021
-     *    meaning they can start adding their hooks to get stuff done
1022
-     *
1023
-     * @access    public
1024
-     * @return    void
1025
-     */
1026
-    public function initialize_shortcodes_and_modules()
1027
-    {
1028
-        // allow modules to set hooks for the rest of the system
1029
-        $this->_initialize_modules();
1030
-    }
1031
-
1032
-
1033
-    /**
1034
-     *    widgets_init
1035
-     *
1036
-     * @access private
1037
-     * @return void
1038
-     */
1039
-    public function widgets_init()
1040
-    {
1041
-        // only init widgets on admin pages when not in complete maintenance, and
1042
-        // on frontend when not in any maintenance mode
1043
-        if (
1044
-            ! EE_Maintenance_Mode::instance()->level()
1045
-            || (
1046
-                is_admin()
1047
-                && EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
1048
-            )
1049
-        ) {
1050
-            // grab list of installed widgets
1051
-            $widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1052
-            // filter list of modules to register
1053
-            $widgets_to_register = apply_filters(
1054
-                'FHEE__EE_Config__register_widgets__widgets_to_register',
1055
-                $widgets_to_register
1056
-            );
1057
-            if (! empty($widgets_to_register)) {
1058
-                // cycle thru widget folders
1059
-                foreach ($widgets_to_register as $widget_path) {
1060
-                    // add to list of installed widget modules
1061
-                    EE_Config::register_ee_widget($widget_path);
1062
-                }
1063
-            }
1064
-            // filter list of installed modules
1065
-            EE_Registry::instance()->widgets = apply_filters(
1066
-                'FHEE__EE_Config__register_widgets__installed_widgets',
1067
-                EE_Registry::instance()->widgets
1068
-            );
1069
-        }
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     *    register_ee_widget - makes core aware of this widget
1075
-     *
1076
-     * @access    public
1077
-     * @param    string $widget_path - full path up to and including widget folder
1078
-     * @return    void
1079
-     */
1080
-    public static function register_ee_widget($widget_path = null)
1081
-    {
1082
-        do_action('AHEE__EE_Config__register_widget__begin', $widget_path);
1083
-        $widget_ext = '.widget.php';
1084
-        // make all separators match
1085
-        $widget_path = rtrim(str_replace('\\', DS, $widget_path), DS);
1086
-        // does the file path INCLUDE the actual file name as part of the path ?
1087
-        if (strpos($widget_path, $widget_ext) !== false) {
1088
-            // grab and shortcode file name from directory name and break apart at dots
1089
-            $file_name = explode('.', basename($widget_path));
1090
-            // take first segment from file name pieces and remove class prefix if it exists
1091
-            $widget = strpos($file_name[0], 'EEW_') === 0 ? substr($file_name[0], 4) : $file_name[0];
1092
-            // sanitize shortcode directory name
1093
-            $widget = sanitize_key($widget);
1094
-            // now we need to rebuild the shortcode path
1095
-            $widget_path = explode('/', $widget_path);
1096
-            // remove last segment
1097
-            array_pop($widget_path);
1098
-            // glue it back together
1099
-            $widget_path = implode(DS, $widget_path);
1100
-        } else {
1101
-            // grab and sanitize widget directory name
1102
-            $widget = sanitize_key(basename($widget_path));
1103
-        }
1104
-        // create classname from widget directory name
1105
-        $widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1106
-        // add class prefix
1107
-        $widget_class = 'EEW_' . $widget;
1108
-        // does the widget exist ?
1109
-        if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1110
-            $msg = sprintf(
1111
-                esc_html__(
1112
-                    'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1113
-                    'event_espresso'
1114
-                ),
1115
-                $widget_class,
1116
-                $widget_path . '/' . $widget_class . $widget_ext
1117
-            );
1118
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1119
-            return;
1120
-        }
1121
-        // load the widget class file
1122
-        require_once($widget_path . '/' . $widget_class . $widget_ext);
1123
-        // verify that class exists
1124
-        if (! class_exists($widget_class)) {
1125
-            $msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1126
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1127
-            return;
1128
-        }
1129
-        register_widget($widget_class);
1130
-        // add to array of registered widgets
1131
-        EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     *        _register_modules
1137
-     *
1138
-     * @access private
1139
-     * @return array
1140
-     */
1141
-    private function _register_modules()
1142
-    {
1143
-        // grab list of installed modules
1144
-        $modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1145
-        // filter list of modules to register
1146
-        $modules_to_register = apply_filters(
1147
-            'FHEE__EE_Config__register_modules__modules_to_register',
1148
-            $modules_to_register
1149
-        );
1150
-        if (! empty($modules_to_register)) {
1151
-            // loop through folders
1152
-            foreach ($modules_to_register as $module_path) {
1153
-                /**TEMPORARILY EXCLUDE gateways from modules for time being**/
1154
-                if (
1155
-                    $module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1156
-                    && $module_path !== EE_MODULES . 'gateways'
1157
-                ) {
1158
-                    // add to list of installed modules
1159
-                    EE_Config::register_module($module_path);
1160
-                }
1161
-            }
1162
-        }
1163
-        // filter list of installed modules
1164
-        return apply_filters(
1165
-            'FHEE__EE_Config___register_modules__installed_modules',
1166
-            EE_Registry::instance()->modules
1167
-        );
1168
-    }
1169
-
1170
-
1171
-    /**
1172
-     *    register_module - makes core aware of this module
1173
-     *
1174
-     * @access    public
1175
-     * @param    string $module_path - full path up to and including module folder
1176
-     * @return    bool
1177
-     */
1178
-    public static function register_module($module_path = null)
1179
-    {
1180
-        do_action('AHEE__EE_Config__register_module__begin', $module_path);
1181
-        $module_ext = '.module.php';
1182
-        // make all separators match
1183
-        $module_path = str_replace(array('\\', '/'), '/', $module_path);
1184
-        // does the file path INCLUDE the actual file name as part of the path ?
1185
-        if (strpos($module_path, $module_ext) !== false) {
1186
-            // grab and shortcode file name from directory name and break apart at dots
1187
-            $module_file = explode('.', basename($module_path));
1188
-            // now we need to rebuild the shortcode path
1189
-            $module_path = explode('/', $module_path);
1190
-            // remove last segment
1191
-            array_pop($module_path);
1192
-            // glue it back together
1193
-            $module_path = implode('/', $module_path) . '/';
1194
-            // take first segment from file name pieces and sanitize it
1195
-            $module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1196
-            // ensure class prefix is added
1197
-            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1198
-        } else {
1199
-            // we need to generate the filename based off of the folder name
1200
-            // grab and sanitize module name
1201
-            $module = strtolower(basename($module_path));
1202
-            $module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1203
-            // like trailingslashit()
1204
-            $module_path = rtrim($module_path, '/') . '/';
1205
-            // create classname from module directory name
1206
-            $module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1207
-            // add class prefix
1208
-            $module_class = 'EED_' . $module;
1209
-        }
1210
-        // does the module exist ?
1211
-        if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1212
-            $msg = sprintf(
1213
-                esc_html__(
1214
-                    'The requested %s module file could not be found or is not readable due to file permissions.',
1215
-                    'event_espresso'
1216
-                ),
1217
-                $module
1218
-            );
1219
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1220
-            return false;
1221
-        }
1222
-        // load the module class file
1223
-        require_once($module_path . $module_class . $module_ext);
1224
-        // verify that class exists
1225
-        if (! class_exists($module_class)) {
1226
-            $msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1227
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1228
-            return false;
1229
-        }
1230
-        // add to array of registered modules
1231
-        EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1232
-        do_action(
1233
-            'AHEE__EE_Config__register_module__complete',
1234
-            $module_class,
1235
-            EE_Registry::instance()->modules->{$module_class}
1236
-        );
1237
-        return true;
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     *    _initialize_modules
1243
-     *    allow modules to set hooks for the rest of the system
1244
-     *
1245
-     * @access private
1246
-     * @return void
1247
-     */
1248
-    private function _initialize_modules()
1249
-    {
1250
-        // cycle thru shortcode folders
1251
-        foreach (EE_Registry::instance()->modules as $module_class => $module_path) {
1252
-            // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
1253
-            // which set hooks ?
1254
-            if (is_admin() && is_callable([$module_class, 'set_hooks_admin'])) {
1255
-                // fire immediately
1256
-                call_user_func([$module_class, 'set_hooks_admin']);
1257
-            } else {
1258
-                // delay until other systems are online
1259
-                add_action(
1260
-                    'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
1261
-                    array($module_class, 'set_hooks')
1262
-                );
1263
-            }
1264
-        }
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     *    register_route - adds module method routes to route_map
1270
-     *
1271
-     * @access    public
1272
-     * @param    string $route       - "pretty" public alias for module method
1273
-     * @param    string $module      - module name (classname without EED_ prefix)
1274
-     * @param    string $method_name - the actual module method to be routed to
1275
-     * @param    string $key         - url param key indicating a route is being called
1276
-     * @return    bool
1277
-     */
1278
-    public static function register_route($route = null, $module = null, $method_name = null, $key = 'ee')
1279
-    {
1280
-        do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1281
-        $module = str_replace('EED_', '', $module);
1282
-        $module_class = 'EED_' . $module;
1283
-        if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1284
-            $msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1285
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1286
-            return false;
1287
-        }
1288
-        if (empty($route)) {
1289
-            $msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1290
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1291
-            return false;
1292
-        }
1293
-        if (! method_exists('EED_' . $module, $method_name)) {
1294
-            $msg = sprintf(
1295
-                esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1296
-                $route
1297
-            );
1298
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1299
-            return false;
1300
-        }
1301
-        EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1302
-        return true;
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     *    get_route - get module method route
1308
-     *
1309
-     * @access    public
1310
-     * @param    string $route - "pretty" public alias for module method
1311
-     * @param    string $key   - url param key indicating a route is being called
1312
-     * @return    string
1313
-     */
1314
-    public static function get_route($route = null, $key = 'ee')
1315
-    {
1316
-        do_action('AHEE__EE_Config__get_route__begin', $route);
1317
-        $route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1318
-        if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1319
-            return EE_Config::$_module_route_map[ $key ][ $route ];
1320
-        }
1321
-        return null;
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     *    get_routes - get ALL module method routes
1327
-     *
1328
-     * @access    public
1329
-     * @return    array
1330
-     */
1331
-    public static function get_routes()
1332
-    {
1333
-        return EE_Config::$_module_route_map;
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     *    register_forward - allows modules to forward request to another module for further processing
1339
-     *
1340
-     * @access    public
1341
-     * @param    string       $route   - "pretty" public alias for module method
1342
-     * @param    integer      $status  - integer value corresponding  to status constant strings set in module parent
1343
-     *                                 class, allows different forwards to be served based on status
1344
-     * @param    array|string $forward - function name or array( class, method )
1345
-     * @param    string       $key     - url param key indicating a route is being called
1346
-     * @return    bool
1347
-     */
1348
-    public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1349
-    {
1350
-        do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1351
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1352
-            $msg = sprintf(
1353
-                esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1354
-                $route
1355
-            );
1356
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1357
-            return false;
1358
-        }
1359
-        if (empty($forward)) {
1360
-            $msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1361
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1362
-            return false;
1363
-        }
1364
-        if (is_array($forward)) {
1365
-            if (! isset($forward[1])) {
1366
-                $msg = sprintf(
1367
-                    esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1368
-                    $route
1369
-                );
1370
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1371
-                return false;
1372
-            }
1373
-            if (! method_exists($forward[0], $forward[1])) {
1374
-                $msg = sprintf(
1375
-                    esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1376
-                    $forward[1],
1377
-                    $route
1378
-                );
1379
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1380
-                return false;
1381
-            }
1382
-        } elseif (! function_exists($forward)) {
1383
-            $msg = sprintf(
1384
-                esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1385
-                $forward,
1386
-                $route
1387
-            );
1388
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1389
-            return false;
1390
-        }
1391
-        EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1392
-        return true;
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     *    get_forward - get forwarding route
1398
-     *
1399
-     * @access    public
1400
-     * @param    string  $route  - "pretty" public alias for module method
1401
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1402
-     *                           allows different forwards to be served based on status
1403
-     * @param    string  $key    - url param key indicating a route is being called
1404
-     * @return    string
1405
-     */
1406
-    public static function get_forward($route = null, $status = 0, $key = 'ee')
1407
-    {
1408
-        do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1409
-        if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1410
-            return apply_filters(
1411
-                'FHEE__EE_Config__get_forward',
1412
-                EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1413
-                $route,
1414
-                $status
1415
-            );
1416
-        }
1417
-        return null;
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     *    register_forward - allows modules to specify different view templates for different method routes and status
1423
-     *    results
1424
-     *
1425
-     * @access    public
1426
-     * @param    string  $route  - "pretty" public alias for module method
1427
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1428
-     *                           allows different views to be served based on status
1429
-     * @param    string  $view
1430
-     * @param    string  $key    - url param key indicating a route is being called
1431
-     * @return    bool
1432
-     */
1433
-    public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1434
-    {
1435
-        do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1436
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1437
-            $msg = sprintf(
1438
-                esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1439
-                $route
1440
-            );
1441
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1442
-            return false;
1443
-        }
1444
-        if (! is_readable($view)) {
1445
-            $msg = sprintf(
1446
-                esc_html__(
1447
-                    'The %s view file could not be found or is not readable due to file permissions.',
1448
-                    'event_espresso'
1449
-                ),
1450
-                $view
1451
-            );
1452
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1453
-            return false;
1454
-        }
1455
-        EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1456
-        return true;
1457
-    }
1458
-
1459
-
1460
-    /**
1461
-     *    get_view - get view for route and status
1462
-     *
1463
-     * @access    public
1464
-     * @param    string  $route  - "pretty" public alias for module method
1465
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1466
-     *                           allows different views to be served based on status
1467
-     * @param    string  $key    - url param key indicating a route is being called
1468
-     * @return    string
1469
-     */
1470
-    public static function get_view($route = null, $status = 0, $key = 'ee')
1471
-    {
1472
-        do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1473
-        if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1474
-            return apply_filters(
1475
-                'FHEE__EE_Config__get_view',
1476
-                EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1477
-                $route,
1478
-                $status
1479
-            );
1480
-        }
1481
-        return null;
1482
-    }
1483
-
1484
-
1485
-    public function update_addon_option_names()
1486
-    {
1487
-        update_option(EE_Config::ADDON_OPTION_NAMES, $this->_addon_option_names);
1488
-    }
1489
-
1490
-
1491
-    public function shutdown()
1492
-    {
1493
-        $this->update_addon_option_names();
1494
-    }
1495
-
1496
-
1497
-    /**
1498
-     * @return LegacyShortcodesManager
1499
-     */
1500
-    public static function getLegacyShortcodesManager()
1501
-    {
1502
-        if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1503
-            EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1504
-                LegacyShortcodesManager::class
1505
-            );
1506
-        }
1507
-        return EE_Config::instance()->legacy_shortcodes_manager;
1508
-    }
1509
-
1510
-
1511
-    /**
1512
-     * register_shortcode - makes core aware of this shortcode
1513
-     *
1514
-     * @deprecated 4.9.26
1515
-     * @param    string $shortcode_path - full path up to and including shortcode folder
1516
-     * @return    bool
1517
-     */
1518
-    public static function register_shortcode($shortcode_path = null)
1519
-    {
1520
-        EE_Error::doing_it_wrong(
1521
-            __METHOD__,
1522
-            esc_html__(
1523
-                'Usage is deprecated. Use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::registerShortcode() as direct replacement, or better yet, please see the new \EventEspresso\core\services\shortcodes\ShortcodesManager class.',
1524
-                'event_espresso'
1525
-            ),
1526
-            '4.9.26'
1527
-        );
1528
-        return EE_Config::instance()->getLegacyShortcodesManager()->registerShortcode($shortcode_path);
1529
-    }
21
+	const OPTION_NAME = 'ee_config';
22
+
23
+	const LOG_NAME = 'ee_config_log';
24
+
25
+	const LOG_LENGTH = 100;
26
+
27
+	const ADDON_OPTION_NAMES = 'ee_config_option_names';
28
+
29
+	/**
30
+	 *    instance of the EE_Config object
31
+	 *
32
+	 * @var    EE_Config $_instance
33
+	 * @access    private
34
+	 */
35
+	private static $_instance;
36
+
37
+	/**
38
+	 * @var boolean $_logging_enabled
39
+	 */
40
+	private static $_logging_enabled = false;
41
+
42
+	/**
43
+	 * @var LegacyShortcodesManager $legacy_shortcodes_manager
44
+	 */
45
+	private $legacy_shortcodes_manager;
46
+
47
+	/**
48
+	 * An StdClass whose property names are addon slugs,
49
+	 * and values are their config classes
50
+	 *
51
+	 * @var StdClass
52
+	 */
53
+	public $addons;
54
+
55
+	/**
56
+	 * @var EE_Admin_Config
57
+	 */
58
+	public $admin;
59
+
60
+	/**
61
+	 * @var EE_Core_Config
62
+	 */
63
+	public $core;
64
+
65
+	/**
66
+	 * @var EE_Currency_Config
67
+	 */
68
+	public $currency;
69
+
70
+	/**
71
+	 * @var EE_Organization_Config
72
+	 */
73
+	public $organization;
74
+
75
+	/**
76
+	 * @var EE_Registration_Config
77
+	 */
78
+	public $registration;
79
+
80
+	/**
81
+	 * @var EE_Template_Config
82
+	 */
83
+	public $template_settings;
84
+
85
+	/**
86
+	 * Holds EE environment values.
87
+	 *
88
+	 * @var EE_Environment_Config
89
+	 */
90
+	public $environment;
91
+
92
+	/**
93
+	 * settings pertaining to Google maps
94
+	 *
95
+	 * @var EE_Map_Config
96
+	 */
97
+	public $map_settings;
98
+
99
+	/**
100
+	 * settings pertaining to Taxes
101
+	 *
102
+	 * @var EE_Tax_Config
103
+	 */
104
+	public $tax_settings;
105
+
106
+	/**
107
+	 * Settings pertaining to global messages settings.
108
+	 *
109
+	 * @var EE_Messages_Config
110
+	 */
111
+	public $messages;
112
+
113
+	/**
114
+	 * @deprecated
115
+	 * @var EE_Gateway_Config
116
+	 */
117
+	public $gateway;
118
+
119
+	/**
120
+	 * @var array
121
+	 */
122
+	private $_addon_option_names = array();
123
+
124
+	/**
125
+	 * @var array
126
+	 */
127
+	private static $_module_route_map = array();
128
+
129
+	/**
130
+	 * @var array
131
+	 */
132
+	private static $_module_forward_map = array();
133
+
134
+	/**
135
+	 * @var array
136
+	 */
137
+	private static $_module_view_map = array();
138
+
139
+	/**
140
+	 * @var bool
141
+	 */
142
+	private static $initialized = false;
143
+
144
+
145
+	/**
146
+	 * @singleton method used to instantiate class object
147
+	 * @access    public
148
+	 * @return EE_Config instance
149
+	 */
150
+	public static function instance()
151
+	{
152
+		// check if class object is instantiated, and instantiated properly
153
+		if (! self::$_instance instanceof EE_Config) {
154
+			self::$_instance = new self();
155
+		}
156
+		return self::$_instance;
157
+	}
158
+
159
+
160
+	/**
161
+	 * Resets the config
162
+	 *
163
+	 * @param bool    $hard_reset    if TRUE, sets EE_CONFig back to its original settings in the database. If FALSE
164
+	 *                               (default) leaves the database alone, and merely resets the EE_Config object to
165
+	 *                               reflect its state in the database
166
+	 * @param boolean $reinstantiate if TRUE (default) call instance() and return it. Otherwise, just leave
167
+	 *                               $_instance as NULL. Useful in case you want to forget about the old instance on
168
+	 *                               EE_Config, but might not be ready to instantiate EE_Config currently (eg if the
169
+	 *                               site was put into maintenance mode)
170
+	 * @return EE_Config
171
+	 */
172
+	public static function reset($hard_reset = false, $reinstantiate = true)
173
+	{
174
+		if (self::$_instance instanceof EE_Config) {
175
+			if ($hard_reset) {
176
+				self::$_instance->legacy_shortcodes_manager = null;
177
+				self::$_instance->_addon_option_names = array();
178
+				self::$_instance->_initialize_config();
179
+				self::$_instance->update_espresso_config();
180
+			}
181
+			self::$_instance->update_addon_option_names();
182
+		}
183
+		self::$_instance = null;
184
+		self::$initialized = false;
185
+		// we don't need to reset the static properties imo because those should
186
+		// only change when a module is added or removed. Currently we don't
187
+		// support removing a module during a request when it previously existed
188
+		if ($reinstantiate) {
189
+			return self::instance();
190
+		} else {
191
+			return null;
192
+		}
193
+	}
194
+
195
+
196
+	private function __construct()
197
+	{
198
+		if (self::$initialized) {
199
+			return;
200
+		}
201
+		self::$initialized = true;
202
+		do_action('AHEE__EE_Config__construct__begin', $this);
203
+		EE_Config::$_logging_enabled = apply_filters('FHEE__EE_Config___construct__logging_enabled', false);
204
+		// setup empty config classes
205
+		$this->_initialize_config();
206
+		// load existing EE site settings
207
+		$this->_load_core_config();
208
+		// confirm everything loaded correctly and set filtered defaults if not
209
+		$this->_verify_config();
210
+		//  register shortcodes and modules
211
+		add_action(
212
+			'AHEE__EE_System__register_shortcodes_modules_and_widgets',
213
+			[$this, 'register_shortcodes_and_modules'],
214
+			999
215
+		);
216
+		//  initialize shortcodes and modules
217
+		add_action('AHEE__EE_System__core_loaded_and_ready', [$this, 'initialize_shortcodes_and_modules']);
218
+		// register widgets
219
+		add_action('widgets_init', [$this, 'widgets_init'], 10);
220
+		// shutdown
221
+		add_action('shutdown', [$this, 'shutdown'], 10);
222
+		// construct__end hook
223
+		do_action('AHEE__EE_Config__construct__end', $this);
224
+		// hardcoded hack
225
+		$this->template_settings->current_espresso_theme = 'Espresso_Arabica_2014';
226
+	}
227
+
228
+
229
+	/**
230
+	 * @return boolean
231
+	 */
232
+	public static function logging_enabled()
233
+	{
234
+		return self::$_logging_enabled;
235
+	}
236
+
237
+
238
+	/**
239
+	 * use to get the current theme if needed from static context
240
+	 *
241
+	 * @return string current theme set.
242
+	 */
243
+	public static function get_current_theme()
244
+	{
245
+		return self::$_instance->template_settings->current_espresso_theme ?? 'Espresso_Arabica_2014';
246
+	}
247
+
248
+
249
+	/**
250
+	 *        _initialize_config
251
+	 *
252
+	 * @access private
253
+	 * @return void
254
+	 */
255
+	private function _initialize_config()
256
+	{
257
+		EE_Config::trim_log();
258
+		// set defaults
259
+		$this->_addon_option_names = get_option(EE_Config::ADDON_OPTION_NAMES, array());
260
+		$this->addons = new stdClass();
261
+		// set _module_route_map
262
+		EE_Config::$_module_route_map = array();
263
+		// set _module_forward_map
264
+		EE_Config::$_module_forward_map = array();
265
+		// set _module_view_map
266
+		EE_Config::$_module_view_map = array();
267
+	}
268
+
269
+
270
+	/**
271
+	 *        load core plugin configuration
272
+	 *
273
+	 * @access private
274
+	 * @return void
275
+	 */
276
+	private function _load_core_config()
277
+	{
278
+		// load_core_config__start hook
279
+		do_action('AHEE__EE_Config___load_core_config__start', $this);
280
+		$espresso_config = (array) $this->get_espresso_config();
281
+		// need to move the "addons" element to the end of the config array
282
+		// in case an addon config references one of the other config classes
283
+		$addons = $espresso_config['addons'] ?? new StdClass();
284
+		unset($espresso_config['addons']);
285
+		$espresso_config['addons'] = $addons;
286
+		foreach ($espresso_config as $config => $settings) {
287
+			// load_core_config__start hook
288
+			$settings = apply_filters(
289
+				'FHEE__EE_Config___load_core_config__config_settings',
290
+				$settings,
291
+				$config,
292
+				$this
293
+			);
294
+			if (is_object($settings) && property_exists($this, $config)) {
295
+				$this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
296
+				// call configs populate method to ensure any defaults are set for empty values.
297
+				if (method_exists($settings, 'populate')) {
298
+					$this->{$config}->populate();
299
+				}
300
+				if (method_exists($settings, 'do_hooks')) {
301
+					$this->{$config}->do_hooks();
302
+				}
303
+			}
304
+		}
305
+		if (apply_filters('FHEE__EE_Config___load_core_config__update_espresso_config', false)) {
306
+			$this->update_espresso_config();
307
+		}
308
+		// load_core_config__end hook
309
+		do_action('AHEE__EE_Config___load_core_config__end', $this);
310
+	}
311
+
312
+
313
+	/**
314
+	 *    _verify_config
315
+	 *
316
+	 * @access    protected
317
+	 * @return    void
318
+	 */
319
+	protected function _verify_config()
320
+	{
321
+		$this->core = $this->core instanceof EE_Core_Config
322
+			? $this->core
323
+			: new EE_Core_Config();
324
+		$this->core = apply_filters('FHEE__EE_Config___initialize_config__core', $this->core);
325
+		$this->organization = $this->organization instanceof EE_Organization_Config
326
+			? $this->organization
327
+			: new EE_Organization_Config();
328
+		$this->organization = apply_filters(
329
+			'FHEE__EE_Config___initialize_config__organization',
330
+			$this->organization
331
+		);
332
+		$this->currency = $this->currency instanceof EE_Currency_Config
333
+			? $this->currency
334
+			: new EE_Currency_Config();
335
+		$this->currency = apply_filters('FHEE__EE_Config___initialize_config__currency', $this->currency);
336
+		$this->registration = $this->registration instanceof EE_Registration_Config
337
+			? $this->registration
338
+			: new EE_Registration_Config();
339
+		$this->registration = apply_filters(
340
+			'FHEE__EE_Config___initialize_config__registration',
341
+			$this->registration
342
+		);
343
+		$this->admin = $this->admin instanceof EE_Admin_Config
344
+			? $this->admin
345
+			: new EE_Admin_Config();
346
+		$this->admin = apply_filters('FHEE__EE_Config___initialize_config__admin', $this->admin);
347
+		$this->template_settings = $this->template_settings instanceof EE_Template_Config
348
+			? $this->template_settings
349
+			: new EE_Template_Config();
350
+		$this->template_settings = apply_filters(
351
+			'FHEE__EE_Config___initialize_config__template_settings',
352
+			$this->template_settings
353
+		);
354
+		$this->map_settings = $this->map_settings instanceof EE_Map_Config
355
+			? $this->map_settings
356
+			: new EE_Map_Config();
357
+		$this->map_settings = apply_filters(
358
+			'FHEE__EE_Config___initialize_config__map_settings',
359
+			$this->map_settings
360
+		);
361
+		$this->environment = $this->environment instanceof EE_Environment_Config
362
+			? $this->environment
363
+			: new EE_Environment_Config();
364
+		$this->environment = apply_filters(
365
+			'FHEE__EE_Config___initialize_config__environment',
366
+			$this->environment
367
+		);
368
+		$this->tax_settings = $this->tax_settings instanceof EE_Tax_Config
369
+			? $this->tax_settings
370
+			: new EE_Tax_Config();
371
+		$this->tax_settings = apply_filters(
372
+			'FHEE__EE_Config___initialize_config__tax_settings',
373
+			$this->tax_settings
374
+		);
375
+		$this->messages = apply_filters('FHEE__EE_Config__initialize_config__messages', $this->messages);
376
+		$this->messages = $this->messages instanceof EE_Messages_Config
377
+			? $this->messages
378
+			: new EE_Messages_Config();
379
+		$this->gateway = $this->gateway instanceof EE_Gateway_Config
380
+			? $this->gateway
381
+			: new EE_Gateway_Config();
382
+		$this->gateway = apply_filters('FHEE__EE_Config___initialize_config__gateway', $this->gateway);
383
+		$this->legacy_shortcodes_manager = null;
384
+	}
385
+
386
+
387
+	/**
388
+	 *    get_espresso_config
389
+	 *
390
+	 * @access    public
391
+	 * @return    array of espresso config stuff
392
+	 */
393
+	public function get_espresso_config()
394
+	{
395
+		// grab espresso configuration
396
+		return apply_filters(
397
+			'FHEE__EE_Config__get_espresso_config__CFG',
398
+			get_option(EE_Config::OPTION_NAME, array())
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 *    double_check_config_comparison
405
+	 *
406
+	 * @access    public
407
+	 * @param string $option
408
+	 * @param        $old_value
409
+	 * @param        $value
410
+	 */
411
+	public function double_check_config_comparison($option, $old_value, $value)
412
+	{
413
+		// make sure we're checking the ee config
414
+		if ($option === EE_Config::OPTION_NAME) {
415
+			// run a loose comparison of the old value against the new value for type and properties,
416
+			// but NOT exact instance like WP update_option does (ie: NOT type safe comparison)
417
+			if ($value != $old_value) {
418
+				// if they are NOT the same, then remove the hook,
419
+				// which means the subsequent update results will be based solely on the update query results
420
+				// the reason we do this is because, as stated above,
421
+				// WP update_option performs an exact instance comparison (===) on any update values passed to it
422
+				// this happens PRIOR to serialization and any subsequent update.
423
+				// If values are found to match their previous old value,
424
+				// then WP bails before performing any update.
425
+				// Since we are passing the EE_Config object, it is comparing the EXACT instance of the saved version
426
+				// it just pulled from the db, with the one being passed to it (which will not match).
427
+				// HOWEVER, once the object is serialized and passed off to MySQL to update,
428
+				// MySQL MAY ALSO NOT perform the update because
429
+				// the string it sees in the db looks the same as the new one it has been passed!!!
430
+				// This results in the query returning an "affected rows" value of ZERO,
431
+				// which gets returned immediately by WP update_option and looks like an error.
432
+				remove_action('update_option', array($this, 'check_config_updated'));
433
+			}
434
+		}
435
+	}
436
+
437
+
438
+	/**
439
+	 *    update_espresso_config
440
+	 *
441
+	 * @access   public
442
+	 */
443
+	protected function _reset_espresso_addon_config()
444
+	{
445
+		$this->_addon_option_names = array();
446
+		foreach ($this->addons as $addon_name => $addon_config_obj) {
447
+			$addon_config_obj = maybe_unserialize($addon_config_obj);
448
+			if ($addon_config_obj instanceof EE_Config_Base) {
449
+				$this->update_config('addons', $addon_name, $addon_config_obj, false);
450
+			}
451
+			$this->addons->{$addon_name} = null;
452
+		}
453
+	}
454
+
455
+
456
+	/**
457
+	 *    update_espresso_config
458
+	 *
459
+	 * @access   public
460
+	 * @param   bool $add_success
461
+	 * @param   bool $add_error
462
+	 * @return   bool
463
+	 */
464
+	public function update_espresso_config($add_success = false, $add_error = true)
465
+	{
466
+		// don't allow config updates during WP heartbeats
467
+		/** @var RequestInterface $request */
468
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
469
+		if ($request->isWordPressHeartbeat()) {
470
+			return false;
471
+		}
472
+		// commented out the following re: https://events.codebasehq.com/projects/event-espresso/tickets/8197
473
+		// $clone = clone( self::$_instance );
474
+		// self::$_instance = NULL;
475
+		do_action('AHEE__EE_Config__update_espresso_config__begin', $this);
476
+		$this->_reset_espresso_addon_config();
477
+		// hook into update_option because that happens AFTER the ( $value === $old_value ) conditional
478
+		// but BEFORE the actual update occurs
479
+		add_action('update_option', array($this, 'double_check_config_comparison'), 1, 3);
480
+		// don't want to persist legacy_shortcodes_manager, but don't want to lose it either
481
+		$legacy_shortcodes_manager = $this->legacy_shortcodes_manager;
482
+		$this->legacy_shortcodes_manager = null;
483
+		// now update "ee_config"
484
+		$saved = update_option(EE_Config::OPTION_NAME, $this);
485
+		$this->legacy_shortcodes_manager = $legacy_shortcodes_manager;
486
+		EE_Config::log(EE_Config::OPTION_NAME);
487
+		// if not saved... check if the hook we just added still exists;
488
+		// if it does, it means one of two things:
489
+		// that update_option bailed at the($value === $old_value) conditional,
490
+		// or...
491
+		// the db update query returned 0 rows affected
492
+		// (probably because the data  value was the same from it's perspective)
493
+		// so the existence of the hook means that a negative result from update_option is NOT an error,
494
+		// but just means no update occurred, so don't display an error to the user.
495
+		// BUT... if update_option returns FALSE, AND the hook is missing,
496
+		// then it means that something truly went wrong
497
+		$saved = ! $saved ? has_action('update_option', array($this, 'double_check_config_comparison')) : $saved;
498
+		// remove our action since we don't want it in the system anymore
499
+		remove_action('update_option', array($this, 'double_check_config_comparison'), 1);
500
+		do_action('AHEE__EE_Config__update_espresso_config__end', $this, $saved);
501
+		// self::$_instance = $clone;
502
+		// unset( $clone );
503
+		// if config remains the same or was updated successfully
504
+		if ($saved) {
505
+			if ($add_success) {
506
+				EE_Error::add_success(
507
+					esc_html__('The Event Espresso Configuration Settings have been successfully updated.', 'event_espresso'),
508
+					__FILE__,
509
+					__FUNCTION__,
510
+					__LINE__
511
+				);
512
+			}
513
+			return true;
514
+		} else {
515
+			if ($add_error) {
516
+				EE_Error::add_error(
517
+					esc_html__('The Event Espresso Configuration Settings were not updated.', 'event_espresso'),
518
+					__FILE__,
519
+					__FUNCTION__,
520
+					__LINE__
521
+				);
522
+			}
523
+			return false;
524
+		}
525
+	}
526
+
527
+
528
+	/**
529
+	 *    _verify_config_params
530
+	 *
531
+	 * @access    private
532
+	 * @param    string         $section
533
+	 * @param    string         $name
534
+	 * @param    string         $config_class
535
+	 * @param    EE_Config_Base $config_obj
536
+	 * @param    array          $tests_to_run
537
+	 * @param    bool           $display_errors
538
+	 * @return    bool    TRUE on success, FALSE on fail
539
+	 */
540
+	private function _verify_config_params(
541
+		$section = '',
542
+		$name = '',
543
+		$config_class = '',
544
+		$config_obj = null,
545
+		$tests_to_run = array(1, 2, 3, 4, 5, 6, 7, 8),
546
+		$display_errors = true
547
+	) {
548
+		try {
549
+			foreach ($tests_to_run as $test) {
550
+				switch ($test) {
551
+					// TEST #1 : check that section was set
552
+					case 1:
553
+						if (empty($section)) {
554
+							if ($display_errors) {
555
+								throw new EE_Error(
556
+									sprintf(
557
+										esc_html__(
558
+											'No configuration section has been provided while attempting to save "%s".',
559
+											'event_espresso'
560
+										),
561
+										$config_class
562
+									)
563
+								);
564
+							}
565
+							return false;
566
+						}
567
+						break;
568
+					// TEST #2 : check that settings section exists
569
+					case 2:
570
+						if (! isset($this->{$section})) {
571
+							if ($display_errors) {
572
+								throw new EE_Error(
573
+									sprintf(
574
+										esc_html__('The "%s" configuration section does not exist.', 'event_espresso'),
575
+										$section
576
+									)
577
+								);
578
+							}
579
+							return false;
580
+						}
581
+						break;
582
+					// TEST #3 : check that section is the proper format
583
+					case 3:
584
+						if (
585
+							! ($this->{$section} instanceof EE_Config_Base || $this->{$section} instanceof stdClass)
586
+						) {
587
+							if ($display_errors) {
588
+								throw new EE_Error(
589
+									sprintf(
590
+										esc_html__(
591
+											'The "%s" configuration settings have not been formatted correctly.',
592
+											'event_espresso'
593
+										),
594
+										$section
595
+									)
596
+								);
597
+							}
598
+							return false;
599
+						}
600
+						break;
601
+					// TEST #4 : check that config section name has been set
602
+					case 4:
603
+						if (empty($name)) {
604
+							if ($display_errors) {
605
+								throw new EE_Error(
606
+									esc_html__(
607
+										'No name has been provided for the specific configuration section.',
608
+										'event_espresso'
609
+									)
610
+								);
611
+							}
612
+							return false;
613
+						}
614
+						break;
615
+					// TEST #5 : check that a config class name has been set
616
+					case 5:
617
+						if (empty($config_class)) {
618
+							if ($display_errors) {
619
+								throw new EE_Error(
620
+									esc_html__(
621
+										'No class name has been provided for the specific configuration section.',
622
+										'event_espresso'
623
+									)
624
+								);
625
+							}
626
+							return false;
627
+						}
628
+						break;
629
+					// TEST #6 : verify config class is accessible
630
+					case 6:
631
+						if (! class_exists($config_class)) {
632
+							if ($display_errors) {
633
+								throw new EE_Error(
634
+									sprintf(
635
+										esc_html__(
636
+											'The "%s" class does not exist. Please ensure that an autoloader has been set for it.',
637
+											'event_espresso'
638
+										),
639
+										$config_class
640
+									)
641
+								);
642
+							}
643
+							return false;
644
+						}
645
+						break;
646
+					// TEST #7 : check that config has even been set
647
+					case 7:
648
+						if (! isset($this->{$section}->{$name})) {
649
+							if ($display_errors) {
650
+								throw new EE_Error(
651
+									sprintf(
652
+										esc_html__('No configuration has been set for "%1$s->%2$s".', 'event_espresso'),
653
+										$section,
654
+										$name
655
+									)
656
+								);
657
+							}
658
+							return false;
659
+						} else {
660
+							// and make sure it's not serialized
661
+							$this->{$section}->{$name} = maybe_unserialize($this->{$section}->{$name});
662
+						}
663
+						break;
664
+					// TEST #8 : check that config is the requested type
665
+					case 8:
666
+						if (! $this->{$section}->{$name} instanceof $config_class) {
667
+							if ($display_errors) {
668
+								throw new EE_Error(
669
+									sprintf(
670
+										esc_html__(
671
+											'The configuration for "%1$s->%2$s" is not of the "%3$s" class.',
672
+											'event_espresso'
673
+										),
674
+										$section,
675
+										$name,
676
+										$config_class
677
+									)
678
+								);
679
+							}
680
+							return false;
681
+						}
682
+						break;
683
+					// TEST #9 : verify config object
684
+					case 9:
685
+						if (! $config_obj instanceof EE_Config_Base) {
686
+							if ($display_errors) {
687
+								throw new EE_Error(
688
+									sprintf(
689
+										esc_html__('The "%s" class is not an instance of EE_Config_Base.', 'event_espresso'),
690
+										print_r($config_obj, true)
691
+									)
692
+								);
693
+							}
694
+							return false;
695
+						}
696
+						break;
697
+				}
698
+			}
699
+		} catch (EE_Error $e) {
700
+			$e->get_error();
701
+		}
702
+		// you have successfully run the gauntlet
703
+		return true;
704
+	}
705
+
706
+
707
+	/**
708
+	 *    _generate_config_option_name
709
+	 *
710
+	 * @access        protected
711
+	 * @param        string $section
712
+	 * @param        string $name
713
+	 * @return        string
714
+	 */
715
+	private function _generate_config_option_name($section = '', $name = '')
716
+	{
717
+		return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
718
+	}
719
+
720
+
721
+	/**
722
+	 *    _set_config_class
723
+	 * ensures that a config class is set, either from a passed config class or one generated from the config name
724
+	 *
725
+	 * @access    private
726
+	 * @param    string $config_class
727
+	 * @param    string $name
728
+	 * @return    string
729
+	 */
730
+	private function _set_config_class($config_class = '', $name = '')
731
+	{
732
+		return ! empty($config_class)
733
+			? $config_class
734
+			: str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
735
+	}
736
+
737
+
738
+	/**
739
+	 * @param string              $section
740
+	 * @param string              $name
741
+	 * @param string              $config_class
742
+	 * @param EE_Config_Base|null $config_obj
743
+	 * @return EE_Config_Base
744
+	 */
745
+	public function set_config(
746
+		string $section = '',
747
+		string $name = '',
748
+		string $config_class = '',
749
+		EE_Config_Base $config_obj = null
750
+	): ?EE_Config_Base {
751
+		// ensure config class is set to something
752
+		$config_class = $this->_set_config_class($config_class, $name);
753
+		// run tests 1-4, 6, and 7 to verify all config params are set and valid
754
+		if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
755
+			return null;
756
+		}
757
+		$config_option_name = $this->_generate_config_option_name($section, $name);
758
+		// if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
759
+		if (! isset($this->_addon_option_names[ $config_option_name ])) {
760
+			$this->_addon_option_names[ $config_option_name ] = $config_class;
761
+			$this->update_addon_option_names();
762
+		}
763
+		// verify the incoming config object but suppress errors
764
+		if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
765
+			$config_obj = new $config_class();
766
+		}
767
+		if (get_option($config_option_name)) {
768
+			EE_Config::log($config_option_name);
769
+			try {
770
+				update_option($config_option_name, $config_obj);
771
+			} catch (Exception $exception) {
772
+				throw new DomainException(
773
+					sprintf(
774
+						esc_html__(
775
+							'The following exception occurred while attempting to update the "%1$s" class for config section "%2$s->%3$s": %4$s',
776
+							'event_espresso'
777
+						),
778
+						$config_class,
779
+						$section,
780
+						$name,
781
+						$exception->getMessage()
782
+					)
783
+				);
784
+			}
785
+			$this->{$section}->{$name} = $config_obj;
786
+			return $this->{$section}->{$name};
787
+		} else {
788
+			// create a wp-option for this config
789
+			if (add_option($config_option_name, $config_obj, '', 'no')) {
790
+				$this->{$section}->{$name} = maybe_unserialize($config_obj);
791
+				return $this->{$section}->{$name};
792
+			} else {
793
+				EE_Error::add_error(
794
+					sprintf(esc_html__('The "%s" could not be saved to the database.', 'event_espresso'), $config_class),
795
+					__FILE__,
796
+					__FUNCTION__,
797
+					__LINE__
798
+				);
799
+				return null;
800
+			}
801
+		}
802
+	}
803
+
804
+
805
+	/**
806
+	 *    update_config
807
+	 * Important: the config object must ALREADY be set, otherwise this will produce an error.
808
+	 *
809
+	 * @access    public
810
+	 * @param    string                $section
811
+	 * @param    string                $name
812
+	 * @param    EE_Config_Base|string $config_obj
813
+	 * @param    bool                  $throw_errors
814
+	 * @return    bool
815
+	 */
816
+	public function update_config($section = '', $name = '', $config_obj = '', $throw_errors = true)
817
+	{
818
+		// don't allow config updates during WP heartbeats
819
+		/** @var RequestInterface $request */
820
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
821
+		if ($request->isWordPressHeartbeat()) {
822
+			return false;
823
+		}
824
+		$config_obj = maybe_unserialize($config_obj);
825
+		// get class name of the incoming object
826
+		$config_class = get_class($config_obj);
827
+		// run tests 1-5 and 9 to verify config
828
+		if (
829
+			! $this->_verify_config_params(
830
+				$section,
831
+				$name,
832
+				$config_class,
833
+				$config_obj,
834
+				array(1, 2, 3, 4, 7, 9)
835
+			)
836
+		) {
837
+			return false;
838
+		}
839
+		$config_option_name = $this->_generate_config_option_name($section, $name);
840
+		// check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
841
+		if (! isset($this->_addon_option_names[ $config_option_name ])) {
842
+			// save new config to db
843
+			if ($this->set_config($section, $name, $config_class, $config_obj)) {
844
+				return true;
845
+			}
846
+		} else {
847
+			// first check if the record already exists
848
+			$existing_config = get_option($config_option_name);
849
+			$config_obj = serialize($config_obj);
850
+			// just return if db record is already up to date (NOT type safe comparison)
851
+			if ($existing_config == $config_obj) {
852
+				$this->{$section}->{$name} = $config_obj;
853
+				return true;
854
+			} elseif (update_option($config_option_name, $config_obj)) {
855
+				EE_Config::log($config_option_name);
856
+				// update wp-option for this config class
857
+				$this->{$section}->{$name} = $config_obj;
858
+				return true;
859
+			} elseif ($throw_errors) {
860
+				EE_Error::add_error(
861
+					sprintf(
862
+						esc_html__(
863
+							'The "%1$s" object stored at"%2$s" was not successfully updated in the database.',
864
+							'event_espresso'
865
+						),
866
+						$config_class,
867
+						'EE_Config->' . $section . '->' . $name
868
+					),
869
+					__FILE__,
870
+					__FUNCTION__,
871
+					__LINE__
872
+				);
873
+			}
874
+		}
875
+		return false;
876
+	}
877
+
878
+
879
+	/**
880
+	 *    get_config
881
+	 *
882
+	 * @access    public
883
+	 * @param    string $section
884
+	 * @param    string $name
885
+	 * @param    string $config_class
886
+	 * @return    mixed EE_Config_Base | NULL
887
+	 */
888
+	public function get_config($section = '', $name = '', $config_class = '')
889
+	{
890
+		// ensure config class is set to something
891
+		$config_class = $this->_set_config_class($config_class, $name);
892
+		// run tests 1-4, 6 and 7 to verify that all params have been set
893
+		if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
894
+			return null;
895
+		}
896
+		// now test if the requested config object exists, but suppress errors
897
+		if ($this->_verify_config_params($section, $name, $config_class, null, array(7, 8), false)) {
898
+			// config already exists, so pass it back
899
+			return $this->{$section}->{$name};
900
+		}
901
+		// load config option from db if it exists
902
+		$config_obj = $this->get_config_option($this->_generate_config_option_name($section, $name));
903
+		// verify the newly retrieved config object, but suppress errors
904
+		if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
905
+			// config is good, so set it and pass it back
906
+			$this->{$section}->{$name} = $config_obj;
907
+			return $this->{$section}->{$name};
908
+		}
909
+		// oops! $config_obj is not already set and does not exist in the db, so create a new one
910
+		$config_obj = $this->set_config($section, $name, $config_class);
911
+		// verify the newly created config object
912
+		if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9))) {
913
+			return $this->{$section}->{$name};
914
+		} else {
915
+			EE_Error::add_error(
916
+				sprintf(esc_html__('The "%s" could not be retrieved from the database.', 'event_espresso'), $config_class),
917
+				__FILE__,
918
+				__FUNCTION__,
919
+				__LINE__
920
+			);
921
+		}
922
+		return null;
923
+	}
924
+
925
+
926
+	/**
927
+	 *    get_config_option
928
+	 *
929
+	 * @access    public
930
+	 * @param    string $config_option_name
931
+	 * @return    mixed EE_Config_Base | FALSE
932
+	 */
933
+	public function get_config_option($config_option_name = '')
934
+	{
935
+		// retrieve the wp-option for this config class.
936
+		$config_option = maybe_unserialize(get_option($config_option_name, array()));
937
+		if (empty($config_option)) {
938
+			EE_Config::log($config_option_name . '-NOT-FOUND');
939
+		}
940
+		return $config_option;
941
+	}
942
+
943
+
944
+	/**
945
+	 * log
946
+	 *
947
+	 * @param string $config_option_name
948
+	 */
949
+	public static function log($config_option_name = '')
950
+	{
951
+		if (EE_Config::logging_enabled() && ! empty($config_option_name)) {
952
+			$config_log = get_option(EE_Config::LOG_NAME, array());
953
+			/** @var RequestParams $request */
954
+			$request = LoaderFactory::getLoader()->getShared(RequestParams::class);
955
+			$config_log[ (string) microtime(true) ] = array(
956
+				'config_name' => $config_option_name,
957
+				'request'     => $request->requestParams(),
958
+			);
959
+			update_option(EE_Config::LOG_NAME, $config_log);
960
+		}
961
+	}
962
+
963
+
964
+	/**
965
+	 * trim_log
966
+	 * reduces the size of the config log to the length specified by EE_Config::LOG_LENGTH
967
+	 */
968
+	public static function trim_log()
969
+	{
970
+		if (! EE_Config::logging_enabled()) {
971
+			return;
972
+		}
973
+		$config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
974
+		$log_length = count($config_log);
975
+		if ($log_length > EE_Config::LOG_LENGTH) {
976
+			ksort($config_log);
977
+			$config_log = array_slice($config_log, $log_length - EE_Config::LOG_LENGTH, null, true);
978
+			update_option(EE_Config::LOG_NAME, $config_log);
979
+		}
980
+	}
981
+
982
+
983
+	/**
984
+	 *    get_page_for_posts
985
+	 *    if the wp-option "show_on_front" is set to "page", then this is the post_name for the post set in the
986
+	 *    wp-option "page_for_posts", or "posts" if no page is selected
987
+	 *
988
+	 * @access    public
989
+	 * @return    string
990
+	 */
991
+	public static function get_page_for_posts()
992
+	{
993
+		$page_for_posts = get_option('page_for_posts');
994
+		if (! $page_for_posts) {
995
+			return 'posts';
996
+		}
997
+		global $wpdb;
998
+		$SQL = "SELECT post_name from $wpdb->posts WHERE post_type='posts' OR post_type='page' AND post_status='publish' AND ID=%d";
999
+		return $wpdb->get_var($wpdb->prepare($SQL, $page_for_posts));
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 *    register_shortcodes_and_modules.
1005
+	 *    At this point, it's too early to tell if we're maintenance mode or not.
1006
+	 *    In fact, this is where we give modules a chance to let core know they exist
1007
+	 *    so they can help trigger maintenance mode if it's needed
1008
+	 *
1009
+	 * @access    public
1010
+	 * @return    void
1011
+	 */
1012
+	public function register_shortcodes_and_modules()
1013
+	{
1014
+		// allow modules to set hooks for the rest of the system
1015
+		EE_Registry::instance()->modules = $this->_register_modules();
1016
+	}
1017
+
1018
+
1019
+	/**
1020
+	 *    initialize_shortcodes_and_modules
1021
+	 *    meaning they can start adding their hooks to get stuff done
1022
+	 *
1023
+	 * @access    public
1024
+	 * @return    void
1025
+	 */
1026
+	public function initialize_shortcodes_and_modules()
1027
+	{
1028
+		// allow modules to set hooks for the rest of the system
1029
+		$this->_initialize_modules();
1030
+	}
1031
+
1032
+
1033
+	/**
1034
+	 *    widgets_init
1035
+	 *
1036
+	 * @access private
1037
+	 * @return void
1038
+	 */
1039
+	public function widgets_init()
1040
+	{
1041
+		// only init widgets on admin pages when not in complete maintenance, and
1042
+		// on frontend when not in any maintenance mode
1043
+		if (
1044
+			! EE_Maintenance_Mode::instance()->level()
1045
+			|| (
1046
+				is_admin()
1047
+				&& EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
1048
+			)
1049
+		) {
1050
+			// grab list of installed widgets
1051
+			$widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1052
+			// filter list of modules to register
1053
+			$widgets_to_register = apply_filters(
1054
+				'FHEE__EE_Config__register_widgets__widgets_to_register',
1055
+				$widgets_to_register
1056
+			);
1057
+			if (! empty($widgets_to_register)) {
1058
+				// cycle thru widget folders
1059
+				foreach ($widgets_to_register as $widget_path) {
1060
+					// add to list of installed widget modules
1061
+					EE_Config::register_ee_widget($widget_path);
1062
+				}
1063
+			}
1064
+			// filter list of installed modules
1065
+			EE_Registry::instance()->widgets = apply_filters(
1066
+				'FHEE__EE_Config__register_widgets__installed_widgets',
1067
+				EE_Registry::instance()->widgets
1068
+			);
1069
+		}
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 *    register_ee_widget - makes core aware of this widget
1075
+	 *
1076
+	 * @access    public
1077
+	 * @param    string $widget_path - full path up to and including widget folder
1078
+	 * @return    void
1079
+	 */
1080
+	public static function register_ee_widget($widget_path = null)
1081
+	{
1082
+		do_action('AHEE__EE_Config__register_widget__begin', $widget_path);
1083
+		$widget_ext = '.widget.php';
1084
+		// make all separators match
1085
+		$widget_path = rtrim(str_replace('\\', DS, $widget_path), DS);
1086
+		// does the file path INCLUDE the actual file name as part of the path ?
1087
+		if (strpos($widget_path, $widget_ext) !== false) {
1088
+			// grab and shortcode file name from directory name and break apart at dots
1089
+			$file_name = explode('.', basename($widget_path));
1090
+			// take first segment from file name pieces and remove class prefix if it exists
1091
+			$widget = strpos($file_name[0], 'EEW_') === 0 ? substr($file_name[0], 4) : $file_name[0];
1092
+			// sanitize shortcode directory name
1093
+			$widget = sanitize_key($widget);
1094
+			// now we need to rebuild the shortcode path
1095
+			$widget_path = explode('/', $widget_path);
1096
+			// remove last segment
1097
+			array_pop($widget_path);
1098
+			// glue it back together
1099
+			$widget_path = implode(DS, $widget_path);
1100
+		} else {
1101
+			// grab and sanitize widget directory name
1102
+			$widget = sanitize_key(basename($widget_path));
1103
+		}
1104
+		// create classname from widget directory name
1105
+		$widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1106
+		// add class prefix
1107
+		$widget_class = 'EEW_' . $widget;
1108
+		// does the widget exist ?
1109
+		if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1110
+			$msg = sprintf(
1111
+				esc_html__(
1112
+					'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1113
+					'event_espresso'
1114
+				),
1115
+				$widget_class,
1116
+				$widget_path . '/' . $widget_class . $widget_ext
1117
+			);
1118
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1119
+			return;
1120
+		}
1121
+		// load the widget class file
1122
+		require_once($widget_path . '/' . $widget_class . $widget_ext);
1123
+		// verify that class exists
1124
+		if (! class_exists($widget_class)) {
1125
+			$msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1126
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1127
+			return;
1128
+		}
1129
+		register_widget($widget_class);
1130
+		// add to array of registered widgets
1131
+		EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 *        _register_modules
1137
+	 *
1138
+	 * @access private
1139
+	 * @return array
1140
+	 */
1141
+	private function _register_modules()
1142
+	{
1143
+		// grab list of installed modules
1144
+		$modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1145
+		// filter list of modules to register
1146
+		$modules_to_register = apply_filters(
1147
+			'FHEE__EE_Config__register_modules__modules_to_register',
1148
+			$modules_to_register
1149
+		);
1150
+		if (! empty($modules_to_register)) {
1151
+			// loop through folders
1152
+			foreach ($modules_to_register as $module_path) {
1153
+				/**TEMPORARILY EXCLUDE gateways from modules for time being**/
1154
+				if (
1155
+					$module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1156
+					&& $module_path !== EE_MODULES . 'gateways'
1157
+				) {
1158
+					// add to list of installed modules
1159
+					EE_Config::register_module($module_path);
1160
+				}
1161
+			}
1162
+		}
1163
+		// filter list of installed modules
1164
+		return apply_filters(
1165
+			'FHEE__EE_Config___register_modules__installed_modules',
1166
+			EE_Registry::instance()->modules
1167
+		);
1168
+	}
1169
+
1170
+
1171
+	/**
1172
+	 *    register_module - makes core aware of this module
1173
+	 *
1174
+	 * @access    public
1175
+	 * @param    string $module_path - full path up to and including module folder
1176
+	 * @return    bool
1177
+	 */
1178
+	public static function register_module($module_path = null)
1179
+	{
1180
+		do_action('AHEE__EE_Config__register_module__begin', $module_path);
1181
+		$module_ext = '.module.php';
1182
+		// make all separators match
1183
+		$module_path = str_replace(array('\\', '/'), '/', $module_path);
1184
+		// does the file path INCLUDE the actual file name as part of the path ?
1185
+		if (strpos($module_path, $module_ext) !== false) {
1186
+			// grab and shortcode file name from directory name and break apart at dots
1187
+			$module_file = explode('.', basename($module_path));
1188
+			// now we need to rebuild the shortcode path
1189
+			$module_path = explode('/', $module_path);
1190
+			// remove last segment
1191
+			array_pop($module_path);
1192
+			// glue it back together
1193
+			$module_path = implode('/', $module_path) . '/';
1194
+			// take first segment from file name pieces and sanitize it
1195
+			$module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1196
+			// ensure class prefix is added
1197
+			$module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1198
+		} else {
1199
+			// we need to generate the filename based off of the folder name
1200
+			// grab and sanitize module name
1201
+			$module = strtolower(basename($module_path));
1202
+			$module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1203
+			// like trailingslashit()
1204
+			$module_path = rtrim($module_path, '/') . '/';
1205
+			// create classname from module directory name
1206
+			$module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1207
+			// add class prefix
1208
+			$module_class = 'EED_' . $module;
1209
+		}
1210
+		// does the module exist ?
1211
+		if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1212
+			$msg = sprintf(
1213
+				esc_html__(
1214
+					'The requested %s module file could not be found or is not readable due to file permissions.',
1215
+					'event_espresso'
1216
+				),
1217
+				$module
1218
+			);
1219
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1220
+			return false;
1221
+		}
1222
+		// load the module class file
1223
+		require_once($module_path . $module_class . $module_ext);
1224
+		// verify that class exists
1225
+		if (! class_exists($module_class)) {
1226
+			$msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1227
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1228
+			return false;
1229
+		}
1230
+		// add to array of registered modules
1231
+		EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1232
+		do_action(
1233
+			'AHEE__EE_Config__register_module__complete',
1234
+			$module_class,
1235
+			EE_Registry::instance()->modules->{$module_class}
1236
+		);
1237
+		return true;
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 *    _initialize_modules
1243
+	 *    allow modules to set hooks for the rest of the system
1244
+	 *
1245
+	 * @access private
1246
+	 * @return void
1247
+	 */
1248
+	private function _initialize_modules()
1249
+	{
1250
+		// cycle thru shortcode folders
1251
+		foreach (EE_Registry::instance()->modules as $module_class => $module_path) {
1252
+			// fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
1253
+			// which set hooks ?
1254
+			if (is_admin() && is_callable([$module_class, 'set_hooks_admin'])) {
1255
+				// fire immediately
1256
+				call_user_func([$module_class, 'set_hooks_admin']);
1257
+			} else {
1258
+				// delay until other systems are online
1259
+				add_action(
1260
+					'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
1261
+					array($module_class, 'set_hooks')
1262
+				);
1263
+			}
1264
+		}
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 *    register_route - adds module method routes to route_map
1270
+	 *
1271
+	 * @access    public
1272
+	 * @param    string $route       - "pretty" public alias for module method
1273
+	 * @param    string $module      - module name (classname without EED_ prefix)
1274
+	 * @param    string $method_name - the actual module method to be routed to
1275
+	 * @param    string $key         - url param key indicating a route is being called
1276
+	 * @return    bool
1277
+	 */
1278
+	public static function register_route($route = null, $module = null, $method_name = null, $key = 'ee')
1279
+	{
1280
+		do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1281
+		$module = str_replace('EED_', '', $module);
1282
+		$module_class = 'EED_' . $module;
1283
+		if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1284
+			$msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1285
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1286
+			return false;
1287
+		}
1288
+		if (empty($route)) {
1289
+			$msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1290
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1291
+			return false;
1292
+		}
1293
+		if (! method_exists('EED_' . $module, $method_name)) {
1294
+			$msg = sprintf(
1295
+				esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1296
+				$route
1297
+			);
1298
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1299
+			return false;
1300
+		}
1301
+		EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1302
+		return true;
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 *    get_route - get module method route
1308
+	 *
1309
+	 * @access    public
1310
+	 * @param    string $route - "pretty" public alias for module method
1311
+	 * @param    string $key   - url param key indicating a route is being called
1312
+	 * @return    string
1313
+	 */
1314
+	public static function get_route($route = null, $key = 'ee')
1315
+	{
1316
+		do_action('AHEE__EE_Config__get_route__begin', $route);
1317
+		$route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1318
+		if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1319
+			return EE_Config::$_module_route_map[ $key ][ $route ];
1320
+		}
1321
+		return null;
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 *    get_routes - get ALL module method routes
1327
+	 *
1328
+	 * @access    public
1329
+	 * @return    array
1330
+	 */
1331
+	public static function get_routes()
1332
+	{
1333
+		return EE_Config::$_module_route_map;
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 *    register_forward - allows modules to forward request to another module for further processing
1339
+	 *
1340
+	 * @access    public
1341
+	 * @param    string       $route   - "pretty" public alias for module method
1342
+	 * @param    integer      $status  - integer value corresponding  to status constant strings set in module parent
1343
+	 *                                 class, allows different forwards to be served based on status
1344
+	 * @param    array|string $forward - function name or array( class, method )
1345
+	 * @param    string       $key     - url param key indicating a route is being called
1346
+	 * @return    bool
1347
+	 */
1348
+	public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1349
+	{
1350
+		do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1351
+		if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1352
+			$msg = sprintf(
1353
+				esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1354
+				$route
1355
+			);
1356
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1357
+			return false;
1358
+		}
1359
+		if (empty($forward)) {
1360
+			$msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1361
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1362
+			return false;
1363
+		}
1364
+		if (is_array($forward)) {
1365
+			if (! isset($forward[1])) {
1366
+				$msg = sprintf(
1367
+					esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1368
+					$route
1369
+				);
1370
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1371
+				return false;
1372
+			}
1373
+			if (! method_exists($forward[0], $forward[1])) {
1374
+				$msg = sprintf(
1375
+					esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1376
+					$forward[1],
1377
+					$route
1378
+				);
1379
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1380
+				return false;
1381
+			}
1382
+		} elseif (! function_exists($forward)) {
1383
+			$msg = sprintf(
1384
+				esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1385
+				$forward,
1386
+				$route
1387
+			);
1388
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1389
+			return false;
1390
+		}
1391
+		EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1392
+		return true;
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 *    get_forward - get forwarding route
1398
+	 *
1399
+	 * @access    public
1400
+	 * @param    string  $route  - "pretty" public alias for module method
1401
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1402
+	 *                           allows different forwards to be served based on status
1403
+	 * @param    string  $key    - url param key indicating a route is being called
1404
+	 * @return    string
1405
+	 */
1406
+	public static function get_forward($route = null, $status = 0, $key = 'ee')
1407
+	{
1408
+		do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1409
+		if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1410
+			return apply_filters(
1411
+				'FHEE__EE_Config__get_forward',
1412
+				EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1413
+				$route,
1414
+				$status
1415
+			);
1416
+		}
1417
+		return null;
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 *    register_forward - allows modules to specify different view templates for different method routes and status
1423
+	 *    results
1424
+	 *
1425
+	 * @access    public
1426
+	 * @param    string  $route  - "pretty" public alias for module method
1427
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1428
+	 *                           allows different views to be served based on status
1429
+	 * @param    string  $view
1430
+	 * @param    string  $key    - url param key indicating a route is being called
1431
+	 * @return    bool
1432
+	 */
1433
+	public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1434
+	{
1435
+		do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1436
+		if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1437
+			$msg = sprintf(
1438
+				esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1439
+				$route
1440
+			);
1441
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1442
+			return false;
1443
+		}
1444
+		if (! is_readable($view)) {
1445
+			$msg = sprintf(
1446
+				esc_html__(
1447
+					'The %s view file could not be found or is not readable due to file permissions.',
1448
+					'event_espresso'
1449
+				),
1450
+				$view
1451
+			);
1452
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1453
+			return false;
1454
+		}
1455
+		EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1456
+		return true;
1457
+	}
1458
+
1459
+
1460
+	/**
1461
+	 *    get_view - get view for route and status
1462
+	 *
1463
+	 * @access    public
1464
+	 * @param    string  $route  - "pretty" public alias for module method
1465
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1466
+	 *                           allows different views to be served based on status
1467
+	 * @param    string  $key    - url param key indicating a route is being called
1468
+	 * @return    string
1469
+	 */
1470
+	public static function get_view($route = null, $status = 0, $key = 'ee')
1471
+	{
1472
+		do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1473
+		if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1474
+			return apply_filters(
1475
+				'FHEE__EE_Config__get_view',
1476
+				EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1477
+				$route,
1478
+				$status
1479
+			);
1480
+		}
1481
+		return null;
1482
+	}
1483
+
1484
+
1485
+	public function update_addon_option_names()
1486
+	{
1487
+		update_option(EE_Config::ADDON_OPTION_NAMES, $this->_addon_option_names);
1488
+	}
1489
+
1490
+
1491
+	public function shutdown()
1492
+	{
1493
+		$this->update_addon_option_names();
1494
+	}
1495
+
1496
+
1497
+	/**
1498
+	 * @return LegacyShortcodesManager
1499
+	 */
1500
+	public static function getLegacyShortcodesManager()
1501
+	{
1502
+		if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1503
+			EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1504
+				LegacyShortcodesManager::class
1505
+			);
1506
+		}
1507
+		return EE_Config::instance()->legacy_shortcodes_manager;
1508
+	}
1509
+
1510
+
1511
+	/**
1512
+	 * register_shortcode - makes core aware of this shortcode
1513
+	 *
1514
+	 * @deprecated 4.9.26
1515
+	 * @param    string $shortcode_path - full path up to and including shortcode folder
1516
+	 * @return    bool
1517
+	 */
1518
+	public static function register_shortcode($shortcode_path = null)
1519
+	{
1520
+		EE_Error::doing_it_wrong(
1521
+			__METHOD__,
1522
+			esc_html__(
1523
+				'Usage is deprecated. Use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::registerShortcode() as direct replacement, or better yet, please see the new \EventEspresso\core\services\shortcodes\ShortcodesManager class.',
1524
+				'event_espresso'
1525
+			),
1526
+			'4.9.26'
1527
+		);
1528
+		return EE_Config::instance()->getLegacyShortcodesManager()->registerShortcode($shortcode_path);
1529
+	}
1530 1530
 }
1531 1531
 
1532 1532
 /**
@@ -1536,98 +1536,98 @@  discard block
 block discarded – undo
1536 1536
  */
1537 1537
 class EE_Config_Base
1538 1538
 {
1539
-    /**
1540
-     * Utility function for escaping the value of a property and returning.
1541
-     *
1542
-     * @param string $property property name (checks to see if exists).
1543
-     * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1544
-     * @throws EE_Error
1545
-     */
1546
-    public function get_pretty($property)
1547
-    {
1548
-        if (! property_exists($this, $property)) {
1549
-            throw new EE_Error(
1550
-                sprintf(
1551
-                    esc_html__(
1552
-                        '%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.',
1553
-                        'event_espresso'
1554
-                    ),
1555
-                    get_class($this),
1556
-                    $property
1557
-                )
1558
-            );
1559
-        }
1560
-        // just handling escaping of strings for now.
1561
-        if (is_string($this->{$property})) {
1562
-            return stripslashes($this->{$property});
1563
-        }
1564
-        return $this->{$property};
1565
-    }
1566
-
1567
-
1568
-    public function populate()
1569
-    {
1570
-        // grab defaults via a new instance of this class.
1571
-        $class_name = get_class($this);
1572
-        $defaults = new $class_name();
1573
-        // loop through the properties for this class and see if they are set.  If they are NOT, then grab the
1574
-        // default from our $defaults object.
1575
-        foreach (get_object_vars($defaults) as $property => $value) {
1576
-            if ($this->{$property} === null) {
1577
-                $this->{$property} = $value;
1578
-            }
1579
-        }
1580
-        // cleanup
1581
-        unset($defaults);
1582
-    }
1583
-
1584
-
1585
-    /**
1586
-     *        __isset
1587
-     *
1588
-     * @param $a
1589
-     * @return bool
1590
-     */
1591
-    public function __isset($a)
1592
-    {
1593
-        return false;
1594
-    }
1595
-
1596
-
1597
-    /**
1598
-     *        __unset
1599
-     *
1600
-     * @param $a
1601
-     * @return bool
1602
-     */
1603
-    public function __unset($a)
1604
-    {
1605
-        return false;
1606
-    }
1607
-
1608
-
1609
-    /**
1610
-     *        __clone
1611
-     */
1612
-    public function __clone()
1613
-    {
1614
-    }
1615
-
1616
-
1617
-    /**
1618
-     *        __wakeup
1619
-     */
1620
-    public function __wakeup()
1621
-    {
1622
-    }
1623
-
1624
-
1625
-    /**
1626
-     *        __destruct
1627
-     */
1628
-    public function __destruct()
1629
-    {
1630
-    }
1539
+	/**
1540
+	 * Utility function for escaping the value of a property and returning.
1541
+	 *
1542
+	 * @param string $property property name (checks to see if exists).
1543
+	 * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1544
+	 * @throws EE_Error
1545
+	 */
1546
+	public function get_pretty($property)
1547
+	{
1548
+		if (! property_exists($this, $property)) {
1549
+			throw new EE_Error(
1550
+				sprintf(
1551
+					esc_html__(
1552
+						'%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.',
1553
+						'event_espresso'
1554
+					),
1555
+					get_class($this),
1556
+					$property
1557
+				)
1558
+			);
1559
+		}
1560
+		// just handling escaping of strings for now.
1561
+		if (is_string($this->{$property})) {
1562
+			return stripslashes($this->{$property});
1563
+		}
1564
+		return $this->{$property};
1565
+	}
1566
+
1567
+
1568
+	public function populate()
1569
+	{
1570
+		// grab defaults via a new instance of this class.
1571
+		$class_name = get_class($this);
1572
+		$defaults = new $class_name();
1573
+		// loop through the properties for this class and see if they are set.  If they are NOT, then grab the
1574
+		// default from our $defaults object.
1575
+		foreach (get_object_vars($defaults) as $property => $value) {
1576
+			if ($this->{$property} === null) {
1577
+				$this->{$property} = $value;
1578
+			}
1579
+		}
1580
+		// cleanup
1581
+		unset($defaults);
1582
+	}
1583
+
1584
+
1585
+	/**
1586
+	 *        __isset
1587
+	 *
1588
+	 * @param $a
1589
+	 * @return bool
1590
+	 */
1591
+	public function __isset($a)
1592
+	{
1593
+		return false;
1594
+	}
1595
+
1596
+
1597
+	/**
1598
+	 *        __unset
1599
+	 *
1600
+	 * @param $a
1601
+	 * @return bool
1602
+	 */
1603
+	public function __unset($a)
1604
+	{
1605
+		return false;
1606
+	}
1607
+
1608
+
1609
+	/**
1610
+	 *        __clone
1611
+	 */
1612
+	public function __clone()
1613
+	{
1614
+	}
1615
+
1616
+
1617
+	/**
1618
+	 *        __wakeup
1619
+	 */
1620
+	public function __wakeup()
1621
+	{
1622
+	}
1623
+
1624
+
1625
+	/**
1626
+	 *        __destruct
1627
+	 */
1628
+	public function __destruct()
1629
+	{
1630
+	}
1631 1631
 }
1632 1632
 
1633 1633
 /**
@@ -1635,304 +1635,304 @@  discard block
 block discarded – undo
1635 1635
  */
1636 1636
 class EE_Core_Config extends EE_Config_Base
1637 1637
 {
1638
-    const OPTION_NAME_UXIP = 'ee_ueip_optin';
1639
-
1640
-
1641
-    public $current_blog_id;
1642
-
1643
-    public $ee_ueip_optin;
1644
-
1645
-    public $ee_ueip_has_notified;
1646
-
1647
-    /**
1648
-     * Not to be confused with the 4 critical page variables (See
1649
-     * get_critical_pages_array()), this is just an array of wp posts that have EE
1650
-     * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode
1651
-     * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array.
1652
-     *
1653
-     * @var array
1654
-     */
1655
-    public $post_shortcodes;
1656
-
1657
-    public $module_route_map;
1658
-
1659
-    public $module_forward_map;
1660
-
1661
-    public $module_view_map;
1662
-
1663
-    /**
1664
-     * The next 4 vars are the IDs of critical EE pages.
1665
-     *
1666
-     * @var int
1667
-     */
1668
-    public $reg_page_id;
1669
-
1670
-    public $txn_page_id;
1671
-
1672
-    public $thank_you_page_id;
1673
-
1674
-    public $cancel_page_id;
1675
-
1676
-    /**
1677
-     * The next 4 vars are the URLs of critical EE pages.
1678
-     *
1679
-     * @var int
1680
-     */
1681
-    public $reg_page_url;
1682
-
1683
-    public $txn_page_url;
1684
-
1685
-    public $thank_you_page_url;
1686
-
1687
-    public $cancel_page_url;
1688
-
1689
-    /**
1690
-     * The next vars relate to the custom slugs for EE CPT routes
1691
-     */
1692
-    public $event_cpt_slug;
1693
-
1694
-    /**
1695
-     * This caches the _ee_ueip_option in case this config is reset in the same
1696
-     * request across blog switches in a multisite context.
1697
-     * Avoids extra queries to the db for this option.
1698
-     *
1699
-     * @var bool
1700
-     */
1701
-    public static $ee_ueip_option;
1702
-
1703
-
1704
-    /**
1705
-     *    class constructor
1706
-     *
1707
-     * @access    public
1708
-     */
1709
-    public function __construct()
1710
-    {
1711
-        // set default organization settings
1712
-        $this->current_blog_id = get_current_blog_id();
1713
-        $this->current_blog_id = $this->current_blog_id === null ? 1 : $this->current_blog_id;
1714
-        $this->ee_ueip_optin = $this->_get_main_ee_ueip_optin();
1715
-        $this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true;
1716
-        $this->post_shortcodes = array();
1717
-        $this->module_route_map = array();
1718
-        $this->module_forward_map = array();
1719
-        $this->module_view_map = array();
1720
-        // critical EE page IDs
1721
-        $this->reg_page_id = 0;
1722
-        $this->txn_page_id = 0;
1723
-        $this->thank_you_page_id = 0;
1724
-        $this->cancel_page_id = 0;
1725
-        // critical EE page URLs
1726
-        $this->reg_page_url = '';
1727
-        $this->txn_page_url = '';
1728
-        $this->thank_you_page_url = '';
1729
-        $this->cancel_page_url = '';
1730
-        // cpt slugs
1731
-        $this->event_cpt_slug = esc_html__('events', 'event_espresso');
1732
-        // ueip constant check
1733
-        if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) {
1734
-            $this->ee_ueip_optin = false;
1735
-            $this->ee_ueip_has_notified = true;
1736
-        }
1737
-    }
1738
-
1739
-
1740
-    /**
1741
-     * @return array
1742
-     */
1743
-    public function get_critical_pages_array()
1744
-    {
1745
-        return array(
1746
-            $this->reg_page_id,
1747
-            $this->txn_page_id,
1748
-            $this->thank_you_page_id,
1749
-            $this->cancel_page_id,
1750
-        );
1751
-    }
1752
-
1753
-
1754
-    /**
1755
-     * @return array
1756
-     */
1757
-    public function get_critical_pages_shortcodes_array()
1758
-    {
1759
-        return array(
1760
-            $this->reg_page_id       => 'ESPRESSO_CHECKOUT',
1761
-            $this->txn_page_id       => 'ESPRESSO_TXN_PAGE',
1762
-            $this->thank_you_page_id => 'ESPRESSO_THANK_YOU',
1763
-            $this->cancel_page_id    => 'ESPRESSO_CANCELLED',
1764
-        );
1765
-    }
1766
-
1767
-
1768
-    /**
1769
-     *  gets/returns URL for EE reg_page
1770
-     *
1771
-     * @access    public
1772
-     * @return    string
1773
-     */
1774
-    public function reg_page_url()
1775
-    {
1776
-        if (! $this->reg_page_url) {
1777
-            $this->reg_page_url = add_query_arg(
1778
-                array('uts' => time()),
1779
-                get_permalink($this->reg_page_id)
1780
-            ) . '#checkout';
1781
-        }
1782
-        return $this->reg_page_url;
1783
-    }
1784
-
1785
-
1786
-    /**
1787
-     *  gets/returns URL for EE txn_page
1788
-     *
1789
-     * @param array $query_args like what gets passed to
1790
-     *                          add_query_arg() as the first argument
1791
-     * @access    public
1792
-     * @return    string
1793
-     */
1794
-    public function txn_page_url($query_args = array())
1795
-    {
1796
-        if (! $this->txn_page_url) {
1797
-            $this->txn_page_url = get_permalink($this->txn_page_id);
1798
-        }
1799
-        if ($query_args) {
1800
-            return add_query_arg($query_args, $this->txn_page_url);
1801
-        } else {
1802
-            return $this->txn_page_url;
1803
-        }
1804
-    }
1805
-
1806
-
1807
-    /**
1808
-     *  gets/returns URL for EE thank_you_page
1809
-     *
1810
-     * @param array $query_args like what gets passed to
1811
-     *                          add_query_arg() as the first argument
1812
-     * @access    public
1813
-     * @return    string
1814
-     */
1815
-    public function thank_you_page_url($query_args = array())
1816
-    {
1817
-        if (! $this->thank_you_page_url) {
1818
-            $this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1819
-        }
1820
-        if ($query_args) {
1821
-            return add_query_arg($query_args, $this->thank_you_page_url);
1822
-        } else {
1823
-            return $this->thank_you_page_url;
1824
-        }
1825
-    }
1826
-
1827
-
1828
-    /**
1829
-     *  gets/returns URL for EE cancel_page
1830
-     *
1831
-     * @access    public
1832
-     * @return    string
1833
-     */
1834
-    public function cancel_page_url()
1835
-    {
1836
-        if (! $this->cancel_page_url) {
1837
-            $this->cancel_page_url = get_permalink($this->cancel_page_id);
1838
-        }
1839
-        return $this->cancel_page_url;
1840
-    }
1841
-
1842
-
1843
-    /**
1844
-     * Resets all critical page urls to their original state.  Used primarily by the __sleep() magic method currently.
1845
-     *
1846
-     * @since 4.7.5
1847
-     */
1848
-    protected function _reset_urls()
1849
-    {
1850
-        $this->reg_page_url = '';
1851
-        $this->txn_page_url = '';
1852
-        $this->cancel_page_url = '';
1853
-        $this->thank_you_page_url = '';
1854
-    }
1855
-
1856
-
1857
-    /**
1858
-     * Used to return what the optin value is set for the EE User Experience Program.
1859
-     * This accounts for multisite and this value being requested for a subsite.  In multisite, the value is set
1860
-     * on the main site only.
1861
-     *
1862
-     * @return bool
1863
-     */
1864
-    protected function _get_main_ee_ueip_optin()
1865
-    {
1866
-        // if this is the main site then we can just bypass our direct query.
1867
-        if (is_main_site()) {
1868
-            return get_option(self::OPTION_NAME_UXIP, false);
1869
-        }
1870
-        // is this already cached for this request?  If so use it.
1871
-        if (EE_Core_Config::$ee_ueip_option !== null) {
1872
-            return EE_Core_Config::$ee_ueip_option;
1873
-        }
1874
-        global $wpdb;
1875
-        $current_network_main_site = is_multisite() ? get_current_site() : null;
1876
-        $current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1877
-        $option = self::OPTION_NAME_UXIP;
1878
-        // set correct table for query
1879
-        $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1880
-        // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1881
-        // get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1882
-        // re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1883
-        // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1884
-        // for the purpose of caching.
1885
-        $pre = apply_filters('pre_option_' . $option, false, $option);
1886
-        if (false !== $pre) {
1887
-            EE_Core_Config::$ee_ueip_option = $pre;
1888
-            return EE_Core_Config::$ee_ueip_option;
1889
-        }
1890
-        $row = $wpdb->get_row(
1891
-            $wpdb->prepare(
1892
-                "SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1",
1893
-                $option
1894
-            )
1895
-        );
1896
-        if (is_object($row)) {
1897
-            $value = $row->option_value;
1898
-        } else { // option does not exist so use default.
1899
-            EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1900
-            return EE_Core_Config::$ee_ueip_option;
1901
-        }
1902
-        EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1903
-        return EE_Core_Config::$ee_ueip_option;
1904
-    }
1905
-
1906
-
1907
-    /**
1908
-     * Utility function for escaping the value of a property and returning.
1909
-     *
1910
-     * @param string $property property name (checks to see if exists).
1911
-     * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1912
-     * @throws EE_Error
1913
-     */
1914
-    public function get_pretty($property)
1915
-    {
1916
-        if ($property === self::OPTION_NAME_UXIP) {
1917
-            return $this->ee_ueip_optin ? 'yes' : 'no';
1918
-        }
1919
-        return parent::get_pretty($property);
1920
-    }
1921
-
1922
-
1923
-    /**
1924
-     * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values
1925
-     * on the object.
1926
-     *
1927
-     * @return array
1928
-     */
1929
-    public function __sleep()
1930
-    {
1931
-        // reset all url properties
1932
-        $this->_reset_urls();
1933
-        // return what to save to db
1934
-        return array_keys(get_object_vars($this));
1935
-    }
1638
+	const OPTION_NAME_UXIP = 'ee_ueip_optin';
1639
+
1640
+
1641
+	public $current_blog_id;
1642
+
1643
+	public $ee_ueip_optin;
1644
+
1645
+	public $ee_ueip_has_notified;
1646
+
1647
+	/**
1648
+	 * Not to be confused with the 4 critical page variables (See
1649
+	 * get_critical_pages_array()), this is just an array of wp posts that have EE
1650
+	 * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode
1651
+	 * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array.
1652
+	 *
1653
+	 * @var array
1654
+	 */
1655
+	public $post_shortcodes;
1656
+
1657
+	public $module_route_map;
1658
+
1659
+	public $module_forward_map;
1660
+
1661
+	public $module_view_map;
1662
+
1663
+	/**
1664
+	 * The next 4 vars are the IDs of critical EE pages.
1665
+	 *
1666
+	 * @var int
1667
+	 */
1668
+	public $reg_page_id;
1669
+
1670
+	public $txn_page_id;
1671
+
1672
+	public $thank_you_page_id;
1673
+
1674
+	public $cancel_page_id;
1675
+
1676
+	/**
1677
+	 * The next 4 vars are the URLs of critical EE pages.
1678
+	 *
1679
+	 * @var int
1680
+	 */
1681
+	public $reg_page_url;
1682
+
1683
+	public $txn_page_url;
1684
+
1685
+	public $thank_you_page_url;
1686
+
1687
+	public $cancel_page_url;
1688
+
1689
+	/**
1690
+	 * The next vars relate to the custom slugs for EE CPT routes
1691
+	 */
1692
+	public $event_cpt_slug;
1693
+
1694
+	/**
1695
+	 * This caches the _ee_ueip_option in case this config is reset in the same
1696
+	 * request across blog switches in a multisite context.
1697
+	 * Avoids extra queries to the db for this option.
1698
+	 *
1699
+	 * @var bool
1700
+	 */
1701
+	public static $ee_ueip_option;
1702
+
1703
+
1704
+	/**
1705
+	 *    class constructor
1706
+	 *
1707
+	 * @access    public
1708
+	 */
1709
+	public function __construct()
1710
+	{
1711
+		// set default organization settings
1712
+		$this->current_blog_id = get_current_blog_id();
1713
+		$this->current_blog_id = $this->current_blog_id === null ? 1 : $this->current_blog_id;
1714
+		$this->ee_ueip_optin = $this->_get_main_ee_ueip_optin();
1715
+		$this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true;
1716
+		$this->post_shortcodes = array();
1717
+		$this->module_route_map = array();
1718
+		$this->module_forward_map = array();
1719
+		$this->module_view_map = array();
1720
+		// critical EE page IDs
1721
+		$this->reg_page_id = 0;
1722
+		$this->txn_page_id = 0;
1723
+		$this->thank_you_page_id = 0;
1724
+		$this->cancel_page_id = 0;
1725
+		// critical EE page URLs
1726
+		$this->reg_page_url = '';
1727
+		$this->txn_page_url = '';
1728
+		$this->thank_you_page_url = '';
1729
+		$this->cancel_page_url = '';
1730
+		// cpt slugs
1731
+		$this->event_cpt_slug = esc_html__('events', 'event_espresso');
1732
+		// ueip constant check
1733
+		if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) {
1734
+			$this->ee_ueip_optin = false;
1735
+			$this->ee_ueip_has_notified = true;
1736
+		}
1737
+	}
1738
+
1739
+
1740
+	/**
1741
+	 * @return array
1742
+	 */
1743
+	public function get_critical_pages_array()
1744
+	{
1745
+		return array(
1746
+			$this->reg_page_id,
1747
+			$this->txn_page_id,
1748
+			$this->thank_you_page_id,
1749
+			$this->cancel_page_id,
1750
+		);
1751
+	}
1752
+
1753
+
1754
+	/**
1755
+	 * @return array
1756
+	 */
1757
+	public function get_critical_pages_shortcodes_array()
1758
+	{
1759
+		return array(
1760
+			$this->reg_page_id       => 'ESPRESSO_CHECKOUT',
1761
+			$this->txn_page_id       => 'ESPRESSO_TXN_PAGE',
1762
+			$this->thank_you_page_id => 'ESPRESSO_THANK_YOU',
1763
+			$this->cancel_page_id    => 'ESPRESSO_CANCELLED',
1764
+		);
1765
+	}
1766
+
1767
+
1768
+	/**
1769
+	 *  gets/returns URL for EE reg_page
1770
+	 *
1771
+	 * @access    public
1772
+	 * @return    string
1773
+	 */
1774
+	public function reg_page_url()
1775
+	{
1776
+		if (! $this->reg_page_url) {
1777
+			$this->reg_page_url = add_query_arg(
1778
+				array('uts' => time()),
1779
+				get_permalink($this->reg_page_id)
1780
+			) . '#checkout';
1781
+		}
1782
+		return $this->reg_page_url;
1783
+	}
1784
+
1785
+
1786
+	/**
1787
+	 *  gets/returns URL for EE txn_page
1788
+	 *
1789
+	 * @param array $query_args like what gets passed to
1790
+	 *                          add_query_arg() as the first argument
1791
+	 * @access    public
1792
+	 * @return    string
1793
+	 */
1794
+	public function txn_page_url($query_args = array())
1795
+	{
1796
+		if (! $this->txn_page_url) {
1797
+			$this->txn_page_url = get_permalink($this->txn_page_id);
1798
+		}
1799
+		if ($query_args) {
1800
+			return add_query_arg($query_args, $this->txn_page_url);
1801
+		} else {
1802
+			return $this->txn_page_url;
1803
+		}
1804
+	}
1805
+
1806
+
1807
+	/**
1808
+	 *  gets/returns URL for EE thank_you_page
1809
+	 *
1810
+	 * @param array $query_args like what gets passed to
1811
+	 *                          add_query_arg() as the first argument
1812
+	 * @access    public
1813
+	 * @return    string
1814
+	 */
1815
+	public function thank_you_page_url($query_args = array())
1816
+	{
1817
+		if (! $this->thank_you_page_url) {
1818
+			$this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1819
+		}
1820
+		if ($query_args) {
1821
+			return add_query_arg($query_args, $this->thank_you_page_url);
1822
+		} else {
1823
+			return $this->thank_you_page_url;
1824
+		}
1825
+	}
1826
+
1827
+
1828
+	/**
1829
+	 *  gets/returns URL for EE cancel_page
1830
+	 *
1831
+	 * @access    public
1832
+	 * @return    string
1833
+	 */
1834
+	public function cancel_page_url()
1835
+	{
1836
+		if (! $this->cancel_page_url) {
1837
+			$this->cancel_page_url = get_permalink($this->cancel_page_id);
1838
+		}
1839
+		return $this->cancel_page_url;
1840
+	}
1841
+
1842
+
1843
+	/**
1844
+	 * Resets all critical page urls to their original state.  Used primarily by the __sleep() magic method currently.
1845
+	 *
1846
+	 * @since 4.7.5
1847
+	 */
1848
+	protected function _reset_urls()
1849
+	{
1850
+		$this->reg_page_url = '';
1851
+		$this->txn_page_url = '';
1852
+		$this->cancel_page_url = '';
1853
+		$this->thank_you_page_url = '';
1854
+	}
1855
+
1856
+
1857
+	/**
1858
+	 * Used to return what the optin value is set for the EE User Experience Program.
1859
+	 * This accounts for multisite and this value being requested for a subsite.  In multisite, the value is set
1860
+	 * on the main site only.
1861
+	 *
1862
+	 * @return bool
1863
+	 */
1864
+	protected function _get_main_ee_ueip_optin()
1865
+	{
1866
+		// if this is the main site then we can just bypass our direct query.
1867
+		if (is_main_site()) {
1868
+			return get_option(self::OPTION_NAME_UXIP, false);
1869
+		}
1870
+		// is this already cached for this request?  If so use it.
1871
+		if (EE_Core_Config::$ee_ueip_option !== null) {
1872
+			return EE_Core_Config::$ee_ueip_option;
1873
+		}
1874
+		global $wpdb;
1875
+		$current_network_main_site = is_multisite() ? get_current_site() : null;
1876
+		$current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1877
+		$option = self::OPTION_NAME_UXIP;
1878
+		// set correct table for query
1879
+		$table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1880
+		// rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1881
+		// get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1882
+		// re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1883
+		// this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1884
+		// for the purpose of caching.
1885
+		$pre = apply_filters('pre_option_' . $option, false, $option);
1886
+		if (false !== $pre) {
1887
+			EE_Core_Config::$ee_ueip_option = $pre;
1888
+			return EE_Core_Config::$ee_ueip_option;
1889
+		}
1890
+		$row = $wpdb->get_row(
1891
+			$wpdb->prepare(
1892
+				"SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1",
1893
+				$option
1894
+			)
1895
+		);
1896
+		if (is_object($row)) {
1897
+			$value = $row->option_value;
1898
+		} else { // option does not exist so use default.
1899
+			EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1900
+			return EE_Core_Config::$ee_ueip_option;
1901
+		}
1902
+		EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1903
+		return EE_Core_Config::$ee_ueip_option;
1904
+	}
1905
+
1906
+
1907
+	/**
1908
+	 * Utility function for escaping the value of a property and returning.
1909
+	 *
1910
+	 * @param string $property property name (checks to see if exists).
1911
+	 * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1912
+	 * @throws EE_Error
1913
+	 */
1914
+	public function get_pretty($property)
1915
+	{
1916
+		if ($property === self::OPTION_NAME_UXIP) {
1917
+			return $this->ee_ueip_optin ? 'yes' : 'no';
1918
+		}
1919
+		return parent::get_pretty($property);
1920
+	}
1921
+
1922
+
1923
+	/**
1924
+	 * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values
1925
+	 * on the object.
1926
+	 *
1927
+	 * @return array
1928
+	 */
1929
+	public function __sleep()
1930
+	{
1931
+		// reset all url properties
1932
+		$this->_reset_urls();
1933
+		// return what to save to db
1934
+		return array_keys(get_object_vars($this));
1935
+	}
1936 1936
 }
1937 1937
 
1938 1938
 /**
@@ -1940,294 +1940,294 @@  discard block
 block discarded – undo
1940 1940
  */
1941 1941
 class EE_Organization_Config extends EE_Config_Base
1942 1942
 {
1943
-    /**
1944
-     * @var string $name
1945
-     * eg EE4.1
1946
-     */
1947
-    public $name;
1948
-
1949
-    /**
1950
-     * @var string $address_1
1951
-     * eg 123 Onna Road
1952
-     */
1953
-    public $address_1 = '';
1954
-
1955
-    /**
1956
-     * @var string $address_2
1957
-     * eg PO Box 123
1958
-     */
1959
-    public $address_2 = '';
1960
-
1961
-    /**
1962
-     * @var string $city
1963
-     * eg Inna City
1964
-     */
1965
-    public $city = '';
1966
-
1967
-    /**
1968
-     * @var int $STA_ID
1969
-     * eg 4
1970
-     */
1971
-    public $STA_ID = 0;
1972
-
1973
-    /**
1974
-     * @var string $CNT_ISO
1975
-     * eg US
1976
-     */
1977
-    public $CNT_ISO = 'US';
1978
-
1979
-    /**
1980
-     * @var string $zip
1981
-     * eg 12345  or V1A 2B3
1982
-     */
1983
-    public $zip = '';
1984
-
1985
-    /**
1986
-     * @var string $email
1987
-     * eg [email protected]
1988
-     */
1989
-    public $email;
1990
-
1991
-    /**
1992
-     * @var string $phone
1993
-     * eg. 111-111-1111
1994
-     */
1995
-    public $phone = '';
1996
-
1997
-    /**
1998
-     * @var string $vat
1999
-     * VAT/Tax Number
2000
-     */
2001
-    public $vat = '';
2002
-
2003
-    /**
2004
-     * @var string $logo_url
2005
-     * eg http://www.somedomain.com/wp-content/uploads/kittehs.jpg
2006
-     */
2007
-    public $logo_url = '';
2008
-
2009
-    /**
2010
-     * The below are all various properties for holding links to organization social network profiles
2011
-     */
2012
-    /**
2013
-     * facebook (facebook.com/profile.name)
2014
-     *
2015
-     * @var string
2016
-     */
2017
-    public $facebook = '';
2018
-
2019
-    /**
2020
-     * twitter (twitter.com/twitter_handle)
2021
-     *
2022
-     * @var string
2023
-     */
2024
-    public $twitter = '';
2025
-
2026
-    /**
2027
-     * linkedin (linkedin.com/in/profile_name)
2028
-     *
2029
-     * @var string
2030
-     */
2031
-    public $linkedin = '';
2032
-
2033
-    /**
2034
-     * pinterest (www.pinterest.com/profile_name)
2035
-     *
2036
-     * @var string
2037
-     */
2038
-    public $pinterest = '';
2039
-
2040
-    /**
2041
-     * google+ (google.com/+profileName)
2042
-     *
2043
-     * @var string
2044
-     */
2045
-    public $google = '';
2046
-
2047
-    /**
2048
-     * instagram (instagram.com/handle)
2049
-     *
2050
-     * @var string
2051
-     */
2052
-    public $instagram = '';
2053
-
2054
-
2055
-    /**
2056
-     *    class constructor
2057
-     *
2058
-     * @access    public
2059
-     */
2060
-    public function __construct()
2061
-    {
2062
-        // set default organization settings
2063
-        // decode HTML entities from the WP blogname, because it's stored in the DB with HTML entities encoded
2064
-        $this->name = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
2065
-        $this->email = get_bloginfo('admin_email');
2066
-    }
2067
-}
2068
-
2069
-/**
2070
- * Class for defining what's in the EE_Config relating to currency
2071
- */
2072
-class EE_Currency_Config extends EE_Config_Base
2073
-{
2074
-    /**
2075
-     * @var string $code
2076
-     * eg 'US'
2077
-     */
2078
-    public $code;
2079
-
2080
-    /**
2081
-     * @var string $name
2082
-     * eg 'Dollar'
2083
-     */
2084
-    public $name;
2085
-
2086
-    /**
2087
-     * plural name
2088
-     *
2089
-     * @var string $plural
2090
-     * eg 'Dollars'
2091
-     */
2092
-    public $plural;
2093
-
2094
-    /**
2095
-     * currency sign
2096
-     *
2097
-     * @var string $sign
2098
-     * eg '$'
2099
-     */
2100
-    public $sign;
2101
-
2102
-    /**
2103
-     * Whether the currency sign should come before the number or not
2104
-     *
2105
-     * @var boolean $sign_b4
2106
-     */
2107
-    public $sign_b4;
2108
-
2109
-    /**
2110
-     * How many digits should come after the decimal place
2111
-     *
2112
-     * @var int $dec_plc
2113
-     */
2114
-    public $dec_plc;
2115
-
2116
-    /**
2117
-     * Symbol to use for decimal mark
2118
-     *
2119
-     * @var string $dec_mrk
2120
-     * eg '.'
2121
-     */
2122
-    public $dec_mrk;
2123
-
2124
-    /**
2125
-     * Symbol to use for thousands
2126
-     *
2127
-     * @var string $thsnds
2128
-     * eg ','
2129
-     */
2130
-    public $thsnds;
2131
-
1943
+	/**
1944
+	 * @var string $name
1945
+	 * eg EE4.1
1946
+	 */
1947
+	public $name;
1948
+
1949
+	/**
1950
+	 * @var string $address_1
1951
+	 * eg 123 Onna Road
1952
+	 */
1953
+	public $address_1 = '';
1954
+
1955
+	/**
1956
+	 * @var string $address_2
1957
+	 * eg PO Box 123
1958
+	 */
1959
+	public $address_2 = '';
1960
+
1961
+	/**
1962
+	 * @var string $city
1963
+	 * eg Inna City
1964
+	 */
1965
+	public $city = '';
1966
+
1967
+	/**
1968
+	 * @var int $STA_ID
1969
+	 * eg 4
1970
+	 */
1971
+	public $STA_ID = 0;
1972
+
1973
+	/**
1974
+	 * @var string $CNT_ISO
1975
+	 * eg US
1976
+	 */
1977
+	public $CNT_ISO = 'US';
1978
+
1979
+	/**
1980
+	 * @var string $zip
1981
+	 * eg 12345  or V1A 2B3
1982
+	 */
1983
+	public $zip = '';
1984
+
1985
+	/**
1986
+	 * @var string $email
1987
+	 * eg [email protected]
1988
+	 */
1989
+	public $email;
1990
+
1991
+	/**
1992
+	 * @var string $phone
1993
+	 * eg. 111-111-1111
1994
+	 */
1995
+	public $phone = '';
1996
+
1997
+	/**
1998
+	 * @var string $vat
1999
+	 * VAT/Tax Number
2000
+	 */
2001
+	public $vat = '';
2002
+
2003
+	/**
2004
+	 * @var string $logo_url
2005
+	 * eg http://www.somedomain.com/wp-content/uploads/kittehs.jpg
2006
+	 */
2007
+	public $logo_url = '';
2008
+
2009
+	/**
2010
+	 * The below are all various properties for holding links to organization social network profiles
2011
+	 */
2012
+	/**
2013
+	 * facebook (facebook.com/profile.name)
2014
+	 *
2015
+	 * @var string
2016
+	 */
2017
+	public $facebook = '';
2018
+
2019
+	/**
2020
+	 * twitter (twitter.com/twitter_handle)
2021
+	 *
2022
+	 * @var string
2023
+	 */
2024
+	public $twitter = '';
2025
+
2026
+	/**
2027
+	 * linkedin (linkedin.com/in/profile_name)
2028
+	 *
2029
+	 * @var string
2030
+	 */
2031
+	public $linkedin = '';
2032
+
2033
+	/**
2034
+	 * pinterest (www.pinterest.com/profile_name)
2035
+	 *
2036
+	 * @var string
2037
+	 */
2038
+	public $pinterest = '';
2039
+
2040
+	/**
2041
+	 * google+ (google.com/+profileName)
2042
+	 *
2043
+	 * @var string
2044
+	 */
2045
+	public $google = '';
2046
+
2047
+	/**
2048
+	 * instagram (instagram.com/handle)
2049
+	 *
2050
+	 * @var string
2051
+	 */
2052
+	public $instagram = '';
2053
+
2054
+
2055
+	/**
2056
+	 *    class constructor
2057
+	 *
2058
+	 * @access    public
2059
+	 */
2060
+	public function __construct()
2061
+	{
2062
+		// set default organization settings
2063
+		// decode HTML entities from the WP blogname, because it's stored in the DB with HTML entities encoded
2064
+		$this->name = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
2065
+		$this->email = get_bloginfo('admin_email');
2066
+	}
2067
+}
2132 2068
 
2133
-    /**
2134
-     * @param string|null $CNT_ISO
2135
-     * @throws EE_Error
2136
-     * @throws ReflectionException
2137
-     */
2138
-    public function __construct(?string $CNT_ISO = 'US')
2139
-    {
2140
-        if ($CNT_ISO && $CNT_ISO === $this->code) {
2141
-            return;
2142
-        }
2143
-        // get country code from organization settings or use default
2144
-        $ORG_CNT = isset(EE_Registry::instance()->CFG->organization)
2145
-                   && EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config
2146
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
2147
-            : 'US';
2148
-        // but override if requested
2149
-        $CNT_ISO = ! empty($CNT_ISO) ? $CNT_ISO : $ORG_CNT;
2150
-        // so if that all went well, and we are not in M-Mode (cuz you can't query the db in M-Mode) and double-check the countries table exists
2151
-        $this->setCurrency($CNT_ISO);
2152
-        // fallback to hardcoded defaults, in case the above failed
2153
-        if (empty($this->code)) {
2154
-            $this->setFallbackCurrency();
2155
-        }
2156
-    }
2157
-
2158
-
2159
-    /**
2160
-     * @param string|null $CNT_ISO
2161
-     * @throws EE_Error
2162
-     * @throws ReflectionException
2163
-     */
2164
-    public function setCurrency(?string $CNT_ISO = 'US')
2165
-    {
2166
-        if (empty($CNT_ISO) || ! EE_Maintenance_Mode::instance()->models_can_query()) {
2167
-            return;
2168
-        }
2169
-
2170
-        /** @var TableAnalysis $table_analysis */
2171
-        $table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
2172
-        if (! $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())) {
2173
-            return;
2174
-        }
2175
-        // retrieve the country settings from the db, just in case they have been customized
2176
-        $country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2177
-        if (! $country instanceof EE_Country) {
2178
-            throw new DomainException(
2179
-                sprintf(
2180
-                    esc_html__('Invalid Country ISO Code: %1$s', 'event_espresso'),
2181
-                    $CNT_ISO
2182
-                )
2183
-            );
2184
-        }
2185
-        $this->code    = $country->currency_code();                  // currency code: USD, CAD, EUR
2186
-        $this->name    = $country->currency_name_single();           // Dollar
2187
-        $this->plural  = $country->currency_name_plural();           // Dollars
2188
-        $this->sign    = $country->currency_sign();                  // currency sign: $
2189
-        $this->sign_b4 = $country->currency_sign_before();           // currency sign before or after
2190
-        $this->dec_plc = $country->currency_decimal_places();        // decimal places: 2 = 0.00  3 = 0.000
2191
-        $this->dec_mrk = $country->currency_decimal_mark();          // decimal mark: ',' = 0,01 or '.' = 0.01
2192
-        $this->thsnds  = $country->currency_thousands_separator();   // thousands sep: ',' = 1,000 or '.' = 1.000
2193
-    }
2194
-
2195
-
2196
-    private function setFallbackCurrency()
2197
-    {
2198
-        // set default currency settings
2199
-        $this->code    = 'USD';
2200
-        $this->name    = esc_html__('Dollar', 'event_espresso');
2201
-        $this->plural  = esc_html__('Dollars', 'event_espresso');
2202
-        $this->sign    = '$';
2203
-        $this->sign_b4 = true;
2204
-        $this->dec_plc = 2;
2205
-        $this->dec_mrk = '.';
2206
-        $this->thsnds  = ',';
2207
-    }
2208
-
2209
-
2210
-    /**
2211
-     * @param string|null $CNT_ISO
2212
-     * @return EE_Currency_Config
2213
-     * @throws EE_Error
2214
-     * @throws ReflectionException
2215
-     */
2216
-    public static function getCurrencyConfig(?string $CNT_ISO = ''): EE_Currency_Config
2217
-    {
2218
-        // if CNT_ISO passed lets try to get currency settings for it.
2219
-        $currency_config = ! empty($CNT_ISO)
2220
-            ? new EE_Currency_Config($CNT_ISO)
2221
-            : null;
2222
-        // default currency settings for site if not set
2223
-        if ($currency_config instanceof EE_Currency_Config) {
2224
-            return $currency_config;
2225
-        }
2226
-        EE_Config::instance()->currency = EE_Config::instance()->currency instanceof EE_Currency_Config
2227
-            ? EE_Config::instance()->currency
2228
-            : new EE_Currency_Config();
2229
-        return EE_Config::instance()->currency;
2230
-    }
2069
+/**
2070
+ * Class for defining what's in the EE_Config relating to currency
2071
+ */
2072
+class EE_Currency_Config extends EE_Config_Base
2073
+{
2074
+	/**
2075
+	 * @var string $code
2076
+	 * eg 'US'
2077
+	 */
2078
+	public $code;
2079
+
2080
+	/**
2081
+	 * @var string $name
2082
+	 * eg 'Dollar'
2083
+	 */
2084
+	public $name;
2085
+
2086
+	/**
2087
+	 * plural name
2088
+	 *
2089
+	 * @var string $plural
2090
+	 * eg 'Dollars'
2091
+	 */
2092
+	public $plural;
2093
+
2094
+	/**
2095
+	 * currency sign
2096
+	 *
2097
+	 * @var string $sign
2098
+	 * eg '$'
2099
+	 */
2100
+	public $sign;
2101
+
2102
+	/**
2103
+	 * Whether the currency sign should come before the number or not
2104
+	 *
2105
+	 * @var boolean $sign_b4
2106
+	 */
2107
+	public $sign_b4;
2108
+
2109
+	/**
2110
+	 * How many digits should come after the decimal place
2111
+	 *
2112
+	 * @var int $dec_plc
2113
+	 */
2114
+	public $dec_plc;
2115
+
2116
+	/**
2117
+	 * Symbol to use for decimal mark
2118
+	 *
2119
+	 * @var string $dec_mrk
2120
+	 * eg '.'
2121
+	 */
2122
+	public $dec_mrk;
2123
+
2124
+	/**
2125
+	 * Symbol to use for thousands
2126
+	 *
2127
+	 * @var string $thsnds
2128
+	 * eg ','
2129
+	 */
2130
+	public $thsnds;
2131
+
2132
+
2133
+	/**
2134
+	 * @param string|null $CNT_ISO
2135
+	 * @throws EE_Error
2136
+	 * @throws ReflectionException
2137
+	 */
2138
+	public function __construct(?string $CNT_ISO = 'US')
2139
+	{
2140
+		if ($CNT_ISO && $CNT_ISO === $this->code) {
2141
+			return;
2142
+		}
2143
+		// get country code from organization settings or use default
2144
+		$ORG_CNT = isset(EE_Registry::instance()->CFG->organization)
2145
+				   && EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config
2146
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
2147
+			: 'US';
2148
+		// but override if requested
2149
+		$CNT_ISO = ! empty($CNT_ISO) ? $CNT_ISO : $ORG_CNT;
2150
+		// so if that all went well, and we are not in M-Mode (cuz you can't query the db in M-Mode) and double-check the countries table exists
2151
+		$this->setCurrency($CNT_ISO);
2152
+		// fallback to hardcoded defaults, in case the above failed
2153
+		if (empty($this->code)) {
2154
+			$this->setFallbackCurrency();
2155
+		}
2156
+	}
2157
+
2158
+
2159
+	/**
2160
+	 * @param string|null $CNT_ISO
2161
+	 * @throws EE_Error
2162
+	 * @throws ReflectionException
2163
+	 */
2164
+	public function setCurrency(?string $CNT_ISO = 'US')
2165
+	{
2166
+		if (empty($CNT_ISO) || ! EE_Maintenance_Mode::instance()->models_can_query()) {
2167
+			return;
2168
+		}
2169
+
2170
+		/** @var TableAnalysis $table_analysis */
2171
+		$table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
2172
+		if (! $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())) {
2173
+			return;
2174
+		}
2175
+		// retrieve the country settings from the db, just in case they have been customized
2176
+		$country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2177
+		if (! $country instanceof EE_Country) {
2178
+			throw new DomainException(
2179
+				sprintf(
2180
+					esc_html__('Invalid Country ISO Code: %1$s', 'event_espresso'),
2181
+					$CNT_ISO
2182
+				)
2183
+			);
2184
+		}
2185
+		$this->code    = $country->currency_code();                  // currency code: USD, CAD, EUR
2186
+		$this->name    = $country->currency_name_single();           // Dollar
2187
+		$this->plural  = $country->currency_name_plural();           // Dollars
2188
+		$this->sign    = $country->currency_sign();                  // currency sign: $
2189
+		$this->sign_b4 = $country->currency_sign_before();           // currency sign before or after
2190
+		$this->dec_plc = $country->currency_decimal_places();        // decimal places: 2 = 0.00  3 = 0.000
2191
+		$this->dec_mrk = $country->currency_decimal_mark();          // decimal mark: ',' = 0,01 or '.' = 0.01
2192
+		$this->thsnds  = $country->currency_thousands_separator();   // thousands sep: ',' = 1,000 or '.' = 1.000
2193
+	}
2194
+
2195
+
2196
+	private function setFallbackCurrency()
2197
+	{
2198
+		// set default currency settings
2199
+		$this->code    = 'USD';
2200
+		$this->name    = esc_html__('Dollar', 'event_espresso');
2201
+		$this->plural  = esc_html__('Dollars', 'event_espresso');
2202
+		$this->sign    = '$';
2203
+		$this->sign_b4 = true;
2204
+		$this->dec_plc = 2;
2205
+		$this->dec_mrk = '.';
2206
+		$this->thsnds  = ',';
2207
+	}
2208
+
2209
+
2210
+	/**
2211
+	 * @param string|null $CNT_ISO
2212
+	 * @return EE_Currency_Config
2213
+	 * @throws EE_Error
2214
+	 * @throws ReflectionException
2215
+	 */
2216
+	public static function getCurrencyConfig(?string $CNT_ISO = ''): EE_Currency_Config
2217
+	{
2218
+		// if CNT_ISO passed lets try to get currency settings for it.
2219
+		$currency_config = ! empty($CNT_ISO)
2220
+			? new EE_Currency_Config($CNT_ISO)
2221
+			: null;
2222
+		// default currency settings for site if not set
2223
+		if ($currency_config instanceof EE_Currency_Config) {
2224
+			return $currency_config;
2225
+		}
2226
+		EE_Config::instance()->currency = EE_Config::instance()->currency instanceof EE_Currency_Config
2227
+			? EE_Config::instance()->currency
2228
+			: new EE_Currency_Config();
2229
+		return EE_Config::instance()->currency;
2230
+	}
2231 2231
 }
2232 2232
 
2233 2233
 /**
@@ -2235,379 +2235,379 @@  discard block
 block discarded – undo
2235 2235
  */
2236 2236
 class EE_Registration_Config extends EE_Config_Base
2237 2237
 {
2238
-    /**
2239
-     * Default registration status
2240
-     *
2241
-     * @var string $default_STS_ID
2242
-     * eg 'RPP'
2243
-     */
2244
-    public $default_STS_ID;
2245
-
2246
-    /**
2247
-     * For new events, this will be the default value for the maximum number of tickets (equivalent to maximum number of
2248
-     * registrations)
2249
-     *
2250
-     * @var int
2251
-     */
2252
-    public $default_maximum_number_of_tickets;
2253
-
2254
-    /**
2255
-     * level of validation to apply to email addresses
2256
-     *
2257
-     * @var string $email_validation_level
2258
-     * options: 'basic', 'wp_default', 'i18n', 'i18n_dns'
2259
-     */
2260
-    public $email_validation_level;
2261
-
2262
-    /**
2263
-     *    whether or not to show alternate payment options during the reg process if payment status is pending
2264
-     *
2265
-     * @var boolean $show_pending_payment_options
2266
-     */
2267
-    public $show_pending_payment_options;
2268
-
2269
-    /**
2270
-     * an array of SPCO reg steps where:
2271
-     *        the keys denotes the reg step order
2272
-     *        each element consists of an array with the following elements:
2273
-     *            "file_path" => the file path to the EE_SPCO_Reg_Step class
2274
-     *            "class_name" => the specific EE_SPCO_Reg_Step child class name
2275
-     *            "slug" => the URL param used to trigger the reg step
2276
-     *
2277
-     * @var array $reg_steps
2278
-     */
2279
-    public $reg_steps;
2280
-
2281
-    /**
2282
-     * Whether registration confirmation should be the last page of SPCO
2283
-     *
2284
-     * @var boolean $reg_confirmation_last
2285
-     */
2286
-    public $reg_confirmation_last;
2287
-
2288
-    /**
2289
-     * Whether or not to enable the EE Bot Trap
2290
-     *
2291
-     * @var boolean $use_bot_trap
2292
-     */
2293
-    public $use_bot_trap;
2294
-
2295
-    /**
2296
-     * Whether or not to encrypt some data sent by the EE Bot Trap
2297
-     *
2298
-     * @var boolean $use_encryption
2299
-     */
2300
-    public $use_encryption;
2301
-
2302
-    /**
2303
-     * Whether or not to use ReCaptcha
2304
-     *
2305
-     * @var boolean $use_captcha
2306
-     */
2307
-    public $use_captcha;
2308
-
2309
-    /**
2310
-     * ReCaptcha Theme
2311
-     *
2312
-     * @var string $recaptcha_theme
2313
-     *    options: 'dark', 'light', 'invisible'
2314
-     */
2315
-    public $recaptcha_theme;
2316
-
2317
-    /**
2318
-     * ReCaptcha Badge - determines the position of the reCAPTCHA badge if using Invisible ReCaptcha.
2319
-     *
2320
-     * @var string $recaptcha_badge
2321
-     *    options: 'bottomright', 'bottomleft', 'inline'
2322
-     */
2323
-    public $recaptcha_badge;
2324
-
2325
-    /**
2326
-     * ReCaptcha Type
2327
-     *
2328
-     * @var string $recaptcha_type
2329
-     *    options: 'audio', 'image'
2330
-     */
2331
-    public $recaptcha_type;
2332
-
2333
-    /**
2334
-     * ReCaptcha language
2335
-     *
2336
-     * @var string $recaptcha_language
2337
-     * eg 'en'
2338
-     */
2339
-    public $recaptcha_language;
2340
-
2341
-    /**
2342
-     * ReCaptcha public key
2343
-     *
2344
-     * @var string $recaptcha_publickey
2345
-     */
2346
-    public $recaptcha_publickey;
2347
-
2348
-    /**
2349
-     * ReCaptcha private key
2350
-     *
2351
-     * @var string $recaptcha_privatekey
2352
-     */
2353
-    public $recaptcha_privatekey;
2354
-
2355
-    /**
2356
-     * array of form names protected by ReCaptcha
2357
-     *
2358
-     * @var array $recaptcha_protected_forms
2359
-     */
2360
-    public $recaptcha_protected_forms;
2361
-
2362
-    /**
2363
-     * ReCaptcha width
2364
-     *
2365
-     * @var int $recaptcha_width
2366
-     * @deprecated
2367
-     */
2368
-    public $recaptcha_width;
2369
-
2370
-    /**
2371
-     * Whether or not invalid attempts to directly access the registration checkout page should be tracked.
2372
-     *
2373
-     * @var boolean $track_invalid_checkout_access
2374
-     */
2375
-    protected $track_invalid_checkout_access = true;
2376
-
2377
-    /**
2378
-     * Whether or not to show the privacy policy consent checkbox
2379
-     *
2380
-     * @var bool
2381
-     */
2382
-    public $consent_checkbox_enabled;
2383
-
2384
-    /**
2385
-     * Label text to show on the checkbox
2386
-     *
2387
-     * @var string
2388
-     */
2389
-    public $consent_checkbox_label_text;
2390
-
2391
-    /*
2238
+	/**
2239
+	 * Default registration status
2240
+	 *
2241
+	 * @var string $default_STS_ID
2242
+	 * eg 'RPP'
2243
+	 */
2244
+	public $default_STS_ID;
2245
+
2246
+	/**
2247
+	 * For new events, this will be the default value for the maximum number of tickets (equivalent to maximum number of
2248
+	 * registrations)
2249
+	 *
2250
+	 * @var int
2251
+	 */
2252
+	public $default_maximum_number_of_tickets;
2253
+
2254
+	/**
2255
+	 * level of validation to apply to email addresses
2256
+	 *
2257
+	 * @var string $email_validation_level
2258
+	 * options: 'basic', 'wp_default', 'i18n', 'i18n_dns'
2259
+	 */
2260
+	public $email_validation_level;
2261
+
2262
+	/**
2263
+	 *    whether or not to show alternate payment options during the reg process if payment status is pending
2264
+	 *
2265
+	 * @var boolean $show_pending_payment_options
2266
+	 */
2267
+	public $show_pending_payment_options;
2268
+
2269
+	/**
2270
+	 * an array of SPCO reg steps where:
2271
+	 *        the keys denotes the reg step order
2272
+	 *        each element consists of an array with the following elements:
2273
+	 *            "file_path" => the file path to the EE_SPCO_Reg_Step class
2274
+	 *            "class_name" => the specific EE_SPCO_Reg_Step child class name
2275
+	 *            "slug" => the URL param used to trigger the reg step
2276
+	 *
2277
+	 * @var array $reg_steps
2278
+	 */
2279
+	public $reg_steps;
2280
+
2281
+	/**
2282
+	 * Whether registration confirmation should be the last page of SPCO
2283
+	 *
2284
+	 * @var boolean $reg_confirmation_last
2285
+	 */
2286
+	public $reg_confirmation_last;
2287
+
2288
+	/**
2289
+	 * Whether or not to enable the EE Bot Trap
2290
+	 *
2291
+	 * @var boolean $use_bot_trap
2292
+	 */
2293
+	public $use_bot_trap;
2294
+
2295
+	/**
2296
+	 * Whether or not to encrypt some data sent by the EE Bot Trap
2297
+	 *
2298
+	 * @var boolean $use_encryption
2299
+	 */
2300
+	public $use_encryption;
2301
+
2302
+	/**
2303
+	 * Whether or not to use ReCaptcha
2304
+	 *
2305
+	 * @var boolean $use_captcha
2306
+	 */
2307
+	public $use_captcha;
2308
+
2309
+	/**
2310
+	 * ReCaptcha Theme
2311
+	 *
2312
+	 * @var string $recaptcha_theme
2313
+	 *    options: 'dark', 'light', 'invisible'
2314
+	 */
2315
+	public $recaptcha_theme;
2316
+
2317
+	/**
2318
+	 * ReCaptcha Badge - determines the position of the reCAPTCHA badge if using Invisible ReCaptcha.
2319
+	 *
2320
+	 * @var string $recaptcha_badge
2321
+	 *    options: 'bottomright', 'bottomleft', 'inline'
2322
+	 */
2323
+	public $recaptcha_badge;
2324
+
2325
+	/**
2326
+	 * ReCaptcha Type
2327
+	 *
2328
+	 * @var string $recaptcha_type
2329
+	 *    options: 'audio', 'image'
2330
+	 */
2331
+	public $recaptcha_type;
2332
+
2333
+	/**
2334
+	 * ReCaptcha language
2335
+	 *
2336
+	 * @var string $recaptcha_language
2337
+	 * eg 'en'
2338
+	 */
2339
+	public $recaptcha_language;
2340
+
2341
+	/**
2342
+	 * ReCaptcha public key
2343
+	 *
2344
+	 * @var string $recaptcha_publickey
2345
+	 */
2346
+	public $recaptcha_publickey;
2347
+
2348
+	/**
2349
+	 * ReCaptcha private key
2350
+	 *
2351
+	 * @var string $recaptcha_privatekey
2352
+	 */
2353
+	public $recaptcha_privatekey;
2354
+
2355
+	/**
2356
+	 * array of form names protected by ReCaptcha
2357
+	 *
2358
+	 * @var array $recaptcha_protected_forms
2359
+	 */
2360
+	public $recaptcha_protected_forms;
2361
+
2362
+	/**
2363
+	 * ReCaptcha width
2364
+	 *
2365
+	 * @var int $recaptcha_width
2366
+	 * @deprecated
2367
+	 */
2368
+	public $recaptcha_width;
2369
+
2370
+	/**
2371
+	 * Whether or not invalid attempts to directly access the registration checkout page should be tracked.
2372
+	 *
2373
+	 * @var boolean $track_invalid_checkout_access
2374
+	 */
2375
+	protected $track_invalid_checkout_access = true;
2376
+
2377
+	/**
2378
+	 * Whether or not to show the privacy policy consent checkbox
2379
+	 *
2380
+	 * @var bool
2381
+	 */
2382
+	public $consent_checkbox_enabled;
2383
+
2384
+	/**
2385
+	 * Label text to show on the checkbox
2386
+	 *
2387
+	 * @var string
2388
+	 */
2389
+	public $consent_checkbox_label_text;
2390
+
2391
+	/*
2392 2392
      * String describing how long to keep payment logs. Passed into DateTime constructor
2393 2393
      * @var string
2394 2394
      */
2395
-    public $gateway_log_lifespan = '1 week';
2396
-
2397
-    /**
2398
-     * Enable copy attendee info at form
2399
-     *
2400
-     * @var boolean $enable_copy_attendee
2401
-     */
2402
-    protected $copy_attendee_info = true;
2403
-
2404
-
2405
-    /**
2406
-     *    class constructor
2407
-     *
2408
-     * @access    public
2409
-     */
2410
-    public function __construct()
2411
-    {
2412
-        // set default registration settings
2413
-        $this->default_STS_ID = EEM_Registration::status_id_pending_payment;
2414
-        $this->email_validation_level = 'wp_default';
2415
-        $this->show_pending_payment_options = true;
2416
-        $this->reg_steps = array();
2417
-        $this->reg_confirmation_last = false;
2418
-        $this->use_bot_trap = true;
2419
-        $this->use_encryption = true;
2420
-        $this->use_captcha = false;
2421
-        $this->recaptcha_theme = 'light';
2422
-        $this->recaptcha_badge = 'bottomleft';
2423
-        $this->recaptcha_type = 'image';
2424
-        $this->recaptcha_language = 'en';
2425
-        $this->recaptcha_publickey = null;
2426
-        $this->recaptcha_privatekey = null;
2427
-        $this->recaptcha_protected_forms = array();
2428
-        $this->recaptcha_width = 500;
2429
-        $this->default_maximum_number_of_tickets = 10;
2430
-        $this->consent_checkbox_enabled = false;
2431
-        $this->consent_checkbox_label_text = '';
2432
-        $this->gateway_log_lifespan = '7 days';
2433
-        $this->copy_attendee_info = true;
2434
-    }
2435
-
2436
-
2437
-    /**
2438
-     * This is called by the config loader and hooks are initialized AFTER the config has been populated.
2439
-     *
2440
-     * @since 4.8.8.rc.019
2441
-     */
2442
-    public function do_hooks()
2443
-    {
2444
-        add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_reg_status_on_EEM_Event'));
2445
-        add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_max_ticket_on_EEM_Event'));
2446
-        add_action('setup_theme', array($this, 'setDefaultCheckboxLabelText'));
2447
-    }
2448
-
2449
-
2450
-    /**
2451
-     * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the
2452
-     * EVT_default_registration_status field matches the config setting for default_STS_ID.
2453
-     */
2454
-    public function set_default_reg_status_on_EEM_Event()
2455
-    {
2456
-        EEM_Event::set_default_reg_status($this->default_STS_ID);
2457
-    }
2458
-
2459
-
2460
-    /**
2461
-     * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the EVT_additional_limit field
2462
-     * for Events matches the config setting for default_maximum_number_of_tickets
2463
-     */
2464
-    public function set_default_max_ticket_on_EEM_Event()
2465
-    {
2466
-        EEM_Event::set_default_additional_limit($this->default_maximum_number_of_tickets);
2467
-    }
2468
-
2469
-
2470
-    /**
2471
-     * Sets the default consent checkbox text. This needs to be done a bit later than when EE_Registration_Config is
2472
-     * constructed because that happens before we can get the privacy policy page's permalink.
2473
-     *
2474
-     * @throws InvalidArgumentException
2475
-     * @throws InvalidDataTypeException
2476
-     * @throws InvalidInterfaceException
2477
-     */
2478
-    public function setDefaultCheckboxLabelText()
2479
-    {
2480
-        if (
2481
-            $this->getConsentCheckboxLabelText() === null
2482
-            || $this->getConsentCheckboxLabelText() === ''
2483
-        ) {
2484
-            $opening_a_tag = '';
2485
-            $closing_a_tag = '';
2486
-            if (function_exists('get_privacy_policy_url')) {
2487
-                $privacy_page_url = get_privacy_policy_url();
2488
-                if (! empty($privacy_page_url)) {
2489
-                    $opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2490
-                    $closing_a_tag = '</a>';
2491
-                }
2492
-            }
2493
-            $loader = LoaderFactory::getLoader();
2494
-            $org_config = $loader->getShared('EE_Organization_Config');
2495
-            /**
2496
-             * @var $org_config EE_Organization_Config
2497
-             */
2498
-
2499
-            $this->setConsentCheckboxLabelText(
2500
-                sprintf(
2501
-                    esc_html__(
2502
-                        'I consent to %1$s storing and using my personal information, according to their %2$sprivacy policy%3$s.',
2503
-                        'event_espresso'
2504
-                    ),
2505
-                    $org_config->name,
2506
-                    $opening_a_tag,
2507
-                    $closing_a_tag
2508
-                )
2509
-            );
2510
-        }
2511
-    }
2512
-
2513
-
2514
-    /**
2515
-     * @return boolean
2516
-     */
2517
-    public function track_invalid_checkout_access()
2518
-    {
2519
-        return $this->track_invalid_checkout_access;
2520
-    }
2521
-
2522
-
2523
-    /**
2524
-     * @param boolean $track_invalid_checkout_access
2525
-     */
2526
-    public function set_track_invalid_checkout_access($track_invalid_checkout_access)
2527
-    {
2528
-        $this->track_invalid_checkout_access = filter_var(
2529
-            $track_invalid_checkout_access,
2530
-            FILTER_VALIDATE_BOOLEAN
2531
-        );
2532
-    }
2533
-
2534
-    /**
2535
-     * @return boolean
2536
-     */
2537
-    public function copyAttendeeInfo()
2538
-    {
2539
-        return $this->copy_attendee_info;
2540
-    }
2541
-
2542
-
2543
-    /**
2544
-     * @param boolean $copy_attendee_info
2545
-     */
2546
-    public function setCopyAttendeeInfo($copy_attendee_info)
2547
-    {
2548
-        $this->copy_attendee_info = filter_var(
2549
-            $copy_attendee_info,
2550
-            FILTER_VALIDATE_BOOLEAN
2551
-        );
2552
-    }
2553
-
2554
-
2555
-    /**
2556
-     * Gets the options to make availalbe for the gateway log lifespan
2557
-     * @return array
2558
-     */
2559
-    public function gatewayLogLifespanOptions()
2560
-    {
2561
-        return (array) apply_filters(
2562
-            'FHEE_EE_Admin_Config__gatewayLogLifespanOptions',
2563
-            array(
2564
-                '1 second' => esc_html__('Don\'t Log At All', 'event_espresso'),
2565
-                '1 day' => esc_html__('1 Day', 'event_espresso'),
2566
-                '7 days' => esc_html__('7 Days', 'event_espresso'),
2567
-                '14 days' => esc_html__('14 Days', 'event_espresso'),
2568
-                '30 days' => esc_html__('30 Days', 'event_espresso')
2569
-            )
2570
-        );
2571
-    }
2572
-
2573
-
2574
-    /**
2575
-     * @return bool
2576
-     */
2577
-    public function isConsentCheckboxEnabled()
2578
-    {
2579
-        return $this->consent_checkbox_enabled;
2580
-    }
2581
-
2582
-
2583
-    /**
2584
-     * @param bool $consent_checkbox_enabled
2585
-     */
2586
-    public function setConsentCheckboxEnabled($consent_checkbox_enabled)
2587
-    {
2588
-        $this->consent_checkbox_enabled = filter_var(
2589
-            $consent_checkbox_enabled,
2590
-            FILTER_VALIDATE_BOOLEAN
2591
-        );
2592
-    }
2593
-
2594
-
2595
-    /**
2596
-     * @return string
2597
-     */
2598
-    public function getConsentCheckboxLabelText()
2599
-    {
2600
-        return $this->consent_checkbox_label_text;
2601
-    }
2602
-
2603
-
2604
-    /**
2605
-     * @param string $consent_checkbox_label_text
2606
-     */
2607
-    public function setConsentCheckboxLabelText($consent_checkbox_label_text)
2608
-    {
2609
-        $this->consent_checkbox_label_text = (string) $consent_checkbox_label_text;
2610
-    }
2395
+	public $gateway_log_lifespan = '1 week';
2396
+
2397
+	/**
2398
+	 * Enable copy attendee info at form
2399
+	 *
2400
+	 * @var boolean $enable_copy_attendee
2401
+	 */
2402
+	protected $copy_attendee_info = true;
2403
+
2404
+
2405
+	/**
2406
+	 *    class constructor
2407
+	 *
2408
+	 * @access    public
2409
+	 */
2410
+	public function __construct()
2411
+	{
2412
+		// set default registration settings
2413
+		$this->default_STS_ID = EEM_Registration::status_id_pending_payment;
2414
+		$this->email_validation_level = 'wp_default';
2415
+		$this->show_pending_payment_options = true;
2416
+		$this->reg_steps = array();
2417
+		$this->reg_confirmation_last = false;
2418
+		$this->use_bot_trap = true;
2419
+		$this->use_encryption = true;
2420
+		$this->use_captcha = false;
2421
+		$this->recaptcha_theme = 'light';
2422
+		$this->recaptcha_badge = 'bottomleft';
2423
+		$this->recaptcha_type = 'image';
2424
+		$this->recaptcha_language = 'en';
2425
+		$this->recaptcha_publickey = null;
2426
+		$this->recaptcha_privatekey = null;
2427
+		$this->recaptcha_protected_forms = array();
2428
+		$this->recaptcha_width = 500;
2429
+		$this->default_maximum_number_of_tickets = 10;
2430
+		$this->consent_checkbox_enabled = false;
2431
+		$this->consent_checkbox_label_text = '';
2432
+		$this->gateway_log_lifespan = '7 days';
2433
+		$this->copy_attendee_info = true;
2434
+	}
2435
+
2436
+
2437
+	/**
2438
+	 * This is called by the config loader and hooks are initialized AFTER the config has been populated.
2439
+	 *
2440
+	 * @since 4.8.8.rc.019
2441
+	 */
2442
+	public function do_hooks()
2443
+	{
2444
+		add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_reg_status_on_EEM_Event'));
2445
+		add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_max_ticket_on_EEM_Event'));
2446
+		add_action('setup_theme', array($this, 'setDefaultCheckboxLabelText'));
2447
+	}
2448
+
2449
+
2450
+	/**
2451
+	 * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the
2452
+	 * EVT_default_registration_status field matches the config setting for default_STS_ID.
2453
+	 */
2454
+	public function set_default_reg_status_on_EEM_Event()
2455
+	{
2456
+		EEM_Event::set_default_reg_status($this->default_STS_ID);
2457
+	}
2458
+
2459
+
2460
+	/**
2461
+	 * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the EVT_additional_limit field
2462
+	 * for Events matches the config setting for default_maximum_number_of_tickets
2463
+	 */
2464
+	public function set_default_max_ticket_on_EEM_Event()
2465
+	{
2466
+		EEM_Event::set_default_additional_limit($this->default_maximum_number_of_tickets);
2467
+	}
2468
+
2469
+
2470
+	/**
2471
+	 * Sets the default consent checkbox text. This needs to be done a bit later than when EE_Registration_Config is
2472
+	 * constructed because that happens before we can get the privacy policy page's permalink.
2473
+	 *
2474
+	 * @throws InvalidArgumentException
2475
+	 * @throws InvalidDataTypeException
2476
+	 * @throws InvalidInterfaceException
2477
+	 */
2478
+	public function setDefaultCheckboxLabelText()
2479
+	{
2480
+		if (
2481
+			$this->getConsentCheckboxLabelText() === null
2482
+			|| $this->getConsentCheckboxLabelText() === ''
2483
+		) {
2484
+			$opening_a_tag = '';
2485
+			$closing_a_tag = '';
2486
+			if (function_exists('get_privacy_policy_url')) {
2487
+				$privacy_page_url = get_privacy_policy_url();
2488
+				if (! empty($privacy_page_url)) {
2489
+					$opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2490
+					$closing_a_tag = '</a>';
2491
+				}
2492
+			}
2493
+			$loader = LoaderFactory::getLoader();
2494
+			$org_config = $loader->getShared('EE_Organization_Config');
2495
+			/**
2496
+			 * @var $org_config EE_Organization_Config
2497
+			 */
2498
+
2499
+			$this->setConsentCheckboxLabelText(
2500
+				sprintf(
2501
+					esc_html__(
2502
+						'I consent to %1$s storing and using my personal information, according to their %2$sprivacy policy%3$s.',
2503
+						'event_espresso'
2504
+					),
2505
+					$org_config->name,
2506
+					$opening_a_tag,
2507
+					$closing_a_tag
2508
+				)
2509
+			);
2510
+		}
2511
+	}
2512
+
2513
+
2514
+	/**
2515
+	 * @return boolean
2516
+	 */
2517
+	public function track_invalid_checkout_access()
2518
+	{
2519
+		return $this->track_invalid_checkout_access;
2520
+	}
2521
+
2522
+
2523
+	/**
2524
+	 * @param boolean $track_invalid_checkout_access
2525
+	 */
2526
+	public function set_track_invalid_checkout_access($track_invalid_checkout_access)
2527
+	{
2528
+		$this->track_invalid_checkout_access = filter_var(
2529
+			$track_invalid_checkout_access,
2530
+			FILTER_VALIDATE_BOOLEAN
2531
+		);
2532
+	}
2533
+
2534
+	/**
2535
+	 * @return boolean
2536
+	 */
2537
+	public function copyAttendeeInfo()
2538
+	{
2539
+		return $this->copy_attendee_info;
2540
+	}
2541
+
2542
+
2543
+	/**
2544
+	 * @param boolean $copy_attendee_info
2545
+	 */
2546
+	public function setCopyAttendeeInfo($copy_attendee_info)
2547
+	{
2548
+		$this->copy_attendee_info = filter_var(
2549
+			$copy_attendee_info,
2550
+			FILTER_VALIDATE_BOOLEAN
2551
+		);
2552
+	}
2553
+
2554
+
2555
+	/**
2556
+	 * Gets the options to make availalbe for the gateway log lifespan
2557
+	 * @return array
2558
+	 */
2559
+	public function gatewayLogLifespanOptions()
2560
+	{
2561
+		return (array) apply_filters(
2562
+			'FHEE_EE_Admin_Config__gatewayLogLifespanOptions',
2563
+			array(
2564
+				'1 second' => esc_html__('Don\'t Log At All', 'event_espresso'),
2565
+				'1 day' => esc_html__('1 Day', 'event_espresso'),
2566
+				'7 days' => esc_html__('7 Days', 'event_espresso'),
2567
+				'14 days' => esc_html__('14 Days', 'event_espresso'),
2568
+				'30 days' => esc_html__('30 Days', 'event_espresso')
2569
+			)
2570
+		);
2571
+	}
2572
+
2573
+
2574
+	/**
2575
+	 * @return bool
2576
+	 */
2577
+	public function isConsentCheckboxEnabled()
2578
+	{
2579
+		return $this->consent_checkbox_enabled;
2580
+	}
2581
+
2582
+
2583
+	/**
2584
+	 * @param bool $consent_checkbox_enabled
2585
+	 */
2586
+	public function setConsentCheckboxEnabled($consent_checkbox_enabled)
2587
+	{
2588
+		$this->consent_checkbox_enabled = filter_var(
2589
+			$consent_checkbox_enabled,
2590
+			FILTER_VALIDATE_BOOLEAN
2591
+		);
2592
+	}
2593
+
2594
+
2595
+	/**
2596
+	 * @return string
2597
+	 */
2598
+	public function getConsentCheckboxLabelText()
2599
+	{
2600
+		return $this->consent_checkbox_label_text;
2601
+	}
2602
+
2603
+
2604
+	/**
2605
+	 * @param string $consent_checkbox_label_text
2606
+	 */
2607
+	public function setConsentCheckboxLabelText($consent_checkbox_label_text)
2608
+	{
2609
+		$this->consent_checkbox_label_text = (string) $consent_checkbox_label_text;
2610
+	}
2611 2611
 }
2612 2612
 
2613 2613
 /**
@@ -2615,156 +2615,156 @@  discard block
 block discarded – undo
2615 2615
  */
2616 2616
 class EE_Admin_Config extends EE_Config_Base
2617 2617
 {
2618
-    /**
2619
-     * @var boolean $useAdvancedEditor
2620
-     */
2621
-    private $useAdvancedEditor;
2622
-
2623
-    /**
2624
-     * @var string $log_file_name
2625
-     */
2626
-    public $log_file_name;
2627
-
2628
-    /**
2629
-     * @var string $debug_file_name
2630
-     */
2631
-    public $debug_file_name;
2632
-
2633
-    /**
2634
-     * @var boolean $use_remote_logging
2635
-     */
2636
-    public $use_remote_logging;
2637
-
2638
-    /**
2639
-     * @var string $remote_logging_url
2640
-     */
2641
-    public $remote_logging_url;
2642
-
2643
-    /**
2644
-     * @var boolean $show_reg_footer
2645
-     */
2646
-    public $show_reg_footer;
2647
-
2648
-    /**
2649
-     * @var string $affiliate_id
2650
-     */
2651
-    public $affiliate_id;
2652
-
2653
-    /**
2654
-     * adds extra layer of encoding to session data to prevent serialization errors
2655
-     * but is incompatible with some server configuration errors
2656
-     * if you get "500 internal server errors" during registration, try turning this on
2657
-     * if you get PHP fatal errors regarding base 64 methods not defined, then turn this off
2658
-     *
2659
-     * @var boolean $encode_session_data
2660
-     */
2661
-    private $encode_session_data = false;
2662
-
2663
-    /**
2664
-     * @var boolean
2665
-     */
2666
-    private $is_caffeinated;
2667
-
2668
-
2669
-    /**
2670
-     *    class constructor
2671
-     *
2672
-     * @access    public
2673
-     */
2674
-    public function __construct()
2675
-    {
2676
-        // set default general admin settings
2677
-        $this->useAdvancedEditor = true;
2678
-        $this->use_remote_logging = false;
2679
-        $this->remote_logging_url = null;
2680
-        $this->show_reg_footer = apply_filters(
2681
-            'FHEE__EE_Admin_Config__show_reg_footer__default',
2682
-            false
2683
-        );
2684
-        $this->affiliate_id = 'default';
2685
-        $this->encode_session_data = false;
2686
-    }
2687
-
2688
-
2689
-    /**
2690
-     * @param bool $reset
2691
-     * @return string
2692
-     */
2693
-    public function log_file_name($reset = false)
2694
-    {
2695
-        if (empty($this->log_file_name) || $reset) {
2696
-            $this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2697
-            EE_Config::instance()->update_espresso_config(false, false);
2698
-        }
2699
-        return $this->log_file_name;
2700
-    }
2701
-
2702
-
2703
-    /**
2704
-     * @param bool $reset
2705
-     * @return string
2706
-     */
2707
-    public function debug_file_name($reset = false)
2708
-    {
2709
-        if (empty($this->debug_file_name) || $reset) {
2710
-            $this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2711
-            EE_Config::instance()->update_espresso_config(false, false);
2712
-        }
2713
-        return $this->debug_file_name;
2714
-    }
2715
-
2716
-
2717
-    /**
2718
-     * @return string
2719
-     */
2720
-    public function affiliate_id()
2721
-    {
2722
-        return ! empty($this->affiliate_id) ? $this->affiliate_id : 'default';
2723
-    }
2724
-
2725
-
2726
-    /**
2727
-     * @return boolean
2728
-     */
2729
-    public function encode_session_data()
2730
-    {
2731
-        return filter_var($this->encode_session_data, FILTER_VALIDATE_BOOLEAN);
2732
-    }
2733
-
2734
-
2735
-    /**
2736
-     * @param boolean $encode_session_data
2737
-     */
2738
-    public function set_encode_session_data($encode_session_data)
2739
-    {
2740
-        $this->encode_session_data = filter_var($encode_session_data, FILTER_VALIDATE_BOOLEAN);
2741
-    }
2742
-
2743
-    /**
2744
-     * @return boolean
2745
-     */
2746
-    public function useAdvancedEditor()
2747
-    {
2748
-        if ($this->is_caffeinated === null) {
2749
-            $domain = LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\Domain');
2750
-            $this->is_caffeinated = $domain->isCaffeinated();
2751
-        }
2752
-        return $this->useAdvancedEditor && $this->is_caffeinated;
2753
-    }
2754
-
2755
-    /**
2756
-     * @param boolean $use_advanced_editor
2757
-     */
2758
-    public function setUseAdvancedEditor($use_advanced_editor = true)
2759
-    {
2760
-        $this->useAdvancedEditor = filter_var(
2761
-            apply_filters(
2762
-                'FHEE__EE_Admin_Config__setUseAdvancedEditor__use_advanced_editor',
2763
-                $use_advanced_editor
2764
-            ),
2765
-            FILTER_VALIDATE_BOOLEAN
2766
-        );
2767
-    }
2618
+	/**
2619
+	 * @var boolean $useAdvancedEditor
2620
+	 */
2621
+	private $useAdvancedEditor;
2622
+
2623
+	/**
2624
+	 * @var string $log_file_name
2625
+	 */
2626
+	public $log_file_name;
2627
+
2628
+	/**
2629
+	 * @var string $debug_file_name
2630
+	 */
2631
+	public $debug_file_name;
2632
+
2633
+	/**
2634
+	 * @var boolean $use_remote_logging
2635
+	 */
2636
+	public $use_remote_logging;
2637
+
2638
+	/**
2639
+	 * @var string $remote_logging_url
2640
+	 */
2641
+	public $remote_logging_url;
2642
+
2643
+	/**
2644
+	 * @var boolean $show_reg_footer
2645
+	 */
2646
+	public $show_reg_footer;
2647
+
2648
+	/**
2649
+	 * @var string $affiliate_id
2650
+	 */
2651
+	public $affiliate_id;
2652
+
2653
+	/**
2654
+	 * adds extra layer of encoding to session data to prevent serialization errors
2655
+	 * but is incompatible with some server configuration errors
2656
+	 * if you get "500 internal server errors" during registration, try turning this on
2657
+	 * if you get PHP fatal errors regarding base 64 methods not defined, then turn this off
2658
+	 *
2659
+	 * @var boolean $encode_session_data
2660
+	 */
2661
+	private $encode_session_data = false;
2662
+
2663
+	/**
2664
+	 * @var boolean
2665
+	 */
2666
+	private $is_caffeinated;
2667
+
2668
+
2669
+	/**
2670
+	 *    class constructor
2671
+	 *
2672
+	 * @access    public
2673
+	 */
2674
+	public function __construct()
2675
+	{
2676
+		// set default general admin settings
2677
+		$this->useAdvancedEditor = true;
2678
+		$this->use_remote_logging = false;
2679
+		$this->remote_logging_url = null;
2680
+		$this->show_reg_footer = apply_filters(
2681
+			'FHEE__EE_Admin_Config__show_reg_footer__default',
2682
+			false
2683
+		);
2684
+		$this->affiliate_id = 'default';
2685
+		$this->encode_session_data = false;
2686
+	}
2687
+
2688
+
2689
+	/**
2690
+	 * @param bool $reset
2691
+	 * @return string
2692
+	 */
2693
+	public function log_file_name($reset = false)
2694
+	{
2695
+		if (empty($this->log_file_name) || $reset) {
2696
+			$this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2697
+			EE_Config::instance()->update_espresso_config(false, false);
2698
+		}
2699
+		return $this->log_file_name;
2700
+	}
2701
+
2702
+
2703
+	/**
2704
+	 * @param bool $reset
2705
+	 * @return string
2706
+	 */
2707
+	public function debug_file_name($reset = false)
2708
+	{
2709
+		if (empty($this->debug_file_name) || $reset) {
2710
+			$this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2711
+			EE_Config::instance()->update_espresso_config(false, false);
2712
+		}
2713
+		return $this->debug_file_name;
2714
+	}
2715
+
2716
+
2717
+	/**
2718
+	 * @return string
2719
+	 */
2720
+	public function affiliate_id()
2721
+	{
2722
+		return ! empty($this->affiliate_id) ? $this->affiliate_id : 'default';
2723
+	}
2724
+
2725
+
2726
+	/**
2727
+	 * @return boolean
2728
+	 */
2729
+	public function encode_session_data()
2730
+	{
2731
+		return filter_var($this->encode_session_data, FILTER_VALIDATE_BOOLEAN);
2732
+	}
2733
+
2734
+
2735
+	/**
2736
+	 * @param boolean $encode_session_data
2737
+	 */
2738
+	public function set_encode_session_data($encode_session_data)
2739
+	{
2740
+		$this->encode_session_data = filter_var($encode_session_data, FILTER_VALIDATE_BOOLEAN);
2741
+	}
2742
+
2743
+	/**
2744
+	 * @return boolean
2745
+	 */
2746
+	public function useAdvancedEditor()
2747
+	{
2748
+		if ($this->is_caffeinated === null) {
2749
+			$domain = LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\Domain');
2750
+			$this->is_caffeinated = $domain->isCaffeinated();
2751
+		}
2752
+		return $this->useAdvancedEditor && $this->is_caffeinated;
2753
+	}
2754
+
2755
+	/**
2756
+	 * @param boolean $use_advanced_editor
2757
+	 */
2758
+	public function setUseAdvancedEditor($use_advanced_editor = true)
2759
+	{
2760
+		$this->useAdvancedEditor = filter_var(
2761
+			apply_filters(
2762
+				'FHEE__EE_Admin_Config__setUseAdvancedEditor__use_advanced_editor',
2763
+				$use_advanced_editor
2764
+			),
2765
+			FILTER_VALIDATE_BOOLEAN
2766
+		);
2767
+	}
2768 2768
 }
2769 2769
 
2770 2770
 /**
@@ -2772,40 +2772,40 @@  discard block
 block discarded – undo
2772 2772
  */
2773 2773
 class EE_Template_Config extends EE_Config_Base
2774 2774
 {
2775
-    /**
2776
-     * @var string $current_espresso_theme
2777
-     */
2778
-    public $current_espresso_theme;
2779
-
2780
-    /**
2781
-     * @var EE_Ticket_Selector_Config $EED_Ticket_Selector
2782
-     */
2783
-    public $EED_Ticket_Selector;
2784
-
2785
-    /**
2786
-     * @var EE_Event_Single_Config $EED_Event_Single
2787
-     */
2788
-    public $EED_Event_Single;
2789
-
2790
-    /**
2791
-     * @var EE_Events_Archive_Config $EED_Events_Archive
2792
-     */
2793
-    public $EED_Events_Archive;
2794
-
2795
-
2796
-    /**
2797
-     *    class constructor
2798
-     *
2799
-     * @access    public
2800
-     */
2801
-    public function __construct()
2802
-    {
2803
-        // set default template settings
2804
-        $this->current_espresso_theme = 'Espresso_Arabica_2014';
2805
-        $this->EED_Event_Single = null;
2806
-        $this->EED_Events_Archive = null;
2807
-        $this->EED_Ticket_Selector = null;
2808
-    }
2775
+	/**
2776
+	 * @var string $current_espresso_theme
2777
+	 */
2778
+	public $current_espresso_theme;
2779
+
2780
+	/**
2781
+	 * @var EE_Ticket_Selector_Config $EED_Ticket_Selector
2782
+	 */
2783
+	public $EED_Ticket_Selector;
2784
+
2785
+	/**
2786
+	 * @var EE_Event_Single_Config $EED_Event_Single
2787
+	 */
2788
+	public $EED_Event_Single;
2789
+
2790
+	/**
2791
+	 * @var EE_Events_Archive_Config $EED_Events_Archive
2792
+	 */
2793
+	public $EED_Events_Archive;
2794
+
2795
+
2796
+	/**
2797
+	 *    class constructor
2798
+	 *
2799
+	 * @access    public
2800
+	 */
2801
+	public function __construct()
2802
+	{
2803
+		// set default template settings
2804
+		$this->current_espresso_theme = 'Espresso_Arabica_2014';
2805
+		$this->EED_Event_Single = null;
2806
+		$this->EED_Events_Archive = null;
2807
+		$this->EED_Ticket_Selector = null;
2808
+	}
2809 2809
 }
2810 2810
 
2811 2811
 /**
@@ -2813,114 +2813,114 @@  discard block
 block discarded – undo
2813 2813
  */
2814 2814
 class EE_Map_Config extends EE_Config_Base
2815 2815
 {
2816
-    /**
2817
-     * @var boolean $use_google_maps
2818
-     */
2819
-    public $use_google_maps;
2820
-
2821
-    /**
2822
-     * @var string $api_key
2823
-     */
2824
-    public $google_map_api_key;
2825
-
2826
-    /**
2827
-     * @var int $event_details_map_width
2828
-     */
2829
-    public $event_details_map_width;
2830
-
2831
-    /**
2832
-     * @var int $event_details_map_height
2833
-     */
2834
-    public $event_details_map_height;
2835
-
2836
-    /**
2837
-     * @var int $event_details_map_zoom
2838
-     */
2839
-    public $event_details_map_zoom;
2840
-
2841
-    /**
2842
-     * @var boolean $event_details_display_nav
2843
-     */
2844
-    public $event_details_display_nav;
2845
-
2846
-    /**
2847
-     * @var boolean $event_details_nav_size
2848
-     */
2849
-    public $event_details_nav_size;
2850
-
2851
-    /**
2852
-     * @var string $event_details_control_type
2853
-     */
2854
-    public $event_details_control_type;
2855
-
2856
-    /**
2857
-     * @var string $event_details_map_align
2858
-     */
2859
-    public $event_details_map_align;
2860
-
2861
-    /**
2862
-     * @var int $event_list_map_width
2863
-     */
2864
-    public $event_list_map_width;
2865
-
2866
-    /**
2867
-     * @var int $event_list_map_height
2868
-     */
2869
-    public $event_list_map_height;
2870
-
2871
-    /**
2872
-     * @var int $event_list_map_zoom
2873
-     */
2874
-    public $event_list_map_zoom;
2875
-
2876
-    /**
2877
-     * @var boolean $event_list_display_nav
2878
-     */
2879
-    public $event_list_display_nav;
2880
-
2881
-    /**
2882
-     * @var boolean $event_list_nav_size
2883
-     */
2884
-    public $event_list_nav_size;
2885
-
2886
-    /**
2887
-     * @var string $event_list_control_type
2888
-     */
2889
-    public $event_list_control_type;
2890
-
2891
-    /**
2892
-     * @var string $event_list_map_align
2893
-     */
2894
-    public $event_list_map_align;
2895
-
2896
-
2897
-    /**
2898
-     *    class constructor
2899
-     *
2900
-     * @access    public
2901
-     */
2902
-    public function __construct()
2903
-    {
2904
-        // set default map settings
2905
-        $this->use_google_maps = true;
2906
-        $this->google_map_api_key = '';
2907
-        // for event details pages (reg page)
2908
-        $this->event_details_map_width = 585;            // ee_map_width_single
2909
-        $this->event_details_map_height = 362;            // ee_map_height_single
2910
-        $this->event_details_map_zoom = 14;            // ee_map_zoom_single
2911
-        $this->event_details_display_nav = true;            // ee_map_nav_display_single
2912
-        $this->event_details_nav_size = false;            // ee_map_nav_size_single
2913
-        $this->event_details_control_type = 'default';        // ee_map_type_control_single
2914
-        $this->event_details_map_align = 'center';            // ee_map_align_single
2915
-        // for event list pages
2916
-        $this->event_list_map_width = 300;            // ee_map_width
2917
-        $this->event_list_map_height = 185;        // ee_map_height
2918
-        $this->event_list_map_zoom = 12;            // ee_map_zoom
2919
-        $this->event_list_display_nav = false;        // ee_map_nav_display
2920
-        $this->event_list_nav_size = true;            // ee_map_nav_size
2921
-        $this->event_list_control_type = 'dropdown';        // ee_map_type_control
2922
-        $this->event_list_map_align = 'center';            // ee_map_align
2923
-    }
2816
+	/**
2817
+	 * @var boolean $use_google_maps
2818
+	 */
2819
+	public $use_google_maps;
2820
+
2821
+	/**
2822
+	 * @var string $api_key
2823
+	 */
2824
+	public $google_map_api_key;
2825
+
2826
+	/**
2827
+	 * @var int $event_details_map_width
2828
+	 */
2829
+	public $event_details_map_width;
2830
+
2831
+	/**
2832
+	 * @var int $event_details_map_height
2833
+	 */
2834
+	public $event_details_map_height;
2835
+
2836
+	/**
2837
+	 * @var int $event_details_map_zoom
2838
+	 */
2839
+	public $event_details_map_zoom;
2840
+
2841
+	/**
2842
+	 * @var boolean $event_details_display_nav
2843
+	 */
2844
+	public $event_details_display_nav;
2845
+
2846
+	/**
2847
+	 * @var boolean $event_details_nav_size
2848
+	 */
2849
+	public $event_details_nav_size;
2850
+
2851
+	/**
2852
+	 * @var string $event_details_control_type
2853
+	 */
2854
+	public $event_details_control_type;
2855
+
2856
+	/**
2857
+	 * @var string $event_details_map_align
2858
+	 */
2859
+	public $event_details_map_align;
2860
+
2861
+	/**
2862
+	 * @var int $event_list_map_width
2863
+	 */
2864
+	public $event_list_map_width;
2865
+
2866
+	/**
2867
+	 * @var int $event_list_map_height
2868
+	 */
2869
+	public $event_list_map_height;
2870
+
2871
+	/**
2872
+	 * @var int $event_list_map_zoom
2873
+	 */
2874
+	public $event_list_map_zoom;
2875
+
2876
+	/**
2877
+	 * @var boolean $event_list_display_nav
2878
+	 */
2879
+	public $event_list_display_nav;
2880
+
2881
+	/**
2882
+	 * @var boolean $event_list_nav_size
2883
+	 */
2884
+	public $event_list_nav_size;
2885
+
2886
+	/**
2887
+	 * @var string $event_list_control_type
2888
+	 */
2889
+	public $event_list_control_type;
2890
+
2891
+	/**
2892
+	 * @var string $event_list_map_align
2893
+	 */
2894
+	public $event_list_map_align;
2895
+
2896
+
2897
+	/**
2898
+	 *    class constructor
2899
+	 *
2900
+	 * @access    public
2901
+	 */
2902
+	public function __construct()
2903
+	{
2904
+		// set default map settings
2905
+		$this->use_google_maps = true;
2906
+		$this->google_map_api_key = '';
2907
+		// for event details pages (reg page)
2908
+		$this->event_details_map_width = 585;            // ee_map_width_single
2909
+		$this->event_details_map_height = 362;            // ee_map_height_single
2910
+		$this->event_details_map_zoom = 14;            // ee_map_zoom_single
2911
+		$this->event_details_display_nav = true;            // ee_map_nav_display_single
2912
+		$this->event_details_nav_size = false;            // ee_map_nav_size_single
2913
+		$this->event_details_control_type = 'default';        // ee_map_type_control_single
2914
+		$this->event_details_map_align = 'center';            // ee_map_align_single
2915
+		// for event list pages
2916
+		$this->event_list_map_width = 300;            // ee_map_width
2917
+		$this->event_list_map_height = 185;        // ee_map_height
2918
+		$this->event_list_map_zoom = 12;            // ee_map_zoom
2919
+		$this->event_list_display_nav = false;        // ee_map_nav_display
2920
+		$this->event_list_nav_size = true;            // ee_map_nav_size
2921
+		$this->event_list_control_type = 'dropdown';        // ee_map_type_control
2922
+		$this->event_list_map_align = 'center';            // ee_map_align
2923
+	}
2924 2924
 }
2925 2925
 
2926 2926
 /**
@@ -2928,46 +2928,46 @@  discard block
 block discarded – undo
2928 2928
  */
2929 2929
 class EE_Events_Archive_Config extends EE_Config_Base
2930 2930
 {
2931
-    public $display_status_banner;
2931
+	public $display_status_banner;
2932 2932
 
2933
-    public $display_description;
2933
+	public $display_description;
2934 2934
 
2935
-    public $display_ticket_selector;
2935
+	public $display_ticket_selector;
2936 2936
 
2937
-    public $display_datetimes;
2937
+	public $display_datetimes;
2938 2938
 
2939
-    public $display_venue;
2939
+	public $display_venue;
2940 2940
 
2941
-    public $display_expired_events;
2941
+	public $display_expired_events;
2942 2942
 
2943
-    public $use_sortable_display_order;
2943
+	public $use_sortable_display_order;
2944 2944
 
2945
-    public $display_order_tickets;
2945
+	public $display_order_tickets;
2946 2946
 
2947
-    public $display_order_datetimes;
2947
+	public $display_order_datetimes;
2948 2948
 
2949
-    public $display_order_event;
2949
+	public $display_order_event;
2950 2950
 
2951
-    public $display_order_venue;
2951
+	public $display_order_venue;
2952 2952
 
2953 2953
 
2954
-    /**
2955
-     *    class constructor
2956
-     */
2957
-    public function __construct()
2958
-    {
2959
-        $this->display_status_banner = 0;
2960
-        $this->display_description = 1;
2961
-        $this->display_ticket_selector = 0;
2962
-        $this->display_datetimes = 1;
2963
-        $this->display_venue = 0;
2964
-        $this->display_expired_events = 0;
2965
-        $this->use_sortable_display_order = false;
2966
-        $this->display_order_tickets = 100;
2967
-        $this->display_order_datetimes = 110;
2968
-        $this->display_order_event = 120;
2969
-        $this->display_order_venue = 130;
2970
-    }
2954
+	/**
2955
+	 *    class constructor
2956
+	 */
2957
+	public function __construct()
2958
+	{
2959
+		$this->display_status_banner = 0;
2960
+		$this->display_description = 1;
2961
+		$this->display_ticket_selector = 0;
2962
+		$this->display_datetimes = 1;
2963
+		$this->display_venue = 0;
2964
+		$this->display_expired_events = 0;
2965
+		$this->use_sortable_display_order = false;
2966
+		$this->display_order_tickets = 100;
2967
+		$this->display_order_datetimes = 110;
2968
+		$this->display_order_event = 120;
2969
+		$this->display_order_venue = 130;
2970
+	}
2971 2971
 }
2972 2972
 
2973 2973
 /**
@@ -2975,34 +2975,34 @@  discard block
 block discarded – undo
2975 2975
  */
2976 2976
 class EE_Event_Single_Config extends EE_Config_Base
2977 2977
 {
2978
-    public $display_status_banner_single;
2978
+	public $display_status_banner_single;
2979 2979
 
2980
-    public $display_venue;
2980
+	public $display_venue;
2981 2981
 
2982
-    public $use_sortable_display_order;
2982
+	public $use_sortable_display_order;
2983 2983
 
2984
-    public $display_order_tickets;
2984
+	public $display_order_tickets;
2985 2985
 
2986
-    public $display_order_datetimes;
2986
+	public $display_order_datetimes;
2987 2987
 
2988
-    public $display_order_event;
2988
+	public $display_order_event;
2989 2989
 
2990
-    public $display_order_venue;
2990
+	public $display_order_venue;
2991 2991
 
2992 2992
 
2993
-    /**
2994
-     *    class constructor
2995
-     */
2996
-    public function __construct()
2997
-    {
2998
-        $this->display_status_banner_single = 0;
2999
-        $this->display_venue = 1;
3000
-        $this->use_sortable_display_order = false;
3001
-        $this->display_order_tickets = 100;
3002
-        $this->display_order_datetimes = 110;
3003
-        $this->display_order_event = 120;
3004
-        $this->display_order_venue = 130;
3005
-    }
2993
+	/**
2994
+	 *    class constructor
2995
+	 */
2996
+	public function __construct()
2997
+	{
2998
+		$this->display_status_banner_single = 0;
2999
+		$this->display_venue = 1;
3000
+		$this->use_sortable_display_order = false;
3001
+		$this->display_order_tickets = 100;
3002
+		$this->display_order_datetimes = 110;
3003
+		$this->display_order_event = 120;
3004
+		$this->display_order_venue = 130;
3005
+	}
3006 3006
 }
3007 3007
 
3008 3008
 /**
@@ -3010,172 +3010,172 @@  discard block
 block discarded – undo
3010 3010
  */
3011 3011
 class EE_Ticket_Selector_Config extends EE_Config_Base
3012 3012
 {
3013
-    /**
3014
-     * constant to indicate that a datetime selector should NEVER be shown for ticket selectors
3015
-     */
3016
-    const DO_NOT_SHOW_DATETIME_SELECTOR = 'no_datetime_selector';
3017
-
3018
-    /**
3019
-     * constant to indicate that a datetime selector should only be shown for ticket selectors
3020
-     * when the number of datetimes for the event matches the value set for $datetime_selector_threshold
3021
-     */
3022
-    const MAYBE_SHOW_DATETIME_SELECTOR = 'maybe_datetime_selector';
3023
-
3024
-    /**
3025
-     * @var boolean $show_ticket_sale_columns
3026
-     */
3027
-    public $show_ticket_sale_columns;
3028
-
3029
-    /**
3030
-     * @var boolean $show_ticket_details
3031
-     */
3032
-    public $show_ticket_details;
3033
-
3034
-    /**
3035
-     * @var boolean $show_expired_tickets
3036
-     */
3037
-    public $show_expired_tickets;
3038
-
3039
-    /**
3040
-     * whether or not to display a dropdown box populated with event datetimes
3041
-     * that toggles which tickets are displayed for a ticket selector.
3042
-     * uses one of the *_DATETIME_SELECTOR constants defined above
3043
-     *
3044
-     * @var string $show_datetime_selector
3045
-     */
3046
-    private $show_datetime_selector = 'no_datetime_selector';
3047
-
3048
-    /**
3049
-     * the number of datetimes an event has to have before conditionally displaying a datetime selector
3050
-     *
3051
-     * @var int $datetime_selector_threshold
3052
-     */
3053
-    private $datetime_selector_threshold = 3;
3054
-
3055
-    /**
3056
-     * determines the maximum number of "checked" dates in the date and time filter
3057
-     *
3058
-     * @var int $datetime_selector_checked
3059
-     */
3060
-    private $datetime_selector_max_checked = 10;
3061
-
3062
-
3063
-    /**
3064
-     *    class constructor
3065
-     */
3066
-    public function __construct()
3067
-    {
3068
-        $this->show_ticket_sale_columns = true;
3069
-        $this->show_ticket_details = true;
3070
-        $this->show_expired_tickets = true;
3071
-        $this->show_datetime_selector = EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3072
-        $this->datetime_selector_threshold = 3;
3073
-        $this->datetime_selector_max_checked = 10;
3074
-    }
3075
-
3076
-
3077
-    /**
3078
-     * returns true if a datetime selector should be displayed
3079
-     *
3080
-     * @param array $datetimes
3081
-     * @return bool
3082
-     */
3083
-    public function showDatetimeSelector(array $datetimes)
3084
-    {
3085
-        // if the settings are NOT: don't show OR below threshold, THEN active = true
3086
-        return ! (
3087
-            $this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
3088
-            || (
3089
-                $this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR
3090
-                && count($datetimes) < $this->getDatetimeSelectorThreshold()
3091
-            )
3092
-        );
3093
-    }
3094
-
3095
-
3096
-    /**
3097
-     * @return string
3098
-     */
3099
-    public function getShowDatetimeSelector()
3100
-    {
3101
-        return $this->show_datetime_selector;
3102
-    }
3103
-
3104
-
3105
-    /**
3106
-     * @param bool $keys_only
3107
-     * @return array
3108
-     */
3109
-    public function getShowDatetimeSelectorOptions($keys_only = true)
3110
-    {
3111
-        return $keys_only
3112
-            ? array(
3113
-                EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR,
3114
-                EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR,
3115
-            )
3116
-            : array(
3117
-                EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR => esc_html__(
3118
-                    'Do not show date & time filter',
3119
-                    'event_espresso'
3120
-                ),
3121
-                EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR  => esc_html__(
3122
-                    'Maybe show date & time filter',
3123
-                    'event_espresso'
3124
-                ),
3125
-            );
3126
-    }
3127
-
3128
-
3129
-    /**
3130
-     * @param string $show_datetime_selector
3131
-     */
3132
-    public function setShowDatetimeSelector($show_datetime_selector)
3133
-    {
3134
-        $this->show_datetime_selector = in_array(
3135
-            $show_datetime_selector,
3136
-            $this->getShowDatetimeSelectorOptions(),
3137
-            true
3138
-        )
3139
-            ? $show_datetime_selector
3140
-            : EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3141
-    }
3142
-
3143
-
3144
-    /**
3145
-     * @return int
3146
-     */
3147
-    public function getDatetimeSelectorThreshold()
3148
-    {
3149
-        return $this->datetime_selector_threshold;
3150
-    }
3151
-
3152
-
3153
-    /**
3154
-     * @param int $datetime_selector_threshold
3155
-     */
3156
-    public function setDatetimeSelectorThreshold($datetime_selector_threshold)
3157
-    {
3158
-        $datetime_selector_threshold = absint($datetime_selector_threshold);
3159
-        $this->datetime_selector_threshold = $datetime_selector_threshold ? $datetime_selector_threshold : 3;
3160
-    }
3161
-
3162
-
3163
-    /**
3164
-     * @return int
3165
-     */
3166
-    public function getDatetimeSelectorMaxChecked()
3167
-    {
3168
-        return $this->datetime_selector_max_checked;
3169
-    }
3170
-
3171
-
3172
-    /**
3173
-     * @param int $datetime_selector_max_checked
3174
-     */
3175
-    public function setDatetimeSelectorMaxChecked($datetime_selector_max_checked)
3176
-    {
3177
-        $this->datetime_selector_max_checked = absint($datetime_selector_max_checked);
3178
-    }
3013
+	/**
3014
+	 * constant to indicate that a datetime selector should NEVER be shown for ticket selectors
3015
+	 */
3016
+	const DO_NOT_SHOW_DATETIME_SELECTOR = 'no_datetime_selector';
3017
+
3018
+	/**
3019
+	 * constant to indicate that a datetime selector should only be shown for ticket selectors
3020
+	 * when the number of datetimes for the event matches the value set for $datetime_selector_threshold
3021
+	 */
3022
+	const MAYBE_SHOW_DATETIME_SELECTOR = 'maybe_datetime_selector';
3023
+
3024
+	/**
3025
+	 * @var boolean $show_ticket_sale_columns
3026
+	 */
3027
+	public $show_ticket_sale_columns;
3028
+
3029
+	/**
3030
+	 * @var boolean $show_ticket_details
3031
+	 */
3032
+	public $show_ticket_details;
3033
+
3034
+	/**
3035
+	 * @var boolean $show_expired_tickets
3036
+	 */
3037
+	public $show_expired_tickets;
3038
+
3039
+	/**
3040
+	 * whether or not to display a dropdown box populated with event datetimes
3041
+	 * that toggles which tickets are displayed for a ticket selector.
3042
+	 * uses one of the *_DATETIME_SELECTOR constants defined above
3043
+	 *
3044
+	 * @var string $show_datetime_selector
3045
+	 */
3046
+	private $show_datetime_selector = 'no_datetime_selector';
3047
+
3048
+	/**
3049
+	 * the number of datetimes an event has to have before conditionally displaying a datetime selector
3050
+	 *
3051
+	 * @var int $datetime_selector_threshold
3052
+	 */
3053
+	private $datetime_selector_threshold = 3;
3054
+
3055
+	/**
3056
+	 * determines the maximum number of "checked" dates in the date and time filter
3057
+	 *
3058
+	 * @var int $datetime_selector_checked
3059
+	 */
3060
+	private $datetime_selector_max_checked = 10;
3061
+
3062
+
3063
+	/**
3064
+	 *    class constructor
3065
+	 */
3066
+	public function __construct()
3067
+	{
3068
+		$this->show_ticket_sale_columns = true;
3069
+		$this->show_ticket_details = true;
3070
+		$this->show_expired_tickets = true;
3071
+		$this->show_datetime_selector = EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3072
+		$this->datetime_selector_threshold = 3;
3073
+		$this->datetime_selector_max_checked = 10;
3074
+	}
3075
+
3076
+
3077
+	/**
3078
+	 * returns true if a datetime selector should be displayed
3079
+	 *
3080
+	 * @param array $datetimes
3081
+	 * @return bool
3082
+	 */
3083
+	public function showDatetimeSelector(array $datetimes)
3084
+	{
3085
+		// if the settings are NOT: don't show OR below threshold, THEN active = true
3086
+		return ! (
3087
+			$this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
3088
+			|| (
3089
+				$this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR
3090
+				&& count($datetimes) < $this->getDatetimeSelectorThreshold()
3091
+			)
3092
+		);
3093
+	}
3094
+
3095
+
3096
+	/**
3097
+	 * @return string
3098
+	 */
3099
+	public function getShowDatetimeSelector()
3100
+	{
3101
+		return $this->show_datetime_selector;
3102
+	}
3103
+
3104
+
3105
+	/**
3106
+	 * @param bool $keys_only
3107
+	 * @return array
3108
+	 */
3109
+	public function getShowDatetimeSelectorOptions($keys_only = true)
3110
+	{
3111
+		return $keys_only
3112
+			? array(
3113
+				EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR,
3114
+				EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR,
3115
+			)
3116
+			: array(
3117
+				EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR => esc_html__(
3118
+					'Do not show date & time filter',
3119
+					'event_espresso'
3120
+				),
3121
+				EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR  => esc_html__(
3122
+					'Maybe show date & time filter',
3123
+					'event_espresso'
3124
+				),
3125
+			);
3126
+	}
3127
+
3128
+
3129
+	/**
3130
+	 * @param string $show_datetime_selector
3131
+	 */
3132
+	public function setShowDatetimeSelector($show_datetime_selector)
3133
+	{
3134
+		$this->show_datetime_selector = in_array(
3135
+			$show_datetime_selector,
3136
+			$this->getShowDatetimeSelectorOptions(),
3137
+			true
3138
+		)
3139
+			? $show_datetime_selector
3140
+			: EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3141
+	}
3142
+
3143
+
3144
+	/**
3145
+	 * @return int
3146
+	 */
3147
+	public function getDatetimeSelectorThreshold()
3148
+	{
3149
+		return $this->datetime_selector_threshold;
3150
+	}
3151
+
3152
+
3153
+	/**
3154
+	 * @param int $datetime_selector_threshold
3155
+	 */
3156
+	public function setDatetimeSelectorThreshold($datetime_selector_threshold)
3157
+	{
3158
+		$datetime_selector_threshold = absint($datetime_selector_threshold);
3159
+		$this->datetime_selector_threshold = $datetime_selector_threshold ? $datetime_selector_threshold : 3;
3160
+	}
3161
+
3162
+
3163
+	/**
3164
+	 * @return int
3165
+	 */
3166
+	public function getDatetimeSelectorMaxChecked()
3167
+	{
3168
+		return $this->datetime_selector_max_checked;
3169
+	}
3170
+
3171
+
3172
+	/**
3173
+	 * @param int $datetime_selector_max_checked
3174
+	 */
3175
+	public function setDatetimeSelectorMaxChecked($datetime_selector_max_checked)
3176
+	{
3177
+		$this->datetime_selector_max_checked = absint($datetime_selector_max_checked);
3178
+	}
3179 3179
 }
3180 3180
 
3181 3181
 /**
@@ -3187,87 +3187,87 @@  discard block
 block discarded – undo
3187 3187
  */
3188 3188
 class EE_Environment_Config extends EE_Config_Base
3189 3189
 {
3190
-    /**
3191
-     * Hold any php environment variables that we want to track.
3192
-     *
3193
-     * @var stdClass;
3194
-     */
3195
-    public $php;
3196
-
3197
-
3198
-    /**
3199
-     *    constructor
3200
-     */
3201
-    public function __construct()
3202
-    {
3203
-        $this->php = new stdClass();
3204
-        $this->_set_php_values();
3205
-    }
3206
-
3207
-
3208
-    /**
3209
-     * This sets the php environment variables.
3210
-     *
3211
-     * @since 4.4.0
3212
-     * @return void
3213
-     */
3214
-    protected function _set_php_values()
3215
-    {
3216
-        $this->php->max_input_vars = ini_get('max_input_vars');
3217
-        $this->php->version = phpversion();
3218
-    }
3219
-
3220
-
3221
-    /**
3222
-     * helper method for determining whether input_count is
3223
-     * reaching the potential maximum the server can handle
3224
-     * according to max_input_vars
3225
-     *
3226
-     * @param int   $input_count the count of input vars.
3227
-     * @return array {
3228
-     *                           An array that represents whether available space and if no available space the error
3229
-     *                           message.
3230
-     * @type bool   $has_space   whether more inputs can be added.
3231
-     * @type string $msg         Any message to be displayed.
3232
-     *                           }
3233
-     */
3234
-    public function max_input_vars_limit_check($input_count = 0)
3235
-    {
3236
-        if (
3237
-            ! empty($this->php->max_input_vars)
3238
-            && ($input_count >= $this->php->max_input_vars)
3239
-        ) {
3240
-            // check the server setting because the config value could be stale
3241
-            $max_input_vars = ini_get('max_input_vars');
3242
-            if ($input_count >= $max_input_vars) {
3243
-                return sprintf(
3244
-                    esc_html__(
3245
-                        'The maximum number of inputs on this page has been exceeded. You cannot make edits to this page because of your server\'s PHP "max_input_vars" setting.%1$sThere are %2$d inputs and the maximum amount currently allowed by your server is %3$d.%1$sPlease contact your web host and ask them to raise the "max_input_vars" limit.',
3246
-                        'event_espresso'
3247
-                    ),
3248
-                    '<br>',
3249
-                    $input_count,
3250
-                    $max_input_vars
3251
-                );
3252
-            } else {
3253
-                return '';
3254
-            }
3255
-        } else {
3256
-            return '';
3257
-        }
3258
-    }
3259
-
3260
-
3261
-    /**
3262
-     * The purpose of this method is just to force rechecking php values so if they've changed, they get updated.
3263
-     *
3264
-     * @since 4.4.1
3265
-     * @return void
3266
-     */
3267
-    public function recheck_values()
3268
-    {
3269
-        $this->_set_php_values();
3270
-    }
3190
+	/**
3191
+	 * Hold any php environment variables that we want to track.
3192
+	 *
3193
+	 * @var stdClass;
3194
+	 */
3195
+	public $php;
3196
+
3197
+
3198
+	/**
3199
+	 *    constructor
3200
+	 */
3201
+	public function __construct()
3202
+	{
3203
+		$this->php = new stdClass();
3204
+		$this->_set_php_values();
3205
+	}
3206
+
3207
+
3208
+	/**
3209
+	 * This sets the php environment variables.
3210
+	 *
3211
+	 * @since 4.4.0
3212
+	 * @return void
3213
+	 */
3214
+	protected function _set_php_values()
3215
+	{
3216
+		$this->php->max_input_vars = ini_get('max_input_vars');
3217
+		$this->php->version = phpversion();
3218
+	}
3219
+
3220
+
3221
+	/**
3222
+	 * helper method for determining whether input_count is
3223
+	 * reaching the potential maximum the server can handle
3224
+	 * according to max_input_vars
3225
+	 *
3226
+	 * @param int   $input_count the count of input vars.
3227
+	 * @return array {
3228
+	 *                           An array that represents whether available space and if no available space the error
3229
+	 *                           message.
3230
+	 * @type bool   $has_space   whether more inputs can be added.
3231
+	 * @type string $msg         Any message to be displayed.
3232
+	 *                           }
3233
+	 */
3234
+	public function max_input_vars_limit_check($input_count = 0)
3235
+	{
3236
+		if (
3237
+			! empty($this->php->max_input_vars)
3238
+			&& ($input_count >= $this->php->max_input_vars)
3239
+		) {
3240
+			// check the server setting because the config value could be stale
3241
+			$max_input_vars = ini_get('max_input_vars');
3242
+			if ($input_count >= $max_input_vars) {
3243
+				return sprintf(
3244
+					esc_html__(
3245
+						'The maximum number of inputs on this page has been exceeded. You cannot make edits to this page because of your server\'s PHP "max_input_vars" setting.%1$sThere are %2$d inputs and the maximum amount currently allowed by your server is %3$d.%1$sPlease contact your web host and ask them to raise the "max_input_vars" limit.',
3246
+						'event_espresso'
3247
+					),
3248
+					'<br>',
3249
+					$input_count,
3250
+					$max_input_vars
3251
+				);
3252
+			} else {
3253
+				return '';
3254
+			}
3255
+		} else {
3256
+			return '';
3257
+		}
3258
+	}
3259
+
3260
+
3261
+	/**
3262
+	 * The purpose of this method is just to force rechecking php values so if they've changed, they get updated.
3263
+	 *
3264
+	 * @since 4.4.1
3265
+	 * @return void
3266
+	 */
3267
+	public function recheck_values()
3268
+	{
3269
+		$this->_set_php_values();
3270
+	}
3271 3271
 }
3272 3272
 
3273 3273
 /**
@@ -3279,21 +3279,21 @@  discard block
 block discarded – undo
3279 3279
  */
3280 3280
 class EE_Tax_Config extends EE_Config_Base
3281 3281
 {
3282
-    /*
3282
+	/*
3283 3283
      * flag to indicate whether or not to display ticket prices with the taxes included
3284 3284
      *
3285 3285
      * @var boolean $prices_displayed_including_taxes
3286 3286
      */
3287
-    public $prices_displayed_including_taxes;
3287
+	public $prices_displayed_including_taxes;
3288 3288
 
3289 3289
 
3290
-    /**
3291
-     *    class constructor
3292
-     */
3293
-    public function __construct()
3294
-    {
3295
-        $this->prices_displayed_including_taxes = true;
3296
-    }
3290
+	/**
3291
+	 *    class constructor
3292
+	 */
3293
+	public function __construct()
3294
+	{
3295
+		$this->prices_displayed_including_taxes = true;
3296
+	}
3297 3297
 }
3298 3298
 
3299 3299
 /**
@@ -3306,19 +3306,19 @@  discard block
 block discarded – undo
3306 3306
  */
3307 3307
 class EE_Messages_Config extends EE_Config_Base
3308 3308
 {
3309
-    /**
3310
-     * This is an integer representing the deletion threshold in months for when old messages will get deleted.
3311
-     * A value of 0 represents never deleting.  Default is 0.
3312
-     *
3313
-     * @var integer
3314
-     */
3315
-    public $delete_threshold;
3316
-
3317
-
3318
-    public function __construct()
3319
-    {
3320
-        $this->delete_threshold = 0;
3321
-    }
3309
+	/**
3310
+	 * This is an integer representing the deletion threshold in months for when old messages will get deleted.
3311
+	 * A value of 0 represents never deleting.  Default is 0.
3312
+	 *
3313
+	 * @var integer
3314
+	 */
3315
+	public $delete_threshold;
3316
+
3317
+
3318
+	public function __construct()
3319
+	{
3320
+		$this->delete_threshold = 0;
3321
+	}
3322 3322
 }
3323 3323
 
3324 3324
 /**
@@ -3328,31 +3328,31 @@  discard block
 block discarded – undo
3328 3328
  */
3329 3329
 class EE_Gateway_Config extends EE_Config_Base
3330 3330
 {
3331
-    /**
3332
-     * Array with keys that are payment gateways slugs, and values are arrays
3333
-     * with any config info the gateway wants to store
3334
-     *
3335
-     * @var array
3336
-     */
3337
-    public $payment_settings;
3338
-
3339
-    /**
3340
-     * Where keys are gateway slugs, and values are booleans indicating whether or not
3341
-     * the gateway is stored in the uploads directory
3342
-     *
3343
-     * @var array
3344
-     */
3345
-    public $active_gateways;
3346
-
3347
-
3348
-    /**
3349
-     *    class constructor
3350
-     *
3351
-     * @deprecated
3352
-     */
3353
-    public function __construct()
3354
-    {
3355
-        $this->payment_settings = array();
3356
-        $this->active_gateways = array('Invoice' => false);
3357
-    }
3331
+	/**
3332
+	 * Array with keys that are payment gateways slugs, and values are arrays
3333
+	 * with any config info the gateway wants to store
3334
+	 *
3335
+	 * @var array
3336
+	 */
3337
+	public $payment_settings;
3338
+
3339
+	/**
3340
+	 * Where keys are gateway slugs, and values are booleans indicating whether or not
3341
+	 * the gateway is stored in the uploads directory
3342
+	 *
3343
+	 * @var array
3344
+	 */
3345
+	public $active_gateways;
3346
+
3347
+
3348
+	/**
3349
+	 *    class constructor
3350
+	 *
3351
+	 * @deprecated
3352
+	 */
3353
+	public function __construct()
3354
+	{
3355
+		$this->payment_settings = array();
3356
+		$this->active_gateways = array('Invoice' => false);
3357
+	}
3358 3358
 }
Please login to merge, or discard this patch.
Spacing   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
     public static function instance()
151 151
     {
152 152
         // check if class object is instantiated, and instantiated properly
153
-        if (! self::$_instance instanceof EE_Config) {
153
+        if ( ! self::$_instance instanceof EE_Config) {
154 154
             self::$_instance = new self();
155 155
         }
156 156
         return self::$_instance;
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
                 $this
293 293
             );
294 294
             if (is_object($settings) && property_exists($this, $config)) {
295
-                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
295
+                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__'.$config, $settings);
296 296
                 // call configs populate method to ensure any defaults are set for empty values.
297 297
                 if (method_exists($settings, 'populate')) {
298 298
                     $this->{$config}->populate();
@@ -567,7 +567,7 @@  discard block
 block discarded – undo
567 567
                         break;
568 568
                     // TEST #2 : check that settings section exists
569 569
                     case 2:
570
-                        if (! isset($this->{$section})) {
570
+                        if ( ! isset($this->{$section})) {
571 571
                             if ($display_errors) {
572 572
                                 throw new EE_Error(
573 573
                                     sprintf(
@@ -628,7 +628,7 @@  discard block
 block discarded – undo
628 628
                         break;
629 629
                     // TEST #6 : verify config class is accessible
630 630
                     case 6:
631
-                        if (! class_exists($config_class)) {
631
+                        if ( ! class_exists($config_class)) {
632 632
                             if ($display_errors) {
633 633
                                 throw new EE_Error(
634 634
                                     sprintf(
@@ -645,7 +645,7 @@  discard block
 block discarded – undo
645 645
                         break;
646 646
                     // TEST #7 : check that config has even been set
647 647
                     case 7:
648
-                        if (! isset($this->{$section}->{$name})) {
648
+                        if ( ! isset($this->{$section}->{$name})) {
649 649
                             if ($display_errors) {
650 650
                                 throw new EE_Error(
651 651
                                     sprintf(
@@ -663,7 +663,7 @@  discard block
 block discarded – undo
663 663
                         break;
664 664
                     // TEST #8 : check that config is the requested type
665 665
                     case 8:
666
-                        if (! $this->{$section}->{$name} instanceof $config_class) {
666
+                        if ( ! $this->{$section}->{$name} instanceof $config_class) {
667 667
                             if ($display_errors) {
668 668
                                 throw new EE_Error(
669 669
                                     sprintf(
@@ -682,7 +682,7 @@  discard block
 block discarded – undo
682 682
                         break;
683 683
                     // TEST #9 : verify config object
684 684
                     case 9:
685
-                        if (! $config_obj instanceof EE_Config_Base) {
685
+                        if ( ! $config_obj instanceof EE_Config_Base) {
686 686
                             if ($display_errors) {
687 687
                                 throw new EE_Error(
688 688
                                     sprintf(
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
      */
715 715
     private function _generate_config_option_name($section = '', $name = '')
716 716
     {
717
-        return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
717
+        return 'ee_config-'.strtolower($section.'-'.str_replace(array('EE_', 'EED_'), '', $name));
718 718
     }
719 719
 
720 720
 
@@ -731,7 +731,7 @@  discard block
 block discarded – undo
731 731
     {
732 732
         return ! empty($config_class)
733 733
             ? $config_class
734
-            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
734
+            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))).'_Config';
735 735
     }
736 736
 
737 737
 
@@ -751,17 +751,17 @@  discard block
 block discarded – undo
751 751
         // ensure config class is set to something
752 752
         $config_class = $this->_set_config_class($config_class, $name);
753 753
         // run tests 1-4, 6, and 7 to verify all config params are set and valid
754
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
754
+        if ( ! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
755 755
             return null;
756 756
         }
757 757
         $config_option_name = $this->_generate_config_option_name($section, $name);
758 758
         // if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
759
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
760
-            $this->_addon_option_names[ $config_option_name ] = $config_class;
759
+        if ( ! isset($this->_addon_option_names[$config_option_name])) {
760
+            $this->_addon_option_names[$config_option_name] = $config_class;
761 761
             $this->update_addon_option_names();
762 762
         }
763 763
         // verify the incoming config object but suppress errors
764
-        if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
764
+        if ( ! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
765 765
             $config_obj = new $config_class();
766 766
         }
767 767
         if (get_option($config_option_name)) {
@@ -838,7 +838,7 @@  discard block
 block discarded – undo
838 838
         }
839 839
         $config_option_name = $this->_generate_config_option_name($section, $name);
840 840
         // check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
841
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
841
+        if ( ! isset($this->_addon_option_names[$config_option_name])) {
842 842
             // save new config to db
843 843
             if ($this->set_config($section, $name, $config_class, $config_obj)) {
844 844
                 return true;
@@ -864,7 +864,7 @@  discard block
 block discarded – undo
864 864
                             'event_espresso'
865 865
                         ),
866 866
                         $config_class,
867
-                        'EE_Config->' . $section . '->' . $name
867
+                        'EE_Config->'.$section.'->'.$name
868 868
                     ),
869 869
                     __FILE__,
870 870
                     __FUNCTION__,
@@ -890,7 +890,7 @@  discard block
 block discarded – undo
890 890
         // ensure config class is set to something
891 891
         $config_class = $this->_set_config_class($config_class, $name);
892 892
         // run tests 1-4, 6 and 7 to verify that all params have been set
893
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
893
+        if ( ! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
894 894
             return null;
895 895
         }
896 896
         // now test if the requested config object exists, but suppress errors
@@ -935,7 +935,7 @@  discard block
 block discarded – undo
935 935
         // retrieve the wp-option for this config class.
936 936
         $config_option = maybe_unserialize(get_option($config_option_name, array()));
937 937
         if (empty($config_option)) {
938
-            EE_Config::log($config_option_name . '-NOT-FOUND');
938
+            EE_Config::log($config_option_name.'-NOT-FOUND');
939 939
         }
940 940
         return $config_option;
941 941
     }
@@ -952,7 +952,7 @@  discard block
 block discarded – undo
952 952
             $config_log = get_option(EE_Config::LOG_NAME, array());
953 953
             /** @var RequestParams $request */
954 954
             $request = LoaderFactory::getLoader()->getShared(RequestParams::class);
955
-            $config_log[ (string) microtime(true) ] = array(
955
+            $config_log[(string) microtime(true)] = array(
956 956
                 'config_name' => $config_option_name,
957 957
                 'request'     => $request->requestParams(),
958 958
             );
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
      */
968 968
     public static function trim_log()
969 969
     {
970
-        if (! EE_Config::logging_enabled()) {
970
+        if ( ! EE_Config::logging_enabled()) {
971 971
             return;
972 972
         }
973 973
         $config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
     public static function get_page_for_posts()
992 992
     {
993 993
         $page_for_posts = get_option('page_for_posts');
994
-        if (! $page_for_posts) {
994
+        if ( ! $page_for_posts) {
995 995
             return 'posts';
996 996
         }
997 997
         global $wpdb;
@@ -1048,13 +1048,13 @@  discard block
 block discarded – undo
1048 1048
             )
1049 1049
         ) {
1050 1050
             // grab list of installed widgets
1051
-            $widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1051
+            $widgets_to_register = glob(EE_WIDGETS.'*', GLOB_ONLYDIR);
1052 1052
             // filter list of modules to register
1053 1053
             $widgets_to_register = apply_filters(
1054 1054
                 'FHEE__EE_Config__register_widgets__widgets_to_register',
1055 1055
                 $widgets_to_register
1056 1056
             );
1057
-            if (! empty($widgets_to_register)) {
1057
+            if ( ! empty($widgets_to_register)) {
1058 1058
                 // cycle thru widget folders
1059 1059
                 foreach ($widgets_to_register as $widget_path) {
1060 1060
                     // add to list of installed widget modules
@@ -1104,31 +1104,31 @@  discard block
 block discarded – undo
1104 1104
         // create classname from widget directory name
1105 1105
         $widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1106 1106
         // add class prefix
1107
-        $widget_class = 'EEW_' . $widget;
1107
+        $widget_class = 'EEW_'.$widget;
1108 1108
         // does the widget exist ?
1109
-        if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1109
+        if ( ! is_readable($widget_path.'/'.$widget_class.$widget_ext)) {
1110 1110
             $msg = sprintf(
1111 1111
                 esc_html__(
1112 1112
                     'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1113 1113
                     'event_espresso'
1114 1114
                 ),
1115 1115
                 $widget_class,
1116
-                $widget_path . '/' . $widget_class . $widget_ext
1116
+                $widget_path.'/'.$widget_class.$widget_ext
1117 1117
             );
1118
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1118
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1119 1119
             return;
1120 1120
         }
1121 1121
         // load the widget class file
1122
-        require_once($widget_path . '/' . $widget_class . $widget_ext);
1122
+        require_once($widget_path.'/'.$widget_class.$widget_ext);
1123 1123
         // verify that class exists
1124
-        if (! class_exists($widget_class)) {
1124
+        if ( ! class_exists($widget_class)) {
1125 1125
             $msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1126
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1126
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1127 1127
             return;
1128 1128
         }
1129 1129
         register_widget($widget_class);
1130 1130
         // add to array of registered widgets
1131
-        EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1131
+        EE_Registry::instance()->widgets->{$widget_class} = $widget_path.'/'.$widget_class.$widget_ext;
1132 1132
     }
1133 1133
 
1134 1134
 
@@ -1141,19 +1141,19 @@  discard block
 block discarded – undo
1141 1141
     private function _register_modules()
1142 1142
     {
1143 1143
         // grab list of installed modules
1144
-        $modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1144
+        $modules_to_register = glob(EE_MODULES.'*', GLOB_ONLYDIR);
1145 1145
         // filter list of modules to register
1146 1146
         $modules_to_register = apply_filters(
1147 1147
             'FHEE__EE_Config__register_modules__modules_to_register',
1148 1148
             $modules_to_register
1149 1149
         );
1150
-        if (! empty($modules_to_register)) {
1150
+        if ( ! empty($modules_to_register)) {
1151 1151
             // loop through folders
1152 1152
             foreach ($modules_to_register as $module_path) {
1153 1153
                 /**TEMPORARILY EXCLUDE gateways from modules for time being**/
1154 1154
                 if (
1155
-                    $module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1156
-                    && $module_path !== EE_MODULES . 'gateways'
1155
+                    $module_path !== EE_MODULES.'zzz-copy-this-module-template'
1156
+                    && $module_path !== EE_MODULES.'gateways'
1157 1157
                 ) {
1158 1158
                     // add to list of installed modules
1159 1159
                     EE_Config::register_module($module_path);
@@ -1190,25 +1190,25 @@  discard block
 block discarded – undo
1190 1190
             // remove last segment
1191 1191
             array_pop($module_path);
1192 1192
             // glue it back together
1193
-            $module_path = implode('/', $module_path) . '/';
1193
+            $module_path = implode('/', $module_path).'/';
1194 1194
             // take first segment from file name pieces and sanitize it
1195 1195
             $module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1196 1196
             // ensure class prefix is added
1197
-            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1197
+            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_'.$module : $module;
1198 1198
         } else {
1199 1199
             // we need to generate the filename based off of the folder name
1200 1200
             // grab and sanitize module name
1201 1201
             $module = strtolower(basename($module_path));
1202 1202
             $module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1203 1203
             // like trailingslashit()
1204
-            $module_path = rtrim($module_path, '/') . '/';
1204
+            $module_path = rtrim($module_path, '/').'/';
1205 1205
             // create classname from module directory name
1206 1206
             $module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1207 1207
             // add class prefix
1208
-            $module_class = 'EED_' . $module;
1208
+            $module_class = 'EED_'.$module;
1209 1209
         }
1210 1210
         // does the module exist ?
1211
-        if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1211
+        if ( ! is_readable($module_path.'/'.$module_class.$module_ext)) {
1212 1212
             $msg = sprintf(
1213 1213
                 esc_html__(
1214 1214
                     'The requested %s module file could not be found or is not readable due to file permissions.',
@@ -1216,19 +1216,19 @@  discard block
 block discarded – undo
1216 1216
                 ),
1217 1217
                 $module
1218 1218
             );
1219
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1219
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1220 1220
             return false;
1221 1221
         }
1222 1222
         // load the module class file
1223
-        require_once($module_path . $module_class . $module_ext);
1223
+        require_once($module_path.$module_class.$module_ext);
1224 1224
         // verify that class exists
1225
-        if (! class_exists($module_class)) {
1225
+        if ( ! class_exists($module_class)) {
1226 1226
             $msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1227
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1227
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1228 1228
             return false;
1229 1229
         }
1230 1230
         // add to array of registered modules
1231
-        EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1231
+        EE_Registry::instance()->modules->{$module_class} = $module_path.$module_class.$module_ext;
1232 1232
         do_action(
1233 1233
             'AHEE__EE_Config__register_module__complete',
1234 1234
             $module_class,
@@ -1279,26 +1279,26 @@  discard block
 block discarded – undo
1279 1279
     {
1280 1280
         do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1281 1281
         $module = str_replace('EED_', '', $module);
1282
-        $module_class = 'EED_' . $module;
1283
-        if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1282
+        $module_class = 'EED_'.$module;
1283
+        if ( ! isset(EE_Registry::instance()->modules->{$module_class})) {
1284 1284
             $msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1285
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1285
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1286 1286
             return false;
1287 1287
         }
1288 1288
         if (empty($route)) {
1289 1289
             $msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1290
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1290
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1291 1291
             return false;
1292 1292
         }
1293
-        if (! method_exists('EED_' . $module, $method_name)) {
1293
+        if ( ! method_exists('EED_'.$module, $method_name)) {
1294 1294
             $msg = sprintf(
1295 1295
                 esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1296 1296
                 $route
1297 1297
             );
1298
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1298
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1299 1299
             return false;
1300 1300
         }
1301
-        EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1301
+        EE_Config::$_module_route_map[(string) $key][(string) $route] = array('EED_'.$module, $method_name);
1302 1302
         return true;
1303 1303
     }
1304 1304
 
@@ -1315,8 +1315,8 @@  discard block
 block discarded – undo
1315 1315
     {
1316 1316
         do_action('AHEE__EE_Config__get_route__begin', $route);
1317 1317
         $route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1318
-        if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1319
-            return EE_Config::$_module_route_map[ $key ][ $route ];
1318
+        if (isset(EE_Config::$_module_route_map[$key][$route])) {
1319
+            return EE_Config::$_module_route_map[$key][$route];
1320 1320
         }
1321 1321
         return null;
1322 1322
     }
@@ -1348,47 +1348,47 @@  discard block
 block discarded – undo
1348 1348
     public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1349 1349
     {
1350 1350
         do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1351
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1351
+        if ( ! isset(EE_Config::$_module_route_map[$key][$route]) || empty($route)) {
1352 1352
             $msg = sprintf(
1353 1353
                 esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1354 1354
                 $route
1355 1355
             );
1356
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1356
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1357 1357
             return false;
1358 1358
         }
1359 1359
         if (empty($forward)) {
1360 1360
             $msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1361
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1361
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1362 1362
             return false;
1363 1363
         }
1364 1364
         if (is_array($forward)) {
1365
-            if (! isset($forward[1])) {
1365
+            if ( ! isset($forward[1])) {
1366 1366
                 $msg = sprintf(
1367 1367
                     esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1368 1368
                     $route
1369 1369
                 );
1370
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1370
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1371 1371
                 return false;
1372 1372
             }
1373
-            if (! method_exists($forward[0], $forward[1])) {
1373
+            if ( ! method_exists($forward[0], $forward[1])) {
1374 1374
                 $msg = sprintf(
1375 1375
                     esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1376 1376
                     $forward[1],
1377 1377
                     $route
1378 1378
                 );
1379
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1379
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1380 1380
                 return false;
1381 1381
             }
1382
-        } elseif (! function_exists($forward)) {
1382
+        } elseif ( ! function_exists($forward)) {
1383 1383
             $msg = sprintf(
1384 1384
                 esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1385 1385
                 $forward,
1386 1386
                 $route
1387 1387
             );
1388
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1388
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1389 1389
             return false;
1390 1390
         }
1391
-        EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1391
+        EE_Config::$_module_forward_map[$key][$route][absint($status)] = $forward;
1392 1392
         return true;
1393 1393
     }
1394 1394
 
@@ -1406,10 +1406,10 @@  discard block
 block discarded – undo
1406 1406
     public static function get_forward($route = null, $status = 0, $key = 'ee')
1407 1407
     {
1408 1408
         do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1409
-        if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1409
+        if (isset(EE_Config::$_module_forward_map[$key][$route][$status])) {
1410 1410
             return apply_filters(
1411 1411
                 'FHEE__EE_Config__get_forward',
1412
-                EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1412
+                EE_Config::$_module_forward_map[$key][$route][$status],
1413 1413
                 $route,
1414 1414
                 $status
1415 1415
             );
@@ -1433,15 +1433,15 @@  discard block
 block discarded – undo
1433 1433
     public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1434 1434
     {
1435 1435
         do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1436
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1436
+        if ( ! isset(EE_Config::$_module_route_map[$key][$route]) || empty($route)) {
1437 1437
             $msg = sprintf(
1438 1438
                 esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1439 1439
                 $route
1440 1440
             );
1441
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1441
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1442 1442
             return false;
1443 1443
         }
1444
-        if (! is_readable($view)) {
1444
+        if ( ! is_readable($view)) {
1445 1445
             $msg = sprintf(
1446 1446
                 esc_html__(
1447 1447
                     'The %s view file could not be found or is not readable due to file permissions.',
@@ -1449,10 +1449,10 @@  discard block
 block discarded – undo
1449 1449
                 ),
1450 1450
                 $view
1451 1451
             );
1452
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1452
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1453 1453
             return false;
1454 1454
         }
1455
-        EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1455
+        EE_Config::$_module_view_map[$key][$route][absint($status)] = $view;
1456 1456
         return true;
1457 1457
     }
1458 1458
 
@@ -1470,10 +1470,10 @@  discard block
 block discarded – undo
1470 1470
     public static function get_view($route = null, $status = 0, $key = 'ee')
1471 1471
     {
1472 1472
         do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1473
-        if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1473
+        if (isset(EE_Config::$_module_view_map[$key][$route][$status])) {
1474 1474
             return apply_filters(
1475 1475
                 'FHEE__EE_Config__get_view',
1476
-                EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1476
+                EE_Config::$_module_view_map[$key][$route][$status],
1477 1477
                 $route,
1478 1478
                 $status
1479 1479
             );
@@ -1499,7 +1499,7 @@  discard block
 block discarded – undo
1499 1499
      */
1500 1500
     public static function getLegacyShortcodesManager()
1501 1501
     {
1502
-        if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1502
+        if ( ! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1503 1503
             EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1504 1504
                 LegacyShortcodesManager::class
1505 1505
             );
@@ -1545,7 +1545,7 @@  discard block
 block discarded – undo
1545 1545
      */
1546 1546
     public function get_pretty($property)
1547 1547
     {
1548
-        if (! property_exists($this, $property)) {
1548
+        if ( ! property_exists($this, $property)) {
1549 1549
             throw new EE_Error(
1550 1550
                 sprintf(
1551 1551
                     esc_html__(
@@ -1773,11 +1773,11 @@  discard block
 block discarded – undo
1773 1773
      */
1774 1774
     public function reg_page_url()
1775 1775
     {
1776
-        if (! $this->reg_page_url) {
1776
+        if ( ! $this->reg_page_url) {
1777 1777
             $this->reg_page_url = add_query_arg(
1778 1778
                 array('uts' => time()),
1779 1779
                 get_permalink($this->reg_page_id)
1780
-            ) . '#checkout';
1780
+            ).'#checkout';
1781 1781
         }
1782 1782
         return $this->reg_page_url;
1783 1783
     }
@@ -1793,7 +1793,7 @@  discard block
 block discarded – undo
1793 1793
      */
1794 1794
     public function txn_page_url($query_args = array())
1795 1795
     {
1796
-        if (! $this->txn_page_url) {
1796
+        if ( ! $this->txn_page_url) {
1797 1797
             $this->txn_page_url = get_permalink($this->txn_page_id);
1798 1798
         }
1799 1799
         if ($query_args) {
@@ -1814,7 +1814,7 @@  discard block
 block discarded – undo
1814 1814
      */
1815 1815
     public function thank_you_page_url($query_args = array())
1816 1816
     {
1817
-        if (! $this->thank_you_page_url) {
1817
+        if ( ! $this->thank_you_page_url) {
1818 1818
             $this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1819 1819
         }
1820 1820
         if ($query_args) {
@@ -1833,7 +1833,7 @@  discard block
 block discarded – undo
1833 1833
      */
1834 1834
     public function cancel_page_url()
1835 1835
     {
1836
-        if (! $this->cancel_page_url) {
1836
+        if ( ! $this->cancel_page_url) {
1837 1837
             $this->cancel_page_url = get_permalink($this->cancel_page_id);
1838 1838
         }
1839 1839
         return $this->cancel_page_url;
@@ -1876,13 +1876,13 @@  discard block
 block discarded – undo
1876 1876
         $current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1877 1877
         $option = self::OPTION_NAME_UXIP;
1878 1878
         // set correct table for query
1879
-        $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1879
+        $table_name = $wpdb->get_blog_prefix($current_main_site_id).'options';
1880 1880
         // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1881 1881
         // get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1882 1882
         // re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1883 1883
         // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1884 1884
         // for the purpose of caching.
1885
-        $pre = apply_filters('pre_option_' . $option, false, $option);
1885
+        $pre = apply_filters('pre_option_'.$option, false, $option);
1886 1886
         if (false !== $pre) {
1887 1887
             EE_Core_Config::$ee_ueip_option = $pre;
1888 1888
             return EE_Core_Config::$ee_ueip_option;
@@ -1896,10 +1896,10 @@  discard block
 block discarded – undo
1896 1896
         if (is_object($row)) {
1897 1897
             $value = $row->option_value;
1898 1898
         } else { // option does not exist so use default.
1899
-            EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1899
+            EE_Core_Config::$ee_ueip_option = apply_filters('default_option_'.$option, false, $option);
1900 1900
             return EE_Core_Config::$ee_ueip_option;
1901 1901
         }
1902
-        EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1902
+        EE_Core_Config::$ee_ueip_option = apply_filters('option_'.$option, maybe_unserialize($value), $option);
1903 1903
         return EE_Core_Config::$ee_ueip_option;
1904 1904
     }
1905 1905
 
@@ -2169,12 +2169,12 @@  discard block
 block discarded – undo
2169 2169
 
2170 2170
         /** @var TableAnalysis $table_analysis */
2171 2171
         $table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
2172
-        if (! $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())) {
2172
+        if ( ! $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())) {
2173 2173
             return;
2174 2174
         }
2175 2175
         // retrieve the country settings from the db, just in case they have been customized
2176 2176
         $country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2177
-        if (! $country instanceof EE_Country) {
2177
+        if ( ! $country instanceof EE_Country) {
2178 2178
             throw new DomainException(
2179 2179
                 sprintf(
2180 2180
                     esc_html__('Invalid Country ISO Code: %1$s', 'event_espresso'),
@@ -2182,14 +2182,14 @@  discard block
 block discarded – undo
2182 2182
                 )
2183 2183
             );
2184 2184
         }
2185
-        $this->code    = $country->currency_code();                  // currency code: USD, CAD, EUR
2186
-        $this->name    = $country->currency_name_single();           // Dollar
2187
-        $this->plural  = $country->currency_name_plural();           // Dollars
2188
-        $this->sign    = $country->currency_sign();                  // currency sign: $
2189
-        $this->sign_b4 = $country->currency_sign_before();           // currency sign before or after
2190
-        $this->dec_plc = $country->currency_decimal_places();        // decimal places: 2 = 0.00  3 = 0.000
2191
-        $this->dec_mrk = $country->currency_decimal_mark();          // decimal mark: ',' = 0,01 or '.' = 0.01
2192
-        $this->thsnds  = $country->currency_thousands_separator();   // thousands sep: ',' = 1,000 or '.' = 1.000
2185
+        $this->code    = $country->currency_code(); // currency code: USD, CAD, EUR
2186
+        $this->name    = $country->currency_name_single(); // Dollar
2187
+        $this->plural  = $country->currency_name_plural(); // Dollars
2188
+        $this->sign    = $country->currency_sign(); // currency sign: $
2189
+        $this->sign_b4 = $country->currency_sign_before(); // currency sign before or after
2190
+        $this->dec_plc = $country->currency_decimal_places(); // decimal places: 2 = 0.00  3 = 0.000
2191
+        $this->dec_mrk = $country->currency_decimal_mark(); // decimal mark: ',' = 0,01 or '.' = 0.01
2192
+        $this->thsnds  = $country->currency_thousands_separator(); // thousands sep: ',' = 1,000 or '.' = 1.000
2193 2193
     }
2194 2194
 
2195 2195
 
@@ -2485,8 +2485,8 @@  discard block
 block discarded – undo
2485 2485
             $closing_a_tag = '';
2486 2486
             if (function_exists('get_privacy_policy_url')) {
2487 2487
                 $privacy_page_url = get_privacy_policy_url();
2488
-                if (! empty($privacy_page_url)) {
2489
-                    $opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2488
+                if ( ! empty($privacy_page_url)) {
2489
+                    $opening_a_tag = '<a href="'.$privacy_page_url.'" target="_blank">';
2490 2490
                     $closing_a_tag = '</a>';
2491 2491
                 }
2492 2492
             }
@@ -2693,7 +2693,7 @@  discard block
 block discarded – undo
2693 2693
     public function log_file_name($reset = false)
2694 2694
     {
2695 2695
         if (empty($this->log_file_name) || $reset) {
2696
-            $this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2696
+            $this->log_file_name = sanitize_key('espresso_log_'.md5(uniqid('', true))).'.txt';
2697 2697
             EE_Config::instance()->update_espresso_config(false, false);
2698 2698
         }
2699 2699
         return $this->log_file_name;
@@ -2707,7 +2707,7 @@  discard block
 block discarded – undo
2707 2707
     public function debug_file_name($reset = false)
2708 2708
     {
2709 2709
         if (empty($this->debug_file_name) || $reset) {
2710
-            $this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2710
+            $this->debug_file_name = sanitize_key('espresso_debug_'.md5(uniqid('', true))).'.txt';
2711 2711
             EE_Config::instance()->update_espresso_config(false, false);
2712 2712
         }
2713 2713
         return $this->debug_file_name;
@@ -2905,21 +2905,21 @@  discard block
 block discarded – undo
2905 2905
         $this->use_google_maps = true;
2906 2906
         $this->google_map_api_key = '';
2907 2907
         // for event details pages (reg page)
2908
-        $this->event_details_map_width = 585;            // ee_map_width_single
2909
-        $this->event_details_map_height = 362;            // ee_map_height_single
2910
-        $this->event_details_map_zoom = 14;            // ee_map_zoom_single
2911
-        $this->event_details_display_nav = true;            // ee_map_nav_display_single
2912
-        $this->event_details_nav_size = false;            // ee_map_nav_size_single
2913
-        $this->event_details_control_type = 'default';        // ee_map_type_control_single
2914
-        $this->event_details_map_align = 'center';            // ee_map_align_single
2908
+        $this->event_details_map_width = 585; // ee_map_width_single
2909
+        $this->event_details_map_height = 362; // ee_map_height_single
2910
+        $this->event_details_map_zoom = 14; // ee_map_zoom_single
2911
+        $this->event_details_display_nav = true; // ee_map_nav_display_single
2912
+        $this->event_details_nav_size = false; // ee_map_nav_size_single
2913
+        $this->event_details_control_type = 'default'; // ee_map_type_control_single
2914
+        $this->event_details_map_align = 'center'; // ee_map_align_single
2915 2915
         // for event list pages
2916
-        $this->event_list_map_width = 300;            // ee_map_width
2917
-        $this->event_list_map_height = 185;        // ee_map_height
2918
-        $this->event_list_map_zoom = 12;            // ee_map_zoom
2919
-        $this->event_list_display_nav = false;        // ee_map_nav_display
2920
-        $this->event_list_nav_size = true;            // ee_map_nav_size
2921
-        $this->event_list_control_type = 'dropdown';        // ee_map_type_control
2922
-        $this->event_list_map_align = 'center';            // ee_map_align
2916
+        $this->event_list_map_width = 300; // ee_map_width
2917
+        $this->event_list_map_height = 185; // ee_map_height
2918
+        $this->event_list_map_zoom = 12; // ee_map_zoom
2919
+        $this->event_list_display_nav = false; // ee_map_nav_display
2920
+        $this->event_list_nav_size = true; // ee_map_nav_size
2921
+        $this->event_list_control_type = 'dropdown'; // ee_map_type_control
2922
+        $this->event_list_map_align = 'center'; // ee_map_align
2923 2923
     }
2924 2924
 }
2925 2925
 
Please login to merge, or discard this patch.
core/EE_Payment_Processor.core.php 2 patches
Indentation   +819 added lines, -819 removed lines patch added patch discarded remove patch
@@ -17,823 +17,823 @@
 block discarded – undo
17 17
  */
18 18
 class EE_Payment_Processor extends EE_Processor_Base implements ResettableInterface
19 19
 {
20
-    /**
21
-     * @var EE_Payment_Processor $_instance
22
-     * @access    private
23
-     */
24
-    private static $_instance;
25
-
26
-
27
-    /**
28
-     * @singleton method used to instantiate class object
29
-     * @access    public
30
-     * @return EE_Payment_Processor instance
31
-     */
32
-    public static function instance()
33
-    {
34
-        // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Payment_Processor) {
36
-            self::$_instance = new self();
37
-        }
38
-        return self::$_instance;
39
-    }
40
-
41
-
42
-    /**
43
-     * @return EE_Payment_Processor
44
-     */
45
-    public static function reset()
46
-    {
47
-        self::$_instance = null;
48
-        return self::instance();
49
-    }
50
-
51
-
52
-    /**
53
-     *private constructor to prevent direct creation
54
-     *
55
-     * @Constructor
56
-     * @access private
57
-     */
58
-    private function __construct()
59
-    {
60
-        do_action('AHEE__EE_Payment_Processor__construct');
61
-        add_action('http_api_curl', [$this, '_curl_requests_to_paypal_use_tls'], 10, 3);
62
-    }
63
-
64
-
65
-    /**
66
-     * Using the selected gateway, processes the payment for that transaction, and updates the transaction
67
-     * appropriately. Saves the payment that is generated
68
-     *
69
-     * @param EE_Payment_Method         $payment_method
70
-     * @param EE_Transaction            $transaction
71
-     * @param float|null                $amount       if only part of the transaction is to be paid for, how much.
72
-     *                                                Leave null if payment is for the full amount owing
73
-     * @param EE_Billing_Info_Form|null $billing_form (or probably null, if it's an offline or offsite payment method).
74
-     *                                                Receive_form_submission() should have
75
-     *                                                already been called on the billing form
76
-     *                                                (ie, its inputs should have their normalized values set).
77
-     * @param string|null               $return_url   string used mostly by offsite gateways to specify
78
-     *                                                where to go AFTER the offsite gateway
79
-     * @param string                    $method       like 'CART', indicates who the client who called this was
80
-     * @param bool                      $by_admin     TRUE if payment is being attempted from the admin
81
-     * @param bool                      $update_txn   whether or not to call
82
-     *                                                EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
83
-     * @param string                    $cancel_url   URL to return to if off-site payments are cancelled
84
-     * @return EE_Payment
85
-     * @throws EE_Error
86
-     * @throws InvalidArgumentException
87
-     * @throws ReflectionException
88
-     * @throws RuntimeException
89
-     * @throws InvalidDataTypeException
90
-     * @throws InvalidInterfaceException
91
-     */
92
-    public function process_payment(
93
-        EE_Payment_Method $payment_method,
94
-        EE_Transaction $transaction,
95
-        ?float $amount = null,
96
-        ?EE_Billing_Info_Form $billing_form = null,
97
-        ?string $return_url = null,
98
-        string $method = 'CART',
99
-        bool $by_admin = false,
100
-        bool $update_txn = true,
101
-        string $cancel_url = ''
102
-    ): ?EE_Payment {
103
-        if ((float) $amount < 0) {
104
-            throw new EE_Error(
105
-                sprintf(
106
-                    esc_html__(
107
-                        'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
108
-                        'event_espresso'
109
-                    ),
110
-                    $amount,
111
-                    $transaction->ID()
112
-                )
113
-            );
114
-        }
115
-        // verify payment method
116
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
117
-            $payment_method,
118
-            true
119
-        );
120
-        // verify transaction
121
-        EEM_Transaction::instance()->ensure_is_obj($transaction);
122
-        $transaction->set_payment_method_ID($payment_method->ID());
123
-        // verify payment method type
124
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
125
-            $payment = $payment_method->type_obj()->process_payment(
126
-                $transaction,
127
-                min($amount, $transaction->remaining()), // make sure we don't overcharge
128
-                $billing_form,
129
-                $return_url,
130
-                add_query_arg(['ee_cancel_payment' => true], $cancel_url),
131
-                $method,
132
-                $by_admin
133
-            );
134
-            // check if payment method uses an off-site gateway
135
-            if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
136
-                // don't process payments for off-site gateways yet because no payment has occurred yet
137
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
138
-            }
139
-            return $payment;
140
-        }
141
-        EE_Error::add_error(
142
-            sprintf(
143
-                esc_html__(
144
-                    'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
145
-                    'event_espresso'
146
-                ),
147
-                '<br/>',
148
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
149
-            ),
150
-            __FILE__,
151
-            __FUNCTION__,
152
-            __LINE__
153
-        );
154
-        return null;
155
-    }
156
-
157
-
158
-    /**
159
-     * @param EE_Transaction|int $transaction
160
-     * @param EE_Payment_Method  $payment_method
161
-     * @return string
162
-     * @throws EE_Error
163
-     * @throws InvalidArgumentException
164
-     * @throws InvalidDataTypeException
165
-     * @throws InvalidInterfaceException
166
-     */
167
-    public function get_ipn_url_for_payment_method($transaction, $payment_method)
168
-    {
169
-        /** @type \EE_Transaction $transaction */
170
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
171
-        $primary_reg = $transaction->primary_registration();
172
-        if (! $primary_reg instanceof EE_Registration) {
173
-            throw new EE_Error(
174
-                sprintf(
175
-                    esc_html__(
176
-                        'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
177
-                        'event_espresso'
178
-                    ),
179
-                    $transaction->ID()
180
-                )
181
-            );
182
-        }
183
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
184
-            $payment_method,
185
-            true
186
-        );
187
-        $url            = add_query_arg(
188
-            [
189
-                'e_reg_url_link'    => $primary_reg->reg_url_link(),
190
-                'ee_payment_method' => $payment_method->slug(),
191
-            ],
192
-            EE_Registry::instance()->CFG->core->txn_page_url()
193
-        );
194
-        return $url;
195
-    }
196
-
197
-
198
-    /**
199
-     * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
200
-     * we can easily find what registration the IPN is for and what payment method.
201
-     * However, if not, we'll give all payment methods a chance to claim it and process it.
202
-     * If a payment is found for the IPN info, it is saved.
203
-     *
204
-     * @param array              $_req_data            form post data
205
-     * @param EE_Transaction|int $transaction          optional (or a transactions id)
206
-     * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
207
-     * @param boolean            $update_txn           whether or not to call
208
-     *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
209
-     * @param bool               $separate_IPN_request whether the IPN uses a separate request (true, like PayPal)
210
-     *                                                 or is processed manually (false, like Authorize.net)
211
-     * @return EE_Payment
212
-     * @throws EE_Error
213
-     * @throws Exception
214
-     * @throws \RuntimeException
215
-     * @throws \ReflectionException
216
-     * @throws \InvalidArgumentException
217
-     * @throws InvalidInterfaceException
218
-     * @throws InvalidDataTypeException
219
-     */
220
-    public function process_ipn(
221
-        $_req_data,
222
-        $transaction = null,
223
-        $payment_method = null,
224
-        $update_txn = true,
225
-        $separate_IPN_request = true
226
-    ) {
227
-        EE_Registry::instance()->load_model('Change_Log');
228
-        $_req_data = $this->_remove_unusable_characters_from_array((array) $_req_data);
229
-        EE_Processor_Base::set_IPN($separate_IPN_request);
230
-        $obj_for_log = null;
231
-        if ($transaction instanceof EE_Transaction) {
232
-            $obj_for_log = $transaction;
233
-            if ($payment_method instanceof EE_Payment_Method) {
234
-                $obj_for_log = EEM_Payment::instance()->get_one(
235
-                    [
236
-                        ['TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()],
237
-                        'order_by' => ['PAY_timestamp' => 'desc'],
238
-                    ]
239
-                );
240
-            }
241
-        } elseif ($payment_method instanceof EE_Payment) {
242
-            $obj_for_log = $payment_method;
243
-        }
244
-        $log = EEM_Change_Log::instance()->log(
245
-            EEM_Change_Log::type_gateway,
246
-            ['IPN data received' => $_req_data],
247
-            $obj_for_log
248
-        );
249
-        try {
250
-            /**
251
-             * @var EE_Payment $payment
252
-             */
253
-            $payment = null;
254
-            if ($transaction && $payment_method) {
255
-                /** @type EE_Transaction $transaction */
256
-                $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
257
-                /** @type EE_Payment_Method $payment_method */
258
-                $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
259
-                if ($payment_method->type_obj() instanceof EE_PMT_Base) {
260
-                    try {
261
-                        $payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
262
-                        $log->set_object($payment);
263
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
264
-                        EEM_Change_Log::instance()->log(
265
-                            EEM_Change_Log::type_gateway,
266
-                            [
267
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
268
-                                'current_url' => EEH_URL::current_url(),
269
-                                'payment'     => $e->getPaymentProperties(),
270
-                                'IPN_data'    => $e->getIpnData(),
271
-                            ],
272
-                            $obj_for_log
273
-                        );
274
-                        return $e->getPayment();
275
-                    }
276
-                } else {
277
-                    // not a payment
278
-                    EE_Error::add_error(
279
-                        sprintf(
280
-                            esc_html__(
281
-                                'A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.',
282
-                                'event_espresso'
283
-                            ),
284
-                            '<br/>',
285
-                            EE_Registry::instance()->CFG->organization->get_pretty('email')
286
-                        ),
287
-                        __FILE__,
288
-                        __FUNCTION__,
289
-                        __LINE__
290
-                    );
291
-                }
292
-            } else {
293
-                // that's actually pretty ok. The IPN just wasn't able
294
-                // to identify which transaction or payment method this was for
295
-                // give all active payment methods a chance to claim it
296
-                $active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
297
-                foreach ($active_payment_methods as $active_payment_method) {
298
-                    try {
299
-                        $payment        = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
300
-                        $payment_method = $active_payment_method;
301
-                        EEM_Change_Log::instance()->log(
302
-                            EEM_Change_Log::type_gateway,
303
-                            ['IPN data' => $_req_data],
304
-                            $payment
305
-                        );
306
-                        break;
307
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
308
-                        EEM_Change_Log::instance()->log(
309
-                            EEM_Change_Log::type_gateway,
310
-                            [
311
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
312
-                                'current_url' => EEH_URL::current_url(),
313
-                                'payment'     => $e->getPaymentProperties(),
314
-                                'IPN_data'    => $e->getIpnData(),
315
-                            ],
316
-                            $obj_for_log
317
-                        );
318
-                        return $e->getPayment();
319
-                    } catch (EE_Error $e) {
320
-                        // that's fine- it apparently couldn't handle the IPN
321
-                    }
322
-                }
323
-            }
324
-            // EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
325
-            if ($payment instanceof EE_Payment) {
326
-                $payment->save();
327
-                //  update the TXN
328
-                $this->update_txn_based_on_payment(
329
-                    $transaction,
330
-                    $payment,
331
-                    $update_txn,
332
-                    $separate_IPN_request
333
-                );
334
-            } else {
335
-                // we couldn't find the payment for this IPN... let's try and log at least SOMETHING
336
-                if ($payment_method) {
337
-                    EEM_Change_Log::instance()->log(
338
-                        EEM_Change_Log::type_gateway,
339
-                        ['IPN data' => $_req_data],
340
-                        $payment_method
341
-                    );
342
-                } elseif ($transaction) {
343
-                    EEM_Change_Log::instance()->log(
344
-                        EEM_Change_Log::type_gateway,
345
-                        ['IPN data' => $_req_data],
346
-                        $transaction
347
-                    );
348
-                }
349
-            }
350
-            return $payment;
351
-        } catch (EE_Error $e) {
352
-            do_action(
353
-                'AHEE__log',
354
-                __FILE__,
355
-                __FUNCTION__,
356
-                sprintf(
357
-                    esc_html__(
358
-                        'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
359
-                        'event_espresso'
360
-                    ),
361
-                    print_r($transaction, true),
362
-                    print_r($_req_data, true),
363
-                    $e->getMessage()
364
-                )
365
-            );
366
-            throw $e;
367
-        }
368
-    }
369
-
370
-
371
-    /**
372
-     * Removes any non-printable illegal characters from the input,
373
-     * which might cause a raucous when trying to insert into the database
374
-     *
375
-     * @param array $request_data
376
-     * @return array
377
-     */
378
-    protected function _remove_unusable_characters_from_array(array $request_data)
379
-    {
380
-        $return_data = [];
381
-        foreach ($request_data as $key => $value) {
382
-            $return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
383
-                $value
384
-            );
385
-        }
386
-        return $return_data;
387
-    }
388
-
389
-
390
-    /**
391
-     * Removes any non-printable illegal characters from the input,
392
-     * which might cause a raucous when trying to insert into the database
393
-     *
394
-     * @param string $request_data
395
-     * @return string
396
-     */
397
-    protected function _remove_unusable_characters($request_data)
398
-    {
399
-        return preg_replace('/[^[:print:]]/', '', $request_data);
400
-    }
401
-
402
-
403
-    /**
404
-     * Should be called just before displaying the payment attempt results to the user,
405
-     * when the payment attempt has finished. Some payment methods may have special
406
-     * logic to perform here. For example, if process_payment() happens on a special request
407
-     * and then the user is redirected to a page that displays the payment's status, this
408
-     * should be called while loading the page that displays the payment's status. If the user is
409
-     * sent to an offsite payment provider, this should be called upon returning from that offsite payment
410
-     * provider.
411
-     *
412
-     * @param EE_Transaction|int $transaction
413
-     * @param bool               $update_txn whether to call
414
-     *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
415
-     * @return EE_Payment
416
-     * @throws EE_Error
417
-     * @throws InvalidArgumentException
418
-     * @throws ReflectionException
419
-     * @throws RuntimeException
420
-     * @throws InvalidDataTypeException
421
-     * @throws InvalidInterfaceException
422
-     * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
423
-     *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
424
-     */
425
-    public function finalize_payment_for(EE_Transaction $transaction, bool $update_txn = true): ?EE_Payment
426
-    {
427
-        $last_payment_method = $transaction->payment_method();
428
-        if ($last_payment_method instanceof EE_Payment_Method) {
429
-            $payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
430
-            $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
431
-            return $payment;
432
-        }
433
-        return null;
434
-    }
435
-
436
-
437
-    /**
438
-     * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
439
-     *
440
-     * @param EE_Payment_Method|null $payment_method
441
-     * @param EE_Payment             $payment_to_refund
442
-     * @param array                  $refund_info
443
-     * @return EE_Payment
444
-     * @throws EE_Error
445
-     * @throws ReflectionException
446
-     */
447
-    public function process_refund(
448
-        ?EE_Payment_Method $payment_method,
449
-        EE_Payment $payment_to_refund,
450
-        array $refund_info = []
451
-    ) {
452
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
453
-            $payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
454
-            $this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
455
-        }
456
-        return $payment_to_refund;
457
-    }
458
-
459
-
460
-    /**
461
-     * This should be called each time there may have been an update to a
462
-     * payment on a transaction (ie, we asked for a payment to process a
463
-     * payment for a transaction, or we told a payment method about an IPN, or
464
-     * we told a payment method to
465
-     * "finalize_payment_for" (a transaction), or we told a payment method to
466
-     * process a refund. This should handle firing the correct hooks to
467
-     * indicate
468
-     * what exactly happened and updating the transaction appropriately). This
469
-     * could be integrated directly into EE_Transaction upon save, but we want
470
-     * this logic to be separate from 'normal' plain-jane saving and updating
471
-     * of transactions and payments, and to be tied to payment processing.
472
-     * Note: this method DOES NOT save the payment passed into it. It is the responsibility
473
-     * of previous code to decide whether or not to save (because the payment passed into
474
-     * this method might be a temporary, never-to-be-saved payment from an offline gateway,
475
-     * in which case we only want that payment object for some temporary usage during this request,
476
-     * but we don't want it to be saved).
477
-     *
478
-     * @param EE_Transaction|int $transaction
479
-     * @param EE_Payment         $payment
480
-     * @param boolean            $update_txn
481
-     *                        whether or not to call
482
-     *                        EE_Transaction_Processor::
483
-     *                        update_transaction_and_registrations_after_checkout_or_payment()
484
-     *                        (you can save 1 DB query if you know you're going
485
-     *                        to save it later instead)
486
-     * @param bool               $IPN
487
-     *                        if processing IPNs or other similar payment
488
-     *                        related activities that occur in alternate
489
-     *                        requests than the main one that is processing the
490
-     *                        TXN, then set this to true to check whether the
491
-     *                        TXN is locked before updating
492
-     * @throws EE_Error
493
-     * @throws InvalidArgumentException
494
-     * @throws ReflectionException
495
-     * @throws RuntimeException
496
-     * @throws InvalidDataTypeException
497
-     * @throws InvalidInterfaceException
498
-     */
499
-    public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
500
-    {
501
-        $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
502
-        /** @type EE_Transaction $transaction */
503
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
504
-        // can we freely update the TXN at this moment?
505
-        if ($IPN && $transaction->is_locked()) {
506
-            // don't update the transaction at this exact moment
507
-            // because the TXN is active in another request
508
-            EE_Cron_Tasks::schedule_update_transaction_with_payment(
509
-                time(),
510
-                $transaction->ID(),
511
-                $payment->ID()
512
-            );
513
-        } else {
514
-            // verify payment and that it has been saved
515
-            if ($payment instanceof EE_Payment && $payment->ID()) {
516
-                if (
517
-                    $payment->payment_method() instanceof EE_Payment_Method
518
-                    && $payment->payment_method()->type_obj() instanceof EE_PMT_Base
519
-                ) {
520
-                    $payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
521
-                    // update TXN registrations with payment info
522
-                    $this->process_registration_payments($transaction, $payment);
523
-                }
524
-                $do_action = $payment->just_approved()
525
-                    ? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
526
-                    : $do_action;
527
-            } else {
528
-                // send out notifications
529
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
530
-                $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
531
-            }
532
-            if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
533
-                /** @type EE_Transaction_Payments $transaction_payments */
534
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
535
-                // set new value for total paid
536
-                $transaction_payments->calculate_total_payments_and_update_status($transaction);
537
-                // call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
538
-                if ($update_txn) {
539
-                    $this->_post_payment_processing($transaction, $payment, $IPN);
540
-                }
541
-            }
542
-            // granular hook for others to use.
543
-            do_action($do_action, $transaction, $payment);
544
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
545
-            // global hook for others to use.
546
-            do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
547
-        }
548
-    }
549
-
550
-
551
-    /**
552
-     * update registrations REG_paid field after successful payment and link registrations with payment
553
-     *
554
-     * @param EE_Transaction    $transaction
555
-     * @param EE_Payment        $payment
556
-     * @param EE_Registration[] $registrations
557
-     * @throws EE_Error
558
-     * @throws InvalidArgumentException
559
-     * @throws RuntimeException
560
-     * @throws InvalidDataTypeException
561
-     * @throws InvalidInterfaceException
562
-     */
563
-    public function process_registration_payments(
564
-        EE_Transaction $transaction,
565
-        EE_Payment $payment,
566
-        array $registrations = []
567
-    ) {
568
-        // only process if payment was successful
569
-        if ($payment->status() !== EEM_Payment::status_id_approved) {
570
-            return;
571
-        }
572
-        // EEM_Registration::instance()->show_next_x_db_queries();
573
-        if (empty($registrations)) {
574
-            // find registrations with monies owing that can receive a payment
575
-            $registrations = $transaction->registrations(
576
-                [
577
-                    [
578
-                        // only these reg statuses can receive payments
579
-                        'STS_ID'           => ['IN', EEM_Registration::reg_statuses_that_allow_payment()],
580
-                        'REG_final_price'  => ['!=', 0],
581
-                        'REG_final_price*' => ['!=', 'REG_paid', true],
582
-                    ],
583
-                ]
584
-            );
585
-        }
586
-        // still nothing ??!??
587
-        if (empty($registrations)) {
588
-            return;
589
-        }
590
-        // todo: break out the following logic into a separate strategy class
591
-        // todo: named something like "Sequential_Reg_Payment_Strategy"
592
-        // todo: which would apply payments using the capitalist "first come first paid" approach
593
-        // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
594
-        // todo: which would be the socialist "everybody gets a piece of pie" approach,
595
-        // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
596
-        $refund = $payment->is_a_refund();
597
-        // how much is available to apply to registrations?
598
-        $available_payment_amount = (float) abs($payment->amount());
599
-        foreach ($registrations as $registration) {
600
-            if ($registration instanceof EE_Registration) {
601
-                // nothing left?
602
-                if ($available_payment_amount <= 0) {
603
-                    break;
604
-                }
605
-                if ($refund) {
606
-                    $available_payment_amount = $this->process_registration_refund(
607
-                        $registration,
608
-                        $payment,
609
-                        $available_payment_amount
610
-                    );
611
-                } else {
612
-                    $available_payment_amount = $this->process_registration_payment(
613
-                        $registration,
614
-                        $payment,
615
-                        $available_payment_amount
616
-                    );
617
-                }
618
-            }
619
-        }
620
-        if (
621
-            $available_payment_amount > 0
622
-            && apply_filters(
623
-                'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
624
-                false
625
-            )
626
-        ) {
627
-            EE_Error::add_attention(
628
-                sprintf(
629
-                    esc_html__(
630
-                        'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
631
-                        'event_espresso'
632
-                    ),
633
-                    EEH_Template::format_currency($available_payment_amount),
634
-                    implode(', ', array_keys($registrations)),
635
-                    '<br/>',
636
-                    EEH_Template::format_currency($payment->amount())
637
-                ),
638
-                __FILE__,
639
-                __FUNCTION__,
640
-                __LINE__
641
-            );
642
-        }
643
-    }
644
-
645
-
646
-    /**
647
-     * update registration REG_paid field after successful payment and link registration with payment
648
-     *
649
-     * @param EE_Registration  $registration
650
-     * @param EE_Payment       $payment
651
-     * @param float|int|string $available_payment_amount
652
-     * @return float
653
-     * @throws EE_Error
654
-     * @throws InvalidArgumentException
655
-     * @throws RuntimeException
656
-     * @throws InvalidDataTypeException
657
-     * @throws InvalidInterfaceException
658
-     * @throws ReflectionException
659
-     */
660
-    public function process_registration_payment(
661
-        EE_Registration $registration,
662
-        EE_Payment $payment,
663
-        $available_payment_amount = 0.00
664
-    ) {
665
-        // update $available_payment_amount
666
-        $available_payment_amount -= $registration->applyPayment($payment, $available_payment_amount);
667
-        return $available_payment_amount;
668
-    }
669
-
670
-
671
-    /**
672
-     * update registration REG_paid field after successful payment and link registration with payment
673
-     *
674
-     * @param EE_Registration $registration
675
-     * @param EE_Payment      $payment
676
-     * @param float           $payment_amount
677
-     * @return void
678
-     * @throws EE_Error
679
-     * @throws InvalidArgumentException
680
-     * @throws InvalidDataTypeException
681
-     * @throws InvalidInterfaceException
682
-     */
683
-    protected function _apply_registration_payment(
684
-        EE_Registration $registration,
685
-        EE_Payment $payment,
686
-        $payment_amount = 0.00
687
-    ) {
688
-        // find any existing reg payment records for this registration and payment
689
-        $existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
690
-            [['REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()]]
691
-        );
692
-        // if existing registration payment exists
693
-        if ($existing_reg_payment instanceof EE_Registration_Payment) {
694
-            // then update that record
695
-            $existing_reg_payment->set_amount($payment_amount);
696
-            $existing_reg_payment->save();
697
-        } else {
698
-            // or add new relation between registration and payment and set amount
699
-            $registration->_add_relation_to(
700
-                $payment,
701
-                'Payment',
702
-                ['RPY_amount' => $payment_amount]
703
-            );
704
-            // make it stick
705
-            $registration->save();
706
-        }
707
-    }
708
-
709
-
710
-    /**
711
-     * update registration REG_paid field after refund and link registration with payment
712
-     *
713
-     * @param EE_Registration $registration
714
-     * @param EE_Payment      $payment
715
-     * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
716
-     * @return float
717
-     * @throws EE_Error
718
-     * @throws InvalidArgumentException
719
-     * @throws RuntimeException
720
-     * @throws InvalidDataTypeException
721
-     * @throws InvalidInterfaceException
722
-     * @throws ReflectionException
723
-     */
724
-    public function process_registration_refund(
725
-        EE_Registration $registration,
726
-        EE_Payment $payment,
727
-        float $available_refund_amount = 0.00
728
-    ) {
729
-        // update $available_payment_amount
730
-        $available_refund_amount -= $registration->applyPayment($payment, $available_refund_amount);
731
-        return $available_refund_amount;
732
-    }
733
-
734
-
735
-    /**
736
-     * Process payments and transaction after payment process completed.
737
-     * ultimately this will send the TXN and payment details off so that notifications can be sent out.
738
-     * if this request happens to be processing an IPN,
739
-     * then we will also set the Payment Options Reg Step to completed,
740
-     * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
741
-     *
742
-     * @param EE_Transaction $transaction
743
-     * @param EE_Payment     $payment
744
-     * @param bool           $IPN
745
-     * @throws EE_Error
746
-     * @throws InvalidArgumentException
747
-     * @throws ReflectionException
748
-     * @throws RuntimeException
749
-     * @throws InvalidDataTypeException
750
-     * @throws InvalidInterfaceException
751
-     */
752
-    protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
753
-    {
754
-        /** @type EE_Transaction_Processor $transaction_processor */
755
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
756
-        // is the Payment Options Reg Step completed ?
757
-        $payment_options_step_completed = $transaction->reg_step_completed('payment_options');
758
-        // if the Payment Options Reg Step is completed...
759
-        $revisit = $payment_options_step_completed === true;
760
-        // then this is kinda sorta a revisit with regards to payments at least
761
-        $transaction_processor->set_revisit($revisit);
762
-        // if this is an IPN, let's consider the Payment Options Reg Step completed if not already
763
-        if (
764
-            $IPN
765
-            && $payment_options_step_completed !== true
766
-            && ($payment->is_approved() || $payment->is_pending())
767
-        ) {
768
-            $payment_options_step_completed = $transaction->set_reg_step_completed(
769
-                'payment_options'
770
-            );
771
-        }
772
-        // maybe update status, but don't save transaction just yet
773
-        $transaction->update_status_based_on_total_paid(false);
774
-        // check if 'finalize_registration' step has been completed...
775
-        $finalized = $transaction->reg_step_completed('finalize_registration');
776
-        //  if this is an IPN and the final step has not been initiated
777
-        if ($IPN && $payment_options_step_completed && $finalized === false) {
778
-            // and if it hasn't already been set as being started...
779
-            $finalized = $transaction->set_reg_step_initiated('finalize_registration');
780
-        }
781
-        $transaction->save();
782
-        // because the above will return false if the final step was not fully completed, we need to check again...
783
-        if ($IPN && $finalized !== false) {
784
-            // and if we are all good to go, then send out notifications
785
-            add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
786
-            // ok, now process the transaction according to the payment
787
-            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
788
-                $transaction,
789
-                $payment
790
-            );
791
-        }
792
-        // DEBUG LOG
793
-        $payment_method = $payment->payment_method();
794
-        if ($payment_method instanceof EE_Payment_Method) {
795
-            $payment_method_type_obj = $payment_method->type_obj();
796
-            if ($payment_method_type_obj instanceof EE_PMT_Base) {
797
-                $gateway = $payment_method_type_obj->get_gateway();
798
-                if ($gateway instanceof EE_Gateway) {
799
-                    $gateway->log(
800
-                        [
801
-                            'message'               => (string) esc_html__(
802
-                                'Post Payment Transaction Details',
803
-                                'event_espresso'
804
-                            ),
805
-                            'transaction'           => $transaction->model_field_array(),
806
-                            'finalized'             => $finalized,
807
-                            'IPN'                   => $IPN,
808
-                            'deliver_notifications' => has_filter(
809
-                                'FHEE__EED_Messages___maybe_registration__deliver_notifications'
810
-                            ),
811
-                        ],
812
-                        $payment
813
-                    );
814
-                }
815
-            }
816
-        }
817
-    }
818
-
819
-
820
-    /**
821
-     * Force posts to PayPal to use TLS v1.2. See:
822
-     * https://core.trac.wordpress.org/ticket/36320
823
-     * https://core.trac.wordpress.org/ticket/34924#comment:15
824
-     * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
825
-     * This will affect PayPal standard, pro, express, and Payflow.
826
-     *
827
-     * @param $handle
828
-     * @param $r
829
-     * @param $url
830
-     */
831
-    public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
832
-    {
833
-        if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
834
-            // Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
835
-            // instead of the constant because it might not be defined
836
-            curl_setopt($handle, CURLOPT_SSLVERSION, 6);
837
-        }
838
-    }
20
+	/**
21
+	 * @var EE_Payment_Processor $_instance
22
+	 * @access    private
23
+	 */
24
+	private static $_instance;
25
+
26
+
27
+	/**
28
+	 * @singleton method used to instantiate class object
29
+	 * @access    public
30
+	 * @return EE_Payment_Processor instance
31
+	 */
32
+	public static function instance()
33
+	{
34
+		// check if class object is instantiated
35
+		if (! self::$_instance instanceof EE_Payment_Processor) {
36
+			self::$_instance = new self();
37
+		}
38
+		return self::$_instance;
39
+	}
40
+
41
+
42
+	/**
43
+	 * @return EE_Payment_Processor
44
+	 */
45
+	public static function reset()
46
+	{
47
+		self::$_instance = null;
48
+		return self::instance();
49
+	}
50
+
51
+
52
+	/**
53
+	 *private constructor to prevent direct creation
54
+	 *
55
+	 * @Constructor
56
+	 * @access private
57
+	 */
58
+	private function __construct()
59
+	{
60
+		do_action('AHEE__EE_Payment_Processor__construct');
61
+		add_action('http_api_curl', [$this, '_curl_requests_to_paypal_use_tls'], 10, 3);
62
+	}
63
+
64
+
65
+	/**
66
+	 * Using the selected gateway, processes the payment for that transaction, and updates the transaction
67
+	 * appropriately. Saves the payment that is generated
68
+	 *
69
+	 * @param EE_Payment_Method         $payment_method
70
+	 * @param EE_Transaction            $transaction
71
+	 * @param float|null                $amount       if only part of the transaction is to be paid for, how much.
72
+	 *                                                Leave null if payment is for the full amount owing
73
+	 * @param EE_Billing_Info_Form|null $billing_form (or probably null, if it's an offline or offsite payment method).
74
+	 *                                                Receive_form_submission() should have
75
+	 *                                                already been called on the billing form
76
+	 *                                                (ie, its inputs should have their normalized values set).
77
+	 * @param string|null               $return_url   string used mostly by offsite gateways to specify
78
+	 *                                                where to go AFTER the offsite gateway
79
+	 * @param string                    $method       like 'CART', indicates who the client who called this was
80
+	 * @param bool                      $by_admin     TRUE if payment is being attempted from the admin
81
+	 * @param bool                      $update_txn   whether or not to call
82
+	 *                                                EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
83
+	 * @param string                    $cancel_url   URL to return to if off-site payments are cancelled
84
+	 * @return EE_Payment
85
+	 * @throws EE_Error
86
+	 * @throws InvalidArgumentException
87
+	 * @throws ReflectionException
88
+	 * @throws RuntimeException
89
+	 * @throws InvalidDataTypeException
90
+	 * @throws InvalidInterfaceException
91
+	 */
92
+	public function process_payment(
93
+		EE_Payment_Method $payment_method,
94
+		EE_Transaction $transaction,
95
+		?float $amount = null,
96
+		?EE_Billing_Info_Form $billing_form = null,
97
+		?string $return_url = null,
98
+		string $method = 'CART',
99
+		bool $by_admin = false,
100
+		bool $update_txn = true,
101
+		string $cancel_url = ''
102
+	): ?EE_Payment {
103
+		if ((float) $amount < 0) {
104
+			throw new EE_Error(
105
+				sprintf(
106
+					esc_html__(
107
+						'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
108
+						'event_espresso'
109
+					),
110
+					$amount,
111
+					$transaction->ID()
112
+				)
113
+			);
114
+		}
115
+		// verify payment method
116
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
117
+			$payment_method,
118
+			true
119
+		);
120
+		// verify transaction
121
+		EEM_Transaction::instance()->ensure_is_obj($transaction);
122
+		$transaction->set_payment_method_ID($payment_method->ID());
123
+		// verify payment method type
124
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
125
+			$payment = $payment_method->type_obj()->process_payment(
126
+				$transaction,
127
+				min($amount, $transaction->remaining()), // make sure we don't overcharge
128
+				$billing_form,
129
+				$return_url,
130
+				add_query_arg(['ee_cancel_payment' => true], $cancel_url),
131
+				$method,
132
+				$by_admin
133
+			);
134
+			// check if payment method uses an off-site gateway
135
+			if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
136
+				// don't process payments for off-site gateways yet because no payment has occurred yet
137
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
138
+			}
139
+			return $payment;
140
+		}
141
+		EE_Error::add_error(
142
+			sprintf(
143
+				esc_html__(
144
+					'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
145
+					'event_espresso'
146
+				),
147
+				'<br/>',
148
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
149
+			),
150
+			__FILE__,
151
+			__FUNCTION__,
152
+			__LINE__
153
+		);
154
+		return null;
155
+	}
156
+
157
+
158
+	/**
159
+	 * @param EE_Transaction|int $transaction
160
+	 * @param EE_Payment_Method  $payment_method
161
+	 * @return string
162
+	 * @throws EE_Error
163
+	 * @throws InvalidArgumentException
164
+	 * @throws InvalidDataTypeException
165
+	 * @throws InvalidInterfaceException
166
+	 */
167
+	public function get_ipn_url_for_payment_method($transaction, $payment_method)
168
+	{
169
+		/** @type \EE_Transaction $transaction */
170
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
171
+		$primary_reg = $transaction->primary_registration();
172
+		if (! $primary_reg instanceof EE_Registration) {
173
+			throw new EE_Error(
174
+				sprintf(
175
+					esc_html__(
176
+						'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
177
+						'event_espresso'
178
+					),
179
+					$transaction->ID()
180
+				)
181
+			);
182
+		}
183
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
184
+			$payment_method,
185
+			true
186
+		);
187
+		$url            = add_query_arg(
188
+			[
189
+				'e_reg_url_link'    => $primary_reg->reg_url_link(),
190
+				'ee_payment_method' => $payment_method->slug(),
191
+			],
192
+			EE_Registry::instance()->CFG->core->txn_page_url()
193
+		);
194
+		return $url;
195
+	}
196
+
197
+
198
+	/**
199
+	 * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
200
+	 * we can easily find what registration the IPN is for and what payment method.
201
+	 * However, if not, we'll give all payment methods a chance to claim it and process it.
202
+	 * If a payment is found for the IPN info, it is saved.
203
+	 *
204
+	 * @param array              $_req_data            form post data
205
+	 * @param EE_Transaction|int $transaction          optional (or a transactions id)
206
+	 * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
207
+	 * @param boolean            $update_txn           whether or not to call
208
+	 *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
209
+	 * @param bool               $separate_IPN_request whether the IPN uses a separate request (true, like PayPal)
210
+	 *                                                 or is processed manually (false, like Authorize.net)
211
+	 * @return EE_Payment
212
+	 * @throws EE_Error
213
+	 * @throws Exception
214
+	 * @throws \RuntimeException
215
+	 * @throws \ReflectionException
216
+	 * @throws \InvalidArgumentException
217
+	 * @throws InvalidInterfaceException
218
+	 * @throws InvalidDataTypeException
219
+	 */
220
+	public function process_ipn(
221
+		$_req_data,
222
+		$transaction = null,
223
+		$payment_method = null,
224
+		$update_txn = true,
225
+		$separate_IPN_request = true
226
+	) {
227
+		EE_Registry::instance()->load_model('Change_Log');
228
+		$_req_data = $this->_remove_unusable_characters_from_array((array) $_req_data);
229
+		EE_Processor_Base::set_IPN($separate_IPN_request);
230
+		$obj_for_log = null;
231
+		if ($transaction instanceof EE_Transaction) {
232
+			$obj_for_log = $transaction;
233
+			if ($payment_method instanceof EE_Payment_Method) {
234
+				$obj_for_log = EEM_Payment::instance()->get_one(
235
+					[
236
+						['TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()],
237
+						'order_by' => ['PAY_timestamp' => 'desc'],
238
+					]
239
+				);
240
+			}
241
+		} elseif ($payment_method instanceof EE_Payment) {
242
+			$obj_for_log = $payment_method;
243
+		}
244
+		$log = EEM_Change_Log::instance()->log(
245
+			EEM_Change_Log::type_gateway,
246
+			['IPN data received' => $_req_data],
247
+			$obj_for_log
248
+		);
249
+		try {
250
+			/**
251
+			 * @var EE_Payment $payment
252
+			 */
253
+			$payment = null;
254
+			if ($transaction && $payment_method) {
255
+				/** @type EE_Transaction $transaction */
256
+				$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
257
+				/** @type EE_Payment_Method $payment_method */
258
+				$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
259
+				if ($payment_method->type_obj() instanceof EE_PMT_Base) {
260
+					try {
261
+						$payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
262
+						$log->set_object($payment);
263
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
264
+						EEM_Change_Log::instance()->log(
265
+							EEM_Change_Log::type_gateway,
266
+							[
267
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
268
+								'current_url' => EEH_URL::current_url(),
269
+								'payment'     => $e->getPaymentProperties(),
270
+								'IPN_data'    => $e->getIpnData(),
271
+							],
272
+							$obj_for_log
273
+						);
274
+						return $e->getPayment();
275
+					}
276
+				} else {
277
+					// not a payment
278
+					EE_Error::add_error(
279
+						sprintf(
280
+							esc_html__(
281
+								'A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.',
282
+								'event_espresso'
283
+							),
284
+							'<br/>',
285
+							EE_Registry::instance()->CFG->organization->get_pretty('email')
286
+						),
287
+						__FILE__,
288
+						__FUNCTION__,
289
+						__LINE__
290
+					);
291
+				}
292
+			} else {
293
+				// that's actually pretty ok. The IPN just wasn't able
294
+				// to identify which transaction or payment method this was for
295
+				// give all active payment methods a chance to claim it
296
+				$active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
297
+				foreach ($active_payment_methods as $active_payment_method) {
298
+					try {
299
+						$payment        = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
300
+						$payment_method = $active_payment_method;
301
+						EEM_Change_Log::instance()->log(
302
+							EEM_Change_Log::type_gateway,
303
+							['IPN data' => $_req_data],
304
+							$payment
305
+						);
306
+						break;
307
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
308
+						EEM_Change_Log::instance()->log(
309
+							EEM_Change_Log::type_gateway,
310
+							[
311
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
312
+								'current_url' => EEH_URL::current_url(),
313
+								'payment'     => $e->getPaymentProperties(),
314
+								'IPN_data'    => $e->getIpnData(),
315
+							],
316
+							$obj_for_log
317
+						);
318
+						return $e->getPayment();
319
+					} catch (EE_Error $e) {
320
+						// that's fine- it apparently couldn't handle the IPN
321
+					}
322
+				}
323
+			}
324
+			// EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
325
+			if ($payment instanceof EE_Payment) {
326
+				$payment->save();
327
+				//  update the TXN
328
+				$this->update_txn_based_on_payment(
329
+					$transaction,
330
+					$payment,
331
+					$update_txn,
332
+					$separate_IPN_request
333
+				);
334
+			} else {
335
+				// we couldn't find the payment for this IPN... let's try and log at least SOMETHING
336
+				if ($payment_method) {
337
+					EEM_Change_Log::instance()->log(
338
+						EEM_Change_Log::type_gateway,
339
+						['IPN data' => $_req_data],
340
+						$payment_method
341
+					);
342
+				} elseif ($transaction) {
343
+					EEM_Change_Log::instance()->log(
344
+						EEM_Change_Log::type_gateway,
345
+						['IPN data' => $_req_data],
346
+						$transaction
347
+					);
348
+				}
349
+			}
350
+			return $payment;
351
+		} catch (EE_Error $e) {
352
+			do_action(
353
+				'AHEE__log',
354
+				__FILE__,
355
+				__FUNCTION__,
356
+				sprintf(
357
+					esc_html__(
358
+						'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
359
+						'event_espresso'
360
+					),
361
+					print_r($transaction, true),
362
+					print_r($_req_data, true),
363
+					$e->getMessage()
364
+				)
365
+			);
366
+			throw $e;
367
+		}
368
+	}
369
+
370
+
371
+	/**
372
+	 * Removes any non-printable illegal characters from the input,
373
+	 * which might cause a raucous when trying to insert into the database
374
+	 *
375
+	 * @param array $request_data
376
+	 * @return array
377
+	 */
378
+	protected function _remove_unusable_characters_from_array(array $request_data)
379
+	{
380
+		$return_data = [];
381
+		foreach ($request_data as $key => $value) {
382
+			$return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
383
+				$value
384
+			);
385
+		}
386
+		return $return_data;
387
+	}
388
+
389
+
390
+	/**
391
+	 * Removes any non-printable illegal characters from the input,
392
+	 * which might cause a raucous when trying to insert into the database
393
+	 *
394
+	 * @param string $request_data
395
+	 * @return string
396
+	 */
397
+	protected function _remove_unusable_characters($request_data)
398
+	{
399
+		return preg_replace('/[^[:print:]]/', '', $request_data);
400
+	}
401
+
402
+
403
+	/**
404
+	 * Should be called just before displaying the payment attempt results to the user,
405
+	 * when the payment attempt has finished. Some payment methods may have special
406
+	 * logic to perform here. For example, if process_payment() happens on a special request
407
+	 * and then the user is redirected to a page that displays the payment's status, this
408
+	 * should be called while loading the page that displays the payment's status. If the user is
409
+	 * sent to an offsite payment provider, this should be called upon returning from that offsite payment
410
+	 * provider.
411
+	 *
412
+	 * @param EE_Transaction|int $transaction
413
+	 * @param bool               $update_txn whether to call
414
+	 *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
415
+	 * @return EE_Payment
416
+	 * @throws EE_Error
417
+	 * @throws InvalidArgumentException
418
+	 * @throws ReflectionException
419
+	 * @throws RuntimeException
420
+	 * @throws InvalidDataTypeException
421
+	 * @throws InvalidInterfaceException
422
+	 * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
423
+	 *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
424
+	 */
425
+	public function finalize_payment_for(EE_Transaction $transaction, bool $update_txn = true): ?EE_Payment
426
+	{
427
+		$last_payment_method = $transaction->payment_method();
428
+		if ($last_payment_method instanceof EE_Payment_Method) {
429
+			$payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
430
+			$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
431
+			return $payment;
432
+		}
433
+		return null;
434
+	}
435
+
436
+
437
+	/**
438
+	 * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
439
+	 *
440
+	 * @param EE_Payment_Method|null $payment_method
441
+	 * @param EE_Payment             $payment_to_refund
442
+	 * @param array                  $refund_info
443
+	 * @return EE_Payment
444
+	 * @throws EE_Error
445
+	 * @throws ReflectionException
446
+	 */
447
+	public function process_refund(
448
+		?EE_Payment_Method $payment_method,
449
+		EE_Payment $payment_to_refund,
450
+		array $refund_info = []
451
+	) {
452
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
453
+			$payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
454
+			$this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
455
+		}
456
+		return $payment_to_refund;
457
+	}
458
+
459
+
460
+	/**
461
+	 * This should be called each time there may have been an update to a
462
+	 * payment on a transaction (ie, we asked for a payment to process a
463
+	 * payment for a transaction, or we told a payment method about an IPN, or
464
+	 * we told a payment method to
465
+	 * "finalize_payment_for" (a transaction), or we told a payment method to
466
+	 * process a refund. This should handle firing the correct hooks to
467
+	 * indicate
468
+	 * what exactly happened and updating the transaction appropriately). This
469
+	 * could be integrated directly into EE_Transaction upon save, but we want
470
+	 * this logic to be separate from 'normal' plain-jane saving and updating
471
+	 * of transactions and payments, and to be tied to payment processing.
472
+	 * Note: this method DOES NOT save the payment passed into it. It is the responsibility
473
+	 * of previous code to decide whether or not to save (because the payment passed into
474
+	 * this method might be a temporary, never-to-be-saved payment from an offline gateway,
475
+	 * in which case we only want that payment object for some temporary usage during this request,
476
+	 * but we don't want it to be saved).
477
+	 *
478
+	 * @param EE_Transaction|int $transaction
479
+	 * @param EE_Payment         $payment
480
+	 * @param boolean            $update_txn
481
+	 *                        whether or not to call
482
+	 *                        EE_Transaction_Processor::
483
+	 *                        update_transaction_and_registrations_after_checkout_or_payment()
484
+	 *                        (you can save 1 DB query if you know you're going
485
+	 *                        to save it later instead)
486
+	 * @param bool               $IPN
487
+	 *                        if processing IPNs or other similar payment
488
+	 *                        related activities that occur in alternate
489
+	 *                        requests than the main one that is processing the
490
+	 *                        TXN, then set this to true to check whether the
491
+	 *                        TXN is locked before updating
492
+	 * @throws EE_Error
493
+	 * @throws InvalidArgumentException
494
+	 * @throws ReflectionException
495
+	 * @throws RuntimeException
496
+	 * @throws InvalidDataTypeException
497
+	 * @throws InvalidInterfaceException
498
+	 */
499
+	public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
500
+	{
501
+		$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
502
+		/** @type EE_Transaction $transaction */
503
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
504
+		// can we freely update the TXN at this moment?
505
+		if ($IPN && $transaction->is_locked()) {
506
+			// don't update the transaction at this exact moment
507
+			// because the TXN is active in another request
508
+			EE_Cron_Tasks::schedule_update_transaction_with_payment(
509
+				time(),
510
+				$transaction->ID(),
511
+				$payment->ID()
512
+			);
513
+		} else {
514
+			// verify payment and that it has been saved
515
+			if ($payment instanceof EE_Payment && $payment->ID()) {
516
+				if (
517
+					$payment->payment_method() instanceof EE_Payment_Method
518
+					&& $payment->payment_method()->type_obj() instanceof EE_PMT_Base
519
+				) {
520
+					$payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
521
+					// update TXN registrations with payment info
522
+					$this->process_registration_payments($transaction, $payment);
523
+				}
524
+				$do_action = $payment->just_approved()
525
+					? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
526
+					: $do_action;
527
+			} else {
528
+				// send out notifications
529
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
530
+				$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
531
+			}
532
+			if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
533
+				/** @type EE_Transaction_Payments $transaction_payments */
534
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
535
+				// set new value for total paid
536
+				$transaction_payments->calculate_total_payments_and_update_status($transaction);
537
+				// call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
538
+				if ($update_txn) {
539
+					$this->_post_payment_processing($transaction, $payment, $IPN);
540
+				}
541
+			}
542
+			// granular hook for others to use.
543
+			do_action($do_action, $transaction, $payment);
544
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
545
+			// global hook for others to use.
546
+			do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
547
+		}
548
+	}
549
+
550
+
551
+	/**
552
+	 * update registrations REG_paid field after successful payment and link registrations with payment
553
+	 *
554
+	 * @param EE_Transaction    $transaction
555
+	 * @param EE_Payment        $payment
556
+	 * @param EE_Registration[] $registrations
557
+	 * @throws EE_Error
558
+	 * @throws InvalidArgumentException
559
+	 * @throws RuntimeException
560
+	 * @throws InvalidDataTypeException
561
+	 * @throws InvalidInterfaceException
562
+	 */
563
+	public function process_registration_payments(
564
+		EE_Transaction $transaction,
565
+		EE_Payment $payment,
566
+		array $registrations = []
567
+	) {
568
+		// only process if payment was successful
569
+		if ($payment->status() !== EEM_Payment::status_id_approved) {
570
+			return;
571
+		}
572
+		// EEM_Registration::instance()->show_next_x_db_queries();
573
+		if (empty($registrations)) {
574
+			// find registrations with monies owing that can receive a payment
575
+			$registrations = $transaction->registrations(
576
+				[
577
+					[
578
+						// only these reg statuses can receive payments
579
+						'STS_ID'           => ['IN', EEM_Registration::reg_statuses_that_allow_payment()],
580
+						'REG_final_price'  => ['!=', 0],
581
+						'REG_final_price*' => ['!=', 'REG_paid', true],
582
+					],
583
+				]
584
+			);
585
+		}
586
+		// still nothing ??!??
587
+		if (empty($registrations)) {
588
+			return;
589
+		}
590
+		// todo: break out the following logic into a separate strategy class
591
+		// todo: named something like "Sequential_Reg_Payment_Strategy"
592
+		// todo: which would apply payments using the capitalist "first come first paid" approach
593
+		// todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
594
+		// todo: which would be the socialist "everybody gets a piece of pie" approach,
595
+		// todo: which would be better for deposits, where you want a bit of the payment applied to each registration
596
+		$refund = $payment->is_a_refund();
597
+		// how much is available to apply to registrations?
598
+		$available_payment_amount = (float) abs($payment->amount());
599
+		foreach ($registrations as $registration) {
600
+			if ($registration instanceof EE_Registration) {
601
+				// nothing left?
602
+				if ($available_payment_amount <= 0) {
603
+					break;
604
+				}
605
+				if ($refund) {
606
+					$available_payment_amount = $this->process_registration_refund(
607
+						$registration,
608
+						$payment,
609
+						$available_payment_amount
610
+					);
611
+				} else {
612
+					$available_payment_amount = $this->process_registration_payment(
613
+						$registration,
614
+						$payment,
615
+						$available_payment_amount
616
+					);
617
+				}
618
+			}
619
+		}
620
+		if (
621
+			$available_payment_amount > 0
622
+			&& apply_filters(
623
+				'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
624
+				false
625
+			)
626
+		) {
627
+			EE_Error::add_attention(
628
+				sprintf(
629
+					esc_html__(
630
+						'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
631
+						'event_espresso'
632
+					),
633
+					EEH_Template::format_currency($available_payment_amount),
634
+					implode(', ', array_keys($registrations)),
635
+					'<br/>',
636
+					EEH_Template::format_currency($payment->amount())
637
+				),
638
+				__FILE__,
639
+				__FUNCTION__,
640
+				__LINE__
641
+			);
642
+		}
643
+	}
644
+
645
+
646
+	/**
647
+	 * update registration REG_paid field after successful payment and link registration with payment
648
+	 *
649
+	 * @param EE_Registration  $registration
650
+	 * @param EE_Payment       $payment
651
+	 * @param float|int|string $available_payment_amount
652
+	 * @return float
653
+	 * @throws EE_Error
654
+	 * @throws InvalidArgumentException
655
+	 * @throws RuntimeException
656
+	 * @throws InvalidDataTypeException
657
+	 * @throws InvalidInterfaceException
658
+	 * @throws ReflectionException
659
+	 */
660
+	public function process_registration_payment(
661
+		EE_Registration $registration,
662
+		EE_Payment $payment,
663
+		$available_payment_amount = 0.00
664
+	) {
665
+		// update $available_payment_amount
666
+		$available_payment_amount -= $registration->applyPayment($payment, $available_payment_amount);
667
+		return $available_payment_amount;
668
+	}
669
+
670
+
671
+	/**
672
+	 * update registration REG_paid field after successful payment and link registration with payment
673
+	 *
674
+	 * @param EE_Registration $registration
675
+	 * @param EE_Payment      $payment
676
+	 * @param float           $payment_amount
677
+	 * @return void
678
+	 * @throws EE_Error
679
+	 * @throws InvalidArgumentException
680
+	 * @throws InvalidDataTypeException
681
+	 * @throws InvalidInterfaceException
682
+	 */
683
+	protected function _apply_registration_payment(
684
+		EE_Registration $registration,
685
+		EE_Payment $payment,
686
+		$payment_amount = 0.00
687
+	) {
688
+		// find any existing reg payment records for this registration and payment
689
+		$existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
690
+			[['REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()]]
691
+		);
692
+		// if existing registration payment exists
693
+		if ($existing_reg_payment instanceof EE_Registration_Payment) {
694
+			// then update that record
695
+			$existing_reg_payment->set_amount($payment_amount);
696
+			$existing_reg_payment->save();
697
+		} else {
698
+			// or add new relation between registration and payment and set amount
699
+			$registration->_add_relation_to(
700
+				$payment,
701
+				'Payment',
702
+				['RPY_amount' => $payment_amount]
703
+			);
704
+			// make it stick
705
+			$registration->save();
706
+		}
707
+	}
708
+
709
+
710
+	/**
711
+	 * update registration REG_paid field after refund and link registration with payment
712
+	 *
713
+	 * @param EE_Registration $registration
714
+	 * @param EE_Payment      $payment
715
+	 * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
716
+	 * @return float
717
+	 * @throws EE_Error
718
+	 * @throws InvalidArgumentException
719
+	 * @throws RuntimeException
720
+	 * @throws InvalidDataTypeException
721
+	 * @throws InvalidInterfaceException
722
+	 * @throws ReflectionException
723
+	 */
724
+	public function process_registration_refund(
725
+		EE_Registration $registration,
726
+		EE_Payment $payment,
727
+		float $available_refund_amount = 0.00
728
+	) {
729
+		// update $available_payment_amount
730
+		$available_refund_amount -= $registration->applyPayment($payment, $available_refund_amount);
731
+		return $available_refund_amount;
732
+	}
733
+
734
+
735
+	/**
736
+	 * Process payments and transaction after payment process completed.
737
+	 * ultimately this will send the TXN and payment details off so that notifications can be sent out.
738
+	 * if this request happens to be processing an IPN,
739
+	 * then we will also set the Payment Options Reg Step to completed,
740
+	 * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
741
+	 *
742
+	 * @param EE_Transaction $transaction
743
+	 * @param EE_Payment     $payment
744
+	 * @param bool           $IPN
745
+	 * @throws EE_Error
746
+	 * @throws InvalidArgumentException
747
+	 * @throws ReflectionException
748
+	 * @throws RuntimeException
749
+	 * @throws InvalidDataTypeException
750
+	 * @throws InvalidInterfaceException
751
+	 */
752
+	protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
753
+	{
754
+		/** @type EE_Transaction_Processor $transaction_processor */
755
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
756
+		// is the Payment Options Reg Step completed ?
757
+		$payment_options_step_completed = $transaction->reg_step_completed('payment_options');
758
+		// if the Payment Options Reg Step is completed...
759
+		$revisit = $payment_options_step_completed === true;
760
+		// then this is kinda sorta a revisit with regards to payments at least
761
+		$transaction_processor->set_revisit($revisit);
762
+		// if this is an IPN, let's consider the Payment Options Reg Step completed if not already
763
+		if (
764
+			$IPN
765
+			&& $payment_options_step_completed !== true
766
+			&& ($payment->is_approved() || $payment->is_pending())
767
+		) {
768
+			$payment_options_step_completed = $transaction->set_reg_step_completed(
769
+				'payment_options'
770
+			);
771
+		}
772
+		// maybe update status, but don't save transaction just yet
773
+		$transaction->update_status_based_on_total_paid(false);
774
+		// check if 'finalize_registration' step has been completed...
775
+		$finalized = $transaction->reg_step_completed('finalize_registration');
776
+		//  if this is an IPN and the final step has not been initiated
777
+		if ($IPN && $payment_options_step_completed && $finalized === false) {
778
+			// and if it hasn't already been set as being started...
779
+			$finalized = $transaction->set_reg_step_initiated('finalize_registration');
780
+		}
781
+		$transaction->save();
782
+		// because the above will return false if the final step was not fully completed, we need to check again...
783
+		if ($IPN && $finalized !== false) {
784
+			// and if we are all good to go, then send out notifications
785
+			add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
786
+			// ok, now process the transaction according to the payment
787
+			$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
788
+				$transaction,
789
+				$payment
790
+			);
791
+		}
792
+		// DEBUG LOG
793
+		$payment_method = $payment->payment_method();
794
+		if ($payment_method instanceof EE_Payment_Method) {
795
+			$payment_method_type_obj = $payment_method->type_obj();
796
+			if ($payment_method_type_obj instanceof EE_PMT_Base) {
797
+				$gateway = $payment_method_type_obj->get_gateway();
798
+				if ($gateway instanceof EE_Gateway) {
799
+					$gateway->log(
800
+						[
801
+							'message'               => (string) esc_html__(
802
+								'Post Payment Transaction Details',
803
+								'event_espresso'
804
+							),
805
+							'transaction'           => $transaction->model_field_array(),
806
+							'finalized'             => $finalized,
807
+							'IPN'                   => $IPN,
808
+							'deliver_notifications' => has_filter(
809
+								'FHEE__EED_Messages___maybe_registration__deliver_notifications'
810
+							),
811
+						],
812
+						$payment
813
+					);
814
+				}
815
+			}
816
+		}
817
+	}
818
+
819
+
820
+	/**
821
+	 * Force posts to PayPal to use TLS v1.2. See:
822
+	 * https://core.trac.wordpress.org/ticket/36320
823
+	 * https://core.trac.wordpress.org/ticket/34924#comment:15
824
+	 * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
825
+	 * This will affect PayPal standard, pro, express, and Payflow.
826
+	 *
827
+	 * @param $handle
828
+	 * @param $r
829
+	 * @param $url
830
+	 */
831
+	public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
832
+	{
833
+		if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
834
+			// Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
835
+			// instead of the constant because it might not be defined
836
+			curl_setopt($handle, CURLOPT_SSLVERSION, 6);
837
+		}
838
+	}
839 839
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     public static function instance()
33 33
     {
34 34
         // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Payment_Processor) {
35
+        if ( ! self::$_instance instanceof EE_Payment_Processor) {
36 36
             self::$_instance = new self();
37 37
         }
38 38
         return self::$_instance;
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
         /** @type \EE_Transaction $transaction */
170 170
         $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
171 171
         $primary_reg = $transaction->primary_registration();
172
-        if (! $primary_reg instanceof EE_Registration) {
172
+        if ( ! $primary_reg instanceof EE_Registration) {
173 173
             throw new EE_Error(
174 174
                 sprintf(
175 175
                     esc_html__(
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
             $payment_method,
185 185
             true
186 186
         );
187
-        $url            = add_query_arg(
187
+        $url = add_query_arg(
188 188
             [
189 189
                 'e_reg_url_link'    => $primary_reg->reg_url_link(),
190 190
                 'ee_payment_method' => $payment_method->slug(),
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
                         EEM_Change_Log::instance()->log(
265 265
                             EEM_Change_Log::type_gateway,
266 266
                             [
267
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
267
+                                'message'     => 'IPN Exception: '.$e->getMessage(),
268 268
                                 'current_url' => EEH_URL::current_url(),
269 269
                                 'payment'     => $e->getPaymentProperties(),
270 270
                                 'IPN_data'    => $e->getIpnData(),
@@ -308,7 +308,7 @@  discard block
 block discarded – undo
308 308
                         EEM_Change_Log::instance()->log(
309 309
                             EEM_Change_Log::type_gateway,
310 310
                             [
311
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
311
+                                'message'     => 'IPN Exception: '.$e->getMessage(),
312 312
                                 'current_url' => EEH_URL::current_url(),
313 313
                                 'payment'     => $e->getPaymentProperties(),
314 314
                                 'IPN_data'    => $e->getIpnData(),
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
     {
380 380
         $return_data = [];
381 381
         foreach ($request_data as $key => $value) {
382
-            $return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
382
+            $return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters(
383 383
                 $value
384 384
             );
385 385
         }
Please login to merge, or discard this patch.
vendor/webonyx/graphql-php/src/Error/Error.php 1 patch
Indentation   +344 added lines, -344 removed lines patch added patch discarded remove patch
@@ -35,348 +35,348 @@
 block discarded – undo
35 35
  */
36 36
 class Error extends Exception implements JsonSerializable, ClientAware
37 37
 {
38
-    const CATEGORY_GRAPHQL  = 'graphql';
39
-    const CATEGORY_INTERNAL = 'internal';
40
-
41
-    /**
42
-     * Lazily initialized.
43
-     *
44
-     * @var SourceLocation[]
45
-     */
46
-    private $locations;
47
-
48
-    /**
49
-     * An array describing the JSON-path into the execution response which
50
-     * corresponds to this error. Only included for errors during execution.
51
-     *
52
-     * @var mixed[]|null
53
-     */
54
-    public $path;
55
-
56
-    /**
57
-     * An array of GraphQL AST Nodes corresponding to this error.
58
-     *
59
-     * @var Node[]|null
60
-     */
61
-    public $nodes;
62
-
63
-    /**
64
-     * The source GraphQL document for the first location of this error.
65
-     *
66
-     * Note that if this Error represents more than one node, the source may not
67
-     * represent nodes after the first node.
68
-     *
69
-     * @var Source|null
70
-     */
71
-    private $source;
72
-
73
-    /** @var int[] */
74
-    private $positions;
75
-
76
-    /** @var bool */
77
-    private $isClientSafe;
78
-
79
-    /** @var string */
80
-    protected $category;
81
-
82
-    /** @var mixed[]|null */
83
-    protected $extensions;
84
-
85
-    /**
86
-     * @param string                       $message
87
-     * @param Node|Node[]|Traversable|null $nodes
88
-     * @param mixed[]                      $positions
89
-     * @param mixed[]|null                 $path
90
-     * @param Throwable                    $previous
91
-     * @param mixed[]                      $extensions
92
-     */
93
-    public function __construct(
94
-        $message = '',
95
-        $nodes = null,
96
-        ?Source $source = null,
97
-        array $positions = [],
98
-        $path = null,
99
-        $previous = null,
100
-        array $extensions = []
101
-    ) {
102
-        parent::__construct($message, 0, $previous);
103
-
104
-        // Compute list of blame nodes.
105
-        if ($nodes instanceof Traversable) {
106
-            $nodes = iterator_to_array($nodes);
107
-        } elseif ($nodes !== null && ! is_array($nodes)) {
108
-            $nodes = [$nodes];
109
-        }
110
-
111
-        $this->nodes      = $nodes;
112
-        $this->source     = $source;
113
-        $this->positions  = $positions;
114
-        $this->path       = $path;
115
-        $this->extensions = count($extensions) > 0 ? $extensions : (
116
-        $previous instanceof self
117
-            ? $previous->extensions
118
-            : []
119
-        );
120
-
121
-        if ($previous instanceof ClientAware) {
122
-            $this->isClientSafe = $previous->isClientSafe();
123
-            $cat                = $previous->getCategory();
124
-            $this->category     = $cat === '' || $cat === null  ? self::CATEGORY_INTERNAL: $cat;
125
-        } elseif ($previous !== null) {
126
-            $this->isClientSafe = false;
127
-            $this->category     = self::CATEGORY_INTERNAL;
128
-        } else {
129
-            $this->isClientSafe = true;
130
-            $this->category     = self::CATEGORY_GRAPHQL;
131
-        }
132
-    }
133
-
134
-    /**
135
-     * Given an arbitrary Error, presumably thrown while attempting to execute a
136
-     * GraphQL operation, produce a new GraphQLError aware of the location in the
137
-     * document responsible for the original Error.
138
-     *
139
-     * @param mixed        $error
140
-     * @param Node[]|null  $nodes
141
-     * @param mixed[]|null $path
142
-     *
143
-     * @return Error
144
-     */
145
-    public static function createLocatedError($error, $nodes = null, $path = null)
146
-    {
147
-        if ($error instanceof self) {
148
-            if ($error->path !== null && $error->nodes !== null && count($error->nodes) !== 0) {
149
-                return $error;
150
-            }
151
-
152
-            $nodes = $nodes ?? $error->nodes;
153
-            $path  = $path ?? $error->path;
154
-        }
155
-
156
-        $source        = null;
157
-        $originalError = null;
158
-        $positions     = [];
159
-        $extensions    = [];
160
-
161
-        if ($error instanceof self) {
162
-            $message       = $error->getMessage();
163
-            $originalError = $error;
164
-            $nodes         = $error->nodes ?? $nodes;
165
-            $source        = $error->source;
166
-            $positions     = $error->positions;
167
-            $extensions    = $error->extensions;
168
-        } elseif ($error instanceof Throwable) {
169
-            $message       = $error->getMessage();
170
-            $originalError = $error;
171
-        } else {
172
-            $message = (string) $error;
173
-        }
174
-
175
-        return new static(
176
-            $message === '' || $message === null ? 'An unknown error occurred.' : $message,
177
-            $nodes,
178
-            $source,
179
-            $positions,
180
-            $path,
181
-            $originalError,
182
-            $extensions
183
-        );
184
-    }
185
-
186
-    /**
187
-     * @return mixed[]
188
-     */
189
-    public static function formatError(Error $error)
190
-    {
191
-        return $error->toSerializableArray();
192
-    }
193
-
194
-    /**
195
-     * @inheritdoc
196
-     */
197
-    public function isClientSafe()
198
-    {
199
-        return $this->isClientSafe;
200
-    }
201
-
202
-    /**
203
-     * @inheritdoc
204
-     */
205
-    public function getCategory()
206
-    {
207
-        return $this->category;
208
-    }
209
-
210
-    public function getSource() : ?Source
211
-    {
212
-        if ($this->source === null) {
213
-            if (isset($this->nodes[0]) && $this->nodes[0]->loc !== null) {
214
-                $this->source = $this->nodes[0]->loc->source;
215
-            }
216
-        }
217
-
218
-        return $this->source;
219
-    }
220
-
221
-    /**
222
-     * @return int[]
223
-     */
224
-    public function getPositions() : array
225
-    {
226
-        if (count($this->positions) === 0 && count($this->nodes ?? []) > 0) {
227
-            $positions = array_map(
228
-                static function ($node) : ?int {
229
-                    return isset($node->loc) ? $node->loc->start : null;
230
-                },
231
-                $this->nodes
232
-            );
233
-
234
-            $positions = array_filter(
235
-                $positions,
236
-                static function ($p) : bool {
237
-                    return $p !== null;
238
-                }
239
-            );
240
-
241
-            $this->positions = array_values($positions);
242
-        }
243
-
244
-        return $this->positions;
245
-    }
246
-
247
-    /**
248
-     * An array of locations within the source GraphQL document which correspond to this error.
249
-     *
250
-     * Each entry has information about `line` and `column` within source GraphQL document:
251
-     * $location->line;
252
-     * $location->column;
253
-     *
254
-     * Errors during validation often contain multiple locations, for example to
255
-     * point out to field mentioned in multiple fragments. Errors during execution include a
256
-     * single location, the field which produced the error.
257
-     *
258
-     * @return SourceLocation[]
259
-     *
260
-     * @api
261
-     */
262
-    public function getLocations() : array
263
-    {
264
-        if (! isset($this->locations)) {
265
-            $positions = $this->getPositions();
266
-            $source    = $this->getSource();
267
-            $nodes     = $this->nodes;
268
-
269
-            if ($source !== null && count($positions) !== 0) {
270
-                $this->locations = array_map(
271
-                    static function ($pos) use ($source) : SourceLocation {
272
-                        return $source->getLocation($pos);
273
-                    },
274
-                    $positions
275
-                );
276
-            } elseif ($nodes !== null && count($nodes) !== 0) {
277
-                $locations       = array_filter(
278
-                    array_map(
279
-                        static function ($node) : ?SourceLocation {
280
-                            if (isset($node->loc->source)) {
281
-                                return $node->loc->source->getLocation($node->loc->start);
282
-                            }
283
-
284
-                            return null;
285
-                        },
286
-                        $nodes
287
-                    )
288
-                );
289
-                $this->locations = array_values($locations);
290
-            } else {
291
-                $this->locations = [];
292
-            }
293
-        }
294
-
295
-        return $this->locations;
296
-    }
297
-
298
-    /**
299
-     * @return Node[]|null
300
-     */
301
-    public function getNodes()
302
-    {
303
-        return $this->nodes;
304
-    }
305
-
306
-    /**
307
-     * Returns an array describing the path from the root value to the field which produced this error.
308
-     * Only included for execution errors.
309
-     *
310
-     * @return mixed[]|null
311
-     *
312
-     * @api
313
-     */
314
-    public function getPath()
315
-    {
316
-        return $this->path;
317
-    }
318
-
319
-    /**
320
-     * @return mixed[]
321
-     */
322
-    public function getExtensions()
323
-    {
324
-        return $this->extensions;
325
-    }
326
-
327
-    /**
328
-     * Returns array representation of error suitable for serialization
329
-     *
330
-     * @deprecated Use FormattedError::createFromException() instead
331
-     *
332
-     * @return mixed[]
333
-     *
334
-     * @codeCoverageIgnore
335
-     */
336
-    public function toSerializableArray()
337
-    {
338
-        $arr = [
339
-            'message' => $this->getMessage(),
340
-        ];
341
-
342
-        $locations = Utils::map(
343
-            $this->getLocations(),
344
-            static function (SourceLocation $loc) : array {
345
-                return $loc->toSerializableArray();
346
-            }
347
-        );
348
-
349
-        if (count($locations) > 0) {
350
-            $arr['locations'] = $locations;
351
-        }
352
-        if (count($this->path ?? []) > 0) {
353
-            $arr['path'] = $this->path;
354
-        }
355
-        if (count($this->extensions ?? []) > 0) {
356
-            $arr['extensions'] = $this->extensions;
357
-        }
358
-
359
-        return $arr;
360
-    }
361
-
362
-    /**
363
-     * Specify data which should be serialized to JSON
364
-     *
365
-     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
366
-     *
367
-     * @return mixed data which can be serialized by <b>json_encode</b>,
368
-     * which is a value of any type other than a resource.
369
-     */
370
-    public function jsonSerialize(): mixed
371
-    {
372
-        return $this->toSerializableArray();
373
-    }
374
-
375
-    /**
376
-     * @return string
377
-     */
378
-    public function __toString()
379
-    {
380
-        return FormattedError::printError($this);
381
-    }
38
+	const CATEGORY_GRAPHQL  = 'graphql';
39
+	const CATEGORY_INTERNAL = 'internal';
40
+
41
+	/**
42
+	 * Lazily initialized.
43
+	 *
44
+	 * @var SourceLocation[]
45
+	 */
46
+	private $locations;
47
+
48
+	/**
49
+	 * An array describing the JSON-path into the execution response which
50
+	 * corresponds to this error. Only included for errors during execution.
51
+	 *
52
+	 * @var mixed[]|null
53
+	 */
54
+	public $path;
55
+
56
+	/**
57
+	 * An array of GraphQL AST Nodes corresponding to this error.
58
+	 *
59
+	 * @var Node[]|null
60
+	 */
61
+	public $nodes;
62
+
63
+	/**
64
+	 * The source GraphQL document for the first location of this error.
65
+	 *
66
+	 * Note that if this Error represents more than one node, the source may not
67
+	 * represent nodes after the first node.
68
+	 *
69
+	 * @var Source|null
70
+	 */
71
+	private $source;
72
+
73
+	/** @var int[] */
74
+	private $positions;
75
+
76
+	/** @var bool */
77
+	private $isClientSafe;
78
+
79
+	/** @var string */
80
+	protected $category;
81
+
82
+	/** @var mixed[]|null */
83
+	protected $extensions;
84
+
85
+	/**
86
+	 * @param string                       $message
87
+	 * @param Node|Node[]|Traversable|null $nodes
88
+	 * @param mixed[]                      $positions
89
+	 * @param mixed[]|null                 $path
90
+	 * @param Throwable                    $previous
91
+	 * @param mixed[]                      $extensions
92
+	 */
93
+	public function __construct(
94
+		$message = '',
95
+		$nodes = null,
96
+		?Source $source = null,
97
+		array $positions = [],
98
+		$path = null,
99
+		$previous = null,
100
+		array $extensions = []
101
+	) {
102
+		parent::__construct($message, 0, $previous);
103
+
104
+		// Compute list of blame nodes.
105
+		if ($nodes instanceof Traversable) {
106
+			$nodes = iterator_to_array($nodes);
107
+		} elseif ($nodes !== null && ! is_array($nodes)) {
108
+			$nodes = [$nodes];
109
+		}
110
+
111
+		$this->nodes      = $nodes;
112
+		$this->source     = $source;
113
+		$this->positions  = $positions;
114
+		$this->path       = $path;
115
+		$this->extensions = count($extensions) > 0 ? $extensions : (
116
+		$previous instanceof self
117
+			? $previous->extensions
118
+			: []
119
+		);
120
+
121
+		if ($previous instanceof ClientAware) {
122
+			$this->isClientSafe = $previous->isClientSafe();
123
+			$cat                = $previous->getCategory();
124
+			$this->category     = $cat === '' || $cat === null  ? self::CATEGORY_INTERNAL: $cat;
125
+		} elseif ($previous !== null) {
126
+			$this->isClientSafe = false;
127
+			$this->category     = self::CATEGORY_INTERNAL;
128
+		} else {
129
+			$this->isClientSafe = true;
130
+			$this->category     = self::CATEGORY_GRAPHQL;
131
+		}
132
+	}
133
+
134
+	/**
135
+	 * Given an arbitrary Error, presumably thrown while attempting to execute a
136
+	 * GraphQL operation, produce a new GraphQLError aware of the location in the
137
+	 * document responsible for the original Error.
138
+	 *
139
+	 * @param mixed        $error
140
+	 * @param Node[]|null  $nodes
141
+	 * @param mixed[]|null $path
142
+	 *
143
+	 * @return Error
144
+	 */
145
+	public static function createLocatedError($error, $nodes = null, $path = null)
146
+	{
147
+		if ($error instanceof self) {
148
+			if ($error->path !== null && $error->nodes !== null && count($error->nodes) !== 0) {
149
+				return $error;
150
+			}
151
+
152
+			$nodes = $nodes ?? $error->nodes;
153
+			$path  = $path ?? $error->path;
154
+		}
155
+
156
+		$source        = null;
157
+		$originalError = null;
158
+		$positions     = [];
159
+		$extensions    = [];
160
+
161
+		if ($error instanceof self) {
162
+			$message       = $error->getMessage();
163
+			$originalError = $error;
164
+			$nodes         = $error->nodes ?? $nodes;
165
+			$source        = $error->source;
166
+			$positions     = $error->positions;
167
+			$extensions    = $error->extensions;
168
+		} elseif ($error instanceof Throwable) {
169
+			$message       = $error->getMessage();
170
+			$originalError = $error;
171
+		} else {
172
+			$message = (string) $error;
173
+		}
174
+
175
+		return new static(
176
+			$message === '' || $message === null ? 'An unknown error occurred.' : $message,
177
+			$nodes,
178
+			$source,
179
+			$positions,
180
+			$path,
181
+			$originalError,
182
+			$extensions
183
+		);
184
+	}
185
+
186
+	/**
187
+	 * @return mixed[]
188
+	 */
189
+	public static function formatError(Error $error)
190
+	{
191
+		return $error->toSerializableArray();
192
+	}
193
+
194
+	/**
195
+	 * @inheritdoc
196
+	 */
197
+	public function isClientSafe()
198
+	{
199
+		return $this->isClientSafe;
200
+	}
201
+
202
+	/**
203
+	 * @inheritdoc
204
+	 */
205
+	public function getCategory()
206
+	{
207
+		return $this->category;
208
+	}
209
+
210
+	public function getSource() : ?Source
211
+	{
212
+		if ($this->source === null) {
213
+			if (isset($this->nodes[0]) && $this->nodes[0]->loc !== null) {
214
+				$this->source = $this->nodes[0]->loc->source;
215
+			}
216
+		}
217
+
218
+		return $this->source;
219
+	}
220
+
221
+	/**
222
+	 * @return int[]
223
+	 */
224
+	public function getPositions() : array
225
+	{
226
+		if (count($this->positions) === 0 && count($this->nodes ?? []) > 0) {
227
+			$positions = array_map(
228
+				static function ($node) : ?int {
229
+					return isset($node->loc) ? $node->loc->start : null;
230
+				},
231
+				$this->nodes
232
+			);
233
+
234
+			$positions = array_filter(
235
+				$positions,
236
+				static function ($p) : bool {
237
+					return $p !== null;
238
+				}
239
+			);
240
+
241
+			$this->positions = array_values($positions);
242
+		}
243
+
244
+		return $this->positions;
245
+	}
246
+
247
+	/**
248
+	 * An array of locations within the source GraphQL document which correspond to this error.
249
+	 *
250
+	 * Each entry has information about `line` and `column` within source GraphQL document:
251
+	 * $location->line;
252
+	 * $location->column;
253
+	 *
254
+	 * Errors during validation often contain multiple locations, for example to
255
+	 * point out to field mentioned in multiple fragments. Errors during execution include a
256
+	 * single location, the field which produced the error.
257
+	 *
258
+	 * @return SourceLocation[]
259
+	 *
260
+	 * @api
261
+	 */
262
+	public function getLocations() : array
263
+	{
264
+		if (! isset($this->locations)) {
265
+			$positions = $this->getPositions();
266
+			$source    = $this->getSource();
267
+			$nodes     = $this->nodes;
268
+
269
+			if ($source !== null && count($positions) !== 0) {
270
+				$this->locations = array_map(
271
+					static function ($pos) use ($source) : SourceLocation {
272
+						return $source->getLocation($pos);
273
+					},
274
+					$positions
275
+				);
276
+			} elseif ($nodes !== null && count($nodes) !== 0) {
277
+				$locations       = array_filter(
278
+					array_map(
279
+						static function ($node) : ?SourceLocation {
280
+							if (isset($node->loc->source)) {
281
+								return $node->loc->source->getLocation($node->loc->start);
282
+							}
283
+
284
+							return null;
285
+						},
286
+						$nodes
287
+					)
288
+				);
289
+				$this->locations = array_values($locations);
290
+			} else {
291
+				$this->locations = [];
292
+			}
293
+		}
294
+
295
+		return $this->locations;
296
+	}
297
+
298
+	/**
299
+	 * @return Node[]|null
300
+	 */
301
+	public function getNodes()
302
+	{
303
+		return $this->nodes;
304
+	}
305
+
306
+	/**
307
+	 * Returns an array describing the path from the root value to the field which produced this error.
308
+	 * Only included for execution errors.
309
+	 *
310
+	 * @return mixed[]|null
311
+	 *
312
+	 * @api
313
+	 */
314
+	public function getPath()
315
+	{
316
+		return $this->path;
317
+	}
318
+
319
+	/**
320
+	 * @return mixed[]
321
+	 */
322
+	public function getExtensions()
323
+	{
324
+		return $this->extensions;
325
+	}
326
+
327
+	/**
328
+	 * Returns array representation of error suitable for serialization
329
+	 *
330
+	 * @deprecated Use FormattedError::createFromException() instead
331
+	 *
332
+	 * @return mixed[]
333
+	 *
334
+	 * @codeCoverageIgnore
335
+	 */
336
+	public function toSerializableArray()
337
+	{
338
+		$arr = [
339
+			'message' => $this->getMessage(),
340
+		];
341
+
342
+		$locations = Utils::map(
343
+			$this->getLocations(),
344
+			static function (SourceLocation $loc) : array {
345
+				return $loc->toSerializableArray();
346
+			}
347
+		);
348
+
349
+		if (count($locations) > 0) {
350
+			$arr['locations'] = $locations;
351
+		}
352
+		if (count($this->path ?? []) > 0) {
353
+			$arr['path'] = $this->path;
354
+		}
355
+		if (count($this->extensions ?? []) > 0) {
356
+			$arr['extensions'] = $this->extensions;
357
+		}
358
+
359
+		return $arr;
360
+	}
361
+
362
+	/**
363
+	 * Specify data which should be serialized to JSON
364
+	 *
365
+	 * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
366
+	 *
367
+	 * @return mixed data which can be serialized by <b>json_encode</b>,
368
+	 * which is a value of any type other than a resource.
369
+	 */
370
+	public function jsonSerialize(): mixed
371
+	{
372
+		return $this->toSerializableArray();
373
+	}
374
+
375
+	/**
376
+	 * @return string
377
+	 */
378
+	public function __toString()
379
+	{
380
+		return FormattedError::printError($this);
381
+	}
382 382
 }
Please login to merge, or discard this patch.
languages/event_espresso-translations-js.php 1 patch
Spacing   +710 added lines, -710 removed lines patch added patch discarded remove patch
@@ -2,137 +2,137 @@  discard block
 block discarded – undo
2 2
 /* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */
3 3
 $generated_i18n_strings = array(
4 4
 	// Reference: packages/ui-components/src/Pagination/constants.ts:6
5
-	__( '2', 'event_espresso' ),
5
+	__('2', 'event_espresso'),
6 6
 
7 7
 	// Reference: packages/ui-components/src/Pagination/constants.ts:7
8
-	__( '6', 'event_espresso' ),
8
+	__('6', 'event_espresso'),
9 9
 
10 10
 	// Reference: packages/ui-components/src/Pagination/constants.ts:8
11
-	__( '12', 'event_espresso' ),
11
+	__('12', 'event_espresso'),
12 12
 
13 13
 	// Reference: packages/ui-components/src/Pagination/constants.ts:9
14
-	__( '24', 'event_espresso' ),
14
+	__('24', 'event_espresso'),
15 15
 
16 16
 	// Reference: packages/ui-components/src/Pagination/constants.ts:10
17
-	__( '48', 'event_espresso' ),
17
+	__('48', 'event_espresso'),
18 18
 
19 19
 	// Reference: domains/core/admin/blocks/src/components/AvatarImage.tsx:27
20
-	__( 'contact avatar', 'event_espresso' ),
20
+	__('contact avatar', 'event_espresso'),
21 21
 
22 22
 	// Reference: domains/core/admin/blocks/src/components/OrderByControl.tsx:12
23
-	__( 'Order by', 'event_espresso' ),
23
+	__('Order by', 'event_espresso'),
24 24
 
25 25
 	// Reference: domains/core/admin/blocks/src/components/RegStatusControl.tsx:17
26 26
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectStatus.tsx:13
27
-	__( 'Select Registration Status', 'event_espresso' ),
27
+	__('Select Registration Status', 'event_espresso'),
28 28
 
29 29
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:14
30
-	__( 'Ascending', 'event_espresso' ),
30
+	__('Ascending', 'event_espresso'),
31 31
 
32 32
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:18
33
-	__( 'Descending', 'event_espresso' ),
33
+	__('Descending', 'event_espresso'),
34 34
 
35 35
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:24
36
-	__( 'Sort order:', 'event_espresso' ),
36
+	__('Sort order:', 'event_espresso'),
37 37
 
38 38
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:41
39
-	__( 'There was some error fetching attendees list', 'event_espresso' ),
39
+	__('There was some error fetching attendees list', 'event_espresso'),
40 40
 
41 41
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:47
42
-	__( 'To get started, select what event you want to show attendees from in the block settings.', 'event_espresso' ),
42
+	__('To get started, select what event you want to show attendees from in the block settings.', 'event_espresso'),
43 43
 
44 44
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:53
45
-	__( 'There are no attendees for selected options.', 'event_espresso' ),
45
+	__('There are no attendees for selected options.', 'event_espresso'),
46 46
 
47 47
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:12
48
-	__( 'Display on Archives', 'event_espresso' ),
48
+	__('Display on Archives', 'event_espresso'),
49 49
 
50 50
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:17
51
-	__( 'Attendees are shown whenever this post is listed in an archive view.', 'event_espresso' ),
51
+	__('Attendees are shown whenever this post is listed in an archive view.', 'event_espresso'),
52 52
 
53 53
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:18
54
-	__( 'Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso' ),
54
+	__('Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso'),
55 55
 
56 56
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/AttendeeLimit.tsx:29
57
-	__( 'Number of Attendees to Display:', 'event_espresso' ),
57
+	__('Number of Attendees to Display:', 'event_espresso'),
58 58
 
59 59
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/AttendeeLimit.tsx:34
60 60
 	/* translators: %d attendees count */
61
-	_n_noop( 'Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso' ),
61
+	_n_noop('Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso'),
62 62
 
63 63
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:27
64
-	__( 'Display Gravatar', 'event_espresso' ),
64
+	__('Display Gravatar', 'event_espresso'),
65 65
 
66 66
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:32
67
-	__( 'Gravatar images are shown for each attendee.', 'event_espresso' ),
67
+	__('Gravatar images are shown for each attendee.', 'event_espresso'),
68 68
 
69 69
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:33
70
-	__( 'No gravatar images are shown for each attendee.', 'event_espresso' ),
70
+	__('No gravatar images are shown for each attendee.', 'event_espresso'),
71 71
 
72 72
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:38
73
-	__( 'Size of Gravatar', 'event_espresso' ),
73
+	__('Size of Gravatar', 'event_espresso'),
74 74
 
75 75
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectDatetime.tsx:22
76
-	__( 'Select Datetime', 'event_espresso' ),
76
+	__('Select Datetime', 'event_espresso'),
77 77
 
78 78
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectEvent.tsx:22
79 79
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectEvent.tsx:22
80
-	__( 'Select Event', 'event_espresso' ),
80
+	__('Select Event', 'event_espresso'),
81 81
 
82 82
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:11
83
-	__( 'Attendee id', 'event_espresso' ),
83
+	__('Attendee id', 'event_espresso'),
84 84
 
85 85
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:15
86
-	__( 'Last name only', 'event_espresso' ),
86
+	__('Last name only', 'event_espresso'),
87 87
 
88 88
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:19
89
-	__( 'First name only', 'event_espresso' ),
89
+	__('First name only', 'event_espresso'),
90 90
 
91 91
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:23
92
-	__( 'First, then Last name', 'event_espresso' ),
92
+	__('First, then Last name', 'event_espresso'),
93 93
 
94 94
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:27
95
-	__( 'Last, then First name', 'event_espresso' ),
95
+	__('Last, then First name', 'event_espresso'),
96 96
 
97 97
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:41
98
-	__( 'Order Attendees by:', 'event_espresso' ),
98
+	__('Order Attendees by:', 'event_espresso'),
99 99
 
100 100
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectTicket.tsx:22
101
-	__( 'Select Ticket', 'event_espresso' ),
101
+	__('Select Ticket', 'event_espresso'),
102 102
 
103 103
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:21
104
-	__( 'Filter By Settings', 'event_espresso' ),
104
+	__('Filter By Settings', 'event_espresso'),
105 105
 
106 106
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:36
107
-	__( 'Gravatar Setttings', 'event_espresso' ),
107
+	__('Gravatar Setttings', 'event_espresso'),
108 108
 
109 109
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:39
110
-	__( 'Archive Settings', 'event_espresso' ),
110
+	__('Archive Settings', 'event_espresso'),
111 111
 
112 112
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:10
113
-	__( 'Event Attendees', 'event_espresso' ),
113
+	__('Event Attendees', 'event_espresso'),
114 114
 
115 115
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:11
116
-	__( 'Displays a list of people that have registered for the specified event', 'event_espresso' ),
116
+	__('Displays a list of people that have registered for the specified event', 'event_espresso'),
117 117
 
118 118
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
119 119
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:12
120 120
 	// Reference: packages/edtr-services/src/constants.ts:25
121
-	__( 'event', 'event_espresso' ),
121
+	__('event', 'event_espresso'),
122 122
 
123 123
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
124
-	__( 'attendees', 'event_espresso' ),
124
+	__('attendees', 'event_espresso'),
125 125
 
126 126
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
127
-	__( 'list', 'event_espresso' ),
127
+	__('list', 'event_espresso'),
128 128
 
129 129
 	// Reference: domains/core/admin/blocks/src/event/DisplayField.tsx:41
130
-	__( 'An unknown error occurred while fetching event details.', 'event_espresso' ),
130
+	__('An unknown error occurred while fetching event details.', 'event_espresso'),
131 131
 
132 132
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:10
133 133
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:24
134 134
 	// Reference: packages/utils/src/list/index.ts:14
135
-	__( 'Select…', 'event_espresso' ),
135
+	__('Select…', 'event_espresso'),
136 136
 
137 137
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:15
138 138
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:75
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:198
142 142
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:49
143 143
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:40
144
-	__( 'Name', 'event_espresso' ),
144
+	__('Name', 'event_espresso'),
145 145
 
146 146
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:19
147 147
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:80
@@ -149,404 +149,404 @@  discard block
 block discarded – undo
149 149
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:203
150 150
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:55
151 151
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:47
152
-	__( 'Description', 'event_espresso' ),
152
+	__('Description', 'event_espresso'),
153 153
 
154 154
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:23
155
-	__( 'Short description', 'event_espresso' ),
155
+	__('Short description', 'event_espresso'),
156 156
 
157 157
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:35
158
-	__( 'Select Field', 'event_espresso' ),
158
+	__('Select Field', 'event_espresso'),
159 159
 
160 160
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:27
161
-	__( 'Text Color', 'event_espresso' ),
161
+	__('Text Color', 'event_espresso'),
162 162
 
163 163
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:32
164
-	__( 'Background Color', 'event_espresso' ),
164
+	__('Background Color', 'event_espresso'),
165 165
 
166 166
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:41
167 167
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:22
168 168
 	// Reference: packages/form-builder/src/FormSection/Tabs/FormSectionTabs.tsx:21
169
-	__( 'Settings', 'event_espresso' ),
169
+	__('Settings', 'event_espresso'),
170 170
 
171 171
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:45
172
-	__( 'Typography', 'event_espresso' ),
172
+	__('Typography', 'event_espresso'),
173 173
 
174 174
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:48
175
-	__( 'Color', 'event_espresso' ),
175
+	__('Color', 'event_espresso'),
176 176
 
177 177
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:12
178
-	__( 'field', 'event_espresso' ),
178
+	__('field', 'event_espresso'),
179 179
 
180 180
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:8
181
-	__( 'Event Field', 'event_espresso' ),
181
+	__('Event Field', 'event_espresso'),
182 182
 
183 183
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:9
184
-	__( 'Displays the selected field of an event', 'event_espresso' ),
184
+	__('Displays the selected field of an event', 'event_espresso'),
185 185
 
186 186
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:17
187
-	__( 'Error', 'event_espresso' ),
187
+	__('Error', 'event_espresso'),
188 188
 
189 189
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:9
190
-	__( 'Loading…', 'event_espresso' ),
190
+	__('Loading…', 'event_espresso'),
191 191
 
192 192
 	// Reference: domains/core/admin/eventEditor/src/ui/EventDescription.tsx:33
193
-	__( 'Event Description', 'event_espresso' ),
193
+	__('Event Description', 'event_espresso'),
194 194
 
195 195
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:28
196
-	__( 'Active status', 'event_espresso' ),
196
+	__('Active status', 'event_espresso'),
197 197
 
198 198
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/AltRegPage.tsx:12
199
-	__( 'Alternative Registration Page', 'event_espresso' ),
199
+	__('Alternative Registration Page', 'event_espresso'),
200 200
 
201 201
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/DefaultRegistrationStatus.tsx:25
202
-	__( 'Default Registration Status', 'event_espresso' ),
202
+	__('Default Registration Status', 'event_espresso'),
203 203
 
204 204
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:8
205
-	__( 'Donations Enabled', 'event_espresso' ),
205
+	__('Donations Enabled', 'event_espresso'),
206 206
 
207 207
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:8
208
-	__( 'Donations Disabled', 'event_espresso' ),
208
+	__('Donations Disabled', 'event_espresso'),
209 209
 
210 210
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/EventManager.tsx:16
211
-	__( 'Event Manager', 'event_espresso' ),
211
+	__('Event Manager', 'event_espresso'),
212 212
 
213 213
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/EventPhoneNumber.tsx:15
214
-	__( 'Event Phone Number', 'event_espresso' ),
214
+	__('Event Phone Number', 'event_espresso'),
215 215
 
216 216
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/MaxRegistrations.tsx:13
217
-	__( 'Max Registrations per Transaction', 'event_espresso' ),
217
+	__('Max Registrations per Transaction', 'event_espresso'),
218 218
 
219 219
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:8
220
-	__( 'Ticket Selector Enabled', 'event_espresso' ),
220
+	__('Ticket Selector Enabled', 'event_espresso'),
221 221
 
222 222
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:8
223
-	__( 'Ticket Selector Disabled', 'event_espresso' ),
223
+	__('Ticket Selector Disabled', 'event_espresso'),
224 224
 
225 225
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/index.tsx:41
226
-	__( 'Event Details', 'event_espresso' ),
226
+	__('Event Details', 'event_espresso'),
227 227
 
228 228
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/index.tsx:47
229
-	__( 'Registration Options', 'event_espresso' ),
229
+	__('Registration Options', 'event_espresso'),
230 230
 
231 231
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:10
232
-	__( 'primary information about the date', 'event_espresso' ),
232
+	__('primary information about the date', 'event_espresso'),
233 233
 
234 234
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:10
235
-	__( 'Date Details', 'event_espresso' ),
235
+	__('Date Details', 'event_espresso'),
236 236
 
237 237
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
238 238
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:16
239 239
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:16
240
-	__( 'relations between tickets and dates', 'event_espresso' ),
240
+	__('relations between tickets and dates', 'event_espresso'),
241 241
 
242 242
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
243
-	__( 'Assign Tickets', 'event_espresso' ),
243
+	__('Assign Tickets', 'event_espresso'),
244 244
 
245 245
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/FooterButtons.tsx:22
246
-	__( 'Save and assign tickets', 'event_espresso' ),
246
+	__('Save and assign tickets', 'event_espresso'),
247 247
 
248 248
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/Modal.tsx:27
249 249
 	/* translators: %s datetime id */
250
-	__( 'Edit datetime %s', 'event_espresso' ),
250
+	__('Edit datetime %s', 'event_espresso'),
251 251
 
252 252
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/Modal.tsx:30
253
-	__( 'New Datetime', 'event_espresso' ),
253
+	__('New Datetime', 'event_espresso'),
254 254
 
255 255
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:110
256 256
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:108
257 257
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:233
258 258
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:107
259
-	__( 'Details', 'event_espresso' ),
259
+	__('Details', 'event_espresso'),
260 260
 
261 261
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:114
262 262
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:112
263 263
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:81
264
-	__( 'Capacity', 'event_espresso' ),
264
+	__('Capacity', 'event_espresso'),
265 265
 
266 266
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:119
267
-	__( 'The maximum number of registrants that can attend the event at this particular date.', 'event_espresso' ),
267
+	__('The maximum number of registrants that can attend the event at this particular date.', 'event_espresso'),
268 268
 
269 269
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:123
270
-	__( 'Set to 0 to close registration or leave blank for no limit.', 'event_espresso' ),
270
+	__('Set to 0 to close registration or leave blank for no limit.', 'event_espresso'),
271 271
 
272 272
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:129
273 273
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:171
274
-	__( 'Trash', 'event_espresso' ),
274
+	__('Trash', 'event_espresso'),
275 275
 
276 276
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:71
277 277
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:45
278 278
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:194
279 279
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:45
280
-	__( 'Basics', 'event_espresso' ),
280
+	__('Basics', 'event_espresso'),
281 281
 
282 282
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:88
283 283
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:63
284 284
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:63
285
-	__( 'Dates', 'event_espresso' ),
285
+	__('Dates', 'event_espresso'),
286 286
 
287 287
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:92
288 288
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:51
289 289
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:215
290
-	__( 'Start Date', 'event_espresso' ),
290
+	__('Start Date', 'event_espresso'),
291 291
 
292 292
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:99
293 293
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:65
294 294
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:222
295
-	__( 'End Date', 'event_espresso' ),
295
+	__('End Date', 'event_espresso'),
296 296
 
297 297
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DateRegistrationsLink.tsx:13
298
-	__( 'view ALL registrations for this date.', 'event_espresso' ),
298
+	__('view ALL registrations for this date.', 'event_espresso'),
299 299
 
300 300
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DateSoldLink.tsx:13
301
-	__( 'view approved registrations for this date.', 'event_espresso' ),
301
+	__('view approved registrations for this date.', 'event_espresso'),
302 302
 
303 303
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:35
304 304
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/TableView.tsx:33
305
-	__( 'Event Dates', 'event_espresso' ),
305
+	__('Event Dates', 'event_espresso'),
306 306
 
307 307
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:38
308
-	__( 'loading event dates…', 'event_espresso' ),
308
+	__('loading event dates…', 'event_espresso'),
309 309
 
310 310
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesListButtons.tsx:22
311
-	__( 'Add a date or a ticket in order to use Ticket Assignment Manager', 'event_espresso' ),
311
+	__('Add a date or a ticket in order to use Ticket Assignment Manager', 'event_espresso'),
312 312
 
313 313
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesListButtons.tsx:32
314
-	__( 'Ticket Assignments', 'event_espresso' ),
314
+	__('Ticket Assignments', 'event_espresso'),
315 315
 
316 316
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:25
317
-	__( 'Number of related tickets', 'event_espresso' ),
317
+	__('Number of related tickets', 'event_espresso'),
318 318
 
319 319
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:26
320
-	__( 'There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso' ),
320
+	__('There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso'),
321 321
 
322 322
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:34
323
-	__( 'assign tickets', 'event_espresso' ),
323
+	__('assign tickets', 'event_espresso'),
324 324
 
325 325
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:21
326
-	__( 'event date main menu', 'event_espresso' ),
326
+	__('event date main menu', 'event_espresso'),
327 327
 
328 328
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:33
329
-	__( 'edit datetime', 'event_espresso' ),
329
+	__('edit datetime', 'event_espresso'),
330 330
 
331 331
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:34
332
-	__( 'copy datetime', 'event_espresso' ),
332
+	__('copy datetime', 'event_espresso'),
333 333
 
334 334
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:15
335 335
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:48
336
-	__( 'delete permanently', 'event_espresso' ),
336
+	__('delete permanently', 'event_espresso'),
337 337
 
338 338
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:15
339
-	__( 'trash datetime', 'event_espresso' ),
339
+	__('trash datetime', 'event_espresso'),
340 340
 
341 341
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:18
342
-	__( 'Permanently Delete Datetime?', 'event_espresso' ),
342
+	__('Permanently Delete Datetime?', 'event_espresso'),
343 343
 
344 344
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:18
345
-	__( 'Move Datetime to Trash?', 'event_espresso' ),
345
+	__('Move Datetime to Trash?', 'event_espresso'),
346 346
 
347 347
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:20
348
-	__( 'Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso' ),
348
+	__('Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso'),
349 349
 
350 350
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:23
351
-	__( 'Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso' ),
351
+	__('Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso'),
352 352
 
353 353
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:33
354
-	__( 'delete', 'event_espresso' ),
354
+	__('delete', 'event_espresso'),
355 355
 
356 356
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:36
357 357
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:40
358 358
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:43
359
-	__( 'bulk actions', 'event_espresso' ),
359
+	__('bulk actions', 'event_espresso'),
360 360
 
361 361
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:40
362
-	__( 'edit datetime details', 'event_espresso' ),
362
+	__('edit datetime details', 'event_espresso'),
363 363
 
364 364
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:44
365
-	__( 'delete datetimes', 'event_espresso' ),
365
+	__('delete datetimes', 'event_espresso'),
366 366
 
367 367
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:44
368
-	__( 'trash datetimes', 'event_espresso' ),
368
+	__('trash datetimes', 'event_espresso'),
369 369
 
370 370
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:14
371
-	__( 'Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso' ),
371
+	__('Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso'),
372 372
 
373 373
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:15
374
-	__( 'Are you sure you want to trash these datetimes?', 'event_espresso' ),
374
+	__('Are you sure you want to trash these datetimes?', 'event_espresso'),
375 375
 
376 376
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:16
377
-	__( 'Delete datetimes permanently', 'event_espresso' ),
377
+	__('Delete datetimes permanently', 'event_espresso'),
378 378
 
379 379
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:16
380
-	__( 'Trash datetimes', 'event_espresso' ),
380
+	__('Trash datetimes', 'event_espresso'),
381 381
 
382 382
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:21
383
-	__( 'Bulk edit date details', 'event_espresso' ),
383
+	__('Bulk edit date details', 'event_espresso'),
384 384
 
385 385
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:22
386
-	__( 'any changes will be applied to ALL of the selected dates.', 'event_espresso' ),
386
+	__('any changes will be applied to ALL of the selected dates.', 'event_espresso'),
387 387
 
388 388
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/formValidation.ts:12
389 389
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/formValidation.ts:12
390
-	__( 'Name must be at least three characters', 'event_espresso' ),
390
+	__('Name must be at least three characters', 'event_espresso'),
391 391
 
392 392
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:67
393 393
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:67
394
-	__( 'Shift dates', 'event_espresso' ),
394
+	__('Shift dates', 'event_espresso'),
395 395
 
396 396
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:92
397 397
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:91
398
-	__( 'earlier', 'event_espresso' ),
398
+	__('earlier', 'event_espresso'),
399 399
 
400 400
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:96
401 401
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:95
402
-	__( 'later', 'event_espresso' ),
402
+	__('later', 'event_espresso'),
403 403
 
404 404
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCapacity.tsx:31
405 405
 	/* translators: click to edit capacity<linebreak>(registration limit)… */
406
-	__( 'click to edit capacity%s(registration limit)…', 'event_espresso' ),
406
+	__('click to edit capacity%s(registration limit)…', 'event_espresso'),
407 407
 
408 408
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:31
409 409
 	// Reference: packages/ee-components/src/SimpleTicketCard/SimpleTicketCard.tsx:27
410 410
 	// Reference: packages/ui-components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:34
411
-	__( 'starts', 'event_espresso' ),
411
+	__('starts', 'event_espresso'),
412 412
 
413 413
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
414 414
 	// Reference: packages/ee-components/src/SimpleTicketCard/SimpleTicketCard.tsx:34
415 415
 	// Reference: packages/ui-components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:47
416
-	__( 'ends', 'event_espresso' ),
416
+	__('ends', 'event_espresso'),
417 417
 
418 418
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
419
-	__( 'started', 'event_espresso' ),
419
+	__('started', 'event_espresso'),
420 420
 
421 421
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
422
-	__( 'ended', 'event_espresso' ),
422
+	__('ended', 'event_espresso'),
423 423
 
424 424
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:46
425
-	__( 'Edit Event Date', 'event_espresso' ),
425
+	__('Edit Event Date', 'event_espresso'),
426 426
 
427 427
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:50
428
-	__( 'edit start and end dates', 'event_espresso' ),
428
+	__('edit start and end dates', 'event_espresso'),
429 429
 
430 430
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:16
431 431
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:16
432
-	__( 'sold', 'event_espresso' ),
432
+	__('sold', 'event_espresso'),
433 433
 
434 434
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:21
435
-	__( 'capacity', 'event_espresso' ),
435
+	__('capacity', 'event_espresso'),
436 436
 
437 437
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:27
438 438
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:26
439
-	__( 'reg list', 'event_espresso' ),
439
+	__('reg list', 'event_espresso'),
440 440
 
441 441
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:43
442 442
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:35
443
-	__( 'add description…', 'event_espresso' ),
443
+	__('add description…', 'event_espresso'),
444 444
 
445 445
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:44
446 446
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:36
447
-	__( 'Edit description', 'event_espresso' ),
447
+	__('Edit description', 'event_espresso'),
448 448
 
449 449
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:45
450 450
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:37
451
-	__( 'click to edit description…', 'event_espresso' ),
451
+	__('click to edit description…', 'event_espresso'),
452 452
 
453 453
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:10
454
-	__( 'Move Date to Trash', 'event_espresso' ),
454
+	__('Move Date to Trash', 'event_espresso'),
455 455
 
456 456
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:13
457 457
 	// Reference: packages/constants/src/datetime.ts:6
458
-	__( 'Active', 'event_espresso' ),
458
+	__('Active', 'event_espresso'),
459 459
 
460 460
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:14
461 461
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:13
462
-	__( 'Trashed', 'event_espresso' ),
462
+	__('Trashed', 'event_espresso'),
463 463
 
464 464
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:15
465 465
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:14
466 466
 	// Reference: packages/constants/src/datetime.ts:8
467
-	__( 'Expired', 'event_espresso' ),
467
+	__('Expired', 'event_espresso'),
468 468
 
469 469
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:16
470 470
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:16
471
-	__( 'Sold Out', 'event_espresso' ),
471
+	__('Sold Out', 'event_espresso'),
472 472
 
473 473
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:17
474 474
 	// Reference: packages/constants/src/datetime.ts:12
475
-	__( 'Upcoming', 'event_espresso' ),
475
+	__('Upcoming', 'event_espresso'),
476 476
 
477 477
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:7
478
-	__( 'Edit Event Date Details', 'event_espresso' ),
478
+	__('Edit Event Date Details', 'event_espresso'),
479 479
 
480 480
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:8
481
-	__( 'View Registrations for this Date', 'event_espresso' ),
481
+	__('View Registrations for this Date', 'event_espresso'),
482 482
 
483 483
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:9
484
-	__( 'Manage Ticket Assignments', 'event_espresso' ),
484
+	__('Manage Ticket Assignments', 'event_espresso'),
485 485
 
486 486
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/editable/EditableName.tsx:41
487 487
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditableName.tsx:41
488
-	__( 'click to edit title…', 'event_espresso' ),
488
+	__('click to edit title…', 'event_espresso'),
489 489
 
490 490
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/editable/EditableName.tsx:42
491 491
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditableName.tsx:42
492
-	__( 'add title…', 'event_espresso' ),
492
+	__('add title…', 'event_espresso'),
493 493
 
494 494
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/ActiveDatesFilters.tsx:17
495 495
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/ActiveTicketsFilters.tsx:17
496
-	__( 'ON', 'event_espresso' ),
496
+	__('ON', 'event_espresso'),
497 497
 
498 498
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:10
499
-	__( 'end dates only', 'event_espresso' ),
499
+	__('end dates only', 'event_espresso'),
500 500
 
501 501
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:11
502
-	__( 'start and end dates', 'event_espresso' ),
502
+	__('start and end dates', 'event_espresso'),
503 503
 
504 504
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:16
505
-	__( 'dates above 90% capacity', 'event_espresso' ),
505
+	__('dates above 90% capacity', 'event_espresso'),
506 506
 
507 507
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:17
508
-	__( 'dates above 75% capacity', 'event_espresso' ),
508
+	__('dates above 75% capacity', 'event_espresso'),
509 509
 
510 510
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:18
511
-	__( 'dates above 50% capacity', 'event_espresso' ),
511
+	__('dates above 50% capacity', 'event_espresso'),
512 512
 
513 513
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:19
514
-	__( 'dates below 50% capacity', 'event_espresso' ),
514
+	__('dates below 50% capacity', 'event_espresso'),
515 515
 
516 516
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:23
517
-	__( 'all dates', 'event_espresso' ),
517
+	__('all dates', 'event_espresso'),
518 518
 
519 519
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:24
520
-	__( 'all active and upcoming', 'event_espresso' ),
520
+	__('all active and upcoming', 'event_espresso'),
521 521
 
522 522
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:25
523
-	__( 'active dates only', 'event_espresso' ),
523
+	__('active dates only', 'event_espresso'),
524 524
 
525 525
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:26
526
-	__( 'upcoming dates only', 'event_espresso' ),
526
+	__('upcoming dates only', 'event_espresso'),
527 527
 
528 528
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:27
529
-	__( 'next active or upcoming only', 'event_espresso' ),
529
+	__('next active or upcoming only', 'event_espresso'),
530 530
 
531 531
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:28
532
-	__( 'sold out dates only', 'event_espresso' ),
532
+	__('sold out dates only', 'event_espresso'),
533 533
 
534 534
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:29
535
-	__( 'recently expired dates', 'event_espresso' ),
535
+	__('recently expired dates', 'event_espresso'),
536 536
 
537 537
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:30
538
-	__( 'all expired dates', 'event_espresso' ),
538
+	__('all expired dates', 'event_espresso'),
539 539
 
540 540
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:31
541
-	__( 'trashed dates only', 'event_espresso' ),
541
+	__('trashed dates only', 'event_espresso'),
542 542
 
543 543
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:35
544 544
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:9
545 545
 	// Reference: packages/dates/src/components/DateRangePicker/index.tsx:61
546
-	__( 'start date', 'event_espresso' ),
546
+	__('start date', 'event_espresso'),
547 547
 
548 548
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:36
549
-	__( 'name', 'event_espresso' ),
549
+	__('name', 'event_espresso'),
550 550
 
551 551
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:37
552 552
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:31
@@ -554,179 +554,179 @@  discard block
 block discarded – undo
554 554
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/HeaderCell.tsx:27
555 555
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:31
556 556
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:23
557
-	__( 'ID', 'event_espresso' ),
557
+	__('ID', 'event_espresso'),
558 558
 
559 559
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:38
560 560
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:47
561
-	__( 'custom order', 'event_espresso' ),
561
+	__('custom order', 'event_espresso'),
562 562
 
563 563
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:42
564 564
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:51
565
-	__( 'display', 'event_espresso' ),
565
+	__('display', 'event_espresso'),
566 566
 
567 567
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:43
568
-	__( 'recurrence', 'event_espresso' ),
568
+	__('recurrence', 'event_espresso'),
569 569
 
570 570
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:44
571 571
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:53
572
-	__( 'sales', 'event_espresso' ),
572
+	__('sales', 'event_espresso'),
573 573
 
574 574
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:45
575 575
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:55
576
-	__( 'sort by', 'event_espresso' ),
576
+	__('sort by', 'event_espresso'),
577 577
 
578 578
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:46
579 579
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:54
580 580
 	// Reference: packages/ee-components/src/EntityList/EntityListFilterBar.tsx:46
581
-	__( 'search', 'event_espresso' ),
581
+	__('search', 'event_espresso'),
582 582
 
583 583
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:47
584 584
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:56
585
-	__( 'status', 'event_espresso' ),
585
+	__('status', 'event_espresso'),
586 586
 
587 587
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:9
588
-	__( 'start dates only', 'event_espresso' ),
588
+	__('start dates only', 'event_espresso'),
589 589
 
590 590
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:26
591 591
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/NewDateModal.tsx:12
592 592
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/OptionsModalButton.tsx:18
593
-	__( 'Add New Date', 'event_espresso' ),
593
+	__('Add New Date', 'event_espresso'),
594 594
 
595 595
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:26
596
-	__( 'Add Single Date', 'event_espresso' ),
596
+	__('Add Single Date', 'event_espresso'),
597 597
 
598 598
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:44
599
-	__( 'Add a single date that only occurs once', 'event_espresso' ),
599
+	__('Add a single date that only occurs once', 'event_espresso'),
600 600
 
601 601
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:46
602
-	__( 'Single Date', 'event_espresso' ),
602
+	__('Single Date', 'event_espresso'),
603 603
 
604 604
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:106
605
-	__( 'Reg list', 'event_espresso' ),
605
+	__('Reg list', 'event_espresso'),
606 606
 
607 607
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:107
608
-	__( 'Regs', 'event_espresso' ),
608
+	__('Regs', 'event_espresso'),
609 609
 
610 610
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:122
611 611
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:121
612 612
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:59
613
-	__( 'Actions', 'event_espresso' ),
613
+	__('Actions', 'event_espresso'),
614 614
 
615 615
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:52
616
-	__( 'Start', 'event_espresso' ),
616
+	__('Start', 'event_espresso'),
617 617
 
618 618
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:66
619
-	__( 'End', 'event_espresso' ),
619
+	__('End', 'event_espresso'),
620 620
 
621 621
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:82
622
-	__( 'Cap', 'event_espresso' ),
622
+	__('Cap', 'event_espresso'),
623 623
 
624 624
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:94
625 625
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:98
626
-	__( 'Sold', 'event_espresso' ),
626
+	__('Sold', 'event_espresso'),
627 627
 
628 628
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:33
629 629
 	// Reference: packages/form-builder/src/constants.ts:67
630
-	__( 'Text Input', 'event_espresso' ),
630
+	__('Text Input', 'event_espresso'),
631 631
 
632 632
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:34
633 633
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:32
634
-	__( 'Attendee First Name', 'event_espresso' ),
634
+	__('Attendee First Name', 'event_espresso'),
635 635
 
636 636
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:39
637 637
 	/* translators: field name */
638
-	__( 'Registration form must have a field of type "%1$s" which maps to "%2$s"', 'event_espresso' ),
638
+	__('Registration form must have a field of type "%1$s" which maps to "%2$s"', 'event_espresso'),
639 639
 
640 640
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:40
641 641
 	// Reference: packages/form-builder/src/constants.ts:82
642
-	__( 'Email Address', 'event_espresso' ),
642
+	__('Email Address', 'event_espresso'),
643 643
 
644 644
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:41
645 645
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:40
646
-	__( 'Attendee Email Address', 'event_espresso' ),
646
+	__('Attendee Email Address', 'event_espresso'),
647 647
 
648 648
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:49
649
-	__( 'Please add the required fields', 'event_espresso' ),
649
+	__('Please add the required fields', 'event_espresso'),
650 650
 
651 651
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/RegistrationForm.tsx:12
652
-	__( 'Registration Form', 'event_espresso' ),
652
+	__('Registration Form', 'event_espresso'),
653 653
 
654 654
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:13
655
-	__( 'primary registrant', 'event_espresso' ),
655
+	__('primary registrant', 'event_espresso'),
656 656
 
657 657
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:17
658
-	__( 'purchaser', 'event_espresso' ),
658
+	__('purchaser', 'event_espresso'),
659 659
 
660 660
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:21
661
-	__( 'registrants', 'event_espresso' ),
661
+	__('registrants', 'event_espresso'),
662 662
 
663 663
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:36
664
-	__( 'Attendee Last Name', 'event_espresso' ),
664
+	__('Attendee Last Name', 'event_espresso'),
665 665
 
666 666
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:44
667
-	__( 'Attendee Address', 'event_espresso' ),
667
+	__('Attendee Address', 'event_espresso'),
668 668
 
669 669
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:9
670
-	__( 'all', 'event_espresso' ),
670
+	__('all', 'event_espresso'),
671 671
 
672 672
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:18
673
-	__( 'Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. 
674
-Please correct the assignments for the highlighted cells.', 'event_espresso' ),
673
+	__('Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. 
674
+Please correct the assignments for the highlighted cells.', 'event_espresso'),
675 675
 
676 676
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:22
677
-	__( 'Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. 
678
-Please correct the assignments for the highlighted cells.', 'event_espresso' ),
677
+	__('Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. 
678
+Please correct the assignments for the highlighted cells.', 'event_espresso'),
679 679
 
680 680
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:32
681
-	__( 'Please Update Assignments', 'event_espresso' ),
681
+	__('Please Update Assignments', 'event_espresso'),
682 682
 
683 683
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:26
684
-	__( 'There seem to be some dates/tickets which have no tickets/dates assigned. Do you want to fix them now?', 'event_espresso' ),
684
+	__('There seem to be some dates/tickets which have no tickets/dates assigned. Do you want to fix them now?', 'event_espresso'),
685 685
 
686 686
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:29
687
-	__( 'Alert!', 'event_espresso' ),
687
+	__('Alert!', 'event_espresso'),
688 688
 
689 689
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:42
690 690
 	/* translators: 1 entity id, 2 entity name */
691
-	__( 'Ticket Assignment Manager for Datetime: %1$s - %2$s', 'event_espresso' ),
691
+	__('Ticket Assignment Manager for Datetime: %1$s - %2$s', 'event_espresso'),
692 692
 
693 693
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:49
694 694
 	/* translators: 1 entity id, 2 entity name */
695
-	__( 'Ticket Assignment Manager for Ticket: %1$s - %2$s', 'event_espresso' ),
695
+	__('Ticket Assignment Manager for Ticket: %1$s - %2$s', 'event_espresso'),
696 696
 
697 697
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/TicketAssignmentsManagerModal.tsx:28
698 698
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/Table.tsx:13
699
-	__( 'Ticket Assignment Manager', 'event_espresso' ),
699
+	__('Ticket Assignment Manager', 'event_espresso'),
700 700
 
701 701
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:10
702
-	__( 'existing relation', 'event_espresso' ),
702
+	__('existing relation', 'event_espresso'),
703 703
 
704 704
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:15
705
-	__( 'remove existing relation', 'event_espresso' ),
705
+	__('remove existing relation', 'event_espresso'),
706 706
 
707 707
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:20
708
-	__( 'add new relation', 'event_espresso' ),
708
+	__('add new relation', 'event_espresso'),
709 709
 
710 710
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:25
711
-	__( 'invalid relation', 'event_espresso' ),
711
+	__('invalid relation', 'event_espresso'),
712 712
 
713 713
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:29
714
-	__( 'no relation', 'event_espresso' ),
714
+	__('no relation', 'event_espresso'),
715 715
 
716 716
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/BodyCell.tsx:23
717
-	__( 'assign ticket', 'event_espresso' ),
717
+	__('assign ticket', 'event_espresso'),
718 718
 
719 719
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:15
720
-	__( 'Assignments', 'event_espresso' ),
720
+	__('Assignments', 'event_espresso'),
721 721
 
722 722
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:16
723
-	__( 'Event Dates are listed below', 'event_espresso' ),
723
+	__('Event Dates are listed below', 'event_espresso'),
724 724
 
725 725
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:17
726
-	__( 'Tickets are listed along the top', 'event_espresso' ),
726
+	__('Tickets are listed along the top', 'event_espresso'),
727 727
 
728 728
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:18
729
-	__( 'Click the cell buttons to toggle assigments', 'event_espresso' ),
729
+	__('Click the cell buttons to toggle assigments', 'event_espresso'),
730 730
 
731 731
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/useSubmitButtonProps.ts:29
732 732
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:16
@@ -735,1566 +735,1566 @@  discard block
 block discarded – undo
735 735
 	// Reference: packages/tpc/src/buttons/useSubmitButtonProps.tsx:29
736 736
 	// Reference: packages/ui-components/src/Modal/useSubmitButtonProps.tsx:13
737 737
 	// Reference: packages/ui-components/src/Stepper/buttons/Submit.tsx:7
738
-	__( 'Submit', 'event_espresso' ),
738
+	__('Submit', 'event_espresso'),
739 739
 
740 740
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:20
741
-	__( 'All Dates', 'event_espresso' ),
741
+	__('All Dates', 'event_espresso'),
742 742
 
743 743
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:27
744
-	__( 'dates by month', 'event_espresso' ),
744
+	__('dates by month', 'event_espresso'),
745 745
 
746 746
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowExpiredTicketsControl.tsx:16
747
-	__( 'show expired tickets', 'event_espresso' ),
747
+	__('show expired tickets', 'event_espresso'),
748 748
 
749 749
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedDatesControl.tsx:13
750
-	__( 'show trashed dates', 'event_espresso' ),
750
+	__('show trashed dates', 'event_espresso'),
751 751
 
752 752
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedTicketsControl.tsx:16
753
-	__( 'show trashed tickets', 'event_espresso' ),
753
+	__('show trashed tickets', 'event_espresso'),
754 754
 
755 755
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/Container.tsx:38
756 756
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actions/Actions.tsx:25
757
-	__( 'Default tickets', 'event_espresso' ),
757
+	__('Default tickets', 'event_espresso'),
758 758
 
759 759
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/ModalBody.tsx:63
760 760
 	// Reference: packages/edtr-services/src/constants.ts:26
761
-	__( 'ticket', 'event_espresso' ),
761
+	__('ticket', 'event_espresso'),
762 762
 
763 763
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:26
764 764
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:33
765
-	__( 'Set ticket prices', 'event_espresso' ),
765
+	__('Set ticket prices', 'event_espresso'),
766 766
 
767 767
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:31
768
-	__( 'Skip prices - Save', 'event_espresso' ),
768
+	__('Skip prices - Save', 'event_espresso'),
769 769
 
770 770
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:37
771 771
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:57
772
-	__( 'Ticket details', 'event_espresso' ),
772
+	__('Ticket details', 'event_espresso'),
773 773
 
774 774
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:38
775
-	__( 'Save', 'event_espresso' ),
775
+	__('Save', 'event_espresso'),
776 776
 
777 777
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/Modal.tsx:22
778 778
 	/* translators: %s ticket id */
779
-	__( 'Edit ticket %s', 'event_espresso' ),
779
+	__('Edit ticket %s', 'event_espresso'),
780 780
 
781 781
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/Modal.tsx:25
782 782
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/Modal.tsx:30
783
-	__( 'New Ticket Details', 'event_espresso' ),
783
+	__('New Ticket Details', 'event_espresso'),
784 784
 
785 785
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:10
786 786
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:10
787
-	__( 'primary information about the ticket', 'event_espresso' ),
787
+	__('primary information about the ticket', 'event_espresso'),
788 788
 
789 789
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:10
790 790
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:10
791
-	__( 'Ticket Details', 'event_espresso' ),
791
+	__('Ticket Details', 'event_espresso'),
792 792
 
793 793
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:12
794 794
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:12
795
-	__( 'apply ticket price modifiers and taxes', 'event_espresso' ),
795
+	__('apply ticket price modifiers and taxes', 'event_espresso'),
796 796
 
797 797
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:14
798 798
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:14
799
-	__( 'Price Calculator', 'event_espresso' ),
799
+	__('Price Calculator', 'event_espresso'),
800 800
 
801 801
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:16
802 802
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:16
803
-	__( 'Assign Dates', 'event_espresso' ),
803
+	__('Assign Dates', 'event_espresso'),
804 804
 
805 805
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:39
806
-	__( 'Skip prices - assign dates', 'event_espresso' ),
806
+	__('Skip prices - assign dates', 'event_espresso'),
807 807
 
808 808
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:50
809
-	__( 'Save and assign dates', 'event_espresso' ),
809
+	__('Save and assign dates', 'event_espresso'),
810 810
 
811 811
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/Modal.tsx:26
812 812
 	/* translators: 1 ticket name, 2 ticket id */
813
-	__( 'Edit ticket "%1$s" - %2$s', 'event_espresso' ),
813
+	__('Edit ticket "%1$s" - %2$s', 'event_espresso'),
814 814
 
815 815
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:101
816
-	__( 'The maximum number of this ticket available for sale.', 'event_espresso' ),
816
+	__('The maximum number of this ticket available for sale.', 'event_espresso'),
817 817
 
818 818
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:103
819
-	__( 'Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso' ),
819
+	__('Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso'),
820 820
 
821 821
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:114
822 822
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:120
823
-	__( 'Number of Uses', 'event_espresso' ),
823
+	__('Number of Uses', 'event_espresso'),
824 824
 
825 825
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:120
826
-	__( 'Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso' ),
826
+	__('Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso'),
827 827
 
828 828
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:124
829
-	__( 'Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso' ),
829
+	__('Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso'),
830 830
 
831 831
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:132
832 832
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:128
833
-	__( 'Minimum Quantity', 'event_espresso' ),
833
+	__('Minimum Quantity', 'event_espresso'),
834 834
 
835 835
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:137
836
-	__( 'The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
836
+	__('The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
837 837
 
838 838
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:141
839
-	__( 'Leave blank for no minimum.', 'event_espresso' ),
839
+	__('Leave blank for no minimum.', 'event_espresso'),
840 840
 
841 841
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:147
842 842
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:136
843
-	__( 'Maximum Quantity', 'event_espresso' ),
843
+	__('Maximum Quantity', 'event_espresso'),
844 844
 
845 845
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:153
846
-	__( 'The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
846
+	__('The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
847 847
 
848 848
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:157
849
-	__( 'Leave blank for no maximum.', 'event_espresso' ),
849
+	__('Leave blank for no maximum.', 'event_espresso'),
850 850
 
851 851
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:163
852 852
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:145
853
-	__( 'Required Ticket', 'event_espresso' ),
853
+	__('Required Ticket', 'event_espresso'),
854 854
 
855 855
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:165
856
-	__( 'If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso' ),
856
+	__('If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso'),
857 857
 
858 858
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:177
859
-	__( 'Visibility', 'event_espresso' ),
859
+	__('Visibility', 'event_espresso'),
860 860
 
861 861
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:211
862
-	__( 'Ticket Sales', 'event_espresso' ),
862
+	__('Ticket Sales', 'event_espresso'),
863 863
 
864 864
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:95
865 865
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:111
866
-	__( 'Quantity For Sale', 'event_espresso' ),
866
+	__('Quantity For Sale', 'event_espresso'),
867 867
 
868 868
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketRegistrationsLink.tsx:13
869
-	__( 'total registrations.', 'event_espresso' ),
869
+	__('total registrations.', 'event_espresso'),
870 870
 
871 871
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketRegistrationsLink.tsx:14
872
-	__( 'view ALL registrations for this ticket.', 'event_espresso' ),
872
+	__('view ALL registrations for this ticket.', 'event_espresso'),
873 873
 
874 874
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketSoldLink.tsx:13
875
-	__( 'view approved registrations for this ticket.', 'event_espresso' ),
875
+	__('view approved registrations for this ticket.', 'event_espresso'),
876 876
 
877 877
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:36
878
-	__( 'Available Tickets', 'event_espresso' ),
878
+	__('Available Tickets', 'event_espresso'),
879 879
 
880 880
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:39
881
-	__( 'loading tickets…', 'event_espresso' ),
881
+	__('loading tickets…', 'event_espresso'),
882 882
 
883 883
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:26
884
-	__( 'Number of related dates', 'event_espresso' ),
884
+	__('Number of related dates', 'event_espresso'),
885 885
 
886 886
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:27
887
-	__( 'There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso' ),
887
+	__('There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso'),
888 888
 
889 889
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:37
890
-	__( 'assign dates', 'event_espresso' ),
890
+	__('assign dates', 'event_espresso'),
891 891
 
892 892
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:19
893
-	__( 'Permanently Delete Ticket?', 'event_espresso' ),
893
+	__('Permanently Delete Ticket?', 'event_espresso'),
894 894
 
895 895
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:19
896
-	__( 'Move Ticket to Trash?', 'event_espresso' ),
896
+	__('Move Ticket to Trash?', 'event_espresso'),
897 897
 
898 898
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:22
899
-	__( 'Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso' ),
899
+	__('Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso'),
900 900
 
901 901
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:48
902 902
 	// Reference: packages/ee-components/src/SimpleTicketCard/actions/Trash.tsx:6
903
-	__( 'trash ticket', 'event_espresso' ),
903
+	__('trash ticket', 'event_espresso'),
904 904
 
905 905
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:25
906
-	__( 'ticket main menu', 'event_espresso' ),
906
+	__('ticket main menu', 'event_espresso'),
907 907
 
908 908
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:38
909 909
 	// Reference: packages/ee-components/src/SimpleTicketCard/actions/Edit.tsx:15
910
-	__( 'edit ticket', 'event_espresso' ),
910
+	__('edit ticket', 'event_espresso'),
911 911
 
912 912
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:39
913
-	__( 'copy ticket', 'event_espresso' ),
913
+	__('copy ticket', 'event_espresso'),
914 914
 
915 915
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:44
916
-	__( 'edit ticket details', 'event_espresso' ),
916
+	__('edit ticket details', 'event_espresso'),
917 917
 
918 918
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:48
919
-	__( 'delete tickets', 'event_espresso' ),
919
+	__('delete tickets', 'event_espresso'),
920 920
 
921 921
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:48
922
-	__( 'trash tickets', 'event_espresso' ),
922
+	__('trash tickets', 'event_espresso'),
923 923
 
924 924
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:52
925
-	__( 'edit ticket prices', 'event_espresso' ),
925
+	__('edit ticket prices', 'event_espresso'),
926 926
 
927 927
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:14
928
-	__( 'Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso' ),
928
+	__('Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso'),
929 929
 
930 930
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:15
931
-	__( 'Are you sure you want to trash these tickets?', 'event_espresso' ),
931
+	__('Are you sure you want to trash these tickets?', 'event_espresso'),
932 932
 
933 933
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:16
934
-	__( 'Delete tickets permanently', 'event_espresso' ),
934
+	__('Delete tickets permanently', 'event_espresso'),
935 935
 
936 936
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:16
937
-	__( 'Trash tickets', 'event_espresso' ),
937
+	__('Trash tickets', 'event_espresso'),
938 938
 
939 939
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:21
940
-	__( 'Bulk edit ticket details', 'event_espresso' ),
940
+	__('Bulk edit ticket details', 'event_espresso'),
941 941
 
942 942
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:22
943
-	__( 'any changes will be applied to ALL of the selected tickets.', 'event_espresso' ),
943
+	__('any changes will be applied to ALL of the selected tickets.', 'event_espresso'),
944 944
 
945 945
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/EditPrices.tsx:19
946
-	__( 'Bulk edit ticket prices', 'event_espresso' ),
946
+	__('Bulk edit ticket prices', 'event_espresso'),
947 947
 
948 948
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:20
949
-	__( 'Edit all prices together', 'event_espresso' ),
949
+	__('Edit all prices together', 'event_espresso'),
950 950
 
951 951
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:21
952
-	__( 'Edit all the selected ticket prices dynamically', 'event_espresso' ),
952
+	__('Edit all the selected ticket prices dynamically', 'event_espresso'),
953 953
 
954 954
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:25
955
-	__( 'Edit prices individually', 'event_espresso' ),
955
+	__('Edit prices individually', 'event_espresso'),
956 956
 
957 957
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:26
958
-	__( 'Edit prices for each ticket individually', 'event_espresso' ),
958
+	__('Edit prices for each ticket individually', 'event_espresso'),
959 959
 
960 960
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:14
961 961
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:34
962 962
 	// Reference: packages/form/src/ResetButton.tsx:18
963 963
 	// Reference: packages/tpc/src/buttons/useResetButtonProps.tsx:12
964
-	__( 'Reset', 'event_espresso' ),
964
+	__('Reset', 'event_espresso'),
965 965
 
966 966
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:15
967 967
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:76
968 968
 	// Reference: packages/ui-components/src/Modal/useCancelButtonProps.tsx:10
969
-	__( 'Cancel', 'event_espresso' ),
969
+	__('Cancel', 'event_espresso'),
970 970
 
971 971
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/editSeparately/TPCInstance.tsx:26
972 972
 	/* translators: %s ticket name */
973
-	__( 'Edit prices for Ticket: %s', 'event_espresso' ),
973
+	__('Edit prices for Ticket: %s', 'event_espresso'),
974 974
 
975 975
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:30
976
-	__( 'sales start', 'event_espresso' ),
976
+	__('sales start', 'event_espresso'),
977 977
 
978 978
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:33
979
-	__( 'sales began', 'event_espresso' ),
979
+	__('sales began', 'event_espresso'),
980 980
 
981 981
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:35
982
-	__( 'sales ended', 'event_espresso' ),
982
+	__('sales ended', 'event_espresso'),
983 983
 
984 984
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:36
985
-	__( 'sales end', 'event_espresso' ),
985
+	__('sales end', 'event_espresso'),
986 986
 
987 987
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:50
988
-	__( 'Edit Ticket Sale Dates', 'event_espresso' ),
988
+	__('Edit Ticket Sale Dates', 'event_espresso'),
989 989
 
990 990
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:54
991
-	__( 'edit ticket sales start and end dates', 'event_espresso' ),
991
+	__('edit ticket sales start and end dates', 'event_espresso'),
992 992
 
993 993
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:21
994
-	__( 'quantity', 'event_espresso' ),
994
+	__('quantity', 'event_espresso'),
995 995
 
996 996
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketQuantity.tsx:28
997 997
 	// Reference: packages/edtr-services/src/apollo/mutations/tickets/useUpdateTicketQtyByCapacity.ts:78
998
-	__( 'Ticket quantity has been adjusted because it cannot be more than the related event date capacity.', 'event_espresso' ),
998
+	__('Ticket quantity has been adjusted because it cannot be more than the related event date capacity.', 'event_espresso'),
999 999
 
1000 1000
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketQuantity.tsx:51
1001
-	__( 'edit quantity of tickets available…', 'event_espresso' ),
1001
+	__('edit quantity of tickets available…', 'event_espresso'),
1002 1002
 
1003 1003
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:10
1004
-	__( 'Move Ticket to Trash', 'event_espresso' ),
1004
+	__('Move Ticket to Trash', 'event_espresso'),
1005 1005
 
1006 1006
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:15
1007 1007
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:52
1008
-	__( 'On Sale', 'event_espresso' ),
1008
+	__('On Sale', 'event_espresso'),
1009 1009
 
1010 1010
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:17
1011
-	__( 'Pending', 'event_espresso' ),
1011
+	__('Pending', 'event_espresso'),
1012 1012
 
1013 1013
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:7
1014
-	__( 'Edit Ticket Details', 'event_espresso' ),
1014
+	__('Edit Ticket Details', 'event_espresso'),
1015 1015
 
1016 1016
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:8
1017
-	__( 'Manage Date Assignments', 'event_espresso' ),
1017
+	__('Manage Date Assignments', 'event_espresso'),
1018 1018
 
1019 1019
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:9
1020 1020
 	// Reference: packages/tpc/src/components/table/Table.tsx:43
1021
-	__( 'Ticket Price Calculator', 'event_espresso' ),
1021
+	__('Ticket Price Calculator', 'event_espresso'),
1022 1022
 
1023 1023
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:39
1024
-	__( 'edit ticket total…', 'event_espresso' ),
1024
+	__('edit ticket total…', 'event_espresso'),
1025 1025
 
1026 1026
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:53
1027
-	__( 'set price…', 'event_espresso' ),
1027
+	__('set price…', 'event_espresso'),
1028 1028
 
1029 1029
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:23
1030
-	__( 'tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso' ),
1030
+	__('tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso'),
1031 1031
 
1032 1032
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:24
1033
-	__( 'tickets list is unlinked and is showing tickets for all event dates', 'event_espresso' ),
1033
+	__('tickets list is unlinked and is showing tickets for all event dates', 'event_espresso'),
1034 1034
 
1035 1035
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:10
1036
-	__( 'ticket sales start and end dates', 'event_espresso' ),
1036
+	__('ticket sales start and end dates', 'event_espresso'),
1037 1037
 
1038 1038
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:15
1039
-	__( 'tickets with 90% or more sold', 'event_espresso' ),
1039
+	__('tickets with 90% or more sold', 'event_espresso'),
1040 1040
 
1041 1041
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:16
1042
-	__( 'tickets with 75% or more sold', 'event_espresso' ),
1042
+	__('tickets with 75% or more sold', 'event_espresso'),
1043 1043
 
1044 1044
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:17
1045
-	__( 'tickets with 50% or more sold', 'event_espresso' ),
1045
+	__('tickets with 50% or more sold', 'event_espresso'),
1046 1046
 
1047 1047
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:19
1048
-	__( 'tickets with less than 50% sold', 'event_espresso' ),
1048
+	__('tickets with less than 50% sold', 'event_espresso'),
1049 1049
 
1050 1050
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:28
1051
-	__( 'all tickets for all dates', 'event_espresso' ),
1051
+	__('all tickets for all dates', 'event_espresso'),
1052 1052
 
1053 1053
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:29
1054
-	__( 'all on sale and sale pending', 'event_espresso' ),
1054
+	__('all on sale and sale pending', 'event_espresso'),
1055 1055
 
1056 1056
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:30
1057
-	__( 'on sale tickets only', 'event_espresso' ),
1057
+	__('on sale tickets only', 'event_espresso'),
1058 1058
 
1059 1059
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:31
1060
-	__( 'sale pending tickets only', 'event_espresso' ),
1060
+	__('sale pending tickets only', 'event_espresso'),
1061 1061
 
1062 1062
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:32
1063
-	__( 'next on sale or sale pending only', 'event_espresso' ),
1063
+	__('next on sale or sale pending only', 'event_espresso'),
1064 1064
 
1065 1065
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:33
1066
-	__( 'sold out tickets only', 'event_espresso' ),
1066
+	__('sold out tickets only', 'event_espresso'),
1067 1067
 
1068 1068
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:34
1069
-	__( 'expired tickets only', 'event_espresso' ),
1069
+	__('expired tickets only', 'event_espresso'),
1070 1070
 
1071 1071
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:35
1072
-	__( 'trashed tickets only', 'event_espresso' ),
1072
+	__('trashed tickets only', 'event_espresso'),
1073 1073
 
1074 1074
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:40
1075
-	__( 'all tickets for above dates', 'event_espresso' ),
1075
+	__('all tickets for above dates', 'event_espresso'),
1076 1076
 
1077 1077
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:44
1078
-	__( 'ticket sale date', 'event_espresso' ),
1078
+	__('ticket sale date', 'event_espresso'),
1079 1079
 
1080 1080
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:45
1081
-	__( 'ticket name', 'event_espresso' ),
1081
+	__('ticket name', 'event_espresso'),
1082 1082
 
1083 1083
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:46
1084
-	__( 'ticket ID', 'event_espresso' ),
1084
+	__('ticket ID', 'event_espresso'),
1085 1085
 
1086 1086
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:52
1087
-	__( 'link', 'event_espresso' ),
1087
+	__('link', 'event_espresso'),
1088 1088
 
1089 1089
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:8
1090
-	__( 'ticket sales start date only', 'event_espresso' ),
1090
+	__('ticket sales start date only', 'event_espresso'),
1091 1091
 
1092 1092
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:9
1093
-	__( 'ticket sales end date only', 'event_espresso' ),
1093
+	__('ticket sales end date only', 'event_espresso'),
1094 1094
 
1095 1095
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:18
1096
-	__( 'Add New Ticket', 'event_espresso' ),
1096
+	__('Add New Ticket', 'event_espresso'),
1097 1097
 
1098 1098
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:32
1099
-	__( 'Add a single ticket and assign the dates to it', 'event_espresso' ),
1099
+	__('Add a single ticket and assign the dates to it', 'event_espresso'),
1100 1100
 
1101 1101
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:34
1102
-	__( 'Single Ticket', 'event_espresso' ),
1102
+	__('Single Ticket', 'event_espresso'),
1103 1103
 
1104 1104
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/TableView.tsx:39
1105
-	__( 'Tickets', 'event_espresso' ),
1105
+	__('Tickets', 'event_espresso'),
1106 1106
 
1107 1107
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:108
1108
-	__( 'Reg List', 'event_espresso' ),
1108
+	__('Reg List', 'event_espresso'),
1109 1109
 
1110 1110
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:51
1111
-	__( 'Goes on Sale', 'event_espresso' ),
1111
+	__('Goes on Sale', 'event_espresso'),
1112 1112
 
1113 1113
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:65
1114
-	__( 'Sale Ends', 'event_espresso' ),
1114
+	__('Sale Ends', 'event_espresso'),
1115 1115
 
1116 1116
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:66
1117
-	__( 'Ends', 'event_espresso' ),
1117
+	__('Ends', 'event_espresso'),
1118 1118
 
1119 1119
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:78
1120
-	__( 'Price', 'event_espresso' ),
1120
+	__('Price', 'event_espresso'),
1121 1121
 
1122 1122
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:88
1123
-	__( 'Qty', 'event_espresso' ),
1123
+	__('Qty', 'event_espresso'),
1124 1124
 
1125 1125
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:105
1126
-	__( 'Select a Venue for the Event', 'event_espresso' ),
1126
+	__('Select a Venue for the Event', 'event_espresso'),
1127 1127
 
1128 1128
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:21
1129
-	__( 'Venue Details', 'event_espresso' ),
1129
+	__('Venue Details', 'event_espresso'),
1130 1130
 
1131 1131
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:38
1132
-	__( 'unlimited space', 'event_espresso' ),
1132
+	__('unlimited space', 'event_espresso'),
1133 1133
 
1134 1134
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:41
1135 1135
 	/* translators: %d venue capacity */
1136
-	__( 'Space for up to %d people', 'event_espresso' ),
1136
+	__('Space for up to %d people', 'event_espresso'),
1137 1137
 
1138 1138
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:60
1139
-	__( 'no image', 'event_espresso' ),
1139
+	__('no image', 'event_espresso'),
1140 1140
 
1141 1141
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:96
1142
-	__( 'Edit this Venue', 'event_espresso' ),
1142
+	__('Edit this Venue', 'event_espresso'),
1143 1143
 
1144 1144
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:29
1145
-	__( 'Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso' ),
1145
+	__('Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso'),
1146 1146
 
1147 1147
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:40
1148
-	__( 'Skip', 'event_espresso' ),
1148
+	__('Skip', 'event_espresso'),
1149 1149
 
1150 1150
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:42
1151
-	__( 'Sure I\'ll help', 'event_espresso' ),
1151
+	__('Sure I\'ll help', 'event_espresso'),
1152 1152
 
1153 1153
 	// Reference: packages/adapters/src/Pagination/Pagination.tsx:23
1154
-	__( 'pagination', 'event_espresso' ),
1154
+	__('pagination', 'event_espresso'),
1155 1155
 
1156 1156
 	// Reference: packages/adapters/src/TagSelector/TagSelector.tsx:113
1157
-	__( 'toggle menu', 'event_espresso' ),
1157
+	__('toggle menu', 'event_espresso'),
1158 1158
 
1159 1159
 	// Reference: packages/constants/src/datetime.ts:10
1160
-	__( 'Postponed', 'event_espresso' ),
1160
+	__('Postponed', 'event_espresso'),
1161 1161
 
1162 1162
 	// Reference: packages/constants/src/datetime.ts:11
1163
-	__( 'SoldOut', 'event_espresso' ),
1163
+	__('SoldOut', 'event_espresso'),
1164 1164
 
1165 1165
 	// Reference: packages/constants/src/datetime.ts:7
1166 1166
 	// Reference: packages/predicates/src/registration/statusOptions.ts:11
1167
-	__( 'Cancelled', 'event_espresso' ),
1167
+	__('Cancelled', 'event_espresso'),
1168 1168
 
1169 1169
 	// Reference: packages/constants/src/datetime.ts:9
1170
-	__( 'Inactive', 'event_espresso' ),
1170
+	__('Inactive', 'event_espresso'),
1171 1171
 
1172 1172
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:25
1173
-	__( 'error creating %s', 'event_espresso' ),
1173
+	__('error creating %s', 'event_espresso'),
1174 1174
 
1175 1175
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:26
1176
-	__( 'error deleting %s', 'event_espresso' ),
1176
+	__('error deleting %s', 'event_espresso'),
1177 1177
 
1178 1178
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:27
1179
-	__( 'error updating %s', 'event_espresso' ),
1179
+	__('error updating %s', 'event_espresso'),
1180 1180
 
1181 1181
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:28
1182
-	__( 'creating %s', 'event_espresso' ),
1182
+	__('creating %s', 'event_espresso'),
1183 1183
 
1184 1184
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:29
1185
-	__( 'deleting %s', 'event_espresso' ),
1185
+	__('deleting %s', 'event_espresso'),
1186 1186
 
1187 1187
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:30
1188
-	__( 'updating %s', 'event_espresso' ),
1188
+	__('updating %s', 'event_espresso'),
1189 1189
 
1190 1190
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:31
1191
-	__( 'successfully created %s', 'event_espresso' ),
1191
+	__('successfully created %s', 'event_espresso'),
1192 1192
 
1193 1193
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:32
1194
-	__( 'successfully deleted %s', 'event_espresso' ),
1194
+	__('successfully deleted %s', 'event_espresso'),
1195 1195
 
1196 1196
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:33
1197
-	__( 'successfully updated %s', 'event_espresso' ),
1197
+	__('successfully updated %s', 'event_espresso'),
1198 1198
 
1199 1199
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:13
1200
-	__( 'day in range', 'event_espresso' ),
1200
+	__('day in range', 'event_espresso'),
1201 1201
 
1202 1202
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:17
1203 1203
 	// Reference: packages/dates/src/components/DateRangePicker/index.tsx:79
1204
-	__( 'end date', 'event_espresso' ),
1204
+	__('end date', 'event_espresso'),
1205 1205
 
1206 1206
 	// Reference: packages/dates/src/components/DateTimePicker.tsx:17
1207 1207
 	// Reference: packages/dates/src/components/TimePicker.tsx:17
1208 1208
 	// Reference: packages/form-builder/src/state/utils.ts:433
1209
-	__( 'time', 'event_espresso' ),
1209
+	__('time', 'event_espresso'),
1210 1210
 
1211 1211
 	// Reference: packages/dates/src/constants.ts:7
1212
-	__( 'End Date & Time must be set later than the Start Date & Time', 'event_espresso' ),
1212
+	__('End Date & Time must be set later than the Start Date & Time', 'event_espresso'),
1213 1213
 
1214 1214
 	// Reference: packages/dates/src/constants.ts:9
1215
-	__( 'Start Date & Time must be set before the End Date & Time', 'event_espresso' ),
1215
+	__('Start Date & Time must be set before the End Date & Time', 'event_espresso'),
1216 1216
 
1217 1217
 	// Reference: packages/dates/src/utils/misc.ts:16
1218
-	__( 'month(s)', 'event_espresso' ),
1218
+	__('month(s)', 'event_espresso'),
1219 1219
 
1220 1220
 	// Reference: packages/dates/src/utils/misc.ts:17
1221
-	__( 'week(s)', 'event_espresso' ),
1221
+	__('week(s)', 'event_espresso'),
1222 1222
 
1223 1223
 	// Reference: packages/dates/src/utils/misc.ts:18
1224
-	__( 'day(s)', 'event_espresso' ),
1224
+	__('day(s)', 'event_espresso'),
1225 1225
 
1226 1226
 	// Reference: packages/dates/src/utils/misc.ts:19
1227
-	__( 'hour(s)', 'event_espresso' ),
1227
+	__('hour(s)', 'event_espresso'),
1228 1228
 
1229 1229
 	// Reference: packages/dates/src/utils/misc.ts:20
1230
-	__( 'minute(s)', 'event_espresso' ),
1230
+	__('minute(s)', 'event_espresso'),
1231 1231
 
1232 1232
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:107
1233
-	__( 'price types initialized', 'event_espresso' ),
1233
+	__('price types initialized', 'event_espresso'),
1234 1234
 
1235 1235
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:117
1236
-	__( 'datetimes initialized', 'event_espresso' ),
1236
+	__('datetimes initialized', 'event_espresso'),
1237 1237
 
1238 1238
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:127
1239
-	__( 'tickets initialized', 'event_espresso' ),
1239
+	__('tickets initialized', 'event_espresso'),
1240 1240
 
1241 1241
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:137
1242
-	__( 'prices initialized', 'event_espresso' ),
1242
+	__('prices initialized', 'event_espresso'),
1243 1243
 
1244 1244
 	// Reference: packages/edtr-services/src/apollo/mutations/useReorderEntities.ts:63
1245
-	__( 'order updated', 'event_espresso' ),
1245
+	__('order updated', 'event_espresso'),
1246 1246
 
1247 1247
 	// Reference: packages/edtr-services/src/constants.ts:24
1248
-	__( 'datetime', 'event_espresso' ),
1248
+	__('datetime', 'event_espresso'),
1249 1249
 
1250 1250
 	// Reference: packages/edtr-services/src/constants.ts:27
1251
-	__( 'price', 'event_espresso' ),
1251
+	__('price', 'event_espresso'),
1252 1252
 
1253 1253
 	// Reference: packages/edtr-services/src/constants.ts:28
1254 1254
 	// Reference: packages/tpc/src/inputs/PriceTypeInput.tsx:20
1255
-	__( 'price type', 'event_espresso' ),
1255
+	__('price type', 'event_espresso'),
1256 1256
 
1257 1257
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:38
1258 1258
 	// Reference: packages/ui-components/src/EditDateRangeButton/EditDateRangeButton.tsx:39
1259
-	__( 'End date has been adjusted', 'event_espresso' ),
1259
+	__('End date has been adjusted', 'event_espresso'),
1260 1260
 
1261 1261
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:59
1262
-	__( 'Required', 'event_espresso' ),
1262
+	__('Required', 'event_espresso'),
1263 1263
 
1264 1264
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:64
1265
-	__( 'Start Date is required', 'event_espresso' ),
1265
+	__('Start Date is required', 'event_espresso'),
1266 1266
 
1267 1267
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:68
1268
-	__( 'End Date is required', 'event_espresso' ),
1268
+	__('End Date is required', 'event_espresso'),
1269 1269
 
1270 1270
 	// Reference: packages/ee-components/src/EntityList/EntityList.tsx:32
1271
-	__( 'no results found', 'event_espresso' ),
1271
+	__('no results found', 'event_espresso'),
1272 1272
 
1273 1273
 	// Reference: packages/ee-components/src/EntityList/EntityList.tsx:33
1274
-	__( 'try changing filter settings', 'event_espresso' ),
1274
+	__('try changing filter settings', 'event_espresso'),
1275 1275
 
1276 1276
 	// Reference: packages/ee-components/src/bulkEdit/ActionCheckbox.tsx:38
1277 1277
 	/* translators: %d entity id */
1278
-	__( 'select entity with id %d', 'event_espresso' ),
1278
+	__('select entity with id %d', 'event_espresso'),
1279 1279
 
1280 1280
 	// Reference: packages/ee-components/src/bulkEdit/ActionCheckbox.tsx:41
1281
-	__( 'select all entities', 'event_espresso' ),
1281
+	__('select all entities', 'event_espresso'),
1282 1282
 
1283 1283
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:20
1284
-	__( 'Note: ', 'event_espresso' ),
1284
+	__('Note: ', 'event_espresso'),
1285 1285
 
1286 1286
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:20
1287
-	__( 'any changes will be applied to ALL of the selected entities.', 'event_espresso' ),
1287
+	__('any changes will be applied to ALL of the selected entities.', 'event_espresso'),
1288 1288
 
1289 1289
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:27
1290
-	__( 'Bulk edit details', 'event_espresso' ),
1290
+	__('Bulk edit details', 'event_espresso'),
1291 1291
 
1292 1292
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:17
1293
-	__( 'Are you sure you want to bulk update the details?', 'event_espresso' ),
1293
+	__('Are you sure you want to bulk update the details?', 'event_espresso'),
1294 1294
 
1295 1295
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:18
1296
-	__( 'Bulk update details', 'event_espresso' ),
1296
+	__('Bulk update details', 'event_espresso'),
1297 1297
 
1298 1298
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:27
1299
-	__( 'set custom dates order', 'event_espresso' ),
1299
+	__('set custom dates order', 'event_espresso'),
1300 1300
 
1301 1301
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:28
1302
-	__( 'set custom tickets order', 'event_espresso' ),
1302
+	__('set custom tickets order', 'event_espresso'),
1303 1303
 
1304 1304
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:30
1305
-	__( 'Set Custom Dates Order - this is how dates are ordered on the frontend', 'event_espresso' ),
1305
+	__('Set Custom Dates Order - this is how dates are ordered on the frontend', 'event_espresso'),
1306 1306
 
1307 1307
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:31
1308
-	__( 'Set Custom Tickets Order - this is how tickets are ordered on the frontend', 'event_espresso' ),
1308
+	__('Set Custom Tickets Order - this is how tickets are ordered on the frontend', 'event_espresso'),
1309 1309
 
1310 1310
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:32
1311
-	__( 'delete form element', 'event_espresso' ),
1311
+	__('delete form element', 'event_espresso'),
1312 1312
 
1313 1313
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:49
1314
-	__( 'form element settings', 'event_espresso' ),
1314
+	__('form element settings', 'event_espresso'),
1315 1315
 
1316 1316
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:59
1317
-	__( 'copy form element', 'event_espresso' ),
1317
+	__('copy form element', 'event_espresso'),
1318 1318
 
1319 1319
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:69
1320
-	__( 'click, hold, and drag to reorder form element', 'event_espresso' ),
1320
+	__('click, hold, and drag to reorder form element', 'event_espresso'),
1321 1321
 
1322 1322
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:20
1323
-	__( 'remove option', 'event_espresso' ),
1323
+	__('remove option', 'event_espresso'),
1324 1324
 
1325 1325
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:42
1326
-	__( 'value', 'event_espresso' ),
1326
+	__('value', 'event_espresso'),
1327 1327
 
1328 1328
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:52
1329
-	__( 'label', 'event_espresso' ),
1329
+	__('label', 'event_espresso'),
1330 1330
 
1331 1331
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:63
1332
-	__( 'click, hold, and drag to reorder field option', 'event_espresso' ),
1332
+	__('click, hold, and drag to reorder field option', 'event_espresso'),
1333 1333
 
1334 1334
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:61
1335
-	__( 'Options are the choices you give people to select from.', 'event_espresso' ),
1335
+	__('Options are the choices you give people to select from.', 'event_espresso'),
1336 1336
 
1337 1337
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:63
1338
-	__( 'The value is a simple key that will be saved to the database and the label is what is shown to the user.', 'event_espresso' ),
1338
+	__('The value is a simple key that will be saved to the database and the label is what is shown to the user.', 'event_espresso'),
1339 1339
 
1340 1340
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:96
1341
-	__( 'add new option', 'event_espresso' ),
1341
+	__('add new option', 'event_espresso'),
1342 1342
 
1343 1343
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:26
1344 1344
 	// Reference: packages/form-builder/src/FormSection/Tabs/FormSectionTabs.tsx:25
1345
-	__( 'Styles', 'event_espresso' ),
1345
+	__('Styles', 'event_espresso'),
1346 1346
 
1347 1347
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:30
1348
-	__( 'Validation', 'event_espresso' ),
1348
+	__('Validation', 'event_espresso'),
1349 1349
 
1350 1350
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:18
1351
-	__( 'Change input type', 'event_espresso' ),
1351
+	__('Change input type', 'event_espresso'),
1352 1352
 
1353 1353
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:19
1354
-	__( 'Some configurations might be lost. Are you sure you want to change the input type?', 'event_espresso' ),
1354
+	__('Some configurations might be lost. Are you sure you want to change the input type?', 'event_espresso'),
1355 1355
 
1356 1356
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:40
1357
-	__( 'type', 'event_espresso' ),
1357
+	__('type', 'event_espresso'),
1358 1358
 
1359 1359
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:26
1360 1360
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:17
1361
-	__( 'public label', 'event_espresso' ),
1361
+	__('public label', 'event_espresso'),
1362 1362
 
1363 1363
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:33
1364 1364
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:22
1365
-	__( 'admin label', 'event_espresso' ),
1365
+	__('admin label', 'event_espresso'),
1366 1366
 
1367 1367
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:40
1368
-	__( 'content', 'event_espresso' ),
1368
+	__('content', 'event_espresso'),
1369 1369
 
1370 1370
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:48
1371
-	__( 'options', 'event_espresso' ),
1371
+	__('options', 'event_espresso'),
1372 1372
 
1373 1373
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:51
1374
-	__( 'placeholder', 'event_espresso' ),
1374
+	__('placeholder', 'event_espresso'),
1375 1375
 
1376 1376
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:57
1377
-	__( 'admin only', 'event_espresso' ),
1377
+	__('admin only', 'event_espresso'),
1378 1378
 
1379 1379
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:62
1380
-	__( 'help text', 'event_espresso' ),
1380
+	__('help text', 'event_espresso'),
1381 1381
 
1382 1382
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:71
1383
-	__( 'maps to', 'event_espresso' ),
1383
+	__('maps to', 'event_espresso'),
1384 1384
 
1385 1385
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:15
1386 1386
 	// Reference: packages/form-builder/src/FormSection/Tabs/Styles.tsx:13
1387
-	__( 'css class', 'event_espresso' ),
1387
+	__('css class', 'event_espresso'),
1388 1388
 
1389 1389
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:20
1390
-	__( 'help text css class', 'event_espresso' ),
1390
+	__('help text css class', 'event_espresso'),
1391 1391
 
1392 1392
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:27
1393
-	__( 'size', 'event_espresso' ),
1393
+	__('size', 'event_espresso'),
1394 1394
 
1395 1395
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:35
1396
-	__( 'step', 'event_espresso' ),
1396
+	__('step', 'event_espresso'),
1397 1397
 
1398 1398
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:41
1399
-	__( 'maxlength', 'event_espresso' ),
1399
+	__('maxlength', 'event_espresso'),
1400 1400
 
1401 1401
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:123
1402
-	__( 'min', 'event_espresso' ),
1402
+	__('min', 'event_espresso'),
1403 1403
 
1404 1404
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:128
1405
-	__( 'max', 'event_espresso' ),
1405
+	__('max', 'event_espresso'),
1406 1406
 
1407 1407
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:28
1408
-	__( 'Germany', 'event_espresso' ),
1408
+	__('Germany', 'event_espresso'),
1409 1409
 
1410 1410
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:32
1411
-	__( 'France', 'event_espresso' ),
1411
+	__('France', 'event_espresso'),
1412 1412
 
1413 1413
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:36
1414
-	__( 'United Kingdom', 'event_espresso' ),
1414
+	__('United Kingdom', 'event_espresso'),
1415 1415
 
1416 1416
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:40
1417
-	__( 'United States', 'event_espresso' ),
1417
+	__('United States', 'event_espresso'),
1418 1418
 
1419 1419
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:44
1420
-	__( 'Custom', 'event_espresso' ),
1420
+	__('Custom', 'event_espresso'),
1421 1421
 
1422 1422
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:54
1423
-	__( 'required', 'event_espresso' ),
1423
+	__('required', 'event_espresso'),
1424 1424
 
1425 1425
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:59
1426
-	__( 'required text', 'event_espresso' ),
1426
+	__('required text', 'event_espresso'),
1427 1427
 
1428 1428
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:66
1429
-	__( 'autocomplete', 'event_espresso' ),
1429
+	__('autocomplete', 'event_espresso'),
1430 1430
 
1431 1431
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:74
1432
-	__( 'custom format', 'event_espresso' ),
1432
+	__('custom format', 'event_espresso'),
1433 1433
 
1434 1434
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:75
1435
-	__( 'format', 'event_espresso' ),
1435
+	__('format', 'event_espresso'),
1436 1436
 
1437 1437
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:83
1438
-	__( 'pattern', 'event_espresso' ),
1438
+	__('pattern', 'event_espresso'),
1439 1439
 
1440 1440
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:110
1441
-	__( 'add new form element', 'event_espresso' ),
1441
+	__('add new form element', 'event_espresso'),
1442 1442
 
1443 1443
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:117
1444 1444
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:52
1445
-	__( 'Add', 'event_espresso' ),
1445
+	__('Add', 'event_espresso'),
1446 1446
 
1447 1447
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:76
1448
-	__( 'Add Form Element', 'event_espresso' ),
1448
+	__('Add Form Element', 'event_espresso'),
1449 1449
 
1450 1450
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:85
1451
-	__( 'form element order can be changed after adding by using the drag handles in the form element toolbar', 'event_espresso' ),
1451
+	__('form element order can be changed after adding by using the drag handles in the form element toolbar', 'event_espresso'),
1452 1452
 
1453 1453
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:92
1454
-	__( 'load existing form section', 'event_espresso' ),
1454
+	__('load existing form section', 'event_espresso'),
1455 1455
 
1456 1456
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:32
1457
-	__( 'delete form section', 'event_espresso' ),
1457
+	__('delete form section', 'event_espresso'),
1458 1458
 
1459 1459
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:47
1460
-	__( 'form section settings', 'event_espresso' ),
1460
+	__('form section settings', 'event_espresso'),
1461 1461
 
1462 1462
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:57
1463
-	__( 'copy form section', 'event_espresso' ),
1463
+	__('copy form section', 'event_espresso'),
1464 1464
 
1465 1465
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:74
1466
-	__( 'click, hold, and drag to reorder form section', 'event_espresso' ),
1466
+	__('click, hold, and drag to reorder form section', 'event_espresso'),
1467 1467
 
1468 1468
 	// Reference: packages/form-builder/src/FormSection/FormSections.tsx:26
1469
-	__( 'Add Form Section', 'event_espresso' ),
1469
+	__('Add Form Section', 'event_espresso'),
1470 1470
 
1471 1471
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:47
1472
-	__( 'save form section for use in other forms', 'event_espresso' ),
1472
+	__('save form section for use in other forms', 'event_espresso'),
1473 1473
 
1474 1474
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:51
1475
-	__( 'save as', 'event_espresso' ),
1475
+	__('save as', 'event_espresso'),
1476 1476
 
1477 1477
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:55
1478
-	__( 'default', 'event_espresso' ),
1478
+	__('default', 'event_espresso'),
1479 1479
 
1480 1480
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:58
1481
-	__( ' a copy of this form section will be automatically added to ALL new events', 'event_espresso' ),
1481
+	__(' a copy of this form section will be automatically added to ALL new events', 'event_espresso'),
1482 1482
 
1483 1483
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:61
1484
-	__( 'shared', 'event_espresso' ),
1484
+	__('shared', 'event_espresso'),
1485 1485
 
1486 1486
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:64
1487
-	__( 'a copy of this form section will be saved for use in other events but not loaded by default', 'event_espresso' ),
1487
+	__('a copy of this form section will be saved for use in other events but not loaded by default', 'event_espresso'),
1488 1488
 
1489 1489
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:27
1490
-	__( 'show label', 'event_espresso' ),
1490
+	__('show label', 'event_espresso'),
1491 1491
 
1492 1492
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:33
1493
-	__( 'applies to', 'event_espresso' ),
1493
+	__('applies to', 'event_espresso'),
1494 1494
 
1495 1495
 	// Reference: packages/form-builder/src/constants.ts:102
1496 1496
 	// Reference: packages/form-builder/src/state/utils.ts:436
1497
-	__( 'URL', 'event_espresso' ),
1497
+	__('URL', 'event_espresso'),
1498 1498
 
1499 1499
 	// Reference: packages/form-builder/src/constants.ts:104
1500
-	__( 'adds a text input for entering a URL address', 'event_espresso' ),
1500
+	__('adds a text input for entering a URL address', 'event_espresso'),
1501 1501
 
1502 1502
 	// Reference: packages/form-builder/src/constants.ts:107
1503
-	__( 'Date', 'event_espresso' ),
1503
+	__('Date', 'event_espresso'),
1504 1504
 
1505 1505
 	// Reference: packages/form-builder/src/constants.ts:109
1506
-	__( 'adds a text input that allows users to enter a date directly via keyboard or a datepicker', 'event_espresso' ),
1506
+	__('adds a text input that allows users to enter a date directly via keyboard or a datepicker', 'event_espresso'),
1507 1507
 
1508 1508
 	// Reference: packages/form-builder/src/constants.ts:112
1509 1509
 	// Reference: packages/form-builder/src/state/utils.ts:369
1510
-	__( 'Local Date', 'event_espresso' ),
1510
+	__('Local Date', 'event_espresso'),
1511 1511
 
1512 1512
 	// Reference: packages/form-builder/src/constants.ts:117
1513
-	__( 'Month', 'event_espresso' ),
1513
+	__('Month', 'event_espresso'),
1514 1514
 
1515 1515
 	// Reference: packages/form-builder/src/constants.ts:119
1516
-	__( 'adds a text input that allows users to enter a month and year directly via keyboard or a datepicker', 'event_espresso' ),
1516
+	__('adds a text input that allows users to enter a month and year directly via keyboard or a datepicker', 'event_espresso'),
1517 1517
 
1518 1518
 	// Reference: packages/form-builder/src/constants.ts:122
1519
-	__( 'Time', 'event_espresso' ),
1519
+	__('Time', 'event_espresso'),
1520 1520
 
1521 1521
 	// Reference: packages/form-builder/src/constants.ts:124
1522
-	__( 'adds a text input that allows users to enter a time directly via keyboard or a timepicker', 'event_espresso' ),
1522
+	__('adds a text input that allows users to enter a time directly via keyboard or a timepicker', 'event_espresso'),
1523 1523
 
1524 1524
 	// Reference: packages/form-builder/src/constants.ts:127
1525
-	__( 'Week', 'event_espresso' ),
1525
+	__('Week', 'event_espresso'),
1526 1526
 
1527 1527
 	// Reference: packages/form-builder/src/constants.ts:129
1528
-	__( 'adds a text input that allows users to enter a week and year directly via keyboard or a datepicker', 'event_espresso' ),
1528
+	__('adds a text input that allows users to enter a week and year directly via keyboard or a datepicker', 'event_espresso'),
1529 1529
 
1530 1530
 	// Reference: packages/form-builder/src/constants.ts:132
1531
-	__( 'Day Selector', 'event_espresso' ),
1531
+	__('Day Selector', 'event_espresso'),
1532 1532
 
1533 1533
 	// Reference: packages/form-builder/src/constants.ts:134
1534
-	__( 'adds a dropdown selector that allows users to select the day of the month (01 to 31)', 'event_espresso' ),
1534
+	__('adds a dropdown selector that allows users to select the day of the month (01 to 31)', 'event_espresso'),
1535 1535
 
1536 1536
 	// Reference: packages/form-builder/src/constants.ts:137
1537
-	__( 'Month Selector', 'event_espresso' ),
1537
+	__('Month Selector', 'event_espresso'),
1538 1538
 
1539 1539
 	// Reference: packages/form-builder/src/constants.ts:139
1540
-	__( 'adds a dropdown selector that allows users to select the month of the year (01 to 12)', 'event_espresso' ),
1540
+	__('adds a dropdown selector that allows users to select the month of the year (01 to 12)', 'event_espresso'),
1541 1541
 
1542 1542
 	// Reference: packages/form-builder/src/constants.ts:142
1543
-	__( 'Year Selector', 'event_espresso' ),
1543
+	__('Year Selector', 'event_espresso'),
1544 1544
 
1545 1545
 	// Reference: packages/form-builder/src/constants.ts:144
1546
-	__( 'adds a dropdown selector that allows users to select the year from a configurable range', 'event_espresso' ),
1546
+	__('adds a dropdown selector that allows users to select the year from a configurable range', 'event_espresso'),
1547 1547
 
1548 1548
 	// Reference: packages/form-builder/src/constants.ts:147
1549
-	__( 'Radio Buttons', 'event_espresso' ),
1549
+	__('Radio Buttons', 'event_espresso'),
1550 1550
 
1551 1551
 	// Reference: packages/form-builder/src/constants.ts:149
1552
-	__( 'adds one or more radio buttons that allow users to only select one option from those provided', 'event_espresso' ),
1552
+	__('adds one or more radio buttons that allow users to only select one option from those provided', 'event_espresso'),
1553 1553
 
1554 1554
 	// Reference: packages/form-builder/src/constants.ts:152
1555 1555
 	// Reference: packages/form-builder/src/state/utils.ts:375
1556
-	__( 'Decimal Number', 'event_espresso' ),
1556
+	__('Decimal Number', 'event_espresso'),
1557 1557
 
1558 1558
 	// Reference: packages/form-builder/src/constants.ts:154
1559
-	__( 'adds a text input that only accepts numbers whose value is a decimal (float)', 'event_espresso' ),
1559
+	__('adds a text input that only accepts numbers whose value is a decimal (float)', 'event_espresso'),
1560 1560
 
1561 1561
 	// Reference: packages/form-builder/src/constants.ts:157
1562 1562
 	// Reference: packages/form-builder/src/state/utils.ts:378
1563
-	__( 'Whole Number', 'event_espresso' ),
1563
+	__('Whole Number', 'event_espresso'),
1564 1564
 
1565 1565
 	// Reference: packages/form-builder/src/constants.ts:159
1566
-	__( 'adds a text input that only accepts numbers whose value is an integer (whole number)', 'event_espresso' ),
1566
+	__('adds a text input that only accepts numbers whose value is an integer (whole number)', 'event_espresso'),
1567 1567
 
1568 1568
 	// Reference: packages/form-builder/src/constants.ts:162
1569
-	__( 'Number Range', 'event_espresso' ),
1569
+	__('Number Range', 'event_espresso'),
1570 1570
 
1571 1571
 	// Reference: packages/form-builder/src/constants.ts:167
1572
-	__( 'Phone Number', 'event_espresso' ),
1572
+	__('Phone Number', 'event_espresso'),
1573 1573
 
1574 1574
 	// Reference: packages/form-builder/src/constants.ts:172
1575
-	__( 'Dropdown', 'event_espresso' ),
1575
+	__('Dropdown', 'event_espresso'),
1576 1576
 
1577 1577
 	// Reference: packages/form-builder/src/constants.ts:174
1578
-	__( 'adds a dropdown selector that accepts a single value', 'event_espresso' ),
1578
+	__('adds a dropdown selector that accepts a single value', 'event_espresso'),
1579 1579
 
1580 1580
 	// Reference: packages/form-builder/src/constants.ts:177
1581
-	__( 'Multi Select', 'event_espresso' ),
1581
+	__('Multi Select', 'event_espresso'),
1582 1582
 
1583 1583
 	// Reference: packages/form-builder/src/constants.ts:179
1584
-	__( 'adds a dropdown selector that accepts multiple values', 'event_espresso' ),
1584
+	__('adds a dropdown selector that accepts multiple values', 'event_espresso'),
1585 1585
 
1586 1586
 	// Reference: packages/form-builder/src/constants.ts:182
1587
-	__( 'Toggle/Switch', 'event_espresso' ),
1587
+	__('Toggle/Switch', 'event_espresso'),
1588 1588
 
1589 1589
 	// Reference: packages/form-builder/src/constants.ts:184
1590
-	__( 'adds a toggle or a switch to accept true or false value', 'event_espresso' ),
1590
+	__('adds a toggle or a switch to accept true or false value', 'event_espresso'),
1591 1591
 
1592 1592
 	// Reference: packages/form-builder/src/constants.ts:187
1593
-	__( 'Multi Checkbox', 'event_espresso' ),
1593
+	__('Multi Checkbox', 'event_espresso'),
1594 1594
 
1595 1595
 	// Reference: packages/form-builder/src/constants.ts:189
1596
-	__( 'adds checkboxes that allow users to select zero or more options from those provided', 'event_espresso' ),
1596
+	__('adds checkboxes that allow users to select zero or more options from those provided', 'event_espresso'),
1597 1597
 
1598 1598
 	// Reference: packages/form-builder/src/constants.ts:192
1599
-	__( 'Country Selector', 'event_espresso' ),
1599
+	__('Country Selector', 'event_espresso'),
1600 1600
 
1601 1601
 	// Reference: packages/form-builder/src/constants.ts:194
1602
-	__( 'adds a dropdown selector populated with names of countries that are enabled for the site', 'event_espresso' ),
1602
+	__('adds a dropdown selector populated with names of countries that are enabled for the site', 'event_espresso'),
1603 1603
 
1604 1604
 	// Reference: packages/form-builder/src/constants.ts:197
1605
-	__( 'State Selector', 'event_espresso' ),
1605
+	__('State Selector', 'event_espresso'),
1606 1606
 
1607 1607
 	// Reference: packages/form-builder/src/constants.ts:202
1608
-	__( 'Button', 'event_espresso' ),
1608
+	__('Button', 'event_espresso'),
1609 1609
 
1610 1610
 	// Reference: packages/form-builder/src/constants.ts:204
1611
-	__( 'adds a button to the form that can be used for triggering fucntionality (requires custom coding)', 'event_espresso' ),
1611
+	__('adds a button to the form that can be used for triggering fucntionality (requires custom coding)', 'event_espresso'),
1612 1612
 
1613 1613
 	// Reference: packages/form-builder/src/constants.ts:207
1614
-	__( 'Reset Button', 'event_espresso' ),
1614
+	__('Reset Button', 'event_espresso'),
1615 1615
 
1616 1616
 	// Reference: packages/form-builder/src/constants.ts:209
1617
-	__( 'adds a button that will reset the form back to its original state.', 'event_espresso' ),
1617
+	__('adds a button that will reset the form back to its original state.', 'event_espresso'),
1618 1618
 
1619 1619
 	// Reference: packages/form-builder/src/constants.ts:55
1620
-	__( 'Form Section', 'event_espresso' ),
1620
+	__('Form Section', 'event_espresso'),
1621 1621
 
1622 1622
 	// Reference: packages/form-builder/src/constants.ts:57
1623
-	__( 'Used for creating logical groupings for questions and form elements. Need to add a heading or description? Use the HTML form element.', 'event_espresso' ),
1623
+	__('Used for creating logical groupings for questions and form elements. Need to add a heading or description? Use the HTML form element.', 'event_espresso'),
1624 1624
 
1625 1625
 	// Reference: packages/form-builder/src/constants.ts:62
1626
-	__( 'HTML Block', 'event_espresso' ),
1626
+	__('HTML Block', 'event_espresso'),
1627 1627
 
1628 1628
 	// Reference: packages/form-builder/src/constants.ts:64
1629
-	__( 'allows you to add HTML like headings or text paragraphs to your form', 'event_espresso' ),
1629
+	__('allows you to add HTML like headings or text paragraphs to your form', 'event_espresso'),
1630 1630
 
1631 1631
 	// Reference: packages/form-builder/src/constants.ts:69
1632
-	__( 'adds a text input that only accepts plain text', 'event_espresso' ),
1632
+	__('adds a text input that only accepts plain text', 'event_espresso'),
1633 1633
 
1634 1634
 	// Reference: packages/form-builder/src/constants.ts:72
1635
-	__( 'Plain Text Area', 'event_espresso' ),
1635
+	__('Plain Text Area', 'event_espresso'),
1636 1636
 
1637 1637
 	// Reference: packages/form-builder/src/constants.ts:74
1638
-	__( 'adds a textarea block that only accepts plain text', 'event_espresso' ),
1638
+	__('adds a textarea block that only accepts plain text', 'event_espresso'),
1639 1639
 
1640 1640
 	// Reference: packages/form-builder/src/constants.ts:77
1641
-	__( 'HTML Text Area', 'event_espresso' ),
1641
+	__('HTML Text Area', 'event_espresso'),
1642 1642
 
1643 1643
 	// Reference: packages/form-builder/src/constants.ts:79
1644
-	__( 'adds a textarea block that accepts text including simple HTML markup', 'event_espresso' ),
1644
+	__('adds a textarea block that accepts text including simple HTML markup', 'event_espresso'),
1645 1645
 
1646 1646
 	// Reference: packages/form-builder/src/constants.ts:84
1647
-	__( 'adds a text input that only accepts a valid email address', 'event_espresso' ),
1647
+	__('adds a text input that only accepts a valid email address', 'event_espresso'),
1648 1648
 
1649 1649
 	// Reference: packages/form-builder/src/constants.ts:87
1650
-	__( 'Email Confirmation', 'event_espresso' ),
1650
+	__('Email Confirmation', 'event_espresso'),
1651 1651
 
1652 1652
 	// Reference: packages/form-builder/src/constants.ts:92
1653
-	__( 'Password', 'event_espresso' ),
1653
+	__('Password', 'event_espresso'),
1654 1654
 
1655 1655
 	// Reference: packages/form-builder/src/constants.ts:94
1656
-	__( 'adds a text input that accepts text but masks what the user enters', 'event_espresso' ),
1656
+	__('adds a text input that accepts text but masks what the user enters', 'event_espresso'),
1657 1657
 
1658 1658
 	// Reference: packages/form-builder/src/constants.ts:97
1659
-	__( 'Password Confirmation', 'event_espresso' ),
1659
+	__('Password Confirmation', 'event_espresso'),
1660 1660
 
1661 1661
 	// Reference: packages/form-builder/src/data/useElementMutator.ts:54
1662
-	__( 'element', 'event_espresso' ),
1662
+	__('element', 'event_espresso'),
1663 1663
 
1664 1664
 	// Reference: packages/form-builder/src/data/useSectionMutator.ts:54
1665
-	__( 'section', 'event_espresso' ),
1665
+	__('section', 'event_espresso'),
1666 1666
 
1667 1667
 	// Reference: packages/form-builder/src/state/utils.ts:360
1668
-	__( 'click', 'event_espresso' ),
1668
+	__('click', 'event_espresso'),
1669 1669
 
1670 1670
 	// Reference: packages/form-builder/src/state/utils.ts:363
1671
-	__( 'checkboxes', 'event_espresso' ),
1671
+	__('checkboxes', 'event_espresso'),
1672 1672
 
1673 1673
 	// Reference: packages/form-builder/src/state/utils.ts:366
1674
-	__( 'date', 'event_espresso' ),
1674
+	__('date', 'event_espresso'),
1675 1675
 
1676 1676
 	// Reference: packages/form-builder/src/state/utils.ts:372
1677
-	__( 'day', 'event_espresso' ),
1677
+	__('day', 'event_espresso'),
1678 1678
 
1679 1679
 	// Reference: packages/form-builder/src/state/utils.ts:381
1680
-	__( 'email address', 'event_espresso' ),
1680
+	__('email address', 'event_espresso'),
1681 1681
 
1682 1682
 	// Reference: packages/form-builder/src/state/utils.ts:384
1683
-	__( 'confirm email address', 'event_espresso' ),
1683
+	__('confirm email address', 'event_espresso'),
1684 1684
 
1685 1685
 	// Reference: packages/form-builder/src/state/utils.ts:388
1686
-	__( 'month', 'event_espresso' ),
1686
+	__('month', 'event_espresso'),
1687 1687
 
1688 1688
 	// Reference: packages/form-builder/src/state/utils.ts:391
1689
-	__( 'password', 'event_espresso' ),
1689
+	__('password', 'event_espresso'),
1690 1690
 
1691 1691
 	// Reference: packages/form-builder/src/state/utils.ts:394
1692
-	__( 'confirm password', 'event_espresso' ),
1692
+	__('confirm password', 'event_espresso'),
1693 1693
 
1694 1694
 	// Reference: packages/form-builder/src/state/utils.ts:397
1695
-	__( 'radio buttons', 'event_espresso' ),
1695
+	__('radio buttons', 'event_espresso'),
1696 1696
 
1697 1697
 	// Reference: packages/form-builder/src/state/utils.ts:400
1698
-	__( 'number range', 'event_espresso' ),
1698
+	__('number range', 'event_espresso'),
1699 1699
 
1700 1700
 	// Reference: packages/form-builder/src/state/utils.ts:403
1701
-	__( 'selection dropdown', 'event_espresso' ),
1701
+	__('selection dropdown', 'event_espresso'),
1702 1702
 
1703 1703
 	// Reference: packages/form-builder/src/state/utils.ts:406
1704
-	__( 'country', 'event_espresso' ),
1704
+	__('country', 'event_espresso'),
1705 1705
 
1706 1706
 	// Reference: packages/form-builder/src/state/utils.ts:409
1707
-	__( 'multi-select dropdown', 'event_espresso' ),
1707
+	__('multi-select dropdown', 'event_espresso'),
1708 1708
 
1709 1709
 	// Reference: packages/form-builder/src/state/utils.ts:412
1710
-	__( 'state/province', 'event_espresso' ),
1710
+	__('state/province', 'event_espresso'),
1711 1711
 
1712 1712
 	// Reference: packages/form-builder/src/state/utils.ts:415
1713
-	__( 'on/off switch', 'event_espresso' ),
1713
+	__('on/off switch', 'event_espresso'),
1714 1714
 
1715 1715
 	// Reference: packages/form-builder/src/state/utils.ts:418
1716
-	__( 'reset', 'event_espresso' ),
1716
+	__('reset', 'event_espresso'),
1717 1717
 
1718 1718
 	// Reference: packages/form-builder/src/state/utils.ts:421
1719
-	__( 'phone number', 'event_espresso' ),
1719
+	__('phone number', 'event_espresso'),
1720 1720
 
1721 1721
 	// Reference: packages/form-builder/src/state/utils.ts:424
1722
-	__( 'text', 'event_espresso' ),
1722
+	__('text', 'event_espresso'),
1723 1723
 
1724 1724
 	// Reference: packages/form-builder/src/state/utils.ts:427
1725
-	__( 'simple textarea', 'event_espresso' ),
1725
+	__('simple textarea', 'event_espresso'),
1726 1726
 
1727 1727
 	// Reference: packages/form-builder/src/state/utils.ts:430
1728
-	__( 'html textarea', 'event_espresso' ),
1728
+	__('html textarea', 'event_espresso'),
1729 1729
 
1730 1730
 	// Reference: packages/form-builder/src/state/utils.ts:439
1731
-	__( 'week', 'event_espresso' ),
1731
+	__('week', 'event_espresso'),
1732 1732
 
1733 1733
 	// Reference: packages/form-builder/src/state/utils.ts:442
1734
-	__( 'year', 'event_espresso' ),
1734
+	__('year', 'event_espresso'),
1735 1735
 
1736 1736
 	// Reference: packages/form/src/adapters/WPMediaImage.tsx:12
1737
-	__( 'Select Image', 'event_espresso' ),
1737
+	__('Select Image', 'event_espresso'),
1738 1738
 
1739 1739
 	// Reference: packages/form/src/adapters/WPMediaImage.tsx:44
1740 1740
 	// Reference: packages/rich-text-editor/src/components/AdvancedTextEditor/toolbarButtons/WPMedia.tsx:11
1741 1741
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:12
1742 1742
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityTemplate.tsx:32
1743
-	__( 'Select', 'event_espresso' ),
1743
+	__('Select', 'event_espresso'),
1744 1744
 
1745 1745
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:36
1746 1746
 	/* translators: %d the entry number */
1747
-	__( 'Entry %d', 'event_espresso' ),
1747
+	__('Entry %d', 'event_espresso'),
1748 1748
 
1749 1749
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:11
1750 1750
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:17
1751
-	__( 'sold out', 'event_espresso' ),
1751
+	__('sold out', 'event_espresso'),
1752 1752
 
1753 1753
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:14
1754 1754
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:14
1755
-	__( 'expired', 'event_espresso' ),
1755
+	__('expired', 'event_espresso'),
1756 1756
 
1757 1757
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:17
1758
-	__( 'upcoming', 'event_espresso' ),
1758
+	__('upcoming', 'event_espresso'),
1759 1759
 
1760 1760
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:20
1761
-	__( 'active', 'event_espresso' ),
1761
+	__('active', 'event_espresso'),
1762 1762
 
1763 1763
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:23
1764 1764
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:11
1765
-	__( 'trashed', 'event_espresso' ),
1765
+	__('trashed', 'event_espresso'),
1766 1766
 
1767 1767
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:26
1768
-	__( 'cancelled', 'event_espresso' ),
1768
+	__('cancelled', 'event_espresso'),
1769 1769
 
1770 1770
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:29
1771
-	__( 'postponed', 'event_espresso' ),
1771
+	__('postponed', 'event_espresso'),
1772 1772
 
1773 1773
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:33
1774
-	__( 'inactive', 'event_espresso' ),
1774
+	__('inactive', 'event_espresso'),
1775 1775
 
1776 1776
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:20
1777
-	__( 'pending', 'event_espresso' ),
1777
+	__('pending', 'event_espresso'),
1778 1778
 
1779 1779
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:23
1780
-	__( 'on sale', 'event_espresso' ),
1780
+	__('on sale', 'event_espresso'),
1781 1781
 
1782 1782
 	// Reference: packages/helpers/src/tickets/ticketVisibilityOptions.ts:6
1783
-	__( 'Where the ticket can be viewed throughout the UI. ', 'event_espresso' ),
1783
+	__('Where the ticket can be viewed throughout the UI. ', 'event_espresso'),
1784 1784
 
1785 1785
 	// Reference: packages/predicates/src/registration/statusOptions.ts:16
1786
-	__( 'Declined', 'event_espresso' ),
1786
+	__('Declined', 'event_espresso'),
1787 1787
 
1788 1788
 	// Reference: packages/predicates/src/registration/statusOptions.ts:21
1789
-	__( 'Incomplete', 'event_espresso' ),
1789
+	__('Incomplete', 'event_espresso'),
1790 1790
 
1791 1791
 	// Reference: packages/predicates/src/registration/statusOptions.ts:26
1792
-	__( 'Not Approved', 'event_espresso' ),
1792
+	__('Not Approved', 'event_espresso'),
1793 1793
 
1794 1794
 	// Reference: packages/predicates/src/registration/statusOptions.ts:31
1795
-	__( 'Pending Payment', 'event_espresso' ),
1795
+	__('Pending Payment', 'event_espresso'),
1796 1796
 
1797 1797
 	// Reference: packages/predicates/src/registration/statusOptions.ts:36
1798
-	__( 'Wait List', 'event_espresso' ),
1798
+	__('Wait List', 'event_espresso'),
1799 1799
 
1800 1800
 	// Reference: packages/predicates/src/registration/statusOptions.ts:6
1801
-	__( 'Approved', 'event_espresso' ),
1801
+	__('Approved', 'event_espresso'),
1802 1802
 
1803 1803
 	// Reference: packages/rich-text-editor/src/components/AdvancedTextEditor/toolbarButtons/WPMedia.tsx:9
1804 1804
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:10
1805
-	__( 'Select media', 'event_espresso' ),
1805
+	__('Select media', 'event_espresso'),
1806 1806
 
1807 1807
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/RichTextEditor.tsx:84
1808
-	__( 'Write something…', 'event_espresso' ),
1808
+	__('Write something…', 'event_espresso'),
1809 1809
 
1810 1810
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/Toolbar.tsx:20
1811
-	__( 'RTE Toolbar', 'event_espresso' ),
1811
+	__('RTE Toolbar', 'event_espresso'),
1812 1812
 
1813 1813
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:11
1814
-	__( 'Normal', 'event_espresso' ),
1814
+	__('Normal', 'event_espresso'),
1815 1815
 
1816 1816
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:12
1817
-	__( 'H1', 'event_espresso' ),
1817
+	__('H1', 'event_espresso'),
1818 1818
 
1819 1819
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:13
1820
-	__( 'H2', 'event_espresso' ),
1820
+	__('H2', 'event_espresso'),
1821 1821
 
1822 1822
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:14
1823
-	__( 'H3', 'event_espresso' ),
1823
+	__('H3', 'event_espresso'),
1824 1824
 
1825 1825
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:15
1826
-	__( 'H4', 'event_espresso' ),
1826
+	__('H4', 'event_espresso'),
1827 1827
 
1828 1828
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:16
1829
-	__( 'H5', 'event_espresso' ),
1829
+	__('H5', 'event_espresso'),
1830 1830
 
1831 1831
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:17
1832
-	__( 'H6', 'event_espresso' ),
1832
+	__('H6', 'event_espresso'),
1833 1833
 
1834 1834
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:18
1835
-	__( 'Block quote', 'event_espresso' ),
1835
+	__('Block quote', 'event_espresso'),
1836 1836
 
1837 1837
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:19
1838
-	__( 'Code', 'event_espresso' ),
1838
+	__('Code', 'event_espresso'),
1839 1839
 
1840 1840
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:36
1841
-	__( 'Set color', 'event_espresso' ),
1841
+	__('Set color', 'event_espresso'),
1842 1842
 
1843 1843
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:45
1844
-	__( 'Text color', 'event_espresso' ),
1844
+	__('Text color', 'event_espresso'),
1845 1845
 
1846 1846
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:47
1847
-	__( 'Background color', 'event_espresso' ),
1847
+	__('Background color', 'event_espresso'),
1848 1848
 
1849 1849
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:39
1850
-	__( 'Add image', 'event_espresso' ),
1850
+	__('Add image', 'event_espresso'),
1851 1851
 
1852 1852
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:51
1853
-	__( 'Image URL', 'event_espresso' ),
1853
+	__('Image URL', 'event_espresso'),
1854 1854
 
1855 1855
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:55
1856
-	__( 'Alt text', 'event_espresso' ),
1856
+	__('Alt text', 'event_espresso'),
1857 1857
 
1858 1858
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:56
1859
-	__( 'Width', 'event_espresso' ),
1859
+	__('Width', 'event_espresso'),
1860 1860
 
1861 1861
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:60
1862
-	__( 'Height', 'event_espresso' ),
1862
+	__('Height', 'event_espresso'),
1863 1863
 
1864 1864
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/link/Component.tsx:54
1865
-	__( 'Edit link', 'event_espresso' ),
1865
+	__('Edit link', 'event_espresso'),
1866 1866
 
1867 1867
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/link/Component.tsx:64
1868
-	__( 'URL title', 'event_espresso' ),
1868
+	__('URL title', 'event_espresso'),
1869 1869
 
1870 1870
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:11
1871
-	__( 'Unordered list', 'event_espresso' ),
1871
+	__('Unordered list', 'event_espresso'),
1872 1872
 
1873 1873
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:12
1874
-	__( 'Ordered list', 'event_espresso' ),
1874
+	__('Ordered list', 'event_espresso'),
1875 1875
 
1876 1876
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:13
1877 1877
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:13
1878
-	__( 'Indent', 'event_espresso' ),
1878
+	__('Indent', 'event_espresso'),
1879 1879
 
1880 1880
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:14
1881 1881
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:14
1882
-	__( 'Outdent', 'event_espresso' ),
1882
+	__('Outdent', 'event_espresso'),
1883 1883
 
1884 1884
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:11
1885
-	__( 'Unordered textalign', 'event_espresso' ),
1885
+	__('Unordered textalign', 'event_espresso'),
1886 1886
 
1887 1887
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:12
1888
-	__( 'Ordered textalign', 'event_espresso' ),
1888
+	__('Ordered textalign', 'event_espresso'),
1889 1889
 
1890 1890
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/render/Image/Toolbar.tsx:32
1891
-	__( 'Image toolbar', 'event_espresso' ),
1891
+	__('Image toolbar', 'event_espresso'),
1892 1892
 
1893 1893
 	// Reference: packages/rich-text-editor/src/components/WithEditMode/WithEditMode.tsx:62
1894 1894
 	// Reference: packages/rich-text-editor/src/rte-old/components/RTEWithEditMode/RTEWithEditMode.tsx:35
1895
-	__( 'Visual editor', 'event_espresso' ),
1895
+	__('Visual editor', 'event_espresso'),
1896 1896
 
1897 1897
 	// Reference: packages/rich-text-editor/src/components/WithEditMode/WithEditMode.tsx:66
1898 1898
 	// Reference: packages/rich-text-editor/src/rte-old/components/RTEWithEditMode/RTEWithEditMode.tsx:39
1899
-	__( 'HTML editor', 'event_espresso' ),
1899
+	__('HTML editor', 'event_espresso'),
1900 1900
 
1901 1901
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:68
1902
-	__( 'Add Media', 'event_espresso' ),
1902
+	__('Add Media', 'event_espresso'),
1903 1903
 
1904 1904
 	// Reference: packages/tpc/src/buttons/AddPriceModifierButton.tsx:16
1905
-	__( 'add new price modifier after this row', 'event_espresso' ),
1905
+	__('add new price modifier after this row', 'event_espresso'),
1906 1906
 
1907 1907
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:14
1908
-	__( 'Delete all prices', 'event_espresso' ),
1908
+	__('Delete all prices', 'event_espresso'),
1909 1909
 
1910 1910
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:27
1911
-	__( 'Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso' ),
1911
+	__('Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso'),
1912 1912
 
1913 1913
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:31
1914
-	__( 'Delete all prices?', 'event_espresso' ),
1914
+	__('Delete all prices?', 'event_espresso'),
1915 1915
 
1916 1916
 	// Reference: packages/tpc/src/buttons/DeletePriceModifierButton.tsx:12
1917
-	__( 'delete price modifier', 'event_espresso' ),
1917
+	__('delete price modifier', 'event_espresso'),
1918 1918
 
1919 1919
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:14
1920
-	__( 'Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso' ),
1920
+	__('Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso'),
1921 1921
 
1922 1922
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:17
1923
-	__( 'Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso' ),
1923
+	__('Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso'),
1924 1924
 
1925 1925
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:21
1926
-	__( 'Disable reverse calculate', 'event_espresso' ),
1926
+	__('Disable reverse calculate', 'event_espresso'),
1927 1927
 
1928 1928
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:21
1929
-	__( 'Enable reverse calculate', 'event_espresso' ),
1929
+	__('Enable reverse calculate', 'event_espresso'),
1930 1930
 
1931 1931
 	// Reference: packages/tpc/src/buttons/TicketPriceCalculatorButton.tsx:28
1932
-	__( 'ticket price calculator', 'event_espresso' ),
1932
+	__('ticket price calculator', 'event_espresso'),
1933 1933
 
1934 1934
 	// Reference: packages/tpc/src/buttons/taxes/AddDefaultTaxesButton.tsx:9
1935
-	__( 'Add default taxes', 'event_espresso' ),
1935
+	__('Add default taxes', 'event_espresso'),
1936 1936
 
1937 1937
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:10
1938
-	__( 'Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso' ),
1938
+	__('Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso'),
1939 1939
 
1940 1940
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:14
1941
-	__( 'Remove all taxes?', 'event_espresso' ),
1941
+	__('Remove all taxes?', 'event_espresso'),
1942 1942
 
1943 1943
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:7
1944
-	__( 'Remove taxes', 'event_espresso' ),
1944
+	__('Remove taxes', 'event_espresso'),
1945 1945
 
1946 1946
 	// Reference: packages/tpc/src/components/AddDefaultPricesButton.tsx:9
1947
-	__( 'Add default prices', 'event_espresso' ),
1947
+	__('Add default prices', 'event_espresso'),
1948 1948
 
1949 1949
 	// Reference: packages/tpc/src/components/DefaultPricesInfo.tsx:29
1950
-	__( 'Modify default prices.', 'event_espresso' ),
1950
+	__('Modify default prices.', 'event_espresso'),
1951 1951
 
1952 1952
 	// Reference: packages/tpc/src/components/DefaultTaxesInfo.tsx:29
1953
-	__( 'New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso' ),
1953
+	__('New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso'),
1954 1954
 
1955 1955
 	// Reference: packages/tpc/src/components/LockedTicketsBanner.tsx:12
1956 1956
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:74
1957
-	__( 'Price editing is disabled!', 'event_espresso' ),
1957
+	__('Price editing is disabled!', 'event_espresso'),
1958 1958
 
1959 1959
 	// Reference: packages/tpc/src/components/NoPriceTypesBanner.tsx:12
1960
-	__( 'One or more price types are missing. Maybe they were placed in the trash?', 'event_espresso' ),
1960
+	__('One or more price types are missing. Maybe they were placed in the trash?', 'event_espresso'),
1961 1961
 
1962 1962
 	// Reference: packages/tpc/src/components/NoPriceTypesBanner.tsx:17
1963 1963
 	/* translators: %s link to price types admin */
1964
-	__( 'Go to the%sto restore (untrash) your price types and/or create some new ones.', 'event_espresso' ),
1964
+	__('Go to the%sto restore (untrash) your price types and/or create some new ones.', 'event_espresso'),
1965 1965
 
1966 1966
 	// Reference: packages/tpc/src/components/NoPriceTypesBanner.tsx:18
1967
-	__( 'price types admin page', 'event_espresso' ),
1967
+	__('price types admin page', 'event_espresso'),
1968 1968
 
1969 1969
 	// Reference: packages/tpc/src/components/NoPriceTypesBanner.tsx:26
1970
-	__( 'Missing Price Types!', 'event_espresso' ),
1970
+	__('Missing Price Types!', 'event_espresso'),
1971 1971
 
1972 1972
 	// Reference: packages/tpc/src/components/NoPricesBanner.tsx:14
1973
-	__( 'This Ticket is Currently Free', 'event_espresso' ),
1973
+	__('This Ticket is Currently Free', 'event_espresso'),
1974 1974
 
1975 1975
 	// Reference: packages/tpc/src/components/NoPricesBanner.tsx:21
1976 1976
 	/* translators: %s default prices */
1977
-	__( 'Click the button below to load your %s into the calculator.', 'event_espresso' ),
1977
+	__('Click the button below to load your %s into the calculator.', 'event_espresso'),
1978 1978
 
1979 1979
 	// Reference: packages/tpc/src/components/NoPricesBanner.tsx:22
1980
-	__( 'default prices', 'event_espresso' ),
1980
+	__('default prices', 'event_espresso'),
1981 1981
 
1982 1982
 	// Reference: packages/tpc/src/components/NoPricesBanner.tsx:29
1983
-	__( 'Additional ticket price modifiers can be added or removed.', 'event_espresso' ),
1983
+	__('Additional ticket price modifiers can be added or removed.', 'event_espresso'),
1984 1984
 
1985 1985
 	// Reference: packages/tpc/src/components/NoPricesBanner.tsx:31
1986
-	__( 'Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso' ),
1986
+	__('Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso'),
1987 1987
 
1988 1988
 	// Reference: packages/tpc/src/components/TicketPriceCalculatorModal.tsx:22
1989 1989
 	// Reference: packages/ui-components/src/Confirm/ConfirmClose.tsx:7
1990 1990
 	// Reference: packages/ui-components/src/Confirm/useConfirmWithButton.tsx:10
1991 1991
 	// Reference: packages/ui-components/src/Confirm/useConfirmationDialog.tsx:52
1992
-	__( 'Changes will be lost if you proceed.', 'event_espresso' ),
1992
+	__('Changes will be lost if you proceed.', 'event_espresso'),
1993 1993
 
1994 1994
 	// Reference: packages/tpc/src/components/TicketPriceCalculatorModal.tsx:33
1995 1995
 	/* translators: %s ticket name */
1996
-	__( 'Price Calculator for Ticket: %s', 'event_espresso' ),
1996
+	__('Price Calculator for Ticket: %s', 'event_espresso'),
1997 1997
 
1998 1998
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:48
1999
-	__( 'Total', 'event_espresso' ),
1999
+	__('Total', 'event_espresso'),
2000 2000
 
2001 2001
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:57
2002
-	__( 'ticket total', 'event_espresso' ),
2002
+	__('ticket total', 'event_espresso'),
2003 2003
 
2004 2004
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:29
2005
-	__( 'Order', 'event_espresso' ),
2005
+	__('Order', 'event_espresso'),
2006 2006
 
2007 2007
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:35
2008
-	__( 'Price Type', 'event_espresso' ),
2008
+	__('Price Type', 'event_espresso'),
2009 2009
 
2010 2010
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:41
2011
-	__( 'Label', 'event_espresso' ),
2011
+	__('Label', 'event_espresso'),
2012 2012
 
2013 2013
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:53
2014
-	__( 'Amount', 'event_espresso' ),
2014
+	__('Amount', 'event_espresso'),
2015 2015
 
2016 2016
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:22
2017
-	__( 'Copy ticket', 'event_espresso' ),
2017
+	__('Copy ticket', 'event_espresso'),
2018 2018
 
2019 2019
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:26
2020
-	__( 'Copy and archive this ticket', 'event_espresso' ),
2020
+	__('Copy and archive this ticket', 'event_espresso'),
2021 2021
 
2022 2022
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:29
2023
-	__( 'OK', 'event_espresso' ),
2023
+	__('OK', 'event_espresso'),
2024 2024
 
2025 2025
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:34
2026
-	__( 'amount', 'event_espresso' ),
2026
+	__('amount', 'event_espresso'),
2027 2027
 
2028 2028
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:46
2029
-	__( 'amount…', 'event_espresso' ),
2029
+	__('amount…', 'event_espresso'),
2030 2030
 
2031 2031
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:14
2032
-	__( 'description…', 'event_espresso' ),
2032
+	__('description…', 'event_espresso'),
2033 2033
 
2034 2034
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:9
2035
-	__( 'price description', 'event_espresso' ),
2035
+	__('price description', 'event_espresso'),
2036 2036
 
2037 2037
 	// Reference: packages/tpc/src/inputs/PriceIdInput.tsx:6
2038
-	__( 'price id', 'event_espresso' ),
2038
+	__('price id', 'event_espresso'),
2039 2039
 
2040 2040
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:13
2041
-	__( 'label…', 'event_espresso' ),
2041
+	__('label…', 'event_espresso'),
2042 2042
 
2043 2043
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:8
2044
-	__( 'price name', 'event_espresso' ),
2044
+	__('price name', 'event_espresso'),
2045 2045
 
2046 2046
 	// Reference: packages/tpc/src/inputs/PriceOrderInput.tsx:14
2047
-	__( 'price order', 'event_espresso' ),
2047
+	__('price order', 'event_espresso'),
2048 2048
 
2049 2049
 	// Reference: packages/tpc/src/utils/constants.ts:8
2050
-	__( 'Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then trash the old tickets.', 'event_espresso' ),
2050
+	__('Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then trash the old tickets.', 'event_espresso'),
2051 2051
 
2052 2052
 	// Reference: packages/ui-components/src/ActiveFilters/ActiveFilters.tsx:8
2053
-	__( 'active filters:', 'event_espresso' ),
2053
+	__('active filters:', 'event_espresso'),
2054 2054
 
2055 2055
 	// Reference: packages/ui-components/src/ActiveFilters/FilterTag/index.tsx:15
2056 2056
 	/* translators: %s filter name */
2057
-	__( 'remove filter - %s', 'event_espresso' ),
2057
+	__('remove filter - %s', 'event_espresso'),
2058 2058
 
2059 2059
 	// Reference: packages/ui-components/src/Address/Address.tsx:72
2060
-	__( 'Address:', 'event_espresso' ),
2060
+	__('Address:', 'event_espresso'),
2061 2061
 
2062 2062
 	// Reference: packages/ui-components/src/Address/Address.tsx:80
2063
-	__( 'City:', 'event_espresso' ),
2063
+	__('City:', 'event_espresso'),
2064 2064
 
2065 2065
 	// Reference: packages/ui-components/src/Address/Address.tsx:86
2066
-	__( 'State:', 'event_espresso' ),
2066
+	__('State:', 'event_espresso'),
2067 2067
 
2068 2068
 	// Reference: packages/ui-components/src/Address/Address.tsx:92
2069
-	__( 'Country:', 'event_espresso' ),
2069
+	__('Country:', 'event_espresso'),
2070 2070
 
2071 2071
 	// Reference: packages/ui-components/src/Address/Address.tsx:98
2072
-	__( 'Zip:', 'event_espresso' ),
2072
+	__('Zip:', 'event_espresso'),
2073 2073
 
2074 2074
 	// Reference: packages/ui-components/src/CalendarDateRange/CalendarDateRange.tsx:37
2075
-	__( 'to', 'event_espresso' ),
2075
+	__('to', 'event_espresso'),
2076 2076
 
2077 2077
 	// Reference: packages/ui-components/src/CalendarPageDate/CalendarPageDate.tsx:54
2078
-	__( 'TO', 'event_espresso' ),
2078
+	__('TO', 'event_espresso'),
2079 2079
 
2080 2080
 	// Reference: packages/ui-components/src/ColorPicker/ColorPicker.tsx:60
2081
-	__( 'Custom color', 'event_espresso' ),
2081
+	__('Custom color', 'event_espresso'),
2082 2082
 
2083 2083
 	// Reference: packages/ui-components/src/ColorPicker/Swatch.tsx:23
2084 2084
 	/* translators: color name */
2085
-	__( 'Color: %s', 'event_espresso' ),
2085
+	__('Color: %s', 'event_espresso'),
2086 2086
 
2087 2087
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:13
2088
-	__( 'Cyan bluish gray', 'event_espresso' ),
2088
+	__('Cyan bluish gray', 'event_espresso'),
2089 2089
 
2090 2090
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:17
2091
-	__( 'White', 'event_espresso' ),
2091
+	__('White', 'event_espresso'),
2092 2092
 
2093 2093
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:21
2094
-	__( 'Pale pink', 'event_espresso' ),
2094
+	__('Pale pink', 'event_espresso'),
2095 2095
 
2096 2096
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:25
2097
-	__( 'Vivid red', 'event_espresso' ),
2097
+	__('Vivid red', 'event_espresso'),
2098 2098
 
2099 2099
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:29
2100
-	__( 'Luminous vivid orange', 'event_espresso' ),
2100
+	__('Luminous vivid orange', 'event_espresso'),
2101 2101
 
2102 2102
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:33
2103
-	__( 'Luminous vivid amber', 'event_espresso' ),
2103
+	__('Luminous vivid amber', 'event_espresso'),
2104 2104
 
2105 2105
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:37
2106
-	__( 'Light green cyan', 'event_espresso' ),
2106
+	__('Light green cyan', 'event_espresso'),
2107 2107
 
2108 2108
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:41
2109
-	__( 'Vivid green cyan', 'event_espresso' ),
2109
+	__('Vivid green cyan', 'event_espresso'),
2110 2110
 
2111 2111
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:45
2112
-	__( 'Pale cyan blue', 'event_espresso' ),
2112
+	__('Pale cyan blue', 'event_espresso'),
2113 2113
 
2114 2114
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:49
2115
-	__( 'Vivid cyan blue', 'event_espresso' ),
2115
+	__('Vivid cyan blue', 'event_espresso'),
2116 2116
 
2117 2117
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:53
2118
-	__( 'Vivid purple', 'event_espresso' ),
2118
+	__('Vivid purple', 'event_espresso'),
2119 2119
 
2120 2120
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:9
2121
-	__( 'Black', 'event_espresso' ),
2121
+	__('Black', 'event_espresso'),
2122 2122
 
2123 2123
 	// Reference: packages/ui-components/src/Confirm/ConfirmClose.tsx:8
2124 2124
 	// Reference: packages/ui-components/src/Modal/ModalWithAlert.tsx:24
2125
-	__( 'Are you sure you want to close this?', 'event_espresso' ),
2125
+	__('Are you sure you want to close this?', 'event_espresso'),
2126 2126
 
2127 2127
 	// Reference: packages/ui-components/src/Confirm/ConfirmClose.tsx:9
2128 2128
 	// Reference: packages/ui-components/src/Modal/ModalWithAlert.tsx:25
2129
-	__( 'Yes, discard changes', 'event_espresso' ),
2129
+	__('Yes, discard changes', 'event_espresso'),
2130 2130
 
2131 2131
 	// Reference: packages/ui-components/src/Confirm/ConfirmDelete.tsx:7
2132
-	__( 'Are you sure you want to delete this?', 'event_espresso' ),
2132
+	__('Are you sure you want to delete this?', 'event_espresso'),
2133 2133
 
2134 2134
 	// Reference: packages/ui-components/src/Confirm/useConfirmWithButton.tsx:11
2135
-	__( 'Please confirm this action.', 'event_espresso' ),
2135
+	__('Please confirm this action.', 'event_espresso'),
2136 2136
 
2137 2137
 	// Reference: packages/ui-components/src/Confirm/useConfirmationDialog.tsx:39
2138
-	__( 'cancel', 'event_espresso' ),
2138
+	__('cancel', 'event_espresso'),
2139 2139
 
2140 2140
 	// Reference: packages/ui-components/src/Confirm/useConfirmationDialog.tsx:40
2141
-	__( 'confirm', 'event_espresso' ),
2141
+	__('confirm', 'event_espresso'),
2142 2142
 
2143 2143
 	// Reference: packages/ui-components/src/CurrencyDisplay/CurrencyDisplay.tsx:34
2144
-	__( 'free', 'event_espresso' ),
2144
+	__('free', 'event_espresso'),
2145 2145
 
2146 2146
 	// Reference: packages/ui-components/src/DateTimeRangePicker/DateTimeRangePicker.tsx:117
2147 2147
 	// Reference: packages/ui-components/src/Popover/PopoverForm/PopoverForm.tsx:44
2148
-	__( 'save', 'event_espresso' ),
2148
+	__('save', 'event_espresso'),
2149 2149
 
2150 2150
 	// Reference: packages/ui-components/src/DebugInfo/DebugInfo.tsx:36
2151
-	__( 'Hide Debug Info', 'event_espresso' ),
2151
+	__('Hide Debug Info', 'event_espresso'),
2152 2152
 
2153 2153
 	// Reference: packages/ui-components/src/DebugInfo/DebugInfo.tsx:36
2154
-	__( 'Show Debug Info', 'event_espresso' ),
2154
+	__('Show Debug Info', 'event_espresso'),
2155 2155
 
2156 2156
 	// Reference: packages/ui-components/src/EditDateRangeButton/EditDateRangeButton.tsx:49
2157
-	__( 'Edit Start and End Dates and Times', 'event_espresso' ),
2157
+	__('Edit Start and End Dates and Times', 'event_espresso'),
2158 2158
 
2159 2159
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/CopyEntity.tsx:8
2160
-	__( 'copy', 'event_espresso' ),
2160
+	__('copy', 'event_espresso'),
2161 2161
 
2162 2162
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/EditEntity.tsx:8
2163
-	__( 'edit', 'event_espresso' ),
2163
+	__('edit', 'event_espresso'),
2164 2164
 
2165 2165
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/TrashEntity.tsx:8
2166
-	__( 'trash', 'event_espresso' ),
2166
+	__('trash', 'event_espresso'),
2167 2167
 
2168 2168
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/Untrash.tsx:8
2169
-	__( 'untrash', 'event_espresso' ),
2169
+	__('untrash', 'event_espresso'),
2170 2170
 
2171 2171
 	// Reference: packages/ui-components/src/EntityList/EntityList.tsx:23
2172
-	__( 'OOPS!', 'event_espresso' ),
2172
+	__('OOPS!', 'event_espresso'),
2173 2173
 
2174 2174
 	// Reference: packages/ui-components/src/EntityList/EntityList.tsx:23
2175
-	__( 'Error Loading Entites List', 'event_espresso' ),
2175
+	__('Error Loading Entites List', 'event_espresso'),
2176 2176
 
2177 2177
 	// Reference: packages/ui-components/src/EntityList/RegistrationsLink/index.tsx:12
2178
-	__( 'click to open the registrations admin page in a new tab or window', 'event_espresso' ),
2178
+	__('click to open the registrations admin page in a new tab or window', 'event_espresso'),
2179 2179
 
2180 2180
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/CardViewFilterButton.tsx:22
2181
-	__( 'card view', 'event_espresso' ),
2181
+	__('card view', 'event_espresso'),
2182 2182
 
2183 2183
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/TableViewFilterButton.tsx:21
2184
-	__( 'table view', 'event_espresso' ),
2184
+	__('table view', 'event_espresso'),
2185 2185
 
2186 2186
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleBulkActionsButton.tsx:8
2187
-	__( 'hide bulk actions', 'event_espresso' ),
2187
+	__('hide bulk actions', 'event_espresso'),
2188 2188
 
2189 2189
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleBulkActionsButton.tsx:8
2190
-	__( 'show bulk actions', 'event_espresso' ),
2190
+	__('show bulk actions', 'event_espresso'),
2191 2191
 
2192 2192
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:9
2193
-	__( 'hide filters', 'event_espresso' ),
2193
+	__('hide filters', 'event_espresso'),
2194 2194
 
2195 2195
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:9
2196
-	__( 'show filters', 'event_espresso' ),
2196
+	__('show filters', 'event_espresso'),
2197 2197
 
2198 2198
 	// Reference: packages/ui-components/src/Legend/ToggleLegendButton.tsx:26
2199
-	__( 'hide legend', 'event_espresso' ),
2199
+	__('hide legend', 'event_espresso'),
2200 2200
 
2201 2201
 	// Reference: packages/ui-components/src/Legend/ToggleLegendButton.tsx:26
2202
-	__( 'show legend', 'event_espresso' ),
2202
+	__('show legend', 'event_espresso'),
2203 2203
 
2204 2204
 	// Reference: packages/ui-components/src/LoadingNotice/LoadingNotice.tsx:11
2205
-	__( 'loading…', 'event_espresso' ),
2205
+	__('loading…', 'event_espresso'),
2206 2206
 
2207 2207
 	// Reference: packages/ui-components/src/Modal/Modal.tsx:58
2208
-	__( 'close modal', 'event_espresso' ),
2208
+	__('close modal', 'event_espresso'),
2209 2209
 
2210 2210
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:10
2211
-	__( 'jump to previous', 'event_espresso' ),
2211
+	__('jump to previous', 'event_espresso'),
2212 2212
 
2213 2213
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:11
2214
-	__( 'jump to next', 'event_espresso' ),
2214
+	__('jump to next', 'event_espresso'),
2215 2215
 
2216 2216
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:12
2217
-	__( 'page', 'event_espresso' ),
2217
+	__('page', 'event_espresso'),
2218 2218
 
2219 2219
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:8
2220
-	__( 'previous', 'event_espresso' ),
2220
+	__('previous', 'event_espresso'),
2221 2221
 
2222 2222
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:9
2223
-	__( 'next', 'event_espresso' ),
2223
+	__('next', 'event_espresso'),
2224 2224
 
2225 2225
 	// Reference: packages/ui-components/src/Pagination/PerPage.tsx:37
2226
-	__( 'items per page', 'event_espresso' ),
2226
+	__('items per page', 'event_espresso'),
2227 2227
 
2228 2228
 	// Reference: packages/ui-components/src/Pagination/constants.ts:10
2229 2229
 	/* translators: %s is per page value */
2230
-	__( '%s / page', 'event_espresso' ),
2230
+	__('%s / page', 'event_espresso'),
2231 2231
 
2232 2232
 	// Reference: packages/ui-components/src/Pagination/constants.ts:13
2233
-	__( 'Next Page', 'event_espresso' ),
2233
+	__('Next Page', 'event_espresso'),
2234 2234
 
2235 2235
 	// Reference: packages/ui-components/src/Pagination/constants.ts:14
2236
-	__( 'Previous Page', 'event_espresso' ),
2236
+	__('Previous Page', 'event_espresso'),
2237 2237
 
2238 2238
 	// Reference: packages/ui-components/src/PercentSign/index.tsx:10
2239
-	__( '%', 'event_espresso' ),
2239
+	__('%', 'event_espresso'),
2240 2240
 
2241 2241
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:31
2242 2242
 	/* translators: entity type to select */
2243
-	__( 'Select an existing %s to use as a template.', 'event_espresso' ),
2243
+	__('Select an existing %s to use as a template.', 'event_espresso'),
2244 2244
 
2245 2245
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:38
2246
-	__( 'or', 'event_espresso' ),
2246
+	__('or', 'event_espresso'),
2247 2247
 
2248 2248
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:43
2249 2249
 	/* translators: entity type to add */
2250
-	__( 'Add a new %s and insert details manually', 'event_espresso' ),
2250
+	__('Add a new %s and insert details manually', 'event_espresso'),
2251 2251
 
2252 2252
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:48
2253
-	__( 'Add New', 'event_espresso' ),
2253
+	__('Add New', 'event_espresso'),
2254 2254
 
2255 2255
 	// Reference: packages/ui-components/src/Stepper/buttons/Next.tsx:8
2256
-	__( 'Next', 'event_espresso' ),
2256
+	__('Next', 'event_espresso'),
2257 2257
 
2258 2258
 	// Reference: packages/ui-components/src/Stepper/buttons/Previous.tsx:8
2259
-	__( 'Previous', 'event_espresso' ),
2259
+	__('Previous', 'event_espresso'),
2260 2260
 
2261 2261
 	// Reference: packages/ui-components/src/Steps/Steps.tsx:31
2262
-	__( 'Steps', 'event_espresso' ),
2262
+	__('Steps', 'event_espresso'),
2263 2263
 
2264 2264
 	// Reference: packages/ui-components/src/TabbableText/index.tsx:21
2265
-	__( 'click to edit…', 'event_espresso' ),
2265
+	__('click to edit…', 'event_espresso'),
2266 2266
 
2267 2267
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:14
2268
-	__( 'The Website\'s Time Zone', 'event_espresso' ),
2268
+	__('The Website\'s Time Zone', 'event_espresso'),
2269 2269
 
2270 2270
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:19
2271
-	__( 'UTC (Greenwich Mean Time)', 'event_espresso' ),
2271
+	__('UTC (Greenwich Mean Time)', 'event_espresso'),
2272 2272
 
2273 2273
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:9
2274
-	__( 'Your Local Time Zone', 'event_espresso' ),
2274
+	__('Your Local Time Zone', 'event_espresso'),
2275 2275
 
2276 2276
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:25
2277
-	__( 'click for timezone information', 'event_espresso' ),
2277
+	__('click for timezone information', 'event_espresso'),
2278 2278
 
2279 2279
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:30
2280
-	__( 'This Date Converted To:', 'event_espresso' ),
2280
+	__('This Date Converted To:', 'event_espresso'),
2281 2281
 
2282 2282
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:120
2283
-	__( 'Add New Venue', 'event_espresso' ),
2283
+	__('Add New Venue', 'event_espresso'),
2284 2284
 
2285 2285
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:36
2286
-	__( '~ no venue ~', 'event_espresso' ),
2286
+	__('~ no venue ~', 'event_espresso'),
2287 2287
 
2288 2288
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:43
2289
-	__( 'assign venue…', 'event_espresso' ),
2289
+	__('assign venue…', 'event_espresso'),
2290 2290
 
2291 2291
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:44
2292
-	__( 'click to select a venue…', 'event_espresso' ),
2292
+	__('click to select a venue…', 'event_espresso'),
2293 2293
 
2294 2294
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:51
2295
-	__( 'select all', 'event_espresso' ),
2295
+	__('select all', 'event_espresso'),
2296 2296
 
2297 2297
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:54
2298
-	__( 'apply', 'event_espresso' )
2298
+	__('apply', 'event_espresso')
2299 2299
 );
2300 2300
 /* THIS IS THE END OF THE GENERATED FILE */
Please login to merge, or discard this patch.