Completed
Branch BUG/migration-touchups (8422af)
by
unknown
26:43 queued 18:02
created
4_5_0_stages/EE_DMS_4_5_0_invoice_settings.dmsstage.php 2 patches
Indentation   +84 added lines, -84 removed lines patch added patch discarded remove patch
@@ -15,95 +15,95 @@
 block discarded – undo
15 15
 class EE_DMS_4_5_0_invoice_settings extends EE_Data_Migration_Script_Stage
16 16
 {
17 17
 
18
-    /**
19
-     * Just initializes the status of the migration
20
-     */
21
-    public function __construct()
22
-    {
23
-        $this->_pretty_name = __('Update Invoice Gateway Settings', 'event_espresso');
24
-        parent::__construct();
25
-    }
18
+	/**
19
+	 * Just initializes the status of the migration
20
+	 */
21
+	public function __construct()
22
+	{
23
+		$this->_pretty_name = __('Update Invoice Gateway Settings', 'event_espresso');
24
+		parent::__construct();
25
+	}
26 26
 
27 27
 
28 28
 
29
-    /**
30
-     * _count_records_to_migrate
31
-     * Counts the records to migrate; the public version may cache it
32
-     *
33
-     * @access protected
34
-     * @return int
35
-     */
36
-    protected function _count_records_to_migrate()
37
-    {
38
-        return 1;
39
-    }
29
+	/**
30
+	 * _count_records_to_migrate
31
+	 * Counts the records to migrate; the public version may cache it
32
+	 *
33
+	 * @access protected
34
+	 * @return int
35
+	 */
36
+	protected function _count_records_to_migrate()
37
+	{
38
+		return 1;
39
+	}
40 40
 
41 41
 
42 42
 
43
-    /**
44
-     *    _migration_step
45
-     *
46
-     * @access protected
47
-     * @param int $num_items
48
-     * @throws EE_Error
49
-     * @return int number of items ACTUALLY migrated
50
-     * @throws InvalidDataTypeException
51
-     */
52
-    protected function _migration_step($num_items = 1)
53
-    {
54
-        // if this isn't set then something is really wrong
55
-        if (! EE_Config::instance()->gateway instanceof EE_Gateway_Config) {
56
-            throw new EE_Error(__('It appears the Event Espresso Core Configuration is not setup correctly.', 'event_espresso'));
57
-        }
58
-        $invoice_settings = isset(EE_Config::instance()->gateway->payment_settings['Invoice']) ? EE_Config::instance()->gateway->payment_settings['Invoice'] : null;
59
-        if (! $invoice_settings) {
60
-            $this->add_error(__('Could not migrate EE4.4 invoice settings to EE4.5 because they didnt exist', 'event_espresso'));
61
-        } else {
62
-            $invoice_settings['template_payment_instructions'] = $invoice_settings['pdf_instructions'];
63
-            $invoice_settings['template_invoice_payee_name'] = $invoice_settings['payable_to'];
64
-            $invoice_settings['template_invoice_address'] = $invoice_settings['payment_address'];
65
-            $invoice_settings['template_invoice_email'] = '';
66
-            $invoice_settings['template_invoice_tax_number'] = '';
67
-            unset($invoice_settings['pdf_instructions']);
68
-            unset($invoice_settings['payable_to']);
69
-            unset($invoice_settings['payment_address']);
70
-            EE_Config::instance()->gateway->payment_settings['Invoice'] = $invoice_settings;
71
-            EE_Config::instance()->update_espresso_config(false, false);
43
+	/**
44
+	 *    _migration_step
45
+	 *
46
+	 * @access protected
47
+	 * @param int $num_items
48
+	 * @throws EE_Error
49
+	 * @return int number of items ACTUALLY migrated
50
+	 * @throws InvalidDataTypeException
51
+	 */
52
+	protected function _migration_step($num_items = 1)
53
+	{
54
+		// if this isn't set then something is really wrong
55
+		if (! EE_Config::instance()->gateway instanceof EE_Gateway_Config) {
56
+			throw new EE_Error(__('It appears the Event Espresso Core Configuration is not setup correctly.', 'event_espresso'));
57
+		}
58
+		$invoice_settings = isset(EE_Config::instance()->gateway->payment_settings['Invoice']) ? EE_Config::instance()->gateway->payment_settings['Invoice'] : null;
59
+		if (! $invoice_settings) {
60
+			$this->add_error(__('Could not migrate EE4.4 invoice settings to EE4.5 because they didnt exist', 'event_espresso'));
61
+		} else {
62
+			$invoice_settings['template_payment_instructions'] = $invoice_settings['pdf_instructions'];
63
+			$invoice_settings['template_invoice_payee_name'] = $invoice_settings['payable_to'];
64
+			$invoice_settings['template_invoice_address'] = $invoice_settings['payment_address'];
65
+			$invoice_settings['template_invoice_email'] = '';
66
+			$invoice_settings['template_invoice_tax_number'] = '';
67
+			unset($invoice_settings['pdf_instructions']);
68
+			unset($invoice_settings['payable_to']);
69
+			unset($invoice_settings['payment_address']);
70
+			EE_Config::instance()->gateway->payment_settings['Invoice'] = $invoice_settings;
71
+			EE_Config::instance()->update_espresso_config(false, false);
72 72
 
73
-            // @todo: check 'invoice_css' too because we can't easily affect that so we might need to set a persistent notice
74
-            // (why is it tough to change? because we want to update the receipt and invoice message template, but
75
-            // message templates are only initialized AFTER migrations and those two are new in 4.5. So if we wanted to
76
-            // update them from a DMS, we'd need to have the DMS create the message templates which is quite a lot of code;
77
-            // also we don't want to build a dependency on the messages code because it is likely to change soon
78
-            if (isset($invoice_settings['invoice_css'])
79
-                && ! in_array($invoice_settings['invoice_css'], array( '', 'simple.css' ))) {
80
-                new PersistentAdminNotice(
81
-                    'invoice_css_not_updated',
82
-                    sprintf(
83
-                        esc_html__(
84
-                            'You had previously set your Invoice Payment Method\'s stylesheet to be %1$s, but that setting has moved. PDF and HTML Invoices and Receipts are now Messages, which means you can easily modify them from your Wordpress Dashboard instead of using filters or uploading template files. Please visit Messages -> Receipt and Messages -> Invoice to change their stylesheets.',
85
-                            'event_espresso'
86
-                        ),
87
-                        $invoice_settings['invoice_css']
88
-                    )
89
-                );
90
-            }
91
-            $templates_relative_path = 'modules/gateways/Invoice/lib/templates/';
92
-            $overridden_invoice_body = EEH_Template::locate_template($templates_relative_path . 'invoice_body.template.php', null, false, false, true);
93
-            $overridden_receipt_body= EEH_Template::locate_template($templates_relative_path . 'receipt_body.template.php', null, false, false, true);
94
-            if ($overridden_invoice_body || $overridden_receipt_body) {
95
-                new PersistentAdminNotice(
96
-                    'invoice_overriding_templates',
97
-                    esc_html__(
98
-                        'Note: in this version of Event Espresso, PDF and HTML Invoices and Receipts are now Messages and can be changed just like any other messages; however we noticed you had previously overridden the old default Invoice/Receipt templates. Because of this, your old Invoice/Receipt templates will continue to be used INSTEAD of the new Invoice/Receipt message equivalents. We recommend deleting your old Invoice/Receipt templates and modifying the new Invoice and Receipt messages\'s content in Messages -> Invoice and Messages -> Receipt.',
99
-                        'event_espresso'
100
-                    ),
101
-                    true
102
-                );
103
-            }
104
-        }
105
-        // regardless of whether it worked or not, we ought to continue the migration
106
-        $this->set_completed();
107
-        return 1;
108
-    }
73
+			// @todo: check 'invoice_css' too because we can't easily affect that so we might need to set a persistent notice
74
+			// (why is it tough to change? because we want to update the receipt and invoice message template, but
75
+			// message templates are only initialized AFTER migrations and those two are new in 4.5. So if we wanted to
76
+			// update them from a DMS, we'd need to have the DMS create the message templates which is quite a lot of code;
77
+			// also we don't want to build a dependency on the messages code because it is likely to change soon
78
+			if (isset($invoice_settings['invoice_css'])
79
+				&& ! in_array($invoice_settings['invoice_css'], array( '', 'simple.css' ))) {
80
+				new PersistentAdminNotice(
81
+					'invoice_css_not_updated',
82
+					sprintf(
83
+						esc_html__(
84
+							'You had previously set your Invoice Payment Method\'s stylesheet to be %1$s, but that setting has moved. PDF and HTML Invoices and Receipts are now Messages, which means you can easily modify them from your Wordpress Dashboard instead of using filters or uploading template files. Please visit Messages -> Receipt and Messages -> Invoice to change their stylesheets.',
85
+							'event_espresso'
86
+						),
87
+						$invoice_settings['invoice_css']
88
+					)
89
+				);
90
+			}
91
+			$templates_relative_path = 'modules/gateways/Invoice/lib/templates/';
92
+			$overridden_invoice_body = EEH_Template::locate_template($templates_relative_path . 'invoice_body.template.php', null, false, false, true);
93
+			$overridden_receipt_body= EEH_Template::locate_template($templates_relative_path . 'receipt_body.template.php', null, false, false, true);
94
+			if ($overridden_invoice_body || $overridden_receipt_body) {
95
+				new PersistentAdminNotice(
96
+					'invoice_overriding_templates',
97
+					esc_html__(
98
+						'Note: in this version of Event Espresso, PDF and HTML Invoices and Receipts are now Messages and can be changed just like any other messages; however we noticed you had previously overridden the old default Invoice/Receipt templates. Because of this, your old Invoice/Receipt templates will continue to be used INSTEAD of the new Invoice/Receipt message equivalents. We recommend deleting your old Invoice/Receipt templates and modifying the new Invoice and Receipt messages\'s content in Messages -> Invoice and Messages -> Receipt.',
99
+						'event_espresso'
100
+					),
101
+					true
102
+				);
103
+			}
104
+		}
105
+		// regardless of whether it worked or not, we ought to continue the migration
106
+		$this->set_completed();
107
+		return 1;
108
+	}
109 109
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -52,11 +52,11 @@  discard block
 block discarded – undo
52 52
     protected function _migration_step($num_items = 1)
53 53
     {
54 54
         // if this isn't set then something is really wrong
55
-        if (! EE_Config::instance()->gateway instanceof EE_Gateway_Config) {
55
+        if ( ! EE_Config::instance()->gateway instanceof EE_Gateway_Config) {
56 56
             throw new EE_Error(__('It appears the Event Espresso Core Configuration is not setup correctly.', 'event_espresso'));
57 57
         }
58 58
         $invoice_settings = isset(EE_Config::instance()->gateway->payment_settings['Invoice']) ? EE_Config::instance()->gateway->payment_settings['Invoice'] : null;
59
-        if (! $invoice_settings) {
59
+        if ( ! $invoice_settings) {
60 60
             $this->add_error(__('Could not migrate EE4.4 invoice settings to EE4.5 because they didnt exist', 'event_espresso'));
61 61
         } else {
62 62
             $invoice_settings['template_payment_instructions'] = $invoice_settings['pdf_instructions'];
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
             // update them from a DMS, we'd need to have the DMS create the message templates which is quite a lot of code;
77 77
             // also we don't want to build a dependency on the messages code because it is likely to change soon
78 78
             if (isset($invoice_settings['invoice_css'])
79
-                && ! in_array($invoice_settings['invoice_css'], array( '', 'simple.css' ))) {
79
+                && ! in_array($invoice_settings['invoice_css'], array('', 'simple.css'))) {
80 80
                 new PersistentAdminNotice(
81 81
                     'invoice_css_not_updated',
82 82
                     sprintf(
@@ -89,8 +89,8 @@  discard block
 block discarded – undo
89 89
                 );
90 90
             }
91 91
             $templates_relative_path = 'modules/gateways/Invoice/lib/templates/';
92
-            $overridden_invoice_body = EEH_Template::locate_template($templates_relative_path . 'invoice_body.template.php', null, false, false, true);
93
-            $overridden_receipt_body= EEH_Template::locate_template($templates_relative_path . 'receipt_body.template.php', null, false, false, true);
92
+            $overridden_invoice_body = EEH_Template::locate_template($templates_relative_path.'invoice_body.template.php', null, false, false, true);
93
+            $overridden_receipt_body = EEH_Template::locate_template($templates_relative_path.'receipt_body.template.php', null, false, false, true);
94 94
             if ($overridden_invoice_body || $overridden_receipt_body) {
95 95
                 new PersistentAdminNotice(
96 96
                     'invoice_overriding_templates',
Please login to merge, or discard this patch.
core/data_migration_scripts/4_1_0_stages/EE_DMS_4_1_0_gateways.dmsstage.php 1 patch
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -14,68 +14,68 @@  discard block
 block discarded – undo
14 14
 class EE_DMS_4_1_0_gateways extends EE_Data_Migration_Script_Stage
15 15
 {
16 16
 
17
-    private $_converted_active_gateways = false;
17
+	private $_converted_active_gateways = false;
18 18
 
19
-    public function _migration_step($num_items = 50)
20
-    {
21
-        // loads existing EE_CONfig from DB, if it exists
22
-        $new_gateway_config_obj = EE_Config::instance()->gateway;
23
-        $items_actually_migrated = 0;
24
-        // convert settings
25
-        $gateways_to_deal_with = array_merge($this->_gateways_we_know_how_to_migrate, $this->_gateways_we_leave_alone);
26
-        // just do a part of them on this request
27
-        $gateways_to_deal_with = array_slice($gateways_to_deal_with, $this->count_records_migrated(), $num_items);// $this->_gateways_we_know_how_to_migrate;
28
-        foreach ($gateways_to_deal_with as $old_gateway_slug => $new_gateway_slug) {
29
-            $old_gateway_wp_option_name = $this->_get_old_gateway_option_name($new_gateway_slug);
30
-            if (isset($this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ])) {
31
-                // determine the old option's name
32
-                $old_gateway_settings = $this->_get_old_gateway_option($new_gateway_slug);
33
-                if (! $old_gateway_settings) {
34
-                    // no settings existed for this gateway anyways... weird...
35
-                    $items_actually_migrated++;
36
-                    continue;
37
-                }
38
-                // now prepare the settings to make sure they're in the 4.1 format
39
-                $new_gateway_settings = $this->_convert_gateway_settings($old_gateway_settings, $new_gateway_slug);
40
-                $new_gateway_config_obj->payment_settings[ $new_gateway_slug ] = $new_gateway_settings;
41
-                // and when we're done, remove the old option. Sometimes we'd prefer to do this in a different stage, but
42
-                // I think it's ok to do right away this time (we wont need gateway settings elsewhere)
43
-                delete_option($old_gateway_wp_option_name);
44
-            } else {// it must be one of the ones we mostly leave alone
45
-                global $wpdb;
46
-                // yeah we could do this all in one query... and if you're reading this and would liek to, go ahead. Although you'll
47
-                // only be saving users 50 milliseconds the one time this runs...
48
-                $wpdb->query($wpdb->prepare("UPDATE ".$wpdb->options." SET autoload='no' WHERE option_name=%s", $old_gateway_wp_option_name));
49
-            }
19
+	public function _migration_step($num_items = 50)
20
+	{
21
+		// loads existing EE_CONfig from DB, if it exists
22
+		$new_gateway_config_obj = EE_Config::instance()->gateway;
23
+		$items_actually_migrated = 0;
24
+		// convert settings
25
+		$gateways_to_deal_with = array_merge($this->_gateways_we_know_how_to_migrate, $this->_gateways_we_leave_alone);
26
+		// just do a part of them on this request
27
+		$gateways_to_deal_with = array_slice($gateways_to_deal_with, $this->count_records_migrated(), $num_items);// $this->_gateways_we_know_how_to_migrate;
28
+		foreach ($gateways_to_deal_with as $old_gateway_slug => $new_gateway_slug) {
29
+			$old_gateway_wp_option_name = $this->_get_old_gateway_option_name($new_gateway_slug);
30
+			if (isset($this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ])) {
31
+				// determine the old option's name
32
+				$old_gateway_settings = $this->_get_old_gateway_option($new_gateway_slug);
33
+				if (! $old_gateway_settings) {
34
+					// no settings existed for this gateway anyways... weird...
35
+					$items_actually_migrated++;
36
+					continue;
37
+				}
38
+				// now prepare the settings to make sure they're in the 4.1 format
39
+				$new_gateway_settings = $this->_convert_gateway_settings($old_gateway_settings, $new_gateway_slug);
40
+				$new_gateway_config_obj->payment_settings[ $new_gateway_slug ] = $new_gateway_settings;
41
+				// and when we're done, remove the old option. Sometimes we'd prefer to do this in a different stage, but
42
+				// I think it's ok to do right away this time (we wont need gateway settings elsewhere)
43
+				delete_option($old_gateway_wp_option_name);
44
+			} else {// it must be one of the ones we mostly leave alone
45
+				global $wpdb;
46
+				// yeah we could do this all in one query... and if you're reading this and would liek to, go ahead. Although you'll
47
+				// only be saving users 50 milliseconds the one time this runs...
48
+				$wpdb->query($wpdb->prepare("UPDATE ".$wpdb->options." SET autoload='no' WHERE option_name=%s", $old_gateway_wp_option_name));
49
+			}
50 50
         
51
-            $items_actually_migrated++;
52
-        }
53
-        // if we can keep going, and it hasn' tbeen done yet, convert active gateways
54
-        if ($items_actually_migrated < $num_items &&  ! $this->_converted_active_gateways) {
55
-            $this->_convert_active_gateways();
56
-            $this->_converted_active_gateways = true;
57
-            $items_actually_migrated++;
58
-        }
51
+			$items_actually_migrated++;
52
+		}
53
+		// if we can keep going, and it hasn' tbeen done yet, convert active gateways
54
+		if ($items_actually_migrated < $num_items &&  ! $this->_converted_active_gateways) {
55
+			$this->_convert_active_gateways();
56
+			$this->_converted_active_gateways = true;
57
+			$items_actually_migrated++;
58
+		}
59 59
     
60
-        EE_Config::instance()->update_espresso_config(false, false);
61
-        if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
62
-            $this->set_completed();
63
-        }
64
-        return $items_actually_migrated;
65
-    }
66
-    public function _count_records_to_migrate()
67
-    {
68
-        $count_of_gateways_to_convert = count($this->_gateways_we_know_how_to_migrate);
69
-        $step_of_setting_active_gateways = 1;
70
-        $count_of_gateways_to_leave_alone = count($this->_gateways_we_leave_alone);
71
-    //  $button_images_to_update =
72
-        return $count_of_gateways_to_convert +  $step_of_setting_active_gateways + $count_of_gateways_to_leave_alone;
73
-    }
74
-    public function __construct()
75
-    {
76
-        $this->_pretty_name = __("Gateways", "event_espresso");
77
-        parent::__construct();
78
-    }
60
+		EE_Config::instance()->update_espresso_config(false, false);
61
+		if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
62
+			$this->set_completed();
63
+		}
64
+		return $items_actually_migrated;
65
+	}
66
+	public function _count_records_to_migrate()
67
+	{
68
+		$count_of_gateways_to_convert = count($this->_gateways_we_know_how_to_migrate);
69
+		$step_of_setting_active_gateways = 1;
70
+		$count_of_gateways_to_leave_alone = count($this->_gateways_we_leave_alone);
71
+	//  $button_images_to_update =
72
+		return $count_of_gateways_to_convert +  $step_of_setting_active_gateways + $count_of_gateways_to_leave_alone;
73
+	}
74
+	public function __construct()
75
+	{
76
+		$this->_pretty_name = __("Gateways", "event_espresso");
77
+		parent::__construct();
78
+	}
79 79
 
80 80
 /**
81 81
  * Takes the old array of 3.1 gateway settings for this gateway and converts it
@@ -85,148 +85,148 @@  discard block
 block discarded – undo
85 85
  * @param string $new_gateway_slug
86 86
  * @return array
87 87
  */
88
-    private function _convert_gateway_settings($old_gateway_settings, $new_gateway_slug)
89
-    {
90
-        $new_gateway_settings = $old_gateway_settings;
91
-        switch ($new_gateway_slug) {
92
-            case 'Bank':
93
-                $new_gateway_settings['account_number'] = $old_gateway_settings['bank_account'];
94
-                $new_gateway_settings['page_title'] = $old_gateway_settings['bank_title'];
95
-                break;
96
-            case 'Invoice':
97
-                $new_gateway_settings['invoice_logo_url'] = $old_gateway_settings['image_url'];
98
-                // Dont' migrate the old invoice payee address. It was usually given dummy data. And in EE4
99
-                // it gets used in the receipts which are available to everyone. So usually it's best to not
100
-                // migrate this.
101
-                unset($new_gateway_settings['payment_address']);
102
-                break;
103
-            case 'Paypal_Pro':
104
-                $new_gateway_settings['email'] = $old_gateway_settings['paypal_pro_email'];
105
-                $new_gateway_settings['username'] = $old_gateway_settings['paypal_api_username'];
106
-                $new_gateway_settings['password'] = $old_gateway_settings['paypal_api_password'];
107
-                $new_gateway_settings['signature'] = $old_gateway_settings['paypal_api_signature'];
108
-                $new_gateway_settings['credit_cards'] = explode(",", $old_gateway_settings['paypal_api_credit_cards']);
109
-                $new_gateway_settings['use_sandbox'] = $old_gateway_settings['paypal_pro_use_sandbox'];
110
-                break;
111
-        }
112
-        return $new_gateway_settings;
113
-    }
88
+	private function _convert_gateway_settings($old_gateway_settings, $new_gateway_slug)
89
+	{
90
+		$new_gateway_settings = $old_gateway_settings;
91
+		switch ($new_gateway_slug) {
92
+			case 'Bank':
93
+				$new_gateway_settings['account_number'] = $old_gateway_settings['bank_account'];
94
+				$new_gateway_settings['page_title'] = $old_gateway_settings['bank_title'];
95
+				break;
96
+			case 'Invoice':
97
+				$new_gateway_settings['invoice_logo_url'] = $old_gateway_settings['image_url'];
98
+				// Dont' migrate the old invoice payee address. It was usually given dummy data. And in EE4
99
+				// it gets used in the receipts which are available to everyone. So usually it's best to not
100
+				// migrate this.
101
+				unset($new_gateway_settings['payment_address']);
102
+				break;
103
+			case 'Paypal_Pro':
104
+				$new_gateway_settings['email'] = $old_gateway_settings['paypal_pro_email'];
105
+				$new_gateway_settings['username'] = $old_gateway_settings['paypal_api_username'];
106
+				$new_gateway_settings['password'] = $old_gateway_settings['paypal_api_password'];
107
+				$new_gateway_settings['signature'] = $old_gateway_settings['paypal_api_signature'];
108
+				$new_gateway_settings['credit_cards'] = explode(",", $old_gateway_settings['paypal_api_credit_cards']);
109
+				$new_gateway_settings['use_sandbox'] = $old_gateway_settings['paypal_pro_use_sandbox'];
110
+				break;
111
+		}
112
+		return $new_gateway_settings;
113
+	}
114 114
 /**
115
- * Figures out the correct 3.1 gateway settings option name for the given 4.1 gateway
116
- * @param string $new_gateway_slug
117
- * @return string
118
- */
119
-    private function _get_old_gateway_option($new_gateway_slug)
120
-    {
121
-        $option_name = $this->_get_old_gateway_option_name($new_gateway_slug);
122
-        $settings =  get_option($option_name, null);
123
-    //  if( ! $settings){
124
-    //      $this->add_error(sprintf(__("There is no wordpress option named %s for gateway %s", "event_espresso"),$option_name,$new_gateway_slug));
125
-    //  }
126
-        return $settings;
127
-    }
115
+	 * Figures out the correct 3.1 gateway settings option name for the given 4.1 gateway
116
+	 * @param string $new_gateway_slug
117
+	 * @return string
118
+	 */
119
+	private function _get_old_gateway_option($new_gateway_slug)
120
+	{
121
+		$option_name = $this->_get_old_gateway_option_name($new_gateway_slug);
122
+		$settings =  get_option($option_name, null);
123
+	//  if( ! $settings){
124
+	//      $this->add_error(sprintf(__("There is no wordpress option named %s for gateway %s", "event_espresso"),$option_name,$new_gateway_slug));
125
+	//  }
126
+		return $settings;
127
+	}
128 128
 
129 129
 /**
130 130
  * Just gets the old gateways slug
131 131
  * @param string $new_gateway_slug
132 132
  * @return string
133 133
  */
134
-    private function _get_old_gateway_option_name($new_gateway_slug)
135
-    {
136
-        $new_gateway_slugs_to_new = array_flip(array_merge($this->_gateways_we_know_how_to_migrate, $this->_gateways_we_leave_alone));
137
-        $old_gateway_slug = $new_gateway_slugs_to_new[ $new_gateway_slug ];
138
-        $normal_option_prefix = 'event_espresso_';
139
-        $normal_option_postfix = '_settings';
140
-        switch ($new_gateway_slug) {
141
-            case 'Bank':
142
-                $option_name = $normal_option_prefix.'bank_deposit'.$normal_option_postfix;
143
-                break;
144
-            case 'Aim':
145
-                $option_name = $normal_option_prefix.'authnet_aim'.$normal_option_postfix;
146
-                break;
147
-            case 'Check':
148
-                $option_name = $normal_option_prefix.'check_payment'.$normal_option_postfix;
149
-                break;
150
-            case 'Ideal':
151
-                $option_name = $normal_option_prefix.'ideal_mollie'.$normal_option_postfix;
152
-                break;
153
-            case 'Invoice':
154
-                $option_name = $normal_option_prefix.'invoice_payment'.$normal_option_postfix;
155
-                break;
156
-            case 'Purchase_Order':
157
-                $option_name = $normal_option_prefix.'purchase_order_payment'.$normal_option_postfix;
158
-                break;
159
-            case 'USAePay_Offsite':
160
-                $option_name = 'espresso_usaepay_offsite'.$normal_option_postfix;
161
-                break;
162
-            case 'USAePay_Onsite':
163
-                $option_name = 'espresso_usaepay_onsite'.$normal_option_postfix;
164
-                break;
165
-            default:
166
-                $option_name = apply_filters('FHEE__EE_DMS_4_1_0_gateways__get_old_gateway_option', $normal_option_prefix.$old_gateway_slug.$normal_option_postfix);
167
-        }
168
-        return $option_name;
169
-    }
134
+	private function _get_old_gateway_option_name($new_gateway_slug)
135
+	{
136
+		$new_gateway_slugs_to_new = array_flip(array_merge($this->_gateways_we_know_how_to_migrate, $this->_gateways_we_leave_alone));
137
+		$old_gateway_slug = $new_gateway_slugs_to_new[ $new_gateway_slug ];
138
+		$normal_option_prefix = 'event_espresso_';
139
+		$normal_option_postfix = '_settings';
140
+		switch ($new_gateway_slug) {
141
+			case 'Bank':
142
+				$option_name = $normal_option_prefix.'bank_deposit'.$normal_option_postfix;
143
+				break;
144
+			case 'Aim':
145
+				$option_name = $normal_option_prefix.'authnet_aim'.$normal_option_postfix;
146
+				break;
147
+			case 'Check':
148
+				$option_name = $normal_option_prefix.'check_payment'.$normal_option_postfix;
149
+				break;
150
+			case 'Ideal':
151
+				$option_name = $normal_option_prefix.'ideal_mollie'.$normal_option_postfix;
152
+				break;
153
+			case 'Invoice':
154
+				$option_name = $normal_option_prefix.'invoice_payment'.$normal_option_postfix;
155
+				break;
156
+			case 'Purchase_Order':
157
+				$option_name = $normal_option_prefix.'purchase_order_payment'.$normal_option_postfix;
158
+				break;
159
+			case 'USAePay_Offsite':
160
+				$option_name = 'espresso_usaepay_offsite'.$normal_option_postfix;
161
+				break;
162
+			case 'USAePay_Onsite':
163
+				$option_name = 'espresso_usaepay_onsite'.$normal_option_postfix;
164
+				break;
165
+			default:
166
+				$option_name = apply_filters('FHEE__EE_DMS_4_1_0_gateways__get_old_gateway_option', $normal_option_prefix.$old_gateway_slug.$normal_option_postfix);
167
+		}
168
+		return $option_name;
169
+	}
170 170
 
171
-    private function _convert_active_gateways()
172
-    {
173
-        // just does it all one big swoop
174
-        $old_active_gateways = get_option('event_espresso_active_gateways');
175
-        $new_active_gateways = EE_Config::instance()->gateway->active_gateways;
176
-        foreach ($old_active_gateways as $old_gateway_slug => $filepath) {
177
-            if (! isset($this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ])) {
178
-                $this->add_error(sprintf(__("The %s gateway does not exist in EE 4.1", "event_espresso"), $old_gateway_slug));
179
-                continue;
180
-            }
181
-            $new_gateway_slug = $this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ];
171
+	private function _convert_active_gateways()
172
+	{
173
+		// just does it all one big swoop
174
+		$old_active_gateways = get_option('event_espresso_active_gateways');
175
+		$new_active_gateways = EE_Config::instance()->gateway->active_gateways;
176
+		foreach ($old_active_gateways as $old_gateway_slug => $filepath) {
177
+			if (! isset($this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ])) {
178
+				$this->add_error(sprintf(__("The %s gateway does not exist in EE 4.1", "event_espresso"), $old_gateway_slug));
179
+				continue;
180
+			}
181
+			$new_gateway_slug = $this->_gateways_we_know_how_to_migrate[ $old_gateway_slug ];
182 182
         
183
-            // in the new format we can also upload gateways to the uploads directory and
184
-            $new_active_gateways[ $new_gateway_slug ] = false;
185
-        }
186
-        EE_Config::instance()->gateway->active_gateways = $new_active_gateways;
187
-    }
183
+			// in the new format we can also upload gateways to the uploads directory and
184
+			$new_active_gateways[ $new_gateway_slug ] = false;
185
+		}
186
+		EE_Config::instance()->gateway->active_gateways = $new_active_gateways;
187
+	}
188 188
     
189
-    protected $_gateways_we_know_how_to_migrate = array(
190
-        'aim'=>'Aim',
191
-        'bank'=>'Bank',
192
-        'check'=>'Check',
193
-        'invoice'=>'Invoice',
194
-        'paypal'=>'Paypal_Standard',
195
-        'paypal_pro'=>'Paypal_Pro',
189
+	protected $_gateways_we_know_how_to_migrate = array(
190
+		'aim'=>'Aim',
191
+		'bank'=>'Bank',
192
+		'check'=>'Check',
193
+		'invoice'=>'Invoice',
194
+		'paypal'=>'Paypal_Standard',
195
+		'paypal_pro'=>'Paypal_Pro',
196 196
 
197
-    );
197
+	);
198 198
     
199
-    protected $_gateways_we_leave_alone = array(
200
-        '2checkout'=>'2checkout',
201
-        'anz'=>'Anz',
202
-        'atos'=>'Atos',
203
-        'authnet'=>'Authnet',
204
-        'beanstream'=>'Beanstream',
205
-        'evertec'=>'Evertec',
206
-        'eway'=>'Eway',
207
-        'eway_rapid3'=>'Eway_Rapid3',
208
-        'exact'=>'Exact',
209
-        'firstdata'=>'Firstdata',
210
-        'firstdat_e4'=>'Firstdata_E4',
211
-        'ideal'=>'Ideal',
212
-        'infusion_payment'=>'InfusionSoft',
213
-        'luottokunta'=>'Luottokunta',
214
-        'megasoft'=>'Megasoft',
215
-        'moneris_hpp'=>'Moneris_HPP',
216
-        'mwarrior'=>'Mwarrior',
217
-        'nab'=>'NAB',
218
-        'paychoice'=>'Paychoice',
219
-        'paytrace'=>'Paytrace',
220
-        'psigate'=>'Psigate',
221
-        'purchase_order'=>'Purchase_Order',
222
-        'qbms'=>'QBMS',
223
-        'quickpay'=>'Quickpay',
224
-        'realauth'=>'Realauth',
225
-        'securepay_aus'=>'Securepay_Aus',
226
-        'stripe'=>'Stripe',
227
-        'usaepay_offsite'=>'USAePay_Offsite',
228
-        'usaepay_onsite'=>'USAePay_Onsite',
229
-        'wepay'=>'Wepay',
230
-        'worldpay'=>'Worldpay'
231
-    );
199
+	protected $_gateways_we_leave_alone = array(
200
+		'2checkout'=>'2checkout',
201
+		'anz'=>'Anz',
202
+		'atos'=>'Atos',
203
+		'authnet'=>'Authnet',
204
+		'beanstream'=>'Beanstream',
205
+		'evertec'=>'Evertec',
206
+		'eway'=>'Eway',
207
+		'eway_rapid3'=>'Eway_Rapid3',
208
+		'exact'=>'Exact',
209
+		'firstdata'=>'Firstdata',
210
+		'firstdat_e4'=>'Firstdata_E4',
211
+		'ideal'=>'Ideal',
212
+		'infusion_payment'=>'InfusionSoft',
213
+		'luottokunta'=>'Luottokunta',
214
+		'megasoft'=>'Megasoft',
215
+		'moneris_hpp'=>'Moneris_HPP',
216
+		'mwarrior'=>'Mwarrior',
217
+		'nab'=>'NAB',
218
+		'paychoice'=>'Paychoice',
219
+		'paytrace'=>'Paytrace',
220
+		'psigate'=>'Psigate',
221
+		'purchase_order'=>'Purchase_Order',
222
+		'qbms'=>'QBMS',
223
+		'quickpay'=>'Quickpay',
224
+		'realauth'=>'Realauth',
225
+		'securepay_aus'=>'Securepay_Aus',
226
+		'stripe'=>'Stripe',
227
+		'usaepay_offsite'=>'USAePay_Offsite',
228
+		'usaepay_onsite'=>'USAePay_Onsite',
229
+		'wepay'=>'Wepay',
230
+		'worldpay'=>'Worldpay'
231
+	);
232 232
 }
Please login to merge, or discard this patch.
core/EE_Data_Migration_Manager.core.php 2 patches
Indentation   +1234 added lines, -1234 removed lines patch added patch discarded remove patch
@@ -32,1238 +32,1238 @@
 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
-     * string indicating the migration should continue
63
-     */
64
-    const status_continue = 'status_continue';
65
-    /**
66
-     * string indicating the migration has completed and should be ended
67
-     */
68
-    const status_completed = 'status_completed';
69
-    /**
70
-     * string indicating a fatal error occurred and the data migration should be completely aborted
71
-     */
72
-    const status_fatal_error = 'status_fatal_error';
73
-
74
-    /**
75
-     * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
76
-     * during migration)
77
-     */
78
-    const step_size = 50;
79
-
80
-    /**
81
-     * option name that stores the queue of ee plugins needing to have
82
-     * their data initialized (or re-initialized) once we are done migrations
83
-     */
84
-    const db_init_queue_option_name = 'ee_db_init_queue';
85
-    /**
86
-     * Array of information concerning data migrations that have ran in the history
87
-     * of this EE installation. Keys should be the name of the version the script upgraded to
88
-     *
89
-     * @var EE_Data_Migration_Script_Base[]
90
-     */
91
-    private $_data_migrations_ran = null;
92
-    /**
93
-     * The last ran script. It's nice to store this somewhere accessible, as its easiest
94
-     * to know which was the last run by which is the newest wp option; but in most of the code
95
-     * we just use the local $_data_migration_ran array, which organized the scripts differently
96
-     *
97
-     * @var EE_Data_Migration_Script_Base
98
-     */
99
-    private $_last_ran_script = null;
100
-
101
-    /**
102
-     * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
103
-     *
104
-     * @var EE_Data_Migration_Script_Base
105
-     */
106
-    private $_last_ran_incomplete_script = null;
107
-    /**
108
-     * array where keys are classnames, and values are filepaths of all the known migration scripts
109
-     *
110
-     * @var array
111
-     */
112
-    private $_data_migration_class_to_filepath_map;
113
-
114
-    /**
115
-     * the following 4 properties are fully set on construction.
116
-     * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
117
-     * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
118
-     * data migration script
119
-     *
120
-     * @var array
121
-     */
122
-    public $stati_that_indicate_to_continue_migrations = array();
123
-
124
-    public $stati_that_indicate_to_stop_migrations = array();
125
-
126
-    public $stati_that_indicate_to_continue_single_migration_script = array();
127
-
128
-    public $stati_that_indicate_to_stop_single_migration_script = array();
129
-
130
-    /**
131
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
132
-     */
133
-    protected $_table_manager;
134
-
135
-    /**
136
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
137
-     */
138
-    protected $_table_analysis;
139
-
140
-    /**
141
-     * @var array $script_migration_versions
142
-     */
143
-    protected $script_migration_versions;
144
-
145
-    /**
146
-     * @var EE_Data_Migration_Manager $_instance
147
-     * @access    private
148
-     */
149
-    private static $_instance = null;
150
-
151
-
152
-    /**
153
-     * @singleton method used to instantiate class object
154
-     * @access    public
155
-     * @return EE_Data_Migration_Manager instance
156
-     */
157
-    public static function instance()
158
-    {
159
-        // check if class object is instantiated
160
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
161
-            self::$_instance = new self();
162
-        }
163
-        return self::$_instance;
164
-    }
165
-
166
-    /**
167
-     * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
168
-     * all new usages of the singleton should be made with Classname::instance()) and returns it
169
-     *
170
-     * @return EE_Data_Migration_Manager
171
-     */
172
-    public static function reset()
173
-    {
174
-        self::$_instance = null;
175
-        return self::instance();
176
-    }
177
-
178
-
179
-    /**
180
-     * constructor
181
-     */
182
-    private function __construct()
183
-    {
184
-        $this->stati_that_indicate_to_continue_migrations = array(
185
-            self::status_continue,
186
-            self::status_completed,
187
-        );
188
-        $this->stati_that_indicate_to_stop_migrations = array(
189
-            self::status_fatal_error,
190
-            self::status_no_more_migration_scripts,
191
-        );
192
-        $this->stati_that_indicate_to_continue_single_migration_script = array(
193
-            self::status_continue,
194
-        );
195
-        $this->stati_that_indicate_to_stop_single_migration_script = array(
196
-            self::status_completed,
197
-            self::status_fatal_error
198
-            // note: status_no_more_migration_scripts doesn't apply
199
-        );
200
-        // make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
201
-        // to be defined, because right now it doesn't get autoloaded on its own
202
-        EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true);
203
-        EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true);
204
-        EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true);
205
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true);
206
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true);
207
-        $this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true);
208
-        $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
209
-    }
210
-
211
-
212
-    /**
213
-     * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
214
-     * the option names are like, but generally they're like
215
-     * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
216
-     * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
217
-     * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg
218
-     * EE_DMS_Core_4_1_0.dms.php)
219
-     *
220
-     * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
221
-     * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of
222
-     *               that plugin (eg '4.1.0')
223
-     */
224
-    private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
225
-    {
226
-        $plugin_slug_and_version_string = str_replace(
227
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
228
-            "",
229
-            $option_name
230
-        );
231
-        // check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
232
-        $parts = explode(".", $plugin_slug_and_version_string);
233
-
234
-        if (count($parts) == 4) {
235
-            // it's 4.2-style.eg Core.4.1.0
236
-            $plugin_slug = $parts[0];// eg Core
237
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
238
-        } else {
239
-            // it's 4.1-style: eg 4.1.0
240
-            $plugin_slug = 'Core';
241
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
242
-        }
243
-        return array($plugin_slug, $version_string);
244
-    }
245
-
246
-    /**
247
-     * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not
248
-     * for a known DMS class.
249
-     *
250
-     * @param string $dms_option_name
251
-     * @param string $dms_option_value (serialized)
252
-     * @return EE_Data_Migration_Script_Base
253
-     * @throws EE_Error
254
-     */
255
-    private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
256
-    {
257
-        $data_migration_data = maybe_unserialize($dms_option_value);
258
-        if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
259
-            $class = new $data_migration_data['class'];
260
-            if ($class instanceof EE_Data_Migration_Script_Base) {
261
-                $class->instantiate_from_array_of_properties($data_migration_data);
262
-                return $class;
263
-            } else {
264
-                // huh, so its an object but not a data migration script?? that shouldn't happen
265
-                // just leave it as an array (which will probably just get ignored)
266
-                throw new EE_Error(
267
-                    sprintf(
268
-                        __(
269
-                            "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
270
-                            'event_espresso'
271
-                        ),
272
-                        $data_migration_data['class']
273
-                    )
274
-                );
275
-            }
276
-        } else {
277
-            // 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
278
-            throw new EE_Error(
279
-                sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name)
280
-            );
281
-        }
282
-    }
283
-
284
-    /**
285
-     * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last
286
-     * ran, and which was the last ran which hasn't finished yet
287
-     *
288
-     * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy
289
-     *               arrays in there - which should probably be ignored)
290
-     */
291
-    public function get_data_migrations_ran()
292
-    {
293
-        if (! $this->_data_migrations_ran) {
294
-            // setup autoloaders for each of the scripts in there
295
-            $this->get_all_data_migration_scripts_available();
296
-            $data_migrations_options = $this->get_all_migration_script_options(
297
-            );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
298
-
299
-            $data_migrations_ran = array();
300
-            // convert into data migration script classes where possible
301
-            foreach ($data_migrations_options as $data_migration_option) {
302
-                list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
303
-                    $data_migration_option['option_name']
304
-                );
305
-
306
-                try {
307
-                    $class = $this->_get_dms_class_from_wp_option(
308
-                        $data_migration_option['option_name'],
309
-                        $data_migration_option['option_value']
310
-                    );
311
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
312
-                    // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
313
-                    $this->_last_ran_script = $class;
314
-                    if (! $class->is_completed()) {
315
-                        // sometimes we also like to know which was the last incomplete script (or if there are any at all)
316
-                        $this->_last_ran_incomplete_script = $class;
317
-                    }
318
-                } catch (EE_Error $e) {
319
-                    // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
320
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
321
-                        $data_migration_option['option_value']
322
-                    );
323
-                }
324
-            }
325
-            // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
326
-            $this->_data_migrations_ran = $data_migrations_ran;
327
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
328
-                $this->_data_migrations_ran = array();
329
-            }
330
-        }
331
-        return $this->_data_migrations_ran;
332
-    }
333
-
334
-
335
-    /**
336
-     *
337
-     * @param string $script_name eg 'DMS_Core_4_1_0'
338
-     * @param string $old_table   eg 'wp_events_detail'
339
-     * @param string $old_pk      eg 'wp_esp_posts'
340
-     * @param        $new_table
341
-     * @return mixed string or int
342
-     */
343
-    public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
344
-    {
345
-        $script = EE_Registry::instance()->load_dms($script_name);
346
-        $mapping = $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
347
-        return $mapping;
348
-    }
349
-
350
-    /**
351
-     * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
352
-     * the last option returned in this array is the most-recently ran DMS option
353
-     *
354
-     * @return array
355
-     */
356
-    public function get_all_migration_script_options()
357
-    {
358
-        global $wpdb;
359
-        return $wpdb->get_results(
360
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
361
-            ARRAY_A
362
-        );
363
-    }
364
-
365
-    /**
366
-     * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
367
-     *
368
-     * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
369
-     *               slashes at the end of the folder name.
370
-     */
371
-    public function get_data_migration_script_folders()
372
-    {
373
-        return apply_filters(
374
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
375
-            array('Core' => EE_CORE . 'data_migration_scripts')
376
-        );
377
-    }
378
-
379
-    /**
380
-     * Gets the version the migration script upgrades to
381
-     *
382
-     * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
383
-     * @return array {
384
-     * @type string  $slug                  like 'Core','Calendar',etc
385
-     * @type string  $version               like 4.3.0
386
-     *                                      }
387
-     * @throws EE_Error
388
-     */
389
-    public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
390
-    {
391
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
392
-            return $this->script_migration_versions[ $migration_script_name ];
393
-        }
394
-        $dms_info = $this->parse_dms_classname($migration_script_name);
395
-        $this->script_migration_versions[ $migration_script_name ] = array(
396
-            'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
397
-            'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
398
-        );
399
-        return $this->script_migration_versions[ $migration_script_name ];
400
-    }
401
-
402
-    /**
403
-     * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
404
-     *
405
-     * @param string $classname
406
-     * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints)
407
-     * @throws EE_Error
408
-     */
409
-    public function parse_dms_classname($classname)
410
-    {
411
-        $matches = array();
412
-        preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
413
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
414
-            throw new EE_Error(
415
-                sprintf(
416
-                    __(
417
-                        "%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, ",
418
-                        "event_espresso"
419
-                    ),
420
-                    $classname
421
-                )
422
-            );
423
-        }
424
-        return array(
425
-            'slug'          => $matches[1],
426
-            'major_version' => intval($matches[2]),
427
-            'minor_version' => intval($matches[3]),
428
-            'micro_version' => intval($matches[4]),
429
-        );
430
-    }
431
-
432
-    /**
433
-     * Ensures that the option indicating the current DB version is set. This should only be
434
-     * a concern when activating EE for the first time, THEORETICALLY.
435
-     * 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
436
-     * to 4.1.x.
437
-     *
438
-     * @return string of current db state
439
-     */
440
-    public function ensure_current_database_state_is_set()
441
-    {
442
-        $espresso_db_core_updates = get_option('espresso_db_update', array());
443
-        $db_state = get_option(EE_Data_Migration_Manager::current_database_state);
444
-        if (! $db_state) {
445
-            // mark the DB as being in the state as the last version in there.
446
-            // this is done to trigger maintenance mode and do data migration scripts
447
-            // if the admin installed this version of EE over 3.1.x or 4.0.x
448
-            // otherwise, the normal maintenance mode code is fine
449
-            $previous_versions_installed = array_keys($espresso_db_core_updates);
450
-            $previous_version_installed = end($previous_versions_installed);
451
-            if (version_compare('4.1.0', $previous_version_installed)) {
452
-                // last installed version was less than 4.1
453
-                // so we want the data migrations to happen. SO, we're going to say the DB is at that state
454
-                $db_state = array('Core' => $previous_version_installed);
455
-            } else {
456
-                $db_state = array('Core' => EVENT_ESPRESSO_VERSION);
457
-            }
458
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
459
-        }
460
-        // in 4.1, $db_state would have only been a simple string like '4.1.0',
461
-        // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
462
-        // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
463
-        if (! is_array($db_state)) {
464
-            $db_state = array('Core' => $db_state);
465
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
466
-        }
467
-        return $db_state;
468
-    }
469
-
470
-    /**
471
-     * Checks if there are any data migration scripts that ought to be run. If found,
472
-     * returns the instantiated classes. If none are found (ie, they've all already been run
473
-     * or they don't apply), returns an empty array
474
-     *
475
-     * @return EE_Data_Migration_Script_Base[]
476
-     */
477
-    public function check_for_applicable_data_migration_scripts()
478
-    {
479
-        // get the option describing what options have already run
480
-        $scripts_ran = $this->get_data_migrations_ran();
481
-        // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
482
-        $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
483
-
484
-
485
-        $current_database_state = $this->ensure_current_database_state_is_set();
486
-        // determine which have already been run
487
-        $script_classes_that_should_run_per_iteration = array();
488
-        $iteration = 0;
489
-        $next_database_state_to_consider = $current_database_state;
490
-        $theoretical_database_state = null;
491
-        do {
492
-            // the next state after the currently-considered one will start off looking the same as the current, but we may make additions...
493
-            $theoretical_database_state = $next_database_state_to_consider;
494
-            // the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?)
495
-            foreach ($script_class_and_filepaths_available as $classname => $filepath) {
496
-                $migrates_to_version = $this->script_migrates_to_version($classname);
497
-                $script_converts_plugin_slug = $migrates_to_version['slug'];
498
-                $script_converts_to_version = $migrates_to_version['version'];
499
-                // check if this version script is DONE or not; or if it's never been ran
500
-                if (! $scripts_ran ||
501
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
502
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
503
-                    // we haven't ran this conversion script before
504
-                    // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
505
-                    $script = new $classname($this->_get_table_manager(), $this->_get_table_analysis());
506
-                    /* @var $script EE_Data_Migration_Script_Base */
507
-                    $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
508
-                    if ($can_migrate) {
509
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
510
-                        $migrates_to_version = $script->migrates_to_version();
511
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
512
-                        unset($script_class_and_filepaths_available[ $classname ]);
513
-                    }
514
-                } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
515
-                    // this script has been ran, or at least started
516
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
517
-                    if ($script->get_status() != self::status_completed) {
518
-                        // this script is already underway... keep going with it
519
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
520
-                        $migrates_to_version = $script->migrates_to_version();
521
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
522
-                        unset($script_class_and_filepaths_available[ $classname ]);
523
-                    } else {
524
-                        // it must have a status that indicates it has finished, so we don't want to try and run it again
525
-                    }
526
-                } else {
527
-                    // it exists but it's not  a proper data migration script
528
-                    // maybe the script got renamed? or was simply removed from EE?
529
-                    // either way, its certainly not runnable!
530
-                }
531
-            }
532
-            $iteration++;
533
-        } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
534
-        // ok we have all the scripts that should run, now let's make them into flat array
535
-        $scripts_that_should_run = array();
536
-        foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
537
-            ksort($scripts_at_priority);
538
-            foreach ($scripts_at_priority as $scripts) {
539
-                foreach ($scripts as $script) {
540
-                    $scripts_that_should_run[ get_class($script) ] = $script;
541
-                }
542
-            }
543
-        }
544
-
545
-        do_action(
546
-            'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
547
-            $scripts_that_should_run
548
-        );
549
-        return $scripts_that_should_run;
550
-    }
551
-
552
-
553
-    /**
554
-     * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE
555
-     * it will return the last ran script even if its complete.
556
-     * This means: if you want to find the currently-executing script, leave it as FALSE.
557
-     * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
558
-     *
559
-     * @param bool $include_completed_scripts
560
-     * @return EE_Data_Migration_Script_Base
561
-     */
562
-    public function get_last_ran_script($include_completed_scripts = false)
563
-    {
564
-        // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
565
-        if (! $this->_data_migrations_ran) {
566
-            $this->get_data_migrations_ran();
567
-        }
568
-        if ($include_completed_scripts) {
569
-            return $this->_last_ran_script;
570
-        } else {
571
-            return $this->_last_ran_incomplete_script;
572
-        }
573
-    }
574
-
575
-
576
-    /**
577
-     * Runs the data migration scripts (well, each request to this method calls one of the
578
-     * data migration scripts' migration_step() functions).
579
-     *
580
-     * @param int   $step_size
581
-     * @throws EE_Error
582
-     * @return array {
583
-     *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
584
-     *                                  //and the second item is a string describing what was done
585
-     * @type int    $records_to_migrate from the current migration script
586
-     * @type int    $records_migrated
587
-     * @type string $status             one of EE_Data_Migration_Manager::status_*
588
-     * @type string $script             verbose name of the current DMS
589
-     * @type string $message            string describing what was done during this step
590
-     *                                  }
591
-     */
592
-    public function migration_step($step_size = 0)
593
-    {
594
-
595
-        // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
596
-        if (class_exists('EE_CPT_Strategy')) {
597
-            remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5);
598
-        }
599
-
600
-        try {
601
-            $currently_executing_script = $this->get_last_ran_script();
602
-            if (! $currently_executing_script) {
603
-                // Find the next script that needs to execute
604
-                $scripts = $this->check_for_applicable_data_migration_scripts();
605
-                if (! $scripts) {
606
-                    // huh, no more scripts to run... apparently we're done!
607
-                    // but dont forget to make sure initial data is there
608
-                    // we should be good to allow them to exit maintenance mode now
609
-                    EE_Maintenance_Mode::instance()->set_maintenance_level(
610
-                        intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
611
-                    );
612
-                    // saving migrations ran should actually be unnecessary, but leaving in place just in case
613
-                    // remember this migration was finished (even if we timeout initing db for core and plugins)
614
-                    $this->_save_migrations_ran();
615
-                    // make sure DB was updated AFTER we've recorded the migration was done
616
-                    $this->initialize_db_for_enqueued_ee_plugins();
617
-                    return array(
618
-                        'records_to_migrate' => 1,
619
-                        'records_migrated'   => 1,
620
-                        'status'             => self::status_no_more_migration_scripts,
621
-                        'script'             => __("Data Migration Completed Successfully", "event_espresso"),
622
-                        'message'            => __("All done!", "event_espresso"),
623
-                    );
624
-                }
625
-                $currently_executing_script = array_shift($scripts);
626
-                // and add to the array/wp option showing the scripts ran
627
-
628
-                $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
629
-                $plugin_slug = $migrates_to['slug'];
630
-                $version = $migrates_to['version'];
631
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
632
-            }
633
-            $current_script_name = get_class($currently_executing_script);
634
-        } catch (Exception $e) {
635
-            // an exception occurred while trying to get migration scripts
636
-
637
-            $message = sprintf(
638
-                __("Error Message: %sStack Trace:%s", "event_espresso"),
639
-                $e->getMessage() . '<br>',
640
-                $e->getTraceAsString()
641
-            );
642
-            // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
643
-            // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
644
-            $this->add_error_to_migrations_ran(
645
-                sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message)
646
-            );
647
-            return array(
648
-                'records_to_migrate' => 1,
649
-                'records_migrated'   => 0,
650
-                'status'             => self::status_fatal_error,
651
-                'script'             => __("Error loading data migration scripts", "event_espresso"),
652
-                'message'            => $message,
653
-            );
654
-        }
655
-        // ok so we definitely have a data migration script
656
-        try {
657
-            // how big of a bite do we want to take? Allow users to easily override via their wp-config
658
-            if (absint($step_size) < 1) {
659
-                $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
660
-                    ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
661
-            }
662
-            // do what we came to do!
663
-            $currently_executing_script->migration_step($step_size);
664
-            // can we wrap it up and verify default data?
665
-            $init_dbs = false;
666
-            switch ($currently_executing_script->get_status()) {
667
-                case EE_Data_Migration_Manager::status_continue:
668
-                    $response_array = array(
669
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
670
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
671
-                        'status'             => EE_Data_Migration_Manager::status_continue,
672
-                        'message'            => $currently_executing_script->get_feedback_message(),
673
-                        'script'             => $currently_executing_script->pretty_name(),
674
-                    );
675
-                    break;
676
-                case EE_Data_Migration_Manager::status_completed:
677
-                    // ok so THAT script has completed
678
-                    $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
679
-                    $response_array = array(
680
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
681
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
682
-                        'status'             => EE_Data_Migration_Manager::status_completed,
683
-                        'message'            => $currently_executing_script->get_feedback_message(),
684
-                        'script'             => sprintf(
685
-                            __("%s Completed", 'event_espresso'),
686
-                            $currently_executing_script->pretty_name()
687
-                        ),
688
-                    );
689
-                    // check if there are any more after this one.
690
-                    $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
691
-                    if (! $scripts_remaining) {
692
-                        // we should be good to allow them to exit maintenance mode now
693
-                        EE_Maintenance_Mode::instance()->set_maintenance_level(
694
-                            intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
695
-                        );
696
-                        // huh, no more scripts to run... apparently we're done!
697
-                        // but dont forget to make sure initial data is there
698
-                        $init_dbs = true;
699
-                        $response_array['status'] = self::status_no_more_migration_scripts;
700
-                    }
701
-                    break;
702
-                default:
703
-                    $response_array = array(
704
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
705
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
706
-                        'status'             => $currently_executing_script->get_status(),
707
-                        'message'            => sprintf(
708
-                            __("Minor errors occurred during %s: %s", "event_espresso"),
709
-                            $currently_executing_script->pretty_name(),
710
-                            implode(", ", $currently_executing_script->get_errors())
711
-                        ),
712
-                        'script'             => $currently_executing_script->pretty_name(),
713
-                    );
714
-                    break;
715
-            }
716
-        } catch (Exception $e) {
717
-            // ok so some exception was thrown which killed the data migration script
718
-            // double-check we have a real script
719
-            if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
720
-                $script_name = $currently_executing_script->pretty_name();
721
-                $currently_executing_script->set_broken();
722
-                $currently_executing_script->add_error($e->getMessage());
723
-            } else {
724
-                $script_name = __("Error getting Migration Script", "event_espresso");
725
-            }
726
-            $response_array = array(
727
-                'records_to_migrate' => 1,
728
-                'records_migrated'   => 0,
729
-                'status'             => self::status_fatal_error,
730
-                'message'            => sprintf(
731
-                    __("A fatal error occurred during the migration: %s", "event_espresso"),
732
-                    $e->getMessage()
733
-                ),
734
-                'script'             => $script_name,
735
-            );
736
-        }
737
-        $successful_save = $this->_save_migrations_ran();
738
-        if ($successful_save !== true) {
739
-            // ok so the current wp option didn't save. that's tricky, because we'd like to update it
740
-            // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
741
-            // however, if we throw an exception, and return that, then the next request
742
-            // won't have as much info in it, and it may be able to save
743
-            throw new EE_Error(
744
-                sprintf(
745
-                    __(
746
-                        "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.",
747
-                        "event_espresso"
748
-                    ),
749
-                    $successful_save
750
-                )
751
-            );
752
-        }
753
-        // if we're all done, initialize EE plugins' default data etc.
754
-        if ($init_dbs) {
755
-            $this->initialize_db_for_enqueued_ee_plugins();
756
-        }
757
-        return $response_array;
758
-    }
759
-
760
-
761
-    /**
762
-     * Echo out JSON response to migration script AJAX requests. Takes precautions
763
-     * to buffer output so that we don't throw junk into our json.
764
-     *
765
-     * @return array with keys:
766
-     * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
767
-     * it's NOT the count of hwo many remain)
768
-     * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
769
-     * records_migrated/records_to_migrate)
770
-     * 'status'=>a string, one of EE_Data_migration_Manager::status_*
771
-     * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
772
-     * errors, notifications, and successes
773
-     * 'script'=>a pretty name of the script currently running
774
-     */
775
-    public function response_to_migration_ajax_request()
776
-    {
777
-        ob_start();
778
-        try {
779
-            $response = $this->migration_step();
780
-        } catch (Exception $e) {
781
-            $response = array(
782
-                'records_to_migrate' => 0,
783
-                'records_migrated'   => 0,
784
-                'status'             => EE_Data_Migration_Manager::status_fatal_error,
785
-                'message'            => sprintf(
786
-                    __("Unknown fatal error occurred: %s", "event_espresso"),
787
-                    $e->getMessage()
788
-                ),
789
-                'script'             => 'Unknown',
790
-            );
791
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
792
-        }
793
-        $warnings_etc = @ob_get_contents();
794
-        ob_end_clean();
795
-        $response['message'] .= $warnings_etc;
796
-        return $response;
797
-    }
798
-
799
-    /**
800
-     * Updates the wordpress option that keeps track of which which EE version the database
801
-     * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
802
-     *
803
-     * @param array $slug_and_version {
804
-     * @type string $slug             like 'Core' or 'Calendar',
805
-     * @type string $version          like '4.1.0'
806
-     *                                }
807
-     * @return void
808
-     */
809
-    public function update_current_database_state_to($slug_and_version = null)
810
-    {
811
-        if (! $slug_and_version) {
812
-            // no version was provided, assume it should be at the current code version
813
-            $slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
814
-        }
815
-        $current_database_state = get_option(self::current_database_state);
816
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
817
-        update_option(self::current_database_state, $current_database_state);
818
-    }
819
-
820
-    /**
821
-     * Determines if the database is currently at a state matching what's indicated in $slug and $version.
822
-     *
823
-     * @param array $slug_and_version {
824
-     * @type string $slug             like 'Core' or 'Calendar',
825
-     * @type string $version          like '4.1.0'
826
-     *                                }
827
-     * @return boolean
828
-     */
829
-    public function database_needs_updating_to($slug_and_version)
830
-    {
831
-
832
-        $slug = $slug_and_version['slug'];
833
-        $version = $slug_and_version['version'];
834
-        $current_database_state = get_option(self::current_database_state);
835
-        if (! isset($current_database_state[ $slug ])) {
836
-            return true;
837
-        } else {
838
-            // 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
839
-            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
840
-            $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
841
-            $needs_updating = false;
842
-            foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
843
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
844
-                    $needs_updating = true;
845
-                    break;
846
-                }
847
-            }
848
-            return $needs_updating;
849
-        }
850
-    }
851
-
852
-
853
-    /**
854
-     * Gets all the data migration scripts available in the core folder and folders
855
-     * in addons. Has the side effect of adding them for autoloading
856
-     *
857
-     * @return array keys are expected classnames, values are their filepaths
858
-     * @throws InvalidInterfaceException
859
-     * @throws InvalidDataTypeException
860
-     * @throws EE_Error
861
-     * @throws InvalidArgumentException
862
-     */
863
-    public function get_all_data_migration_scripts_available()
864
-    {
865
-        if (! $this->_data_migration_class_to_filepath_map) {
866
-            $this->_data_migration_class_to_filepath_map = array();
867
-            foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
868
-                // strip any placeholders added to classname to make it a unique array key
869
-                $eeAddonClass = trim($eeAddonClass, '*');
870
-                $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
871
-                    ? $eeAddonClass
872
-                    : '';
873
-                $folder_path = EEH_File::end_with_directory_separator($folder_path);
874
-                $files = glob($folder_path . '*.dms.php');
875
-                if (empty($files)) {
876
-                    continue;
877
-                }
878
-                foreach ($files as $file) {
879
-                    $pos_of_last_slash = strrpos($file, DS);
880
-                    $classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
881
-                    $migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass);
882
-                    $slug = $migrates_to['slug'];
883
-                    // check that the slug as contained in the DMS is associated with
884
-                    // the slug of an addon or core
885
-                    if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
886
-                        EE_Error::doing_it_wrong(
887
-                            __FUNCTION__,
888
-                            sprintf(
889
-                                esc_html__(
890
-                                    'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
891
-                                    'event_espresso'
892
-                                ),
893
-                                $classname,
894
-                                $slug,
895
-                                implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
896
-                            ),
897
-                            '4.3.0.alpha.019'
898
-                        );
899
-                    }
900
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
901
-                }
902
-            }
903
-            EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
904
-        }
905
-        return $this->_data_migration_class_to_filepath_map;
906
-    }
907
-
908
-
909
-    /**
910
-     * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
911
-     * from each addon, and check if they need updating,
912
-     *
913
-     * @return boolean
914
-     */
915
-    public function addons_need_updating()
916
-    {
917
-        return false;
918
-    }
919
-
920
-    /**
921
-     * Adds this error string to the data_migrations_ran array, but we dont necessarily know
922
-     * where to put it, so we just throw it in there... better than nothing...
923
-     *
924
-     * @param string $error_message
925
-     * @throws EE_Error
926
-     */
927
-    public function add_error_to_migrations_ran($error_message)
928
-    {
929
-        // get last-ran migration script
930
-        global $wpdb;
931
-        $last_migration_script_option = $wpdb->get_row(
932
-            "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
933
-            ARRAY_A
934
-        );
935
-
936
-        $last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
937
-            ? maybe_unserialize($last_migration_script_option['option_value']) : null;
938
-        // now, tread lightly because we're here because a FATAL non-catchable error
939
-        // was thrown last time when we were trying to run a data migration script
940
-        // so the fatal error could have happened while getting the migration script
941
-        // or doing running it...
942
-        $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
943
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
944
-            "",
945
-            $last_migration_script_option['option_name']
946
-        ) : null;
947
-
948
-        // check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet
949
-        // because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done)
950
-        if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) {
951
-            // ok then just add this error to its list of errors
952
-            $last_ran_migration_script_properties['_errors'][] = $error_message;
953
-            $last_ran_migration_script_properties['_status'] = self::status_fatal_error;
954
-        } else {
955
-            // so we don't even know which script was last running
956
-            // use the data migration error stub, which is designed specifically for this type of thing
957
-            $general_migration_error = new EE_DMS_Unknown_1_0_0();
958
-            $general_migration_error->add_error($error_message);
959
-            $general_migration_error->set_broken();
960
-            $last_ran_migration_script_properties = $general_migration_error->properties_as_array();
961
-            $versions_migrated_to = 'Unknown.1.0.0';
962
-            // now just to make sure appears as last (in case the were previously a fatal error like this)
963
-            // delete the old one
964
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
965
-        }
966
-        update_option(
967
-            self::data_migration_script_option_prefix . $versions_migrated_to,
968
-            $last_ran_migration_script_properties
969
-        );
970
-    }
971
-
972
-    /**
973
-     * saves what data migrations have ran to the database
974
-     *
975
-     * @return mixed TRUE if successfully saved migrations ran, string if an error occurred
976
-     */
977
-    protected function _save_migrations_ran()
978
-    {
979
-        if ($this->_data_migrations_ran == null) {
980
-            $this->get_data_migrations_ran();
981
-        }
982
-        // now, we don't want to save actual classes to the DB because that's messy
983
-        $successful_updates = true;
984
-        foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
985
-            foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
986
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
987
-                $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
988
-                $old_option_value = get_option($option_name);
989
-                if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
990
-                    $script_array_for_saving = $array_or_migration_obj->properties_as_array();
991
-                    if ($old_option_value != $script_array_for_saving) {
992
-                        $successful_updates = update_option($option_name, $script_array_for_saving);
993
-                    }
994
-                } else {// we don't know what this array-thing is. So just save it as-is
995
-                    if ($old_option_value != $array_or_migration_obj) {
996
-                        $successful_updates = update_option($option_name, $array_or_migration_obj);
997
-                    }
998
-                }
999
-                if (! $successful_updates) {
1000
-                    global $wpdb;
1001
-                    return $wpdb->last_error;
1002
-                }
1003
-            }
1004
-        }
1005
-        return true;
1006
-        // $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1007
-        // if ($updated !== true) {
1008
-        //     global $wpdb;
1009
-        //     return $wpdb->last_error;
1010
-        // } else {
1011
-        //     return true;
1012
-        // }
1013
-        // wp_mail(
1014
-        //     "[email protected]",
1015
-        //     time() . " price debug info",
1016
-        //     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1017
-        //         serialize($array_of_migrations)
1018
-        //     )
1019
-        // );
1020
-    }
1021
-
1022
-    /**
1023
-     * Takes an array of data migration script properties and re-creates the class from
1024
-     * them. The argument $properties_array is assumed to have been made by
1025
-     * EE_Data_Migration_Script_Base::properties_as_array()
1026
-     *
1027
-     * @param array $properties_array
1028
-     * @return EE_Data_Migration_Script_Base
1029
-     * @throws EE_Error
1030
-     */
1031
-    public function _instantiate_script_from_properties_array($properties_array)
1032
-    {
1033
-        if (! isset($properties_array['class'])) {
1034
-            throw new EE_Error(
1035
-                sprintf(
1036
-                    __("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1037
-                    implode(",", $properties_array)
1038
-                )
1039
-            );
1040
-        }
1041
-        $class_name = $properties_array['class'];
1042
-        if (! class_exists($class_name)) {
1043
-            throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1044
-        }
1045
-        $class = new $class_name;
1046
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1047
-            throw new EE_Error(
1048
-                sprintf(
1049
-                    __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
1050
-                    $class_name,
1051
-                    get_class($class)
1052
-                )
1053
-            );
1054
-        }
1055
-        $class->instantiate_from_array_of_properties($properties_array);
1056
-        return $class;
1057
-    }
1058
-
1059
-    /**
1060
-     * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1061
-     * leave the DB in a state usable by the current plugin code).
1062
-     *
1063
-     * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1064
-     * @return string
1065
-     */
1066
-    public function get_most_up_to_date_dms($plugin_slug = 'Core')
1067
-    {
1068
-        $class_to_filepath_map = $this->get_all_data_migration_scripts_available();
1069
-        $most_up_to_date_dms_classname = null;
1070
-        foreach ($class_to_filepath_map as $classname => $filepath) {
1071
-            if ($most_up_to_date_dms_classname === null) {
1072
-                $migrates_to = $this->script_migrates_to_version($classname);
1073
-                $this_plugin_slug = $migrates_to['slug'];
1074
-                if ($this_plugin_slug == $plugin_slug) {
1075
-                    // if it's for core, it wins
1076
-                    $most_up_to_date_dms_classname = $classname;
1077
-                }
1078
-                // if it wasn't for core, we must keep searching for one that is!
1079
-                continue;
1080
-            } else {
1081
-                $champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1082
-                $contender_migrates_to = $this->script_migrates_to_version($classname);
1083
-                if ($contender_migrates_to['slug'] == $plugin_slug
1084
-                    && version_compare(
1085
-                        $champion_migrates_to['version'],
1086
-                        $contender_migrates_to['version'],
1087
-                        '<'
1088
-                    )) {
1089
-                    // so the contenders version is higher and its for Core
1090
-                    $most_up_to_date_dms_classname = $classname;
1091
-                }
1092
-            }
1093
-        }
1094
-        return $most_up_to_date_dms_classname;
1095
-    }
1096
-
1097
-    /**
1098
-     * Gets the migration script specified but ONLY if it has already ran.
1099
-     *
1100
-     * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code:
1101
-     * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1102
-     * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1103
-     * other addon) DMS has ran, in case the current DMS depends on it.
1104
-     *
1105
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1106
-     *                            period. Eg '4.1.0'
1107
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1108
-     * @return EE_Data_Migration_Script_Base
1109
-     */
1110
-    public function get_migration_ran($version, $plugin_slug = 'Core')
1111
-    {
1112
-        $migrations_ran = $this->get_data_migrations_ran();
1113
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1114
-            return $migrations_ran[ $plugin_slug ][ $version ];
1115
-        } else {
1116
-            return null;
1117
-        }
1118
-    }
1119
-
1120
-    /**
1121
-     * Resets the borked data migration scripts so they're no longer borked
1122
-     * so we can again attempt to migrate
1123
-     *
1124
-     * @return bool
1125
-     * @throws EE_Error
1126
-     */
1127
-    public function reattempt()
1128
-    {
1129
-        // find if the last-ran script was borked
1130
-        // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1131
-        // add an 'error' saying that we attempted to reset
1132
-        // does it have a stage that was borked too? if so make it no longer borked
1133
-        // add an 'error' saying we attempted to reset
1134
-        $last_ran_script = $this->get_last_ran_script();
1135
-        if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1136
-            // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1137
-            $last_ran_script->set_completed();
1138
-        } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1139
-            $last_ran_script->reattempt();
1140
-        } else {
1141
-            throw new EE_Error(
1142
-                sprintf(
1143
-                    __(
1144
-                        'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1145
-                        'event_espresso'
1146
-                    ),
1147
-                    print_r($last_ran_script, true)
1148
-                )
1149
-            );
1150
-        }
1151
-        return $this->_save_migrations_ran();
1152
-    }
1153
-
1154
-    /**
1155
-     * Gets whether or not this particular migration has run or not
1156
-     *
1157
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1158
-     *                            period. Eg '4.1.0'
1159
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1160
-     * @return boolean
1161
-     */
1162
-    public function migration_has_ran($version, $plugin_slug = 'Core')
1163
-    {
1164
-        return $this->get_migration_ran($version, $plugin_slug) !== null;
1165
-    }
1166
-
1167
-    /**
1168
-     * Enqueues this ee plugin to have its data initialized
1169
-     *
1170
-     * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1171
-     */
1172
-    public function enqueue_db_initialization_for($plugin_slug)
1173
-    {
1174
-        $queue = $this->get_db_initialization_queue();
1175
-        if (! in_array($plugin_slug, $queue)) {
1176
-            $queue[] = $plugin_slug;
1177
-        }
1178
-        update_option(self::db_init_queue_option_name, $queue);
1179
-    }
1180
-
1181
-    /**
1182
-     * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1183
-     * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1184
-     * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1185
-     */
1186
-    public function initialize_db_for_enqueued_ee_plugins()
1187
-    {
1188
-        $queue = $this->get_db_initialization_queue();
1189
-        foreach ($queue as $plugin_slug) {
1190
-            $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1191
-            if (! $most_up_to_date_dms) {
1192
-                // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1193
-                $verify_db = false;
1194
-            } else {
1195
-                $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1196
-                $verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1197
-            }
1198
-            if ($plugin_slug == 'Core') {
1199
-                EE_System::instance()->initialize_db_if_no_migrations_required(
1200
-                    false,
1201
-                    $verify_db
1202
-                );
1203
-            } else {
1204
-                // just loop through the addons to make sure their database is setup
1205
-                foreach (EE_Registry::instance()->addons as $addon) {
1206
-                    if ($addon->name() == $plugin_slug) {
1207
-                        $addon->initialize_db_if_no_migrations_required($verify_db);
1208
-                        break;
1209
-                    }
1210
-                }
1211
-            }
1212
-        }
1213
-        // because we just initialized the DBs for the enqueued ee plugins
1214
-        // we don't need to keep remembering which ones needed to be initialized
1215
-        delete_option(self::db_init_queue_option_name);
1216
-    }
1217
-
1218
-    /**
1219
-     * Gets a numerically-indexed array of plugin slugs that need to have their databases
1220
-     * (re-)initialized after migrations are complete. ie, each element should be either
1221
-     * 'Core', or the return value of EE_Addon::name() for an addon
1222
-     *
1223
-     * @return array
1224
-     */
1225
-    public function get_db_initialization_queue()
1226
-    {
1227
-        return get_option(self::db_init_queue_option_name, array());
1228
-    }
1229
-
1230
-    /**
1231
-     * Gets the injected table analyzer, or throws an exception
1232
-     *
1233
-     * @return TableAnalysis
1234
-     * @throws EE_Error
1235
-     */
1236
-    protected function _get_table_analysis()
1237
-    {
1238
-        if ($this->_table_analysis instanceof TableAnalysis) {
1239
-            return $this->_table_analysis;
1240
-        } else {
1241
-            throw new EE_Error(
1242
-                sprintf(
1243
-                    __('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1244
-                    get_class($this)
1245
-                )
1246
-            );
1247
-        }
1248
-    }
1249
-
1250
-    /**
1251
-     * Gets the injected table manager, or throws an exception
1252
-     *
1253
-     * @return TableManager
1254
-     * @throws EE_Error
1255
-     */
1256
-    protected function _get_table_manager()
1257
-    {
1258
-        if ($this->_table_manager instanceof TableManager) {
1259
-            return $this->_table_manager;
1260
-        } else {
1261
-            throw new EE_Error(
1262
-                sprintf(
1263
-                    __('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1264
-                    get_class($this)
1265
-                )
1266
-            );
1267
-        }
1268
-    }
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
+	 * string indicating the migration should continue
63
+	 */
64
+	const status_continue = 'status_continue';
65
+	/**
66
+	 * string indicating the migration has completed and should be ended
67
+	 */
68
+	const status_completed = 'status_completed';
69
+	/**
70
+	 * string indicating a fatal error occurred and the data migration should be completely aborted
71
+	 */
72
+	const status_fatal_error = 'status_fatal_error';
73
+
74
+	/**
75
+	 * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
76
+	 * during migration)
77
+	 */
78
+	const step_size = 50;
79
+
80
+	/**
81
+	 * option name that stores the queue of ee plugins needing to have
82
+	 * their data initialized (or re-initialized) once we are done migrations
83
+	 */
84
+	const db_init_queue_option_name = 'ee_db_init_queue';
85
+	/**
86
+	 * Array of information concerning data migrations that have ran in the history
87
+	 * of this EE installation. Keys should be the name of the version the script upgraded to
88
+	 *
89
+	 * @var EE_Data_Migration_Script_Base[]
90
+	 */
91
+	private $_data_migrations_ran = null;
92
+	/**
93
+	 * The last ran script. It's nice to store this somewhere accessible, as its easiest
94
+	 * to know which was the last run by which is the newest wp option; but in most of the code
95
+	 * we just use the local $_data_migration_ran array, which organized the scripts differently
96
+	 *
97
+	 * @var EE_Data_Migration_Script_Base
98
+	 */
99
+	private $_last_ran_script = null;
100
+
101
+	/**
102
+	 * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
103
+	 *
104
+	 * @var EE_Data_Migration_Script_Base
105
+	 */
106
+	private $_last_ran_incomplete_script = null;
107
+	/**
108
+	 * array where keys are classnames, and values are filepaths of all the known migration scripts
109
+	 *
110
+	 * @var array
111
+	 */
112
+	private $_data_migration_class_to_filepath_map;
113
+
114
+	/**
115
+	 * the following 4 properties are fully set on construction.
116
+	 * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
117
+	 * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
118
+	 * data migration script
119
+	 *
120
+	 * @var array
121
+	 */
122
+	public $stati_that_indicate_to_continue_migrations = array();
123
+
124
+	public $stati_that_indicate_to_stop_migrations = array();
125
+
126
+	public $stati_that_indicate_to_continue_single_migration_script = array();
127
+
128
+	public $stati_that_indicate_to_stop_single_migration_script = array();
129
+
130
+	/**
131
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
132
+	 */
133
+	protected $_table_manager;
134
+
135
+	/**
136
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
137
+	 */
138
+	protected $_table_analysis;
139
+
140
+	/**
141
+	 * @var array $script_migration_versions
142
+	 */
143
+	protected $script_migration_versions;
144
+
145
+	/**
146
+	 * @var EE_Data_Migration_Manager $_instance
147
+	 * @access    private
148
+	 */
149
+	private static $_instance = null;
150
+
151
+
152
+	/**
153
+	 * @singleton method used to instantiate class object
154
+	 * @access    public
155
+	 * @return EE_Data_Migration_Manager instance
156
+	 */
157
+	public static function instance()
158
+	{
159
+		// check if class object is instantiated
160
+		if (! self::$_instance instanceof EE_Data_Migration_Manager) {
161
+			self::$_instance = new self();
162
+		}
163
+		return self::$_instance;
164
+	}
165
+
166
+	/**
167
+	 * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
168
+	 * all new usages of the singleton should be made with Classname::instance()) and returns it
169
+	 *
170
+	 * @return EE_Data_Migration_Manager
171
+	 */
172
+	public static function reset()
173
+	{
174
+		self::$_instance = null;
175
+		return self::instance();
176
+	}
177
+
178
+
179
+	/**
180
+	 * constructor
181
+	 */
182
+	private function __construct()
183
+	{
184
+		$this->stati_that_indicate_to_continue_migrations = array(
185
+			self::status_continue,
186
+			self::status_completed,
187
+		);
188
+		$this->stati_that_indicate_to_stop_migrations = array(
189
+			self::status_fatal_error,
190
+			self::status_no_more_migration_scripts,
191
+		);
192
+		$this->stati_that_indicate_to_continue_single_migration_script = array(
193
+			self::status_continue,
194
+		);
195
+		$this->stati_that_indicate_to_stop_single_migration_script = array(
196
+			self::status_completed,
197
+			self::status_fatal_error
198
+			// note: status_no_more_migration_scripts doesn't apply
199
+		);
200
+		// make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
201
+		// to be defined, because right now it doesn't get autoloaded on its own
202
+		EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true);
203
+		EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true);
204
+		EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true);
205
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true);
206
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true);
207
+		$this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true);
208
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
209
+	}
210
+
211
+
212
+	/**
213
+	 * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
214
+	 * the option names are like, but generally they're like
215
+	 * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
216
+	 * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
217
+	 * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg
218
+	 * EE_DMS_Core_4_1_0.dms.php)
219
+	 *
220
+	 * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
221
+	 * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of
222
+	 *               that plugin (eg '4.1.0')
223
+	 */
224
+	private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
225
+	{
226
+		$plugin_slug_and_version_string = str_replace(
227
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
228
+			"",
229
+			$option_name
230
+		);
231
+		// check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
232
+		$parts = explode(".", $plugin_slug_and_version_string);
233
+
234
+		if (count($parts) == 4) {
235
+			// it's 4.2-style.eg Core.4.1.0
236
+			$plugin_slug = $parts[0];// eg Core
237
+			$version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
238
+		} else {
239
+			// it's 4.1-style: eg 4.1.0
240
+			$plugin_slug = 'Core';
241
+			$version_string = $plugin_slug_and_version_string;// eg 4.1.0
242
+		}
243
+		return array($plugin_slug, $version_string);
244
+	}
245
+
246
+	/**
247
+	 * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not
248
+	 * for a known DMS class.
249
+	 *
250
+	 * @param string $dms_option_name
251
+	 * @param string $dms_option_value (serialized)
252
+	 * @return EE_Data_Migration_Script_Base
253
+	 * @throws EE_Error
254
+	 */
255
+	private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
256
+	{
257
+		$data_migration_data = maybe_unserialize($dms_option_value);
258
+		if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
259
+			$class = new $data_migration_data['class'];
260
+			if ($class instanceof EE_Data_Migration_Script_Base) {
261
+				$class->instantiate_from_array_of_properties($data_migration_data);
262
+				return $class;
263
+			} else {
264
+				// huh, so its an object but not a data migration script?? that shouldn't happen
265
+				// just leave it as an array (which will probably just get ignored)
266
+				throw new EE_Error(
267
+					sprintf(
268
+						__(
269
+							"Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
270
+							'event_espresso'
271
+						),
272
+						$data_migration_data['class']
273
+					)
274
+				);
275
+			}
276
+		} else {
277
+			// 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
278
+			throw new EE_Error(
279
+				sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name)
280
+			);
281
+		}
282
+	}
283
+
284
+	/**
285
+	 * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last
286
+	 * ran, and which was the last ran which hasn't finished yet
287
+	 *
288
+	 * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy
289
+	 *               arrays in there - which should probably be ignored)
290
+	 */
291
+	public function get_data_migrations_ran()
292
+	{
293
+		if (! $this->_data_migrations_ran) {
294
+			// setup autoloaders for each of the scripts in there
295
+			$this->get_all_data_migration_scripts_available();
296
+			$data_migrations_options = $this->get_all_migration_script_options(
297
+			);// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
298
+
299
+			$data_migrations_ran = array();
300
+			// convert into data migration script classes where possible
301
+			foreach ($data_migrations_options as $data_migration_option) {
302
+				list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
303
+					$data_migration_option['option_name']
304
+				);
305
+
306
+				try {
307
+					$class = $this->_get_dms_class_from_wp_option(
308
+						$data_migration_option['option_name'],
309
+						$data_migration_option['option_value']
310
+					);
311
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
312
+					// ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
313
+					$this->_last_ran_script = $class;
314
+					if (! $class->is_completed()) {
315
+						// sometimes we also like to know which was the last incomplete script (or if there are any at all)
316
+						$this->_last_ran_incomplete_script = $class;
317
+					}
318
+				} catch (EE_Error $e) {
319
+					// ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
320
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
321
+						$data_migration_option['option_value']
322
+					);
323
+				}
324
+			}
325
+			// so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
326
+			$this->_data_migrations_ran = $data_migrations_ran;
327
+			if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
328
+				$this->_data_migrations_ran = array();
329
+			}
330
+		}
331
+		return $this->_data_migrations_ran;
332
+	}
333
+
334
+
335
+	/**
336
+	 *
337
+	 * @param string $script_name eg 'DMS_Core_4_1_0'
338
+	 * @param string $old_table   eg 'wp_events_detail'
339
+	 * @param string $old_pk      eg 'wp_esp_posts'
340
+	 * @param        $new_table
341
+	 * @return mixed string or int
342
+	 */
343
+	public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
344
+	{
345
+		$script = EE_Registry::instance()->load_dms($script_name);
346
+		$mapping = $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
347
+		return $mapping;
348
+	}
349
+
350
+	/**
351
+	 * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
352
+	 * the last option returned in this array is the most-recently ran DMS option
353
+	 *
354
+	 * @return array
355
+	 */
356
+	public function get_all_migration_script_options()
357
+	{
358
+		global $wpdb;
359
+		return $wpdb->get_results(
360
+			"SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
361
+			ARRAY_A
362
+		);
363
+	}
364
+
365
+	/**
366
+	 * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
367
+	 *
368
+	 * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
369
+	 *               slashes at the end of the folder name.
370
+	 */
371
+	public function get_data_migration_script_folders()
372
+	{
373
+		return apply_filters(
374
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
375
+			array('Core' => EE_CORE . 'data_migration_scripts')
376
+		);
377
+	}
378
+
379
+	/**
380
+	 * Gets the version the migration script upgrades to
381
+	 *
382
+	 * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
383
+	 * @return array {
384
+	 * @type string  $slug                  like 'Core','Calendar',etc
385
+	 * @type string  $version               like 4.3.0
386
+	 *                                      }
387
+	 * @throws EE_Error
388
+	 */
389
+	public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
390
+	{
391
+		if (isset($this->script_migration_versions[ $migration_script_name ])) {
392
+			return $this->script_migration_versions[ $migration_script_name ];
393
+		}
394
+		$dms_info = $this->parse_dms_classname($migration_script_name);
395
+		$this->script_migration_versions[ $migration_script_name ] = array(
396
+			'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
397
+			'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
398
+		);
399
+		return $this->script_migration_versions[ $migration_script_name ];
400
+	}
401
+
402
+	/**
403
+	 * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
404
+	 *
405
+	 * @param string $classname
406
+	 * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints)
407
+	 * @throws EE_Error
408
+	 */
409
+	public function parse_dms_classname($classname)
410
+	{
411
+		$matches = array();
412
+		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
413
+		if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
414
+			throw new EE_Error(
415
+				sprintf(
416
+					__(
417
+						"%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, ",
418
+						"event_espresso"
419
+					),
420
+					$classname
421
+				)
422
+			);
423
+		}
424
+		return array(
425
+			'slug'          => $matches[1],
426
+			'major_version' => intval($matches[2]),
427
+			'minor_version' => intval($matches[3]),
428
+			'micro_version' => intval($matches[4]),
429
+		);
430
+	}
431
+
432
+	/**
433
+	 * Ensures that the option indicating the current DB version is set. This should only be
434
+	 * a concern when activating EE for the first time, THEORETICALLY.
435
+	 * 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
436
+	 * to 4.1.x.
437
+	 *
438
+	 * @return string of current db state
439
+	 */
440
+	public function ensure_current_database_state_is_set()
441
+	{
442
+		$espresso_db_core_updates = get_option('espresso_db_update', array());
443
+		$db_state = get_option(EE_Data_Migration_Manager::current_database_state);
444
+		if (! $db_state) {
445
+			// mark the DB as being in the state as the last version in there.
446
+			// this is done to trigger maintenance mode and do data migration scripts
447
+			// if the admin installed this version of EE over 3.1.x or 4.0.x
448
+			// otherwise, the normal maintenance mode code is fine
449
+			$previous_versions_installed = array_keys($espresso_db_core_updates);
450
+			$previous_version_installed = end($previous_versions_installed);
451
+			if (version_compare('4.1.0', $previous_version_installed)) {
452
+				// last installed version was less than 4.1
453
+				// so we want the data migrations to happen. SO, we're going to say the DB is at that state
454
+				$db_state = array('Core' => $previous_version_installed);
455
+			} else {
456
+				$db_state = array('Core' => EVENT_ESPRESSO_VERSION);
457
+			}
458
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
459
+		}
460
+		// in 4.1, $db_state would have only been a simple string like '4.1.0',
461
+		// but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
462
+		// db, and possibly other keys for other addons like 'Calendar','Permissions',etc
463
+		if (! is_array($db_state)) {
464
+			$db_state = array('Core' => $db_state);
465
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
466
+		}
467
+		return $db_state;
468
+	}
469
+
470
+	/**
471
+	 * Checks if there are any data migration scripts that ought to be run. If found,
472
+	 * returns the instantiated classes. If none are found (ie, they've all already been run
473
+	 * or they don't apply), returns an empty array
474
+	 *
475
+	 * @return EE_Data_Migration_Script_Base[]
476
+	 */
477
+	public function check_for_applicable_data_migration_scripts()
478
+	{
479
+		// get the option describing what options have already run
480
+		$scripts_ran = $this->get_data_migrations_ran();
481
+		// $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
482
+		$script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
483
+
484
+
485
+		$current_database_state = $this->ensure_current_database_state_is_set();
486
+		// determine which have already been run
487
+		$script_classes_that_should_run_per_iteration = array();
488
+		$iteration = 0;
489
+		$next_database_state_to_consider = $current_database_state;
490
+		$theoretical_database_state = null;
491
+		do {
492
+			// the next state after the currently-considered one will start off looking the same as the current, but we may make additions...
493
+			$theoretical_database_state = $next_database_state_to_consider;
494
+			// the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?)
495
+			foreach ($script_class_and_filepaths_available as $classname => $filepath) {
496
+				$migrates_to_version = $this->script_migrates_to_version($classname);
497
+				$script_converts_plugin_slug = $migrates_to_version['slug'];
498
+				$script_converts_to_version = $migrates_to_version['version'];
499
+				// check if this version script is DONE or not; or if it's never been ran
500
+				if (! $scripts_ran ||
501
+					! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
502
+					! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
503
+					// we haven't ran this conversion script before
504
+					// now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
505
+					$script = new $classname($this->_get_table_manager(), $this->_get_table_analysis());
506
+					/* @var $script EE_Data_Migration_Script_Base */
507
+					$can_migrate = $script->can_migrate_from_version($theoretical_database_state);
508
+					if ($can_migrate) {
509
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
510
+						$migrates_to_version = $script->migrates_to_version();
511
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
512
+						unset($script_class_and_filepaths_available[ $classname ]);
513
+					}
514
+				} elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
515
+					// this script has been ran, or at least started
516
+					$script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
517
+					if ($script->get_status() != self::status_completed) {
518
+						// this script is already underway... keep going with it
519
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
520
+						$migrates_to_version = $script->migrates_to_version();
521
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
522
+						unset($script_class_and_filepaths_available[ $classname ]);
523
+					} else {
524
+						// it must have a status that indicates it has finished, so we don't want to try and run it again
525
+					}
526
+				} else {
527
+					// it exists but it's not  a proper data migration script
528
+					// maybe the script got renamed? or was simply removed from EE?
529
+					// either way, its certainly not runnable!
530
+				}
531
+			}
532
+			$iteration++;
533
+		} while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
534
+		// ok we have all the scripts that should run, now let's make them into flat array
535
+		$scripts_that_should_run = array();
536
+		foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
537
+			ksort($scripts_at_priority);
538
+			foreach ($scripts_at_priority as $scripts) {
539
+				foreach ($scripts as $script) {
540
+					$scripts_that_should_run[ get_class($script) ] = $script;
541
+				}
542
+			}
543
+		}
544
+
545
+		do_action(
546
+			'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
547
+			$scripts_that_should_run
548
+		);
549
+		return $scripts_that_should_run;
550
+	}
551
+
552
+
553
+	/**
554
+	 * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE
555
+	 * it will return the last ran script even if its complete.
556
+	 * This means: if you want to find the currently-executing script, leave it as FALSE.
557
+	 * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
558
+	 *
559
+	 * @param bool $include_completed_scripts
560
+	 * @return EE_Data_Migration_Script_Base
561
+	 */
562
+	public function get_last_ran_script($include_completed_scripts = false)
563
+	{
564
+		// make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
565
+		if (! $this->_data_migrations_ran) {
566
+			$this->get_data_migrations_ran();
567
+		}
568
+		if ($include_completed_scripts) {
569
+			return $this->_last_ran_script;
570
+		} else {
571
+			return $this->_last_ran_incomplete_script;
572
+		}
573
+	}
574
+
575
+
576
+	/**
577
+	 * Runs the data migration scripts (well, each request to this method calls one of the
578
+	 * data migration scripts' migration_step() functions).
579
+	 *
580
+	 * @param int   $step_size
581
+	 * @throws EE_Error
582
+	 * @return array {
583
+	 *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
584
+	 *                                  //and the second item is a string describing what was done
585
+	 * @type int    $records_to_migrate from the current migration script
586
+	 * @type int    $records_migrated
587
+	 * @type string $status             one of EE_Data_Migration_Manager::status_*
588
+	 * @type string $script             verbose name of the current DMS
589
+	 * @type string $message            string describing what was done during this step
590
+	 *                                  }
591
+	 */
592
+	public function migration_step($step_size = 0)
593
+	{
594
+
595
+		// bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
596
+		if (class_exists('EE_CPT_Strategy')) {
597
+			remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5);
598
+		}
599
+
600
+		try {
601
+			$currently_executing_script = $this->get_last_ran_script();
602
+			if (! $currently_executing_script) {
603
+				// Find the next script that needs to execute
604
+				$scripts = $this->check_for_applicable_data_migration_scripts();
605
+				if (! $scripts) {
606
+					// huh, no more scripts to run... apparently we're done!
607
+					// but dont forget to make sure initial data is there
608
+					// we should be good to allow them to exit maintenance mode now
609
+					EE_Maintenance_Mode::instance()->set_maintenance_level(
610
+						intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
611
+					);
612
+					// saving migrations ran should actually be unnecessary, but leaving in place just in case
613
+					// remember this migration was finished (even if we timeout initing db for core and plugins)
614
+					$this->_save_migrations_ran();
615
+					// make sure DB was updated AFTER we've recorded the migration was done
616
+					$this->initialize_db_for_enqueued_ee_plugins();
617
+					return array(
618
+						'records_to_migrate' => 1,
619
+						'records_migrated'   => 1,
620
+						'status'             => self::status_no_more_migration_scripts,
621
+						'script'             => __("Data Migration Completed Successfully", "event_espresso"),
622
+						'message'            => __("All done!", "event_espresso"),
623
+					);
624
+				}
625
+				$currently_executing_script = array_shift($scripts);
626
+				// and add to the array/wp option showing the scripts ran
627
+
628
+				$migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
629
+				$plugin_slug = $migrates_to['slug'];
630
+				$version = $migrates_to['version'];
631
+				$this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
632
+			}
633
+			$current_script_name = get_class($currently_executing_script);
634
+		} catch (Exception $e) {
635
+			// an exception occurred while trying to get migration scripts
636
+
637
+			$message = sprintf(
638
+				__("Error Message: %sStack Trace:%s", "event_espresso"),
639
+				$e->getMessage() . '<br>',
640
+				$e->getTraceAsString()
641
+			);
642
+			// record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
643
+			// but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
644
+			$this->add_error_to_migrations_ran(
645
+				sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message)
646
+			);
647
+			return array(
648
+				'records_to_migrate' => 1,
649
+				'records_migrated'   => 0,
650
+				'status'             => self::status_fatal_error,
651
+				'script'             => __("Error loading data migration scripts", "event_espresso"),
652
+				'message'            => $message,
653
+			);
654
+		}
655
+		// ok so we definitely have a data migration script
656
+		try {
657
+			// how big of a bite do we want to take? Allow users to easily override via their wp-config
658
+			if (absint($step_size) < 1) {
659
+				$step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
660
+					? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
661
+			}
662
+			// do what we came to do!
663
+			$currently_executing_script->migration_step($step_size);
664
+			// can we wrap it up and verify default data?
665
+			$init_dbs = false;
666
+			switch ($currently_executing_script->get_status()) {
667
+				case EE_Data_Migration_Manager::status_continue:
668
+					$response_array = array(
669
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
670
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
671
+						'status'             => EE_Data_Migration_Manager::status_continue,
672
+						'message'            => $currently_executing_script->get_feedback_message(),
673
+						'script'             => $currently_executing_script->pretty_name(),
674
+					);
675
+					break;
676
+				case EE_Data_Migration_Manager::status_completed:
677
+					// ok so THAT script has completed
678
+					$this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
679
+					$response_array = array(
680
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
681
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
682
+						'status'             => EE_Data_Migration_Manager::status_completed,
683
+						'message'            => $currently_executing_script->get_feedback_message(),
684
+						'script'             => sprintf(
685
+							__("%s Completed", 'event_espresso'),
686
+							$currently_executing_script->pretty_name()
687
+						),
688
+					);
689
+					// check if there are any more after this one.
690
+					$scripts_remaining = $this->check_for_applicable_data_migration_scripts();
691
+					if (! $scripts_remaining) {
692
+						// we should be good to allow them to exit maintenance mode now
693
+						EE_Maintenance_Mode::instance()->set_maintenance_level(
694
+							intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
695
+						);
696
+						// huh, no more scripts to run... apparently we're done!
697
+						// but dont forget to make sure initial data is there
698
+						$init_dbs = true;
699
+						$response_array['status'] = self::status_no_more_migration_scripts;
700
+					}
701
+					break;
702
+				default:
703
+					$response_array = array(
704
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
705
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
706
+						'status'             => $currently_executing_script->get_status(),
707
+						'message'            => sprintf(
708
+							__("Minor errors occurred during %s: %s", "event_espresso"),
709
+							$currently_executing_script->pretty_name(),
710
+							implode(", ", $currently_executing_script->get_errors())
711
+						),
712
+						'script'             => $currently_executing_script->pretty_name(),
713
+					);
714
+					break;
715
+			}
716
+		} catch (Exception $e) {
717
+			// ok so some exception was thrown which killed the data migration script
718
+			// double-check we have a real script
719
+			if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
720
+				$script_name = $currently_executing_script->pretty_name();
721
+				$currently_executing_script->set_broken();
722
+				$currently_executing_script->add_error($e->getMessage());
723
+			} else {
724
+				$script_name = __("Error getting Migration Script", "event_espresso");
725
+			}
726
+			$response_array = array(
727
+				'records_to_migrate' => 1,
728
+				'records_migrated'   => 0,
729
+				'status'             => self::status_fatal_error,
730
+				'message'            => sprintf(
731
+					__("A fatal error occurred during the migration: %s", "event_espresso"),
732
+					$e->getMessage()
733
+				),
734
+				'script'             => $script_name,
735
+			);
736
+		}
737
+		$successful_save = $this->_save_migrations_ran();
738
+		if ($successful_save !== true) {
739
+			// ok so the current wp option didn't save. that's tricky, because we'd like to update it
740
+			// and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
741
+			// however, if we throw an exception, and return that, then the next request
742
+			// won't have as much info in it, and it may be able to save
743
+			throw new EE_Error(
744
+				sprintf(
745
+					__(
746
+						"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.",
747
+						"event_espresso"
748
+					),
749
+					$successful_save
750
+				)
751
+			);
752
+		}
753
+		// if we're all done, initialize EE plugins' default data etc.
754
+		if ($init_dbs) {
755
+			$this->initialize_db_for_enqueued_ee_plugins();
756
+		}
757
+		return $response_array;
758
+	}
759
+
760
+
761
+	/**
762
+	 * Echo out JSON response to migration script AJAX requests. Takes precautions
763
+	 * to buffer output so that we don't throw junk into our json.
764
+	 *
765
+	 * @return array with keys:
766
+	 * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
767
+	 * it's NOT the count of hwo many remain)
768
+	 * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
769
+	 * records_migrated/records_to_migrate)
770
+	 * 'status'=>a string, one of EE_Data_migration_Manager::status_*
771
+	 * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
772
+	 * errors, notifications, and successes
773
+	 * 'script'=>a pretty name of the script currently running
774
+	 */
775
+	public function response_to_migration_ajax_request()
776
+	{
777
+		ob_start();
778
+		try {
779
+			$response = $this->migration_step();
780
+		} catch (Exception $e) {
781
+			$response = array(
782
+				'records_to_migrate' => 0,
783
+				'records_migrated'   => 0,
784
+				'status'             => EE_Data_Migration_Manager::status_fatal_error,
785
+				'message'            => sprintf(
786
+					__("Unknown fatal error occurred: %s", "event_espresso"),
787
+					$e->getMessage()
788
+				),
789
+				'script'             => 'Unknown',
790
+			);
791
+			$this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
792
+		}
793
+		$warnings_etc = @ob_get_contents();
794
+		ob_end_clean();
795
+		$response['message'] .= $warnings_etc;
796
+		return $response;
797
+	}
798
+
799
+	/**
800
+	 * Updates the wordpress option that keeps track of which which EE version the database
801
+	 * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
802
+	 *
803
+	 * @param array $slug_and_version {
804
+	 * @type string $slug             like 'Core' or 'Calendar',
805
+	 * @type string $version          like '4.1.0'
806
+	 *                                }
807
+	 * @return void
808
+	 */
809
+	public function update_current_database_state_to($slug_and_version = null)
810
+	{
811
+		if (! $slug_and_version) {
812
+			// no version was provided, assume it should be at the current code version
813
+			$slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
814
+		}
815
+		$current_database_state = get_option(self::current_database_state);
816
+		$current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
817
+		update_option(self::current_database_state, $current_database_state);
818
+	}
819
+
820
+	/**
821
+	 * Determines if the database is currently at a state matching what's indicated in $slug and $version.
822
+	 *
823
+	 * @param array $slug_and_version {
824
+	 * @type string $slug             like 'Core' or 'Calendar',
825
+	 * @type string $version          like '4.1.0'
826
+	 *                                }
827
+	 * @return boolean
828
+	 */
829
+	public function database_needs_updating_to($slug_and_version)
830
+	{
831
+
832
+		$slug = $slug_and_version['slug'];
833
+		$version = $slug_and_version['version'];
834
+		$current_database_state = get_option(self::current_database_state);
835
+		if (! isset($current_database_state[ $slug ])) {
836
+			return true;
837
+		} else {
838
+			// 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
839
+			$version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
840
+			$version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
841
+			$needs_updating = false;
842
+			foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
843
+				if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
844
+					$needs_updating = true;
845
+					break;
846
+				}
847
+			}
848
+			return $needs_updating;
849
+		}
850
+	}
851
+
852
+
853
+	/**
854
+	 * Gets all the data migration scripts available in the core folder and folders
855
+	 * in addons. Has the side effect of adding them for autoloading
856
+	 *
857
+	 * @return array keys are expected classnames, values are their filepaths
858
+	 * @throws InvalidInterfaceException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws EE_Error
861
+	 * @throws InvalidArgumentException
862
+	 */
863
+	public function get_all_data_migration_scripts_available()
864
+	{
865
+		if (! $this->_data_migration_class_to_filepath_map) {
866
+			$this->_data_migration_class_to_filepath_map = array();
867
+			foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
868
+				// strip any placeholders added to classname to make it a unique array key
869
+				$eeAddonClass = trim($eeAddonClass, '*');
870
+				$eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
871
+					? $eeAddonClass
872
+					: '';
873
+				$folder_path = EEH_File::end_with_directory_separator($folder_path);
874
+				$files = glob($folder_path . '*.dms.php');
875
+				if (empty($files)) {
876
+					continue;
877
+				}
878
+				foreach ($files as $file) {
879
+					$pos_of_last_slash = strrpos($file, DS);
880
+					$classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
881
+					$migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass);
882
+					$slug = $migrates_to['slug'];
883
+					// check that the slug as contained in the DMS is associated with
884
+					// the slug of an addon or core
885
+					if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
886
+						EE_Error::doing_it_wrong(
887
+							__FUNCTION__,
888
+							sprintf(
889
+								esc_html__(
890
+									'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
891
+									'event_espresso'
892
+								),
893
+								$classname,
894
+								$slug,
895
+								implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
896
+							),
897
+							'4.3.0.alpha.019'
898
+						);
899
+					}
900
+					$this->_data_migration_class_to_filepath_map[ $classname ] = $file;
901
+				}
902
+			}
903
+			EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
904
+		}
905
+		return $this->_data_migration_class_to_filepath_map;
906
+	}
907
+
908
+
909
+	/**
910
+	 * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
911
+	 * from each addon, and check if they need updating,
912
+	 *
913
+	 * @return boolean
914
+	 */
915
+	public function addons_need_updating()
916
+	{
917
+		return false;
918
+	}
919
+
920
+	/**
921
+	 * Adds this error string to the data_migrations_ran array, but we dont necessarily know
922
+	 * where to put it, so we just throw it in there... better than nothing...
923
+	 *
924
+	 * @param string $error_message
925
+	 * @throws EE_Error
926
+	 */
927
+	public function add_error_to_migrations_ran($error_message)
928
+	{
929
+		// get last-ran migration script
930
+		global $wpdb;
931
+		$last_migration_script_option = $wpdb->get_row(
932
+			"SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
933
+			ARRAY_A
934
+		);
935
+
936
+		$last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
937
+			? maybe_unserialize($last_migration_script_option['option_value']) : null;
938
+		// now, tread lightly because we're here because a FATAL non-catchable error
939
+		// was thrown last time when we were trying to run a data migration script
940
+		// so the fatal error could have happened while getting the migration script
941
+		// or doing running it...
942
+		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
943
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
944
+			"",
945
+			$last_migration_script_option['option_name']
946
+		) : null;
947
+
948
+		// check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet
949
+		// because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done)
950
+		if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) {
951
+			// ok then just add this error to its list of errors
952
+			$last_ran_migration_script_properties['_errors'][] = $error_message;
953
+			$last_ran_migration_script_properties['_status'] = self::status_fatal_error;
954
+		} else {
955
+			// so we don't even know which script was last running
956
+			// use the data migration error stub, which is designed specifically for this type of thing
957
+			$general_migration_error = new EE_DMS_Unknown_1_0_0();
958
+			$general_migration_error->add_error($error_message);
959
+			$general_migration_error->set_broken();
960
+			$last_ran_migration_script_properties = $general_migration_error->properties_as_array();
961
+			$versions_migrated_to = 'Unknown.1.0.0';
962
+			// now just to make sure appears as last (in case the were previously a fatal error like this)
963
+			// delete the old one
964
+			delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
965
+		}
966
+		update_option(
967
+			self::data_migration_script_option_prefix . $versions_migrated_to,
968
+			$last_ran_migration_script_properties
969
+		);
970
+	}
971
+
972
+	/**
973
+	 * saves what data migrations have ran to the database
974
+	 *
975
+	 * @return mixed TRUE if successfully saved migrations ran, string if an error occurred
976
+	 */
977
+	protected function _save_migrations_ran()
978
+	{
979
+		if ($this->_data_migrations_ran == null) {
980
+			$this->get_data_migrations_ran();
981
+		}
982
+		// now, we don't want to save actual classes to the DB because that's messy
983
+		$successful_updates = true;
984
+		foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
985
+			foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
986
+				$plugin_slug_for_use_in_option_name = $plugin_slug . ".";
987
+				$option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
988
+				$old_option_value = get_option($option_name);
989
+				if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
990
+					$script_array_for_saving = $array_or_migration_obj->properties_as_array();
991
+					if ($old_option_value != $script_array_for_saving) {
992
+						$successful_updates = update_option($option_name, $script_array_for_saving);
993
+					}
994
+				} else {// we don't know what this array-thing is. So just save it as-is
995
+					if ($old_option_value != $array_or_migration_obj) {
996
+						$successful_updates = update_option($option_name, $array_or_migration_obj);
997
+					}
998
+				}
999
+				if (! $successful_updates) {
1000
+					global $wpdb;
1001
+					return $wpdb->last_error;
1002
+				}
1003
+			}
1004
+		}
1005
+		return true;
1006
+		// $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1007
+		// if ($updated !== true) {
1008
+		//     global $wpdb;
1009
+		//     return $wpdb->last_error;
1010
+		// } else {
1011
+		//     return true;
1012
+		// }
1013
+		// wp_mail(
1014
+		//     "[email protected]",
1015
+		//     time() . " price debug info",
1016
+		//     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1017
+		//         serialize($array_of_migrations)
1018
+		//     )
1019
+		// );
1020
+	}
1021
+
1022
+	/**
1023
+	 * Takes an array of data migration script properties and re-creates the class from
1024
+	 * them. The argument $properties_array is assumed to have been made by
1025
+	 * EE_Data_Migration_Script_Base::properties_as_array()
1026
+	 *
1027
+	 * @param array $properties_array
1028
+	 * @return EE_Data_Migration_Script_Base
1029
+	 * @throws EE_Error
1030
+	 */
1031
+	public function _instantiate_script_from_properties_array($properties_array)
1032
+	{
1033
+		if (! isset($properties_array['class'])) {
1034
+			throw new EE_Error(
1035
+				sprintf(
1036
+					__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1037
+					implode(",", $properties_array)
1038
+				)
1039
+			);
1040
+		}
1041
+		$class_name = $properties_array['class'];
1042
+		if (! class_exists($class_name)) {
1043
+			throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1044
+		}
1045
+		$class = new $class_name;
1046
+		if (! $class instanceof EE_Data_Migration_Script_Base) {
1047
+			throw new EE_Error(
1048
+				sprintf(
1049
+					__("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
1050
+					$class_name,
1051
+					get_class($class)
1052
+				)
1053
+			);
1054
+		}
1055
+		$class->instantiate_from_array_of_properties($properties_array);
1056
+		return $class;
1057
+	}
1058
+
1059
+	/**
1060
+	 * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1061
+	 * leave the DB in a state usable by the current plugin code).
1062
+	 *
1063
+	 * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1064
+	 * @return string
1065
+	 */
1066
+	public function get_most_up_to_date_dms($plugin_slug = 'Core')
1067
+	{
1068
+		$class_to_filepath_map = $this->get_all_data_migration_scripts_available();
1069
+		$most_up_to_date_dms_classname = null;
1070
+		foreach ($class_to_filepath_map as $classname => $filepath) {
1071
+			if ($most_up_to_date_dms_classname === null) {
1072
+				$migrates_to = $this->script_migrates_to_version($classname);
1073
+				$this_plugin_slug = $migrates_to['slug'];
1074
+				if ($this_plugin_slug == $plugin_slug) {
1075
+					// if it's for core, it wins
1076
+					$most_up_to_date_dms_classname = $classname;
1077
+				}
1078
+				// if it wasn't for core, we must keep searching for one that is!
1079
+				continue;
1080
+			} else {
1081
+				$champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1082
+				$contender_migrates_to = $this->script_migrates_to_version($classname);
1083
+				if ($contender_migrates_to['slug'] == $plugin_slug
1084
+					&& version_compare(
1085
+						$champion_migrates_to['version'],
1086
+						$contender_migrates_to['version'],
1087
+						'<'
1088
+					)) {
1089
+					// so the contenders version is higher and its for Core
1090
+					$most_up_to_date_dms_classname = $classname;
1091
+				}
1092
+			}
1093
+		}
1094
+		return $most_up_to_date_dms_classname;
1095
+	}
1096
+
1097
+	/**
1098
+	 * Gets the migration script specified but ONLY if it has already ran.
1099
+	 *
1100
+	 * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code:
1101
+	 * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1102
+	 * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1103
+	 * other addon) DMS has ran, in case the current DMS depends on it.
1104
+	 *
1105
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1106
+	 *                            period. Eg '4.1.0'
1107
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1108
+	 * @return EE_Data_Migration_Script_Base
1109
+	 */
1110
+	public function get_migration_ran($version, $plugin_slug = 'Core')
1111
+	{
1112
+		$migrations_ran = $this->get_data_migrations_ran();
1113
+		if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1114
+			return $migrations_ran[ $plugin_slug ][ $version ];
1115
+		} else {
1116
+			return null;
1117
+		}
1118
+	}
1119
+
1120
+	/**
1121
+	 * Resets the borked data migration scripts so they're no longer borked
1122
+	 * so we can again attempt to migrate
1123
+	 *
1124
+	 * @return bool
1125
+	 * @throws EE_Error
1126
+	 */
1127
+	public function reattempt()
1128
+	{
1129
+		// find if the last-ran script was borked
1130
+		// set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1131
+		// add an 'error' saying that we attempted to reset
1132
+		// does it have a stage that was borked too? if so make it no longer borked
1133
+		// add an 'error' saying we attempted to reset
1134
+		$last_ran_script = $this->get_last_ran_script();
1135
+		if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1136
+			// if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1137
+			$last_ran_script->set_completed();
1138
+		} elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1139
+			$last_ran_script->reattempt();
1140
+		} else {
1141
+			throw new EE_Error(
1142
+				sprintf(
1143
+					__(
1144
+						'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1145
+						'event_espresso'
1146
+					),
1147
+					print_r($last_ran_script, true)
1148
+				)
1149
+			);
1150
+		}
1151
+		return $this->_save_migrations_ran();
1152
+	}
1153
+
1154
+	/**
1155
+	 * Gets whether or not this particular migration has run or not
1156
+	 *
1157
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1158
+	 *                            period. Eg '4.1.0'
1159
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1160
+	 * @return boolean
1161
+	 */
1162
+	public function migration_has_ran($version, $plugin_slug = 'Core')
1163
+	{
1164
+		return $this->get_migration_ran($version, $plugin_slug) !== null;
1165
+	}
1166
+
1167
+	/**
1168
+	 * Enqueues this ee plugin to have its data initialized
1169
+	 *
1170
+	 * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1171
+	 */
1172
+	public function enqueue_db_initialization_for($plugin_slug)
1173
+	{
1174
+		$queue = $this->get_db_initialization_queue();
1175
+		if (! in_array($plugin_slug, $queue)) {
1176
+			$queue[] = $plugin_slug;
1177
+		}
1178
+		update_option(self::db_init_queue_option_name, $queue);
1179
+	}
1180
+
1181
+	/**
1182
+	 * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1183
+	 * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1184
+	 * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1185
+	 */
1186
+	public function initialize_db_for_enqueued_ee_plugins()
1187
+	{
1188
+		$queue = $this->get_db_initialization_queue();
1189
+		foreach ($queue as $plugin_slug) {
1190
+			$most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1191
+			if (! $most_up_to_date_dms) {
1192
+				// if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1193
+				$verify_db = false;
1194
+			} else {
1195
+				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1196
+				$verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1197
+			}
1198
+			if ($plugin_slug == 'Core') {
1199
+				EE_System::instance()->initialize_db_if_no_migrations_required(
1200
+					false,
1201
+					$verify_db
1202
+				);
1203
+			} else {
1204
+				// just loop through the addons to make sure their database is setup
1205
+				foreach (EE_Registry::instance()->addons as $addon) {
1206
+					if ($addon->name() == $plugin_slug) {
1207
+						$addon->initialize_db_if_no_migrations_required($verify_db);
1208
+						break;
1209
+					}
1210
+				}
1211
+			}
1212
+		}
1213
+		// because we just initialized the DBs for the enqueued ee plugins
1214
+		// we don't need to keep remembering which ones needed to be initialized
1215
+		delete_option(self::db_init_queue_option_name);
1216
+	}
1217
+
1218
+	/**
1219
+	 * Gets a numerically-indexed array of plugin slugs that need to have their databases
1220
+	 * (re-)initialized after migrations are complete. ie, each element should be either
1221
+	 * 'Core', or the return value of EE_Addon::name() for an addon
1222
+	 *
1223
+	 * @return array
1224
+	 */
1225
+	public function get_db_initialization_queue()
1226
+	{
1227
+		return get_option(self::db_init_queue_option_name, array());
1228
+	}
1229
+
1230
+	/**
1231
+	 * Gets the injected table analyzer, or throws an exception
1232
+	 *
1233
+	 * @return TableAnalysis
1234
+	 * @throws EE_Error
1235
+	 */
1236
+	protected function _get_table_analysis()
1237
+	{
1238
+		if ($this->_table_analysis instanceof TableAnalysis) {
1239
+			return $this->_table_analysis;
1240
+		} else {
1241
+			throw new EE_Error(
1242
+				sprintf(
1243
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1244
+					get_class($this)
1245
+				)
1246
+			);
1247
+		}
1248
+	}
1249
+
1250
+	/**
1251
+	 * Gets the injected table manager, or throws an exception
1252
+	 *
1253
+	 * @return TableManager
1254
+	 * @throws EE_Error
1255
+	 */
1256
+	protected function _get_table_manager()
1257
+	{
1258
+		if ($this->_table_manager instanceof TableManager) {
1259
+			return $this->_table_manager;
1260
+		} else {
1261
+			throw new EE_Error(
1262
+				sprintf(
1263
+					__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1264
+					get_class($this)
1265
+				)
1266
+			);
1267
+		}
1268
+	}
1269 1269
 }
