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