Completed
Branch BUG/3575-event-deletion-previe... (bbeda1)
by
unknown
06:40 queued 04:49
created
core/EE_Data_Migration_Manager.core.php 2 patches
Indentation   +1312 added lines, -1312 removed lines patch added patch discarded remove patch
@@ -32,1316 +32,1316 @@
 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
-            $class = LoaderFactory::getLoader()->getShared($data_migration_data['class']);
269
-            if ($class instanceof EE_Data_Migration_Script_Base) {
270
-                $class->instantiate_from_array_of_properties($data_migration_data);
271
-                return $class;
272
-            } else {
273
-                // huh, so it's an object but not a data migration script?? that shouldn't happen
274
-                // just leave it as an array (which will probably just get ignored)
275
-                throw new EE_Error(
276
-                    sprintf(
277
-                        esc_html__(
278
-                            "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
279
-                            'event_espresso'
280
-                        ),
281
-                        $data_migration_data['class']
282
-                    )
283
-                );
284
-            }
285
-        } else {
286
-            // 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
287
-            throw new EE_Error(
288
-                sprintf(
289
-                    esc_html__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'),
290
-                    $dms_option_name
291
-                )
292
-            );
293
-        }
294
-    }
295
-
296
-
297
-    /**
298
-     * Gets the array describing what data migrations have run.
299
-     * Also has a side effect of recording which was the last run,
300
-     * and which was the last run which hasn't finished yet
301
-     *
302
-     * @return array where each element should be an array of EE_Data_Migration_Script_Base
303
-     *               (but also has a few legacy arrays in there - which should probably be ignored)
304
-     * @throws EE_Error
305
-     */
306
-    public function get_data_migrations_ran()
307
-    {
308
-        if (! $this->_data_migrations_ran) {
309
-            // setup autoloaders for each of the scripts in there
310
-            $this->get_all_data_migration_scripts_available();
311
-            $data_migrations_options =
312
-                $this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
313
-
314
-            $data_migrations_ran = [];
315
-            // convert into data migration script classes where possible
316
-            foreach ($data_migrations_options as $data_migration_option) {
317
-                list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
318
-                    $data_migration_option['option_name']
319
-                );
320
-
321
-                try {
322
-                    $class                                                  = $this->_get_dms_class_from_wp_option(
323
-                        $data_migration_option['option_name'],
324
-                        $data_migration_option['option_value']
325
-                    );
326
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
327
-                    // ok so far THIS is the 'last-run-script'... unless we find another on next iteration
328
-                    $this->_last_ran_script = $class;
329
-                    if (! $class->is_completed()) {
330
-                        // sometimes we also like to know which was the last incomplete script (or if there are any at all)
331
-                        $this->_last_ran_incomplete_script = $class;
332
-                    }
333
-                } catch (EE_Error $e) {
334
-                    // ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
335
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
336
-                        $data_migration_option['option_value']
337
-                    );
338
-                }
339
-            }
340
-            // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
341
-            $this->_data_migrations_ran = $data_migrations_ran;
342
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
343
-                $this->_data_migrations_ran = [];
344
-            }
345
-        }
346
-        return $this->_data_migrations_ran;
347
-    }
348
-
349
-
350
-    /**
351
-     *
352
-     * @param string $script_name eg 'DMS_Core_4_1_0'
353
-     * @param string $old_table   eg 'wp_events_detail'
354
-     * @param string $old_pk      eg 'wp_esp_posts'
355
-     * @param        $new_table
356
-     * @return mixed string or int
357
-     * @throws EE_Error
358
-     * @throws ReflectionException
359
-     */
360
-    public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
361
-    {
362
-        $script  = EE_Registry::instance()->load_dms($script_name);
363
-        return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
364
-    }
365
-
366
-
367
-    /**
368
-     * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
369
-     * the last option returned in this array is the most-recently run DMS option
370
-     *
371
-     * @return array
372
-     */
373
-    public function get_all_migration_script_options()
374
-    {
375
-        global $wpdb;
376
-        return $wpdb->get_results(
377
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '"
378
-            . EE_Data_Migration_Manager::data_migration_script_option_prefix
379
-            . "%' ORDER BY option_id ASC",
380
-            ARRAY_A
381
-        );
382
-    }
383
-
384
-
385
-    /**
386
-     * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
387
-     *
388
-     * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
389
-     *               slashes at the end of the folder name.
390
-     */
391
-    public function get_data_migration_script_folders()
392
-    {
393
-        return apply_filters(
394
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
395
-            ['Core' => EE_CORE . 'data_migration_scripts']
396
-        );
397
-    }
398
-
399
-
400
-    /**
401
-     * Gets the version the migration script upgrades to
402
-     *
403
-     * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
404
-     * @return array {
405
-     *      @type string  $slug     like 'Core','Calendar',etc
406
-     *      @type string  $version  like 4.3.0
407
-     * }
408
-     * @throws EE_Error
409
-     */
410
-    public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
411
-    {
412
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
413
-            return $this->script_migration_versions[ $migration_script_name ];
414
-        }
415
-        $dms_info                                                  = $this->parse_dms_classname($migration_script_name);
416
-        $this->script_migration_versions[ $migration_script_name ] = [
417
-            'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
418
-            'version' => $dms_info['major_version']
419
-                         . "."
420
-                         . $dms_info['minor_version']
421
-                         . "."
422
-                         . $dms_info['micro_version'],
423
-        ];
424
-        return $this->script_migration_versions[ $migration_script_name ];
425
-    }
426
-
427
-
428
-    /**
429
-     * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
430
-     *
431
-     * @param string $classname
432
-     * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are integers)
433
-     * @throws EE_Error
434
-     */
435
-    public function parse_dms_classname($classname)
436
-    {
437
-        $matches = [];
438
-        preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
439
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
440
-            throw new EE_Error(
441
-                sprintf(
442
-                    esc_html__(
443
-                        "%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, ",
444
-                        "event_espresso"
445
-                    ),
446
-                    $classname
447
-                )
448
-            );
449
-        }
450
-        return [
451
-            'slug'          => $matches[1],
452
-            'major_version' => intval($matches[2]),
453
-            'minor_version' => intval($matches[3]),
454
-            'micro_version' => intval($matches[4]),
455
-        ];
456
-    }
457
-
458
-
459
-    /**
460
-     * Ensures that the option indicating the current DB version is set. This should only be
461
-     * a concern when activating EE for the first time, THEORETICALLY.
462
-     * 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
463
-     * to 4.1.x.
464
-     *
465
-     * @return string of current db state
466
-     */
467
-    public function ensure_current_database_state_is_set()
468
-    {
469
-        $espresso_db_core_updates = get_option('espresso_db_update', []);
470
-        $db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
471
-        if (! $db_state) {
472
-            // mark the DB as being in the state as the last version in there.
473
-            // this is done to trigger maintenance mode and do data migration scripts
474
-            // if the admin installed this version of EE over 3.1.x or 4.0.x
475
-            // otherwise, the normal maintenance mode code is fine
476
-            $previous_versions_installed = array_keys($espresso_db_core_updates);
477
-            $previous_version_installed  = end($previous_versions_installed);
478
-            if (version_compare('4.1.0', $previous_version_installed)) {
479
-                // last installed version was less than 4.1, so we want the data migrations to happen.
480
-                // SO, we're going to say the DB is at that state
481
-                $db_state = ['Core' => $previous_version_installed];
482
-            } else {
483
-                $db_state = ['Core' => EVENT_ESPRESSO_VERSION];
484
-            }
485
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
486
-        }
487
-        // in 4.1, $db_state would have only been a simple string like '4.1.0',
488
-        // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
489
-        // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
490
-        if (! is_array($db_state)) {
491
-            $db_state = ['Core' => $db_state];
492
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
493
-        }
494
-        return $db_state;
495
-    }
496
-
497
-
498
-    /**
499
-     * Checks if there are any data migration scripts that ought to be run.
500
-     * If found, returns the instantiated classes.
501
-     * If none are found (ie, they've all already been run, or they don't apply), returns an empty array
502
-     *
503
-     * @return EE_Data_Migration_Script_Base[]
504
-     * @throws EE_Error
505
-     * @throws EE_Error
506
-     */
507
-    public function check_for_applicable_data_migration_scripts()
508
-    {
509
-        // get the option describing what options have already run
510
-        $scripts_ran = $this->get_data_migrations_ran();
511
-        // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
512
-        $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
513
-
514
-
515
-        $current_database_state = $this->ensure_current_database_state_is_set();
516
-        // determine which have already been run
517
-        $script_classes_that_should_run_per_iteration = [];
518
-        $iteration                                    = 0;
519
-        $next_database_state_to_consider              = $current_database_state;
520
-        $theoretical_database_state = null;
521
-        do {
522
-            // the next state after the currently-considered one
523
-            // will start off looking the same as the current, but we may make additions...
524
-            $theoretical_database_state = $next_database_state_to_consider;
525
-            // the next db state to consider is
526
-            // "what would the DB be like had we run all the scripts we found that applied last time?"
527
-            foreach ($script_class_and_filepaths_available as $classname => $filepath) {
528
-                $migrates_to_version         = $this->script_migrates_to_version($classname);
529
-                $script_converts_plugin_slug = $migrates_to_version['slug'];
530
-                $script_converts_to_version  = $migrates_to_version['version'];
531
-                // check if this version script is DONE or not; or if it's never been run
532
-                if (
533
-                    ! $scripts_ran
534
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ])
535
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
536
-                ) {
537
-                    // we haven't run this conversion script before
538
-                    // now check if it applies...
539
-                    // note that we've added an autoloader for it on get_all_data_migration_scripts_available
540
-                    $script = LoaderFactory::getLoader()->load($classname);
541
-                    /* @var $script EE_Data_Migration_Script_Base */
542
-                    $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
543
-                    if ($can_migrate) {
544
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
545
-                        $migrates_to_version                                                                 =
546
-                            $script->migrates_to_version();
547
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
548
-                            $migrates_to_version['version'];
549
-                        unset($script_class_and_filepaths_available[ $classname ]);
550
-                    }
551
-                } elseif (
552
-                    $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
553
-                          instanceof
554
-                          EE_Data_Migration_Script_Base
555
-                ) {
556
-                    // this script has been run, or at least started
557
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
558
-                    if ($script->get_status() !== self::status_completed) {
559
-                        // this script is already underway... keep going with it
560
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
561
-                        $migrates_to_version                                                                 =
562
-                            $script->migrates_to_version();
563
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
564
-                            $migrates_to_version['version'];
565
-                        unset($script_class_and_filepaths_available[ $classname ]);
566
-                    }
567
-                    // else it must have a status that indicates it has finished,
568
-                    // so we don't want to try and run it again
569
-                }
570
-                // else it exists, but it's not  a proper data migration script maybe the script got renamed?
571
-                // or was simply removed from EE? either way, it's certainly not runnable!
572
-            }
573
-            $iteration++;
574
-        } while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
575
-        // ok we have all the scripts that should run, now let's make them into flat array
576
-        $scripts_that_should_run = [];
577
-        foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
578
-            ksort($scripts_at_priority);
579
-            foreach ($scripts_at_priority as $scripts) {
580
-                foreach ($scripts as $script) {
581
-                    $scripts_that_should_run[ get_class($script) ] = $script;
582
-                }
583
-            }
584
-        }
585
-
586
-        do_action(
587
-            'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
588
-            $scripts_that_should_run
589
-        );
590
-        return $scripts_that_should_run;
591
-    }
592
-
593
-
594
-    /**
595
-     * Gets the script which is currently being run, if there is one. If $include_completed_scripts is set to TRUE
596
-     * it will return the last run script even if it's complete.
597
-     * This means: if you want to find the currently-executing script, leave it as FALSE.
598
-     * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
599
-     *
600
-     * @param bool $include_completed_scripts
601
-     * @return EE_Data_Migration_Script_Base
602
-     * @throws EE_Error
603
-     */
604
-    public function get_last_ran_script($include_completed_scripts = false)
605
-    {
606
-        // make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
607
-        if (! $this->_data_migrations_ran) {
608
-            $this->get_data_migrations_ran();
609
-        }
610
-        if ($include_completed_scripts) {
611
-            return $this->_last_ran_script;
612
-        } else {
613
-            return $this->_last_ran_incomplete_script;
614
-        }
615
-    }
616
-
617
-
618
-    /**
619
-     * Runs the data migration scripts (well, each request to this method calls one of the
620
-     * data migration scripts' migration_step() functions).
621
-     *
622
-     * @param int   $step_size
623
-     * @return array {
624
-     *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
625
-     *                                  //and the second item is a string describing what was done
626
-     * @type int    $records_to_migrate from the current migration script
627
-     * @type int    $records_migrated
628
-     * @type string $status             one of EE_Data_Migration_Manager::status_*
629
-     * @type string $script             verbose name of the current DMS
630
-     * @type string $message            string describing what was done during this step
631
-     *                                  }
632
-     * @throws EE_Error
633
-     */
634
-    public function migration_step($step_size = 0)
635
-    {
636
-
637
-        // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
638
-        if (class_exists('EE_CPT_Strategy')) {
639
-            remove_action('pre_get_posts', [EE_CPT_Strategy::instance(), 'pre_get_posts'], 5);
640
-        }
641
-
642
-        try {
643
-            $currently_executing_script = $this->get_last_ran_script();
644
-            if (! $currently_executing_script) {
645
-                // Find the next script that needs to execute
646
-                $scripts = $this->check_for_applicable_data_migration_scripts();
647
-                if (! $scripts) {
648
-                    // huh, no more scripts to run... apparently we're done!
649
-                    // but don't forget to make sure initial data is there
650
-                    // we should be good to allow them to exit maintenance mode now
651
-                    EE_Maintenance_Mode::instance()->set_maintenance_level(
652
-                        EE_Maintenance_Mode::level_0_not_in_maintenance
653
-                    );
654
-                    // saving migrations run should actually be unnecessary,
655
-                    // but leaving in place just in case... remember this migration was finished
656
-                    // (even if we time out while initializing db for core and plugins)
657
-                    $this->_save_migrations_ran();
658
-                    // make sure DB was updated AFTER we've recorded the migration was done
659
-                    $this->initialize_db_for_enqueued_ee_plugins();
660
-                    return [
661
-                        'records_to_migrate' => 1,
662
-                        'records_migrated'   => 1,
663
-                        'status'             => self::status_no_more_migration_scripts,
664
-                        'script'             => esc_html__("Data Migration Completed Successfully", "event_espresso"),
665
-                        'message'            => esc_html__("All done!", "event_espresso"),
666
-                    ];
667
-                }
668
-                $currently_executing_script = array_shift($scripts);
669
-                // and add to the array/wp option showing the scripts run
670
-
671
-                $migrates_to                                            =
672
-                    $this->script_migrates_to_version(get_class($currently_executing_script));
673
-                $plugin_slug                                            = $migrates_to['slug'];
674
-                $version                                                = $migrates_to['version'];
675
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
676
-            }
677
-            $current_script_name = get_class($currently_executing_script);
678
-        } catch (Exception $e) {
679
-            // an exception occurred while trying to get migration scripts
680
-
681
-            $message = sprintf(
682
-                esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
683
-                $e->getMessage() . '<br>',
684
-                $e->getTraceAsString()
685
-            );
686
-            // record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
687
-            // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
688
-            $this->add_error_to_migrations_ran(
689
-                sprintf(esc_html__("Could not run data migrations because: %s", "event_espresso"), $message)
690
-            );
691
-            return [
692
-                'records_to_migrate' => 1,
693
-                'records_migrated'   => 0,
694
-                'status'             => self::status_fatal_error,
695
-                'script'             => esc_html__("Error loading data migration scripts", "event_espresso"),
696
-                'message'            => $message,
697
-            ];
698
-        }
699
-        // can we wrap it up and verify default data?
700
-        $init_dbs = false;
701
-        // ok so we definitely have a data migration script
702
-        try {
703
-            // how big of a bite do we want to take? Allow users to easily override via their wp-config
704
-            if (absint($step_size) < 1) {
705
-                $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
706
-                    ? EE_MIGRATION_STEP_SIZE
707
-                    : EE_Data_Migration_Manager::step_size;
708
-            }
709
-            // do what we came to do!
710
-            $currently_executing_script->migration_step($step_size);
711
-            switch ($currently_executing_script->get_status()) {
712
-                case EE_Data_Migration_Manager::status_continue:
713
-                    $response_array = [
714
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
715
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
716
-                        'status'             => EE_Data_Migration_Manager::status_continue,
717
-                        'message'            => $currently_executing_script->get_feedback_message(),
718
-                        'script'             => $currently_executing_script->pretty_name(),
719
-                    ];
720
-                    break;
721
-                case EE_Data_Migration_Manager::status_completed:
722
-                    // ok so THAT script has completed
723
-                    $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
724
-                    $response_array = [
725
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
726
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
727
-                        'status'             => EE_Data_Migration_Manager::status_completed,
728
-                        'message'            => $currently_executing_script->get_feedback_message(),
729
-                        'script'             => sprintf(
730
-                            esc_html__("%s Completed", 'event_espresso'),
731
-                            $currently_executing_script->pretty_name()
732
-                        ),
733
-                    ];
734
-                    // check if there are any more after this one.
735
-                    $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
736
-                    if (! $scripts_remaining) {
737
-                        // we should be good to allow them to exit maintenance mode now
738
-                        EE_Maintenance_Mode::instance()->set_maintenance_level(
739
-                            EE_Maintenance_Mode::level_0_not_in_maintenance
740
-                        );
741
-                        // huh, no more scripts to run... apparently we're done!
742
-                        // but don't forget to make sure initial data is there
743
-                        $init_dbs                 = true;
744
-                        $response_array['status'] = self::status_no_more_migration_scripts;
745
-                    }
746
-                    break;
747
-                default:
748
-                    $response_array = [
749
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
750
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
751
-                        'status'             => $currently_executing_script->get_status(),
752
-                        'message'            => sprintf(
753
-                            esc_html__("Minor errors occurred during %s: %s", "event_espresso"),
754
-                            $currently_executing_script->pretty_name(),
755
-                            implode(", ", $currently_executing_script->get_errors())
756
-                        ),
757
-                        'script'             => $currently_executing_script->pretty_name(),
758
-                    ];
759
-                    break;
760
-            }
761
-        } catch (Exception $e) {
762
-            // ok so some exception was thrown which killed the data migration script
763
-            // double-check we have a real script
764
-            if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
765
-                $script_name = $currently_executing_script->pretty_name();
766
-                $currently_executing_script->set_broken();
767
-                $currently_executing_script->add_error($e->getMessage());
768
-            } else {
769
-                $script_name = esc_html__("Error getting Migration Script", "event_espresso");
770
-            }
771
-            $response_array = [
772
-                'records_to_migrate' => 1,
773
-                'records_migrated'   => 0,
774
-                'status'             => self::status_fatal_error,
775
-                'message'            => sprintf(
776
-                    esc_html__("A fatal error occurred during the migration: %s", "event_espresso"),
777
-                    $e->getMessage()
778
-                ),
779
-                'script'             => $script_name,
780
-            ];
781
-        }
782
-        $successful_save = $this->_save_migrations_ran();
783
-        if ($successful_save !== true) {
784
-            // ok so the current wp option didn't save. that's tricky, because we'd like to update it
785
-            // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
786
-            // however, if we throw an exception, and return that, then the next request
787
-            // won't have as much info in it, and it may be able to save
788
-            throw new EE_Error(
789
-                sprintf(
790
-                    esc_html__(
791
-                        "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.",
792
-                        "event_espresso"
793
-                    ),
794
-                    $successful_save
795
-                )
796
-            );
797
-        }
798
-        // if we're all done, initialize EE plugins' default data etc.
799
-        if ($init_dbs) {
800
-            $this->initialize_db_for_enqueued_ee_plugins();
801
-        }
802
-        return $response_array;
803
-    }
804
-
805
-
806
-    /**
807
-     * Echo out JSON response to migration script AJAX requests. Takes precautions
808
-     * to buffer output so that we don't throw junk into our json.
809
-     *
810
-     * @return array with keys:
811
-     * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
812
-     * it's NOT the count of hwo many remain)
813
-     * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
814
-     * records_migrated/records_to_migrate)
815
-     * 'status'=>a string, one of EE_Data_migration_Manager::status_*
816
-     * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
817
-     * errors, notifications, and successes
818
-     * 'script'=>a pretty name of the script currently running
819
-     */
820
-    public function response_to_migration_ajax_request()
821
-    {
822
-        ob_start();
823
-        try {
824
-            $response = $this->migration_step();
825
-        } catch (Exception $e) {
826
-            $response = [
827
-                'records_to_migrate' => 0,
828
-                'records_migrated'   => 0,
829
-                'status'             => EE_Data_Migration_Manager::status_fatal_error,
830
-                'message'            => sprintf(
831
-                    esc_html__("Unknown fatal error occurred: %s", "event_espresso"),
832
-                    $e->getMessage()
833
-                ),
834
-                'script'             => 'Unknown',
835
-            ];
836
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
837
-        }
838
-        $warnings_etc = @ob_get_contents();
839
-        ob_end_clean();
840
-        $response['message'] .= $warnings_etc;
841
-        return $response;
842
-    }
843
-
844
-
845
-    /**
846
-     * Updates the WordPress option that keeps track of which EE version the database
847
-     * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
848
-     *
849
-     * @param array $slug_and_version {
850
-     * @type string $slug             like 'Core' or 'Calendar',
851
-     * @type string $version          like '4.1.0'
852
-     *                                }
853
-     * @return void
854
-     */
855
-    public function update_current_database_state_to($slug_and_version = null)
856
-    {
857
-        if (! $slug_and_version) {
858
-            // no version was provided, assume it should be at the current code version
859
-            $slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
860
-        }
861
-        $current_database_state                              = get_option(self::current_database_state);
862
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
863
-        update_option(self::current_database_state, $current_database_state);
864
-    }
865
-
866
-
867
-    /**
868
-     * Determines if the database is currently at a state matching what's indicated in $slug and $version.
869
-     *
870
-     * @param array $slug_and_version {
871
-     * @type string $slug             like 'Core' or 'Calendar',
872
-     * @type string $version          like '4.1.0'
873
-     *                                }
874
-     * @return boolean
875
-     */
876
-    public function database_needs_updating_to($slug_and_version)
877
-    {
878
-
879
-        $slug                   = $slug_and_version['slug'];
880
-        $version                = $slug_and_version['version'];
881
-        $current_database_state = get_option(self::current_database_state);
882
-        if (! isset($current_database_state[ $slug ])) {
883
-            return true;
884
-        } else {
885
-            // 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
886
-            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
887
-            $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
888
-            $needs_updating                     = false;
889
-            foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
890
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
891
-                    $needs_updating = true;
892
-                    break;
893
-                }
894
-            }
895
-            return $needs_updating;
896
-        }
897
-    }
898
-
899
-
900
-    /**
901
-     * Gets all the data migration scripts available in the core folder and folders
902
-     * in addons. Has the side effect of adding them for autoloading
903
-     *
904
-     * @return array keys are expected classnames, values are their filepaths
905
-     * @throws InvalidInterfaceException
906
-     * @throws InvalidDataTypeException
907
-     * @throws EE_Error
908
-     * @throws InvalidArgumentException
909
-     */
910
-    public function get_all_data_migration_scripts_available()
911
-    {
912
-        if (! $this->_data_migration_class_to_filepath_map) {
913
-            $this->_data_migration_class_to_filepath_map = [];
914
-            foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
915
-                // strip any placeholders added to classname to make it a unique array key
916
-                $eeAddonClass = trim($eeAddonClass, '*');
917
-                $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
918
-                    ? $eeAddonClass
919
-                    : '';
920
-                $folder_path  = EEH_File::end_with_directory_separator($folder_path);
921
-                $files        = glob($folder_path . '*.dms.php');
922
-                if (empty($files)) {
923
-                    continue;
924
-                }
925
-                foreach ($files as $file) {
926
-                    $pos_of_last_slash = strrpos($file, '/');
927
-                    $classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
928
-                    $migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
929
-                    $slug              = $migrates_to['slug'];
930
-                    // check that the slug as contained in the DMS is associated with
931
-                    // the slug of an addon or core
932
-                    if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
933
-                        EE_Error::doing_it_wrong(
934
-                            __FUNCTION__,
935
-                            sprintf(
936
-                                esc_html__(
937
-                                    'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
938
-                                    'event_espresso'
939
-                                ),
940
-                                $classname,
941
-                                $slug,
942
-                                implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
943
-                            ),
944
-                            '4.3.0.alpha.019'
945
-                        );
946
-                    }
947
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
948
-                }
949
-            }
950
-            EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
951
-        }
952
-        return $this->_data_migration_class_to_filepath_map;
953
-    }
954
-
955
-
956
-    /**
957
-     * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
958
-     * from each addon, and check if they need updating,
959
-     *
960
-     * @return boolean
961
-     */
962
-    public function addons_need_updating()
963
-    {
964
-        return false;
965
-    }
966
-
967
-
968
-    /**
969
-     * Adds this error string to the data_migrations_ran array, but we don't necessarily know
970
-     * where to put it, so we just throw it in there... better than nothing...
971
-     *
972
-     * @param string $error_message
973
-     */
974
-    public function add_error_to_migrations_ran($error_message)
975
-    {
976
-        // get last-run migration script
977
-        global $wpdb;
978
-        $last_migration_script_option = $wpdb->get_row(
979
-            "SELECT * FROM $wpdb->options WHERE option_name like '"
980
-            . EE_Data_Migration_Manager::data_migration_script_option_prefix
981
-            . "%' ORDER BY option_id DESC LIMIT 1",
982
-            ARRAY_A
983
-        );
984
-
985
-        $last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
986
-            ? maybe_unserialize($last_migration_script_option['option_value']) : null;
987
-        // now, tread lightly because we're here because a FATAL non-catchable error
988
-        // was thrown last time when we were trying to run a data migration script
989
-        // so the fatal error could have happened while getting the migration script
990
-        // or doing running it...
991
-        $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
992
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
993
-            "",
994
-            $last_migration_script_option['option_name']
995
-        ) : null;
996
-
997
-        // check if it THINKS it's a data migration script and especially if it's one that HASN'T finished yet
998
-        // because if it has finished, then it obviously couldn't be the cause of this error, right? (because it's all done)
999
-        if (
1000
-            isset($last_ran_migration_script_properties['class'])
1001
-            && isset($last_ran_migration_script_properties['_status'])
1002
-            && $last_ran_migration_script_properties['_status'] != self::status_completed
1003
-        ) {
1004
-            // ok then just add this error to its list of errors
1005
-            $last_ran_migration_script_properties['_errors'][] = $error_message;
1006
-            $last_ran_migration_script_properties['_status']   = self::status_fatal_error;
1007
-        } else {
1008
-            // so we don't even know which script was last running
1009
-            // use the data migration error stub, which is designed specifically for this type of thing
1010
-            $general_migration_error = new EE_DMS_Unknown_1_0_0();
1011
-            $general_migration_error->add_error($error_message);
1012
-            $general_migration_error->set_broken();
1013
-            $last_ran_migration_script_properties = $general_migration_error->properties_as_array();
1014
-            $versions_migrated_to                 = 'Unknown.1.0.0';
1015
-            // now just to make sure appears as last (in case the were previously a fatal error like this)
1016
-            // delete the old one
1017
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1018
-        }
1019
-        update_option(
1020
-            self::data_migration_script_option_prefix . $versions_migrated_to,
1021
-            $last_ran_migration_script_properties
1022
-        );
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * saves what data migrations have run to the database
1028
-     *
1029
-     * @return bool|string TRUE if successfully saved migrations ran, string if an error occurred
1030
-     * @throws EE_Error
1031
-     */
1032
-    protected function _save_migrations_ran()
1033
-    {
1034
-        if ($this->_data_migrations_ran == null) {
1035
-            $this->get_data_migrations_ran();
1036
-        }
1037
-        // now, we don't want to save actual classes to the DB because that's messy
1038
-        $successful_updates = true;
1039
-        foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1040
-            foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1041
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1042
-                $option_name                        =
1043
-                    self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1044
-                $old_option_value                   = get_option($option_name);
1045
-                if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1046
-                    $script_array_for_saving = $array_or_migration_obj->properties_as_array();
1047
-                    if ($old_option_value != $script_array_for_saving) {
1048
-                        $successful_updates = update_option($option_name, $script_array_for_saving);
1049
-                    }
1050
-                } else {// we don't know what this array-thing is. So just save it as-is
1051
-                    if ($old_option_value != $array_or_migration_obj) {
1052
-                        $successful_updates = update_option($option_name, $array_or_migration_obj);
1053
-                    }
1054
-                }
1055
-                if (! $successful_updates) {
1056
-                    global $wpdb;
1057
-                    return $wpdb->last_error;
1058
-                }
1059
-            }
1060
-        }
1061
-        return true;
1062
-        // $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1063
-        // if ($updated !== true) {
1064
-        //     global $wpdb;
1065
-        //     return $wpdb->last_error;
1066
-        // } else {
1067
-        //     return true;
1068
-        // }
1069
-        // wp_mail(
1070
-        //     "[email protected]",
1071
-        //     time() . " price debug info",
1072
-        //     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1073
-        //         serialize($array_of_migrations)
1074
-        //     )
1075
-        // );
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * Takes an array of data migration script properties and re-creates the class from
1081
-     * them. The argument $properties_array is assumed to have been made by
1082
-     * EE_Data_Migration_Script_Base::properties_as_array()
1083
-     *
1084
-     * @param array $properties_array
1085
-     * @return EE_Data_Migration_Script_Base
1086
-     * @throws EE_Error
1087
-     */
1088
-    public function _instantiate_script_from_properties_array($properties_array)
1089
-    {
1090
-        if (! isset($properties_array['class'])) {
1091
-            throw new EE_Error(
1092
-                sprintf(
1093
-                    esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1094
-                    implode(",", $properties_array)
1095
-                )
1096
-            );
1097
-        }
1098
-        $class_name = $properties_array['class'];
1099
-        if (! class_exists($class_name)) {
1100
-            throw new EE_Error(sprintf(
1101
-                esc_html__("There is no migration script named %s", "event_espresso"),
1102
-                $class_name
1103
-            ));
1104
-        }
1105
-        $class = new $class_name();
1106
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1107
-            throw new EE_Error(
1108
-                sprintf(
1109
-                    esc_html__(
1110
-                        "Class '%s' is supposed to be a migration script. Its not, its a '%s'",
1111
-                        "event_espresso"
1112
-                    ),
1113
-                    $class_name,
1114
-                    get_class($class)
1115
-                )
1116
-            );
1117
-        }
1118
-        $class->instantiate_from_array_of_properties($properties_array);
1119
-        return $class;
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1125
-     * leave the DB in a state usable by the current plugin code).
1126
-     *
1127
-     * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1128
-     * @return string
1129
-     * @throws EE_Error
1130
-     * @throws EE_Error
1131
-     */
1132
-    public function get_most_up_to_date_dms($plugin_slug = 'Core')
1133
-    {
1134
-        $class_to_filepath_map         = $this->get_all_data_migration_scripts_available();
1135
-        $most_up_to_date_dms_classname = null;
1136
-        foreach ($class_to_filepath_map as $classname => $filepath) {
1137
-            if ($most_up_to_date_dms_classname === null) {
1138
-                $migrates_to      = $this->script_migrates_to_version($classname);
1139
-                $this_plugin_slug = $migrates_to['slug'];
1140
-                if ($this_plugin_slug == $plugin_slug) {
1141
-                    // if it's for core, it wins
1142
-                    $most_up_to_date_dms_classname = $classname;
1143
-                }
1144
-                // if it wasn't for core, we must keep searching for one that is!
1145
-                continue;
1146
-            }
1147
-            $champion_migrates_to  = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1148
-            $contender_migrates_to = $this->script_migrates_to_version($classname);
1149
-            if (
1150
-                $contender_migrates_to['slug'] == $plugin_slug
1151
-                && version_compare(
1152
-                    $champion_migrates_to['version'],
1153
-                    $contender_migrates_to['version'],
1154
-                    '<'
1155
-                )
1156
-            ) {
1157
-                // so the contenders version is higher, and it's for Core
1158
-                $most_up_to_date_dms_classname = $classname;
1159
-            }
1160
-        }
1161
-        return $most_up_to_date_dms_classname;
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Gets the migration script specified but ONLY if it has already run.
1167
-     *
1168
-     * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has run, you would run the following code:
1169
-     * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1170
-     * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1171
-     * other addon) DMS has run, in case the current DMS depends on it.
1172
-     *
1173
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1174
-     *                            period. Eg '4.1.0'
1175
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1176
-     * @return EE_Data_Migration_Script_Base
1177
-     * @throws EE_Error
1178
-     */
1179
-    public function get_migration_ran($version, $plugin_slug = 'Core')
1180
-    {
1181
-        $migrations_ran = $this->get_data_migrations_ran();
1182
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1183
-            return $migrations_ran[ $plugin_slug ][ $version ];
1184
-        } else {
1185
-            return null;
1186
-        }
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * Resets the borked data migration scripts, so they're no longer borked, and we can again attempt to migrate
1192
-     *
1193
-     * @return bool
1194
-     * @throws EE_Error
1195
-     */
1196
-    public function reattempt()
1197
-    {
1198
-        // find if the last-run script was borked
1199
-        // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1200
-        // add an 'error' saying that we attempted to reset
1201
-        // does it have a stage that was borked too? if so make it no longer borked
1202
-        // add an 'error' saying we attempted to reset
1203
-        $last_ran_script = $this->get_last_ran_script();
1204
-        if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1205
-            // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1206
-            $last_ran_script->set_completed();
1207
-        } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1208
-            $last_ran_script->reattempt();
1209
-        } else {
1210
-            throw new EE_Error(
1211
-                sprintf(
1212
-                    esc_html__(
1213
-                        'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1214
-                        'event_espresso'
1215
-                    ),
1216
-                    print_r($last_ran_script, true)
1217
-                )
1218
-            );
1219
-        }
1220
-        return $this->_save_migrations_ran();
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * Gets whether this particular migration has run or not
1226
-     *
1227
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1228
-     *                            period. Eg '4.1.0'
1229
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1230
-     * @return boolean
1231
-     * @throws EE_Error
1232
-     */
1233
-    public function migration_has_ran($version, $plugin_slug = 'Core')
1234
-    {
1235
-        return $this->get_migration_ran($version, $plugin_slug) !== null;
1236
-    }
1237
-
1238
-
1239
-    /**
1240
-     * Enqueues this ee plugin to have its data initialized
1241
-     *
1242
-     * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1243
-     */
1244
-    public function enqueue_db_initialization_for($plugin_slug)
1245
-    {
1246
-        $queue = $this->get_db_initialization_queue();
1247
-        if (! in_array($plugin_slug, $queue)) {
1248
-            $queue[] = $plugin_slug;
1249
-        }
1250
-        update_option(self::db_init_queue_option_name, $queue);
1251
-    }
1252
-
1253
-
1254
-    /**
1255
-     * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1256
-     * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1257
-     * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1258
-     *
1259
-     * @throws EE_Error
1260
-     */
1261
-    public function initialize_db_for_enqueued_ee_plugins()
1262
-    {
1263
-        $queue = $this->get_db_initialization_queue();
1264
-        foreach ($queue as $plugin_slug) {
1265
-            $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1266
-            if (! $most_up_to_date_dms) {
1267
-                // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1268
-                $verify_db = false;
1269
-            } else {
1270
-                $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1271
-                $verify_db                       = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1272
-            }
1273
-            if ($plugin_slug == 'Core') {
1274
-                EE_System::instance()->initialize_db_if_no_migrations_required(
1275
-                    false,
1276
-                    $verify_db
1277
-                );
1278
-            } else {
1279
-                // just loop through the addons to make sure their database is set up
1280
-                foreach (EE_Registry::instance()->addons as $addon) {
1281
-                    if ($addon->name() == $plugin_slug) {
1282
-                        $addon->initialize_db_if_no_migrations_required($verify_db);
1283
-                        break;
1284
-                    }
1285
-                }
1286
-            }
1287
-        }
1288
-        // because we just initialized the DBs for the enqueued ee plugins
1289
-        // we don't need to keep remembering which ones needed to be initialized
1290
-        delete_option(self::db_init_queue_option_name);
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * Gets a numerically-indexed array of plugin slugs that need to have their databases
1296
-     * (re-)initialized after migrations are complete. ie, each element should be either
1297
-     * 'Core', or the return value of EE_Addon::name() for an addon
1298
-     *
1299
-     * @return array
1300
-     */
1301
-    public function get_db_initialization_queue()
1302
-    {
1303
-        return get_option(self::db_init_queue_option_name, []);
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * Gets the injected table analyzer, or throws an exception
1309
-     *
1310
-     * @return TableAnalysis
1311
-     * @throws EE_Error
1312
-     */
1313
-    protected function _get_table_analysis()
1314
-    {
1315
-        if ($this->_table_analysis instanceof TableAnalysis) {
1316
-            return $this->_table_analysis;
1317
-        } else {
1318
-            throw new EE_Error(
1319
-                sprintf(
1320
-                    esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1321
-                    get_class($this)
1322
-                )
1323
-            );
1324
-        }
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Gets the injected table manager, or throws an exception
1330
-     *
1331
-     * @return TableManager
1332
-     * @throws EE_Error
1333
-     */
1334
-    protected function _get_table_manager()
1335
-    {
1336
-        if ($this->_table_manager instanceof TableManager) {
1337
-            return $this->_table_manager;
1338
-        } else {
1339
-            throw new EE_Error(
1340
-                sprintf(
1341
-                    esc_html__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1342
-                    get_class($this)
1343
-                )
1344
-            );
1345
-        }
1346
-    }
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
+			$class = LoaderFactory::getLoader()->getShared($data_migration_data['class']);
269
+			if ($class instanceof EE_Data_Migration_Script_Base) {
270
+				$class->instantiate_from_array_of_properties($data_migration_data);
271
+				return $class;
272
+			} else {
273
+				// huh, so it's an object but not a data migration script?? that shouldn't happen
274
+				// just leave it as an array (which will probably just get ignored)
275
+				throw new EE_Error(
276
+					sprintf(
277
+						esc_html__(
278
+							"Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
279
+							'event_espresso'
280
+						),
281
+						$data_migration_data['class']
282
+					)
283
+				);
284
+			}
285
+		} else {
286
+			// 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
287
+			throw new EE_Error(
288
+				sprintf(
289
+					esc_html__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'),
290
+					$dms_option_name
291
+				)
292
+			);
293
+		}
294
+	}
295
+
296
+
297
+	/**
298
+	 * Gets the array describing what data migrations have run.
299
+	 * Also has a side effect of recording which was the last run,
300
+	 * and which was the last run which hasn't finished yet
301
+	 *
302
+	 * @return array where each element should be an array of EE_Data_Migration_Script_Base
303
+	 *               (but also has a few legacy arrays in there - which should probably be ignored)
304
+	 * @throws EE_Error
305
+	 */
306
+	public function get_data_migrations_ran()
307
+	{
308
+		if (! $this->_data_migrations_ran) {
309
+			// setup autoloaders for each of the scripts in there
310
+			$this->get_all_data_migration_scripts_available();
311
+			$data_migrations_options =
312
+				$this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
313
+
314
+			$data_migrations_ran = [];
315
+			// convert into data migration script classes where possible
316
+			foreach ($data_migrations_options as $data_migration_option) {
317
+				list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
318
+					$data_migration_option['option_name']
319
+				);
320
+
321
+				try {
322
+					$class                                                  = $this->_get_dms_class_from_wp_option(
323
+						$data_migration_option['option_name'],
324
+						$data_migration_option['option_value']
325
+					);
326
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
327
+					// ok so far THIS is the 'last-run-script'... unless we find another on next iteration
328
+					$this->_last_ran_script = $class;
329
+					if (! $class->is_completed()) {
330
+						// sometimes we also like to know which was the last incomplete script (or if there are any at all)
331
+						$this->_last_ran_incomplete_script = $class;
332
+					}
333
+				} catch (EE_Error $e) {
334
+					// ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
335
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
336
+						$data_migration_option['option_value']
337
+					);
338
+				}
339
+			}
340
+			// so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
341
+			$this->_data_migrations_ran = $data_migrations_ran;
342
+			if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
343
+				$this->_data_migrations_ran = [];
344
+			}
345
+		}
346
+		return $this->_data_migrations_ran;
347
+	}
348
+
349
+
350
+	/**
351
+	 *
352
+	 * @param string $script_name eg 'DMS_Core_4_1_0'
353
+	 * @param string $old_table   eg 'wp_events_detail'
354
+	 * @param string $old_pk      eg 'wp_esp_posts'
355
+	 * @param        $new_table
356
+	 * @return mixed string or int
357
+	 * @throws EE_Error
358
+	 * @throws ReflectionException
359
+	 */
360
+	public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
361
+	{
362
+		$script  = EE_Registry::instance()->load_dms($script_name);
363
+		return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
364
+	}
365
+
366
+
367
+	/**
368
+	 * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
369
+	 * the last option returned in this array is the most-recently run DMS option
370
+	 *
371
+	 * @return array
372
+	 */
373
+	public function get_all_migration_script_options()
374
+	{
375
+		global $wpdb;
376
+		return $wpdb->get_results(
377
+			"SELECT * FROM {$wpdb->options} WHERE option_name like '"
378
+			. EE_Data_Migration_Manager::data_migration_script_option_prefix
379
+			. "%' ORDER BY option_id ASC",
380
+			ARRAY_A
381
+		);
382
+	}
383
+
384
+
385
+	/**
386
+	 * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
387
+	 *
388
+	 * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
389
+	 *               slashes at the end of the folder name.
390
+	 */
391
+	public function get_data_migration_script_folders()
392
+	{
393
+		return apply_filters(
394
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
395
+			['Core' => EE_CORE . 'data_migration_scripts']
396
+		);
397
+	}
398
+
399
+
400
+	/**
401
+	 * Gets the version the migration script upgrades to
402
+	 *
403
+	 * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
404
+	 * @return array {
405
+	 *      @type string  $slug     like 'Core','Calendar',etc
406
+	 *      @type string  $version  like 4.3.0
407
+	 * }
408
+	 * @throws EE_Error
409
+	 */
410
+	public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
411
+	{
412
+		if (isset($this->script_migration_versions[ $migration_script_name ])) {
413
+			return $this->script_migration_versions[ $migration_script_name ];
414
+		}
415
+		$dms_info                                                  = $this->parse_dms_classname($migration_script_name);
416
+		$this->script_migration_versions[ $migration_script_name ] = [
417
+			'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
418
+			'version' => $dms_info['major_version']
419
+						 . "."
420
+						 . $dms_info['minor_version']
421
+						 . "."
422
+						 . $dms_info['micro_version'],
423
+		];
424
+		return $this->script_migration_versions[ $migration_script_name ];
425
+	}
426
+
427
+
428
+	/**
429
+	 * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
430
+	 *
431
+	 * @param string $classname
432
+	 * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are integers)
433
+	 * @throws EE_Error
434
+	 */
435
+	public function parse_dms_classname($classname)
436
+	{
437
+		$matches = [];
438
+		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
439
+		if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
440
+			throw new EE_Error(
441
+				sprintf(
442
+					esc_html__(
443
+						"%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, ",
444
+						"event_espresso"
445
+					),
446
+					$classname
447
+				)
448
+			);
449
+		}
450
+		return [
451
+			'slug'          => $matches[1],
452
+			'major_version' => intval($matches[2]),
453
+			'minor_version' => intval($matches[3]),
454
+			'micro_version' => intval($matches[4]),
455
+		];
456
+	}
457
+
458
+
459
+	/**
460
+	 * Ensures that the option indicating the current DB version is set. This should only be
461
+	 * a concern when activating EE for the first time, THEORETICALLY.
462
+	 * 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
463
+	 * to 4.1.x.
464
+	 *
465
+	 * @return string of current db state
466
+	 */
467
+	public function ensure_current_database_state_is_set()
468
+	{
469
+		$espresso_db_core_updates = get_option('espresso_db_update', []);
470
+		$db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
471
+		if (! $db_state) {
472
+			// mark the DB as being in the state as the last version in there.
473
+			// this is done to trigger maintenance mode and do data migration scripts
474
+			// if the admin installed this version of EE over 3.1.x or 4.0.x
475
+			// otherwise, the normal maintenance mode code is fine
476
+			$previous_versions_installed = array_keys($espresso_db_core_updates);
477
+			$previous_version_installed  = end($previous_versions_installed);
478
+			if (version_compare('4.1.0', $previous_version_installed)) {
479
+				// last installed version was less than 4.1, so we want the data migrations to happen.
480
+				// SO, we're going to say the DB is at that state
481
+				$db_state = ['Core' => $previous_version_installed];
482
+			} else {
483
+				$db_state = ['Core' => EVENT_ESPRESSO_VERSION];
484
+			}
485
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
486
+		}
487
+		// in 4.1, $db_state would have only been a simple string like '4.1.0',
488
+		// but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
489
+		// db, and possibly other keys for other addons like 'Calendar','Permissions',etc
490
+		if (! is_array($db_state)) {
491
+			$db_state = ['Core' => $db_state];
492
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
493
+		}
494
+		return $db_state;
495
+	}
496
+
497
+
498
+	/**
499
+	 * Checks if there are any data migration scripts that ought to be run.
500
+	 * If found, returns the instantiated classes.
501
+	 * If none are found (ie, they've all already been run, or they don't apply), returns an empty array
502
+	 *
503
+	 * @return EE_Data_Migration_Script_Base[]
504
+	 * @throws EE_Error
505
+	 * @throws EE_Error
506
+	 */
507
+	public function check_for_applicable_data_migration_scripts()
508
+	{
509
+		// get the option describing what options have already run
510
+		$scripts_ran = $this->get_data_migrations_ran();
511
+		// $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
512
+		$script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
513
+
514
+
515
+		$current_database_state = $this->ensure_current_database_state_is_set();
516
+		// determine which have already been run
517
+		$script_classes_that_should_run_per_iteration = [];
518
+		$iteration                                    = 0;
519
+		$next_database_state_to_consider              = $current_database_state;
520
+		$theoretical_database_state = null;
521
+		do {
522
+			// the next state after the currently-considered one
523
+			// will start off looking the same as the current, but we may make additions...
524
+			$theoretical_database_state = $next_database_state_to_consider;
525
+			// the next db state to consider is
526
+			// "what would the DB be like had we run all the scripts we found that applied last time?"
527
+			foreach ($script_class_and_filepaths_available as $classname => $filepath) {
528
+				$migrates_to_version         = $this->script_migrates_to_version($classname);
529
+				$script_converts_plugin_slug = $migrates_to_version['slug'];
530
+				$script_converts_to_version  = $migrates_to_version['version'];
531
+				// check if this version script is DONE or not; or if it's never been run
532
+				if (
533
+					! $scripts_ran
534
+					|| ! isset($scripts_ran[ $script_converts_plugin_slug ])
535
+					|| ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
536
+				) {
537
+					// we haven't run this conversion script before
538
+					// now check if it applies...
539
+					// note that we've added an autoloader for it on get_all_data_migration_scripts_available
540
+					$script = LoaderFactory::getLoader()->load($classname);
541
+					/* @var $script EE_Data_Migration_Script_Base */
542
+					$can_migrate = $script->can_migrate_from_version($theoretical_database_state);
543
+					if ($can_migrate) {
544
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
545
+						$migrates_to_version                                                                 =
546
+							$script->migrates_to_version();
547
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
548
+							$migrates_to_version['version'];
549
+						unset($script_class_and_filepaths_available[ $classname ]);
550
+					}
551
+				} elseif (
552
+					$scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
553
+						  instanceof
554
+						  EE_Data_Migration_Script_Base
555
+				) {
556
+					// this script has been run, or at least started
557
+					$script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
558
+					if ($script->get_status() !== self::status_completed) {
559
+						// this script is already underway... keep going with it
560
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
561
+						$migrates_to_version                                                                 =
562
+							$script->migrates_to_version();
563
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
564
+							$migrates_to_version['version'];
565
+						unset($script_class_and_filepaths_available[ $classname ]);
566
+					}
567
+					// else it must have a status that indicates it has finished,
568
+					// so we don't want to try and run it again
569
+				}
570
+				// else it exists, but it's not  a proper data migration script maybe the script got renamed?
571
+				// or was simply removed from EE? either way, it's certainly not runnable!
572
+			}
573
+			$iteration++;
574
+		} while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
575
+		// ok we have all the scripts that should run, now let's make them into flat array
576
+		$scripts_that_should_run = [];
577
+		foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
578
+			ksort($scripts_at_priority);
579
+			foreach ($scripts_at_priority as $scripts) {
580
+				foreach ($scripts as $script) {
581
+					$scripts_that_should_run[ get_class($script) ] = $script;
582
+				}
583
+			}
584
+		}
585
+
586
+		do_action(
587
+			'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
588
+			$scripts_that_should_run
589
+		);
590
+		return $scripts_that_should_run;
591
+	}
592
+
593
+
594
+	/**
595
+	 * Gets the script which is currently being run, if there is one. If $include_completed_scripts is set to TRUE
596
+	 * it will return the last run script even if it's complete.
597
+	 * This means: if you want to find the currently-executing script, leave it as FALSE.
598
+	 * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
599
+	 *
600
+	 * @param bool $include_completed_scripts
601
+	 * @return EE_Data_Migration_Script_Base
602
+	 * @throws EE_Error
603
+	 */
604
+	public function get_last_ran_script($include_completed_scripts = false)
605
+	{
606
+		// make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
607
+		if (! $this->_data_migrations_ran) {
608
+			$this->get_data_migrations_ran();
609
+		}
610
+		if ($include_completed_scripts) {
611
+			return $this->_last_ran_script;
612
+		} else {
613
+			return $this->_last_ran_incomplete_script;
614
+		}
615
+	}
616
+
617
+
618
+	/**
619
+	 * Runs the data migration scripts (well, each request to this method calls one of the
620
+	 * data migration scripts' migration_step() functions).
621
+	 *
622
+	 * @param int   $step_size
623
+	 * @return array {
624
+	 *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
625
+	 *                                  //and the second item is a string describing what was done
626
+	 * @type int    $records_to_migrate from the current migration script
627
+	 * @type int    $records_migrated
628
+	 * @type string $status             one of EE_Data_Migration_Manager::status_*
629
+	 * @type string $script             verbose name of the current DMS
630
+	 * @type string $message            string describing what was done during this step
631
+	 *                                  }
632
+	 * @throws EE_Error
633
+	 */
634
+	public function migration_step($step_size = 0)
635
+	{
636
+
637
+		// bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
638
+		if (class_exists('EE_CPT_Strategy')) {
639
+			remove_action('pre_get_posts', [EE_CPT_Strategy::instance(), 'pre_get_posts'], 5);
640
+		}
641
+
642
+		try {
643
+			$currently_executing_script = $this->get_last_ran_script();
644
+			if (! $currently_executing_script) {
645
+				// Find the next script that needs to execute
646
+				$scripts = $this->check_for_applicable_data_migration_scripts();
647
+				if (! $scripts) {
648
+					// huh, no more scripts to run... apparently we're done!
649
+					// but don't forget to make sure initial data is there
650
+					// we should be good to allow them to exit maintenance mode now
651
+					EE_Maintenance_Mode::instance()->set_maintenance_level(
652
+						EE_Maintenance_Mode::level_0_not_in_maintenance
653
+					);
654
+					// saving migrations run should actually be unnecessary,
655
+					// but leaving in place just in case... remember this migration was finished
656
+					// (even if we time out while initializing db for core and plugins)
657
+					$this->_save_migrations_ran();
658
+					// make sure DB was updated AFTER we've recorded the migration was done
659
+					$this->initialize_db_for_enqueued_ee_plugins();
660
+					return [
661
+						'records_to_migrate' => 1,
662
+						'records_migrated'   => 1,
663
+						'status'             => self::status_no_more_migration_scripts,
664
+						'script'             => esc_html__("Data Migration Completed Successfully", "event_espresso"),
665
+						'message'            => esc_html__("All done!", "event_espresso"),
666
+					];
667
+				}
668
+				$currently_executing_script = array_shift($scripts);
669
+				// and add to the array/wp option showing the scripts run
670
+
671
+				$migrates_to                                            =
672
+					$this->script_migrates_to_version(get_class($currently_executing_script));
673
+				$plugin_slug                                            = $migrates_to['slug'];
674
+				$version                                                = $migrates_to['version'];
675
+				$this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
676
+			}
677
+			$current_script_name = get_class($currently_executing_script);
678
+		} catch (Exception $e) {
679
+			// an exception occurred while trying to get migration scripts
680
+
681
+			$message = sprintf(
682
+				esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
683
+				$e->getMessage() . '<br>',
684
+				$e->getTraceAsString()
685
+			);
686
+			// record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
687
+			// but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
688
+			$this->add_error_to_migrations_ran(
689
+				sprintf(esc_html__("Could not run data migrations because: %s", "event_espresso"), $message)
690
+			);
691
+			return [
692
+				'records_to_migrate' => 1,
693
+				'records_migrated'   => 0,
694
+				'status'             => self::status_fatal_error,
695
+				'script'             => esc_html__("Error loading data migration scripts", "event_espresso"),
696
+				'message'            => $message,
697
+			];
698
+		}
699
+		// can we wrap it up and verify default data?
700
+		$init_dbs = false;
701
+		// ok so we definitely have a data migration script
702
+		try {
703
+			// how big of a bite do we want to take? Allow users to easily override via their wp-config
704
+			if (absint($step_size) < 1) {
705
+				$step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
706
+					? EE_MIGRATION_STEP_SIZE
707
+					: EE_Data_Migration_Manager::step_size;
708
+			}
709
+			// do what we came to do!
710
+			$currently_executing_script->migration_step($step_size);
711
+			switch ($currently_executing_script->get_status()) {
712
+				case EE_Data_Migration_Manager::status_continue:
713
+					$response_array = [
714
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
715
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
716
+						'status'             => EE_Data_Migration_Manager::status_continue,
717
+						'message'            => $currently_executing_script->get_feedback_message(),
718
+						'script'             => $currently_executing_script->pretty_name(),
719
+					];
720
+					break;
721
+				case EE_Data_Migration_Manager::status_completed:
722
+					// ok so THAT script has completed
723
+					$this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
724
+					$response_array = [
725
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
726
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
727
+						'status'             => EE_Data_Migration_Manager::status_completed,
728
+						'message'            => $currently_executing_script->get_feedback_message(),
729
+						'script'             => sprintf(
730
+							esc_html__("%s Completed", 'event_espresso'),
731
+							$currently_executing_script->pretty_name()
732
+						),
733
+					];
734
+					// check if there are any more after this one.
735
+					$scripts_remaining = $this->check_for_applicable_data_migration_scripts();
736
+					if (! $scripts_remaining) {
737
+						// we should be good to allow them to exit maintenance mode now
738
+						EE_Maintenance_Mode::instance()->set_maintenance_level(
739
+							EE_Maintenance_Mode::level_0_not_in_maintenance
740
+						);
741
+						// huh, no more scripts to run... apparently we're done!
742
+						// but don't forget to make sure initial data is there
743
+						$init_dbs                 = true;
744
+						$response_array['status'] = self::status_no_more_migration_scripts;
745
+					}
746
+					break;
747
+				default:
748
+					$response_array = [
749
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
750
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
751
+						'status'             => $currently_executing_script->get_status(),
752
+						'message'            => sprintf(
753
+							esc_html__("Minor errors occurred during %s: %s", "event_espresso"),
754
+							$currently_executing_script->pretty_name(),
755
+							implode(", ", $currently_executing_script->get_errors())
756
+						),
757
+						'script'             => $currently_executing_script->pretty_name(),
758
+					];
759
+					break;
760
+			}
761
+		} catch (Exception $e) {
762
+			// ok so some exception was thrown which killed the data migration script
763
+			// double-check we have a real script
764
+			if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
765
+				$script_name = $currently_executing_script->pretty_name();
766
+				$currently_executing_script->set_broken();
767
+				$currently_executing_script->add_error($e->getMessage());
768
+			} else {
769
+				$script_name = esc_html__("Error getting Migration Script", "event_espresso");
770
+			}
771
+			$response_array = [
772
+				'records_to_migrate' => 1,
773
+				'records_migrated'   => 0,
774
+				'status'             => self::status_fatal_error,
775
+				'message'            => sprintf(
776
+					esc_html__("A fatal error occurred during the migration: %s", "event_espresso"),
777
+					$e->getMessage()
778
+				),
779
+				'script'             => $script_name,
780
+			];
781
+		}
782
+		$successful_save = $this->_save_migrations_ran();
783
+		if ($successful_save !== true) {
784
+			// ok so the current wp option didn't save. that's tricky, because we'd like to update it
785
+			// and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
786
+			// however, if we throw an exception, and return that, then the next request
787
+			// won't have as much info in it, and it may be able to save
788
+			throw new EE_Error(
789
+				sprintf(
790
+					esc_html__(
791
+						"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.",
792
+						"event_espresso"
793
+					),
794
+					$successful_save
795
+				)
796
+			);
797
+		}
798
+		// if we're all done, initialize EE plugins' default data etc.
799
+		if ($init_dbs) {
800
+			$this->initialize_db_for_enqueued_ee_plugins();
801
+		}
802
+		return $response_array;
803
+	}
804
+
805
+
806
+	/**
807
+	 * Echo out JSON response to migration script AJAX requests. Takes precautions
808
+	 * to buffer output so that we don't throw junk into our json.
809
+	 *
810
+	 * @return array with keys:
811
+	 * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
812
+	 * it's NOT the count of hwo many remain)
813
+	 * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
814
+	 * records_migrated/records_to_migrate)
815
+	 * 'status'=>a string, one of EE_Data_migration_Manager::status_*
816
+	 * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
817
+	 * errors, notifications, and successes
818
+	 * 'script'=>a pretty name of the script currently running
819
+	 */
820
+	public function response_to_migration_ajax_request()
821
+	{
822
+		ob_start();
823
+		try {
824
+			$response = $this->migration_step();
825
+		} catch (Exception $e) {
826
+			$response = [
827
+				'records_to_migrate' => 0,
828
+				'records_migrated'   => 0,
829
+				'status'             => EE_Data_Migration_Manager::status_fatal_error,
830
+				'message'            => sprintf(
831
+					esc_html__("Unknown fatal error occurred: %s", "event_espresso"),
832
+					$e->getMessage()
833
+				),
834
+				'script'             => 'Unknown',
835
+			];
836
+			$this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
837
+		}
838
+		$warnings_etc = @ob_get_contents();
839
+		ob_end_clean();
840
+		$response['message'] .= $warnings_etc;
841
+		return $response;
842
+	}
843
+
844
+
845
+	/**
846
+	 * Updates the WordPress option that keeps track of which EE version the database
847
+	 * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
848
+	 *
849
+	 * @param array $slug_and_version {
850
+	 * @type string $slug             like 'Core' or 'Calendar',
851
+	 * @type string $version          like '4.1.0'
852
+	 *                                }
853
+	 * @return void
854
+	 */
855
+	public function update_current_database_state_to($slug_and_version = null)
856
+	{
857
+		if (! $slug_and_version) {
858
+			// no version was provided, assume it should be at the current code version
859
+			$slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
860
+		}
861
+		$current_database_state                              = get_option(self::current_database_state);
862
+		$current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
863
+		update_option(self::current_database_state, $current_database_state);
864
+	}
865
+
866
+
867
+	/**
868
+	 * Determines if the database is currently at a state matching what's indicated in $slug and $version.
869
+	 *
870
+	 * @param array $slug_and_version {
871
+	 * @type string $slug             like 'Core' or 'Calendar',
872
+	 * @type string $version          like '4.1.0'
873
+	 *                                }
874
+	 * @return boolean
875
+	 */
876
+	public function database_needs_updating_to($slug_and_version)
877
+	{
878
+
879
+		$slug                   = $slug_and_version['slug'];
880
+		$version                = $slug_and_version['version'];
881
+		$current_database_state = get_option(self::current_database_state);
882
+		if (! isset($current_database_state[ $slug ])) {
883
+			return true;
884
+		} else {
885
+			// 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
886
+			$version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
887
+			$version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
888
+			$needs_updating                     = false;
889
+			foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
890
+				if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
891
+					$needs_updating = true;
892
+					break;
893
+				}
894
+			}
895
+			return $needs_updating;
896
+		}
897
+	}
898
+
899
+
900
+	/**
901
+	 * Gets all the data migration scripts available in the core folder and folders
902
+	 * in addons. Has the side effect of adding them for autoloading
903
+	 *
904
+	 * @return array keys are expected classnames, values are their filepaths
905
+	 * @throws InvalidInterfaceException
906
+	 * @throws InvalidDataTypeException
907
+	 * @throws EE_Error
908
+	 * @throws InvalidArgumentException
909
+	 */
910
+	public function get_all_data_migration_scripts_available()
911
+	{
912
+		if (! $this->_data_migration_class_to_filepath_map) {
913
+			$this->_data_migration_class_to_filepath_map = [];
914
+			foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
915
+				// strip any placeholders added to classname to make it a unique array key
916
+				$eeAddonClass = trim($eeAddonClass, '*');
917
+				$eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
918
+					? $eeAddonClass
919
+					: '';
920
+				$folder_path  = EEH_File::end_with_directory_separator($folder_path);
921
+				$files        = glob($folder_path . '*.dms.php');
922
+				if (empty($files)) {
923
+					continue;
924
+				}
925
+				foreach ($files as $file) {
926
+					$pos_of_last_slash = strrpos($file, '/');
927
+					$classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
928
+					$migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
929
+					$slug              = $migrates_to['slug'];
930
+					// check that the slug as contained in the DMS is associated with
931
+					// the slug of an addon or core
932
+					if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
933
+						EE_Error::doing_it_wrong(
934
+							__FUNCTION__,
935
+							sprintf(
936
+								esc_html__(
937
+									'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
938
+									'event_espresso'
939
+								),
940
+								$classname,
941
+								$slug,
942
+								implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
943
+							),
944
+							'4.3.0.alpha.019'
945
+						);
946
+					}
947
+					$this->_data_migration_class_to_filepath_map[ $classname ] = $file;
948
+				}
949
+			}
950
+			EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
951
+		}
952
+		return $this->_data_migration_class_to_filepath_map;
953
+	}
954
+
955
+
956
+	/**
957
+	 * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
958
+	 * from each addon, and check if they need updating,
959
+	 *
960
+	 * @return boolean
961
+	 */
962
+	public function addons_need_updating()
963
+	{
964
+		return false;
965
+	}
966
+
967
+
968
+	/**
969
+	 * Adds this error string to the data_migrations_ran array, but we don't necessarily know
970
+	 * where to put it, so we just throw it in there... better than nothing...
971
+	 *
972
+	 * @param string $error_message
973
+	 */
974
+	public function add_error_to_migrations_ran($error_message)
975
+	{
976
+		// get last-run migration script
977
+		global $wpdb;
978
+		$last_migration_script_option = $wpdb->get_row(
979
+			"SELECT * FROM $wpdb->options WHERE option_name like '"
980
+			. EE_Data_Migration_Manager::data_migration_script_option_prefix
981
+			. "%' ORDER BY option_id DESC LIMIT 1",
982
+			ARRAY_A
983
+		);
984
+
985
+		$last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
986
+			? maybe_unserialize($last_migration_script_option['option_value']) : null;
987
+		// now, tread lightly because we're here because a FATAL non-catchable error
988
+		// was thrown last time when we were trying to run a data migration script
989
+		// so the fatal error could have happened while getting the migration script
990
+		// or doing running it...
991
+		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
992
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
993
+			"",
994
+			$last_migration_script_option['option_name']
995
+		) : null;
996
+
997
+		// check if it THINKS it's a data migration script and especially if it's one that HASN'T finished yet
998
+		// because if it has finished, then it obviously couldn't be the cause of this error, right? (because it's all done)
999
+		if (
1000
+			isset($last_ran_migration_script_properties['class'])
1001
+			&& isset($last_ran_migration_script_properties['_status'])
1002
+			&& $last_ran_migration_script_properties['_status'] != self::status_completed
1003
+		) {
1004
+			// ok then just add this error to its list of errors
1005
+			$last_ran_migration_script_properties['_errors'][] = $error_message;
1006
+			$last_ran_migration_script_properties['_status']   = self::status_fatal_error;
1007
+		} else {
1008
+			// so we don't even know which script was last running
1009
+			// use the data migration error stub, which is designed specifically for this type of thing
1010
+			$general_migration_error = new EE_DMS_Unknown_1_0_0();
1011
+			$general_migration_error->add_error($error_message);
1012
+			$general_migration_error->set_broken();
1013
+			$last_ran_migration_script_properties = $general_migration_error->properties_as_array();
1014
+			$versions_migrated_to                 = 'Unknown.1.0.0';
1015
+			// now just to make sure appears as last (in case the were previously a fatal error like this)
1016
+			// delete the old one
1017
+			delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1018
+		}
1019
+		update_option(
1020
+			self::data_migration_script_option_prefix . $versions_migrated_to,
1021
+			$last_ran_migration_script_properties
1022
+		);
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * saves what data migrations have run to the database
1028
+	 *
1029
+	 * @return bool|string TRUE if successfully saved migrations ran, string if an error occurred
1030
+	 * @throws EE_Error
1031
+	 */
1032
+	protected function _save_migrations_ran()
1033
+	{
1034
+		if ($this->_data_migrations_ran == null) {
1035
+			$this->get_data_migrations_ran();
1036
+		}
1037
+		// now, we don't want to save actual classes to the DB because that's messy
1038
+		$successful_updates = true;
1039
+		foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1040
+			foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1041
+				$plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1042
+				$option_name                        =
1043
+					self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1044
+				$old_option_value                   = get_option($option_name);
1045
+				if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1046
+					$script_array_for_saving = $array_or_migration_obj->properties_as_array();
1047
+					if ($old_option_value != $script_array_for_saving) {
1048
+						$successful_updates = update_option($option_name, $script_array_for_saving);
1049
+					}
1050
+				} else {// we don't know what this array-thing is. So just save it as-is
1051
+					if ($old_option_value != $array_or_migration_obj) {
1052
+						$successful_updates = update_option($option_name, $array_or_migration_obj);
1053
+					}
1054
+				}
1055
+				if (! $successful_updates) {
1056
+					global $wpdb;
1057
+					return $wpdb->last_error;
1058
+				}
1059
+			}
1060
+		}
1061
+		return true;
1062
+		// $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1063
+		// if ($updated !== true) {
1064
+		//     global $wpdb;
1065
+		//     return $wpdb->last_error;
1066
+		// } else {
1067
+		//     return true;
1068
+		// }
1069
+		// wp_mail(
1070
+		//     "[email protected]",
1071
+		//     time() . " price debug info",
1072
+		//     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1073
+		//         serialize($array_of_migrations)
1074
+		//     )
1075
+		// );
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * Takes an array of data migration script properties and re-creates the class from
1081
+	 * them. The argument $properties_array is assumed to have been made by
1082
+	 * EE_Data_Migration_Script_Base::properties_as_array()
1083
+	 *
1084
+	 * @param array $properties_array
1085
+	 * @return EE_Data_Migration_Script_Base
1086
+	 * @throws EE_Error
1087
+	 */
1088
+	public function _instantiate_script_from_properties_array($properties_array)
1089
+	{
1090
+		if (! isset($properties_array['class'])) {
1091
+			throw new EE_Error(
1092
+				sprintf(
1093
+					esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1094
+					implode(",", $properties_array)
1095
+				)
1096
+			);
1097
+		}
1098
+		$class_name = $properties_array['class'];
1099
+		if (! class_exists($class_name)) {
1100
+			throw new EE_Error(sprintf(
1101
+				esc_html__("There is no migration script named %s", "event_espresso"),
1102
+				$class_name
1103
+			));
1104
+		}
1105
+		$class = new $class_name();
1106
+		if (! $class instanceof EE_Data_Migration_Script_Base) {
1107
+			throw new EE_Error(
1108
+				sprintf(
1109
+					esc_html__(
1110
+						"Class '%s' is supposed to be a migration script. Its not, its a '%s'",
1111
+						"event_espresso"
1112
+					),
1113
+					$class_name,
1114
+					get_class($class)
1115
+				)
1116
+			);
1117
+		}
1118
+		$class->instantiate_from_array_of_properties($properties_array);
1119
+		return $class;
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1125
+	 * leave the DB in a state usable by the current plugin code).
1126
+	 *
1127
+	 * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1128
+	 * @return string
1129
+	 * @throws EE_Error
1130
+	 * @throws EE_Error
1131
+	 */
1132
+	public function get_most_up_to_date_dms($plugin_slug = 'Core')
1133
+	{
1134
+		$class_to_filepath_map         = $this->get_all_data_migration_scripts_available();
1135
+		$most_up_to_date_dms_classname = null;
1136
+		foreach ($class_to_filepath_map as $classname => $filepath) {
1137
+			if ($most_up_to_date_dms_classname === null) {
1138
+				$migrates_to      = $this->script_migrates_to_version($classname);
1139
+				$this_plugin_slug = $migrates_to['slug'];
1140
+				if ($this_plugin_slug == $plugin_slug) {
1141
+					// if it's for core, it wins
1142
+					$most_up_to_date_dms_classname = $classname;
1143
+				}
1144
+				// if it wasn't for core, we must keep searching for one that is!
1145
+				continue;
1146
+			}
1147
+			$champion_migrates_to  = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1148
+			$contender_migrates_to = $this->script_migrates_to_version($classname);
1149
+			if (
1150
+				$contender_migrates_to['slug'] == $plugin_slug
1151
+				&& version_compare(
1152
+					$champion_migrates_to['version'],
1153
+					$contender_migrates_to['version'],
1154
+					'<'
1155
+				)
1156
+			) {
1157
+				// so the contenders version is higher, and it's for Core
1158
+				$most_up_to_date_dms_classname = $classname;
1159
+			}
1160
+		}
1161
+		return $most_up_to_date_dms_classname;
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Gets the migration script specified but ONLY if it has already run.
1167
+	 *
1168
+	 * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has run, you would run the following code:
1169
+	 * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1170
+	 * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1171
+	 * other addon) DMS has run, in case the current DMS depends on it.
1172
+	 *
1173
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1174
+	 *                            period. Eg '4.1.0'
1175
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1176
+	 * @return EE_Data_Migration_Script_Base
1177
+	 * @throws EE_Error
1178
+	 */
1179
+	public function get_migration_ran($version, $plugin_slug = 'Core')
1180
+	{
1181
+		$migrations_ran = $this->get_data_migrations_ran();
1182
+		if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1183
+			return $migrations_ran[ $plugin_slug ][ $version ];
1184
+		} else {
1185
+			return null;
1186
+		}
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * Resets the borked data migration scripts, so they're no longer borked, and we can again attempt to migrate
1192
+	 *
1193
+	 * @return bool
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public function reattempt()
1197
+	{
1198
+		// find if the last-run script was borked
1199
+		// set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1200
+		// add an 'error' saying that we attempted to reset
1201
+		// does it have a stage that was borked too? if so make it no longer borked
1202
+		// add an 'error' saying we attempted to reset
1203
+		$last_ran_script = $this->get_last_ran_script();
1204
+		if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1205
+			// if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1206
+			$last_ran_script->set_completed();
1207
+		} elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1208
+			$last_ran_script->reattempt();
1209
+		} else {
1210
+			throw new EE_Error(
1211
+				sprintf(
1212
+					esc_html__(
1213
+						'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1214
+						'event_espresso'
1215
+					),
1216
+					print_r($last_ran_script, true)
1217
+				)
1218
+			);
1219
+		}
1220
+		return $this->_save_migrations_ran();
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * Gets whether this particular migration has run or not
1226
+	 *
1227
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1228
+	 *                            period. Eg '4.1.0'
1229
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1230
+	 * @return boolean
1231
+	 * @throws EE_Error
1232
+	 */
1233
+	public function migration_has_ran($version, $plugin_slug = 'Core')
1234
+	{
1235
+		return $this->get_migration_ran($version, $plugin_slug) !== null;
1236
+	}
1237
+
1238
+
1239
+	/**
1240
+	 * Enqueues this ee plugin to have its data initialized
1241
+	 *
1242
+	 * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1243
+	 */
1244
+	public function enqueue_db_initialization_for($plugin_slug)
1245
+	{
1246
+		$queue = $this->get_db_initialization_queue();
1247
+		if (! in_array($plugin_slug, $queue)) {
1248
+			$queue[] = $plugin_slug;
1249
+		}
1250
+		update_option(self::db_init_queue_option_name, $queue);
1251
+	}
1252
+
1253
+
1254
+	/**
1255
+	 * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1256
+	 * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1257
+	 * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1258
+	 *
1259
+	 * @throws EE_Error
1260
+	 */
1261
+	public function initialize_db_for_enqueued_ee_plugins()
1262
+	{
1263
+		$queue = $this->get_db_initialization_queue();
1264
+		foreach ($queue as $plugin_slug) {
1265
+			$most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1266
+			if (! $most_up_to_date_dms) {
1267
+				// if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1268
+				$verify_db = false;
1269
+			} else {
1270
+				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1271
+				$verify_db                       = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1272
+			}
1273
+			if ($plugin_slug == 'Core') {
1274
+				EE_System::instance()->initialize_db_if_no_migrations_required(
1275
+					false,
1276
+					$verify_db
1277
+				);
1278
+			} else {
1279
+				// just loop through the addons to make sure their database is set up
1280
+				foreach (EE_Registry::instance()->addons as $addon) {
1281
+					if ($addon->name() == $plugin_slug) {
1282
+						$addon->initialize_db_if_no_migrations_required($verify_db);
1283
+						break;
1284
+					}
1285
+				}
1286
+			}
1287
+		}
1288
+		// because we just initialized the DBs for the enqueued ee plugins
1289
+		// we don't need to keep remembering which ones needed to be initialized
1290
+		delete_option(self::db_init_queue_option_name);
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * Gets a numerically-indexed array of plugin slugs that need to have their databases
1296
+	 * (re-)initialized after migrations are complete. ie, each element should be either
1297
+	 * 'Core', or the return value of EE_Addon::name() for an addon
1298
+	 *
1299
+	 * @return array
1300
+	 */
1301
+	public function get_db_initialization_queue()
1302
+	{
1303
+		return get_option(self::db_init_queue_option_name, []);
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * Gets the injected table analyzer, or throws an exception
1309
+	 *
1310
+	 * @return TableAnalysis
1311
+	 * @throws EE_Error
1312
+	 */
1313
+	protected function _get_table_analysis()
1314
+	{
1315
+		if ($this->_table_analysis instanceof TableAnalysis) {
1316
+			return $this->_table_analysis;
1317
+		} else {
1318
+			throw new EE_Error(
1319
+				sprintf(
1320
+					esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1321
+					get_class($this)
1322
+				)
1323
+			);
1324
+		}
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Gets the injected table manager, or throws an exception
1330
+	 *
1331
+	 * @return TableManager
1332
+	 * @throws EE_Error
1333
+	 */
1334
+	protected function _get_table_manager()
1335
+	{
1336
+		if ($this->_table_manager instanceof TableManager) {
1337
+			return $this->_table_manager;
1338
+		} else {
1339
+			throw new EE_Error(
1340
+				sprintf(
1341
+					esc_html__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1342
+					get_class($this)
1343
+				)
1344
+			);
1345
+		}
1346
+	}
1347 1347
 }
Please login to merge, or discard this patch.
Spacing   +61 added lines, -61 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
     }
@@ -305,11 +305,11 @@  discard block
 block discarded – undo
305 305
      */
306 306
     public function get_data_migrations_ran()
307 307
     {
308
-        if (! $this->_data_migrations_ran) {
308
+        if ( ! $this->_data_migrations_ran) {
309 309
             // setup autoloaders for each of the scripts in there
310 310
             $this->get_all_data_migration_scripts_available();
311 311
             $data_migrations_options =
312
-                $this->get_all_migration_script_options();// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
312
+                $this->get_all_migration_script_options(); // get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
313 313
 
314 314
             $data_migrations_ran = [];
315 315
             // convert into data migration script classes where possible
@@ -319,27 +319,27 @@  discard block
 block discarded – undo
319 319
                 );
320 320
 
321 321
                 try {
322
-                    $class                                                  = $this->_get_dms_class_from_wp_option(
322
+                    $class = $this->_get_dms_class_from_wp_option(
323 323
                         $data_migration_option['option_name'],
324 324
                         $data_migration_option['option_value']
325 325
                     );
326
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
326
+                    $data_migrations_ran[$plugin_slug][$version_string] = $class;
327 327
                     // ok so far THIS is the 'last-run-script'... unless we find another on next iteration
328 328
                     $this->_last_ran_script = $class;
329
-                    if (! $class->is_completed()) {
329
+                    if ( ! $class->is_completed()) {
330 330
                         // sometimes we also like to know which was the last incomplete script (or if there are any at all)
331 331
                         $this->_last_ran_incomplete_script = $class;
332 332
                     }
333 333
                 } catch (EE_Error $e) {
334 334
                     // ok so it's not a DMS. We'll just keep it, although other code will need to expect non-DMSs
335
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
335
+                    $data_migrations_ran[$plugin_slug][$version_string] = maybe_unserialize(
336 336
                         $data_migration_option['option_value']
337 337
                     );
338 338
                 }
339 339
             }
340 340
             // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
341 341
             $this->_data_migrations_ran = $data_migrations_ran;
342
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
342
+            if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
343 343
                 $this->_data_migrations_ran = [];
344 344
             }
345 345
         }
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
      */
360 360
     public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
361 361
     {
362
-        $script  = EE_Registry::instance()->load_dms($script_name);
362
+        $script = EE_Registry::instance()->load_dms($script_name);
363 363
         return $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
364 364
     }
365 365
 
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
     {
393 393
         return apply_filters(
394 394
             'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
395
-            ['Core' => EE_CORE . 'data_migration_scripts']
395
+            ['Core' => EE_CORE.'data_migration_scripts']
396 396
         );
397 397
     }
398 398
 
@@ -409,11 +409,11 @@  discard block
 block discarded – undo
409 409
      */
410 410
     public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
411 411
     {
412
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
413
-            return $this->script_migration_versions[ $migration_script_name ];
412
+        if (isset($this->script_migration_versions[$migration_script_name])) {
413
+            return $this->script_migration_versions[$migration_script_name];
414 414
         }
415 415
         $dms_info                                                  = $this->parse_dms_classname($migration_script_name);
416
-        $this->script_migration_versions[ $migration_script_name ] = [
416
+        $this->script_migration_versions[$migration_script_name] = [
417 417
             'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
418 418
             'version' => $dms_info['major_version']
419 419
                          . "."
@@ -421,7 +421,7 @@  discard block
 block discarded – undo
421 421
                          . "."
422 422
                          . $dms_info['micro_version'],
423 423
         ];
424
-        return $this->script_migration_versions[ $migration_script_name ];
424
+        return $this->script_migration_versions[$migration_script_name];
425 425
     }
426 426
 
427 427
 
@@ -436,7 +436,7 @@  discard block
 block discarded – undo
436 436
     {
437 437
         $matches = [];
438 438
         preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
439
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
439
+        if ( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
440 440
             throw new EE_Error(
441 441
                 sprintf(
442 442
                     esc_html__(
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
     {
469 469
         $espresso_db_core_updates = get_option('espresso_db_update', []);
470 470
         $db_state                 = get_option(EE_Data_Migration_Manager::current_database_state);
471
-        if (! $db_state) {
471
+        if ( ! $db_state) {
472 472
             // mark the DB as being in the state as the last version in there.
473 473
             // this is done to trigger maintenance mode and do data migration scripts
474 474
             // if the admin installed this version of EE over 3.1.x or 4.0.x
@@ -487,7 +487,7 @@  discard block
 block discarded – undo
487 487
         // in 4.1, $db_state would have only been a simple string like '4.1.0',
488 488
         // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
489 489
         // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
490
-        if (! is_array($db_state)) {
490
+        if ( ! is_array($db_state)) {
491 491
             $db_state = ['Core' => $db_state];
492 492
             update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
493 493
         }
@@ -531,8 +531,8 @@  discard block
 block discarded – undo
531 531
                 // check if this version script is DONE or not; or if it's never been run
532 532
                 if (
533 533
                     ! $scripts_ran
534
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ])
535
-                    || ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])
534
+                    || ! isset($scripts_ran[$script_converts_plugin_slug])
535
+                    || ! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])
536 536
                 ) {
537 537
                     // we haven't run this conversion script before
538 538
                     // now check if it applies...
@@ -541,28 +541,28 @@  discard block
 block discarded – undo
541 541
                     /* @var $script EE_Data_Migration_Script_Base */
542 542
                     $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
543 543
                     if ($can_migrate) {
544
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
544
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
545 545
                         $migrates_to_version                                                                 =
546 546
                             $script->migrates_to_version();
547
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
547
+                        $next_database_state_to_consider[$migrates_to_version['slug']]                     =
548 548
                             $migrates_to_version['version'];
549
-                        unset($script_class_and_filepaths_available[ $classname ]);
549
+                        unset($script_class_and_filepaths_available[$classname]);
550 550
                     }
551 551
                 } elseif (
552
-                    $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]
552
+                    $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version]
553 553
                           instanceof
554 554
                           EE_Data_Migration_Script_Base
555 555
                 ) {
556 556
                     // this script has been run, or at least started
557
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
557
+                    $script = $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version];
558 558
                     if ($script->get_status() !== self::status_completed) {
559 559
                         // this script is already underway... keep going with it
560
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
560
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
561 561
                         $migrates_to_version                                                                 =
562 562
                             $script->migrates_to_version();
563
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ]                     =
563
+                        $next_database_state_to_consider[$migrates_to_version['slug']]                     =
564 564
                             $migrates_to_version['version'];
565
-                        unset($script_class_and_filepaths_available[ $classname ]);
565
+                        unset($script_class_and_filepaths_available[$classname]);
566 566
                     }
567 567
                     // else it must have a status that indicates it has finished,
568 568
                     // so we don't want to try and run it again
@@ -571,14 +571,14 @@  discard block
 block discarded – undo
571 571
                 // or was simply removed from EE? either way, it's certainly not runnable!
572 572
             }
573 573
             $iteration++;
574
-        } while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
574
+        }while ($next_database_state_to_consider !== $theoretical_database_state && $iteration < 6);
575 575
         // ok we have all the scripts that should run, now let's make them into flat array