Please login to merge, or discard this patch.
Spacing   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
     public static function instance()
158 158
     {
159 159
         // check if class object is instantiated
160
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
160
+        if ( ! self::$_instance instanceof EE_Data_Migration_Manager) {
161 161
             self::$_instance = new self();
162 162
         }
163 163
         return self::$_instance;
@@ -233,12 +233,12 @@  discard block
 block discarded – undo
233 233
 
234 234
         if (count($parts) == 4) {
235 235
             // it's 4.2-style.eg Core.4.1.0
236
-            $plugin_slug = $parts[0];// eg Core
237
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
236
+            $plugin_slug = $parts[0]; // eg Core
237
+            $version_string = $parts[1].".".$parts[2].".".$parts[3]; // eg 4.1.0
238 238
         } else {
239 239
             // it's 4.1-style: eg 4.1.0
240 240
             $plugin_slug = 'Core';
241
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
241
+            $version_string = $plugin_slug_and_version_string; // eg 4.1.0
242 242
         }
243 243
         return array($plugin_slug, $version_string);
244 244
     }
@@ -290,11 +290,11 @@  discard block
 block discarded – undo
290 290
      */
291 291
     public function get_data_migrations_ran()
292 292
     {
293
-        if (! $this->_data_migrations_ran) {
293
+        if ( ! $this->_data_migrations_ran) {
294 294
             // setup autoloaders for each of the scripts in there
295 295
             $this->get_all_data_migration_scripts_available();
296 296
             $data_migrations_options = $this->get_all_migration_script_options(
297
-            );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
297
+            ); // get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
298 298
 
299 299
             $data_migrations_ran = array();
300 300
             // convert into data migration script classes where possible
@@ -308,23 +308,23 @@  discard block
 block discarded – undo
308 308
                         $data_migration_option['option_name'],
309 309
                         $data_migration_option['option_value']
310 310
                     );
311
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
311
+                    $data_migrations_ran[$plugin_slug][$version_string] = $class;
312 312
                     // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
313 313
                     $this->_last_ran_script = $class;
314
-                    if (! $class->is_completed()) {
314
+                    if ( ! $class->is_completed()) {
315 315
                         // sometimes we also like to know which was the last incomplete script (or if there are any at all)
316 316
                         $this->_last_ran_incomplete_script = $class;
317 317
                     }
318 318
                 } catch (EE_Error $e) {
319 319
                     // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
320
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
320
+                    $data_migrations_ran[$plugin_slug][$version_string] = maybe_unserialize(
321 321
                         $data_migration_option['option_value']
322 322
                     );
323 323
                 }
324 324
             }
