Completed
Branch BUG/dont-reuse-DMS-scripts-dur... (d7e798)
by
unknown
05:24 queued 03:12
created
core/EE_Data_Migration_Manager.core.php 2 patches
Indentation   +1316 added lines, -1316 removed lines patch added patch discarded remove patch
@@ -32,1320 +32,1320 @@
 block discarded – undo
32 32
 class EE_Data_Migration_Manager implements ResettableInterface
33 33
 {
34 34
 
35
-    /**
36
-     *
37
-     * @var EE_Registry
38
-     */
39
-    // protected $EE;
40
-    /**
41
-     * name of the WordPress option which stores an array of data about
42
-     */
43
-    const data_migrations_option_name = 'ee_data_migration';
44
-
45
-
46
-    const data_migration_script_option_prefix         = 'ee_data_migration_script_';
47
-
48
-    const data_migration_script_mapping_option_prefix = 'ee_dms_map_';
49
-
50
-    /**
51
-     * name of the WordPress option which stores the database' current version. IE, the code may be at version 4.2.0,
52
-     * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc.
53
-     */
54
-    const current_database_state = 'ee_data_migration_current_db_state';
55
-
56
-    /**
57
-     * Special status string returned when we're positive there are no more data migration
58
-     * scripts that can be run.
59
-     */
60
-    const status_no_more_migration_scripts = 'no_more_migration_scripts';
61
-
62
-    /**
63
-     * string indicating the migration should continue
64
-     */
65
-    const status_continue = 'status_continue';
66
-
67
-    /**
68
-     * string indicating the migration has completed and should be ended
69
-     */
70
-    const status_completed = 'status_completed';
71
-
72
-    /**
73
-     * string indicating a fatal error occurred and the data migration should be completely aborted
74
-     */
75
-    const status_fatal_error = 'status_fatal_error';
76
-
77
-    /**
78
-     * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
79
-     * during migration)
80
-     */
81
-    const step_size = 50;
82
-
83
-    /**
84
-     * option name that stores the queue of ee plugins needing to have
85
-     * their data initialized (or re-initialized) once we are done migrations
86
-     */
87
-    const db_init_queue_option_name = 'ee_db_init_queue';
88
-
89
-    /**
90
-     * Array of information concerning data migrations that have run in the history
91
-     * of this EE installation. Keys should be the name of the version the script upgraded to
92
-     *
93
-     * @var EE_Data_Migration_Script_Base[]
94
-     */
95
-    private $_data_migrations_ran = null;
96
-
97
-    /**
98
-     * The last run script. It's nice to store this somewhere accessible, as its easiest
99
-     * to know which was the last run by which is the newest wp option; but in most of the code
100
-     * we just use the local $_data_migration_ran array, which organized the scripts differently
101
-     *
102
-     * @var EE_Data_Migration_Script_Base
103
-     */
104
-    private $_last_ran_script = null;
105
-
106
-    /**
107
-     * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
108
-     *
109
-     * @var EE_Data_Migration_Script_Base
110
-     */
111
-    private $_last_ran_incomplete_script = null;
112
-
113
-    /**
114
-     * array where keys are classnames, and values are filepaths of all the known migration scripts
115
-     *
116
-     * @var array
117
-     */
118
-    private $_data_migration_class_to_filepath_map;
119
-
120
-    /**
121
-     * the following 4 properties are fully set on construction.
122
-     * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
123
-     * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
124
-     * data migration script
125
-     *
126
-     * @var array
127
-     */
128
-    public $stati_that_indicate_to_continue_migrations              = [];
129
-
130
-    public $stati_that_indicate_to_stop_migrations                  = [];
131
-
132
-    public $stati_that_indicate_to_continue_single_migration_script = [];
133
-
134
-    public $stati_that_indicate_to_stop_single_migration_script     = [];
135
-
136
-    /**
137
-     * @var TableManager $table_manager
138
-     */
139
-    protected $_table_manager;
140
-
141
-    /**
142
-     * @var TableAnalysis $table_analysis
143
-     */
144
-    protected $_table_analysis;
145
-
146
-    /**
147
-     * @var array $script_migration_versions
148
-     */
149
-    protected $script_migration_versions;
150
-
151
-    /**
152
-     * @var EE_Data_Migration_Manager $_instance
153
-     * @access    private
154
-     */
155
-    private static $_instance = null;
156
-
157
-
158
-    /**
159
-     * @singleton method used to instantiate class object
160
-     * @access    public
161
-     * @return EE_Data_Migration_Manager instance
162
-     */
163
-    public static function instance()
164
-    {
165
-        // check if class object is instantiated
166
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
167
-            self::$_instance = new self();
168
-        }
169
-        return self::$_instance;
170
-    }
171
-
172
-
173
-    /**
174
-     * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
175
-     * all new usages of the singleton should be made with Classname::instance()) and returns it
176
-     *
177
-     * @return EE_Data_Migration_Manager
178
-     */
179
-    public static function reset()
180
-    {
181
-        self::$_instance = null;
182
-        return self::instance();
183
-    }
184
-
185
-
186
-    /**
187
-     * @throws EE_Error
188
-     * @throws ReflectionException
189
-     */
190
-    private function __construct()
191
-    {
192
-        $this->stati_that_indicate_to_continue_migrations              = [
193
-            self::status_continue,
194
-            self::status_completed,
195
-        ];
196
-        $this->stati_that_indicate_to_stop_migrations                  = [
197
-            self::status_fatal_error,
198
-            self::status_no_more_migration_scripts,
199
-        ];
200
-        $this->stati_that_indicate_to_continue_single_migration_script = [
201
-            self::status_continue,
202
-        ];
203
-        $this->stati_that_indicate_to_stop_single_migration_script     = [
204
-            self::status_completed,
205
-            self::status_fatal_error
206
-            // note: status_no_more_migration_scripts doesn't apply
207
-        ];
208
-        // make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
209
-        // to be defined, because right now it doesn't get autoloaded on its own
210
-        EE_Registry::instance()->load_core('Data_Migration_Class_Base', [], true);
211
-        EE_Registry::instance()->load_core('Data_Migration_Script_Base', [], true);
212
-        EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', [], true);
213
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage', [], true);
214
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', [], true);
215
-        $this->_table_manager  = EE_Registry::instance()->create('TableManager', [], true);
216
-        $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
217
-    }
218
-
219
-
220
-    /**
221
-     * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
222
-     * the option names are like, but generally they're like
223
-     * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
224
-     * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
225
-     * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php
226
-     * (ex: EE_DMS_Core_4_1_0.dms.php)
227
-     *
228
-     * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
229
-     * @return array where the first item is the plugin slug (eg 'Core','Calendar', etc.) and the 2nd is the version of
230
-     *                            that plugin (eg '4.1.0')
231
-     */
232
-    private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
233
-    {
234
-        $plugin_slug_and_version_string = str_replace(
235
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
236
-            "",
237
-            $option_name
238
-        );
239
-        // check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
240
-        $parts = explode(".", $plugin_slug_and_version_string);
241
-
242
-        if (count($parts) == 4) {
243
-            // it's 4.2-style.eg Core.4.1.0
244
-            $plugin_slug    = $parts[0];                                     // eg Core
245
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
246
-        } else {
247
-            // it's 4.1-style: eg 4.1.0
248
-            $plugin_slug    = 'Core';
249
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
250
-        }
251
-        return [$plugin_slug, $version_string];
252
-    }
253
-
254
-
255
-    /**
256
-     * Gets the DMS class from the WordPress option, otherwise throws an EE_Error if it's not
257
-     * for a known DMS class.
258
-     *
259
-     * @param string $dms_option_name
260
-     * @param string $dms_option_value (serialized)
261
-     * @return EE_Data_Migration_Script_Base
262
-     * @throws EE_Error
263
-     */
264
-    private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
265
-    {
266
-        $data_migration_data = maybe_unserialize($dms_option_value);
267
-        if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
268
-            // During multisite migrations, it's possible we already grabbed another instance of this class
269
-            // but for a different blog. Make sure we don't reuse them (as they store info specific
270
-            // to their respective blog, like which database table to migrate).
271
-            $class = LoaderFactory::getLoader()->getNew($data_migration_data['class']);
272
-            if ($class instanceof EE_Data_Migration_Script_Base) {
273
-                $class->instantiate_from_array_of_properties($data_migration_data);
274
-                return $class;
275
-            } else {
276
-                // huh, so it's an object but not a data migration script?? that shouldn't happen
277
-                // just leave it as an array (which will probably just get ignored)
278
-                throw new EE_Error(
279
-                    sprintf(
280
-                        esc_html__(
281
-                            "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
282
-                            'event_espresso'
283
-                        ),
284
-                        $data_migration_data['class']
285
-                    )
286
-                );
287
-            }
288
-        } else {
289
-            // so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists
290
-            throw new EE_Error(
291
-                sprintf(
292
-                    esc_html__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'),
293
-                    $dms_option_name
294
-                )
295
-            );
296
-        }
297
-    }
298
-
299
-
300
-    /**
301
-     * Gets the array describing what data migrations have run.
302
-     * Also has a side effect of recording which was the last run,
303
-     * and which was the last run which hasn't finished yet
304
-     *
305
-     * @return array where each element should be an array of EE_Data_Migration_Script_Base
306
-     *               (but also has a few legacy arrays in there - which should probably be ignored)
307
-     * @throws EE_Error
308
-     */
309
-    public function get_data_migrations_ran()
310
-    {
311
-        if (! $this->_data_migrations_ran) {
312
-            // setup autoloaders for each of the scripts in there
313
-            $this->get_all_data_migration_scripts_available();
314
-            $data_migrations_options =
315
-                $this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
316
-
317
-            $data_migrations_ran = [];
318
-            // convert into data migration script classes where possible
319
-            foreach ($data_migrations_options as $data_migration_option) {
320
-                list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
321
-                    $data_migration_option['option_name']
322
-                );
323
-
324
-                try {
325
-                    $class                                                  = $this->_get_dms_class_from_wp_option(
326
-                        $data_migration_option['option_name'],
327
-                        $data_migration_option['option_value']
328
-                    );
329
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
330
-                    // ok so far THIS is the 'last-run-script'... unless we find another on next iteration
331
-                    $this->_last_ran_script = $class;
332
-                    if (! $class->is_completed()) {
333
-                        // sometimes we also like to know which was the last incomplete script (or if there are any at all)
334
-                        $this->_last_ran_incomplete_script = $class;
335
-                    }
336
-                } catch (EE_Error $e) {
337
-                    // ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
338
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
339
-                        $data_migration_option['option_value']
340
-                    );
341
-                }
342
-            }
343
-            // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
344
-            $this->_data_migrations_ran = $data_migrations_ran;
345
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
346
-                $this->_data_migrations_ran = [];
347
-            }
348
-        }
349
-        return $this->_data_migrations_ran;
350
-    }
351
-
352
-
353
-    /**
354
-     *
355
-     * @param string $script_name eg 'DMS_Core_4_1_0'
356
-     * @param string $old_table   eg 'wp_events_detail'
357
-     * @param string $old_pk      eg 'wp_esp_posts'
358
-     * @param        $new_table
359
-     * @return mixed string or int
360
-     * @throws EE_Error
361
-     * @throws ReflectionException
362
-     */
363
-    public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
364
-    {
365
-        $script  = EE_Registry::instance()->load_dms($script_name);
366
-        return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
367
-    }
368
-
369
-
370
-    /**
371
-     * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
372
-     * the last option returned in this array is the most-recently run DMS option
373
-     *
374
-     * @return array
375
-     */
376
-    public function get_all_migration_script_options()
377
-    {
378
-        global $wpdb;
379
-        return $wpdb->get_results(
380
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '"
381
-            . EE_Data_Migration_Manager::data_migration_script_option_prefix
382
-            . "%' ORDER BY option_id ASC",
383
-            ARRAY_A
384
-        );
385
-    }
386
-
387
-
388
-    /**
389
-     * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
390
-     *
391
-     * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
392
-     *               slashes at the end of the folder name.
393
-     */
394
-    public function get_data_migration_script_folders()
395
-    {
396
-        return apply_filters(
397
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
398
-            ['Core' => EE_CORE . 'data_migration_scripts']
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * Gets the version the migration script upgrades to
405
-     *
406
-     * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
407
-     * @return array {
408
-     *      @type string  $slug     like 'Core','Calendar',etc
409
-     *      @type string  $version  like 4.3.0
410
-     * }
411
-     * @throws EE_Error
412
-     */
413
-    public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
414
-    {
415
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
416
-            return $this->script_migration_versions[ $migration_script_name ];
417
-        }
418
-        $dms_info                                                  = $this->parse_dms_classname($migration_script_name);
419
-        $this->script_migration_versions[ $migration_script_name ] = [
420
-            'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
421
-            'version' => $dms_info['major_version']
422
-                         . "."
423
-                         . $dms_info['minor_version']
424
-                         . "."
425
-                         . $dms_info['micro_version'],
426
-        ];
427
-        return $this->script_migration_versions[ $migration_script_name ];
428
-    }
429
-
430
-
431
-    /**
432
-     * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
433
-     *
434
-     * @param string $classname
435
-     * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are integers)
436
-     * @throws EE_Error
437
-     */
438
-    public function parse_dms_classname($classname)
439
-    {
440
-        $matches = [];
441
-        preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
442
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
443
-            throw new EE_Error(
444
-                sprintf(
445
-                    esc_html__(
446
-                        "%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ",
447
-                        "event_espresso"
448
-                    ),
449
-                    $classname
450
-                )
451
-            );
452
-        }
453
-        return [
454
-            'slug'          => $matches[1],
455
-            'major_version' => intval($matches[2]),
456
-            'minor_version' => intval($matches[3]),
457
-            'micro_version' => intval($matches[4]),
458
-        ];
459
-    }
460
-
461
-
462
-    /**
463
-     * Ensures that the option indicating the current DB version is set. This should only be
464
-     * a concern when activating EE for the first time, THEORETICALLY.
465
-     * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise
466
-     * to 4.1.x.
467
-     *
468
-     * @return string of current db state
469
-     */
470
-    public function ensure_current_database_state_is_set()
471
-    {
472
-        $espresso_db_core_updates = get_option('espresso_db_update', []);
473
-        $db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
474
-        if (! $db_state) {
475
-            // mark the DB as being in the state as the last version in there.
476
-            // this is done to trigger maintenance mode and do data migration scripts
477
-            // if the admin installed this version of EE over 3.1.x or 4.0.x
478
-            // otherwise, the normal maintenance mode code is fine
479
-            $previous_versions_installed = array_keys($espresso_db_core_updates);
480
-            $previous_version_installed  = end($previous_versions_installed);
481
-            if (version_compare('4.1.0', $previous_version_installed)) {
482
-                // last installed version was less than 4.1, so we want the data migrations to happen.
483
-                // SO, we're going to say the DB is at that state
484
-                $db_state = ['Core' => $previous_version_installed];
485
-            } else {
486
-                $db_state = ['Core' => EVENT_ESPRESSO_VERSION];
487
-            }
488
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
489
-        }
490
-        // in 4.1, $db_state would have only been a simple string like '4.1.0',
491
-        // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
492
-        // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
493
-        if (! is_array($db_state)) {
494
-            $db_state = ['Core' => $db_state];
495
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
496
-        }
497
-        return $db_state;
498
-    }
499
-
500
-
501
-    /**
502
-     * Checks if there are any data migration scripts that ought to be run.
503
-     * If found, returns the instantiated classes.
504
-     * If none are found (ie, they've all already been run, or they don't apply), returns an empty array
505
-     *
506
-     * @return EE_Data_Migration_Script_Base[]
507
-     * @throws EE_Error
508
-     * @throws EE_Error
509
-     */
510
-    public function check_for_applicable_data_migration_scripts()
511
-    {
512
-        // get the option describing what options have already run
513
-        $scripts_ran = $this->get_data_migrations_ran();
514
-        // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
515
-        $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
516
-
517
-
518
-        $current_database_state = $this->ensure_current_database_state_is_set();
519
-        // determine which have already been run
520
-        $script_classes_that_should_run_per_iteration = [];
521
-        $iteration                                    = 0;
522
-        $next_database_state_to_consider              = $current_database_state;
523
-        $theoretical_database_state = null;
524
-        do {
525
-            // the next state after the currently-considered one
526
-            // will start off looking the same as the current, but we may make additions...
527
-            $theoretical_database_state = $next_database_state_to_consider;
528
-            // the next db state to consider is
529
-            // "what would the DB be like had we run all the scripts we found that applied last time?"
530
-            foreach ($script_class_and_filepaths_available as $classname => $filepath) {
531
-                $migrates_to_version         = $this->script_migrates_to_version($classname);
532
-                $script_converts_plugin_slug = $migrates_to_version['slug'];
533
-                $script_converts_to_version  = $migrates_to_version['version'];
534
-                // check if this version script is DONE or not; or if it's never been run
535
-                if (
536
-                    ! $scripts_ran
537
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
538
-                ) {
539
-                    // we haven't run this conversion script before
540
-                    // now check if it applies...
541
-                    // note that we've added an autoloader for it on get_all_data_migration_scripts_available
542
-                    // Also, make sure we get a new one. It's possible this is being ran during a multisite migration,
543
-                    // in which case we don't want to reuse a DMS script from a different blog!
544
-                    $script = LoaderFactory::getLoader()->getNew($classname);
545
-                    /* @var $script EE_Data_Migration_Script_Base */
546
-                    $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
547
-                    if ($can_migrate) {
548
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
549
-                        $migrates_to_version                                                                 =
550
-                            $script->migrates_to_version();
551
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
552
-                            $migrates_to_version['version'];
553
-                        unset($script_class_and_filepaths_available[ $classname ]);
554
-                    }
555
-                } elseif (
556
-                    $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
557
-                          instanceof
558
-                          EE_Data_Migration_Script_Base
559
-                ) {
560
-                    // this script has been run, or at least started
561
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
562
-                    if ($script->get_status() !== self::status_completed) {
563
-                        // this script is already underway... keep going with it
564
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
565
-                        $migrates_to_version                                                                 =
566
-                            $script->migrates_to_version();
567
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
568
-                            $migrates_to_version['version'];
569
-                        unset($script_class_and_filepaths_available[ $classname ]);
570
-                    }
571
-                    // else it must have a status that indicates it has finished,
572
-                    // so we don't want to try and run it again
573
-                }
574
-                // else it exists, but it's not  a proper data migration script maybe the script got renamed?
575
-                // or was simply removed from EE? either way, it's certainly not runnable!
576
-            }
577
-            $iteration++;
578
-        } while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
579
-        // ok we have all the scripts that should run, now let's make them into flat array
580
-        $scripts_that_should_run = [];
581
-        foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
582
-            ksort($scripts_at_priority);
583
-            foreach ($scripts_at_priority as $scripts) {
584
-                foreach ($scripts as $script) {
585
-                    $scripts_that_should_run[ get_class($script) ] = $script;
586
-                }
587
-            }
588
-        }
589
-
590
-        do_action(
591
-            'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
592
-            $scripts_that_should_run
593
-        );
594
-        return $scripts_that_should_run;
595
-    }
596
-
597
-
598
-    /**
599
-     * Gets the script which is currently being run, if there is one. If $include_completed_scripts is set to TRUE
600
-     * it will return the last run script even if it's complete.
601
-     * This means: if you want to find the currently-executing script, leave it as FALSE.
602
-     * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
603
-     *
604
-     * @param bool $include_completed_scripts
605
-     * @return EE_Data_Migration_Script_Base
606
-     * @throws EE_Error
607
-     */
608
-    public function get_last_ran_script($include_completed_scripts = false)
609
-    {
610
-        // make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
611
-        if (! $this->_data_migrations_ran) {
612
-            $this->get_data_migrations_ran();
613
-        }
614
-        if ($include_completed_scripts) {
615
-            return $this->_last_ran_script;
616
-        } else {
617
-            return $this->_last_ran_incomplete_script;
618
-        }
619
-    }
620
-
621
-
622
-    /**
623
-     * Runs the data migration scripts (well, each request to this method calls one of the
624
-     * data migration scripts' migration_step() functions).
625
-     *
626
-     * @param int   $step_size
627
-     * @return array {
628
-     *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
629
-     *                                  //and the second item is a string describing what was done
630
-     * @type int    $records_to_migrate from the current migration script
631
-     * @type int    $records_migrated
632
-     * @type string $status             one of EE_Data_Migration_Manager::status_*
633
-     * @type string $script             verbose name of the current DMS
634
-     * @type string $message            string describing what was done during this step
635
-     *                                  }
636
-     * @throws EE_Error
637
-     */
638
-    public function migration_step($step_size = 0)
639
-    {
640
-
641
-        // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
642
-        if (class_exists('EE_CPT_Strategy')) {
643
-            remove_action('pre_get_posts', [EE_CPT_Strategy::instance(), 'pre_get_posts'], 5);
644
-        }
645
-
646
-        try {
647
-            $currently_executing_script = $this->get_last_ran_script();
648
-            if (! $currently_executing_script) {
649
-                // Find the next script that needs to execute
650
-                $scripts = $this->check_for_applicable_data_migration_scripts();
651
-                if (! $scripts) {
652
-                    // huh, no more scripts to run... apparently we're done!
653
-                    // but don't forget to make sure initial data is there
654
-                    // we should be good to allow them to exit maintenance mode now
655
-                    EE_Maintenance_Mode::instance()->set_maintenance_level(
656
-                        EE_Maintenance_Mode::level_0_not_in_maintenance
657
-                    );
658
-                    // saving migrations run should actually be unnecessary,
659
-                    // but leaving in place just in case... remember this migration was finished
660
-                    // (even if we time out while initializing db for core and plugins)
661
-                    $this->_save_migrations_ran();
662
-                    // make sure DB was updated AFTER we've recorded the migration was done
663
-                    $this->initialize_db_for_enqueued_ee_plugins();
664
-                    return [
665
-                        'records_to_migrate' => 1,
666
-                        'records_migrated'   => 1,
667
-                        'status'             => self::status_no_more_migration_scripts,
668
-                        'script'             => esc_html__("Data Migration Completed Successfully", "event_espresso"),
669
-                        'message'            => esc_html__("All done!", "event_espresso"),
670
-                    ];
671
-                }
672
-                $currently_executing_script = array_shift($scripts);
673
-                // and add to the array/wp option showing the scripts run
674
-
675
-                $migrates_to                                            =
676
-                    $this->script_migrates_to_version(get_class($currently_executing_script));
677
-                $plugin_slug                                            = $migrates_to['slug'];
678
-                $version                                                = $migrates_to['version'];
679
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
680
-            }
681
-            $current_script_name = get_class($currently_executing_script);
682
-        } catch (Exception $e) {
683
-            // an exception occurred while trying to get migration scripts
684
-
685
-            $message = sprintf(
686
-                esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
687
-                $e->getMessage() . '<br>',
688
-                $e->getTraceAsString()
689
-            );
690
-            // record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
691
-            // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
692
-            $this->add_error_to_migrations_ran(
693
-                sprintf(esc_html__("Could not run data migrations because: %s", "event_espresso"), $message)
694
-            );
695
-            return [
696
-                'records_to_migrate' => 1,
697
-                'records_migrated'   => 0,
698
-                'status'             => self::status_fatal_error,
699
-                'script'             => esc_html__("Error loading data migration scripts", "event_espresso"),
700
-                'message'            => $message,
701
-            ];
702
-        }
703
-        // can we wrap it up and verify default data?
704
-        $init_dbs = false;
705
-        // ok so we definitely have a data migration script
706
-        try {
707
-            // how big of a bite do we want to take? Allow users to easily override via their wp-config
708
-            if (absint($step_size) < 1) {
709
-                $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
710
-                    ? EE_MIGRATION_STEP_SIZE
711
-                    : EE_Data_Migration_Manager::step_size;
712
-            }
713
-            // do what we came to do!
714
-            $currently_executing_script->migration_step($step_size);
715
-            switch ($currently_executing_script->get_status()) {
716
-                case EE_Data_Migration_Manager::status_continue:
717
-                    $response_array = [
718
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
719
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
720
-                        'status'             => EE_Data_Migration_Manager::status_continue,
721
-                        'message'            => $currently_executing_script->get_feedback_message(),
722
-                        'script'             => $currently_executing_script->pretty_name(),
723
-                    ];
724
-                    break;
725
-                case EE_Data_Migration_Manager::status_completed:
726
-                    // ok so THAT script has completed
727
-                    $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
728
-                    $response_array = [
729
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
730
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
731
-                        'status'             => EE_Data_Migration_Manager::status_completed,
732
-                        'message'            => $currently_executing_script->get_feedback_message(),
733
-                        'script'             => sprintf(
734
-                            esc_html__("%s Completed", 'event_espresso'),
735
-                            $currently_executing_script->pretty_name()
736
-                        ),
737
-                    ];
738
-                    // check if there are any more after this one.
739
-                    $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
740
-                    if (! $scripts_remaining) {
741
-                        // we should be good to allow them to exit maintenance mode now
742
-                        EE_Maintenance_Mode::instance()->set_maintenance_level(
743
-                            EE_Maintenance_Mode::level_0_not_in_maintenance
744
-                        );
745
-                        // huh, no more scripts to run... apparently we're done!
746
-                        // but don't forget to make sure initial data is there
747
-                        $init_dbs                 = true;
748
-                        $response_array['status'] = self::status_no_more_migration_scripts;
749
-                    }
750
-                    break;
751
-                default:
752
-                    $response_array = [
753
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
754
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
755
-                        'status'             => $currently_executing_script->get_status(),
756
-                        'message'            => sprintf(
757
-                            esc_html__("Minor errors occurred during %s: %s", "event_espresso"),
758
-                            $currently_executing_script->pretty_name(),
759
-                            implode(", ", $currently_executing_script->get_errors())
760
-                        ),
761
-                        'script'             => $currently_executing_script->pretty_name(),
762
-                    ];
763
-                    break;
764
-            }
765
-        } catch (Exception $e) {
766
-            // ok so some exception was thrown which killed the data migration script
767
-            // double-check we have a real script
768
-            if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
769
-                $script_name = $currently_executing_script->pretty_name();
770
-                $currently_executing_script->set_broken();
771
-                $currently_executing_script->add_error($e->getMessage());
772
-            } else {
773
-                $script_name = esc_html__("Error getting Migration Script", "event_espresso");
774
-            }
775
-            $response_array = [
776
-                'records_to_migrate' => 1,
777
-                'records_migrated'   => 0,
778
-                'status'             => self::status_fatal_error,
779
-                'message'            => sprintf(
780
-                    esc_html__("A fatal error occurred during the migration: %s", "event_espresso"),
781
-                    $e->getMessage()
782
-                ),
783
-                'script'             => $script_name,
784
-            ];
785
-        }
786
-        $successful_save = $this->_save_migrations_ran();
787
-        if ($successful_save !== true) {
788
-            // ok so the current wp option didn't save. that's tricky, because we'd like to update it
789
-            // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
790
-            // however, if we throw an exception, and return that, then the next request
791
-            // won't have as much info in it, and it may be able to save
792
-            throw new EE_Error(
793
-                sprintf(
794
-                    esc_html__(
795
-                        "The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.",
796
-                        "event_espresso"
797
-                    ),
798
-                    $successful_save
799
-                )
800
-            );
801
-        }
802
-        // if we're all done, initialize EE plugins' default data etc.
803
-        if ($init_dbs) {
804
-            $this->initialize_db_for_enqueued_ee_plugins();
805
-        }
806
-        return $response_array;
807
-    }
808
-
809
-
810
-    /**
811
-     * Echo out JSON response to migration script AJAX requests. Takes precautions
812
-     * to buffer output so that we don't throw junk into our json.
813
-     *
814
-     * @return array with keys:
815
-     * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
816
-     * it's NOT the count of hwo many remain)
817
-     * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
818
-     * records_migrated/records_to_migrate)
819
-     * 'status'=>a string, one of EE_Data_migration_Manager::status_*
820
-     * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
821
-     * errors, notifications, and successes
822
-     * 'script'=>a pretty name of the script currently running
823
-     */
824
-    public function response_to_migration_ajax_request()
825
-    {
826
-        ob_start();
827
-        try {
828
-            $response = $this->migration_step();
829
-        } catch (Exception $e) {
830
-            $response = [
831
-                'records_to_migrate' => 0,
832
-                'records_migrated'   => 0,
833
-                'status'             => EE_Data_Migration_Manager::status_fatal_error,
834
-                'message'            => sprintf(
835
-                    esc_html__("Unknown fatal error occurred: %s", "event_espresso"),
836
-                    $e->getMessage()
837
-                ),
838
-                'script'             => 'Unknown',
839
-            ];
840
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
841
-        }
842
-        $warnings_etc = @ob_get_contents();
843
-        ob_end_clean();
844
-        $response['message'] .= $warnings_etc;
845
-        return $response;
846
-    }
847
-
848
-
849
-    /**
850
-     * Updates the WordPress option that keeps track of which EE version the database
851
-     * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
852
-     *
853
-     * @param array $slug_and_version {
854
-     * @type string $slug             like 'Core' or 'Calendar',
855
-     * @type string $version          like '4.1.0'
856
-     *                                }
857
-     * @return void
858
-     */
859
-    public function update_current_database_state_to($slug_and_version = null)
860
-    {
861
-        if (! $slug_and_version) {
862
-            // no version was provided, assume it should be at the current code version
863
-            $slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
864
-        }
865
-        $current_database_state                              = get_option(self::current_database_state);
866
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
867
-        update_option(self::current_database_state, $current_database_state);
868
-    }
869
-
870
-
871
-    /**
872
-     * Determines if the database is currently at a state matching what's indicated in $slug and $version.
873
-     *
874
-     * @param array $slug_and_version {
875
-     * @type string $slug             like 'Core' or 'Calendar',
876
-     * @type string $version          like '4.1.0'
877
-     *                                }
878
-     * @return boolean
879
-     */
880
-    public function database_needs_updating_to($slug_and_version)
881
-    {
882
-
883
-        $slug                   = $slug_and_version['slug'];
884
-        $version                = $slug_and_version['version'];
885
-        $current_database_state = get_option(self::current_database_state);
886
-        if (! isset($current_database_state[ $slug ])) {
887
-            return true;
888
-        } else {
889
-            // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
890
-            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
891
-            $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
892
-            $needs_updating                     = false;
893
-            foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
894
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
895
-                    $needs_updating = true;
896
-                    break;
897
-                }
898
-            }
899
-            return $needs_updating;
900
-        }
901
-    }
902
-
903
-
904
-    /**
905
-     * Gets all the data migration scripts available in the core folder and folders
906
-     * in addons. Has the side effect of adding them for autoloading
907
-     *
908
-     * @return array keys are expected classnames, values are their filepaths
909
-     * @throws InvalidInterfaceException
910
-     * @throws InvalidDataTypeException
911
-     * @throws EE_Error
912
-     * @throws InvalidArgumentException
913
-     */
914
-    public function get_all_data_migration_scripts_available()
915
-    {
916
-        if (! $this->_data_migration_class_to_filepath_map) {
917
-            $this->_data_migration_class_to_filepath_map = [];
918
-            foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
919
-                // strip any placeholders added to classname to make it a unique array key
920
-                $eeAddonClass = trim($eeAddonClass, '*');
921
-                $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
922
-                    ? $eeAddonClass
923
-                    : '';
924
-                $folder_path  = EEH_File::end_with_directory_separator($folder_path);
925
-                $files        = glob($folder_path . '*.dms.php');
926
-                if (empty($files)) {
927
-                    continue;
928
-                }
929
-                foreach ($files as $file) {
930
-                    $pos_of_last_slash = strrpos($file, '/');
931
-                    $classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
932
-                    $migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
933
-                    $slug              = $migrates_to['slug'];
934
-                    // check that the slug as contained in the DMS is associated with
935
-                    // the slug of an addon or core
936
-                    if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
937
-                        EE_Error::doing_it_wrong(
938
-                            __FUNCTION__,
939
-                            sprintf(
940
-                                esc_html__(
941
-                                    'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
942
-                                    'event_espresso'
943
-                                ),
944
-                                $classname,
945
-                                $slug,
946
-                                implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
947
-                            ),
948
-                            '4.3.0.alpha.019'
949
-                        );
950
-                    }
951
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
952
-                }
953
-            }
954
-            EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
955
-        }
956
-        return $this->_data_migration_class_to_filepath_map;
957
-    }
958
-
959
-
960
-    /**
961
-     * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
962
-     * from each addon, and check if they need updating,
963
-     *
964
-     * @return boolean
965
-     */
966
-    public function addons_need_updating()
967
-    {
968
-        return false;
969
-    }
970
-
971
-
972
-    /**
973
-     * Adds this error string to the data_migrations_ran array, but we don't necessarily know
974
-     * where to put it, so we just throw it in there... better than nothing...
975
-     *
976
-     * @param string $error_message
977
-     */
978
-    public function add_error_to_migrations_ran($error_message)
979
-    {
980
-        // get last-run migration script
981
-        global $wpdb;
982
-        $last_migration_script_option = $wpdb->get_row(
983
-            "SELECT * FROM $wpdb->options WHERE option_name like '"
984
-            . EE_Data_Migration_Manager::data_migration_script_option_prefix
985
-            . "%' ORDER BY option_id DESC LIMIT 1",
986
-            ARRAY_A
987
-        );
988
-
989
-        $last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
990
-            ? maybe_unserialize($last_migration_script_option['option_value']) : null;
991
-        // now, tread lightly because we're here because a FATAL non-catchable error
992
-        // was thrown last time when we were trying to run a data migration script
993
-        // so the fatal error could have happened while getting the migration script
994
-        // or doing running it...
995
-        $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
996
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
997
-            "",
998
-            $last_migration_script_option['option_name']
999
-        ) : null;
1000
-
1001
-        // check if it THINKS it's a data migration script and especially if it's one that HASN'T finished yet
1002
-        // because if it has finished, then it obviously couldn't be the cause of this error, right? (because it's all done)
1003
-        if (
1004
-            isset($last_ran_migration_script_properties['class'])
1005
-            && isset($last_ran_migration_script_properties['_status'])
1006
-            && $last_ran_migration_script_properties['_status'] != self::status_completed
1007
-        ) {
1008
-            // ok then just add this error to its list of errors
1009
-            $last_ran_migration_script_properties['_errors'][] = $error_message;
1010
-            $last_ran_migration_script_properties['_status']   = self::status_fatal_error;
1011
-        } else {
1012
-            // so we don't even know which script was last running
1013
-            // use the data migration error stub, which is designed specifically for this type of thing
1014
-            $general_migration_error = new EE_DMS_Unknown_1_0_0();
1015
-            $general_migration_error->add_error($error_message);
1016
-            $general_migration_error->set_broken();
1017
-            $last_ran_migration_script_properties = $general_migration_error->properties_as_array();
1018
-            $versions_migrated_to                 = 'Unknown.1.0.0';
1019
-            // now just to make sure appears as last (in case the were previously a fatal error like this)
1020
-            // delete the old one
1021
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1022
-        }
1023
-        update_option(
1024
-            self::data_migration_script_option_prefix . $versions_migrated_to,
1025
-            $last_ran_migration_script_properties
1026
-        );
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * saves what data migrations have run to the database
1032
-     *
1033
-     * @return bool|string TRUE if successfully saved migrations ran, string if an error occurred
1034
-     * @throws EE_Error
1035
-     */
1036
-    protected function _save_migrations_ran()
1037
-    {
1038
-        if ($this->_data_migrations_ran == null) {
1039
-            $this->get_data_migrations_ran();
1040
-        }
1041
-        // now, we don't want to save actual classes to the DB because that's messy
1042
-        $successful_updates = true;
1043
-        foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1044
-            foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1045
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1046
-                $option_name                        =
1047
-                    self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1048
-                $old_option_value                   = get_option($option_name);
1049
-                if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1050
-                    $script_array_for_saving = $array_or_migration_obj->properties_as_array();
1051
-                    if ($old_option_value != $script_array_for_saving) {
1052
-                        $successful_updates = update_option($option_name, $script_array_for_saving);
1053
-                    }
1054
-                } else {// we don't know what this array-thing is. So just save it as-is
1055
-                    if ($old_option_value != $array_or_migration_obj) {
1056
-                        $successful_updates = update_option($option_name, $array_or_migration_obj);
1057
-                    }
1058
-                }
1059
-                if (! $successful_updates) {
1060
-                    global $wpdb;
1061
-                    return $wpdb->last_error;
1062
-                }
1063
-            }
1064
-        }
1065
-        return true;
1066
-        // $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1067
-        // if ($updated !== true) {
1068
-        //     global $wpdb;
1069
-        //     return $wpdb->last_error;
1070
-        // } else {
1071
-        //     return true;
1072
-        // }
1073
-        // wp_mail(
1074
-        //     "[email protected]",
1075
-        //     time() . " price debug info",
1076
-        //     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1077
-        //         serialize($array_of_migrations)
1078
-        //     )
1079
-        // );
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * Takes an array of data migration script properties and re-creates the class from
1085
-     * them. The argument $properties_array is assumed to have been made by
1086
-     * EE_Data_Migration_Script_Base::properties_as_array()
1087
-     *
1088
-     * @param array $properties_array
1089
-     * @return EE_Data_Migration_Script_Base
1090
-     * @throws EE_Error
1091
-     */
1092
-    public function _instantiate_script_from_properties_array($properties_array)
1093
-    {
1094
-        if (! isset($properties_array['class'])) {
1095
-            throw new EE_Error(
1096
-                sprintf(
1097
-                    esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1098
-                    implode(",", $properties_array)
1099
-                )
1100
-            );
1101
-        }
1102
-        $class_name = $properties_array['class'];
1103
-        if (! class_exists($class_name)) {
1104
-            throw new EE_Error(sprintf(
1105
-                esc_html__("There is no migration script named %s", "event_espresso"),
1106
-                $class_name
1107
-            ));
1108
-        }
1109
-        $class = new $class_name();
1110
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1111
-            throw new EE_Error(
1112
-                sprintf(
1113
-                    esc_html__(
1114
-                        "Class '%s' is supposed to be a migration script. Its not, its a '%s'",
1115
-                        "event_espresso"
1116
-                    ),
1117
-                    $class_name,
1118
-                    get_class($class)
1119
-                )
1120
-            );
1121
-        }
1122
-        $class->instantiate_from_array_of_properties($properties_array);
1123
-        return $class;
1124
-    }
1125
-
1126
-
1127
-    /**
1128
-     * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1129
-     * leave the DB in a state usable by the current plugin code).
1130
-     *
1131
-     * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1132
-     * @return string
1133
-     * @throws EE_Error
1134
-     * @throws EE_Error
1135
-     */
1136
-    public function get_most_up_to_date_dms($plugin_slug = 'Core')
1137
-    {
1138
-        $class_to_filepath_map         = $this->get_all_data_migration_scripts_available();
1139
-        $most_up_to_date_dms_classname = null;
1140
-        foreach ($class_to_filepath_map as $classname => $filepath) {
1141
-            if ($most_up_to_date_dms_classname === null) {
1142
-                $migrates_to      = $this->script_migrates_to_version($classname);
1143
-                $this_plugin_slug = $migrates_to['slug'];
1144
-                if ($this_plugin_slug == $plugin_slug) {
1145
-                    // if it's for core, it wins
1146
-                    $most_up_to_date_dms_classname = $classname;
1147
-                }
1148
-                // if it wasn't for core, we must keep searching for one that is!
1149
-                continue;
1150
-            }
1151
-            $champion_migrates_to  = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1152
-            $contender_migrates_to = $this->script_migrates_to_version($classname);
1153
-            if (
1154
-                $contender_migrates_to['slug'] == $plugin_slug
1155
-                && version_compare(
1156
-                    $champion_migrates_to['version'],
1157
-                    $contender_migrates_to['version'],
1158
-                    '<'
1159
-                )
1160
-            ) {
1161
-                // so the contenders version is higher, and it's for Core
1162
-                $most_up_to_date_dms_classname = $classname;
1163
-            }
1164
-        }
1165
-        return $most_up_to_date_dms_classname;
1166
-    }
1167
-
1168
-
1169
-    /**
1170
-     * Gets the migration script specified but ONLY if it has already run.
1171
-     *
1172
-     * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has run, you would run the following code:
1173
-     * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1174
-     * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1175
-     * other addon) DMS has run, in case the current DMS depends on it.
1176
-     *
1177
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1178
-     *                            period. Eg '4.1.0'
1179
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1180
-     * @return EE_Data_Migration_Script_Base
1181
-     * @throws EE_Error
1182
-     */
1183
-    public function get_migration_ran($version, $plugin_slug = 'Core')
1184
-    {
1185
-        $migrations_ran = $this->get_data_migrations_ran();
1186
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1187
-            return $migrations_ran[ $plugin_slug ][ $version ];
1188
-        } else {
1189
-            return null;
1190
-        }
1191
-    }
1192
-
1193
-
1194
-    /**
1195
-     * Resets the borked data migration scripts, so they're no longer borked, and we can again attempt to migrate
1196
-     *
1197
-     * @return bool
1198
-     * @throws EE_Error
1199
-     */
1200
-    public function reattempt()
1201
-    {
1202
-        // find if the last-run script was borked
1203
-        // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1204
-        // add an 'error' saying that we attempted to reset
1205
-        // does it have a stage that was borked too? if so make it no longer borked
1206
-        // add an 'error' saying we attempted to reset
1207
-        $last_ran_script = $this->get_last_ran_script();
1208
-        if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1209
-            // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1210
-            $last_ran_script->set_completed();
1211
-        } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1212
-            $last_ran_script->reattempt();
1213
-        } else {
1214
-            throw new EE_Error(
1215
-                sprintf(
1216
-                    esc_html__(
1217
-                        'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1218
-                        'event_espresso'
1219
-                    ),
1220
-                    print_r($last_ran_script, true)
1221
-                )
1222
-            );
1223
-        }
1224
-        return $this->_save_migrations_ran();
1225
-    }
1226
-
1227
-
1228
-    /**
1229
-     * Gets whether this particular migration has run or not
1230
-     *
1231
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1232
-     *                            period. Eg '4.1.0'
1233
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1234
-     * @return boolean
1235
-     * @throws EE_Error
1236
-     */
1237
-    public function migration_has_ran($version, $plugin_slug = 'Core')
1238
-    {
1239
-        return $this->get_migration_ran($version, $plugin_slug) !== null;
1240
-    }
1241
-
1242
-
1243
-    /**
1244
-     * Enqueues this ee plugin to have its data initialized
1245
-     *
1246
-     * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1247
-     */
1248
-    public function enqueue_db_initialization_for($plugin_slug)
1249
-    {
1250
-        $queue = $this->get_db_initialization_queue();
1251
-        if (! in_array($plugin_slug, $queue)) {
1252
-            $queue[] = $plugin_slug;
1253
-        }
1254
-        update_option(self::db_init_queue_option_name, $queue);
1255
-    }
1256
-
1257
-
1258
-    /**
1259
-     * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1260
-     * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1261
-     * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1262
-     *
1263
-     * @throws EE_Error
1264
-     */
1265
-    public function initialize_db_for_enqueued_ee_plugins()
1266
-    {
1267
-        $queue = $this->get_db_initialization_queue();
1268
-        foreach ($queue as $plugin_slug) {
1269
-            $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1270
-            if (! $most_up_to_date_dms) {
1271
-                // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1272
-                $verify_db = false;
1273
-            } else {
1274
-                $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1275
-                $verify_db                       = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1276
-            }
1277
-            if ($plugin_slug == 'Core') {
1278
-                EE_System::instance()->initialize_db_if_no_migrations_required(
1279
-                    false,
1280
-                    $verify_db
1281
-                );
1282
-            } else {
1283
-                // just loop through the addons to make sure their database is set up
1284
-                foreach (EE_Registry::instance()->addons as $addon) {
1285
-                    if ($addon->name() == $plugin_slug) {
1286
-                        $addon->initialize_db_if_no_migrations_required($verify_db);
1287
-                        break;
1288
-                    }
1289
-                }
1290
-            }
1291
-        }
1292
-        // because we just initialized the DBs for the enqueued ee plugins
1293
-        // we don't need to keep remembering which ones needed to be initialized
1294
-        delete_option(self::db_init_queue_option_name);
1295
-    }
1296
-
1297
-
1298
-    /**
1299
-     * Gets a numerically-indexed array of plugin slugs that need to have their databases
1300
-     * (re-)initialized after migrations are complete. ie, each element should be either
1301
-     * 'Core', or the return value of EE_Addon::name() for an addon
1302
-     *
1303
-     * @return array
1304
-     */
1305
-    public function get_db_initialization_queue()
1306
-    {
1307
-        return get_option(self::db_init_queue_option_name, []);
1308
-    }
1309
-
1310
-
1311
-    /**
1312
-     * Gets the injected table analyzer, or throws an exception
1313
-     *
1314
-     * @return TableAnalysis
1315
-     * @throws EE_Error
1316
-     */
1317
-    protected function _get_table_analysis()
1318
-    {
1319
-        if ($this->_table_analysis instanceof TableAnalysis) {
1320
-            return $this->_table_analysis;
1321
-        } else {
1322
-            throw new EE_Error(
1323
-                sprintf(
1324
-                    esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1325
-                    get_class($this)
1326
-                )
1327
-            );
1328
-        }
1329
-    }
1330
-
1331
-
1332
-    /**
1333
-     * Gets the injected table manager, or throws an exception
1334
-     *
1335
-     * @return TableManager
1336
-     * @throws EE_Error
1337
-     */
1338
-    protected function _get_table_manager()
1339
-    {
1340
-        if ($this->_table_manager instanceof TableManager) {
1341
-            return $this->_table_manager;
1342
-        } else {
1343
-            throw new EE_Error(
1344
-                sprintf(
1345
-                    esc_html__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1346
-                    get_class($this)
1347
-                )
1348
-            );
1349
-        }
1350
-    }
35
+	/**
36
+	 *
37
+	 * @var EE_Registry
38
+	 */
39
+	// protected $EE;
40
+	/**
41
+	 * name of the WordPress option which stores an array of data about
42
+	 */
43
+	const data_migrations_option_name = 'ee_data_migration';
44
+
45
+
46
+	const data_migration_script_option_prefix         = 'ee_data_migration_script_';
47
+
48
+	const data_migration_script_mapping_option_prefix = 'ee_dms_map_';
49
+
50
+	/**
51
+	 * name of the WordPress option which stores the database' current version. IE, the code may be at version 4.2.0,
52
+	 * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc.
53
+	 */
54
+	const current_database_state = 'ee_data_migration_current_db_state';
55
+
56
+	/**
57
+	 * Special status string returned when we're positive there are no more data migration
58
+	 * scripts that can be run.
59
+	 */
60
+	const status_no_more_migration_scripts = 'no_more_migration_scripts';
61
+
62
+	/**
63
+	 * string indicating the migration should continue
64
+	 */
65
+	const status_continue = 'status_continue';
66
+
67
+	/**
68
+	 * string indicating the migration has completed and should be ended
69
+	 */
70
+	const status_completed = 'status_completed';
71
+
72
+	/**
73
+	 * string indicating a fatal error occurred and the data migration should be completely aborted
74
+	 */
75
+	const status_fatal_error = 'status_fatal_error';
76
+
77
+	/**
78
+	 * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
79
+	 * during migration)
80
+	 */
81
+	const step_size = 50;
82
+
83
+	/**
84
+	 * option name that stores the queue of ee plugins needing to have
85
+	 * their data initialized (or re-initialized) once we are done migrations
86
+	 */
87
+	const db_init_queue_option_name = 'ee_db_init_queue';
88
+
89
+	/**
90
+	 * Array of information concerning data migrations that have run in the history
91
+	 * of this EE installation. Keys should be the name of the version the script upgraded to
92
+	 *
93
+	 * @var EE_Data_Migration_Script_Base[]
94
+	 */
95
+	private $_data_migrations_ran = null;
96
+
97
+	/**
98
+	 * The last run script. It's nice to store this somewhere accessible, as its easiest
99
+	 * to know which was the last run by which is the newest wp option; but in most of the code
100
+	 * we just use the local $_data_migration_ran array, which organized the scripts differently
101
+	 *
102
+	 * @var EE_Data_Migration_Script_Base
103
+	 */
104
+	private $_last_ran_script = null;
105
+
106
+	/**
107
+	 * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
108
+	 *
109
+	 * @var EE_Data_Migration_Script_Base
110
+	 */
111
+	private $_last_ran_incomplete_script = null;
112
+
113
+	/**
114
+	 * array where keys are classnames, and values are filepaths of all the known migration scripts
115
+	 *
116
+	 * @var array
117
+	 */
118
+	private $_data_migration_class_to_filepath_map;
119
+
120
+	/**
121
+	 * the following 4 properties are fully set on construction.
122
+	 * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
123
+	 * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
124
+	 * data migration script
125
+	 *
126
+	 * @var array
127
+	 */
128
+	public $stati_that_indicate_to_continue_migrations              = [];
129
+
130
+	public $stati_that_indicate_to_stop_migrations                  = [];
131
+
132
+	public $stati_that_indicate_to_continue_single_migration_script = [];
133
+
134
+	public $stati_that_indicate_to_stop_single_migration_script     = [];
135
+
136
+	/**
137
+	 * @var TableManager $table_manager
138
+	 */
139
+	protected $_table_manager;
140
+
141
+	/**
142
+	 * @var TableAnalysis $table_analysis
143
+	 */
144
+	protected $_table_analysis;
145
+
146
+	/**
147
+	 * @var array $script_migration_versions
148
+	 */
149
+	protected $script_migration_versions;
150
+
151
+	/**
152
+	 * @var EE_Data_Migration_Manager $_instance
153
+	 * @access    private
154
+	 */
155
+	private static $_instance = null;
156
+
157
+
158
+	/**
159
+	 * @singleton method used to instantiate class object
160
+	 * @access    public
161
+	 * @return EE_Data_Migration_Manager instance
162
+	 */
163
+	public static function instance()
164
+	{
165
+		// check if class object is instantiated
166
+		if (! self::$_instance instanceof EE_Data_Migration_Manager) {
167
+			self::$_instance = new self();
168
+		}
169
+		return self::$_instance;
170
+	}
171
+
172
+
173
+	/**
174
+	 * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
175
+	 * all new usages of the singleton should be made with Classname::instance()) and returns it
176
+	 *
177
+	 * @return EE_Data_Migration_Manager
178
+	 */
179
+	public static function reset()
180
+	{
181
+		self::$_instance = null;
182
+		return self::instance();
183
+	}
184
+
185
+
186
+	/**
187
+	 * @throws EE_Error
188
+	 * @throws ReflectionException
189
+	 */
190
+	private function __construct()
191
+	{
192
+		$this->stati_that_indicate_to_continue_migrations              = [
193
+			self::status_continue,
194
+			self::status_completed,
195
+		];
196
+		$this->stati_that_indicate_to_stop_migrations                  = [
197
+			self::status_fatal_error,
198
+			self::status_no_more_migration_scripts,
199
+		];
200
+		$this->stati_that_indicate_to_continue_single_migration_script = [
201
+			self::status_continue,
202
+		];
203
+		$this->stati_that_indicate_to_stop_single_migration_script     = [
204
+			self::status_completed,
205
+			self::status_fatal_error
206
+			// note: status_no_more_migration_scripts doesn't apply
207
+		];
208
+		// make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
209
+		// to be defined, because right now it doesn't get autoloaded on its own
210
+		EE_Registry::instance()->load_core('Data_Migration_Class_Base', [], true);
211
+		EE_Registry::instance()->load_core('Data_Migration_Script_Base', [], true);
212
+		EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', [], true);
213
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage', [], true);
214
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', [], true);
215
+		$this->_table_manager  = EE_Registry::instance()->create('TableManager', [], true);
216
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
217
+	}
218
+
219
+
220
+	/**
221
+	 * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
222
+	 * the option names are like, but generally they're like
223
+	 * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
224
+	 * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
225
+	 * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php
226
+	 * (ex: EE_DMS_Core_4_1_0.dms.php)
227
+	 *
228
+	 * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
229
+	 * @return array where the first item is the plugin slug (eg 'Core','Calendar', etc.) and the 2nd is the version of
230
+	 *                            that plugin (eg '4.1.0')
231
+	 */
232
+	private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
233
+	{
234
+		$plugin_slug_and_version_string = str_replace(
235
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
236
+			"",
237
+			$option_name
238
+		);
239
+		// check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
240
+		$parts = explode(".", $plugin_slug_and_version_string);
241
+
242
+		if (count($parts) == 4) {
243
+			// it's 4.2-style.eg Core.4.1.0
244
+			$plugin_slug    = $parts[0];                                     // eg Core
245
+			$version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
246
+		} else {
247
+			// it's 4.1-style: eg 4.1.0
248
+			$plugin_slug    = 'Core';
249
+			$version_string = $plugin_slug_and_version_string;// eg 4.1.0
250
+		}
251
+		return [$plugin_slug, $version_string];
252
+	}
253
+
254
+
255
+	/**
256
+	 * Gets the DMS class from the WordPress option, otherwise throws an EE_Error if it's not
257
+	 * for a known DMS class.
258
+	 *
259
+	 * @param string $dms_option_name
260
+	 * @param string $dms_option_value (serialized)
261
+	 * @return EE_Data_Migration_Script_Base
262
+	 * @throws EE_Error
263
+	 */
264
+	private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
265
+	{
266
+		$data_migration_data = maybe_unserialize($dms_option_value);
267
+		if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
268
+			// During multisite migrations, it's possible we already grabbed another instance of this class
269
+			// but for a different blog. Make sure we don't reuse them (as they store info specific
270
+			// to their respective blog, like which database table to migrate).
271
+			$class = LoaderFactory::getLoader()->getNew($data_migration_data['class']);
272
+			if ($class instanceof EE_Data_Migration_Script_Base) {
273
+				$class->instantiate_from_array_of_properties($data_migration_data);
274
+				return $class;
275
+			} else {
276
+				// huh, so it's an object but not a data migration script?? that shouldn't happen
277
+				// just leave it as an array (which will probably just get ignored)
278
+				throw new EE_Error(
279
+					sprintf(
280
+						esc_html__(
281
+							"Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
282
+							'event_espresso'
283
+						),
284
+						$data_migration_data['class']
285
+					)
286
+				);
287
+			}
288
+		} else {
289
+			// so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists
290
+			throw new EE_Error(
291
+				sprintf(
292
+					esc_html__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'),
293
+					$dms_option_name
294
+				)
295
+			);
296
+		}
297
+	}
298
+
299
+
300
+	/**
301
+	 * Gets the array describing what data migrations have run.
302
+	 * Also has a side effect of recording which was the last run,
303
+	 * and which was the last run which hasn't finished yet
304
+	 *
305
+	 * @return array where each element should be an array of EE_Data_Migration_Script_Base
306
+	 *               (but also has a few legacy arrays in there - which should probably be ignored)
307
+	 * @throws EE_Error
308
+	 */
309
+	public function get_data_migrations_ran()
310
+	{
311
+		if (! $this->_data_migrations_ran) {
312
+			// setup autoloaders for each of the scripts in there
313
+			$this->get_all_data_migration_scripts_available();
314
+			$data_migrations_options =
315
+				$this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
316
+
317
+			$data_migrations_ran = [];
318
+			// convert into data migration script classes where possible
319
+			foreach ($data_migrations_options as $data_migration_option) {
320
+				list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
321
+					$data_migration_option['option_name']
322
+				);
323
+
324
+				try {
325
+					$class                                                  = $this->_get_dms_class_from_wp_option(
326
+						$data_migration_option['option_name'],
327
+						$data_migration_option['option_value']
328
+					);
329
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
330
+					// ok so far THIS is the 'last-run-script'... unless we find another on next iteration
331
+					$this->_last_ran_script = $class;
332
+					if (! $class->is_completed()) {
333
+						// sometimes we also like to know which was the last incomplete script (or if there are any at all)
334
+						$this->_last_ran_incomplete_script = $class;
335
+					}
336
+				} catch (EE_Error $e) {
337
+					// ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
338
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
339
+						$data_migration_option['option_value']
340
+					);
341
+				}
342
+			}
343
+			// so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
344
+			$this->_data_migrations_ran = $data_migrations_ran;
345
+			if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
346
+				$this->_data_migrations_ran = [];
347
+			}
348
+		}
349
+		return $this->_data_migrations_ran;
350
+	}
351
+
352
+
353
+	/**
354
+	 *
355
+	 * @param string $script_name eg 'DMS_Core_4_1_0'
356
+	 * @param string $old_table   eg 'wp_events_detail'
357
+	 * @param string $old_pk      eg 'wp_esp_posts'
358
+	 * @param        $new_table
359
+	 * @return mixed string or int
360
+	 * @throws EE_Error
361
+	 * @throws ReflectionException
362
+	 */
363
+	public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
364
+	{
365
+		$script  = EE_Registry::instance()->load_dms($script_name);
366
+		return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
367
+	}
368
+
369
+
370
+	/**
371
+	 * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
372
+	 * the last option returned in this array is the most-recently run DMS option
373
+	 *
374
+	 * @return array
375
+	 */
376
+	public function get_all_migration_script_options()
377
+	{
378
+		global $wpdb;
379
+		return $wpdb->get_results(
380
+			"SELECT * FROM {$wpdb->options} WHERE option_name like '"
381
+			. EE_Data_Migration_Manager::data_migration_script_option_prefix
382
+			. "%' ORDER BY option_id ASC",
383
+			ARRAY_A
384
+		);
385
+	}
386
+
387
+
388
+	/**
389
+	 * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
390
+	 *
391
+	 * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
392
+	 *               slashes at the end of the folder name.
393
+	 */
394
+	public function get_data_migration_script_folders()
395
+	{
396
+		return apply_filters(
397
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
398
+			['Core' => EE_CORE . 'data_migration_scripts']
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * Gets the version the migration script upgrades to
405
+	 *
406
+	 * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
407
+	 * @return array {
408
+	 *      @type string  $slug     like 'Core','Calendar',etc
409
+	 *      @type string  $version  like 4.3.0
410
+	 * }
411
+	 * @throws EE_Error
412
+	 */
413
+	public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
414
+	{
415
+		if (isset($this->script_migration_versions[ $migration_script_name ])) {
416
+			return $this->script_migration_versions[ $migration_script_name ];
417
+		}
418
+		$dms_info                                                  = $this->parse_dms_classname($migration_script_name);
419
+		$this->script_migration_versions[ $migration_script_name ] = [
420
+			'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
421
+			'version' => $dms_info['major_version']
422
+						 . "."
423
+						 . $dms_info['minor_version']
424
+						 . "."
425
+						 . $dms_info['micro_version'],
426
+		];
427
+		return $this->script_migration_versions[ $migration_script_name ];
428
+	}
429
+
430
+
431
+	/**
432
+	 * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
433
+	 *
434
+	 * @param string $classname
435
+	 * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are integers)
436
+	 * @throws EE_Error
437
+	 */
438
+	public function parse_dms_classname($classname)
439
+	{
440
+		$matches = [];
441
+		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
442
+		if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
443
+			throw new EE_Error(
444
+				sprintf(
445
+					esc_html__(
446
+						"%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ",
447
+						"event_espresso"
448
+					),
449
+					$classname
450
+				)
451
+			);
452
+		}
453
+		return [
454
+			'slug'          => $matches[1],
455
+			'major_version' => intval($matches[2]),
456
+			'minor_version' => intval($matches[3]),
457
+			'micro_version' => intval($matches[4]),
458
+		];
459
+	}
460
+
461
+
462
+	/**
463
+	 * Ensures that the option indicating the current DB version is set. This should only be
464
+	 * a concern when activating EE for the first time, THEORETICALLY.
465
+	 * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise
466
+	 * to 4.1.x.
467
+	 *
468
+	 * @return string of current db state
469
+	 */
470
+	public function ensure_current_database_state_is_set()
471
+	{
472
+		$espresso_db_core_updates = get_option('espresso_db_update', []);
473
+		$db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
474
+		if (! $db_state) {
475
+			// mark the DB as being in the state as the last version in there.
476
+			// this is done to trigger maintenance mode and do data migration scripts
477
+			// if the admin installed this version of EE over 3.1.x or 4.0.x
478
+			// otherwise, the normal maintenance mode code is fine
479
+			$previous_versions_installed = array_keys($espresso_db_core_updates);
480
+			$previous_version_installed  = end($previous_versions_installed);
481
+			if (version_compare('4.1.0', $previous_version_installed)) {
482
+				// last installed version was less than 4.1, so we want the data migrations to happen.
483
+				// SO, we're going to say the DB is at that state
484
+				$db_state = ['Core' => $previous_version_installed];
485
+			} else {
486
+				$db_state = ['Core' => EVENT_ESPRESSO_VERSION];
487
+			}
488
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
489
+		}
490
+		// in 4.1, $db_state would have only been a simple string like '4.1.0',
491
+		// but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
492
+		// db, and possibly other keys for other addons like 'Calendar','Permissions',etc
493
+		if (! is_array($db_state)) {
494
+			$db_state = ['Core' => $db_state];
495
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
496
+		}
497
+		return $db_state;
498
+	}
499
+
500
+
501
+	/**
502
+	 * Checks if there are any data migration scripts that ought to be run.
503
+	 * If found, returns the instantiated classes.
504
+	 * If none are found (ie, they've all already been run, or they don't apply), returns an empty array
505
+	 *
506
+	 * @return EE_Data_Migration_Script_Base[]
507
+	 * @throws EE_Error
508
+	 * @throws EE_Error
509
+	 */
510
+	public function check_for_applicable_data_migration_scripts()
511
+	{
512
+		// get the option describing what options have already run
513
+		$scripts_ran = $this->get_data_migrations_ran();
514
+		// $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
515
+		$script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
516
+
517
+
518
+		$current_database_state = $this->ensure_current_database_state_is_set();
519
+		// determine which have already been run
520
+		$script_classes_that_should_run_per_iteration = [];
521
+		$iteration                                    = 0;
522
+		$next_database_state_to_consider              = $current_database_state;
523
+		$theoretical_database_state = null;
524
+		do {
525
+			// the next state after the currently-considered one
526
+			// will start off looking the same as the current, but we may make additions...
527
+			$theoretical_database_state = $next_database_state_to_consider;
528
+			// the next db state to consider is
529
+			// "what would the DB be like had we run all the scripts we found that applied last time?"
530
+			foreach ($script_class_and_filepaths_available as $classname => $filepath) {
531
+				$migrates_to_version         = $this->script_migrates_to_version($classname);
532
+				$script_converts_plugin_slug = $migrates_to_version['slug'];
533
+				$script_converts_to_version  = $migrates_to_version['version'];
534
+				// check if this version script is DONE or not; or if it's never been run
535
+				if (
536
+					! $scripts_ran
537
+					|| ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
538
+				) {
539
+					// we haven't run this conversion script before
540
+					// now check if it applies...
541
+					// note that we've added an autoloader for it on get_all_data_migration_scripts_available
542
+					// Also, make sure we get a new one. It's possible this is being ran during a multisite migration,
543
+					// in which case we don't want to reuse a DMS script from a different blog!
544
+					$script = LoaderFactory::getLoader()->getNew($classname);
545
+					/* @var $script EE_Data_Migration_Script_Base */
546
+					$can_migrate = $script->can_migrate_from_version($theoretical_database_state);
547
+					if ($can_migrate) {
548
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
549
+						$migrates_to_version                                                                 =
550
+							$script->migrates_to_version();
551
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
552
+							$migrates_to_version['version'];
553
+						unset($script_class_and_filepaths_available[ $classname ]);
554
+					}
555
+				} elseif (
556
+					$scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
557
+						  instanceof
558
+						  EE_Data_Migration_Script_Base
559
+				) {
560
+					// this script has been run, or at least started
561
+					$script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
562
+					if ($script->get_status() !== self::status_completed) {
563
+						// this script is already underway... keep going with it
564
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
565
+						$migrates_to_version                                                                 =
566
+							$script->migrates_to_version();
567
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
568
+							$migrates_to_version['version'];
569
+						unset($script_class_and_filepaths_available[ $classname ]);
570
+					}
571
+					// else it must have a status that indicates it has finished,
572
+					// so we don't want to try and run it again
573
+				}
574
+				// else it exists, but it's not  a proper data migration script maybe the script got renamed?
575
+				// or was simply removed from EE? either way, it's certainly not runnable!
576
+			}
577
+			$iteration++;
578
+		} while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
579
+		// ok we have all the scripts that should run, now let's make them into flat array
580
+		$scripts_that_should_run = [];
581
+		foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
582
+			ksort($scripts_at_priority);
583
+			foreach ($scripts_at_priority as $scripts) {
584
+				foreach ($scripts as $script) {
585
+					$scripts_that_should_run[ get_class($script) ] = $script;
586
+				}
587
+			}
588
+		}
589
+
590
+		do_action(
591
+			'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
592
+			$scripts_that_should_run
593
+		);
594
+		return $scripts_that_should_run;
595
+	}
596
+
597
+
598
+	/**
599
+	 * Gets the script which is currently being run, if there is one. If $include_completed_scripts is set to TRUE
600
+	 * it will return the last run script even if it's complete.
601
+	 * This means: if you want to find the currently-executing script, leave it as FALSE.
602
+	 * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
603
+	 *
604
+	 * @param bool $include_completed_scripts
605
+	 * @return EE_Data_Migration_Script_Base
606
+	 * @throws EE_Error
607
+	 */
608
+	public function get_last_ran_script($include_completed_scripts = false)
609
+	{
610
+		// make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
611
+		if (! $this->_data_migrations_ran) {
612
+			$this->get_data_migrations_ran();
613
+		}
614
+		if ($include_completed_scripts) {
615
+			return $this->_last_ran_script;
616
+		} else {
617
+			return $this->_last_ran_incomplete_script;
618
+		}
619
+	}
620
+
621
+
622
+	/**
623
+	 * Runs the data migration scripts (well, each request to this method calls one of the
624
+	 * data migration scripts' migration_step() functions).
625
+	 *
626
+	 * @param int   $step_size
627
+	 * @return array {
628
+	 *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
629
+	 *                                  //and the second item is a string describing what was done
630
+	 * @type int    $records_to_migrate from the current migration script
631
+	 * @type int    $records_migrated
632
+	 * @type string $status             one of EE_Data_Migration_Manager::status_*
633
+	 * @type string $script             verbose name of the current DMS
634
+	 * @type string $message            string describing what was done during this step
635
+	 *                                  }
636
+	 * @throws EE_Error
637
+	 */
638
+	public function migration_step($step_size = 0)
639
+	{
640
+
641
+		// bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
642
+		if (class_exists('EE_CPT_Strategy')) {
643
+			remove_action('pre_get_posts', [EE_CPT_Strategy::instance(), 'pre_get_posts'], 5);
644
+		}
645
+
646
+		try {
647
+			$currently_executing_script = $this->get_last_ran_script();
648
+			if (! $currently_executing_script) {
649
+				// Find the next script that needs to execute
650
+				$scripts = $this->check_for_applicable_data_migration_scripts();
651
+				if (! $scripts) {
652
+					// huh, no more scripts to run... apparently we're done!
653
+					// but don't forget to make sure initial data is there
654
+					// we should be good to allow them to exit maintenance mode now
655
+					EE_Maintenance_Mode::instance()->set_maintenance_level(
656
+						EE_Maintenance_Mode::level_0_not_in_maintenance
657
+					);
658
+					// saving migrations run should actually be unnecessary,
659
+					// but leaving in place just in case... remember this migration was finished
660
+					// (even if we time out while initializing db for core and plugins)
661
+					$this->_save_migrations_ran();
662
+					// make sure DB was updated AFTER we've recorded the migration was done
663
+					$this->initialize_db_for_enqueued_ee_plugins();
664
+					return [
665
+						'records_to_migrate' => 1,
666
+						'records_migrated'   => 1,
667
+						'status'             => self::status_no_more_migration_scripts,
668
+						'script'             => esc_html__("Data Migration Completed Successfully", "event_espresso"),
669
+						'message'            => esc_html__("All done!", "event_espresso"),
670
+					];
671
+				}
672
+				$currently_executing_script = array_shift($scripts);
673
+				// and add to the array/wp option showing the scripts run
674
+
675
+				$migrates_to                                            =
676
+					$this->script_migrates_to_version(get_class($currently_executing_script));
677
+				$plugin_slug                                            = $migrates_to['slug'];
678
+				$version                                                = $migrates_to['version'];
679
+				$this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
680
+			}
681
+			$current_script_name = get_class($currently_executing_script);
682
+		} catch (Exception $e) {
683
+			// an exception occurred while trying to get migration scripts
684
+
685
+			$message = sprintf(
686
+				esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
687
+				$e->getMessage() . '<br>',
688
+				$e->getTraceAsString()
689
+			);
690
+			// record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
691
+			// but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
692
+			$this->add_error_to_migrations_ran(
693
+				sprintf(esc_html__("Could not run data migrations because: %s", "event_espresso"), $message)
694
+			);
695
+			return [
696
+				'records_to_migrate' => 1,
697
+				'records_migrated'   => 0,
698
+				'status'             => self::status_fatal_error,
699
+				'script'             => esc_html__("Error loading data migration scripts", "event_espresso"),
700
+				'message'            => $message,
701
+			];
702
+		}
703
+		// can we wrap it up and verify default data?
704
+		$init_dbs = false;
705
+		// ok so we definitely have a data migration script
706
+		try {
707
+			// how big of a bite do we want to take? Allow users to easily override via their wp-config
708
+			if (absint($step_size) < 1) {
709
+				$step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
710
+					? EE_MIGRATION_STEP_SIZE
711
+					: EE_Data_Migration_Manager::step_size;
712
+			}
713
+			// do what we came to do!
714
+			$currently_executing_script->migration_step($step_size);
715
+			switch ($currently_executing_script->get_status()) {
716
+				case EE_Data_Migration_Manager::status_continue:
717
+					$response_array = [
718
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
719
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
720
+						'status'             => EE_Data_Migration_Manager::status_continue,
721
+						'message'            => $currently_executing_script->get_feedback_message(),
722
+						'script'             => $currently_executing_script->pretty_name(),
723
+					];
724
+					break;
725
+				case EE_Data_Migration_Manager::status_completed:
726
+					// ok so THAT script has completed
727
+					$this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
728
+					$response_array = [
729
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
730
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
731
+						'status'             => EE_Data_Migration_Manager::status_completed,
732
+						'message'            => $currently_executing_script->get_feedback_message(),
733
+						'script'             => sprintf(
734
+							esc_html__("%s Completed", 'event_espresso'),
735
+							$currently_executing_script->pretty_name()
736
+						),
737
+					];
738
+					// check if there are any more after this one.
739
+					$scripts_remaining = $this->check_for_applicable_data_migration_scripts();
740
+					if (! $scripts_remaining) {
741
+						// we should be good to allow them to exit maintenance mode now
742
+						EE_Maintenance_Mode::instance()->set_maintenance_level(
743
+							EE_Maintenance_Mode::level_0_not_in_maintenance
744
+						);
745
+						// huh, no more scripts to run... apparently we're done!
746
+						// but don't forget to make sure initial data is there
747
+						$init_dbs                 = true;
748
+						$response_array['status'] = self::status_no_more_migration_scripts;
749
+					}
750
+					break;
751
+				default:
752
+					$response_array = [
753
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
754
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
755
+						'status'             => $currently_executing_script->get_status(),
756
+						'message'            => sprintf(
757
+							esc_html__("Minor errors occurred during %s: %s", "event_espresso"),
758
+							$currently_executing_script->pretty_name(),
759
+							implode(", ", $currently_executing_script->get_errors())
760
+						),
761
+						'script'             => $currently_executing_script->pretty_name(),
762
+					];
763
+					break;
764
+			}
765
+		} catch (Exception $e) {
766
+			// ok so some exception was thrown which killed the data migration script
767
+			// double-check we have a real script
768
+			if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
769
+				$script_name = $currently_executing_script->pretty_name();
770
+				$currently_executing_script->set_broken();
771
+				$currently_executing_script->add_error($e->getMessage());
772
+			} else {
773
+				$script_name = esc_html__("Error getting Migration Script", "event_espresso");
774
+			}
775
+			$response_array = [
776
+				'records_to_migrate' => 1,
777
+				'records_migrated'   => 0,
778
+				'status'             => self::status_fatal_error,
779
+				'message'            => sprintf(
780
+					esc_html__("A fatal error occurred during the migration: %s", "event_espresso"),
781
+					$e->getMessage()
782
+				),
783
+				'script'             => $script_name,
784
+			];
785
+		}
786
+		$successful_save = $this->_save_migrations_ran();
787
+		if ($successful_save !== true) {
788
+			// ok so the current wp option didn't save. that's tricky, because we'd like to update it
789
+			// and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
790
+			// however, if we throw an exception, and return that, then the next request
791
+			// won't have as much info in it, and it may be able to save
792
+			throw new EE_Error(
793
+				sprintf(
794
+					esc_html__(
795
+						"The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.",
796
+						"event_espresso"
797
+					),
798
+					$successful_save
799
+				)
800
+			);
801
+		}
802
+		// if we're all done, initialize EE plugins' default data etc.
803
+		if ($init_dbs) {
804
+			$this->initialize_db_for_enqueued_ee_plugins();
805
+		}
806
+		return $response_array;
807
+	}
808
+
809
+
810
+	/**
811
+	 * Echo out JSON response to migration script AJAX requests. Takes precautions
812
+	 * to buffer output so that we don't throw junk into our json.
813
+	 *
814
+	 * @return array with keys:
815
+	 * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
816
+	 * it's NOT the count of hwo many remain)
817
+	 * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
818
+	 * records_migrated/records_to_migrate)
819
+	 * 'status'=>a string, one of EE_Data_migration_Manager::status_*
820
+	 * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
821
+	 * errors, notifications, and successes
822
+	 * 'script'=>a pretty name of the script currently running
823
+	 */
824
+	public function response_to_migration_ajax_request()
825
+	{
826
+		ob_start();
827
+		try {
828
+			$response = $this->migration_step();
829
+		} catch (Exception $e) {
830
+			$response = [
831
+				'records_to_migrate' => 0,
832
+				'records_migrated'   => 0,
833
+				'status'             => EE_Data_Migration_Manager::status_fatal_error,
834
+				'message'            => sprintf(
835
+					esc_html__("Unknown fatal error occurred: %s", "event_espresso"),
836
+					$e->getMessage()
837
+				),
838
+				'script'             => 'Unknown',
839
+			];
840
+			$this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
841
+		}
842
+		$warnings_etc = @ob_get_contents();
843
+		ob_end_clean();
844
+		$response['message'] .= $warnings_etc;
845
+		return $response;
846
+	}
847
+
848
+
849
+	/**
850
+	 * Updates the WordPress option that keeps track of which EE version the database
851
+	 * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
852
+	 *
853
+	 * @param array $slug_and_version {
854
+	 * @type string $slug             like 'Core' or 'Calendar',
855
+	 * @type string $version          like '4.1.0'
856
+	 *                                }
857
+	 * @return void
858
+	 */
859
+	public function update_current_database_state_to($slug_and_version = null)
860
+	{
861
+		if (! $slug_and_version) {
862
+			// no version was provided, assume it should be at the current code version
863
+			$slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
864
+		}
865
+		$current_database_state                              = get_option(self::current_database_state);
866
+		$current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
867
+		update_option(self::current_database_state, $current_database_state);
868
+	}
869
+
870
+
871
+	/**
872
+	 * Determines if the database is currently at a state matching what's indicated in $slug and $version.
873
+	 *
874
+	 * @param array $slug_and_version {
875
+	 * @type string $slug             like 'Core' or 'Calendar',
876
+	 * @type string $version          like '4.1.0'
877
+	 *                                }
878
+	 * @return boolean
879
+	 */
880
+	public function database_needs_updating_to($slug_and_version)
881
+	{
882
+
883
+		$slug                   = $slug_and_version['slug'];
884
+		$version                = $slug_and_version['version'];
885
+		$current_database_state = get_option(self::current_database_state);
886
+		if (! isset($current_database_state[ $slug ])) {
887
+			return true;
888
+		} else {
889
+			// just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
890
+			$version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
891
+			$version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
892
+			$needs_updating                     = false;
893
+			foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
894
+				if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
895
+					$needs_updating = true;
896
+					break;
897
+				}
898
+			}
899
+			return $needs_updating;
900
+		}
901
+	}
902
+
903
+
904
+	/**
905
+	 * Gets all the data migration scripts available in the core folder and folders
906
+	 * in addons. Has the side effect of adding them for autoloading
907
+	 *
908
+	 * @return array keys are expected classnames, values are their filepaths
909
+	 * @throws InvalidInterfaceException
910
+	 * @throws InvalidDataTypeException
911
+	 * @throws EE_Error
912
+	 * @throws InvalidArgumentException
913
+	 */
914
+	public function get_all_data_migration_scripts_available()
915
+	{
916
+		if (! $this->_data_migration_class_to_filepath_map) {
917
+			$this->_data_migration_class_to_filepath_map = [];
918
+			foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
919
+				// strip any placeholders added to classname to make it a unique array key
920
+				$eeAddonClass = trim($eeAddonClass, '*');
921
+				$eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
922
+					? $eeAddonClass
923
+					: '';
924
+				$folder_path  = EEH_File::end_with_directory_separator($folder_path);
925
+				$files        = glob($folder_path . '*.dms.php');
926
+				if (empty($files)) {
927
+					continue;
928
+				}
929
+				foreach ($files as $file) {
930
+					$pos_of_last_slash = strrpos($file, '/');
931
+					$classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
932
+					$migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
933
+					$slug              = $migrates_to['slug'];
934
+					// check that the slug as contained in the DMS is associated with
935
+					// the slug of an addon or core
936
+					if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
937
+						EE_Error::doing_it_wrong(
938
+							__FUNCTION__,
939
+							sprintf(
940
+								esc_html__(
941
+									'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
942
+									'event_espresso'
943
+								),
944
+								$classname,
945
+								$slug,
946
+								implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
947
+							),
948
+							'4.3.0.alpha.019'
949
+						);
950
+					}
951
+					$this->_data_migration_class_to_filepath_map[ $classname ] = $file;
952
+				}
953
+			}
954
+			EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
955
+		}
956
+		return $this->_data_migration_class_to_filepath_map;
957
+	}
958
+
959
+
960
+	/**
961
+	 * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
962
+	 * from each addon, and check if they need updating,
963
+	 *
964
+	 * @return boolean
965
+	 */
966
+	public function addons_need_updating()
967
+	{
968
+		return false;
969
+	}
970
+
971
+
972
+	/**
973
+	 * Adds this error string to the data_migrations_ran array, but we don't necessarily know
974
+	 * where to put it, so we just throw it in there... better than nothing...
975
+	 *
976
+	 * @param string $error_message
977
+	 */
978
+	public function add_error_to_migrations_ran($error_message)
979
+	{
980
+		// get last-run migration script
981
+		global $wpdb;
982
+		$last_migration_script_option = $wpdb->get_row(
983
+			"SELECT * FROM $wpdb->options WHERE option_name like '"
984
+			. EE_Data_Migration_Manager::data_migration_script_option_prefix
985
+			. "%' ORDER BY option_id DESC LIMIT 1",
986
+			ARRAY_A
987
+		);
988
+
989
+		$last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
990
+			? maybe_unserialize($last_migration_script_option['option_value']) : null;
991
+		// now, tread lightly because we're here because a FATAL non-catchable error
992
+		// was thrown last time when we were trying to run a data migration script
993
+		// so the fatal error could have happened while getting the migration script
994
+		// or doing running it...
995
+		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
996
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
997
+			"",
998
+			$last_migration_script_option['option_name']
999
+		) : null;
1000
+
1001
+		// check if it THINKS it's a data migration script and especially if it's one that HASN'T finished yet
1002
+		// because if it has finished, then it obviously couldn't be the cause of this error, right? (because it's all done)
1003
+		if (
1004
+			isset($last_ran_migration_script_properties['class'])
1005
+			&& isset($last_ran_migration_script_properties['_status'])
1006
+			&& $last_ran_migration_script_properties['_status'] != self::status_completed
1007
+		) {
1008
+			// ok then just add this error to its list of errors
1009
+			$last_ran_migration_script_properties['_errors'][] = $error_message;
1010
+			$last_ran_migration_script_properties['_status']   = self::status_fatal_error;
1011
+		} else {
1012
+			// so we don't even know which script was last running
1013
+			// use the data migration error stub, which is designed specifically for this type of thing
1014
+			$general_migration_error = new EE_DMS_Unknown_1_0_0();
1015
+			$general_migration_error->add_error($error_message);
1016
+			$general_migration_error->set_broken();
1017
+			$last_ran_migration_script_properties = $general_migration_error->properties_as_array();
1018
+			$versions_migrated_to                 = 'Unknown.1.0.0';
1019
+			// now just to make sure appears as last (in case the were previously a fatal error like this)
1020
+			// delete the old one
1021
+			delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1022
+		}
1023
+		update_option(
1024
+			self::data_migration_script_option_prefix . $versions_migrated_to,
1025
+			$last_ran_migration_script_properties
1026
+		);
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * saves what data migrations have run to the database
1032
+	 *
1033
+	 * @return bool|string TRUE if successfully saved migrations ran, string if an error occurred
1034
+	 * @throws EE_Error
1035
+	 */
1036
+	protected function _save_migrations_ran()
1037
+	{
1038
+		if ($this->_data_migrations_ran == null) {
1039
+			$this->get_data_migrations_ran();
1040
+		}
1041
+		// now, we don't want to save actual classes to the DB because that's messy
1042
+		$successful_updates = true;
1043
+		foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1044
+			foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1045
+				$plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1046
+				$option_name                        =
1047
+					self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1048
+				$old_option_value                   = get_option($option_name);
1049
+				if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1050
+					$script_array_for_saving = $array_or_migration_obj->properties_as_array();
1051
+					if ($old_option_value != $script_array_for_saving) {
1052
+						$successful_updates = update_option($option_name, $script_array_for_saving);
1053
+					}
1054
+				} else {// we don't know what this array-thing is. So just save it as-is
1055
+					if ($old_option_value != $array_or_migration_obj) {
1056
+						$successful_updates = update_option($option_name, $array_or_migration_obj);
1057
+					}
1058
+				}
1059
+				if (! $successful_updates) {
1060
+					global $wpdb;
1061
+					return $wpdb->last_error;
1062
+				}
1063
+			}
1064
+		}
1065
+		return true;
1066
+		// $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1067
+		// if ($updated !== true) {
1068
+		//     global $wpdb;
1069
+		//     return $wpdb->last_error;
1070
+		// } else {
1071
+		//     return true;
1072
+		// }
1073
+		// wp_mail(
1074
+		//     "[email protected]",
1075
+		//     time() . " price debug info",
1076
+		//     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1077
+		//         serialize($array_of_migrations)
1078
+		//     )
1079
+		// );
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * Takes an array of data migration script properties and re-creates the class from
1085
+	 * them. The argument $properties_array is assumed to have been made by
1086
+	 * EE_Data_Migration_Script_Base::properties_as_array()
1087
+	 *
1088
+	 * @param array $properties_array
1089
+	 * @return EE_Data_Migration_Script_Base
1090
+	 * @throws EE_Error
1091
+	 */
1092
+	public function _instantiate_script_from_properties_array($properties_array)
1093
+	{
1094
+		if (! isset($properties_array['class'])) {
1095
+			throw new EE_Error(
1096
+				sprintf(
1097
+					esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1098
+					implode(",", $properties_array)
1099
+				)
1100
+			);
1101
+		}
1102
+		$class_name = $properties_array['class'];
1103
+		if (! class_exists($class_name)) {
1104
+			throw new EE_Error(sprintf(
1105
+				esc_html__("There is no migration script named %s", "event_espresso"),
1106
+				$class_name
1107
+			));
1108
+		}
1109
+		$class = new $class_name();
1110
+		if (! $class instanceof EE_Data_Migration_Script_Base) {
1111
+			throw new EE_Error(
1112
+				sprintf(
1113
+					esc_html__(
1114
+						"Class '%s' is supposed to be a migration script. Its not, its a '%s'",
1115
+						"event_espresso"
1116
+					),
1117
+					$class_name,
1118
+					get_class($class)
1119
+				)
1120
+			);
1121
+		}
1122
+		$class->instantiate_from_array_of_properties($properties_array);
1123
+		return $class;
1124
+	}
1125
+
1126
+
1127
+	/**
1128
+	 * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1129
+	 * leave the DB in a state usable by the current plugin code).
1130
+	 *
1131
+	 * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1132
+	 * @return string
1133
+	 * @throws EE_Error
1134
+	 * @throws EE_Error
1135
+	 */
1136
+	public function get_most_up_to_date_dms($plugin_slug = 'Core')
1137
+	{
1138
+		$class_to_filepath_map         = $this->get_all_data_migration_scripts_available();
1139
+		$most_up_to_date_dms_classname = null;
1140
+		foreach ($class_to_filepath_map as $classname => $filepath) {
1141
+			if ($most_up_to_date_dms_classname === null) {
1142
+				$migrates_to      = $this->script_migrates_to_version($classname);
1143
+				$this_plugin_slug = $migrates_to['slug'];
1144
+				if ($this_plugin_slug == $plugin_slug) {
1145
+					// if it's for core, it wins
1146
+					$most_up_to_date_dms_classname = $classname;
1147
+				}
1148
+				// if it wasn't for core, we must keep searching for one that is!
1149
+				continue;
1150
+			}
1151
+			$champion_migrates_to  = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1152
+			$contender_migrates_to = $this->script_migrates_to_version($classname);
1153
+			if (
1154
+				$contender_migrates_to['slug'] == $plugin_slug
1155
+				&& version_compare(
1156
+					$champion_migrates_to['version'],
1157
+					$contender_migrates_to['version'],
1158
+					'<'
1159
+				)
1160
+			) {
1161
+				// so the contenders version is higher, and it's for Core
1162
+				$most_up_to_date_dms_classname = $classname;
1163
+			}
1164
+		}
1165
+		return $most_up_to_date_dms_classname;
1166
+	}
1167
+
1168
+
1169
+	/**
1170
+	 * Gets the migration script specified but ONLY if it has already run.
1171
+	 *
1172
+	 * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has run, you would run the following code:
1173
+	 * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1174
+	 * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1175
+	 * other addon) DMS has run, in case the current DMS depends on it.
1176
+	 *
1177
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1178
+	 *                            period. Eg '4.1.0'
1179
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1180
+	 * @return EE_Data_Migration_Script_Base
1181
+	 * @throws EE_Error
1182
+	 */
1183
+	public function get_migration_ran($version, $plugin_slug = 'Core')
1184
+	{
1185
+		$migrations_ran = $this->get_data_migrations_ran();
1186
+		if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1187
+			return $migrations_ran[ $plugin_slug ][ $version ];
1188
+		} else {
1189
+			return null;
1190
+		}
1191
+	}
1192
+
1193
+
1194
+	/**
1195
+	 * Resets the borked data migration scripts, so they're no longer borked, and we can again attempt to migrate
1196
+	 *
1197
+	 * @return bool
1198
+	 * @throws EE_Error
1199
+	 */
1200
+	public function reattempt()
1201
+	{
1202
+		// find if the last-run script was borked
1203
+		// set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1204
+		// add an 'error' saying that we attempted to reset
1205
+		// does it have a stage that was borked too? if so make it no longer borked
1206
+		// add an 'error' saying we attempted to reset
1207
+		$last_ran_script = $this->get_last_ran_script();
1208
+		if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1209
+			// if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1210
+			$last_ran_script->set_completed();
1211
+		} elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1212
+			$last_ran_script->reattempt();
1213
+		} else {
1214
+			throw new EE_Error(
1215
+				sprintf(
1216
+					esc_html__(
1217
+						'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1218
+						'event_espresso'
1219
+					),
1220
+					print_r($last_ran_script, true)
1221
+				)
1222
+			);
1223
+		}
1224
+		return $this->_save_migrations_ran();
1225
+	}
1226
+
1227
+
1228
+	/**
1229
+	 * Gets whether this particular migration has run or not
1230
+	 *
1231
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1232
+	 *                            period. Eg '4.1.0'
1233
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1234
+	 * @return boolean
1235
+	 * @throws EE_Error
1236
+	 */
1237
+	public function migration_has_ran($version, $plugin_slug = 'Core')
1238
+	{
1239
+		return $this->get_migration_ran($version, $plugin_slug) !== null;
1240
+	}
1241
+
1242
+
1243
+	/**
1244
+	 * Enqueues this ee plugin to have its data initialized
1245
+	 *
1246
+	 * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1247
+	 */
1248
+	public function enqueue_db_initialization_for($plugin_slug)
1249
+	{
1250
+		$queue = $this->get_db_initialization_queue();
1251
+		if (! in_array($plugin_slug, $queue)) {
1252
+			$queue[] = $plugin_slug;
1253
+		}
1254
+		update_option(self::db_init_queue_option_name, $queue);
1255
+	}
1256
+
1257
+
1258
+	/**
1259
+	 * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1260
+	 * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1261
+	 * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1262
+	 *
1263
+	 * @throws EE_Error
1264
+	 */
1265
+	public function initialize_db_for_enqueued_ee_plugins()
1266
+	{
1267
+		$queue = $this->get_db_initialization_queue();
1268
+		foreach ($queue as $plugin_slug) {
1269
+			$most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1270
+			if (! $most_up_to_date_dms) {
1271
+				// if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1272
+				$verify_db = false;
1273
+			} else {
1274
+				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1275
+				$verify_db                       = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1276
+			}
1277
+			if ($plugin_slug == 'Core') {
1278
+				EE_System::instance()->initialize_db_if_no_migrations_required(
1279
+					false,
1280
+					$verify_db
1281
+				);
1282
+			} else {
1283
+				// just loop through the addons to make sure their database is set up
1284
+				foreach (EE_Registry::instance()->addons as $addon) {
1285
+					if ($addon->name() == $plugin_slug) {
1286
+						$addon->initialize_db_if_no_migrations_required($verify_db);
1287
+						break;
1288
+					}
1289
+				}
1290
+			}
1291
+		}
1292
+		// because we just initialized the DBs for the enqueued ee plugins
1293
+		// we don't need to keep remembering which ones needed to be initialized
1294
+		delete_option(self::db_init_queue_option_name);
1295
+	}
1296
+
1297
+
1298
+	/**
1299
+	 * Gets a numerically-indexed array of plugin slugs that need to have their databases
1300
+	 * (re-)initialized after migrations are complete. ie, each element should be either
1301
+	 * 'Core', or the return value of EE_Addon::name() for an addon
1302
+	 *
1303
+	 * @return array
1304
+	 */
1305
+	public function get_db_initialization_queue()
1306
+	{
1307
+		return get_option(self::db_init_queue_option_name, []);
1308
+	}
1309
+
1310
+
1311
+	/**
1312
+	 * Gets the injected table analyzer, or throws an exception
1313
+	 *
1314
+	 * @return TableAnalysis
1315
+	 * @throws EE_Error
1316
+	 */
1317
+	protected function _get_table_analysis()
1318
+	{
1319
+		if ($this->_table_analysis instanceof TableAnalysis) {
1320
+			return $this->_table_analysis;
1321
+		} else {
1322
+			throw new EE_Error(
1323
+				sprintf(
1324
+					esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1325
+					get_class($this)
1326
+				)
1327
+			);
1328
+		}
1329
+	}
1330
+
1331
+
1332
+	/**
1333
+	 * Gets the injected table manager, or throws an exception
1334
+	 *
1335
+	 * @return TableManager
1336
+	 * @throws EE_Error
1337
+	 */
1338
+	protected function _get_table_manager()
1339
+	{
1340
+		if ($this->_table_manager instanceof TableManager) {
1341
+			return $this->_table_manager;
1342
+		} else {
1343
+			throw new EE_Error(
1344
+				sprintf(
1345
+					esc_html__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1346
+					get_class($this)
1347
+				)
1348
+			);
1349
+		}
1350
+	}
1351 1351
 }