576 576
         $scripts_that_should_run = [];
577 577
         foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
578 578
             ksort($scripts_at_priority);
579 579
             foreach ($scripts_at_priority as $scripts) {
580 580
                 foreach ($scripts as $script) {
581
-                    $scripts_that_should_run[ get_class($script) ] = $script;
581
+                    $scripts_that_should_run[get_class($script)] = $script;
582 582
                 }
583 583
             }
584 584
         }
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
     public function get_last_ran_script($include_completed_scripts = false)
605 605
     {
606 606
         // make sure we've set up the class properties _last_ran_script and _last_ran_incomplete_script
607
-        if (! $this->_data_migrations_ran) {
607
+        if ( ! $this->_data_migrations_ran) {
608 608
             $this->get_data_migrations_ran();
609 609
         }
610 610
         if ($include_completed_scripts) {
@@ -641,10 +641,10 @@  discard block
 block discarded – undo
641 641
 
642 642
         try {
643 643
             $currently_executing_script = $this->get_last_ran_script();
644
-            if (! $currently_executing_script) {
644
+            if ( ! $currently_executing_script) {
645 645
                 // Find the next script that needs to execute
646 646
                 $scripts = $this->check_for_applicable_data_migration_scripts();
647
-                if (! $scripts) {
647
+                if ( ! $scripts) {
648 648
                     // huh, no more scripts to run... apparently we're done!
649 649
                     // but don't forget to make sure initial data is there
650 650
                     // we should be good to allow them to exit maintenance mode now
@@ -672,7 +672,7 @@  discard block
 block discarded – undo
672 672
                     $this->script_migrates_to_version(get_class($currently_executing_script));
673 673
                 $plugin_slug                                            = $migrates_to['slug'];
674 674
                 $version                                                = $migrates_to['version'];
675
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
675
+                $this->_data_migrations_ran[$plugin_slug][$version] = $currently_executing_script;
676 676
             }
677 677
             $current_script_name = get_class($currently_executing_script);
678 678
         } catch (Exception $e) {
@@ -680,7 +680,7 @@  discard block
 block discarded – undo
680 680
 
681 681
             $message = sprintf(
682 682
                 esc_html__("Error Message: %sStack Trace:%s", "event_espresso"),
683
-                $e->getMessage() . '<br>',
683
+                $e->getMessage().'<br>',
684 684
                 $e->getTraceAsString()
685 685
             );
686 686
             // record it on the array of data migration scripts run. This will be overwritten next time we try and try to run data migrations
@@ -733,7 +733,7 @@  discard block
 block discarded – undo
733 733
                     ];
734 734
                     // check if there are any more after this one.
735 735
                     $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
736
-                    if (! $scripts_remaining) {
736
+                    if ( ! $scripts_remaining) {
737 737
                         // we should be good to allow them to exit maintenance mode now
738 738
                         EE_Maintenance_Mode::instance()->set_maintenance_level(
739 739
                             EE_Maintenance_Mode::level_0_not_in_maintenance
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
                 ),
834 834
                 'script'             => 'Unknown',
835 835
             ];
836
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
836
+            $this->add_error_to_migrations_ran($e->getMessage()."; Stack trace:".$e->getTraceAsString());
837 837
         }
838 838
         $warnings_etc = @ob_get_contents();
839 839
         ob_end_clean();
@@ -854,12 +854,12 @@  discard block
 block discarded – undo
854 854
      */
855 855
     public function update_current_database_state_to($slug_and_version = null)
856 856
     {
857
-        if (! $slug_and_version) {
857
+        if ( ! $slug_and_version) {
858 858
             // no version was provided, assume it should be at the current code version
859 859
             $slug_and_version = ['slug' => 'Core', 'version' => espresso_version()];
860 860
         }
861 861
         $current_database_state                              = get_option(self::current_database_state);
862
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
862
+        $current_database_state[$slug_and_version['slug']] = $slug_and_version['version'];
863 863
         update_option(self::current_database_state, $current_database_state);
864 864
     }
865 865
 
@@ -879,15 +879,15 @@  discard block
 block discarded – undo
879 879
         $slug                   = $slug_and_version['slug'];
880 880
         $version                = $slug_and_version['version'];
881 881
         $current_database_state = get_option(self::current_database_state);
882
-        if (! isset($current_database_state[ $slug ])) {
882
+        if ( ! isset($current_database_state[$slug])) {
883 883
             return true;
884 884
         } else {
885 885
             // 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
886
-            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
886
+            $version_parts_current_db_state     = array_slice(explode('.', $current_database_state[$slug]), 0, 3);
887 887
             $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
888 888
             $needs_updating                     = false;
889 889
             foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
890
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
890
+                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[$offset]) {
891 891
                     $needs_updating = true;
892 892
                     break;
893 893
                 }
@@ -909,7 +909,7 @@  discard block
 block discarded – undo
909 909
      */
910 910
     public function get_all_data_migration_scripts_available()
911 911
     {
912
-        if (! $this->_data_migration_class_to_filepath_map) {
912
+        if ( ! $this->_data_migration_class_to_filepath_map) {
913 913
             $this->_data_migration_class_to_filepath_map = [];
914 914
             foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
915 915
                 // strip any placeholders added to classname to make it a unique array key
@@ -918,7 +918,7 @@  discard block
 block discarded – undo
918 918
                     ? $eeAddonClass
919 919
                     : '';
920 920
                 $folder_path  = EEH_File::end_with_directory_separator($folder_path);
921
-                $files        = glob($folder_path . '*.dms.php');
921
+                $files        = glob($folder_path.'*.dms.php');
922 922
                 if (empty($files)) {
923 923
                     continue;
924 924
                 }
@@ -944,7 +944,7 @@  discard block
 block discarded – undo
944 944
                             '4.3.0.alpha.019'
945 945
                         );
946 946
                     }
947
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
947
+                    $this->_data_migration_class_to_filepath_map[$classname] = $file;
948 948
                 }
949 949
             }
950 950
             EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
@@ -1014,10 +1014,10 @@  discard block
 block discarded – undo
1014 1014
             $versions_migrated_to                 = 'Unknown.1.0.0';
1015 1015
             // now just to make sure appears as last (in case the were previously a fatal error like this)
1016 1016
             // delete the old one
1017
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
1017
+            delete_option(self::data_migration_script_option_prefix.$versions_migrated_to);
1018 1018
         }
1019 1019
         update_option(
1020
-            self::data_migration_script_option_prefix . $versions_migrated_to,
1020
+            self::data_migration_script_option_prefix.$versions_migrated_to,
1021 1021
             $last_ran_migration_script_properties
1022 1022
         );
1023 1023
     }
@@ -1038,9 +1038,9 @@  discard block
 block discarded – undo
1038 1038
         $successful_updates = true;
1039 1039
         foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
1040 1040
             foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
1041
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
1041
+                $plugin_slug_for_use_in_option_name = $plugin_slug.".";
1042 1042
                 $option_name                        =
1043
-                    self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
1043
+                    self::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string;
1044 1044
                 $old_option_value                   = get_option($option_name);
1045 1045
                 if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
1046 1046
                     $script_array_for_saving = $array_or_migration_obj->properties_as_array();
@@ -1052,7 +1052,7 @@  discard block
 block discarded – undo
1052 1052
                         $successful_updates = update_option($option_name, $array_or_migration_obj);
1053 1053
                     }
1054 1054
                 }
1055
-                if (! $successful_updates) {
1055
+                if ( ! $successful_updates) {
1056 1056
                     global $wpdb;
1057 1057
                     return $wpdb->last_error;
1058 1058
                 }
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
      */
1088 1088
     public function _instantiate_script_from_properties_array($properties_array)
1089 1089
     {
1090
-        if (! isset($properties_array['class'])) {
1090
+        if ( ! isset($properties_array['class'])) {
1091 1091
             throw new EE_Error(
1092 1092
                 sprintf(
1093 1093
                     esc_html__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
@@ -1096,14 +1096,14 @@  discard block
 block discarded – undo
1096 1096
             );
1097 1097
         }
1098 1098
         $class_name = $properties_array['class'];
1099
-        if (! class_exists($class_name)) {
1099
+        if ( ! class_exists($class_name)) {
1100 1100
             throw new EE_Error(sprintf(
1101 1101
                 esc_html__("There is no migration script named %s", "event_espresso"),
1102 1102
                 $class_name
1103 1103
             ));
1104 1104
         }
1105 1105
         $class = new $class_name();
1106
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1106
+        if ( ! $class instanceof EE_Data_Migration_Script_Base) {
1107 1107
             throw new EE_Error(
1108 1108
                 sprintf(
1109 1109
                     esc_html__(
@@ -1179,8 +1179,8 @@  discard block
 block discarded – undo
1179 1179
     public function get_migration_ran($version, $plugin_slug = 'Core')
1180 1180
     {
1181 1181
         $migrations_ran = $this->get_data_migrations_ran();
1182
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1183
-            return $migrations_ran[ $plugin_slug ][ $version ];
1182
+        if (isset($migrations_ran[$plugin_slug]) && isset($migrations_ran[$plugin_slug][$version])) {
1183
+            return $migrations_ran[$plugin_slug][$version];
1184 1184
         } else {
1185 1185
             return null;
1186 1186
         }
@@ -1244,7 +1244,7 @@  discard block
 block discarded – undo
1244 1244
     public function enqueue_db_initialization_for($plugin_slug)
1245 1245
     {
1246 1246
         $queue = $this->get_db_initialization_queue();
1247
-        if (! in_array($plugin_slug, $queue)) {
1247
+        if ( ! in_array($plugin_slug, $queue)) {
1248 1248
             $queue[] = $plugin_slug;
1249 1249
         }
1250 1250
         update_option(self::db_init_queue_option_name, $queue);
@@ -1263,7 +1263,7 @@  discard block
 block discarded – undo
1263 1263
         $queue = $this->get_db_initialization_queue();
1264 1264
         foreach ($queue as $plugin_slug) {
1265 1265
             $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1266
-            if (! $most_up_to_date_dms) {
1266
+            if ( ! $most_up_to_date_dms) {
1267 1267
                 // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1268 1268
                 $verify_db = false;
1269 1269
             } else {
Please login to merge, or discard this patch.
core/libraries/shortcodes/EE_Shortcodes.lib.php 2 patches
Indentation   +452 added lines, -452 removed lines patch added patch discarded remove patch
@@ -17,456 +17,456 @@
 block discarded – undo
17 17
 abstract class EE_Shortcodes extends EE_Base
18 18
 {
19 19
 
20
-    /**
21
-     * holds label for library
22
-     * This is used for referencing the library label
23
-     *
24
-     * @access public
25
-     * @var string
26
-     */
27
-    public $label;
28
-
29
-
30
-    /**
31
-     * This property is used for referencing a short description of the library
32
-     *
33
-     * @access public
34
-     * @var string
35
-     */
36
-    public $description;
37
-
38
-
39
-    /**
40
-     * This will hold an array of shortcodes with the key as the shortcode ([shortcode]) and the value as a
41
-     * label/description for the shortcode.
42
-     *
43
-     * @access protected
44
-     * @var array
45
-     */
46
-    protected $_shortcodes;
47
-
48
-
49
-    /**
50
-     * This will hold the incoming data item sent to the parser method
51
-     *
52
-     * @access protected
53
-     * @var mixed (array|object)
54
-     */
55
-    protected $_data;
56
-
57
-
58
-    /**
59
-     * some shortcodes may require extra data to parse.  This property is provided for that.
60
-     *
61
-     * @var array
62
-     */
63
-    protected $_extra_data;
64
-
65
-
66
-    /**
67
-     * EE_messenger used to generate the template being parsed.
68
-     *
69
-     * @since 4.5.0
70
-     * @var EE_messenger
71
-     */
72
-    protected $_messenger;
73
-
74
-
75
-    /**
76
-     * message type used to generate the template being parsed.
77
-     *
78
-     * @since 4.5.0
79
-     * @var EE_message_type
80
-     */
81
-    protected $_message_type;
82
-
83
-
84
-    /**
85
-     * context used for the template being parsed
86
-     *
87
-     * @since 4.5.0
88
-     * @var string
89
-     */
90
-    protected $_context;
91
-
92
-
93
-    /**
94
-     * Specific Message Template Group ID
95
-     *
96
-     * @since 4.5.0
97
-     * @var int
98
-     */
99
-    protected $_GRP_ID;
100
-
101
-
102
-    /**
103
-     * @since 4.9.0
104
-     * @type EE_Message
105
-     */
106
-    protected $_message;
107
-
108
-
109
-    /**
110
-     * This will hold an instance of the EEH_Parse_Shortcodes helper that will be used when handling list type
111
-     * shortcodes
112
-     *
113
-     * @var EEH_Parse_Shortcodes
114
-     */
115
-    protected $_shortcode_helper;
116
-
117
-
118
-    public function __construct()
119
-    {
120
-        $this->_set_defaults();
121
-        $this->_init_props();
122
-    }
123
-
124
-
125
-    /**
126
-     * This sets the defaults for the properties.  Child classes will override these properties in their _init_props
127
-     * method
128
-     */
129
-    private function _set_defaults()
130
-    {
131
-        $this->name = $this->description = '';
132
-        $this->_shortcodes = array();
133
-        $this->_set_shortcode_helper();
134
-    }
135
-
136
-
137
-    /**
138
-     * loads an instance of the EE_Shortcode_Parser helper when requested
139
-     */
140
-    protected function _set_shortcode_helper()
141
-    {
142
-        // get shortcode_replace instance- set when _get_messages is called in child...
143
-        $this->_shortcode_helper = new EEH_Parse_Shortcodes();
144
-    }
145
-
146
-
147
-    public function get_shortcode_helper()
148
-    {
149
-        if (! $this->_shortcode_helper instanceof EEH_Parse_Shortcodes) {
150
-            $this->_set_shortcode_helper();
151
-        }
152
-        return $this->_shortcode_helper;
153
-    }
154
-
155
-
156
-    /**
157
-     * This is the public method for kicking of the parser included with each child.  It can be overridden by child
158
-     * classes if necessary (see EE_Questions_Answers for example)
159
-     *
160
-     * @param  string $shortcode incoming shortcode to be parsed
161
-     * @param  mixed (object|array) $data       incoming data to be be used for parsing
162
-     * @param  mixed (object|array) $extra_data extra incoming data (usually EE_Messages_Addressee)
163
-     * @return string            parsed shortcode.
164
-     */
165
-    public function parser($shortcode, $data, $extra_data = array())
166
-    {
167
-
168
-        // filter setup shortcodes
169
-        $this->_shortcodes = $this->get_shortcodes();
170
-
171
-        // we need to setup any dynamic shortcodes so that they work with the array_key_exists
172
-        preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
173
-        $sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
174
-
175
-        // first we want to make sure this is a valid shortcode
176
-        if (! array_key_exists($sc_to_verify, $this->_shortcodes)) {
177
-            return false;
178
-        } //get out, this parser doesn't handle the incoming shortcode.
179
-        $this->_data = $data;
180
-        $this->_extra_data = $extra_data;
181
-        $this->_set_messages_properties();
182
-        $parsed = apply_filters(
183
-            'FHEE__' . get_class($this) . '__parser_after',
184
-            $this->_parser($shortcode),
185
-            $shortcode,
186
-            $data,
187
-            $extra_data,
188
-            $this
189
-        );
190
-
191
-        // note the below filter applies to ALL shortcode parsers... be careful!
192
-        return apply_filters('FHEE__EE_Shortcodes__parser_after', $parsed, $shortcode, $data, $extra_data, $this);
193
-    }
194
-
195
-
196
-    /**
197
-     * This method just returns the shortcodes in the $_shortcodes array property.
198
-     *
199
-     * @access public
200
-     * @return array array of shortcodes => description pairs
201
-     */
202
-    public function get_shortcodes()
203
-    {
204
-        $this->_shortcodes = apply_filters('FHEE__' . get_class($this) . '__shortcodes', $this->_shortcodes, $this);
205
-
206
-        // note the below filter applies to ALL shortcode parsers... be careful!
207
-        $this->_shortcodes = apply_filters('FHEE__EE_Shortcodes__shortcodes', $this->_shortcodes, $this);
208
-
209
-        return $this->_shortcodes;
210
-    }
211
-
212
-
213
-    /**
214
-     * Child classes use this method to set the $name, $description, and $_shortcodes properties.
215
-     *
216
-     * @abstract
217
-     * @access protected
218
-     * @return void
219
-     */
220
-    abstract protected function _init_props();
221
-
222
-
223
-    /**
224
-     * This method will give parsing instructions for each shortcode defined in the _shortcodes array.  Child methods
225
-     * will have to take care of handling.
226
-     *
227
-     * @abstract
228
-     * @access protected
229
-     * @param string $shortcode    the shortcode to be parsed.
230
-     * @param mixed (object|array) $data      incoming data for the parser.  The data could be either an object or
231
-     *                             array because there are some shortcodes that might be replaced by prepared data that
232
-     *                             has multiple items in a list (i.e. list of attendees in an event and we're showing
233
-     *                             fname/lname for each attendee).  In this case data will be in an array.  Otherwise
234
-     *                             the data shoudl be in a properly formatted object.  The
235
-     *                             EEH_Parse_Shortcodes.helper.php describes the data object we're expecting.
236
-     * @return string parsed shortcode
237
-     */
238
-    abstract protected function _parser($shortcode);
239
-
240
-
241
-    /**
242
-     * This just validates incoming data for list type shortcode parsers (and they call this method) to make sure it
243
-     * meets their requirements
244
-     *
245
-     * @return mixed (void|exception) If validation fails we'll throw an exception.
246
-     */
247
-    protected function _validate_list_requirements()
248
-    {
249
-
250
-        // first test to make sure we've got an array!
251
-        if (! is_array($this->_data)) {
252
-            throw new EE_Error(
253
-                sprintf(
254
-                    esc_html__(
255
-                        'Expecting an array for the data sent to %s. Instead it was %s',
256
-                        'event_espresso'
257
-                    ),
258
-                    get_class($this),
259
-                    gettype($this->_data)
260
-                )
261
-            );
262
-        }
263
-
264
-        // next test to make sure we've got the required template in the index!
265
-        if (! isset($this->_data['template'])) {
266
-            throw new EE_Error(
267
-                sprintf(
268
-                    esc_html__(
269
-                        'The incoming data does not have the required template index in its array',
270
-                        'event_espresso'
271
-                    )
272
-                )
273
-            );
274
-        }
275
-
276
-        // next test to make sure we've got got a data index in the incoming data array
277
-        if (! isset($this->_data['data'])) {
278
-            throw new EE_Error(
279
-                esc_html__(
280
-                    'The incoming data does not have the required data index in its array',
281
-                    'event_espresso'
282
-                )
283
-            );
284
-        }
285
-
286
-        // all is well let's make sure _extra_data always has the values needed.
287
-        // let's make sure that extra_data includes all templates (for later parsing if necessary)
288
-        if (empty($this->_extra_data) || (empty($this->_extra_data['data']) && empty($this->_extra_data['template']))) {
289
-            $this->_extra_data['data'] = $this->_data['data'];
290
-            $this->_extra_data['template'] = $this->_data['template'];
291
-        }
292
-    }
293
-
294
-
295
-    /**
296
-     * This returns any attributes that may be existing on an EE_Shortcode
297
-     *
298
-     * @since 4.5.0
299
-     * @param string $shortcode incoming shortcode
300
-     * @return array An array with the attributes
301
-     */
302
-    protected function _get_shortcode_attrs($shortcode)
303
-    {
304
-        // make sure the required wp helper function is present
305
-        // require the shortcode file if necessary
306
-        if (! function_exists('shortcode_parse_atts')) {
307
-            require_once(ABSPATH . WPINC . '/shortcodes.php');
308
-        }
309
-
310
-        // let's get any attributes that may be present and set the defaults.
311
-        $shortcode_to_parse = str_replace('[', '', str_replace(']', '', $shortcode));
312
-        return shortcode_parse_atts($shortcode_to_parse);
313
-    }
314
-
315
-
316
-    /**
317
-     * Conditional blocks are shortcode patterns with an opening conditional tag `[IF_*]` and a corresponding
318
-     * closing tag (eg `[/IF_*]`).  The content within the tags will be displayed/hidden depending on whatever
319
-     * conditions existed in the opening tag.  This method handles parsing the actual template to show/hide this
320
-     * conditional content.
321
-     *
322
-     * @since 4.9.32
323
-     *
324
-     * @param string $shortcode This should be original shortcode as used in the template and passed to the parser.
325
-     * @param bool   $show      true means the opening and closing tags are removed and the content is left showing,
326
-     *                          false means the opening and closing tags and the contained content are removed.
327
-     * @return string     The template for the shortcode is returned.
328
-     */
329
-    protected function _mutate_conditional_block_in_template($shortcode, $show = true)
330
-    {
331
-        // first let's get all the matches in the template for this particular shortcode.
332
-        preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches);
333
-
334
-        if ($matches && is_array($matches[0]) && ! empty($matches[0])) {
335
-            // we need to hide all instances of the matches
336
-            foreach ($matches[0] as $index => $content_to_show_or_hide) {
337
-                $content_to_show_or_hide = preg_quote($content_to_show_or_hide);
338
-                $replacement = $show ? $matches[4][ $index ] : '';
339
-                $this->_data['template'] = preg_replace(
340
-                    '~' . $content_to_show_or_hide . '~',
341
-                    $replacement,
342
-                    $this->_data['template']
343
-                );
344
-            }
345
-        }
346
-        // return $template
347
-        return $this->_data['template'];
348
-    }
349
-
350
-
351
-    /**
352
-     * This returns the regex pattern to use for conditional shortcodes parsing.
353
-     *
354
-     * Note: regex comes in part from the WP `get_shortcode_regex` expression in \wp-includes\shortcodes.php
355
-     *
356
-     * @param $shortcode
357
-     * @since 4.9.32
358
-     * @return string
359
-     */
360
-    private function _get_conditional_block_regex($shortcode)
361
-    {
362
-        // get just the shortcode tag for the match
363
-        preg_match('@\[([^<>&/\[\]\x00-\x20=]++)@', $shortcode, $shortcode_tag_matches);
364
-        if (empty($shortcode_tag_matches[1])) {
365
-            return $this->_data['template'];
366
-        }
367
-
368
-        $shortcode_tag = $shortcode_tag_matches[1];
369
-        // get attributes_part_of_tag
370
-        $attributes_part = preg_quote(str_replace(array($shortcode_tag, '[', ']'), '', $shortcode));
371
-        // escape
372
-        $shortcode_tag = preg_quote($shortcode_tag);
373
-
374
-        return
375
-            '\['                                  // Opening Bracket
376
-            . "($shortcode_tag)$attributes_part"    // 1: Shortcode Name
377
-            . '(?![\w-])'                           // Not followed by word character or hyphen
378
-            . '('                                   // 2: Unroll the loop: Inside the opening shortcode tag
379
-            . '[^\]\/]*'                          // Not a closing bracket or forward slash
380
-            . '(?:'
381
-            . '\/(?!\])'                      // A forward slash not followed by a closing bracket
382
-            . '[^\]\/]*'                      // Not a closing bracket or forward slash.
383
-            . ')*?'
384
-            . ')'
385
-            . '(?:'
386
-            . '(\/)'                              // 3. Self closing tag ...
387
-            . '\]'                                // ... and closing bracket
388
-            . '|'
389
-            . '\]'                                // Closing bracket
390
-            . '(?:'
391
-            . '('                             // 4: Unroll the loop: Optionally, anything between the opening and closing brackets
392
-            . '[^\[]*+'                   // Not an opening bracket
393
-            . '(?:'
394
-            . '\[(?!\/\1\])'          // An opening bracket not followed by the closing shortcode tag.
395
-            . '[^\[]*+'               // Not an opening bracket
396
-            . ')*+'
397
-            . ')'
398
-            . '\[\/\1\]'                      // Closing shortcode tag
399
-            . ')?'
400
-            . ')';
401
-    }
402
-
403
-
404
-    /**
405
-     * This sets the properties related to the messages system
406
-     *
407
-     * @since 4.5.0
408
-     * @return void
409
-     */
410
-    protected function _set_messages_properties()
411
-    {
412
-        // should be in _extra_data
413
-        if (isset($this->_extra_data['messenger'])) {
414
-            $this->_messenger = $this->_extra_data['messenger'];
415
-            $this->_message_type = $this->_extra_data['message_type'];
416
-            $this->_context = $this->_extra_data['message'] instanceof EE_Message
417
-                ? $this->_extra_data['message']->context() : '';
418
-            $this->_GRP_ID = $this->_extra_data['message'] instanceof EE_Message
419
-                ? $this->_extra_data['message']->GRP_ID() : 0;
420
-            $this->_message = $this->_extra_data['message'] instanceof EE_Message ? $this->_extra_data['message']
421
-                : null;
422
-        }
423
-    }
424
-
425
-
426
-    /**
427
-     * This returns whatever the set message type object is that was set on this shortcode parser.
428
-     *
429
-     * @since 4.5.0
430
-     * @return EE_message_type
431
-     */
432
-    public function get_set_message_type()
433
-    {
434
-        return $this->_message_type;
435
-    }
436
-
437
-
438
-    /**
439
-     * This returns whatever the set messenger object is that was set on this shortcode parser
440
-     *
441
-     * @since 4.5.0
442
-     * @return EE_messenger
443
-     */
444
-    public function get_set_messenger()
445
-    {
446
-        return $this->_messenger;
447
-    }
448
-
449
-
450
-    /**
451
-     * This returns whatever the set context string is on this shortcode parser.
452
-     *
453
-     * @since 4.5.0
454
-     * @return string
455
-     */
456
-    public function get_set_context()
457
-    {
458
-        return $this->_context;
459
-    }
460
-
461
-
462
-    /**
463
-     * This returns whatever the set EE_Message object is on this shortcode.
464
-     *
465
-     * @since 4.9.0
466
-     * @return EE_Message
467
-     */
468
-    public function get_set_message()
469
-    {
470
-        return $this->_message;
471
-    }
20
+	/**
21
+	 * holds label for library
22
+	 * This is used for referencing the library label
23
+	 *
24
+	 * @access public
25
+	 * @var string
26
+	 */
27
+	public $label;
28
+
29
+
30
+	/**
31
+	 * This property is used for referencing a short description of the library
32
+	 *
33
+	 * @access public
34
+	 * @var string
35
+	 */
36
+	public $description;
37
+
38
+
39
+	/**
40
+	 * This will hold an array of shortcodes with the key as the shortcode ([shortcode]) and the value as a
41
+	 * label/description for the shortcode.
42
+	 *
43
+	 * @access protected
44
+	 * @var array
45
+	 */
46
+	protected $_shortcodes;
47
+
48
+
49
+	/**
50
+	 * This will hold the incoming data item sent to the parser method
51
+	 *
52
+	 * @access protected
53
+	 * @var mixed (array|object)
54
+	 */
55
+	protected $_data;
56
+
57
+
58
+	/**
59
+	 * some shortcodes may require extra data to parse.  This property is provided for that.
60
+	 *
61
+	 * @var array
62
+	 */
63
+	protected $_extra_data;
64
+
65
+
66
+	/**
67
+	 * EE_messenger used to generate the template being parsed.
68
+	 *
69
+	 * @since 4.5.0
70
+	 * @var EE_messenger
71
+	 */
72
+	protected $_messenger;
73
+
74
+
75
+	/**
76
+	 * message type used to generate the template being parsed.
77
+	 *
78
+	 * @since 4.5.0
79
+	 * @var EE_message_type
80
+	 */
81
+	protected $_message_type;
82
+
83
+
84
+	/**
85
+	 * context used for the template being parsed
86
+	 *
87
+	 * @since 4.5.0
88
+	 * @var string
89
+	 */
90
+	protected $_context;
91
+
92
+
93
+	/**
94
+	 * Specific Message Template Group ID
95
+	 *
96
+	 * @since 4.5.0
97
+	 * @var int
98
+	 */
99
+	protected $_GRP_ID;
100
+
101
+
102
+	/**
103
+	 * @since 4.9.0
104
+	 * @type EE_Message
105
+	 */
106
+	protected $_message;
107
+
108
+
109
+	/**
110
+	 * This will hold an instance of the EEH_Parse_Shortcodes helper that will be used when handling list type
111
+	 * shortcodes
112
+	 *
113
+	 * @var EEH_Parse_Shortcodes
114
+	 */
115
+	protected $_shortcode_helper;
116
+
117
+
118
+	public function __construct()
119
+	{
120
+		$this->_set_defaults();
121
+		$this->_init_props();
122
+	}
123
+
124
+
125
+	/**
126
+	 * This sets the defaults for the properties.  Child classes will override these properties in their _init_props
127
+	 * method
128
+	 */
129
+	private function _set_defaults()
130
+	{
131
+		$this->name = $this->description = '';
132
+		$this->_shortcodes = array();
133
+		$this->_set_shortcode_helper();
134
+	}
135
+
136
+
137
+	/**
138
+	 * loads an instance of the EE_Shortcode_Parser helper when requested
139
+	 */
140
+	protected function _set_shortcode_helper()
141
+	{
142
+		// get shortcode_replace instance- set when _get_messages is called in child...
143
+		$this->_shortcode_helper = new EEH_Parse_Shortcodes();
144
+	}
145
+
146
+
147
+	public function get_shortcode_helper()
148
+	{
149
+		if (! $this->_shortcode_helper instanceof EEH_Parse_Shortcodes) {
150
+			$this->_set_shortcode_helper();
151
+		}
152
+		return $this->_shortcode_helper;
153
+	}
154
+
155
+
156
+	/**
157
+	 * This is the public method for kicking of the parser included with each child.  It can be overridden by child
158
+	 * classes if necessary (see EE_Questions_Answers for example)
159
+	 *
160
+	 * @param  string $shortcode incoming shortcode to be parsed
161
+	 * @param  mixed (object|array) $data       incoming data to be be used for parsing
162
+	 * @param  mixed (object|array) $extra_data extra incoming data (usually EE_Messages_Addressee)
163
+	 * @return string            parsed shortcode.
164
+	 */
165
+	public function parser($shortcode, $data, $extra_data = array())
166
+	{
167
+
168
+		// filter setup shortcodes
169
+		$this->_shortcodes = $this->get_shortcodes();
170
+
171
+		// we need to setup any dynamic shortcodes so that they work with the array_key_exists
172
+		preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
173
+		$sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
174
+
175
+		// first we want to make sure this is a valid shortcode
176
+		if (! array_key_exists($sc_to_verify, $this->_shortcodes)) {
177
+			return false;
178
+		} //get out, this parser doesn't handle the incoming shortcode.
179
+		$this->_data = $data;
180
+		$this->_extra_data = $extra_data;
181
+		$this->_set_messages_properties();
182
+		$parsed = apply_filters(
183
+			'FHEE__' . get_class($this) . '__parser_after',
184
+			$this->_parser($shortcode),
185
+			$shortcode,
186
+			$data,
187
+			$extra_data,
188
+			$this
189
+		);
190
+
191
+		// note the below filter applies to ALL shortcode parsers... be careful!
192
+		return apply_filters('FHEE__EE_Shortcodes__parser_after', $parsed, $shortcode, $data, $extra_data, $this);
193
+	}
194
+
195
+
196
+	/**
197
+	 * This method just returns the shortcodes in the $_shortcodes array property.
198
+	 *
199
+	 * @access public
200
+	 * @return array array of shortcodes => description pairs
201
+	 */
202
+	public function get_shortcodes()
203
+	{
204
+		$this->_shortcodes = apply_filters('FHEE__' . get_class($this) . '__shortcodes', $this->_shortcodes, $this);
205
+
206
+		// note the below filter applies to ALL shortcode parsers... be careful!
207
+		$this->_shortcodes = apply_filters('FHEE__EE_Shortcodes__shortcodes', $this->_shortcodes, $this);
208
+
209
+		return $this->_shortcodes;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Child classes use this method to set the $name, $description, and $_shortcodes properties.
215
+	 *
216
+	 * @abstract
217
+	 * @access protected
218
+	 * @return void
219
+	 */
220
+	abstract protected function _init_props();
221
+
222
+
223
+	/**
224
+	 * This method will give parsing instructions for each shortcode defined in the _shortcodes array.  Child methods
225
+	 * will have to take care of handling.
226
+	 *
227
+	 * @abstract
228
+	 * @access protected
229
+	 * @param string $shortcode    the shortcode to be parsed.
230
+	 * @param mixed (object|array) $data      incoming data for the parser.  The data could be either an object or
231
+	 *                             array because there are some shortcodes that might be replaced by prepared data that
232
+	 *                             has multiple items in a list (i.e. list of attendees in an event and we're showing
233
+	 *                             fname/lname for each attendee).  In this case data will be in an array.  Otherwise
234
+	 *                             the data shoudl be in a properly formatted object.  The
235
+	 *                             EEH_Parse_Shortcodes.helper.php describes the data object we're expecting.
236
+	 * @return string parsed shortcode
237
+	 */
238
+	abstract protected function _parser($shortcode);
239
+
240
+
241
+	/**
242
+	 * This just validates incoming data for list type shortcode parsers (and they call this method) to make sure it
243
+	 * meets their requirements
244
+	 *
245
+	 * @return mixed (void|exception) If validation fails we'll throw an exception.
246
+	 */
247
+	protected function _validate_list_requirements()
248
+	{
249
+
250
+		// first test to make sure we've got an array!
251
+		if (! is_array($this->_data)) {
252
+			throw new EE_Error(
253
+				sprintf(
254
+					esc_html__(
255
+						'Expecting an array for the data sent to %s. Instead it was %s',
256
+						'event_espresso'
257
+					),
258
+					get_class($this),
259
+					gettype($this->_data)
260
+				)
261
+			);
262
+		}
263
+
264
+		// next test to make sure we've got the required template in the index!
265
+		if (! isset($this->_data['template'])) {
266
+			throw new EE_Error(
267
+				sprintf(
268
+					esc_html__(
269
+						'The incoming data does not have the required template index in its array',
270
+						'event_espresso'
271
+					)
272
+				)
273
+			);
274
+		}
275
+
276
+		// next test to make sure we've got got a data index in the incoming data array
277
+		if (! isset($this->_data['data'])) {
278
+			throw new EE_Error(
279
+				esc_html__(
280
+					'The incoming data does not have the required data index in its array',
281
+					'event_espresso'
282
+				)
283
+			);
284
+		}
285
+
286
+		// all is well let's make sure _extra_data always has the values needed.
287
+		// let's make sure that extra_data includes all templates (for later parsing if necessary)
288
+		if (empty($this->_extra_data) || (empty($this->_extra_data['data']) && empty($this->_extra_data['template']))) {
289
+			$this->_extra_data['data'] = $this->_data['data'];
290
+			$this->_extra_data['template'] = $this->_data['template'];
291
+		}
292
+	}
293
+
294
+
295
+	/**
296
+	 * This returns any attributes that may be existing on an EE_Shortcode
297
+	 *
298
+	 * @since 4.5.0
299
+	 * @param string $shortcode incoming shortcode
300
+	 * @return array An array with the attributes
301
+	 */
302
+	protected function _get_shortcode_attrs($shortcode)
303
+	{
304
+		// make sure the required wp helper function is present
305
+		// require the shortcode file if necessary
306
+		if (! function_exists('shortcode_parse_atts')) {
307
+			require_once(ABSPATH . WPINC . '/shortcodes.php');
308
+		}
309
+
310
+		// let's get any attributes that may be present and set the defaults.
311
+		$shortcode_to_parse = str_replace('[', '', str_replace(']', '', $shortcode));
312
+		return shortcode_parse_atts($shortcode_to_parse);
313
+	}
314
+
315
+
316
+	/**
317
+	 * Conditional blocks are shortcode patterns with an opening conditional tag `[IF_*]` and a corresponding
318
+	 * closing tag (eg `[/IF_*]`).  The content within the tags will be displayed/hidden depending on whatever
319
+	 * conditions existed in the opening tag.  This method handles parsing the actual template to show/hide this
320
+	 * conditional content.
321
+	 *
322
+	 * @since 4.9.32
323
+	 *
324
+	 * @param string $shortcode This should be original shortcode as used in the template and passed to the parser.
325
+	 * @param bool   $show      true means the opening and closing tags are removed and the content is left showing,
326
+	 *                          false means the opening and closing tags and the contained content are removed.
327
+	 * @return string     The template for the shortcode is returned.
328
+	 */
329
+	protected function _mutate_conditional_block_in_template($shortcode, $show = true)
330
+	{
331
+		// first let's get all the matches in the template for this particular shortcode.
332
+		preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches);
333
+
334
+		if ($matches && is_array($matches[0]) && ! empty($matches[0])) {
335
+			// we need to hide all instances of the matches
336
+			foreach ($matches[0] as $index => $content_to_show_or_hide) {
337
+				$content_to_show_or_hide = preg_quote($content_to_show_or_hide);
338
+				$replacement = $show ? $matches[4][ $index ] : '';
339
+				$this->_data['template'] = preg_replace(
340
+					'~' . $content_to_show_or_hide . '~',
341
+					$replacement,
342
+					$this->_data['template']
343
+				);
344
+			}
345
+		}
346
+		// return $template
347
+		return $this->_data['template'];
348
+	}
349
+
350
+
351
+	/**
352
+	 * This returns the regex pattern to use for conditional shortcodes parsing.
353
+	 *
354
+	 * Note: regex comes in part from the WP `get_shortcode_regex` expression in \wp-includes\shortcodes.php
355
+	 *
356
+	 * @param $shortcode
357
+	 * @since 4.9.32
358
+	 * @return string
359
+	 */
360
+	private function _get_conditional_block_regex($shortcode)
361
+	{
362
+		// get just the shortcode tag for the match
363
+		preg_match('@\[([^<>&/\[\]\x00-\x20=]++)@', $shortcode, $shortcode_tag_matches);
364
+		if (empty($shortcode_tag_matches[1])) {
365
+			return $this->_data['template'];
366
+		}
367
+
368
+		$shortcode_tag = $shortcode_tag_matches[1];
369
+		// get attributes_part_of_tag
370
+		$attributes_part = preg_quote(str_replace(array($shortcode_tag, '[', ']'), '', $shortcode));
371
+		// escape
372
+		$shortcode_tag = preg_quote($shortcode_tag);
373
+
374
+		return
375
+			'\['                                  // Opening Bracket
376
+			. "($shortcode_tag)$attributes_part"    // 1: Shortcode Name
377
+			. '(?![\w-])'                           // Not followed by word character or hyphen
378
+			. '('                                   // 2: Unroll the loop: Inside the opening shortcode tag
379
+			. '[^\]\/]*'                          // Not a closing bracket or forward slash
380
+			. '(?:'
381
+			. '\/(?!\])'                      // A forward slash not followed by a closing bracket
382
+			. '[^\]\/]*'                      // Not a closing bracket or forward slash.
383
+			. ')*?'
384
+			. ')'
385
+			. '(?:'
386
+			. '(\/)'                              // 3. Self closing tag ...
387
+			. '\]'                                // ... and closing bracket
388
+			. '|'
389
+			. '\]'                                // Closing bracket
390
+			. '(?:'
391
+			. '('                             // 4: Unroll the loop: Optionally, anything between the opening and closing brackets
392
+			. '[^\[]*+'                   // Not an opening bracket
393
+			. '(?:'
394
+			. '\[(?!\/\1\])'          // An opening bracket not followed by the closing shortcode tag.
395
+			. '[^\[]*+'               // Not an opening bracket
396
+			. ')*+'
397
+			. ')'
398
+			. '\[\/\1\]'                      // Closing shortcode tag
399
+			. ')?'
400
+			. ')';
401
+	}
402
+
403
+
404
+	/**
405
+	 * This sets the properties related to the messages system
406
+	 *
407
+	 * @since 4.5.0
408
+	 * @return void
409
+	 */
410
+	protected function _set_messages_properties()
411
+	{
412
+		// should be in _extra_data
413
+		if (isset($this->_extra_data['messenger'])) {
414
+			$this->_messenger = $this->_extra_data['messenger'];
415
+			$this->_message_type = $this->_extra_data['message_type'];
416
+			$this->_context = $this->_extra_data['message'] instanceof EE_Message
417
+				? $this->_extra_data['message']->context() : '';
418
+			$this->_GRP_ID = $this->_extra_data['message'] instanceof EE_Message
419
+				? $this->_extra_data['message']->GRP_ID() : 0;
420
+			$this->_message = $this->_extra_data['message'] instanceof EE_Message ? $this->_extra_data['message']
421
+				: null;
422
+		}
423
+	}
424
+
425
+
426
+	/**
427
+	 * This returns whatever the set message type object is that was set on this shortcode parser.
428
+	 *
429
+	 * @since 4.5.0
430
+	 * @return EE_message_type
431
+	 */
432
+	public function get_set_message_type()
433
+	{
434
+		return $this->_message_type;
435
+	}
436
+
437
+
438
+	/**
439
+	 * This returns whatever the set messenger object is that was set on this shortcode parser
440
+	 *
441
+	 * @since 4.5.0
442
+	 * @return EE_messenger
443
+	 */
444
+	public function get_set_messenger()
445
+	{
446
+		return $this->_messenger;
447
+	}
448
+
449
+
450
+	/**
451
+	 * This returns whatever the set context string is on this shortcode parser.
452
+	 *
453
+	 * @since 4.5.0
454
+	 * @return string
455
+	 */
456
+	public function get_set_context()
457
+	{
458
+		return $this->_context;
459
+	}
460
+
461
+
462
+	/**
463
+	 * This returns whatever the set EE_Message object is on this shortcode.
464
+	 *
465
+	 * @since 4.9.0
466
+	 * @return EE_Message
467
+	 */
468
+	public function get_set_message()
469
+	{
470
+		return $this->_message;
471
+	}
472 472
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
 
147 147
     public function get_shortcode_helper()
148 148
     {
149
-        if (! $this->_shortcode_helper instanceof EEH_Parse_Shortcodes) {
149
+        if ( ! $this->_shortcode_helper instanceof EEH_Parse_Shortcodes) {
150 150
             $this->_set_shortcode_helper();
151 151
         }
152 152
         return $this->_shortcode_helper;
@@ -170,17 +170,17 @@  discard block
 block discarded – undo
170 170
 
171 171
         // we need to setup any dynamic shortcodes so that they work with the array_key_exists
172 172
         preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
173
-        $sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
173
+        $sc_to_verify = ! empty($matches[0]) ? $matches[0][0].']' : $shortcode;
174 174
 
175 175
         // first we want to make sure this is a valid shortcode
176
-        if (! array_key_exists($sc_to_verify, $this->_shortcodes)) {
176
+        if ( ! array_key_exists($sc_to_verify, $this->_shortcodes)) {
177 177
             return false;
178 178
         } //get out, this parser doesn't handle the incoming shortcode.
179 179
         $this->_data = $data;
180 180
         $this->_extra_data = $extra_data;
181 181
         $this->_set_messages_properties();
182 182
         $parsed = apply_filters(
183
-            'FHEE__' . get_class($this) . '__parser_after',
183
+            'FHEE__'.get_class($this).'__parser_after',
184 184
             $this->_parser($shortcode),
185 185
             $shortcode,
186 186
             $data,
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
      */
202 202
     public function get_shortcodes()
203 203
     {
204
-        $this->_shortcodes = apply_filters('FHEE__' . get_class($this) . '__shortcodes', $this->_shortcodes, $this);
204
+        $this->_shortcodes = apply_filters('FHEE__'.get_class($this).'__shortcodes', $this->_shortcodes, $this);
205 205
 
206 206
         // note the below filter applies to ALL shortcode parsers... be careful!
207 207
         $this->_shortcodes = apply_filters('FHEE__EE_Shortcodes__shortcodes', $this->_shortcodes, $this);
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
     {
249 249
 
250 250
         // first test to make sure we've got an array!
251
-        if (! is_array($this->_data)) {
251
+        if ( ! is_array($this->_data)) {
252 252
             throw new EE_Error(
253 253
                 sprintf(
254 254
                     esc_html__(
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
         }
263 263
 
264 264
         // next test to make sure we've got the required template in the index!
265
-        if (! isset($this->_data['template'])) {
265
+        if ( ! isset($this->_data['template'])) {
266 266
             throw new EE_Error(
267 267
                 sprintf(
268 268
                     esc_html__(
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
         }
275 275
 
276 276
         // next test to make sure we've got got a data index in the incoming data array
277
-        if (! isset($this->_data['data'])) {
277
+        if ( ! isset($this->_data['data'])) {
278 278
             throw new EE_Error(
279 279
                 esc_html__(
280 280
                     'The incoming data does not have the required data index in its array',
@@ -303,8 +303,8 @@  discard block
 block discarded – undo
303 303
     {
304 304
         // make sure the required wp helper function is present
305 305
         // require the shortcode file if necessary
306
-        if (! function_exists('shortcode_parse_atts')) {
307
-            require_once(ABSPATH . WPINC . '/shortcodes.php');
306
+        if ( ! function_exists('shortcode_parse_atts')) {
307
+            require_once(ABSPATH.WPINC.'/shortcodes.php');
308 308
         }
309 309
 
310 310
         // let's get any attributes that may be present and set the defaults.
@@ -329,15 +329,15 @@  discard block
 block discarded – undo
329 329
     protected function _mutate_conditional_block_in_template($shortcode, $show = true)
330 330
     {
331 331
         // first let's get all the matches in the template for this particular shortcode.
332
-        preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches);
332
+        preg_match_all('~'.$this->_get_conditional_block_regex($shortcode).'~', $this->_data['template'], $matches);
333 333
 
334 334
         if ($matches && is_array($matches[0]) && ! empty($matches[0])) {
335 335
             // we need to hide all instances of the matches
336 336
             foreach ($matches[0] as $index => $content_to_show_or_hide) {
337 337
                 $content_to_show_or_hide = preg_quote($content_to_show_or_hide);
338
-                $replacement = $show ? $matches[4][ $index ] : '';
338
+                $replacement = $show ? $matches[4][$index] : '';
339 339
                 $this->_data['template'] = preg_replace(
340
-                    '~' . $content_to_show_or_hide . '~',
340
+                    '~'.$content_to_show_or_hide.'~',
341 341
                     $replacement,
342 342
                     $this->_data['template']
343 343
                 );
Please login to merge, or discard this patch.
core/libraries/iframe_display/iframe_wrapper.template.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
                 <?php echo $eei18n; ?>
33 33
             </script>
34 34
         <?php foreach ($header_js as $key => $url) :?>
35
-            <?php $header_attributes = isset($header_js_attributes[ $key ]) ? $header_js_attributes[ $key ] : ''; ?>
35
+            <?php $header_attributes = isset($header_js_attributes[$key]) ? $header_js_attributes[$key] : ''; ?>
36 36
         <script type="text/javascript" src="<?php echo esc_url_raw($url); ?>"<?php echo $header_attributes; ?>></script>
37 37
         <?php endforeach; ?>
38 38
     <?php endif; ?>
@@ -43,7 +43,7 @@  discard block
 block discarded – undo
43 43
     <?php echo $content; // already escaped ?>
44 44
 </div>
45 45
 <?php foreach ($footer_js as $key => $url) : ?>
46
-    <?php $footer_attributes = isset($footer_js_attributes[ $key ]) ? $footer_js_attributes[ $key ] : ''; ?>
46
+    <?php $footer_attributes = isset($footer_js_attributes[$key]) ? $footer_js_attributes[$key] : ''; ?>
47 47
     <script type="text/javascript" src="<?php echo esc_url_raw($url); ?>"<?php echo $footer_attributes; ?>></script>
48 48
 <?php endforeach; ?>
49 49
 <?php if ($enqueue_wp_assets) : ?>
Please login to merge, or discard this patch.
Braces   +5 added lines, -2 removed lines patch added patch discarded remove patch
@@ -24,9 +24,12 @@
 block discarded – undo
24 24
     <title><?php echo wp_strip_all_tags($title); ?></title>
25 25
     <?php if ($enqueue_wp_assets) : ?>
26 26
         <?php wp_head(); ?>
27
-    <?php else : ?>
27
+    <?php else {
28
+	: ?>
28 29
         <?php foreach ($css as $url) :?>
29
-    <link rel="stylesheet" type="text/css" href="<?php echo esc_url_raw($url); ?>">
30
+    <link rel="stylesheet" type="text/css" href="<?php echo esc_url_raw($url);
31
+}
32
+?>">
30 33
         <?php endforeach; ?>
31 34
             <script type="text/javascript">
32 35
                 <?php echo $eei18n; ?>
Please login to merge, or discard this patch.
core/libraries/iframe_display/IframeEmbedButton.php 2 patches
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -13,274 +13,274 @@
 block discarded – undo
13 13
 {
14 14
 
15 15
 
16
-    /**
17
-     * @var string $iframe_name
18
-     */
19
-    private $iframe_name;
16
+	/**
17
+	 * @var string $iframe_name
18
+	 */
19
+	private $iframe_name;
20 20
 
21
-    /**
22
-     * @var string $route_name
23
-     */
24
-    private $route_name;
21
+	/**
22
+	 * @var string $route_name
23
+	 */
24
+	private $route_name;
25 25
 
26
-    /**
27
-     * @var string $slug
28
-     */
29
-    private $slug;
26
+	/**
27
+	 * @var string $slug
28
+	 */
29
+	private $slug;
30 30
 
31
-    /**
32
-     * @var boolean $append_filterable_content
33
-     */
34
-    private $append_filterable_content;
31
+	/**
32
+	 * @var boolean $append_filterable_content
33
+	 */
34
+	private $append_filterable_content;
35 35
 
36 36
 
37
-    /**
38
-     * IframeEmbedButton constructor.
39
-     *
40
-     * @param string $iframe_name i18n name for the iframe. This will be used in HTML
41
-     * @param string $route_name  the name of the registered route
42
-     * @param string $slug        URL slug used for the thing the iframe button is being embedded in.
43
-     *                            will most likely be "event" since that's the only usage atm
44
-     */
45
-    public function __construct($iframe_name, $route_name, $slug = 'event')
46
-    {
47
-        $this->iframe_name = $iframe_name;
48
-        $this->route_name = $route_name;
49
-        $this->slug = $slug;
50
-    }
37
+	/**
38
+	 * IframeEmbedButton constructor.
39
+	 *
40
+	 * @param string $iframe_name i18n name for the iframe. This will be used in HTML
41
+	 * @param string $route_name  the name of the registered route
42
+	 * @param string $slug        URL slug used for the thing the iframe button is being embedded in.
43
+	 *                            will most likely be "event" since that's the only usage atm
44
+	 */
45
+	public function __construct($iframe_name, $route_name, $slug = 'event')
46
+	{
47
+		$this->iframe_name = $iframe_name;
48
+		$this->route_name = $route_name;
49
+		$this->slug = $slug;
50
+	}
51 51
 
52 52
 
53
-    /**
54
-     * Adds an iframe embed code button to the Event editor.
55
-     */
56
-    public function addEventEditorIframeEmbedButtonFilter()
57
-    {
58
-        // add button for iframe code to event editor.
59
-        add_filter(
60
-            'get_sample_permalink_html',
61
-            array($this, 'appendIframeEmbedButtonToSamplePermalinkHtml'),
62
-            10,
63
-            2
64
-        );
65
-        add_action(
66
-            'admin_enqueue_scripts',
67
-            array($this, 'embedButtonAssets'),
68
-            10
69
-        );
70
-    }
53
+	/**
54
+	 * Adds an iframe embed code button to the Event editor.
55
+	 */
56
+	public function addEventEditorIframeEmbedButtonFilter()
57
+	{
58
+		// add button for iframe code to event editor.
59
+		add_filter(
60
+			'get_sample_permalink_html',
61
+			array($this, 'appendIframeEmbedButtonToSamplePermalinkHtml'),
62
+			10,
63
+			2
64
+		);
65
+		add_action(
66
+			'admin_enqueue_scripts',
67
+			array($this, 'embedButtonAssets'),
68
+			10
69
+		);
70
+	}
71 71
 
72 72
 
73
-    /**
74
-     * @param $permalink_string
75
-     * @param $id
76
-     * @return string
77
-     */
78
-    public function appendIframeEmbedButtonToSamplePermalinkHtml($permalink_string, $id)
79
-    {
80
-        return $this->eventEditorIframeEmbedButton(
81
-            $permalink_string,
82
-            $id
83
-        );
84
-    }
73
+	/**
74
+	 * @param $permalink_string
75
+	 * @param $id
76
+	 * @return string
77
+	 */
78
+	public function appendIframeEmbedButtonToSamplePermalinkHtml($permalink_string, $id)
79
+	{
80
+		return $this->eventEditorIframeEmbedButton(
81
+			$permalink_string,
82
+			$id
83
+		);
84
+	}
85 85
 
86 86
 
87
-    /**
88
-     * iframe embed code button to the Event editor.
89
-     *
90
-     * @param string $permalink_string
91
-     * @param int    $id
92
-     * @return string
93
-     */
94
-    public function eventEditorIframeEmbedButton(
95
-        $permalink_string,
96
-        $id
97
-    ) {
98
-        // make sure this is ONLY when editing and the event id has been set.
99
-        if (! empty($id)) {
100
-            $post = get_post($id);
101
-            // if NOT event then let's get out.
102
-            if ($post->post_type !== 'espresso_events') {
103
-                return $permalink_string;
104
-            }
105
-            $permalink_string .= $this->embedButtonHtml(
106
-                array($this->slug => $id),
107
-                'button-small'
108
-            );
109
-        }
110
-        return $permalink_string;
111
-    }
87
+	/**
88
+	 * iframe embed code button to the Event editor.
89
+	 *
90
+	 * @param string $permalink_string
91
+	 * @param int    $id
92
+	 * @return string
93
+	 */
94
+	public function eventEditorIframeEmbedButton(
95
+		$permalink_string,
96
+		$id
97
+	) {
98
+		// make sure this is ONLY when editing and the event id has been set.
99
+		if (! empty($id)) {
100
+			$post = get_post($id);
101
+			// if NOT event then let's get out.
102
+			if ($post->post_type !== 'espresso_events') {
103
+				return $permalink_string;
104
+			}
105
+			$permalink_string .= $this->embedButtonHtml(
106
+				array($this->slug => $id),
107
+				'button-small'
108
+			);
109
+		}
110
+		return $permalink_string;
111
+	}
112 112
 
113 113
 
114
-    /**
115
-     * Adds an iframe embed code button via a WP do_action() as determined by the first parameter
116
-     *
117
-     * @param string $action name of the WP do_action() to hook into
118
-     */
119
-    public function addActionIframeEmbedButton($action)
120
-    {
121
-        // add button for iframe code to event editor.
122
-        add_action(
123
-            $action,
124
-            array($this, 'addActionIframeEmbedButtonCallback'),
125
-            10,
126
-            2
127
-        );
128
-    }
114
+	/**
115
+	 * Adds an iframe embed code button via a WP do_action() as determined by the first parameter
116
+	 *
117
+	 * @param string $action name of the WP do_action() to hook into
118
+	 */
119
+	public function addActionIframeEmbedButton($action)
120
+	{
121
+		// add button for iframe code to event editor.
122
+		add_action(
123
+			$action,
124
+			array($this, 'addActionIframeEmbedButtonCallback'),
125
+			10,
126
+			2
127
+		);
128
+	}
129 129
 
130 130
 
131
-    /**
132
-     * @return void
133
-     */
134
-    public function addActionIframeEmbedButtonCallback()
135
-    {
136
-        echo $this->embedButtonHtml(); // already escaped
137
-    }
131
+	/**
132
+	 * @return void
133
+	 */
134
+	public function addActionIframeEmbedButtonCallback()
135
+	{
136
+		echo $this->embedButtonHtml(); // already escaped
137
+	}
138 138
 
139 139
 
140
-    /**
141
-     * Adds an iframe embed code button via a WP apply_filters() as determined by the first parameter
142
-     *
143
-     * @param string $filter     name of the WP apply_filters() to hook into
144
-     * @param bool   $append     if true, will add iframe embed button to end of content,
145
-     *                           else if false, will add to the beginning of the content
146
-     */
147
-    public function addFilterIframeEmbedButton($filter, $append = true)
148
-    {
149
-        $this->append_filterable_content = $append;
150
-        // add button for iframe code to event editor.
151
-        add_filter(
152
-            $filter,
153
-            array($this, 'addFilterIframeEmbedButtonCallback'),
154
-            10
155
-        );
156
-    }
140
+	/**
141
+	 * Adds an iframe embed code button via a WP apply_filters() as determined by the first parameter
142
+	 *
143
+	 * @param string $filter     name of the WP apply_filters() to hook into
144
+	 * @param bool   $append     if true, will add iframe embed button to end of content,
145
+	 *                           else if false, will add to the beginning of the content
146
+	 */
147
+	public function addFilterIframeEmbedButton($filter, $append = true)
148
+	{
149
+		$this->append_filterable_content = $append;
150
+		// add button for iframe code to event editor.
151
+		add_filter(
152
+			$filter,
153
+			array($this, 'addFilterIframeEmbedButtonCallback'),
154
+			10
155
+		);
156
+	}
157 157
 
158 158
 
159
-    /**
160
-     * @param array|string $filterable_content
161
-     * @return array|string
162
-     */
163
-    public function addFilterIframeEmbedButtonCallback($filterable_content)
164
-    {
165
-        $embedButtonHtml = $this->embedButtonHtml();
166
-        if (is_array($filterable_content)) {
167
-            $filterable_content = $this->append_filterable_content
168
-                ? $filterable_content + array($this->route_name => $embedButtonHtml)
169
-                : array($this->route_name => $embedButtonHtml) + $filterable_content;
170
-        } else {
171
-            $filterable_content = $this->append_filterable_content
172
-                ? $filterable_content . $embedButtonHtml
173
-                : $embedButtonHtml . $filterable_content;
174
-        }
175
-        return $filterable_content;
176
-    }
159
+	/**
160
+	 * @param array|string $filterable_content
161
+	 * @return array|string
162
+	 */
163
+	public function addFilterIframeEmbedButtonCallback($filterable_content)
164
+	{
165
+		$embedButtonHtml = $this->embedButtonHtml();
166
+		if (is_array($filterable_content)) {
167
+			$filterable_content = $this->append_filterable_content
168
+				? $filterable_content + array($this->route_name => $embedButtonHtml)
169
+				: array($this->route_name => $embedButtonHtml) + $filterable_content;
170
+		} else {
171
+			$filterable_content = $this->append_filterable_content
172
+				? $filterable_content . $embedButtonHtml
173
+				: $embedButtonHtml . $filterable_content;
174
+		}
175
+		return $filterable_content;
176
+	}
177 177
 
178 178
 
179
-    /**
180
-     * iframe_embed_html
181
-     *
182
-     * @param array  $query_args
183
-     * @param string $button_class
184
-     * @return string
185
-     */
186
-    public function embedButtonHtml($query_args = array(), $button_class = '')
187
-    {
188
-        // incoming args will replace the defaults listed here in the second array (union preserves first array)
189
-        $query_args = (array) $query_args + array($this->route_name => 'iframe');
190
-        $query_args = (array) apply_filters(
191
-            'FHEE__EventEspresso_core_libraries_iframe_display_IframeEmbedButton__embedButtonHtml__query_args',
192
-            $query_args
193
-        );
194
-        // add this route to our localized vars
195
-        $iframe_module_routes = isset(\EE_Registry::$i18n_js_strings['iframe_module_routes'])
196
-            ? \EE_Registry::$i18n_js_strings['iframe_module_routes']
197
-            : array();
198
-        $iframe_module_routes[ $this->route_name ] = $this->route_name;
199
-        \EE_Registry::$i18n_js_strings['iframe_module_routes'] = $iframe_module_routes;
200
-        $iframe_embed_html = \EEH_HTML::link(
201
-            '#',
202
-            sprintf(esc_html__('Embed %1$s', 'event_espresso'), $this->iframe_name),
203
-            sprintf(
204
-                esc_html__(
205
-                    'click here to generate code for embedding %1$s iframe into another site.',
206
-                    'event_espresso'
207
-                ),
208
-                \EEH_Inflector::add_indefinite_article($this->iframe_name)
209
-            ),
210
-            esc_attr($this->route_name) . "-iframe-embed-trigger-js",
211
-            'iframe-embed-trigger-js button ' . esc_attr($button_class),
212
-            '',
213
-            ' data-iframe_embed_button="#' . esc_attr($this->route_name) . '-iframe-js" tabindex="-1"'
214
-        );
215
-        $iframe_embed_html .= \EEH_HTML::div(
216
-            '',
217
-            esc_attr($this->route_name) . "-iframe-js",
218
-            'iframe-embed-wrapper-js',
219
-            'display:none;'
220
-        );
221
-        $iframe_embed_html .= esc_html(
222
-            \EEH_HTML::div(
223
-                '<iframe src="' . esc_url_raw(add_query_arg($query_args, site_url())) . '" width="100%" height="100%"></iframe>',
224
-                '',
225
-                '',
226
-                'width:100%; height: 500px;'
227
-            )
228
-        );
229
-        $iframe_embed_html .= \EEH_HTML::divx();
230
-        return $iframe_embed_html;
231
-    }
179
+	/**
180
+	 * iframe_embed_html
181
+	 *
182
+	 * @param array  $query_args
183
+	 * @param string $button_class
184
+	 * @return string
185
+	 */
186
+	public function embedButtonHtml($query_args = array(), $button_class = '')
187
+	{
188
+		// incoming args will replace the defaults listed here in the second array (union preserves first array)
189
+		$query_args = (array) $query_args + array($this->route_name => 'iframe');
190
+		$query_args = (array) apply_filters(
191
+			'FHEE__EventEspresso_core_libraries_iframe_display_IframeEmbedButton__embedButtonHtml__query_args',
192
+			$query_args
193
+		);
194
+		// add this route to our localized vars
195
+		$iframe_module_routes = isset(\EE_Registry::$i18n_js_strings['iframe_module_routes'])
196
+			? \EE_Registry::$i18n_js_strings['iframe_module_routes']
197
+			: array();
198
+		$iframe_module_routes[ $this->route_name ] = $this->route_name;
199
+		\EE_Registry::$i18n_js_strings['iframe_module_routes'] = $iframe_module_routes;
200
+		$iframe_embed_html = \EEH_HTML::link(
201
+			'#',
202
+			sprintf(esc_html__('Embed %1$s', 'event_espresso'), $this->iframe_name),
203
+			sprintf(
204
+				esc_html__(
205
+					'click here to generate code for embedding %1$s iframe into another site.',
206
+					'event_espresso'
207
+				),
208
+				\EEH_Inflector::add_indefinite_article($this->iframe_name)
209
+			),
210
+			esc_attr($this->route_name) . "-iframe-embed-trigger-js",
211
+			'iframe-embed-trigger-js button ' . esc_attr($button_class),
212
+			'',
213
+			' data-iframe_embed_button="#' . esc_attr($this->route_name) . '-iframe-js" tabindex="-1"'
214
+		);
215
+		$iframe_embed_html .= \EEH_HTML::div(
216
+			'',
217
+			esc_attr($this->route_name) . "-iframe-js",
218
+			'iframe-embed-wrapper-js',
219
+			'display:none;'
220
+		);
221
+		$iframe_embed_html .= esc_html(
222
+			\EEH_HTML::div(
223
+				'<iframe src="' . esc_url_raw(add_query_arg($query_args, site_url())) . '" width="100%" height="100%"></iframe>',
224
+				'',
225
+				'',
226
+				'width:100%; height: 500px;'
227
+			)
228
+		);
229
+		$iframe_embed_html .= \EEH_HTML::divx();
230
+		return $iframe_embed_html;
231
+	}
232 232
 
233 233
 
234
-    /**
235
-     * enqueue iframe button js
236
-     */
237
-    public function embedButtonAssets()
238
-    {
239
-        \EE_Registry::$i18n_js_strings['iframe_embed_title'] = esc_html__(
240
-            'copy and paste the following into any other site\'s content to display this event:',
241
-            'event_espresso'
242
-        );
243
-        \EE_Registry::$i18n_js_strings['iframe_embed_close_msg'] = esc_html__(
244
-            'click anywhere outside of this window to close it.',
245
-            'event_espresso'
246
-        );
247
-        wp_register_script(
248
-            'iframe_embed_button',
249
-            plugin_dir_url(__FILE__) . 'iframe-embed-button.js',
250
-            array('ee-dialog'),
251
-            EVENT_ESPRESSO_VERSION,
252
-            true
253
-        );
254
-        wp_enqueue_script('iframe_embed_button');
255
-    }
234
+	/**
235
+	 * enqueue iframe button js
236
+	 */
237
+	public function embedButtonAssets()
238
+	{
239
+		\EE_Registry::$i18n_js_strings['iframe_embed_title'] = esc_html__(
240
+			'copy and paste the following into any other site\'s content to display this event:',
241
+			'event_espresso'
242
+		);
243
+		\EE_Registry::$i18n_js_strings['iframe_embed_close_msg'] = esc_html__(
244
+			'click anywhere outside of this window to close it.',
245
+			'event_espresso'
246
+		);
247
+		wp_register_script(
248
+			'iframe_embed_button',
249
+			plugin_dir_url(__FILE__) . 'iframe-embed-button.js',
250
+			array('ee-dialog'),
251
+			EVENT_ESPRESSO_VERSION,
252
+			true
253
+		);
254
+		wp_enqueue_script('iframe_embed_button');
255
+	}
256 256
 
257 257
 
258
-    /**
259
-     * generates embed button sections for admin pages
260
-     *
261
-     * @param array $embed_buttons
262
-     * @return string
263
-     */
264
-    public function addIframeEmbedButtonsSection(array $embed_buttons)
265
-    {
266
-        $embed_buttons = (array) apply_filters(
267
-            'FHEE__EventEspresso_core_libraries_iframe_display_IframeEmbedButton__addIframeEmbedButtonsSection__embed_buttons',
268
-            $embed_buttons
269
-        );
270
-        if (empty($embed_buttons)) {
271
-            return '';
272
-        }
273
-        // add button for iframe code to event editor.
274
-        $html = \EEH_HTML::br(2);
275
-        $html .= \EEH_HTML::h3(esc_html__('iFrame Embed Code', 'event_espresso'));
276
-        $html .= \EEH_HTML::p(
277
-            esc_html__(
278
-                'Click the following button(s) to generate iframe HTML that will allow you to embed your event content within the content of other websites.',
279
-                'event_espresso'
280
-            )
281
-        );
282
-        $html .= ' &nbsp; ' . implode(' &nbsp; ', $embed_buttons) . ' ';
283
-        $html .= \EEH_HTML::br(2);
284
-        return $html;
285
-    }
258
+	/**
259
+	 * generates embed button sections for admin pages
260
+	 *
261
+	 * @param array $embed_buttons
262
+	 * @return string
263
+	 */
264
+	public function addIframeEmbedButtonsSection(array $embed_buttons)
265
+	{
266
+		$embed_buttons = (array) apply_filters(
267
+			'FHEE__EventEspresso_core_libraries_iframe_display_IframeEmbedButton__addIframeEmbedButtonsSection__embed_buttons',
268
+			$embed_buttons
269
+		);
270
+		if (empty($embed_buttons)) {
271
+			return '';
272
+		}
273
+		// add button for iframe code to event editor.
274
+		$html = \EEH_HTML::br(2);
275
+		$html .= \EEH_HTML::h3(esc_html__('iFrame Embed Code', 'event_espresso'));
276
+		$html .= \EEH_HTML::p(
277
+			esc_html__(
278
+				'Click the following button(s) to generate iframe HTML that will allow you to embed your event content within the content of other websites.',
279
+				'event_espresso'
280
+			)
281
+		);
282
+		$html .= ' &nbsp; ' . implode(' &nbsp; ', $embed_buttons) . ' ';
283
+		$html .= \EEH_HTML::br(2);
284
+		return $html;
285
+	}
286 286
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
         $id
97 97
     ) {
98 98
         // make sure this is ONLY when editing and the event id has been set.
99
-        if (! empty($id)) {
99
+        if ( ! empty($id)) {
100 100
             $post = get_post($id);
101 101
             // if NOT event then let's get out.
102 102
             if ($post->post_type !== 'espresso_events') {
@@ -169,8 +169,8 @@  discard block
 block discarded – undo
169 169
                 : array($this->route_name => $embedButtonHtml) + $filterable_content;
170 170
         } else {
171 171
             $filterable_content = $this->append_filterable_content
172
-                ? $filterable_content . $embedButtonHtml
173
-                : $embedButtonHtml . $filterable_content;
172
+                ? $filterable_content.$embedButtonHtml
173
+                : $embedButtonHtml.$filterable_content;
174 174
         }
175 175
         return $filterable_content;
176 176
     }
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
         $iframe_module_routes = isset(\EE_Registry::$i18n_js_strings['iframe_module_routes'])
196 196
             ? \EE_Registry::$i18n_js_strings['iframe_module_routes']
197 197
             : array();
198
-        $iframe_module_routes[ $this->route_name ] = $this->route_name;
198
+        $iframe_module_routes[$this->route_name] = $this->route_name;
199 199
         \EE_Registry::$i18n_js_strings['iframe_module_routes'] = $iframe_module_routes;
200 200
         $iframe_embed_html = \EEH_HTML::link(
201 201
             '#',
@@ -207,20 +207,20 @@  discard block
 block discarded – undo
207 207
                 ),
208 208
                 \EEH_Inflector::add_indefinite_article($this->iframe_name)
209 209
             ),
210
-            esc_attr($this->route_name) . "-iframe-embed-trigger-js",
211
-            'iframe-embed-trigger-js button ' . esc_attr($button_class),
210
+            esc_attr($this->route_name)."-iframe-embed-trigger-js",
211
+            'iframe-embed-trigger-js button '.esc_attr($button_class),
212 212
             '',
213
-            ' data-iframe_embed_button="#' . esc_attr($this->route_name) . '-iframe-js" tabindex="-1"'
213
+            ' data-iframe_embed_button="#'.esc_attr($this->route_name).'-iframe-js" tabindex="-1"'
214 214
         );
215 215
         $iframe_embed_html .= \EEH_HTML::div(
216 216
             '',
217
-            esc_attr($this->route_name) . "-iframe-js",
217
+            esc_attr($this->route_name)."-iframe-js",
218 218
             'iframe-embed-wrapper-js',
219 219
             'display:none;'
220 220
         );
221 221
         $iframe_embed_html .= esc_html(
222 222
             \EEH_HTML::div(
223
-                '<iframe src="' . esc_url_raw(add_query_arg($query_args, site_url())) . '" width="100%" height="100%"></iframe>',
223
+                '<iframe src="'.esc_url_raw(add_query_arg($query_args, site_url())).'" width="100%" height="100%"></iframe>',
224 224
                 '',
225 225
                 '',
226 226
                 'width:100%; height: 500px;'
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
         );
247 247
         wp_register_script(
248 248
             'iframe_embed_button',
249
-            plugin_dir_url(__FILE__) . 'iframe-embed-button.js',
249
+            plugin_dir_url(__FILE__).'iframe-embed-button.js',
250 250
             array('ee-dialog'),
251 251
             EVENT_ESPRESSO_VERSION,
252 252
             true
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
                 'event_espresso'
280 280
             )
281 281
         );
282
-        $html .= ' &nbsp; ' . implode(' &nbsp; ', $embed_buttons) . ' ';
282
+        $html .= ' &nbsp; '.implode(' &nbsp; ', $embed_buttons).' ';
283 283
         $html .= \EEH_HTML::br(2);
284 284
         return $html;
285 285
     }
Please login to merge, or discard this patch.
libraries/payment_methods/templates/payment_details_content.template.php 2 patches
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 /**
7 7
  * payment_details_content
@@ -11,5 +11,5 @@  discard block
 block discarded – undo
11 11
  */
12 12
 $gateway_response = $payment->gateway_response();
13 13
 if (! empty($gateway_response)) {
14
-    echo '<span class="error payment-problem">' . esc_html($gateway_response) . '</span>';
14
+	echo '<span class="error payment-problem">' . esc_html($gateway_response) . '</span>';
15 15
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-if (! defined('EVENT_ESPRESSO_VERSION')) {
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
5 5
 }
6 6
 /**
@@ -10,6 +10,6 @@  discard block
 block discarded – undo
10 10
  * @var EE_Payment_Method $payment_method
11 11
  */
12 12
 $gateway_response = $payment->gateway_response();
13
-if (! empty($gateway_response)) {
14
-    echo '<span class="error payment-problem">' . esc_html($gateway_response) . '</span>';
13
+if ( ! empty($gateway_response)) {
14
+    echo '<span class="error payment-problem">'.esc_html($gateway_response).'</span>';
15 15
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_Type_Collection.lib.php 2 patches
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -14,170 +14,170 @@
 block discarded – undo
14 14
 class EE_Message_Type_Collection extends EE_Object_Collection
15 15
 {
16 16
 
17
-    /**
18
-     * EE_Message_Type_Collection constructor.
19
-     */
20
-    public function __construct()
21
-    {
22
-        $this->interface = 'EE_message_type';
23
-    }
24
-
25
-
26
-
27
-    /**
28
-     * add
29
-     *
30
-     * attaches an object to the Collection
31
-     * and sets any supplied data associated with the current iterator entry
32
-     * by calling EE_Object_Collection::set_info()
33
-     *
34
-     * @access public
35
-     * @param object $object
36
-     * @param mixed  $info
37
-     * @return bool
38
-     */
39
-    public function add($object, $info = null)
40
-    {
41
-        $info = empty($info) && $object instanceof $this->interface ? $object->name : $info;
42
-        return parent::add($object, $info);
43
-    }
44
-
45
-
46
-
47
-    /**
48
-     * set_info
49
-     *
50
-     * Sets the data associated with an object in the Collection
51
-     * if no $info is supplied, then the spl_object_hash() is used
52
-     *
53
-     * @access public
54
-     * @param object $object
55
-     * @param mixed  $info
56
-     * @return bool
57
-     */
58
-    public function set_info($object, $info = null)
59
-    {
60
-        $info = empty($info) && $object instanceof $this->interface ? $object->name : $info;
61
-        return parent::set_info($object, $info);
62
-    }
63
-
64
-
65
-
66
-    /**
67
-     * get_by_info
68
-     *
69
-     * finds and returns an object in the Collection based on the info that was set using addObject()
70
-     * PLZ NOTE: the pointer is reset to the beginning of the collection before returning
71
-     *
72
-     * @access public
73
-     * @param mixed
74
-     * @return null | object
75
-     */
76
-    public function get_by_info($info)
77
-    {
78
-        return parent::get_by_info(str_replace(' ', '_', strtolower($info)));
79
-    }
80
-
81
-
82
-
83
-    /**
84
-     * has
85
-     *
86
-     * returns TRUE or FALSE depending on whether the supplied object is within the Collection
87
-     *
88
-     * @access public
89
-     * @param object $object
90
-     * @return bool
91
-     */
92
-    public function has($object)
93
-    {
94
-        return parent::has($object);
95
-    }
96
-
97
-
98
-
99
-    /**
100
-     * has_by_name
101
-     *
102
-     * returns TRUE or FALSE depending on whether the supplied message_type classname is within the Collection
103
-     *
104
-     * @access public
105
-     * @param string $message_type_name
106
-     * @return bool
107
-     */
108
-    public function has_by_name($message_type_name)
109
-    {
110
-        return $this->get_by_info($message_type_name) instanceof $this->interface ? true : false;
111
-    }
112
-
113
-
114
-
115
-    /**
116
-     * remove
117
-     *
118
-     * detaches an object from the Collection
119
-     *
120
-     * @access public
121
-     * @param $object
122
-     * @return bool
123
-     */
124
-    public function remove($object)
125
-    {
126
-        return parent::remove($object);
127
-    }
128
-
129
-
130
-
131
-    /**
132
-     * set_current
133
-     *
134
-     * advances pointer to the provided object
135
-     *
136
-     * @access public
137
-     * @param $object
138
-     * @return void
139
-     */
140
-    public function set_current($object)
141
-    {
142
-        parent::set_current($object);
143
-    }
144
-
145
-
146
-
147
-    /**
148
-     * set_current_by_info
149
-     *
150
-     * advances pointer to the object whose info matches that which was provided
151
-     *
152
-     * @access public
153
-     * @param $info
154
-     * @return void
155
-     */
156
-    public function set_current_by_info($info)
157
-    {
158
-        parent::set_current_by_info($info);
159
-    }
160
-
161
-
162
-
163
-    /**
164
-     * show_collection_classes
165
-     *
166
-     * displays list of collection classes if WP_DEBUG is on
167
-     *
168
-     * @access public
169
-     * @return void
170
-     */
171
-    public function show_collection_classes()
172
-    {
173
-        if (WP_DEBUG) {
174
-            $this->rewind();
175
-            while ($this->valid()) {
176
-                echo '<h5 style="color:#2EA2CC;">
17
+	/**
18
+	 * EE_Message_Type_Collection constructor.
19
+	 */
20
+	public function __construct()
21
+	{
22
+		$this->interface = 'EE_message_type';
23
+	}
24
+
25
+
26
+
27
+	/**
28
+	 * add
29
+	 *
30
+	 * attaches an object to the Collection
31
+	 * and sets any supplied data associated with the current iterator entry
32
+	 * by calling EE_Object_Collection::set_info()
33
+	 *
34
+	 * @access public
35
+	 * @param object $object
36
+	 * @param mixed  $info
37
+	 * @return bool
38
+	 */
39
+	public function add($object, $info = null)
40
+	{
41
+		$info = empty($info) && $object instanceof $this->interface ? $object->name : $info;
42
+		return parent::add($object, $info);
43
+	}
44
+
45
+
46
+
47
+	/**
48
+	 * set_info
49
+	 *
50
+	 * Sets the data associated with an object in the Collection
51
+	 * if no $info is supplied, then the spl_object_hash() is used
52
+	 *
53
+	 * @access public
54
+	 * @param object $object
55
+	 * @param mixed  $info
56
+	 * @return bool
57
+	 */
58
+	public function set_info($object, $info = null)
59
+	{
60
+		$info = empty($info) && $object instanceof $this->interface ? $object->name : $info;
61
+		return parent::set_info($object, $info);
62
+	}
63
+
64
+
65
+
66
+	/**
67
+	 * get_by_info
68
+	 *
69
+	 * finds and returns an object in the Collection based on the info that was set using addObject()
70
+	 * PLZ NOTE: the pointer is reset to the beginning of the collection before returning
71
+	 *
72
+	 * @access public
73
+	 * @param mixed
74
+	 * @return null | object
75
+	 */
76
+	public function get_by_info($info)
77
+	{
78
+		return parent::get_by_info(str_replace(' ', '_', strtolower($info)));
79
+	}
80
+
81
+
82
+
83
+	/**
84
+	 * has
85
+	 *
86
+	 * returns TRUE or FALSE depending on whether the supplied object is within the Collection
87
+	 *
88
+	 * @access public
89
+	 * @param object $object
90
+	 * @return bool
91
+	 */
92
+	public function has($object)
93
+	{
94
+		return parent::has($object);
95
+	}
96
+
97
+
98
+
99
+	/**
100
+	 * has_by_name
101
+	 *
102
+	 * returns TRUE or FALSE depending on whether the supplied message_type classname is within the Collection
103
+	 *
104
+	 * @access public
105
+	 * @param string $message_type_name
106
+	 * @return bool
107
+	 */
108
+	public function has_by_name($message_type_name)
109
+	{
110
+		return $this->get_by_info($message_type_name) instanceof $this->interface ? true : false;
111
+	}
112
+
113
+
114
+
115
+	/**
116
+	 * remove
117
+	 *
118
+	 * detaches an object from the Collection
119
+	 *
120
+	 * @access public
121
+	 * @param $object
122
+	 * @return bool
123
+	 */
124
+	public function remove($object)
125
+	{
126
+		return parent::remove($object);
127
+	}
128
+
129
+
130
+
131
+	/**
132
+	 * set_current
133
+	 *
134
+	 * advances pointer to the provided object
135
+	 *
136
+	 * @access public
137
+	 * @param $object
138
+	 * @return void
139
+	 */
140
+	public function set_current($object)
141
+	{
142
+		parent::set_current($object);
143
+	}
144
+
145
+
146
+
147
+	/**
148
+	 * set_current_by_info
149
+	 *
150
+	 * advances pointer to the object whose info matches that which was provided
151
+	 *
152
+	 * @access public
153
+	 * @param $info
154
+	 * @return void
155
+	 */
156
+	public function set_current_by_info($info)
157
+	{
158
+		parent::set_current_by_info($info);
159
+	}
160
+
161
+
162
+
163
+	/**
164
+	 * show_collection_classes
165
+	 *
166
+	 * displays list of collection classes if WP_DEBUG is on
167
+	 *
168
+	 * @access public
169
+	 * @return void
170
+	 */
171
+	public function show_collection_classes()
172
+	{
173
+		if (WP_DEBUG) {
174
+			$this->rewind();
175
+			while ($this->valid()) {
176
+				echo '<h5 style="color:#2EA2CC;">
177 177
                     ' . __CLASS__ . ' class : <span style="color:#E76700">' . esc_html($this->getInfo()) . '</span>
178 178
                     </h5>';
179
-                $this->next();
180
-            }
181
-        }
182
-    }
179
+				$this->next();
180
+			}
181
+		}
182
+	}
183 183
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -174,7 +174,7 @@
 block discarded – undo
174 174
             $this->rewind();
175 175
             while ($this->valid()) {
176 176
                 echo '<h5 style="color:#2EA2CC;">
177
-                    ' . __CLASS__ . ' class : <span style="color:#E76700">' . esc_html($this->getInfo()) . '</span>
177
+                    ' . __CLASS__.' class : <span style="color:#E76700">'.esc_html($this->getInfo()).'</span>
178 178
                     </h5>';
179 179
                 $this->next();
180 180
             }
Please login to merge, or discard this patch.
libraries/messages/defaults/default/html_receipt_ticket_list.template.php 1 patch
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -24,14 +24,14 @@  discard block
 block discarded – undo
24 24
         <div class="ticket-time-and-place-details">
25 25
             <div class="ticket-time-details">
26 26
                 <h4 class="sub-section-title no-bottom-margin">
27
-                    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL . 'clock-16x16.png'); ?>">
27
+                    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL.'clock-16x16.png'); ?>">
28 28
                     <?php esc_html_e('Date/Time:', 'event_espresso'); ?>
29 29
                 </h4>
30 30
                 <ul class="event-dates">[DATETIME_LIST]</ul>
31 31
             </div>
32 32
             <div class="ticket-place-details">
33 33
                 <h4 class="sub-section-title no-bottom-margin">
34
-                    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL . 'location-pin-16x16.png'); ?>">
34
+                    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL.'location-pin-16x16.png'); ?>">
35 35
                     <?php esc_html_e('Venue', 'event_espresso'); ?>
36 36
                 </h4>
37 37
                 <ul class="event-venues">
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
         </div>
46 46
         <div class="ticket-registrations-area">
47 47
             <h4 class="sub-section-title">
48
-                <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL . 'users-16x16.png'); ?>">
48
+                <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL.'users-16x16.png'); ?>">
49 49
                 <?php esc_html_e("Registration Details", "event_espresso"); ?>
50 50
                 <span class="small-text link">
51 51
                     ( <a class="print_button noPrint" href="[PRIMARY_REGISTRANT_FRONTEND_EDIT_REG_LINK]">
Please login to merge, or discard this patch.
libraries/messages/defaults/default/html_receipt_event_list.template.php 1 patch
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@
 block discarded – undo
6 6
 
7 7
 ?>
8 8
 <h3 class="section-title event-name">
9
-    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL . 'calendar_year-24x24.png'); ?>">
9
+    <img class="icon" src="<?php echo esc_url_raw(EE_IMAGES_URL.'calendar_year-24x24.png'); ?>">
10 10
     <?php esc_html_e("Event Name:", "event_espresso") ?>
11 11
     <span class="plain-text">[EVENT_NAME]</span>
12 12
     <span class="small-text link">
Please login to merge, or discard this patch.
libraries/messages/defaults/default/html_receipt_attendee_list.template.php 1 patch
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -8,11 +8,11 @@
 block discarded – undo
8 8
 <li class="ticket-registration">
9 9
     <table class="registration-details">
10 10
         <tr class="odd">
11
-            <th><?php	_e('Attendee', 'event_espresso');?></th>
11
+            <th><?php	_e('Attendee', 'event_espresso'); ?></th>
12 12
             <td>[FNAME] [LNAME] ([ATTENDEE_EMAIL])</td>
13 13
         </tr>
14 14
         <tr>
15
-            <th><?php esc_html_e("Registration Code:", "event_espresso");?></th>
15
+            <th><?php esc_html_e("Registration Code:", "event_espresso"); ?></th>
16 16
             <td>[REGISTRATION_CODE] - <span class="[REGISTRATION_STATUS_ID]">[REGISTRATION_STATUS_LABEL]</span></td>
17 17
         </tr>
18 18
     </table>
Please login to merge, or discard this patch.