PluginProbe
YayMail – WooCommerce Email Customizer / 4.3.3
YayMail – WooCommerce Email Customizer v4.3.3
4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 3.4.2 3.4.3 All 55 releases
yaymail / src / Models / MigrationModel.php

MigrationModel.php in YayMail – WooCommerce Email Customizer 4.3.3, at src/Models/MigrationModel.php

280 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace YayMail\Models;
3
4 use YayMail\Migrations\AbstractMigration;
5 use YayMail\Utils\SingletonTrait;
6 use YayMail\Utils\Logger;
7 use YayMail\Migrations\MainMigration;
8 use YayMail\Migrations\MigrationHelper;
9
10 /**
11 * Migration Model
12 *
13 * @method static MigrationModel get_instance()
14 */
15 class MigrationModel {
16 use SingletonTrait;
17
18 /** @var Logger */
19 private $logger;
20
21 private function __construct() {
22 $this->logger = new Logger();
23 }
24
25 public function get_onload_data() {
26 return [
27 'required_migrations' => $this->get_required_migration_names(),
28 'backups' => $this->get_backups(),
29 ];
30 }
31
32 public function migrate() {
33 $is_migration_succeeded = MainMigration::get_instance()->migrate();
34 if ( ! $is_migration_succeeded ) {
35 throw new \Exception( esc_html__( 'Migration failed, please contact our Customer Support for help!', 'yaymail' ), 500 );
36 }
37 return [ 'is_critical_migration_required' => $this->check_if_critical_migration_required() ];
38 }
39
40 /**
41 * Restore backup to a specific version
42 *
43 * @param array $backup Backup data containing posts, postmeta, options, metadata, and version.
44 *
45 * @return array Returns array with 'is_critical_migration_required' boolean flag.
46 * @throws \Exception When backup doesn't exist or restoration fails.
47 */
48 public function reset( $backup ) {
49 global $wpdb;
50
51 if ( ! $backup || ! $backup['version'] || ! $backup['name'] ) {
52 throw new \Exception( 'Back up does not exist', 500 );
53 }
54
55 try {
56 $backup_name = $backup['name'];
57 $version = $backup['version'];
58
59 $wpdb->query( 'START TRANSACTION' );
60 $this->logger->log( '***** Start reset transaction ****' );
61 $this->logger->log( "Backup name: $backup_name" );
62
63 // Get IDs of posts to be deleted
64 $post_ids_to_delete = $wpdb->get_col(
65 $wpdb->prepare(
66 "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s",
67 'yaymail_template'
68 )
69 );
70 if ( $post_ids_to_delete ) {
71 // Delete current post meta data
72 $delete_postmeta_query = sprintf(
73 "DELETE FROM {$wpdb->postmeta} WHERE post_id IN (%s)",
74 implode( ',', array_map( 'intval', $post_ids_to_delete ) )
75 );
76 $this->logger->log( $delete_postmeta_query );
77 $wpdb->query( $delete_postmeta_query );// phpcs:ignore
78
79 // Delete the posts
80 $delete_template_posts_query = sprintf(
81 "DELETE FROM {$wpdb->posts} WHERE ID IN (%s)",
82 implode( ',', array_map( 'intval', $post_ids_to_delete ) )
83 );
84 $this->logger->log( $delete_template_posts_query );
85 $wpdb->query( $delete_template_posts_query );// phpcs:ignore
86 }
87
88 $delete_template_posts_query = $wpdb->prepare(
89 "DELETE FROM {$wpdb->posts} WHERE post_type = %s",
90 'yaymail_template'
91 );
92 $this->logger->log( $delete_template_posts_query );
93 $wpdb->query( $delete_template_posts_query );// phpcs:ignore
94
95 // Restore the backed-up posts
96 $backed_up_posts = $backup['posts'];
97 $backed_up_postmeta = $backup['postmeta'];
98 foreach ( $backed_up_posts as $post ) {
99 $wpdb->insert(
100 $wpdb->posts,
101 [
102 'post_author' => $post->post_author,
103 'post_date' => $post->post_date,
104 'post_date_gmt' => $post->post_date_gmt,
105 'post_content' => $post->post_content,
106 'post_title' => $post->post_title,
107 'post_excerpt' => $post->post_excerpt,
108 'post_status' => $post->post_status,
109 'comment_status' => $post->comment_status,
110 'ping_status' => $post->ping_status,
111 'post_password' => $post->post_password,
112 'post_name' => $post->post_name,
113 'to_ping' => $post->to_ping,
114 'pinged' => $post->pinged,
115 'post_modified' => $post->post_modified,
116 'post_modified_gmt' => $post->post_modified_gmt,
117 'post_content_filtered' => $post->post_content_filtered,
118 'post_parent' => $post->post_parent,
119 'guid' => $post->guid,
120 'menu_order' => $post->menu_order,
121 'post_type' => $post->post_type,
122 'post_mime_type' => $post->post_mime_type,
123 'comment_count' => $post->comment_count,
124 ]
125 );
126
127 // Insert post meta data
128 $inserted_post_id = $wpdb->insert_id;
129 $postmetas_for_current_post = array_filter(
130 $backed_up_postmeta,
131 function( $postmeta ) use ( $post ) {
132 return $postmeta->post_id === $post->ID;
133 }
134 );
135 if ( ! empty( $postmetas_for_current_post ) ) {
136 foreach ( $postmetas_for_current_post as $postmeta ) {
137 add_post_meta( $inserted_post_id, $postmeta->meta_key, maybe_unserialize( $postmeta->meta_value ) );
138 }
139 }
140 }//end foreach
141
142 // Restore backed-up options
143 foreach ( $backup['options'] as $option ) {
144 // Only restore options that belong to YayMail (same pattern as export)
145 if ( strpos( $option->option_name, 'yaymail' ) !== false ) {
146 update_option( $option->option_name, maybe_unserialize( $option->option_value ) );
147 }
148 }
149
150 // Remove the succeeded migration log from db
151 $successful_migrations = get_option( AbstractMigration::SUCCESSFUL_MIGRATIONS, null );
152 $removed_migrations = [];
153 if ( ! empty( $successful_migrations ) ) {
154 $filtered_successful_migrations = array_filter(
155 $successful_migrations,
156 function( $migration ) use ( $version, $backup ) {
157 $backup_date = new \DateTime( $backup['created_date'], wp_timezone() );
158 $migration_date = new \DateTime( $migration['created_date'], wp_timezone() );
159 $should_remove = $migration_date >= $backup_date;
160
161 return ! $should_remove;
162 }
163 );
164
165 update_option( AbstractMigration::SUCCESSFUL_MIGRATIONS, $filtered_successful_migrations );
166 $removed_migrations = array_udiff(
167 $successful_migrations,
168 $filtered_successful_migrations,
169 function( $a, $b ) {
170 return strcmp( serialize( $a ), serialize( $b ) );
171 }
172 );
173 }//end if
174
175 // Restore core version
176 update_option( 'yaymail_version', $version );
177 wp_cache_delete( 'yaymail_version', 'options' );
178
179 // Restore addon versions
180 $addon_versions = get_option( 'yaymail_addon_versions', [] );
181 $restored_addon_versions = array_filter(
182 $addon_versions,
183 function( $addon_version, $addon_namespace ) use ( $removed_migrations ) {
184 foreach ( $removed_migrations as $migration ) {
185 if ( ! empty( $migration['addon_namespace'] ) && $migration['addon_namespace'] === $addon_namespace && version_compare( $addon_version, $migration['to_version'], '<=' ) ) {
186 return false;
187 }
188 }
189 return true;
190 },
191 ARRAY_FILTER_USE_BOTH
192 );
193 update_option( 'yaymail_addon_versions', $restored_addon_versions );
194
195 do_action( 'yaymail_before_reset_migration_commit', $backup, $removed_migrations );
196
197 $wpdb->query( 'COMMIT' );
198 $this->logger->log( '***** Finish reset transaction ****' );
199 $this->logger->log( "$backup_name restored successfully!" );
200
201 return [ 'is_critical_migration_required' => $this->check_if_critical_migration_required() ];
202
203 } catch ( \Exception $e ) {
204 $wpdb->query( 'ROLLBACK' );
205 $this->logger->log( '***** Transaction rolled back. ' . $e->getMessage() );
206 throw new \Exception( esc_html__( 'Restoration failed', 'yaymail' ), 500 );
207 }//end try
208 }
209
210 public function check_if_critical_migration_required() {
211 $old_version = get_option( 'yaymail_version' );
212 if ( $old_version ) {
213 return version_compare( $old_version, '4.0.0', '<' );
214 }
215 return false;
216 }
217
218 private function get_required_migration_names() {
219 $old_version = MigrationHelper::format_version_number( get_option( 'yaymail_version' ) );
220 $new_version = MigrationHelper::format_version_number( YAYMAIL_VERSION );
221 $successful_migrations = get_option( AbstractMigration::SUCCESSFUL_MIGRATIONS, [] );
222
223 // If freshly installed or already on latest version with no migrations needed
224 if ( ( version_compare( $old_version, $new_version, '>=' ) && empty( $successful_migrations ) ) ) {
225 return apply_filters( 'yaymail_required_migration_names', [] );
226 }
227
228 $args = [
229 'post_type' => 'yaymail_template',
230 'post_status' => 'any',
231 'posts_per_page' => -1,
232 ];
233
234 $query = new \WP_Query( $args );
235
236 $has_yaymail_template = $query->have_posts();
237 if ( ( $old_version == null && ! $has_yaymail_template ) && empty( $successful_migrations ) ) {
238 return [];
239 }
240
241 // Check if any migrations have already been run up to current version
242 foreach ( $successful_migrations as $migration ) {
243 if ( empty( $migration['addon_namespace'] ) && version_compare( $migration['to_version'], YAYMAIL_VERSION, '>=' ) ) {
244 return apply_filters( 'yaymail_required_migration_names', [] );
245 }
246 }
247
248 // Get available migrations that need to be run
249 $core_migrations = MainMigration::CORE_MIGRATIONS;
250 $filtered_migrations = MigrationHelper::filter_migrations( $core_migrations, $old_version, $new_version );
251
252 $needed_migrations = empty( $filtered_migrations ) ? [] : [ 'YayMail' ];
253
254 return apply_filters( 'yaymail_required_migration_names', $needed_migrations );
255 }
256
257 private function get_backups() {
258 global $wpdb;
259
260 $backup_prefix = AbstractMigration::BACKUP_PREFIX;
261
262 $backup_options_query = $wpdb->prepare(
263 "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE %s",
264 $backup_prefix . '%'
265 );
266 $backups_result = $wpdb->get_results( $backup_options_query );// phpcs:ignore
267
268 $backups = [];
269 foreach ( $backups_result as $backup ) {
270 $data = maybe_unserialize( $backup->option_value );
271 $backups[] = [
272 'created_date' => $data['created_date'] ?? 'created_date not found',
273 'name' => $backup->option_name ?? 'backup name not found',
274 ];
275 }
276
277 return $backups;
278 }
279 }
280