new option ID * * @since 2.0.0 * @var array */ protected $settings_mapping = [ // Company settings - these exist in the plugin 'easy_invoice_business_logo' => 'easy_invoice_company_logo', 'easy_invoice_business_name' => 'easy_invoice_company_name', 'easy_invoice_business_address' => 'easy_invoice_company_address', 'easy_invoice_business_website_url' => 'easy_invoice_company_website', 'easy_invoice_business_additional_info' => 'easy_invoice_company_additional_info', 'easy_invoice_business_phone' => 'easy_invoice_company_phone', 'easy_invoice_business_email' => 'easy_invoice_company_email', 'easy_invoice_business_vat' => 'easy_invoice_tax_number', 'easy_invoice_company_phone' => 'easy_invoice_company_phone', 'easy_invoice_company_email' => 'easy_invoice_company_email', 'easy_invoice_company_additional_info' => 'easy_invoice_company_additional_info', // Email settings - these exist in the plugin 'easy_invoice_email_from_address' => 'easy_invoice_email_from_address', 'easy_invoice_email_from_name' => 'easy_invoice_email_from_name', 'easy_invoice_email_send_admin_copy' => 'easy_invoice_bcc_admin', 'easy_invoice_email_reply_to' => 'easy_invoice_email_reply_to', 'easy_invoice_email_reply_to_name' => 'easy_invoice_email_reply_to_name', 'easy_invoice_email_logo' => 'easy_invoice_email_logo', 'easy_invoice_email_footer_text' => 'easy_invoice_email_footer_text', 'easy_invoice_enable_email_styling' => 'easy_invoice_enable_email_styling', 'easy_invoice_admin_email' => 'easy_invoice_admin_email', 'easy_invoice_test_email' => 'easy_invoice_test_email', // Invoice settings - these exist in the plugin 'easy_invoice_number_prefix' => 'easy_invoice_invoice_prefix', 'easy_invoice_invoice_number' => 'easy_invoice_invoice_starting_number', 'easy_invoice_show_hide_adjust' => 'easy_invoice_invoice_show_adjust_field', 'easy_invoice_terms_conditions' => 'easy_invoice_invoice_terms_conditions', 'easy_invoice_footer_text' => 'easy_invoice_invoice_footer_text', // Quote settings - these exist in the plugin 'easy_invoice_quote_number_prefix' => 'easy_invoice_quote_prefix', 'easy_invoice_quote_number' => 'easy_invoice_quote_starting_number', 'easy_invoice_quote_show_hide_adjust' => 'easy_invoice_quote_show_adjust_field', 'easy_invoice_quote_terms_conditions' => 'easy_invoice_quote_terms_conditions', 'easy_invoice_quote_footer_text' => 'easy_invoice_quote_footer_text', 'easy_invoice_quote_accept_quote_button' => 'easy_invoice_quote_accept_button', 'easy_invoice_quote_accept_quote_button_action' => 'easy_invoice_quote_accept_action', 'easy_invoice_accept_quote_text' => 'easy_invoice_quote_accept_text', 'easy_invoice_accepted_quote_message' => 'easy_invoice_quote_accepted_message', 'easy_invoice_decline_quote_reason_required' => 'easy_invoice_quote_decline_reason_required', 'easy_invoice_declined_quote_message' => 'easy_invoice_quote_declined_message', // Currency settings - these exist in the plugin 'easy_invoice_currency' => 'easy_invoice_currency_code', 'easy_invoice_currency_symbol_type' => 'easy_invoice_currency_symbol_type', 'easy_invoice_currency_position' => 'easy_invoice_currency_position', 'easy_invoice_thousand_separator' => 'easy_invoice_thousands_separator', 'easy_invoice_decimal_separator' => 'easy_invoice_decimal_separator', 'easy_invoice_price_number_decimals' => 'easy_invoice_decimal_precision', // Tax settings - these exist in the plugin 'easy_invoice_tax_type' => 'easy_invoice_tax_entry_method', 'easy_invoice_tax_percentage' => 'easy_invoice_tax_rate', // Payment settings - these exist in the plugin 'easy_invoice_payment_methods' => 'easy_invoice_payment_methods', 'easy_invoice_payment_gateway_order' => 'easy_invoice_payment_gateway_order', 'easy_invoice_payment_email_enabled' => 'easy_invoice_payment_email_enabled', 'easy_invoice_payment_email_subject' => 'easy_invoice_payment_email_subject', 'easy_invoice_payment_email_body' => 'easy_invoice_payment_email_body', 'easy_invoice_payment_reminder_days' => 'easy_invoice_payment_reminder_days', 'easy_invoice_payment_terms' => 'easy_invoice_payment_terms', // Additional settings that might exist 'easy_invoice_pre_defined_line_items' => 'easy_invoice_pre_defined_line_items', 'easy_invoice_client_portal_enabled' => 'easy_invoice_client_portal_enabled', 'easy_invoice_client_registration_enabled' => 'easy_invoice_client_registration_enabled', 'easy_invoice_client_login_redirect' => 'easy_invoice_client_login_redirect', 'easy_invoice_client_registration_redirect' => 'easy_invoice_client_registration_redirect', ]; /** * Check if migration is needed. * * @since 2.0.0 * @return bool */ public function is_needed(): bool { // Check if settings have already been migrated if (get_option('easy_invoice_settings_migrated', false)) { return false; } // Check if any old settings exist foreach ($this->settings_mapping as $old_key => $new_key) { if ($this->option_exists($old_key)) { $this->log(sprintf('Found setting %s that needs migration', $old_key)); return true; } } return false; } /** * Run the migration. * * @since 2.0.0 * @return array */ public function migrate(): array { $this->log('Starting settings migration'); try { $migrated_count = 0; $errors = []; // Simple migration: copy data from old options to new options foreach ($this->settings_mapping as $old_key => $new_key) { try { $old_value = get_option($old_key); if ($old_value !== false) { // Transform the value if needed $transformed_value = $this->transform_setting_value($old_key, $old_value); // Copy the transformed value to new option update_option($new_key, $transformed_value); // Delete old option //delete_option($old_key); $migrated_count++; $this->log(sprintf('Successfully migrated setting %s to %s (value: %s)', $old_key, $new_key, var_export($transformed_value, true))); } } catch (\Exception $e) { $errors[] = sprintf('Failed to migrate setting %s: %s', $old_key, $e->getMessage()); $this->log(sprintf('Failed to migrate setting %s: %s', $old_key, $e->getMessage()), 'error'); } } // Special handling for payment gateways $this->migrate_payment_gateways(); if (empty($errors)) { // Set a flag to indicate settings migration is complete update_option('easy_invoice_settings_migrated', true); return $this->success_result(sprintf('Successfully migrated %d settings', $migrated_count)); } else { return $this->error_result('Settings migration completed with errors: ' . implode(', ', $errors)); } } catch (\Exception $e) { $this->log('Settings migration failed: ' . $e->getMessage(), 'error'); return $this->error_result('Settings migration failed: ' . $e->getMessage()); } } /** * Check if an option exists. * * @since 2.0.0 * @param string $option Option name * @return bool */ protected function option_exists(string $option): bool { return get_option($option) !== false; } /** * Transform setting value based on the setting type. * * @since 2.0.0 * @param string $old_key Old setting key * @param mixed $value Setting value * @return mixed Transformed value */ protected function transform_setting_value(string $old_key, $value) { // Handle tax_type transformation if ($old_key === 'easy_invoice_tax_type') { return $value === 'inclusive' ? 'yes' : 'no'; } // Handle tax_percentage - ensure it's numeric if ($old_key === 'easy_invoice_tax_percentage') { return floatval($value); } // Handle number fields - ensure they're numeric if (in_array($old_key, [ 'easy_invoice_invoice_number', 'easy_invoice_quote_number', 'easy_invoice_price_number_decimals' ])) { return intval($value); } // Handle checkbox fields - ensure they're boolean strings if (in_array($old_key, [ 'easy_invoice_show_hide_adjust', 'easy_invoice_quote_show_hide_adjust', 'easy_invoice_quote_accept_quote_button', 'easy_invoice_decline_quote_reason_required', 'easy_invoice_payment_gateway_test_mode', 'easy_invoice_enable_proceed_to_payment' ])) { return $value ? 'yes' : 'no'; } // Handle payment gateways - ensure it's an array if ($old_key === 'easy_invoice_payment_gateways') { if (is_array($value)) { return $value; } elseif (is_string($value)) { // If it's a serialized string, unserialize it $unserialized = maybe_unserialize($value); return is_array($unserialized) ? $unserialized : []; } return []; } // Default: return value as-is return $value; } /** * Migrate payment gateways with special handling. * * @since 2.0.0 * @return void */ protected function migrate_payment_gateways(): void { $this->log('Starting payment gateways migration'); // Get old payment gateways $old_gateways = get_option('easy_invoice_payment_gateways', []); if (empty($old_gateways)) { $this->log('No payment gateways found to migrate'); return; } // Transform old gateway format to new format $new_gateways = []; foreach ($old_gateways as $gateway_id => $enabled) { if ($enabled) { $new_gateways[] = $gateway_id; } } // Save new payment gateways if (!empty($new_gateways)) { update_option('easy_invoice_payment_methods', $new_gateways); $this->log(sprintf('Migrated payment gateways: %s', implode(', ', $new_gateways))); } // Handle individual gateway settings $this->migrate_individual_gateway_settings(); } /** * Migrate individual gateway settings. * * @since 2.0.0 * @return void */ protected function migrate_individual_gateway_settings(): void { // Common gateway settings that might exist $gateway_settings = [ 'easy_invoice_paypal_enabled' => 'easy_invoice_paypal_enabled', 'easy_invoice_stripe_enabled' => 'easy_invoice_stripe_enabled', 'easy_invoice_bank_transfer_enabled' => 'easy_invoice_bank_transfer_enabled', 'easy_invoice_cash_enabled' => 'easy_invoice_cash_enabled', 'easy_invoice_cheque_enabled' => 'easy_invoice_cheque_enabled', ]; foreach ($gateway_settings as $old_key => $new_key) { $old_value = get_option($old_key); if ($old_value !== false) { $transformed_value = $this->transform_setting_value($old_key, $old_value); update_option($new_key, $transformed_value); $this->log(sprintf('Migrated gateway setting %s to %s', $old_key, $new_key)); } } } }