emails
4 years ago
class-experimental-abtest.php
3 years ago
connect-existing-pages.php
3 years ago
core-functions.php
4 years ago
feature-config.php
3 years ago
page-controller-functions.php
4 years ago
wc-admin-update-functions.php
3 years ago
wc-admin-update-functions.php
285 lines
| 1 | <?php |
| 2 | /** |
| 3 | * WooCommerce Admin Updates |
| 4 | * |
| 5 | * Functions for updating data, used by the background updater. |
| 6 | * |
| 7 | * @package WooCommerce\Admin |
| 8 | */ |
| 9 | |
| 10 | use \Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; |
| 11 | use \Automattic\WooCommerce\Admin\Notes\Notes; |
| 12 | use \Automattic\WooCommerce\Internal\Admin\Notes\UnsecuredReportFiles; |
| 13 | use \Automattic\WooCommerce\Admin\ReportExporter; |
| 14 | |
| 15 | /** |
| 16 | * Update order stats `status` index length. |
| 17 | * See: https://github.com/woocommerce/woocommerce-admin/issues/2969. |
| 18 | */ |
| 19 | function wc_admin_update_0201_order_status_index() { |
| 20 | global $wpdb; |
| 21 | |
| 22 | // Max DB index length. See wp_get_db_schema(). |
| 23 | $max_index_length = 191; |
| 24 | |
| 25 | $index = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}wc_order_stats WHERE key_name = 'status'" ); |
| 26 | |
| 27 | if ( property_exists( $index, 'Sub_part' ) ) { |
| 28 | // The index was created with the right length. Time to bail. |
| 29 | if ( $max_index_length === $index->Sub_part ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName |
| 30 | return; |
| 31 | } |
| 32 | |
| 33 | // We need to drop the index so it can be recreated. |
| 34 | $wpdb->query( "DROP INDEX `status` ON {$wpdb->prefix}wc_order_stats" ); |
| 35 | } |
| 36 | |
| 37 | // Recreate the status index with a max length. |
| 38 | $wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}wc_order_stats ADD INDEX status (status(%d))", $max_index_length ) ); |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Rename "gross_total" to "total_sales". |
| 43 | * See: https://github.com/woocommerce/woocommerce-admin/issues/3175 |
| 44 | */ |
| 45 | function wc_admin_update_0230_rename_gross_total() { |
| 46 | global $wpdb; |
| 47 | |
| 48 | // We first need to drop the new `total_sales` column, since dbDelta() will have created it. |
| 49 | $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats DROP COLUMN `total_sales`" ); |
| 50 | // Then we can rename the existing `gross_total` column. |
| 51 | $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats CHANGE COLUMN `gross_total` `total_sales` double DEFAULT 0 NOT NULL" ); |
| 52 | } |
| 53 | |
| 54 | /** |
| 55 | * Remove the note unsnoozing scheduled action. |
| 56 | */ |
| 57 | function wc_admin_update_0251_remove_unsnooze_action() { |
| 58 | as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-data' ); |
| 59 | as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-notes' ); |
| 60 | } |
| 61 | |
| 62 | /** |
| 63 | * Remove Facebook Extension note. |
| 64 | */ |
| 65 | function wc_admin_update_110_remove_facebook_note() { |
| 66 | Notes::delete_notes_with_name( 'wc-admin-facebook-extension' ); |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * Remove Dismiss action from tracking opt-in admin note. |
| 71 | */ |
| 72 | function wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note() { |
| 73 | global $wpdb; |
| 74 | |
| 75 | $wpdb->query( "DELETE actions FROM {$wpdb->prefix}wc_admin_note_actions actions INNER JOIN {$wpdb->prefix}wc_admin_notes notes USING (note_id) WHERE actions.name = 'tracking-dismiss' AND notes.name = 'wc-admin-usage-tracking-opt-in'" ); |
| 76 | } |
| 77 | |
| 78 | /** |
| 79 | |
| 80 | * Update DB Version. |
| 81 | */ |
| 82 | function wc_admin_update_130_db_version() { |
| 83 | Installer::update_db_version( '1.3.0' ); |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Update DB Version. |
| 88 | */ |
| 89 | function wc_admin_update_140_db_version() { |
| 90 | Installer::update_db_version( '1.4.0' ); |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * Remove Facebook Experts note. |
| 95 | */ |
| 96 | function wc_admin_update_160_remove_facebook_note() { |
| 97 | Notes::delete_notes_with_name( 'wc-admin-facebook-marketing-expert' ); |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Set "two column" homescreen layout as default for existing stores. |
| 102 | */ |
| 103 | function wc_admin_update_170_homescreen_layout() { |
| 104 | add_option( 'woocommerce_default_homepage_layout', 'two_columns', '', 'no' ); |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Delete the preexisting export files. |
| 109 | */ |
| 110 | function wc_admin_update_270_delete_report_downloads() { |
| 111 | $upload_dir = wp_upload_dir(); |
| 112 | $base_dir = trailingslashit( $upload_dir['basedir'] ); |
| 113 | |
| 114 | $failed_files = array(); |
| 115 | $exports_status = get_option( ReportExporter::EXPORT_STATUS_OPTION, array() ); |
| 116 | $has_failure = false; |
| 117 | |
| 118 | if ( ! is_array( $exports_status ) ) { |
| 119 | // This is essentially the same path as files failing deletion. Handle as such. |
| 120 | return; |
| 121 | } |
| 122 | |
| 123 | // Delete all export files based on the status option values. |
| 124 | foreach ( $exports_status as $key => $progress ) { |
| 125 | list( $report_type, $export_id ) = explode( ':', $key ); |
| 126 | |
| 127 | if ( ! $export_id ) { |
| 128 | continue; |
| 129 | } |
| 130 | |
| 131 | $file = "{$base_dir}wc-{$report_type}-report-export-{$export_id}.csv"; |
| 132 | $header = $file . '.headers'; |
| 133 | |
| 134 | // phpcs:ignore |
| 135 | if ( @file_exists( $file ) && false === @unlink( $file ) ) { |
| 136 | array_push( $failed_files, $file ); |
| 137 | } |
| 138 | |
| 139 | // phpcs:ignore |
| 140 | if ( @file_exists( $header ) && false === @unlink( $header ) ) { |
| 141 | array_push( $failed_files, $header ); |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | // If the status option was missing or corrupt, there will be files left over. |
| 146 | $potential_exports = glob( $base_dir . 'wc-*-report-export-*.csv' ); |
| 147 | $reports_pattern = '(revenue|products|variations|orders|categories|coupons|taxes|stock|customers|downloads)'; |
| 148 | |
| 149 | /** |
| 150 | * Look for files we can be reasonably sure were created by the report export. |
| 151 | * |
| 152 | * Export files we created will match the 'wc-*-report-export-*.csv' glob, with |
| 153 | * the first wildcard being one of the exportable report slugs, and the second |
| 154 | * being an integer with 11-14 digits (from microtime()'s output) that represents |
| 155 | * a time in the past. |
| 156 | */ |
| 157 | foreach ( $potential_exports as $potential_export ) { |
| 158 | $matches = array(); |
| 159 | // See if the filename matches an unfiltered export pattern. |
| 160 | if ( ! preg_match( "/wc-{$reports_pattern}-report-export-(?P<export_id>\d{11,14})\.csv\$/", $potential_export, $matches ) ) { |
| 161 | $has_failure = true; |
| 162 | continue; |
| 163 | } |
| 164 | |
| 165 | // Validate the timestamp (anything in the past). |
| 166 | $timestamp = (int) substr( $matches['export_id'], 0, 10 ); |
| 167 | |
| 168 | if ( ! $timestamp || $timestamp > time() ) { |
| 169 | $has_failure = true; |
| 170 | continue; |
| 171 | } |
| 172 | |
| 173 | // phpcs:ignore |
| 174 | if ( false === @unlink( $potential_export ) ) { |
| 175 | array_push( $failed_files, $potential_export ); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | // Try deleting failed files once more. |
| 180 | foreach ( $failed_files as $failed_file ) { |
| 181 | // phpcs:ignore |
| 182 | if ( false === @unlink( $failed_file ) ) { |
| 183 | $has_failure = true; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | if ( $has_failure ) { |
| 188 | UnsecuredReportFiles::possibly_add_note(); |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | /** |
| 193 | * Update the old task list options. |
| 194 | */ |
| 195 | function wc_admin_update_271_update_task_list_options() { |
| 196 | $hidden_lists = get_option( 'woocommerce_task_list_hidden_lists', array() ); |
| 197 | $setup_list_hidden = get_option( 'woocommerce_task_list_hidden', 'no' ); |
| 198 | $extended_list_hidden = get_option( 'woocommerce_extended_task_list_hidden', 'no' ); |
| 199 | if ( 'yes' === $setup_list_hidden ) { |
| 200 | $hidden_lists[] = 'setup'; |
| 201 | } |
| 202 | if ( 'yes' === $extended_list_hidden ) { |
| 203 | $hidden_lists[] = 'extended'; |
| 204 | } |
| 205 | |
| 206 | update_option( 'woocommerce_task_list_hidden_lists', array_unique( $hidden_lists ) ); |
| 207 | delete_option( 'woocommerce_task_list_hidden' ); |
| 208 | delete_option( 'woocommerce_extended_task_list_hidden' ); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Update order stats `status`. |
| 213 | */ |
| 214 | function wc_admin_update_280_order_status() { |
| 215 | global $wpdb; |
| 216 | |
| 217 | $wpdb->query( |
| 218 | "UPDATE {$wpdb->prefix}wc_order_stats refunds |
| 219 | INNER JOIN {$wpdb->prefix}wc_order_stats orders |
| 220 | ON orders.order_id = refunds.parent_id |
| 221 | SET refunds.status = orders.status |
| 222 | WHERE refunds.parent_id != 0" |
| 223 | ); |
| 224 | } |
| 225 | |
| 226 | /** |
| 227 | * Update the old task list options. |
| 228 | */ |
| 229 | function wc_admin_update_290_update_apperance_task_option() { |
| 230 | $is_actioned = get_option( 'woocommerce_task_list_appearance_complete', false ); |
| 231 | |
| 232 | $task = TaskLists::get_task( 'appearance' ); |
| 233 | if ( $task && $is_actioned ) { |
| 234 | $task->mark_actioned(); |
| 235 | } |
| 236 | |
| 237 | delete_option( 'woocommerce_task_list_appearance_complete' ); |
| 238 | } |
| 239 | |
| 240 | /** |
| 241 | * Delete the old woocommerce_default_homepage_layout option. |
| 242 | */ |
| 243 | function wc_admin_update_290_delete_default_homepage_layout_option() { |
| 244 | delete_option( 'woocommerce_default_homepage_layout' ); |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * Use woocommerce_admin_activity_panel_inbox_last_read from the user meta to set wc_admin_notes.is_read col. |
| 249 | */ |
| 250 | function wc_admin_update_300_update_is_read_from_last_read() { |
| 251 | global $wpdb; |
| 252 | $meta_key = 'woocommerce_admin_activity_panel_inbox_last_read'; |
| 253 | // phpcs:ignore |
| 254 | $users = get_users( "meta_key={$meta_key}&orderby={$meta_key}&fields=all_with_meta&number=1" ); |
| 255 | |
| 256 | if ( count( $users ) ) { |
| 257 | $last_read = current( $users )->{$meta_key}; |
| 258 | $date_in_utc = gmdate( 'Y-m-d H:i:s', intval( $last_read ) / 1000 ); |
| 259 | $wpdb->query( |
| 260 | $wpdb->prepare( |
| 261 | " |
| 262 | update {$wpdb->prefix}wc_admin_notes set is_read = 1 |
| 263 | where |
| 264 | date_created <= %s", |
| 265 | $date_in_utc |
| 266 | ) |
| 267 | ); |
| 268 | $wpdb->query( $wpdb->prepare( "delete from {$wpdb->usermeta} where meta_key=%s", $meta_key ) ); |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | /** |
| 273 | * Delete "is_primary" column from the wc_admin_notes table. |
| 274 | */ |
| 275 | function wc_admin_update_340_remove_is_primary_from_note_action() { |
| 276 | global $wpdb; |
| 277 | $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_admin_note_actions DROP COLUMN `is_primary`" ); |
| 278 | } |
| 279 | |
| 280 | /** |
| 281 | * Delete the deprecated remote inbox notifications option since transients are now used. |
| 282 | */ |
| 283 | function wc_update_670_delete_deprecated_remote_inbox_notifications_option() { |
| 284 | delete_option( 'wc_remote_inbox_notifications_specs' ); |
| 285 | } |