325 325
             // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
326 326
             $this->_data_migrations_ran = $data_migrations_ran;
327
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
327
+            if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
328 328
                 $this->_data_migrations_ran = array();
329 329
             }
330 330
         }
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
     {
358 358
         global $wpdb;
359 359
         return $wpdb->get_results(
360
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
360
+            "SELECT * FROM {$wpdb->options} WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id ASC",
361 361
             ARRAY_A
362 362
         );
363 363
     }
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
     {
373 373
         return apply_filters(
374 374
             'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
375
-            array('Core' => EE_CORE . 'data_migration_scripts')
375
+            array('Core' => EE_CORE.'data_migration_scripts')
376 376
         );
377 377
     }
378 378
 
@@ -388,15 +388,15 @@  discard block
 block discarded – undo
388 388
      */
389 389
     public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
390 390
     {
391
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
392
-            return $this->script_migration_versions[ $migration_script_name ];
391
+        if (isset($this->script_migration_versions[$migration_script_name])) {
392
+            return $this->script_migration_versions[$migration_script_name];
393 393
         }
394 394
         $dms_info = $this->parse_dms_classname($migration_script_name);
395
-        $this->script_migration_versions[ $migration_script_name ] = array(
395
+        $this->script_migration_versions[$migration_script_name] = array(
396 396
             'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
397
-            'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
397
+            'version' => $dms_info['major_version'].".".$dms_info['minor_version'].".".$dms_info['micro_version'],
398 398
         );
399
-        return $this->script_migration_versions[ $migration_script_name ];
399
+        return $this->script_migration_versions[$migration_script_name];
400 400
     }
401 401
 
402 402
     /**
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
     {
411 411
         $matches = array();
412 412
         preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
413
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
413
+        if ( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
414 414
             throw new EE_Error(
415 415
                 sprintf(
416 416
                     __(
@@ -441,7 +441,7 @@  discard block
 block discarded – undo
441 441
     {
442 442
         $espresso_db_core_updates = get_option('espresso_db_update', array());
443 443
         $db_state = get_option(EE_Data_Migration_Manager::current_database_state);
444
-        if (! $db_state) {
444
+        if ( ! $db_state) {
445 445
             // mark the DB as being in the state as the last version in there.
446 446
             // this is done to trigger maintenance mode and do data migration scripts
447 447
             // if the admin installed this version of EE over 3.1.x or 4.0.x
@@ -460,7 +460,7 @@  discard block
 block discarded – undo
460 460
         // in 4.1, $db_state would have only been a simple string like '4.1.0',
461 461
         // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
462 462
         // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
463
-        if (! is_array($db_state)) {
463
+        if ( ! is_array($db_state)) {
464 464
             $db_state = array('Core' => $db_state);
465 465
             update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
466 466
         }
@@ -497,29 +497,29 @@  discard block
 block discarded – undo
497 497
                 $script_converts_plugin_slug = $migrates_to_version['slug'];
498 498
                 $script_converts_to_version = $migrates_to_version['version'];
499 499
                 // check if this version script is DONE or not; or if it's never been ran
500
-                if (! $scripts_ran ||
501
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
502
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
500
+                if ( ! $scripts_ran ||
501
+                    ! isset($scripts_ran[$script_converts_plugin_slug]) ||
502
+                    ! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])) {
503 503
                     // we haven't ran this conversion script before
504 504
                     // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
505 505
                     $script = new $classname($this->_get_table_manager(), $this->_get_table_analysis());
506 506
                     /* @var $script EE_Data_Migration_Script_Base */
507 507
                     $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
508 508
                     if ($can_migrate) {
509
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
509
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
510 510
                         $migrates_to_version = $script->migrates_to_version();
511
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
512
-                        unset($script_class_and_filepaths_available[ $classname ]);
511
+                        $next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
512
+                        unset($script_class_and_filepaths_available[$classname]);
513 513
                     }
514
-                } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
514
+                } elseif ($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version] instanceof EE_Data_Migration_Script_Base) {
515 515
                     // this script has been ran, or at least started
516
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
516
+                    $script = $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version];
517 517
                     if ($script->get_status() != self::status_completed) {
518 518
                         // this script is already underway... keep going with it
519
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
519
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
520 520
                         $migrates_to_version = $script->migrates_to_version();
521
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
522
-                        unset($script_class_and_filepaths_available[ $classname ]);
521
+                        $next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
522
+                        unset($script_class_and_filepaths_available[$classname]);
523 523
                     } else {
524 524
                         // it must have a status that indicates it has finished, so we don't want to try and run it again
525 525
                     }