Please login to merge, or discard this patch.
Spacing   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
     public static function instance()
164 164
     {
165 165
         // check if class object is instantiated
166
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
166
+        if ( ! self::$_instance instanceof EE_Data_Migration_Manager) {
167 167
             self::$_instance = new self();
168 168
         }
169 169
         return self::$_instance;
@@ -189,11 +189,11 @@  discard block
 block discarded – undo
189 189
      */
190 190
     private function __construct()
191 191
     {
192
-        $this->stati_that_indicate_to_continue_migrations              = [
192
+        $this->stati_that_indicate_to_continue_migrations = [
193 193
             self::status_continue,
194 194
             self::status_completed,
195 195
         ];
196
-        $this->stati_that_indicate_to_stop_migrations                  = [
196
+        $this->stati_that_indicate_to_stop_migrations = [
197 197
             self::status_fatal_error,
198 198
             self::status_no_more_migration_scripts,
199 199
         ];
@@ -241,12 +241,12 @@  discard block
 block discarded – undo
241 241
 
242 242
         if (count($parts) == 4) {
243 243
             // it's 4.2-style.eg Core.4.1.0
244
-            $plugin_slug    = $parts[0];                                     // eg Core
245
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
244
+            $plugin_slug    = $parts[0]; // eg Core
245
+            $version_string = $parts[1].".".$parts[2].".".$parts[3]; // eg 4.1.0
246 246
         } else {
247 247
             // it's 4.1-style: eg 4.1.0
248 248
             $plugin_slug    = 'Core';
249
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
249
+            $version_string = $plugin_slug_and_version_string; // eg 4.1.0
250 250
         }
251 251
         return [$plugin_slug, $version_string];
252 252
     }
@@ -308,11 +308,11 @@  discard block
 block discarded – undo
308 308
      */
309 309
     public function get_data_migrations_ran()
310 310
     {
311
-        if (! $this->_data_migrations_ran) {
311
+        if ( ! $this->_data_migrations_ran) {
312 312
             // setup autoloaders for each of the scripts in there
313 313
             $this->get_all_data_migration_scripts_available();
314 314
             $data_migrations_options =
315
-                $this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
315
+                $this->get_all_migration_script_options(); // get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
316 316
 
317 317
             $data_migrations_ran = [];
318 318
             // convert into data migration script classes where possible
@@ -322,27 +322,27 @@  discard block
 block discarded – undo
322 322
                 );
323 323
 
324 324
                 try {
325
-                    $class                                                  = $this->_get_dms_class_from_wp_option(
325
+                    $class = $this->_get_dms_class_from_wp_option(
326 326
                         $data_migration_option['option_name'],
327 327
                         $data_migration_option['option_value']
328 328
                     );
329
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
329
+                    $data_migrations_ran[$plugin_slug][$version_string] = $class;
330 330
                     // ok so far THIS is the 'last-run-script'... unless we find another on next iteration
331 331
                     $this->_last_ran_script = $class;
332
-                    if (! $class->is_completed()) {
332
+                    if ( ! $class->is_completed()) {
333 333
                         // sometimes we also like to know which was the last incomplete script (or if there are any at all)
334 334
                         $this->_last_ran_incomplete_script = $class;
335 335
                     }
336 336
                 } catch (EE_Error $e) {
337 337
                     // ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
338
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
338
+                    $data_migrations_ran[$plugin_slug][$version_string] = maybe_unserialize(
339 339
                         $data_migration_option['option_value']
340 340
                     );
341 341
                 }
342 342
             }
343 343
             // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
344 344
             $this->_data_migrations_ran = $data_migrations_ran;
345
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
345
+            if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
346 346
                 $this->_data_migrations_ran = [];
347 347
             }
348 348
         }
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
      */
363 363
     public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
364 364
     {
365
-        $script  = EE_Registry::instance()->load_dms($script_name);
365
+        $script = EE_Registry::instance()->load_dms($script_name);
366 366
         return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
367 367
     }
368 368
 
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
     {
396 396
         return apply_filters(
397 397
             'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
398
-            ['Core' => EE_CORE . 'data_migration_scripts']
398
+            ['Core' => EE_CORE.'data_migration_scripts']
399 399
         );
400 400
     }
401 401
 
@@ -412,11 +412,11 @@  discard block
 block discarded – undo
412 412
      */
413 413
     public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
414 414
     {
415
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
416
-            return $this->script_migration_versions[ $migration_script_name ];
415
+        if (isset($this->script_migration_versions[$migration_script_name])) {
416
+            return $this->script_migration_versions[$migration_script_name];
417 417
         }
418 418
         $dms_info                                                  = $this->parse_dms_classname($migration_script_name);
419
-        $this->script_migration_versions[ $migration_script_name ] = [
419
+        $this->script_migration_versions[$migration_script_name] = [
420 420
             'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
421 421
             'version' => $dms_info['major_version']
422 422
                          . "."
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
                          . "."
425 425
                          . $dms_info['micro_version'],
426 426
         ];
427
-        return $this->script_migration_versions[ $migration_script_name ];
427
+        return $this->script_migration_versions[$migration_script_name];
428 428
     }
429 429
 
430 430
 
@@ -439,7 +439,7 @@  discard block
 block discarded – undo
439 439
     {
440 440
         $matches = [];
441 441
         preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
442
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
442
+        if ( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
443 443
             throw new EE_Error(
444 444
                 sprintf(
445 445
                     esc_html__(
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
     {
472 472
         $espresso_db_core_updates = get_option('espresso_db_update', []);
473 473
         $db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
474
-        if (! $db_state) {
474
+        if ( ! $db_state) {
475 475
             // mark the DB as being in the state as the last version in there.
476 476
             // this is done to trigger maintenance mode and do data migration scripts
477 477
             // if the admin installed this version of EE over 3.1.x or 4.0.x
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
         // in 4.1, $db_state would have only been a simple string like '4.1.0',
491 491
         // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
492 492
         // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
493
-        if (! is_array($db_state)) {
493
+        if ( ! is_array($db_state)) {
494 494
             $db_state = ['Core' => $db_state];
495 495
             update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
496 496
         }
@@ -534,7 +534,7 @@  discard block
 block discarded – undo
534 534
                 // check if this version script is DONE or not; or if it's never been run
535 535
                 if (
536 536
                     ! $scripts_ran
537
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
537
+                    || ! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])
538 538
                 ) {
539 539
                     // we haven't run this conversion script before
540 540
                     // now check if it applies...
@@ -545,28 +545,28 @@  discard block
 block discarded – undo
545 545
                     /* @var $script EE_Data_Migration_Script_Base */
546 546
                     $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
547 547
                     if ($can_migrate) {
548
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
548
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
549 549
                         $migrates_to_version                                                                 =
550 550
                             $script->migrates_to_version();
551
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
551
+                        $next_database_state_to_consider[$migrates_to_version['slug']]                     =
552 552
                             $migrates_to_version['version'];
553
-                        unset($script_class_and_filepaths_available[ $classname ]);
553
+                        unset($script_class_and_filepaths_available[$classname]);
554 554
                     }
555 555
                 } elseif (
556
-                    $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
556
+                    $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version]
557 557
                           instanceof
558 558
                           EE_Data_Migration_Script_Base
559 559
                 ) {
560 560
                     // this script has been run, or at least started
561
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
561
+                    $script = $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version];
562 562
                     if ($script->get_status() !== self::status_completed) {
563 563
                         // this script is already underway... keep going with it
564
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
564
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
565 565
                         $migrates_to_version                                                                 =
566 566
                             $script->migrates_to_version();
567
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
567
+                        $next_database_state_to_consider[$migrates_to_version['slug']]                     =
568 568
                             $migrates_to_version['version'];
569
-                        unset($script_class_and_filepaths_available[ $classname ]);
569
+                        unset($script_class_and_filepaths_available[$classname]);
570 570
                     }
571 571
                     // else it must have a status that indicates it has finished,
572 572
                     // so we don't want to try and run it again
@@ -575,14 +575,14 @@  discard block
 block discarded – undo
575 575
                 // or was simply removed from EE? either way, it's certainly not runnable!
576 576
             }
577 577
             $iteration++;
578
-        } while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
578
+        }while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
579 579
         // ok we have all the scripts that should run, now let's make them into flat array
580 580
         $scripts_that_should_run = [];
581 581
         foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
582 582
             ksort($scripts_at_priority);
583 583
             foreach ($scripts_at_priority as $scripts) {
584 584
                 foreach ($scripts as $script) {
585
-                    $scripts_that_should_run[ get_class($script) ] = $script;
585
+                    $scripts_that_should_run[get_class($script)] = $script;
586 586
                 }
587 587
             }
588 588
         }
@@ -608,7 +608,7 @@  discard block
 block discarded – undo
608 608
     public function get_last_ran_script($include_completed_scripts = false)
609 609
     {
610 610
         // make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
611
-        if (! $this->_data_migrations_ran) {
611
+        if ( ! $this->_data_migrations_ran) {
612 612
             $this->get_data_migrations_ran();
613 613
         }
614 614
         if ($include_completed_scripts) {
@@ -645,10 +645,10 @@  discard block
 block discarded – undo
645 645
 
646 646
         try {
647 647
             $currently_executing_script = $this->get_last_ran_script();
648
-            if (! $currently_executing_script) {
648
+            if ( ! $currently_executing_script) {
649 649
                 // Find the next script that needs to execute
650 650
                 $scripts = $this->check_for_applicable_data_migration_scripts();
651
-                if (! $scripts) {
651
+                if ( ! $scripts) {
652 652
                     // huh, no more scripts to run... apparently we're done!
653 653
                     // but don't forget to make sure initial data is there
654 654
                     // we should be good to allow them to exit maintenance mode now
@@ -676,7 +676,7 @@  discard block
 block discarded – undo
676 676
                     $this->script_migrates_to_version(get_class($currently_executing_script));
677 677
                 $plugin_slug                                            = $migrates_to['slug'];
678 678
                 $version                                                = $migrates_to['version'];
679
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
679
+                $this->_data_migrations_ran[$plugin_slug][$version] = $currently_executing_script;
680 680
             }
681 681
             $current_script_name = get_class($currently_executing_script);
682 682
         } catch (Exception $e) {
@@ -684,7 +684,7 @@  discard block
 block discarded – undo
684 684
 
685 685
             $message = sprintf(
686 686
                 esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
687
-                $e->getMessage() . '<br>',
687
+                $e->getMessage().'<br>',
688 688
                 $e->getTraceAsString()
689 689
             );
690 690
             // record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
@@ -737,7 +737,7 @@  discard block
 block discarded – undo
737 737
                     ];
738 738
                     // check if there are any more after this one.
739 739
                     $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
740
-                    if (! $scripts_remaining) {
740
+                    if ( ! $scripts_remaining) {
741 741
                         // we should be good to allow them to exit maintenance mode now
742 742
                         EE_Maintenance_Mode::instance()->set_maintenance_level(
743 743
                             EE_Maintenance_Mode::level_0_not_in_maintenance
@@ -837,7 +837,7 @@  discard block
 block discarded – undo
837 837
                 ),
838 838
                 'script'             => 'Unknown',
839 839
             ];
840
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
840
+            $this->add_error_to_migrations_ran($e->getMessage()."; Stack trace:".$e->getTraceAsString());
841 841
         }
842 842
         $warnings_etc = @ob_get_contents();
843 843
         ob_end_clean();
@@ -858,12 +858,12 @@  discard block
 block discarded – undo
858 858
      */
859 859
     public function update_current_database_state_to($slug_and_version = null)
860 860
     {
861
-        if (! $slug_and_version) {
861
+        if ( ! $slug_and_version) {
862 862
             // no version was provided, assume it should be at the current code version
863 863
             $slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
864 864
         }
865 865
         $current_database_state                              = get_option(self::current_database_state);
866
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
866
+        $current_database_state[$slug_and_version['slug']] = $slug_and_version['version'];
867 867
         update_option(self::current_database_state, $current_database_state);
868 868
     }
869 869
 
@@ -883,15 +883,15 @@  discard block
 block discarded – undo
883 883
         $slug                   = $slug_and_version['slug'];
884 884
         $version                = $slug_and_version['version'];
885 885
         $current_database_state = get_option(self::current_database_state);
886
-        if (! isset($current_database_state[ $slug ])) {
886
+        if ( ! isset($current_database_state[$slug])) {
887 887
             return true;
888 888
         } else {
889 889
             // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
890
-            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
890
+            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[$slug]), 0, 3);
891 891
             $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
892 892
             $needs_updating                     = false;
893 893
             foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
894
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
894
+                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[$offset]) {
895 895
                     $needs_updating = true;
896 896
                     break;
897 897
                 }
@@ -913,7 +913,7 @@  discard block
 block discarded – undo
913 913
      */
914 914
     public function get_all_data_migration_scripts_available()
915 915
     {
916
-        if (! $this->_data_migration_class_to_filepath_map) {
916
+        if ( ! $this->_data_migration_class_to_filepath_map) {
917 917
             $this->_data_migration_class_to_filepath_map = [];
918 918
             foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
919 919
                 // strip any placeholders added to classname to make it a unique array key
@@ -922,7 +922,7 @@  discard block
 block discarded – undo
922 922
                     ? $eeAddonClass
923 923
                     : '';
924 924
                 $folder_path  = EEH_File::end_with_directory_separator($folder_path);
925
-                $files        = glob($folder_path . '*.dms.php');
925
+                $files        = glob($folder_path.'*.dms.php');
926 926
                 if (empty($files)) {
927 927
                     continue;
928 928
                 }
@@ -948,7 +948,7 @@  discard block
 block discarded – undo
948 948
                             '4.3.0.alpha.019'
949 949
                         );
950 950
                     }
951
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
951
+                    $this->_data_migration_class_to_filepath_map[$classname] = $file;
952 952
                 }
953 953
             }
954 954
             EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
@@ -1018,10 +1018,10 @@  discard block
 block discarded – undo
1018 1018
             $versions_migrated_to                 = 'Unknown.1.0.0';
1019 1019
             // now just to make sure appears as last (in case the were previously a fatal error like this)
1020 1020
             // delete the old one
1021
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1021
+            delete_option(self::data_migration_script_option_prefix.$versions_migrated_to);
1022 1022
         }
1023 1023
         update_option(
1024
-            self::data_migration_script_option_prefix . $versions_migrated_to,
1024
+            self::data_migration_script_option_prefix.$versions_migrated_to,
1025 1025
             $last_ran_migration_script_properties
1026 1026
         );
1027 1027
     }
@@ -1042,9 +1042,9 @@  discard block
 block discarded – undo
1042 1042
         $successful_updates = true;
1043 1043
         foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1044 1044
             foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1045
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1045
+                $plugin_slug_for_use_in_option_name = $plugin_slug.".";
1046 1046
                 $option_name                        =
1047
-                    self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1047
+                    self::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string;
1048 1048
                 $old_option_value                   = get_option($option_name);
1049 1049
                 if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1050 1050
                     $script_array_for_saving = $array_or_migration_obj->properties_as_array();
@@ -1056,7 +1056,7 @@  discard block
 block discarded – undo
1056 1056
                         $successful_updates = update_option($option_name, $array_or_migration_obj);
1057 1057
                     }
1058 1058
                 }
1059
-                if (! $successful_updates) {
1059
+                if ( ! $successful_updates) {
1060 1060
                     global $wpdb;
1061 1061
                     return $wpdb->last_error;
1062 1062
                 }
@@ -1091,7 +1091,7 @@  discard block
 block discarded – undo
1091 1091
      */
1092 1092
     public function _instantiate_script_from_properties_array($properties_array)
1093 1093
     {
1094
-        if (! isset($properties_array['class'])) {
1094
+        if ( ! isset($properties_array['class'])) {
1095 1095
             throw new EE_Error(
1096 1096
                 sprintf(
1097 1097
                     esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
@@ -1100,14 +1100,14 @@  discard block
 block discarded – undo
1100 1100
             );
1101 1101
         }
1102 1102
         $class_name = $properties_array['class'];
1103
-        if (! class_exists($class_name)) {
1103
+        if ( ! class_exists($class_name)) {
1104 1104
             throw new EE_Error(sprintf(
1105 1105
                 esc_html__("There is no migration script named %s", "event_espresso"),
1106 1106
                 $class_name
1107 1107
             ));
1108 1108
         }
1109 1109
         $class = new $class_name();
1110
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1110
+        if ( ! $class instanceof EE_Data_Migration_Script_Base) {
1111 1111
             throw new EE_Error(
1112 1112
                 sprintf(
1113 1113
                     esc_html__(
@@ -1183,8 +1183,8 @@  discard block
 block discarded – undo
1183 1183
     public function get_migration_ran($version, $plugin_slug = 'Core')
1184 1184
     {
1185 1185
         $migrations_ran = $this->get_data_migrations_ran();
1186
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1187
-            return $migrations_ran[ $plugin_slug ][ $version ];
1186
+        if (isset($migrations_ran[$plugin_slug]) && isset($migrations_ran[$plugin_slug][$version])) {
1187
+            return $migrations_ran[$plugin_slug][$version];
1188 1188
         } else {
1189 1189
             return null;
1190 1190
         }
@@ -1248,7 +1248,7 @@  discard block
 block discarded – undo
1248 1248
     public function enqueue_db_initialization_for($plugin_slug)
1249 1249
     {
1250 1250
         $queue = $this->get_db_initialization_queue();
1251
-        if (! in_array($plugin_slug, $queue)) {
1251
+        if ( ! in_array($plugin_slug, $queue)) {
1252 1252
             $queue[] = $plugin_slug;
1253 1253
         }
1254 1254
         update_option(self::db_init_queue_option_name, $queue);
@@ -1267,7 +1267,7 @@  discard block
 block discarded – undo
1267 1267
         $queue = $this->get_db_initialization_queue();
1268 1268
         foreach ($queue as $plugin_slug) {
1269 1269
             $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1270
-            if (! $most_up_to_date_dms) {
1270
+            if ( ! $most_up_to_date_dms) {
1271 1271
                 // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1272 1272
                 $verify_db = false;
1273 1273
             } else {
Please login to merge, or discard this patch.
core/EED_Module.module.php 1 patch
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -15,141 +15,141 @@
 block discarded – undo
15 15
 abstract class EED_Module extends EE_Configurable implements ResettableInterface
16 16
 {
17 17
 
18
-    /**
19
-     * rendered output to be returned to WP
20
-     *
21
-     * @var    string $output
22
-     */
23
-    protected $output = '';
24
-
25
-    /**
26
-     * the current active espresso template theme
27
-     *
28
-     * @var    string $theme
29
-     */
30
-    protected $theme = '';
31
-
32
-
33
-    /**
34
-     * @return void
35
-     */
36
-    public static function reset()
37
-    {
38
-        $module_name = get_called_class();
39
-        new $module_name();
40
-    }
41
-
42
-
43
-    /**
44
-     *    set_hooks - for hooking into EE Core, other modules, etc
45
-     *
46
-     * @access    public
47
-     * @return    void
48
-     */
49
-    public static function set_hooks()
50
-    {
51
-    }
52
-
53
-
54
-    /**
55
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
56
-     *
57
-     * @access    public
58
-     * @return    void
59
-     */
60
-    public static function set_hooks_admin()
61
-    {
62
-    }
63
-
64
-
65
-    /**
66
-     *    run - initial module setup
67
-     *    this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters
68
-     *
69
-     * @access    public
70
-     * @var            WP $WP
71
-     * @return    void
72
-     */
73
-    abstract public function run($WP);
74
-
75
-
76
-    /**
77
-     * EED_Module constructor.
78
-     */
79
-    final public function __construct()
80
-    {
81
-        $this->theme = EE_Config::get_current_theme();
82
-        $module_name = $this->module_name();
83
-        EE_Registry::instance()->modules->{$module_name} = $this;
84
-    }
85
-
86
-
87
-    /**
88
-     * @param string $module_name
89
-     * @return EED_Module|mixed
90
-     * @throws EE_Error
91
-     * @throws ReflectionException
92
-     */
93
-    protected static function get_instance($module_name = '')
94
-    {
95
-        $module_name = ! empty($module_name)
96
-            ? $module_name
97
-            : get_called_class();
98
-        if (
99
-            ! isset(EE_Registry::instance()->modules->{$module_name})
100
-            || ! EE_Registry::instance()->modules->{$module_name} instanceof EED_Module
101
-        ) {
102
-            EE_Registry::instance()->add_module($module_name);
103
-        }
104
-        return EE_Registry::instance()->get_module($module_name);
105
-    }
106
-
107
-
108
-    /**
109
-     *    module_name
110
-     *
111
-     * @access    public
112
-     * @return    string
113
-     */
114
-    public function module_name()
115
-    {
116
-        return get_class($this);
117
-    }
118
-
119
-
120
-    /**
121
-     * @return string
122
-     */
123
-    public function theme()
124
-    {
125
-        return $this->theme;
126
-    }
127
-
128
-
129
-    /**
130
-     * @return RequestInterface
131
-     * @since   4.10.14.p
132
-     */
133
-    protected static function getRequest()
134
-    {
135
-        static $request;
136
-        if (! $request instanceof RequestInterface) {
137
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
138
-        }
139
-        return $request;
140
-    }
141
-
142
-
143
-    /**
144
-     * @return ResponseInterface
145
-     * @since   4.10.14.p
146
-     */
147
-    protected static function getResponse()
148
-    {
149
-        static $response;
150
-        if (! $response instanceof RequestInterface) {
151
-            $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class);
152
-        }
153
-        return $response;
154
-    }
18
+	/**
19
+	 * rendered output to be returned to WP
20
+	 *
21
+	 * @var    string $output
22
+	 */
23
+	protected $output = '';
24
+
25
+	/**
26
+	 * the current active espresso template theme
27
+	 *
28
+	 * @var    string $theme
29
+	 */
30
+	protected $theme = '';
31
+
32
+
33
+	/**
34
+	 * @return void
35
+	 */
36
+	public static function reset()
37
+	{
38
+		$module_name = get_called_class();
39
+		new $module_name();
40
+	}
41
+
42
+
43
+	/**
44
+	 *    set_hooks - for hooking into EE Core, other modules, etc
45
+	 *
46
+	 * @access    public
47
+	 * @return    void
48
+	 */
49
+	public static function set_hooks()
50
+	{
51
+	}
52
+
53
+
54
+	/**
55
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
56
+	 *
57
+	 * @access    public
58
+	 * @return    void
59
+	 */
60
+	public static function set_hooks_admin()
61
+	{
62
+	}
63
+
64
+
65
+	/**
66
+	 *    run - initial module setup
67
+	 *    this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters
68
+	 *
69
+	 * @access    public
70
+	 * @var            WP $WP
71
+	 * @return    void
72
+	 */
73
+	abstract public function run($WP);
74
+
75
+
76
+	/**
77
+	 * EED_Module constructor.
78
+	 */
79
+	final public function __construct()
80
+	{
81
+		$this->theme = EE_Config::get_current_theme();
82
+		$module_name = $this->module_name();
83
+		EE_Registry::instance()->modules->{$module_name} = $this;
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param string $module_name
89
+	 * @return EED_Module|mixed
90
+	 * @throws EE_Error
91
+	 * @throws ReflectionException
92
+	 */
93
+	protected static function get_instance($module_name = '')
94
+	{
95
+		$module_name = ! empty($module_name)
96
+			? $module_name
97
+			: get_called_class();
98
+		if (
99
+			! isset(EE_Registry::instance()->modules->{$module_name})
100
+			|| ! EE_Registry::instance()->modules->{$module_name} instanceof EED_Module
101
+		) {
102
+			EE_Registry::instance()->add_module($module_name);
103
+		}
104
+		return EE_Registry::instance()->get_module($module_name);
105
+	}
106
+
107
+
108
+	/**
109
+	 *    module_name
110
+	 *
111
+	 * @access    public
112
+	 * @return    string
113
+	 */
114
+	public function module_name()
115
+	{
116
+		return get_class($this);
117
+	}
118
+
119
+
120
+	/**
121
+	 * @return string
122
+	 */
123
+	public function theme()
124
+	{
125
+		return $this->theme;
126
+	}
127
+
128
+
129
+	/**
130
+	 * @return RequestInterface
131
+	 * @since   4.10.14.p
132
+	 */
133
+	protected static function getRequest()
134
+	{
135
+		static $request;
136
+		if (! $request instanceof RequestInterface) {
137
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
138
+		}
139
+		return $request;
140
+	}
141
+
142
+
143
+	/**
144
+	 * @return ResponseInterface
145
+	 * @since   4.10.14.p
146
+	 */
147
+	protected static function getResponse()
148
+	{
149
+		static $response;
150
+		if (! $response instanceof RequestInterface) {
151
+			$response = LoaderFactory::getLoader()->getShared(ResponseInterface::class);
152
+		}
153
+		return $response;
154
+	}
155 155
 }
Please login to merge, or discard this patch.
modules/events_archive/EED_Events_Archive.module.php 2 patches
Indentation   +1052 added lines, -1052 removed lines patch added patch discarded remove patch
@@ -17,1047 +17,1047 @@  discard block
 block discarded – undo
17 17
 class EED_Events_Archive extends EED_Module
18 18
 {
19 19
 
20
-    const EVENT_DETAILS_PRIORITY   = 100;
21
-
22
-    const EVENT_DATETIMES_PRIORITY = 110;
23
-
24
-    const EVENT_TICKETS_PRIORITY   = 120;
25
-
26
-    const EVENT_VENUES_PRIORITY    = 130;
27
-
28
-
29
-    public static $espresso_event_list_ID    = 0;
30
-
31
-    public static $espresso_grid_event_lists = [];
32
-
33
-    /**
34
-     * @type bool $using_get_the_excerpt
35
-     */
36
-    protected static $using_get_the_excerpt = false;
37
-
38
-    /**
39
-     * Used to flag when the event list is being called from an external iframe.
40
-     *
41
-     * @var bool $iframe
42
-     */
43
-    protected static $iframe = false;
44
-
45
-    /**
46
-     * @var EventListIframeEmbedButton $_iframe_embed_button
47
-     */
48
-    private static $_iframe_embed_button;
49
-
50
-    /**
51
-     * @type EE_Template_Part_Manager $template_parts
52
-     */
53
-    protected $template_parts;
54
-
55
-
56
-    /**
57
-     * @return EED_Events_Archive
58
-     * @throws EE_Error
59
-     * @throws ReflectionException
60
-     */
61
-    public static function instance()
62
-    {
63
-        return parent::get_instance(__CLASS__);
64
-    }
65
-
66
-
67
-    /**
68
-     * for hooking into EE Core, other modules, etc
69
-     *
70
-     * @return void
71
-     * @throws InvalidArgumentException
72
-     * @throws InvalidDataTypeException
73
-     * @throws InvalidInterfaceException
74
-     */
75
-    public static function set_hooks()
76
-    {
77
-        /** @var CustomPostTypeDefinitions $custom_post_type_definitions */
78
-        $custom_post_type_definitions = LoaderFactory::getLoader()->getShared(CustomPostTypeDefinitions::class);
79
-        $custom_post_types            = $custom_post_type_definitions->getDefinitions();
80
-        EE_Config::register_route(
81
-            $custom_post_types['espresso_events']['plural_slug'],
82
-            'Events_Archive',
83
-            'run'
84
-        );
85
-        EE_Config::register_route(
86
-            'event_list',
87
-            'Events_Archive',
88
-            'event_list'
89
-        );
90
-        EE_Config::register_route(
91
-            'iframe',
92
-            'Events_Archive',
93
-            'event_list_iframe',
94
-            'event_list'
95
-        );
96
-        add_action('wp_loaded', ['EED_Events_Archive', 'set_definitions'], 2);
97
-    }
98
-
99
-
100
-    /**
101
-     * for hooking into EE Admin Core, other modules, etc
102
-     *
103
-     * @return void
104
-     */
105
-    public static function set_hooks_admin()
106
-    {
107
-        add_action('wp_loaded', ['EED_Events_Archive', 'set_definitions'], 2);
108
-        // hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
-        // to load assets for "espresso_events" page on the "default" route (action)
110
-        add_action(
111
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
112
-            ['EED_Events_Archive', 'event_list_iframe_embed_button'],
113
-            10
114
-        );
115
-    }
116
-
117
-
118
-    /**
119
-     * @return void
120
-     */
121
-    public static function set_definitions()
122
-    {
123
-        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
124
-        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
125
-    }
126
-
127
-
128
-    /**
129
-     * set up EE_Events_Archive_Config
130
-     */
131
-    protected function set_config()
132
-    {
133
-        $this->set_config_section('template_settings');
134
-        $this->set_config_class('EE_Events_Archive_Config');
135
-        $this->set_config_name('EED_Events_Archive');
136
-    }
137
-
138
-
139
-    /**
140
-     * @return EventListIframeEmbedButton
141
-     */
142
-    public static function get_iframe_embed_button()
143
-    {
144
-        if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
145
-            self::$_iframe_embed_button = new EventListIframeEmbedButton();
146
-        }
147
-        return self::$_iframe_embed_button;
148
-    }
149
-
150
-
151
-    /**
152
-     * @return void
153
-     */
154
-    public static function event_list_iframe_embed_button()
155
-    {
156
-        $iframe_embed_button = EED_Events_Archive::get_iframe_embed_button();
157
-        $iframe_embed_button->addEmbedButton();
158
-    }
159
-
160
-
161
-    /**
162
-     * @param EE_Events_Archive_Config|null $config
163
-     * @return EE_Template_Part_Manager
164
-     * @throws EE_Error
165
-     */
166
-    public function initialize_template_parts(EE_Events_Archive_Config $config = null)
167
-    {
168
-        $config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
169
-        EEH_Autoloader::instance()->register_template_part_autoloaders();
170
-        $template_parts = new EE_Template_Part_Manager();
171
-        $template_parts->add_template_part(
172
-            'tickets',
173
-            esc_html__('Ticket Selector', 'event_espresso'),
174
-            'content-espresso_events-tickets.php',
175
-            $config->display_order_tickets
176
-        );
177
-        $template_parts->add_template_part(
178
-            'datetimes',
179
-            esc_html__('Dates and Times', 'event_espresso'),
180
-            'content-espresso_events-datetimes.php',
181
-            $config->display_order_datetimes
182
-        );
183
-        $template_parts->add_template_part(
184
-            'event',
185
-            esc_html__('Event Description', 'event_espresso'),
186
-            'content-espresso_events-details.php',
187
-            $config->display_order_event
188
-        );
189
-        $template_parts->add_template_part(
190
-            'venue',
191
-            esc_html__('Venue Information', 'event_espresso'),
192
-            'content-espresso_events-venues.php',
193
-            $config->display_order_venue
194
-        );
195
-        do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
196
-        return $template_parts;
197
-    }
198
-
199
-
200
-    /**
201
-     * initial module setup
202
-     * this gets called by the EE_Front_Controller if the module route is found in the incoming request
203
-     *
204
-     * @param WP $WP
205
-     * @return void
206
-     */
207
-    public function run($WP)
208
-    {
209
-        do_action('AHEE__EED_Events_Archive__before_run');
210
-        // ensure valid EE_Events_Archive_Config() object exists
211
-        $this->set_config();
212
-        /** @type EE_Events_Archive_Config $config */
213
-        $config = $this->config();
214
-        // load other required components
215
-        $this->load_event_list_assets();
216
-        // filter the WP posts_join, posts_where, and posts_orderby SQL clauses
217
-        // add query filters
218
-        EEH_Event_Query::add_query_filters();
219
-        // set params that will get used by the filters
220
-        EEH_Event_Query::set_query_params(
221
-            '',                             // month
222
-            '',                             // category
223
-            $config->display_expired_events // show_expired
224
-        );
225
-        // check what template is loaded
226
-        add_filter('template_include', [$this, 'template_include'], 999, 1);
227
-    }
228
-
229
-
230
-    /**
231
-     * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
232
-     *
233
-     * @return void
234
-     */
235
-    public function event_list()
236
-    {
237
-        // ensure valid EE_Events_Archive_Config() object exists
238
-        $this->set_config();
239
-        // load other required components
240
-        $this->load_event_list_assets();
241
-    }
242
-
243
-
244
-    /**
245
-     * @return void
246
-     * @throws EE_Error
247
-     * @throws ReflectionException
248
-     */
249
-    public function event_list_iframe()
250
-    {
251
-        EED_Events_Archive::$iframe = true;
252
-        $event_list_iframe          = new EventsArchiveIframe($this);
253
-        $event_list_iframe->display();
254
-    }
255
-
256
-
257
-    /**
258
-     * @return bool
259
-     */
260
-    public static function is_iframe()
261
-    {
262
-        return EED_Events_Archive::$iframe;
263
-    }
264
-
265
-
266
-    /**
267
-     * @return string
268
-     */
269
-    public static function link_target()
270
-    {
271
-        return EED_Events_Archive::$iframe ? ' target="_blank"' : '';
272
-    }
273
-
274
-
275
-    /**
276
-     * @param string $template
277
-     * @return string
278
-     * @throws EE_Error
279
-     * @throws ReflectionException
280
-     */
281
-    public function template_include($template = '')
282
-    {
283
-        // don't add content filter for dedicated EE child themes or private posts
284
-        if (! EEH_Template::is_espresso_theme()) {
285
-            /** @type EE_Events_Archive_Config $config */
286
-            $config = $this->config();
287
-            // add status banner ?
288
-            if ($config->display_status_banner) {
289
-                add_filter('the_title', ['EED_Events_Archive', 'the_title'], 100, 2);
290
-            }
291
-            // if NOT a custom template
292
-            if (
293
-                apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
294
-                || EE_Registry::instance()
295
-                              ->load_core('Front_Controller')
296
-                              ->get_selected_template() !== 'archive-espresso_events.php'
297
-            ) {
298
-                add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
299
-                // load functions.php file for the theme (loaded by WP if using child theme)
300
-                EEH_Template::load_espresso_theme_functions();
301
-                EED_Events_Archive::addEventDetailsFilters();
302
-                // don't display entry meta because the existing theme will take care of that
303
-                add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
304
-            }
305
-        }
306
-        return $template;
307
-    }
308
-
309
-
310
-    /**
311
-     * kinda hacky, but if a theme is using get_the_excerpt(),
312
-     * then we need to remove our filters on the_content()
313
-     *
314
-     * @param string $excerpt
315
-     * @return string
316
-     * @throws EE_Error
317
-     * @throws ReflectionException
318
-     */
319
-    public static function get_the_excerpt($excerpt = '')
320
-    {
321
-        if (post_password_required()) {
322
-            return $excerpt;
323
-        }
324
-        if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
325
-            EED_Events_Archive::removeEventDetailsFilters(false);
326
-            $excerpt = EED_Events_Archive::event_details($excerpt);
327
-        } else {
328
-            EED_Events_Archive::$using_get_the_excerpt = true;
329
-            add_filter('wp_trim_excerpt', ['EED_Events_Archive', 'end_get_the_excerpt'], 999, 1);
330
-        }
331
-        return $excerpt;
332
-    }
333
-
334
-
335
-    /**
336
-     * @param string $text
337
-     * @return string
338
-     */
339
-    public static function end_get_the_excerpt($text = '')
340
-    {
341
-        EED_Events_Archive::$using_get_the_excerpt = false;
342
-        return $text;
343
-    }
344
-
345
-
346
-    /**
347
-     * @param string $title
348
-     * @param string $id
349
-     * @return string
350
-     * @throws EE_Error
351
-     * @throws ReflectionException
352
-     */
353
-    public static function the_title($title = '', $id = '')
354
-    {
355
-        global $post;
356
-        if ($post instanceof WP_Post) {
357
-            return (EED_Events_Archive::isBlockTheme() || in_the_loop()) && $post->ID == $id
358
-                ? espresso_event_status_banner($post->ID) . $title
359
-                : $title;
360
-        }
361
-        return $title;
362
-    }
363
-
364
-
365
-    /**
366
-     * @param string $content
367
-     * @return string
368
-     * @throws EE_Error
369
-     * @throws ReflectionException
370
-     */
371
-    public static function event_details($content)
372
-    {
373
-        global $post;
374
-        static $current_post_ID = 0;
375
-        if (
376
-            $current_post_ID !== $post->ID
377
-            && $post->post_type === 'espresso_events'
378
-            && ! EED_Events_Archive::$using_get_the_excerpt
379
-            && ! post_password_required()
380
-            && (
381
-                apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
382
-                || ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
383
-            )
384
-        ) {
385
-            // Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
386
-            // Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
387
-            // BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
388
-            // We want to allow those plugins to still do their thing and have access to our content, but depending on
389
-            // how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
390
-            // so the following allows this filter to be applied multiple times, but only once for real
391
-            $current_post_ID = did_action('loop_start') ? $post->ID : 0;
392
-            if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
393
-                $content = EED_Events_Archive::use_sortable_display_order();
394
-            } else {
395
-                $content = EED_Events_Archive::use_filterable_display_order();
396
-            }
397
-        }
398
-        return $content;
399
-    }
400
-
401
-
402
-    /**
403
-     * @return string
404
-     * @throws EE_Error
405
-     * @throws ReflectionException
406
-     */
407
-    protected static function use_sortable_display_order()
408
-    {
409
-        // no further password checks required atm
410
-        add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
411
-        // remove this callback from being applied to the_content()
412
-        EED_Events_Archive::removeEventDetailsFilters();
413
-        // now add additional content depending on whether event is using the_excerpt() or the_content()
414
-        EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
415
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
416
-        $content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
417
-        // re-add our main filters (or else the next event won't have them)
418
-        EED_Events_Archive::addEventDetailsFilters();
419
-        remove_filter(
420
-            'FHEE__EED_Events_Archive__event_details__no_post_password_required',
421
-            '__return_true'
422
-        );
423
-        return $content;
424
-    }
425
-
426
-
427
-    /**
428
-     * @return string
429
-     */
430
-    protected static function use_filterable_display_order()
431
-    {
432
-        // remove this callback from being applied to the_content()
433
-        EED_Events_Archive::removeEventDetailsFilters();
434
-        // now add additional content depending on whether event is using the_excerpt() or the_content()
435
-        EED_Events_Archive::_add_additional_excerpt_filters();
436
-        EED_Events_Archive::_add_additional_content_filters();
437
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
438
-        // now load our template
439
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
440
-        // re-add our main filters (or else the next event won't have them)
441
-        EED_Events_Archive::addEventDetailsFilters();
442
-        // but remove the other filters so that they don't get applied to the next post
443
-        EED_Events_Archive::_remove_additional_events_archive_filters();
444
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
445
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
446
-        // return ! empty( $template ) ? $template : $content;
447
-        return $content;
448
-    }
449
-
450
-
451
-    /**
452
-     * adds datetimes ABOVE content
453
-     *
454
-     * @param string $content
455
-     * @return string
456
-     */
457
-    public static function event_datetimes($content)
458
-    {
459
-        if (post_password_required()) {
460
-            return $content;
461
-        }
462
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
463
-    }
464
-
465
-
466
-    /**
467
-     * adds tickets ABOVE content (which includes datetimes)
468
-     *
469
-     * @param string $content
470
-     * @return string
471
-     */
472
-    public static function event_tickets($content)
473
-    {
474
-        if (post_password_required()) {
475
-            return $content;
476
-        }
477
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
478
-    }
479
-
480
-
481
-    /**
482
-     * adds venues BELOW content
483
-     *
484
-     * @param string $content
485
-     * @return string
486
-     */
487
-    public static function event_venue($content)
488
-    {
489
-        return EED_Events_Archive::event_venues($content);
490
-    }
491
-
492
-
493
-    /**
494
-     * adds venues BELOW content
495
-     *
496
-     * @param string $content
497
-     * @return string
498
-     */
499
-    public static function event_venues($content)
500
-    {
501
-        if (post_password_required()) {
502
-            return $content;
503
-        }
504
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
505
-    }
506
-
507
-
508
-    /**
509
-     * @return bool
510
-     * @since $VID:$
511
-     */
512
-    public static function isBlockTheme()
513
-    {
514
-        return function_exists('wp_is_block_theme') && wp_is_block_theme();
515
-    }
516
-
517
-
518
-    /**
519
-     * @return string
520
-     * @since $VID:$
521
-     */
522
-    public static function getExcerptFilter()
523
-    {
524
-        static $excerpt_filter = null;
525
-        if ($excerpt_filter === null) {
526
-            $excerpt_filter = EED_Events_Archive::isBlockTheme() ? 'get_the_excerpt' : 'the_excerpt';
527
-        }
528
-        return $excerpt_filter;
529
-    }
530
-
531
-
532
-    /**
533
-     * @since $VID:$
534
-     */
535
-    protected static function addEventDetailsFilters()
536
-    {
537
-        add_filter(
538
-            'the_content',
539
-            ['EED_Events_Archive', 'event_details'],
540
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
541
-        );
542
-        // but because we don't know if the theme is using the_excerpt()
543
-        add_filter(
544
-            EED_Events_Archive::getExcerptFilter(),
545
-            ['EED_Events_Archive', 'event_details'],
546
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
547
-        );
548
-        // and just in case they are running get_the_excerpt() which DESTROYS things
549
-        add_filter('get_the_excerpt', ['EED_Events_Archive', 'get_the_excerpt'], 1, 1);
550
-    }
551
-
552
-
553
-    /**
554
-     * @param bool $and_get_the_excerpt
555
-     * @since $VID:$
556
-     */
557
-    protected static function removeEventDetailsFilters($and_get_the_excerpt = true)
558
-    {
559
-        // we need to first remove all callbacks from being applied to the_content()
560
-        // (otherwise it will recurse and blow up the interweb)
561
-        remove_filter(
562
-            'the_content',
563
-            ['EED_Events_Archive', 'event_details'],
564
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
565
-        );
566
-        remove_filter(
567
-            EED_Events_Archive::getExcerptFilter(),
568
-            ['EED_Events_Archive', 'event_details'],
569
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
570
-        );
571
-        if ($and_get_the_excerpt) {
572
-            remove_filter('get_the_excerpt', ['EED_Events_Archive', 'get_the_excerpt'], 1);
573
-        }
574
-    }
575
-
576
-
577
-    /**
578
-     * @return void
579
-     */
580
-    private static function _add_additional_excerpt_filters()
581
-    {
582
-        add_filter(
583
-            EED_Events_Archive::getExcerptFilter(),
584
-            ['EED_Events_Archive', 'event_datetimes'],
585
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
586
-        );
587
-        add_filter(
588
-            EED_Events_Archive::getExcerptFilter(),
589
-            ['EED_Events_Archive', 'event_tickets'],
590
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
591
-        );
592
-        add_filter(
593
-            EED_Events_Archive::getExcerptFilter(),
594
-            ['EED_Events_Archive', 'event_venues'],
595
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
596
-        );
597
-    }
598
-
599
-
600
-    /**
601
-     * @return void
602
-     */
603
-    private static function _add_additional_content_filters()
604
-    {
605
-        add_filter(
606
-            'the_content',
607
-            ['EED_Events_Archive', 'event_datetimes'],
608
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
609
-        );
610
-        add_filter(
611
-            'the_content',
612
-            ['EED_Events_Archive', 'event_tickets'],
613
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
614
-        );
615
-        add_filter(
616
-            'the_content',
617
-            ['EED_Events_Archive', 'event_venues'],
618
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
619
-        );
620
-    }
621
-
622
-
623
-    /**
624
-     * @return void
625
-     */
626
-    private static function _remove_additional_events_archive_filters()
627
-    {
628
-        remove_filter(
629
-            EED_Events_Archive::getExcerptFilter(),
630
-            ['EED_Events_Archive', 'event_datetimes'],
631
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
632
-        );
633
-        remove_filter(
634
-            EED_Events_Archive::getExcerptFilter(),
635
-            ['EED_Events_Archive', 'event_tickets'],
636
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
637
-        );
638
-        remove_filter(
639
-            EED_Events_Archive::getExcerptFilter(),
640
-            ['EED_Events_Archive', 'event_venues'],
641
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
642
-        );
643
-        remove_filter(
644
-            'the_content',
645
-            ['EED_Events_Archive', 'event_datetimes'],
646
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
647
-        );
648
-        remove_filter(
649
-            'the_content',
650
-            ['EED_Events_Archive', 'event_tickets'],
651
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
652
-        );
653
-        remove_filter(
654
-            'the_content',
655
-            ['EED_Events_Archive', 'event_venues'],
656
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
657
-        );
658
-    }
659
-
660
-
661
-    /**
662
-     * @return void
663
-     */
664
-    public static function remove_all_events_archive_filters()
665
-    {
666
-        // remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
667
-        remove_filter('the_title', ['EED_Events_Archive', 'the_title'], 1);
668
-        remove_filter(
669
-            EED_Events_Archive::getExcerptFilter(),
670
-            ['EED_Events_Archive', 'event_details'],
671
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
672
-        );
673
-        remove_filter(
674
-            EED_Events_Archive::getExcerptFilter(),
675
-            ['EED_Events_Archive', 'event_datetimes'],
676
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
677
-        );
678
-        remove_filter(
679
-            EED_Events_Archive::getExcerptFilter(),
680
-            ['EED_Events_Archive', 'event_tickets'],
681
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
682
-        );
683
-        remove_filter(
684
-            EED_Events_Archive::getExcerptFilter(),
685
-            ['EED_Events_Archive', 'event_venues'],
686
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
687
-        );
688
-        remove_filter(
689
-            'the_content',
690
-            ['EED_Events_Archive', 'event_details'],
691
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
692
-        );
693
-        remove_filter(
694
-            'the_content',
695
-            ['EED_Events_Archive', 'event_datetimes'],
696
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
697
-        );
698
-        remove_filter(
699
-            'the_content',
700
-            ['EED_Events_Archive', 'event_tickets'],
701
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
702
-        );
703
-        remove_filter(
704
-            'the_content',
705
-            ['EED_Events_Archive', 'event_venues'],
706
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
707
-        );
708
-        // don't display entry meta because the existing theme will take care of that
709
-        remove_filter(
710
-            'FHEE__content_espresso_events_details_template__display_entry_meta',
711
-            '__return_false'
712
-        );
713
-    }
714
-
715
-
716
-    /**
717
-     * @return void
718
-     */
719
-    public function load_event_list_assets()
720
-    {
721
-        do_action('AHEE__EED_Events_Archive__before_load_assets');
722
-        add_filter('FHEE_load_EE_Session', '__return_true');
723
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
724
-        add_action('wp_enqueue_scripts', [$this, 'wp_enqueue_scripts'], 10);
725
-        if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
726
-            add_action('wp_enqueue_scripts', ['EEH_Maps', 'espresso_google_map_js'], 11);
727
-        }
728
-    }
729
-
730
-
731
-    /**
732
-     * @return void
733
-     * @throws EE_Error
734
-     */
735
-    public function wp_enqueue_scripts()
736
-    {
737
-        // get some style
738
-        if (apply_filters('FHEE_enable_default_espresso_css', false)) {
739
-            // first check uploads folder
740
-            if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
741
-                wp_register_style(
742
-                    $this->theme,
743
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
744
-                    ['dashicons', 'espresso_default']
745
-                );
746
-            }
747
-            wp_enqueue_style($this->theme);
748
-        }
749
-    }
750
-
751
-
752
-    /**
753
-     * @static
754
-     * @return void
755
-     */
756
-    public static function template_settings_form()
757
-    {
758
-        $template_settings                     = EE_Registry::instance()->CFG->template_settings;
759
-        $template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive)
760
-            ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
761
-        $template_settings->EED_Events_Archive = apply_filters(
762
-            'FHEE__EED_Events_Archive__template_settings_form__event_list_config',
763
-            $template_settings->EED_Events_Archive
764
-        );
765
-        $events_archive_settings               = [
766
-            'display_status_banner'   => 0,
767
-            'display_description'     => 1,
768
-            'display_ticket_selector' => 0,
769
-            'display_datetimes'       => 1,
770
-            'display_venue'           => 0,
771
-            'display_expired_events'  => 0,
772
-        ];
773
-        $events_archive_settings               = array_merge(
774
-            $events_archive_settings,
775
-            (array) $template_settings->EED_Events_Archive
776
-        );
777
-        EEH_Template::display_template(
778
-            EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php',
779
-            $events_archive_settings
780
-        );
781
-    }
782
-
783
-
784
-    /**
785
-     * @param EE_Template_Config $CFG
786
-     * @param array              $REQ
787
-     * @return EE_Template_Config
788
-     */
789
-    public static function update_template_settings($CFG, $REQ)
790
-    {
791
-        $CFG->EED_Events_Archive = new EE_Events_Archive_Config();
792
-        // unless we are resetting the config...
793
-        if (
794
-            ! isset($REQ['EED_Events_Archive_reset_event_list_settings'])
795
-            || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1
796
-        ) {
797
-            $CFG->EED_Events_Archive->display_status_banner   = isset($REQ['EED_Events_Archive_display_status_banner'])
798
-                ? absint($REQ['EED_Events_Archive_display_status_banner'])
799
-                : 0;
800
-            $CFG->EED_Events_Archive->display_description     = isset($REQ['EED_Events_Archive_display_description'])
801
-                ? absint($REQ['EED_Events_Archive_display_description'])
802
-                : 1;
803
-            $CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector'])
804
-                ? absint($REQ['EED_Events_Archive_display_ticket_selector'])
805
-                : 0;
806
-            $CFG->EED_Events_Archive->display_datetimes       = isset($REQ['EED_Events_Archive_display_datetimes'])
807
-                ? absint($REQ['EED_Events_Archive_display_datetimes'])
808
-                : 1;
809
-            $CFG->EED_Events_Archive->display_venue           = isset($REQ['EED_Events_Archive_display_venue'])
810
-                ? absint($REQ['EED_Events_Archive_display_venue'])
811
-                : 0;
812
-            $CFG->EED_Events_Archive->display_expired_events  = isset($REQ['EED_Events_Archive_display_expired_events'])
813
-                ? absint($REQ['EED_Events_Archive_display_expired_events'])
814
-                : 0;
815
-        }
816
-        return $CFG;
817
-    }
818
-
819
-
820
-    /**
821
-     * @param string $extra_class
822
-     * @return string
823
-     */
824
-    public static function event_list_css($extra_class = '')
825
-    {
826
-        $event_list_css   = ! empty($extra_class) ? [$extra_class] : [];
827
-        $event_list_css[] = 'espresso-event-list-event';
828
-        return implode(' ', $event_list_css);
829
-    }
830
-
831
-
832
-    /**
833
-     * @return array
834
-     * @throws EE_Error
835
-     * @throws ReflectionException
836
-     */
837
-    public static function event_categories()
838
-    {
839
-        return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
840
-    }
841
-
842
-
843
-    /**
844
-     * @param $value
845
-     * @return bool
846
-     */
847
-    public static function display_description($value)
848
-    {
849
-        $config              = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
850
-        $display_description = isset($config->display_description) ? $config->display_description : 1;
851
-        return $display_description === $value;
852
-    }
853
-
854
-
855
-    /**
856
-     * @return bool
857
-     */
858
-    public static function display_ticket_selector()
859
-    {
860
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
861
-        return isset($config->display_ticket_selector) && $config->display_ticket_selector;
862
-    }
863
-
864
-
865
-    /**
866
-     * @return bool
867
-     * @throws EE_Error
868
-     * @throws ReflectionException
869
-     */
870
-    public static function display_venue()
871
-    {
872
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
873
-        return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name();
874
-    }
875
-
876
-
877
-    /**
878
-     * @return bool
879
-     */
880
-    public static function display_datetimes()
881
-    {
882
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
883
-        return isset($config->display_datetimes) && $config->display_datetimes;
884
-    }
885
-
886
-
887
-    /**
888
-     * @return string
889
-     */
890
-    public static function event_list_title()
891
-    {
892
-        return apply_filters(
893
-            'FHEE__archive_espresso_events_template__upcoming_events_h1',
894
-            esc_html__('Upcoming Events', 'event_espresso')
895
-        );
896
-    }
897
-
898
-
899
-    // GRAVEYARD
900
-
901
-
902
-    /**
903
-     * @since 4.4.0
904
-     */
905
-    public static function _doing_it_wrong_notice($function = '')
906
-    {
907
-        EE_Error::doing_it_wrong(
908
-            __FUNCTION__,
909
-            sprintf(
910
-                esc_html__(
911
-                    'EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s',
912
-                    'event_espresso'
913
-                ),
914
-                $function,
915
-                '<br />',
916
-                '4.6.0'
917
-            ),
918
-            '4.4.0'
919
-        );
920
-    }
921
-
922
-
923
-    /**
924
-     * @deprecated
925
-     * @since 4.4.0
926
-     */
927
-    public function get_post_data()
928
-    {
929
-        EEH_Event_Query::set_query_params();
930
-    }
931
-
932
-
933
-    /**
934
-     * @throws EE_Error
935
-     * @since 4.4.0
936
-     * @deprecated
937
-     */
938
-    public function posts_fields($SQL, WP_Query $wp_query)
939
-    {
940
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
941
-        return EEH_Event_Query::posts_fields($SQL, $wp_query);
942
-    }
943
-
944
-
945
-    /**
946
-     * @throws EE_Error
947
-     * @since 4.4.0
948
-     * @deprecated
949
-     */
950
-    public static function posts_fields_sql_for_orderby($orderby_params = [])
951
-    {
952
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
953
-        return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
954
-    }
955
-
956
-
957
-    /**
958
-     * @throws EE_Error
959
-     * @since 4.4.0
960
-     * @deprecated
961
-     */
962
-    public function posts_join($SQL, WP_Query $wp_query)
963
-    {
964
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
965
-        return EEH_Event_Query::posts_join($SQL, $wp_query);
966
-    }
967
-
968
-
969
-    /**
970
-     * @deprecated
971
-     * @since 4.4.0
972
-     */
973
-    public static function posts_join_sql_for_terms($join_terms = null)
974
-    {
975
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
976
-        return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
977
-    }
978
-
979
-
980
-    /**
981
-     * @throws EE_Error
982
-     * @since 4.4.0
983
-     * @deprecated
984
-     */
985
-    public static function posts_join_for_orderby($orderby_params = [])
986
-    {
987
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
988
-        return EEH_Event_Query::posts_join_for_orderby($orderby_params);
989
-    }
990
-
991
-
992
-    /**
993
-     * @throws EE_Error
994
-     * @since 4.4.0
995
-     * @deprecated
996
-     */
997
-    public function posts_where($SQL, WP_Query $wp_query)
998
-    {
999
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1000
-        return EEH_Event_Query::posts_where($SQL, $wp_query);
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * @throws EE_Error
1006
-     * @since 4.4.0
1007
-     * @deprecated
1008
-     */
1009
-    public static function posts_where_sql_for_show_expired($show_expired = false)
1010
-    {
1011
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1012
-        return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * @deprecated
1018
-     * @since 4.4.0
1019
-     */
1020
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1021
-    {
1022
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1023
-        return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * @throws EE_Error
1029
-     * @since 4.4.0
1030
-     * @deprecated
1031
-     */
1032
-    public static function posts_where_sql_for_event_list_month($month = null)
1033
-    {
1034
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1035
-        return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * @throws EE_Error
1041
-     * @since 4.4.0
1042
-     * @deprecated
1043
-     */
1044
-    public function posts_orderby($SQL, WP_Query $wp_query)
1045
-    {
1046
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1047
-        return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1048
-    }
1049
-
1050
-
1051
-    /**
1052
-     * @throws EE_Error
1053
-     * @since 4.4.0
1054
-     * @deprecated
1055
-     */
1056
-    public static function posts_orderby_sql($orderby_params = [], $sort = 'ASC')
1057
-    {
1058
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1059
-        return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1060
-    }
20
+	const EVENT_DETAILS_PRIORITY   = 100;
21
+
22
+	const EVENT_DATETIMES_PRIORITY = 110;
23
+
24
+	const EVENT_TICKETS_PRIORITY   = 120;
25
+
26
+	const EVENT_VENUES_PRIORITY    = 130;
27
+
28
+
29
+	public static $espresso_event_list_ID    = 0;
30
+
31
+	public static $espresso_grid_event_lists = [];
32
+
33
+	/**
34
+	 * @type bool $using_get_the_excerpt
35
+	 */
36
+	protected static $using_get_the_excerpt = false;
37
+
38
+	/**
39
+	 * Used to flag when the event list is being called from an external iframe.
40
+	 *
41
+	 * @var bool $iframe
42
+	 */
43
+	protected static $iframe = false;
44
+
45
+	/**
46
+	 * @var EventListIframeEmbedButton $_iframe_embed_button
47
+	 */
48
+	private static $_iframe_embed_button;
49
+
50
+	/**
51
+	 * @type EE_Template_Part_Manager $template_parts
52
+	 */
53
+	protected $template_parts;
54
+
55
+
56
+	/**
57
+	 * @return EED_Events_Archive
58
+	 * @throws EE_Error
59
+	 * @throws ReflectionException
60
+	 */
61
+	public static function instance()
62
+	{
63
+		return parent::get_instance(__CLASS__);
64
+	}
65
+
66
+
67
+	/**
68
+	 * for hooking into EE Core, other modules, etc
69
+	 *
70
+	 * @return void
71
+	 * @throws InvalidArgumentException
72
+	 * @throws InvalidDataTypeException
73
+	 * @throws InvalidInterfaceException
74
+	 */
75
+	public static function set_hooks()
76
+	{
77
+		/** @var CustomPostTypeDefinitions $custom_post_type_definitions */
78
+		$custom_post_type_definitions = LoaderFactory::getLoader()->getShared(CustomPostTypeDefinitions::class);
79
+		$custom_post_types            = $custom_post_type_definitions->getDefinitions();
80
+		EE_Config::register_route(
81
+			$custom_post_types['espresso_events']['plural_slug'],
82
+			'Events_Archive',
83
+			'run'
84
+		);
85
+		EE_Config::register_route(
86
+			'event_list',
87
+			'Events_Archive',
88
+			'event_list'
89
+		);
90
+		EE_Config::register_route(
91
+			'iframe',
92
+			'Events_Archive',
93
+			'event_list_iframe',
94
+			'event_list'
95
+		);
96
+		add_action('wp_loaded', ['EED_Events_Archive', 'set_definitions'], 2);
97
+	}
98
+
99
+
100
+	/**
101
+	 * for hooking into EE Admin Core, other modules, etc
102
+	 *
103
+	 * @return void
104
+	 */
105
+	public static function set_hooks_admin()
106
+	{
107
+		add_action('wp_loaded', ['EED_Events_Archive', 'set_definitions'], 2);
108
+		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
+		// to load assets for "espresso_events" page on the "default" route (action)
110
+		add_action(
111
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
112
+			['EED_Events_Archive', 'event_list_iframe_embed_button'],
113
+			10
114
+		);
115
+	}
116
+
117
+
118
+	/**
119
+	 * @return void
120
+	 */
121
+	public static function set_definitions()
122
+	{
123
+		define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
124
+		define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
125
+	}
126
+
127
+
128
+	/**
129
+	 * set up EE_Events_Archive_Config
130
+	 */
131
+	protected function set_config()
132
+	{
133
+		$this->set_config_section('template_settings');
134
+		$this->set_config_class('EE_Events_Archive_Config');
135
+		$this->set_config_name('EED_Events_Archive');
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return EventListIframeEmbedButton
141
+	 */
142
+	public static function get_iframe_embed_button()
143
+	{
144
+		if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
145
+			self::$_iframe_embed_button = new EventListIframeEmbedButton();
146
+		}
147
+		return self::$_iframe_embed_button;
148
+	}
149
+
150
+
151
+	/**
152
+	 * @return void
153
+	 */
154
+	public static function event_list_iframe_embed_button()
155
+	{
156
+		$iframe_embed_button = EED_Events_Archive::get_iframe_embed_button();
157
+		$iframe_embed_button->addEmbedButton();
158
+	}
159
+
160
+
161
+	/**
162
+	 * @param EE_Events_Archive_Config|null $config
163
+	 * @return EE_Template_Part_Manager
164
+	 * @throws EE_Error
165
+	 */
166
+	public function initialize_template_parts(EE_Events_Archive_Config $config = null)
167
+	{
168
+		$config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
169
+		EEH_Autoloader::instance()->register_template_part_autoloaders();
170
+		$template_parts = new EE_Template_Part_Manager();
171
+		$template_parts->add_template_part(
172
+			'tickets',
173
+			esc_html__('Ticket Selector', 'event_espresso'),
174
+			'content-espresso_events-tickets.php',
175
+			$config->display_order_tickets
176
+		);
177
+		$template_parts->add_template_part(
178
+			'datetimes',
179
+			esc_html__('Dates and Times', 'event_espresso'),
180
+			'content-espresso_events-datetimes.php',
181
+			$config->display_order_datetimes
182
+		);
183
+		$template_parts->add_template_part(
184
+			'event',
185
+			esc_html__('Event Description', 'event_espresso'),
186
+			'content-espresso_events-details.php',
187
+			$config->display_order_event
188
+		);
189
+		$template_parts->add_template_part(
190
+			'venue',
191
+			esc_html__('Venue Information', 'event_espresso'),
192
+			'content-espresso_events-venues.php',
193
+			$config->display_order_venue
194
+		);
195
+		do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
196
+		return $template_parts;
197
+	}
198
+
199
+
200
+	/**
201
+	 * initial module setup
202
+	 * this gets called by the EE_Front_Controller if the module route is found in the incoming request
203
+	 *
204
+	 * @param WP $WP
205
+	 * @return void
206
+	 */
207
+	public function run($WP)
208
+	{
209
+		do_action('AHEE__EED_Events_Archive__before_run');
210
+		// ensure valid EE_Events_Archive_Config() object exists
211
+		$this->set_config();
212
+		/** @type EE_Events_Archive_Config $config */
213
+		$config = $this->config();
214
+		// load other required components
215
+		$this->load_event_list_assets();
216
+		// filter the WP posts_join, posts_where, and posts_orderby SQL clauses
217
+		// add query filters
218
+		EEH_Event_Query::add_query_filters();
219
+		// set params that will get used by the filters
220
+		EEH_Event_Query::set_query_params(
221
+			'',                             // month
222
+			'',                             // category
223
+			$config->display_expired_events // show_expired
224
+		);
225
+		// check what template is loaded
226
+		add_filter('template_include', [$this, 'template_include'], 999, 1);
227
+	}
228
+
229
+
230
+	/**
231
+	 * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
232
+	 *
233
+	 * @return void
234
+	 */
235
+	public function event_list()
236
+	{
237
+		// ensure valid EE_Events_Archive_Config() object exists
238
+		$this->set_config();
239
+		// load other required components
240
+		$this->load_event_list_assets();
241
+	}
242
+
243
+
244
+	/**
245
+	 * @return void
246
+	 * @throws EE_Error
247
+	 * @throws ReflectionException
248
+	 */
249
+	public function event_list_iframe()
250
+	{
251
+		EED_Events_Archive::$iframe = true;
252
+		$event_list_iframe          = new EventsArchiveIframe($this);
253
+		$event_list_iframe->display();
254
+	}
255
+
256
+
257
+	/**
258
+	 * @return bool
259
+	 */
260
+	public static function is_iframe()
261
+	{
262
+		return EED_Events_Archive::$iframe;
263
+	}
264
+
265
+
266
+	/**
267
+	 * @return string
268
+	 */
269
+	public static function link_target()
270
+	{
271
+		return EED_Events_Archive::$iframe ? ' target="_blank"' : '';
272
+	}
273
+
274
+
275
+	/**
276
+	 * @param string $template
277
+	 * @return string
278
+	 * @throws EE_Error
279
+	 * @throws ReflectionException
280
+	 */
281
+	public function template_include($template = '')
282
+	{
283
+		// don't add content filter for dedicated EE child themes or private posts
284
+		if (! EEH_Template::is_espresso_theme()) {
285
+			/** @type EE_Events_Archive_Config $config */
286
+			$config = $this->config();
287
+			// add status banner ?
288
+			if ($config->display_status_banner) {
289
+				add_filter('the_title', ['EED_Events_Archive', 'the_title'], 100, 2);
290
+			}
291
+			// if NOT a custom template
292
+			if (
293
+				apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
294
+				|| EE_Registry::instance()
295
+							  ->load_core('Front_Controller')
296
+							  ->get_selected_template() !== 'archive-espresso_events.php'
297
+			) {
298
+				add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
299
+				// load functions.php file for the theme (loaded by WP if using child theme)
300
+				EEH_Template::load_espresso_theme_functions();
301
+				EED_Events_Archive::addEventDetailsFilters();
302
+				// don't display entry meta because the existing theme will take care of that
303
+				add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
304
+			}
305
+		}
306
+		return $template;
307
+	}
308
+
309
+
310
+	/**
311
+	 * kinda hacky, but if a theme is using get_the_excerpt(),
312
+	 * then we need to remove our filters on the_content()
313
+	 *
314
+	 * @param string $excerpt
315
+	 * @return string
316
+	 * @throws EE_Error
317
+	 * @throws ReflectionException
318
+	 */
319
+	public static function get_the_excerpt($excerpt = '')
320
+	{
321
+		if (post_password_required()) {
322
+			return $excerpt;
323
+		}
324
+		if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
325
+			EED_Events_Archive::removeEventDetailsFilters(false);
326
+			$excerpt = EED_Events_Archive::event_details($excerpt);
327
+		} else {
328
+			EED_Events_Archive::$using_get_the_excerpt = true;
329
+			add_filter('wp_trim_excerpt', ['EED_Events_Archive', 'end_get_the_excerpt'], 999, 1);
330
+		}
331
+		return $excerpt;
332
+	}
333
+
334
+
335
+	/**
336
+	 * @param string $text
337
+	 * @return string
338
+	 */
339
+	public static function end_get_the_excerpt($text = '')
340
+	{
341
+		EED_Events_Archive::$using_get_the_excerpt = false;
342
+		return $text;
343
+	}
344
+
345
+
346
+	/**
347
+	 * @param string $title
348
+	 * @param string $id
349
+	 * @return string
350
+	 * @throws EE_Error
351
+	 * @throws ReflectionException
352
+	 */
353
+	public static function the_title($title = '', $id = '')
354
+	{
355
+		global $post;
356
+		if ($post instanceof WP_Post) {
357
+			return (EED_Events_Archive::isBlockTheme() || in_the_loop()) && $post->ID == $id
358
+				? espresso_event_status_banner($post->ID) . $title
359
+				: $title;
360
+		}
361
+		return $title;
362
+	}
363
+
364
+
365
+	/**
366
+	 * @param string $content
367
+	 * @return string
368
+	 * @throws EE_Error
369
+	 * @throws ReflectionException
370
+	 */
371
+	public static function event_details($content)
372
+	{
373
+		global $post;
374
+		static $current_post_ID = 0;
375
+		if (
376
+			$current_post_ID !== $post->ID
377
+			&& $post->post_type === 'espresso_events'
378
+			&& ! EED_Events_Archive::$using_get_the_excerpt
379
+			&& ! post_password_required()
380
+			&& (
381
+				apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
382
+				|| ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
383
+			)
384
+		) {
385
+			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
386
+			// Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
387
+			// BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
388
+			// We want to allow those plugins to still do their thing and have access to our content, but depending on
389
+			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
390
+			// so the following allows this filter to be applied multiple times, but only once for real
391
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
392
+			if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
393
+				$content = EED_Events_Archive::use_sortable_display_order();
394
+			} else {
395
+				$content = EED_Events_Archive::use_filterable_display_order();
396
+			}
397
+		}
398
+		return $content;
399
+	}
400
+
401
+
402
+	/**
403
+	 * @return string
404
+	 * @throws EE_Error
405
+	 * @throws ReflectionException
406
+	 */
407
+	protected static function use_sortable_display_order()
408
+	{
409
+		// no further password checks required atm
410
+		add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
411
+		// remove this callback from being applied to the_content()
412
+		EED_Events_Archive::removeEventDetailsFilters();
413
+		// now add additional content depending on whether event is using the_excerpt() or the_content()
414
+		EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
415
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
416
+		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
417
+		// re-add our main filters (or else the next event won't have them)
418
+		EED_Events_Archive::addEventDetailsFilters();
419
+		remove_filter(
420
+			'FHEE__EED_Events_Archive__event_details__no_post_password_required',
421
+			'__return_true'
422
+		);
423
+		return $content;
424
+	}
425
+
426
+
427
+	/**
428
+	 * @return string
429
+	 */
430
+	protected static function use_filterable_display_order()
431
+	{
432
+		// remove this callback from being applied to the_content()
433
+		EED_Events_Archive::removeEventDetailsFilters();
434
+		// now add additional content depending on whether event is using the_excerpt() or the_content()
435
+		EED_Events_Archive::_add_additional_excerpt_filters();
436
+		EED_Events_Archive::_add_additional_content_filters();
437
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
438
+		// now load our template
439
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
440
+		// re-add our main filters (or else the next event won't have them)
441
+		EED_Events_Archive::addEventDetailsFilters();
442
+		// but remove the other filters so that they don't get applied to the next post
443
+		EED_Events_Archive::_remove_additional_events_archive_filters();
444
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
445
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
446
+		// return ! empty( $template ) ? $template : $content;
447
+		return $content;
448
+	}
449
+
450
+
451
+	/**
452
+	 * adds datetimes ABOVE content
453
+	 *
454
+	 * @param string $content
455
+	 * @return string
456
+	 */
457
+	public static function event_datetimes($content)
458
+	{
459
+		if (post_password_required()) {
460
+			return $content;
461
+		}
462
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
463
+	}
464
+
465
+
466
+	/**
467
+	 * adds tickets ABOVE content (which includes datetimes)
468
+	 *
469
+	 * @param string $content
470
+	 * @return string
471
+	 */
472
+	public static function event_tickets($content)
473
+	{
474
+		if (post_password_required()) {
475
+			return $content;
476
+		}
477
+		return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
478
+	}
479
+
480
+
481
+	/**
482
+	 * adds venues BELOW content
483
+	 *
484
+	 * @param string $content
485
+	 * @return string
486
+	 */
487
+	public static function event_venue($content)
488
+	{
489
+		return EED_Events_Archive::event_venues($content);
490
+	}
491
+
492
+
493
+	/**
494
+	 * adds venues BELOW content
495
+	 *
496
+	 * @param string $content
497
+	 * @return string
498
+	 */
499
+	public static function event_venues($content)
500
+	{
501
+		if (post_password_required()) {
502
+			return $content;
503
+		}
504
+		return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
505
+	}
506
+
507
+
508
+	/**
509
+	 * @return bool
510
+	 * @since $VID:$
511
+	 */
512
+	public static function isBlockTheme()
513
+	{
514
+		return function_exists('wp_is_block_theme') && wp_is_block_theme();
515
+	}
516
+
517
+
518
+	/**
519
+	 * @return string
520
+	 * @since $VID:$
521
+	 */
522
+	public static function getExcerptFilter()
523
+	{
524
+		static $excerpt_filter = null;
525
+		if ($excerpt_filter === null) {
526
+			$excerpt_filter = EED_Events_Archive::isBlockTheme() ? 'get_the_excerpt' : 'the_excerpt';
527
+		}
528
+		return $excerpt_filter;
529
+	}
530
+
531
+
532
+	/**
533
+	 * @since $VID:$
534
+	 */
535
+	protected static function addEventDetailsFilters()
536
+	{
537
+		add_filter(
538
+			'the_content',
539
+			['EED_Events_Archive', 'event_details'],
540
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
541
+		);
542
+		// but because we don't know if the theme is using the_excerpt()
543
+		add_filter(
544
+			EED_Events_Archive::getExcerptFilter(),
545
+			['EED_Events_Archive', 'event_details'],
546
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
547
+		);
548
+		// and just in case they are running get_the_excerpt() which DESTROYS things
549
+		add_filter('get_the_excerpt', ['EED_Events_Archive', 'get_the_excerpt'], 1, 1);
550
+	}
551
+
552
+
553
+	/**
554
+	 * @param bool $and_get_the_excerpt
555
+	 * @since $VID:$
556
+	 */
557
+	protected static function removeEventDetailsFilters($and_get_the_excerpt = true)
558
+	{
559
+		// we need to first remove all callbacks from being applied to the_content()
560
+		// (otherwise it will recurse and blow up the interweb)
561
+		remove_filter(
562
+			'the_content',
563
+			['EED_Events_Archive', 'event_details'],
564
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
565
+		);
566
+		remove_filter(
567
+			EED_Events_Archive::getExcerptFilter(),
568
+			['EED_Events_Archive', 'event_details'],
569
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
570
+		);
571
+		if ($and_get_the_excerpt) {
572
+			remove_filter('get_the_excerpt', ['EED_Events_Archive', 'get_the_excerpt'], 1);
573
+		}
574
+	}
575
+
576
+
577
+	/**
578
+	 * @return void
579
+	 */
580
+	private static function _add_additional_excerpt_filters()
581
+	{
582
+		add_filter(
583
+			EED_Events_Archive::getExcerptFilter(),
584
+			['EED_Events_Archive', 'event_datetimes'],
585
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
586
+		);
587
+		add_filter(
588
+			EED_Events_Archive::getExcerptFilter(),
589
+			['EED_Events_Archive', 'event_tickets'],
590
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
591
+		);
592
+		add_filter(
593
+			EED_Events_Archive::getExcerptFilter(),
594
+			['EED_Events_Archive', 'event_venues'],
595
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
596
+		);
597
+	}
598
+
599
+
600
+	/**
601
+	 * @return void
602
+	 */
603
+	private static function _add_additional_content_filters()
604
+	{
605
+		add_filter(
606
+			'the_content',
607
+			['EED_Events_Archive', 'event_datetimes'],
608
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
609
+		);
610
+		add_filter(
611
+			'the_content',
612
+			['EED_Events_Archive', 'event_tickets'],
613
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
614
+		);
615
+		add_filter(
616
+			'the_content',
617
+			['EED_Events_Archive', 'event_venues'],
618
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
619
+		);
620
+	}
621
+
622
+
623
+	/**
624
+	 * @return void
625
+	 */
626
+	private static function _remove_additional_events_archive_filters()
627
+	{
628
+		remove_filter(
629
+			EED_Events_Archive::getExcerptFilter(),
630
+			['EED_Events_Archive', 'event_datetimes'],
631
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
632
+		);
633
+		remove_filter(
634
+			EED_Events_Archive::getExcerptFilter(),
635
+			['EED_Events_Archive', 'event_tickets'],
636
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
637
+		);
638
+		remove_filter(
639
+			EED_Events_Archive::getExcerptFilter(),
640
+			['EED_Events_Archive', 'event_venues'],
641
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
642
+		);
643
+		remove_filter(
644
+			'the_content',
645
+			['EED_Events_Archive', 'event_datetimes'],
646
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
647
+		);
648
+		remove_filter(
649
+			'the_content',
650
+			['EED_Events_Archive', 'event_tickets'],
651
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
652
+		);
653
+		remove_filter(
654
+			'the_content',
655
+			['EED_Events_Archive', 'event_venues'],
656
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
657
+		);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @return void
663
+	 */
664
+	public static function remove_all_events_archive_filters()
665
+	{
666
+		// remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
667
+		remove_filter('the_title', ['EED_Events_Archive', 'the_title'], 1);
668
+		remove_filter(
669
+			EED_Events_Archive::getExcerptFilter(),
670
+			['EED_Events_Archive', 'event_details'],
671
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
672
+		);
673
+		remove_filter(
674
+			EED_Events_Archive::getExcerptFilter(),
675
+			['EED_Events_Archive', 'event_datetimes'],
676
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
677
+		);
678
+		remove_filter(
679
+			EED_Events_Archive::getExcerptFilter(),
680
+			['EED_Events_Archive', 'event_tickets'],
681
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
682
+		);
683
+		remove_filter(
684
+			EED_Events_Archive::getExcerptFilter(),
685
+			['EED_Events_Archive', 'event_venues'],
686
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
687
+		);
688
+		remove_filter(
689
+			'the_content',
690
+			['EED_Events_Archive', 'event_details'],
691
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
692
+		);
693
+		remove_filter(
694
+			'the_content',
695
+			['EED_Events_Archive', 'event_datetimes'],
696
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
697
+		);
698
+		remove_filter(
699
+			'the_content',
700
+			['EED_Events_Archive', 'event_tickets'],
701
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
702
+		);
703
+		remove_filter(
704
+			'the_content',
705
+			['EED_Events_Archive', 'event_venues'],
706
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
707
+		);
708
+		// don't display entry meta because the existing theme will take care of that
709
+		remove_filter(
710
+			'FHEE__content_espresso_events_details_template__display_entry_meta',
711
+			'__return_false'
712
+		);
713
+	}
714
+
715
+
716
+	/**
717
+	 * @return void
718
+	 */
719
+	public function load_event_list_assets()
720
+	{
721
+		do_action('AHEE__EED_Events_Archive__before_load_assets');
722
+		add_filter('FHEE_load_EE_Session', '__return_true');
723
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
724
+		add_action('wp_enqueue_scripts', [$this, 'wp_enqueue_scripts'], 10);
725
+		if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
726
+			add_action('wp_enqueue_scripts', ['EEH_Maps', 'espresso_google_map_js'], 11);
727
+		}
728
+	}
729
+
730
+
731
+	/**
732
+	 * @return void
733
+	 * @throws EE_Error
734
+	 */
735
+	public function wp_enqueue_scripts()
736
+	{
737
+		// get some style
738
+		if (apply_filters('FHEE_enable_default_espresso_css', false)) {
739
+			// first check uploads folder
740
+			if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
741
+				wp_register_style(
742
+					$this->theme,
743
+					get_stylesheet_directory_uri() . $this->theme . '/style.css',
744
+					['dashicons', 'espresso_default']
745
+				);
746
+			}
747
+			wp_enqueue_style($this->theme);
748
+		}
749
+	}
750
+
751
+
752
+	/**
753
+	 * @static
754
+	 * @return void
755
+	 */
756
+	public static function template_settings_form()
757
+	{
758
+		$template_settings                     = EE_Registry::instance()->CFG->template_settings;
759
+		$template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive)
760
+			? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
761
+		$template_settings->EED_Events_Archive = apply_filters(
762
+			'FHEE__EED_Events_Archive__template_settings_form__event_list_config',
763
+			$template_settings->EED_Events_Archive
764
+		);
765
+		$events_archive_settings               = [
766
+			'display_status_banner'   => 0,
767
+			'display_description'     => 1,
768
+			'display_ticket_selector' => 0,
769
+			'display_datetimes'       => 1,
770
+			'display_venue'           => 0,
771
+			'display_expired_events'  => 0,
772
+		];
773
+		$events_archive_settings               = array_merge(
774
+			$events_archive_settings,
775
+			(array) $template_settings->EED_Events_Archive
776
+		);
777
+		EEH_Template::display_template(
778
+			EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php',
779
+			$events_archive_settings
780
+		);
781
+	}
782
+
783
+
784
+	/**
785
+	 * @param EE_Template_Config $CFG
786
+	 * @param array              $REQ
787
+	 * @return EE_Template_Config
788
+	 */
789
+	public static function update_template_settings($CFG, $REQ)
790
+	{
791
+		$CFG->EED_Events_Archive = new EE_Events_Archive_Config();
792
+		// unless we are resetting the config...
793
+		if (
794
+			! isset($REQ['EED_Events_Archive_reset_event_list_settings'])
795
+			|| absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1
796
+		) {
797
+			$CFG->EED_Events_Archive->display_status_banner   = isset($REQ['EED_Events_Archive_display_status_banner'])
798
+				? absint($REQ['EED_Events_Archive_display_status_banner'])
799
+				: 0;
800
+			$CFG->EED_Events_Archive->display_description     = isset($REQ['EED_Events_Archive_display_description'])
801
+				? absint($REQ['EED_Events_Archive_display_description'])
802
+				: 1;
803
+			$CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector'])
804
+				? absint($REQ['EED_Events_Archive_display_ticket_selector'])
805
+				: 0;
806
+			$CFG->EED_Events_Archive->display_datetimes       = isset($REQ['EED_Events_Archive_display_datetimes'])
807
+				? absint($REQ['EED_Events_Archive_display_datetimes'])
808
+				: 1;
809
+			$CFG->EED_Events_Archive->display_venue           = isset($REQ['EED_Events_Archive_display_venue'])
810
+				? absint($REQ['EED_Events_Archive_display_venue'])
811
+				: 0;
812
+			$CFG->EED_Events_Archive->display_expired_events  = isset($REQ['EED_Events_Archive_display_expired_events'])
813
+				? absint($REQ['EED_Events_Archive_display_expired_events'])
814
+				: 0;
815
+		}
816
+		return $CFG;
817
+	}
818
+
819
+
820
+	/**
821
+	 * @param string $extra_class
822
+	 * @return string
823
+	 */
824
+	public static function event_list_css($extra_class = '')
825
+	{
826
+		$event_list_css   = ! empty($extra_class) ? [$extra_class] : [];
827
+		$event_list_css[] = 'espresso-event-list-event';
828
+		return implode(' ', $event_list_css);
829
+	}
830
+
831
+
832
+	/**
833
+	 * @return array
834
+	 * @throws EE_Error
835
+	 * @throws ReflectionException
836
+	 */
837
+	public static function event_categories()
838
+	{
839
+		return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
840
+	}
841
+
842
+
843
+	/**
844
+	 * @param $value
845
+	 * @return bool
846
+	 */
847
+	public static function display_description($value)
848
+	{
849
+		$config              = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
850
+		$display_description = isset($config->display_description) ? $config->display_description : 1;
851
+		return $display_description === $value;
852
+	}
853
+
854
+
855
+	/**
856
+	 * @return bool
857
+	 */
858
+	public static function display_ticket_selector()
859
+	{
860
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
861
+		return isset($config->display_ticket_selector) && $config->display_ticket_selector;
862
+	}
863
+
864
+
865
+	/**
866
+	 * @return bool
867
+	 * @throws EE_Error
868
+	 * @throws ReflectionException
869
+	 */
870
+	public static function display_venue()
871
+	{
872
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
873
+		return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name();
874
+	}
875
+
876
+
877
+	/**
878
+	 * @return bool
879
+	 */
880
+	public static function display_datetimes()
881
+	{
882
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
883
+		return isset($config->display_datetimes) && $config->display_datetimes;
884
+	}
885
+
886
+
887
+	/**
888
+	 * @return string
889
+	 */
890
+	public static function event_list_title()
891
+	{
892
+		return apply_filters(
893
+			'FHEE__archive_espresso_events_template__upcoming_events_h1',
894
+			esc_html__('Upcoming Events', 'event_espresso')
895
+		);
896
+	}
897
+
898
+
899
+	// GRAVEYARD
900
+
901
+
902
+	/**
903
+	 * @since 4.4.0
904
+	 */
905
+	public static function _doing_it_wrong_notice($function = '')
906
+	{
907
+		EE_Error::doing_it_wrong(
908
+			__FUNCTION__,
909
+			sprintf(
910
+				esc_html__(
911
+					'EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s',
912
+					'event_espresso'
913
+				),
914
+				$function,
915
+				'<br />',
916
+				'4.6.0'
917
+			),
918
+			'4.4.0'
919
+		);
920
+	}
921
+
922
+
923
+	/**
924
+	 * @deprecated
925
+	 * @since 4.4.0
926
+	 */
927
+	public function get_post_data()
928
+	{
929
+		EEH_Event_Query::set_query_params();
930
+	}
931
+
932
+
933
+	/**
934
+	 * @throws EE_Error
935
+	 * @since 4.4.0
936
+	 * @deprecated
937
+	 */
938
+	public function posts_fields($SQL, WP_Query $wp_query)
939
+	{
940
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
941
+		return EEH_Event_Query::posts_fields($SQL, $wp_query);
942
+	}
943
+
944
+
945
+	/**
946
+	 * @throws EE_Error
947
+	 * @since 4.4.0
948
+	 * @deprecated
949
+	 */
950
+	public static function posts_fields_sql_for_orderby($orderby_params = [])
951
+	{
952
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
953
+		return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
954
+	}
955
+
956
+
957
+	/**
958
+	 * @throws EE_Error
959
+	 * @since 4.4.0
960
+	 * @deprecated
961
+	 */
962
+	public function posts_join($SQL, WP_Query $wp_query)
963
+	{
964
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
965
+		return EEH_Event_Query::posts_join($SQL, $wp_query);
966
+	}
967
+
968
+
969
+	/**
970
+	 * @deprecated
971
+	 * @since 4.4.0
972
+	 */
973
+	public static function posts_join_sql_for_terms($join_terms = null)
974
+	{
975
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
976
+		return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
977
+	}
978
+
979
+
980
+	/**
981
+	 * @throws EE_Error
982
+	 * @since 4.4.0
983
+	 * @deprecated
984
+	 */
985
+	public static function posts_join_for_orderby($orderby_params = [])
986
+	{
987
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
988
+		return EEH_Event_Query::posts_join_for_orderby($orderby_params);
989
+	}
990
+
991
+
992
+	/**
993
+	 * @throws EE_Error
994
+	 * @since 4.4.0
995
+	 * @deprecated
996
+	 */
997
+	public function posts_where($SQL, WP_Query $wp_query)
998
+	{
999
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1000
+		return EEH_Event_Query::posts_where($SQL, $wp_query);
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * @throws EE_Error
1006
+	 * @since 4.4.0
1007
+	 * @deprecated
1008
+	 */
1009
+	public static function posts_where_sql_for_show_expired($show_expired = false)
1010
+	{
1011
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1012
+		return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * @deprecated
1018
+	 * @since 4.4.0
1019
+	 */
1020
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1021
+	{
1022
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1023
+		return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * @throws EE_Error
1029
+	 * @since 4.4.0
1030
+	 * @deprecated
1031
+	 */
1032
+	public static function posts_where_sql_for_event_list_month($month = null)
1033
+	{
1034
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1035
+		return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * @throws EE_Error
1041
+	 * @since 4.4.0
1042
+	 * @deprecated
1043
+	 */
1044
+	public function posts_orderby($SQL, WP_Query $wp_query)
1045
+	{
1046
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1047
+		return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1048
+	}
1049
+
1050
+
1051
+	/**
1052
+	 * @throws EE_Error
1053
+	 * @since 4.4.0
1054
+	 * @deprecated
1055
+	 */
1056
+	public static function posts_orderby_sql($orderby_params = [], $sort = 'ASC')
1057
+	{
1058
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1059
+		return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1060
+	}
1061 1061
 }
1062 1062
 
1063 1063
 
@@ -1066,9 +1066,9 @@  discard block
 block discarded – undo
1066 1066
  */
1067 1067
 function espresso_get_event_list_ID()
1068 1068
 {
1069
-    EED_Events_Archive::$espresso_event_list_ID++;
1070
-    EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1071
-    return EED_Events_Archive::$espresso_event_list_ID;
1069
+	EED_Events_Archive::$espresso_event_list_ID++;
1070
+	EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1071
+	return EED_Events_Archive::$espresso_event_list_ID;
1072 1072
 }
1073 1073
 
1074 1074
 
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
  */
1078 1078
 function espresso_event_list_title()
1079 1079
 {
1080
-    return EED_Events_Archive::event_list_title();
1080
+	return EED_Events_Archive::event_list_title();
1081 1081
 }
1082 1082
 
1083 1083
 
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
  */
1088 1088
 function espresso_event_list_css($extra_class = '')
1089 1089
 {
1090
-    return EED_Events_Archive::event_list_css($extra_class);
1090
+	return EED_Events_Archive::event_list_css($extra_class);
1091 1091
 }
1092 1092
 
1093 1093
 
@@ -1098,7 +1098,7 @@  discard block
 block discarded – undo
1098 1098
  */
1099 1099
 function espresso_get_event_categories()
1100 1100
 {
1101
-    return EED_Events_Archive::event_categories();
1101
+	return EED_Events_Archive::event_categories();
1102 1102
 }
1103 1103
 
1104 1104
 
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
  */
1108 1108
 function espresso_display_full_description_in_event_list()
1109 1109
 {
1110
-    return EED_Events_Archive::display_description(2);
1110
+	return EED_Events_Archive::display_description(2);
1111 1111
 }
1112 1112
 
1113 1113
 
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
  */
1117 1117
 function espresso_display_excerpt_in_event_list()
1118 1118
 {
1119
-    return EED_Events_Archive::display_description(1);
1119
+	return EED_Events_Archive::display_description(1);
1120 1120
 }
1121 1121
 
1122 1122
 
@@ -1125,7 +1125,7 @@  discard block
 block discarded – undo
1125 1125
  */
1126 1126
 function espresso_display_ticket_selector_in_event_list()
1127 1127
 {
1128
-    return EED_Events_Archive::display_ticket_selector();
1128
+	return EED_Events_Archive::display_ticket_selector();
1129 1129
 }
1130 1130
 
1131 1131
 
@@ -1136,7 +1136,7 @@  discard block
 block discarded – undo
1136 1136
  */
1137 1137
 function espresso_display_venue_in_event_list()
1138 1138
 {
1139
-    return EED_Events_Archive::display_venue();
1139
+	return EED_Events_Archive::display_venue();
1140 1140
 }
1141 1141
 
1142 1142
 
@@ -1145,5 +1145,5 @@  discard block
 block discarded – undo
1145 1145
  */
1146 1146
 function espresso_display_datetimes_in_event_list()
1147 1147
 {
1148
-    return EED_Events_Archive::display_datetimes();
1148
+	return EED_Events_Archive::display_datetimes();
1149 1149
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -120,8 +120,8 @@  discard block
 block discarded – undo
120 120
      */
121 121
     public static function set_definitions()
122 122
     {
123
-        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
124
-        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
123
+        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__).'assets/');
124
+        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)).'templates/');
125 125
     }
126 126
 
127 127
 
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
      */
142 142
     public static function get_iframe_embed_button()
143 143
     {
144
-        if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
144
+        if ( ! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
145 145
             self::$_iframe_embed_button = new EventListIframeEmbedButton();
146 146
         }
147 147
         return self::$_iframe_embed_button;
@@ -218,8 +218,8 @@  discard block
 block discarded – undo
218 218
         EEH_Event_Query::add_query_filters();
219 219
         // set params that will get used by the filters
220 220
         EEH_Event_Query::set_query_params(
221
-            '',                             // month
222
-            '',                             // category
221
+            '', // month
222
+            '', // category
223 223
             $config->display_expired_events // show_expired
224 224
         );
225 225
         // check what template is loaded
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
     public function template_include($template = '')
282 282
     {
283 283
         // don't add content filter for dedicated EE child themes or private posts
284
-        if (! EEH_Template::is_espresso_theme()) {
284
+        if ( ! EEH_Template::is_espresso_theme()) {
285 285
             /** @type EE_Events_Archive_Config $config */
286 286
             $config = $this->config();
287 287
             // add status banner ?
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
         global $post;
356 356
         if ($post instanceof WP_Post) {
357 357
             return (EED_Events_Archive::isBlockTheme() || in_the_loop()) && $post->ID == $id
358
-                ? espresso_event_status_banner($post->ID) . $title
358
+                ? espresso_event_status_banner($post->ID).$title
359 359
                 : $title;
360 360
         }
361 361
         return $title;
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
         if (post_password_required()) {
460 460
             return $content;
461 461
         }
462
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
462
+        return EEH_Template::locate_template('content-espresso_events-datetimes.php').$content;
463 463
     }
464 464
 
465 465
 
@@ -474,7 +474,7 @@  discard block
 block discarded – undo
474 474
         if (post_password_required()) {
475 475
             return $content;
476 476
         }
477
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
477
+        return EEH_Template::locate_template('content-espresso_events-tickets.php').$content;
478 478
     }
479 479
 
480 480
 
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
         if (post_password_required()) {
502 502
             return $content;
503 503
         }
504
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
504
+        return $content.EEH_Template::locate_template('content-espresso_events-venues.php');
505 505
     }
506 506
 
507 507
 
@@ -737,10 +737,10 @@  discard block
 block discarded – undo
737 737
         // get some style
738 738
         if (apply_filters('FHEE_enable_default_espresso_css', false)) {
739 739
             // first check uploads folder
740
-            if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
740
+            if (EEH_File::is_readable(get_stylesheet_directory().$this->theme.'/style.css')) {
741 741
                 wp_register_style(
742 742
                     $this->theme,
743
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
743
+                    get_stylesheet_directory_uri().$this->theme.'/style.css',
744 744
                     ['dashicons', 'espresso_default']
745 745
                 );
746 746
             }
@@ -762,7 +762,7 @@  discard block
 block discarded – undo
762 762
             'FHEE__EED_Events_Archive__template_settings_form__event_list_config',
763 763
             $template_settings->EED_Events_Archive
764 764
         );
765
-        $events_archive_settings               = [
765
+        $events_archive_settings = [
766 766
             'display_status_banner'   => 0,
767 767
             'display_description'     => 1,
768 768
             'display_ticket_selector' => 0,
@@ -770,12 +770,12 @@  discard block
 block discarded – undo
770 770
             'display_venue'           => 0,
771 771
             'display_expired_events'  => 0,
772 772
         ];
773
-        $events_archive_settings               = array_merge(
773
+        $events_archive_settings = array_merge(
774 774
             $events_archive_settings,
775 775
             (array) $template_settings->EED_Events_Archive
776 776
         );
777 777
         EEH_Template::display_template(
778
-            EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php',
778
+            EVENTS_ARCHIVE_TEMPLATES_PATH.'admin-event-list-settings.template.php',
779 779
             $events_archive_settings
780 780
         );
781 781
     }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.10.33.rc.011');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.10.33.rc.011');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
141 141
\ No newline at end of file
Please login to merge, or discard this patch.