@@ -530,14 +530,14 @@  discard block
 block discarded – undo
530 530
                 }
531 531
             }
532 532
             $iteration++;
533
-        } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
533
+        }while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
534 534
         // ok we have all the scripts that should run, now let's make them into flat array
535 535
         $scripts_that_should_run = array();
536 536
         foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
537 537
             ksort($scripts_at_priority);
538 538
             foreach ($scripts_at_priority as $scripts) {
539 539
                 foreach ($scripts as $script) {
540
-                    $scripts_that_should_run[ get_class($script) ] = $script;
540
+                    $scripts_that_should_run[get_class($script)] = $script;
541 541
                 }
542 542
             }
543 543
         }
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
     public function get_last_ran_script($include_completed_scripts = false)
563 563
     {
564 564
         // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
565
-        if (! $this->_data_migrations_ran) {
565
+        if ( ! $this->_data_migrations_ran) {
566 566
             $this->get_data_migrations_ran();
567 567
         }
568 568
         if ($include_completed_scripts) {
@@ -599,10 +599,10 @@  discard block
 block discarded – undo
599 599
 
600 600
         try {
601 601
             $currently_executing_script = $this->get_last_ran_script();
602
-            if (! $currently_executing_script) {
602
+            if ( ! $currently_executing_script) {
603 603
                 // Find the next script that needs to execute
604 604
                 $scripts = $this->check_for_applicable_data_migration_scripts();
605
-                if (! $scripts) {
605
+                if ( ! $scripts) {
606 606
                     // huh, no more scripts to run... apparently we're done!
607 607
                     // but dont forget to make sure initial data is there
608 608
                     // we should be good to allow them to exit maintenance mode now
@@ -628,7 +628,7 @@  discard block
 block discarded – undo
628 628
                 $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
629 629
                 $plugin_slug = $migrates_to['slug'];
630 630
                 $version = $migrates_to['version'];
631
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
631
+                $this->_data_migrations_ran[$plugin_slug][$version] = $currently_executing_script;
632 632
             }
633 633
             $current_script_name = get_class($currently_executing_script);
634 634
         } catch (Exception $e) {
@@ -636,7 +636,7 @@  discard block
 block discarded – undo
636 636
 
637 637
             $message = sprintf(
638 638
                 __("Error Message: %sStack Trace:%s", "event_espresso"),
639
-                $e->getMessage() . '<br>',
639
+                $e->getMessage().'<br>',
640 640
                 $e->getTraceAsString()
641 641
             );
642 642
             // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
                     );
689 689
                     // check if there are any more after this one.
690 690
                     $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
691
-                    if (! $scripts_remaining) {
691
+                    if ( ! $scripts_remaining) {
692 692
                         // we should be good to allow them to exit maintenance mode now
693 693
                         EE_Maintenance_Mode::instance()->set_maintenance_level(
694 694
                             intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
@@ -788,7 +788,7 @@  discard block
 block discarded – undo
788 788
                 ),
789 789
                 'script'             => 'Unknown',
790 790
             );
791
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
791
+            $this->add_error_to_migrations_ran($e->getMessage()."; Stack trace:".$e->getTraceAsString());
792 792
         }
793 793
         $warnings_etc = @ob_get_contents();
794 794
         ob_end_clean();
@@ -808,12 +808,12 @@  discard block
 block discarded – undo
808 808
      */
809 809
     public function update_current_database_state_to($slug_and_version = null)
810 810
     {
811
-        if (! $slug_and_version) {
811
+        if ( ! $slug_and_version) {
812 812
             // no version was provided, assume it should be at the current code version
813 813
             $slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
814 814
         }
815 815
         $current_database_state = get_option(self::current_database_state);
816
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
816
+        $current_database_state[$slug_and_version['slug']] = $slug_and_version['version'];
817 817
         update_option(self::current_database_state, $current_database_state);
818 818
     }
819 819
 
@@ -832,15 +832,15 @@  discard block
 block discarded – undo
832 832
         $slug = $slug_and_version['slug'];
833 833
         $version = $slug_and_version['version'];
834 834
         $current_database_state = get_option(self::current_database_state);
835
-        if (! isset($current_database_state[ $slug ])) {
835
+        if ( ! isset($current_database_state[$slug])) {
836 836
             return true;
837 837
         } else {
838 838
             // 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
839
-            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
839
+            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[$slug]), 0, 3);
840 840
             $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
841 841
             $needs_updating = false;
842 842
             foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
843
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
843
+                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[$offset]) {
844 844
                     $needs_updating = true;
845 845
                     break;
846 846
                 }
@@ -862,7 +862,7 @@  discard block
 block discarded – undo
862 862
      */
863 863
     public function get_all_data_migration_scripts_available()
864 864
     {
865
-        if (! $this->_data_migration_class_to_filepath_map) {
865
+        if ( ! $this->_data_migration_class_to_filepath_map) {
866 866
             $this->_data_migration_class_to_filepath_map = array();
867 867
             foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
868 868
                 // strip any placeholders added to classname to make it a unique array key
@@ -871,7 +871,7 @@  discard block
 block discarded – undo
871 871
                     ? $eeAddonClass
872 872
                     : '';
873 873
                 $folder_path = EEH_File::end_with_directory_separator($folder_path);
874
-                $files = glob($folder_path . '*.dms.php');
874
+                $files = glob($folder_path.'*.dms.php');
875 875
                 if (empty($files)) {
876 876
                     continue;
877 877
                 }
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
                             '4.3.0.alpha.019'
898 898
                         );
899 899
                     }
900
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
900
+                    $this->_data_migration_class_to_filepath_map[$classname] = $file;
901 901
                 }
902 902
             }
903 903
             EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
         // get last-ran migration script
930 930
         global $wpdb;
931 931
         $last_migration_script_option = $wpdb->get_row(
932
-            "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
932
+            "SELECT * FROM $wpdb->options WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id DESC LIMIT 1",
933 933
             ARRAY_A
934 934
         );
935 935
 
@@ -961,10 +961,10 @@  discard block
 block discarded – undo
961 961
             $versions_migrated_to = 'Unknown.1.0.0';
962 962
             // now just to make sure appears as last (in case the were previously a fatal error like this)
963 963
             // delete the old one
964
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
964
+            delete_option(self::data_migration_script_option_prefix.$versions_migrated_to);
965 965
         }
966 966
         update_option(
967
-            self::data_migration_script_option_prefix . $versions_migrated_to,
967
+            self::data_migration_script_option_prefix.$versions_migrated_to,
968 968
             $last_ran_migration_script_properties
969 969
         );
970 970
     }
@@ -983,8 +983,8 @@  discard block
 block discarded – undo
983 983
         $successful_updates = true;
984 984
         foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
985 985
             foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
986
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
987
-                $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
986
+                $plugin_slug_for_use_in_option_name = $plugin_slug.".";
987
+                $option_name = self::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string;
988 988
                 $old_option_value = get_option($option_name);
989 989
                 if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
990 990
                     $script_array_for_saving = $array_or_migration_obj->properties_as_array();
@@ -996,7 +996,7 @@  discard block
 block discarded – undo
996 996
                         $successful_updates = update_option($option_name, $array_or_migration_obj);
997 997
                     }
998 998
                 }
999
-                if (! $successful_updates) {
999
+                if ( ! $successful_updates) {
1000 1000
                     global $wpdb;
1001 1001
                     return $wpdb->last_error;
1002 1002
                 }
@@ -1030,7 +1030,7 @@  discard block
 block discarded – undo
1030 1030
      */
1031 1031
     public function _instantiate_script_from_properties_array($properties_array)
1032 1032
     {
1033
-        if (! isset($properties_array['class'])) {
1033
+        if ( ! isset($properties_array['class'])) {
1034 1034
             throw new EE_Error(
1035 1035
                 sprintf(
1036 1036
                     __("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
@@ -1039,11 +1039,11 @@  discard block
 block discarded – undo
1039 1039
             );
1040 1040
         }
1041 1041
         $class_name = $properties_array['class'];
1042
-        if (! class_exists($class_name)) {
1042
+        if ( ! class_exists($class_name)) {
1043 1043
             throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1044 1044
         }
1045 1045
         $class = new $class_name;
1046
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1046
+        if ( ! $class instanceof EE_Data_Migration_Script_Base) {
1047 1047
             throw new EE_Error(
1048 1048
                 sprintf(
1049 1049
                     __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
@@ -1110,8 +1110,8 @@  discard block
 block discarded – undo
1110 1110
     public function get_migration_ran($version, $plugin_slug = 'Core')
1111 1111
     {
1112 1112
         $migrations_ran = $this->get_data_migrations_ran();
1113
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1114
-            return $migrations_ran[ $plugin_slug ][ $version ];
1113
+        if (isset($migrations_ran[$plugin_slug]) && isset($migrations_ran[$plugin_slug][$version])) {
1114
+            return $migrations_ran[$plugin_slug][$version];
1115 1115
         } else {
1116 1116
             return null;
1117 1117
         }
@@ -1172,7 +1172,7 @@  discard block
 block discarded – undo
1172 1172
     public function enqueue_db_initialization_for($plugin_slug)
1173 1173
     {
1174 1174
         $queue = $this->get_db_initialization_queue();
1175
-        if (! in_array($plugin_slug, $queue)) {
1175
+        if ( ! in_array($plugin_slug, $queue)) {
1176 1176
             $queue[] = $plugin_slug;
1177 1177
         }
1178 1178
         update_option(self::db_init_queue_option_name, $queue);
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
         $queue = $this->get_db_initialization_queue();
1189 1189
         foreach ($queue as $plugin_slug) {
1190 1190
             $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1191
-            if (! $most_up_to_date_dms) {
1191
+            if ( ! $most_up_to_date_dms) {
1192 1192
                 // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1193 1193
                 $verify_db = false;
1194 1194
             } else {
Please login to merge, or discard this patch.