Changeset 1176158
- Timestamp:
- 06/07/2015 12:08:13 PM (11 years ago)
- Location:
- upress-link
- Files:
-
- 32 added
- 5 edited
-
branches/1.0.0 (added)
-
branches/1.0.0/admin (added)
-
branches/1.0.0/admin/css (added)
-
branches/1.0.0/admin/css/lc_switch.css (added)
-
branches/1.0.0/admin/css/upress-link.css (added)
-
branches/1.0.0/admin/js (added)
-
branches/1.0.0/admin/js/lc_switch.min.js (added)
-
branches/1.0.0/admin/js/upress-link.js (added)
-
branches/1.0.0/admin/options.php (added)
-
branches/1.0.0/includes (added)
-
branches/1.0.0/index.php (added)
-
branches/1.0.0/languages (added)
-
branches/1.0.0/languages/upress-link.pot (added)
-
branches/1.0.0/readme.txt (added)
-
branches/1.0.0/screenshot-1.jpg (added)
-
branches/1.0.0/upress-link.php (added)
-
branches/1.1.0 (added)
-
branches/1.1.0/admin (added)
-
branches/1.1.0/admin/css (added)
-
branches/1.1.0/admin/css/lc_switch.css (added)
-
branches/1.1.0/admin/css/upress-link.css (added)
-
branches/1.1.0/admin/js (added)
-
branches/1.1.0/admin/js/lc_switch.min.js (added)
-
branches/1.1.0/admin/js/upress-link.js (added)
-
branches/1.1.0/admin/options.php (added)
-
branches/1.1.0/includes (added)
-
branches/1.1.0/index.php (added)
-
branches/1.1.0/languages (added)
-
branches/1.1.0/languages/upress-link.pot (added)
-
branches/1.1.0/readme.txt (added)
-
branches/1.1.0/screenshot-1.jpg (added)
-
branches/1.1.0/upress-link.php (added)
-
trunk/admin/css/upress-link.css (modified) (1 diff)
-
trunk/admin/js/upress-link.js (modified) (2 diffs)
-
trunk/admin/options.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/upress-link.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
upress-link/trunk/admin/css/upress-link.css
r1135956 r1176158 6 6 .no-api-key, .api-error, .api-success { 7 7 display: none; 8 white-space: pre; 8 9 } 9 10 #api_key { -
upress-link/trunk/admin/js/upress-link.js
r1135956 r1176158 87 87 toggleSwitchSpinner(self, 'hide'); 88 88 }); 89 89 90 }).on('click', 'button[data-action], input[type=button][data-action]', function(e) { 90 91 e.preventDefault(); 91 92 92 93 var self = $(this); 93 var wrapper = self.parents('.ajax-button-wrapper'); 94 self.css({ 95 width: self.outerWidth(), 96 height: self.outerHeight() 97 }).find('.text').fadeOut('fast', function() { 98 self.find('.spinner').fadeIn('fast'); 99 }).end().attr('disabled', true); 94 startAjaxSpinner(self); 100 95 101 96 $.post(ajaxurl, { … … 120 115 } 121 116 122 self.find('.spinner').fadeOut('fast', function () { 123 self.find('.text').fadeIn('fast').end().css( { 124 width: '', 125 height: '' 126 }).removeAttr('disabled'); 127 }); 128 }); 117 endAjaxSpinner(self); 118 }); 119 120 }).on('click', '.media-path-fix-button', function(e) { 121 e.preventDefault(); 122 123 var self = $(this); 124 startAjaxSpinner(self); 125 126 $.post(ajaxurl, { 127 'action': 'fix_media_upload_path', 128 '_nonce': upressAjax._nonce 129 }, function(response) { 130 console.log(response); 131 132 if (response.status == "fail") { 133 flashErrorMessage(response.data.message); 134 } 135 if(response.status == "success") { 136 if(self.data('success-message')) { 137 flashSuccessMessage(self.data('success-message')); 138 } else { 139 flashSuccessMessage(upressAjax.requestSuccess); 140 } 141 } 142 143 endAjaxSpinner(self); 144 }); 145 }).on('click', '.search-and-replace-button', function(e) { 146 e.preventDefault(); 147 148 var self = $(this); 149 startAjaxSpinner(self); 150 151 $.post(ajaxurl, { 152 'action': 'database_search_and_replace', 153 'replace_from': $('.search-and-replace-from').val(), 154 'replace_to': $('.search-and-replace-to').val(), 155 '_nonce': upressAjax._nonce 156 }, function(response) { 157 console.log(response); 158 159 if (response.status == "fail") { 160 flashErrorMessage(response.errors_msg); 161 } 162 if(response.status == "success") { 163 $('.search-and-replace-from').val(''); 164 $('.search-and-replace-to').val(''); 165 166 if(self.data('success-message')) { 167 flashSuccessMessage(self.data('success-message')); 168 } else { 169 if(response.success_msg) { 170 flashSuccessMessage(response.success_msg); 171 } else { 172 flashSuccessMessage(upressAjax.requestSuccess); 173 } 174 } 175 } 176 177 endAjaxSpinner(self); 178 }); 179 }); 180 }; 181 182 var startAjaxSpinner = function(self) { 183 var wrapper = self.parents('.ajax-button-wrapper'); 184 self.css({ 185 width: self.outerWidth(), 186 height: self.outerHeight() 187 }).find('.text').fadeOut('fast', function() { 188 self.find('.spinner').fadeIn('fast'); 189 }).end().attr('disabled', true); 190 }; 191 var endAjaxSpinner = function(self) { 192 self.find('.spinner').fadeOut('fast', function () { 193 self.find('.text').fadeIn('fast').end().css( { 194 width: '', 195 height: '' 196 }).removeAttr('disabled'); 129 197 }); 130 198 }; 131 199 132 200 var initButtons = function() { 133 $('button[data-action] ').each(function() {201 $('button[data-action], button[data-ajax-spinner]').each(function() { 134 202 var self = $(this); 135 203 var text = self.text(); -
upress-link/trunk/admin/options.php
r1135956 r1176158 47 47 </form> 48 48 49 50 <hr> 51 <h3><?php esc_attr_e( 'More actions', $this->text_domain ); ?></h3> 52 <div class="wrap"> 53 <h4><?php esc_attr_e( 'Fix media upload path', $this->text_domain ); ?></h4> 54 <p><?php esc_attr_e( 'Sometimes after migrating a WordPress installation the media path is not set correctly and breaks uploading media content. This will fix the issue and correct the upload path.', $this->text_domain ); ?></p> 55 <p><button class="button-secondary media-path-fix-button" type="button" data-ajax-spinner><?php esc_attr_e( 'Run media path fix', $this->text_domain ); ?></button></p> 56 57 <h4><?php esc_attr_e( 'Database search and replace', $this->text_domain ); ?></h4> 58 <p><?php esc_attr_e( 'This will allow you to replace a text in your entire website in a simple click of a button', $this->text_domain ); ?></p> 59 <p> 60 <table class="form-table"> 61 <tr valign="top"> 62 <th scope="row"><?php esc_attr_e( 'Search:', $this->text_domain ); ?></th> 63 <td><input type="text" class="regular-text search-and-replace-from" /></td> 64 </tr> 65 <tr valign="top"> 66 <th scope="row"><?php esc_attr_e( 'Replace:', $this->text_domain ); ?></th> 67 <td><input type="text" class="regular-text search-and-replace-to" /></td> 68 </tr> 69 </table> 70 71 <button class="button-secondary search-and-replace-button" type="button" data-ajax-spinner><?php esc_attr_e( 'Search and replace', $this->text_domain ); ?></button> 72 </p> 73 </div> 74 75 49 76 <?php if( $is_api_key_set ) : ?> 50 77 <hr> … … 198 225 <input type="hidden" id="api-key-valid" value="<?php echo (int)$is_api_key_correct; ?>"> 199 226 227 228 <hr> 200 229 <span class="description"><?php esc_attr_e( '*Updates are queued and refreshed 1 minute after the update.', $this->text_domain ); ?></span> -
upress-link/trunk/readme.txt
r1135956 r1176158 53 53 54 54 == Changelog == 55 = 1.1 = 56 1. Added option to fix media upload path 57 1. Added options to search and replace in database 55 58 = 1.0 = 56 59 Initial release -
upress-link/trunk/upress-link.php
r1135956 r1176158 29 29 die; 30 30 } 31 define( 'UPL_VERSION', '1. 0.0' );31 define( 'UPL_VERSION', '1.1.0' ); 32 32 define( 'UPL_PATH', dirname( __FILE__ ) ); 33 33 define( 'UPL_PATH_INCLUDES', dirname( __FILE__ ) . '/includes' ); … … 52 52 add_action( 'admin_enqueue_scripts', array( $this, 'upl_admin_enqueue_scripts' ) ); 53 53 54 //ajax actions 54 55 add_action( 'wp_ajax_check_api_key', array( $this, 'upl_ajax_check_api_key' ) ); 55 56 add_action( 'wp_ajax_send_request', array( $this, 'upl_ajax_send_request' ) ); 57 58 add_action( 'wp_ajax_fix_media_upload_path', array( $this, 'upl_ajax_fix_media_upload_path' ) ); 59 add_action( 'wp_ajax_database_search_and_replace', array( $this, 'upl_ajax_database_search_and_replace' ) ); 56 60 } 57 61 … … 199 203 exit; 200 204 } 205 function upl_ajax_fix_media_upload_path() { 206 global $wpdb; 207 208 $nonce = $_POST['_nonce']; 209 if ( ! wp_verify_nonce( $nonce, $this->plugin_slug . '_ajax' ) ) { wp_die( 'Not authorized!' ); } 210 if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); } 211 212 $result = $wpdb->update( $wpdb->options, array( 'option_value' => null ), array( 'option_name' => 'upload_path' ) ); 213 214 $response = array( 215 'status' => ( $result === false ? 'fail' : 'success' ), 216 'data' => ( $result === false ? $wpdb->last_error : $wpdb->last_query ), 217 'debug' => $wpdb 218 ); 219 220 $response = json_encode( $response ); 221 header( "Content-Type: application/json" ); 222 echo $response; 223 exit; 224 } 225 function upl_ajax_database_search_and_replace() { 226 global $wpdb; 227 228 $nonce = $_POST['_nonce']; 229 if ( ! wp_verify_nonce( $nonce, $this->plugin_slug . '_ajax' ) ) { wp_die( 'Not authorized!' ); } 230 if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); } 231 232 $search = $_POST['replace_from']; 233 $replace = $_POST['replace_to']; 234 235 if( ! isset( $search ) || ! isset( $replace ) ) wp_die( 'Something is missing!' ); 236 237 $result = $wpdb->get_results( 238 'SHOW TABLES', 239 ARRAY_N 240 ); 241 /*$result = $wpdb->query( 242 $wpdb->prepare( 243 'SHOW TABLES' 244 ) 245 );*/ 246 $tables = array(); 247 foreach ( $result as $res ) 248 { 249 $tables[] = $res[0]; 250 } 251 252 $report = array( 'tables' => 0, 253 'rows' => 0, 254 'change' => 0, 255 'updates' => 0, 256 'start' => microtime( ), 257 'end' => microtime( ), 258 'errors' => array( ), 259 ); 260 261 if ( is_array( $tables ) && ! empty( $tables ) ) { 262 foreach( $tables as $table ) { 263 $report[ 'tables' ]++; 264 265 $columns = array( ); 266 267 $fields = $wpdb->get_results( 'DESCRIBE ' . $table, ARRAY_A ); 268 foreach( $fields as $column ) { 269 $columns[ $column[ 'Field' ] ] = $column[ 'Key' ] == 'PRI' ? true : false; 270 } 271 272 $rows_result = $wpdb->get_row( 'SELECT COUNT(*) FROM ' . $table, ARRAY_N ); 273 $row_count = $rows_result[ 0 ]; 274 if ( $row_count == 0 ) 275 continue; 276 277 $page_size = 50000; 278 $pages = ceil( $row_count / $page_size ); 279 280 for( $page = 0; $page < $pages; $page++ ) { 281 $current_row = 0; 282 $start = $page * $page_size; 283 $end = $start + $page_size; 284 // Grab the content of the table 285 $data = $wpdb->get_results( sprintf( 'SELECT * FROM %s LIMIT %d, %d', $table, $start, $end ), ARRAY_A ); 286 287 if ( ! $data ) 288 $report[ 'errors' ][] = mysql_error( ); 289 290 foreach( $data as $row ) { 291 $report[ 'rows' ]++; // Increment the row counter 292 $current_row++; 293 294 $update_sql = array( ); 295 $where_sql = array( ); 296 $upd = false; 297 298 foreach( $columns as $column => $primary_key ) { 299 $edited_data = $data_to_fix = $row[ $column ]; 300 301 // Run a search replace on the data that'll respect the serialisation. 302 $edited_data = $this->recursive_unserialize_replace( $search, $replace, $data_to_fix ); 303 304 // Something was changed 305 if ( $edited_data != $data_to_fix ) { 306 $report[ 'change' ]++; 307 $update_sql[] = $column . ' = "' . esc_sql( $edited_data ) . '"'; 308 $upd = true; 309 } 310 311 if ( $primary_key ) 312 $where_sql[] = $column . ' = "' . esc_sql( $data_to_fix ) . '"'; 313 } 314 315 if ( $upd && ! empty( $where_sql ) ) { 316 $sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) ); 317 $result = $wpdb->get_results( $sql, ARRAY_A ); 318 if ( ! $result ) 319 $report[ 'errors' ][] = mysql_error( ); 320 else 321 $report[ 'updates' ]++; 322 323 } elseif ( $upd ) { 324 $report[ 'errors' ][] = sprintf( '"%s" has no primary key, manual change needed on row %s.', $table, $current_row ); 325 } 326 } 327 } 328 } 329 } 330 331 $report[ 'end' ] = microtime( ); 332 333 $errors = ''; 334 if ( ! empty( $report[ 'errors' ] ) && is_array( $report[ 'errors' ] ) ) { 335 foreach( $report[ 'errors' ] as $error ) 336 $errors .= $error . "\n"; 337 } 338 $time = array_sum( explode( ' ', $report[ 'end' ] ) ) - array_sum( explode( ' ', $report[ 'start' ] ) ); 339 340 $response = array( 341 'status' => ( $result === false ? 'fail' : 'success' ), 342 'data' => ( $result === false ? $wpdb->last_error : $report ), 343 'debug' => $wpdb, 344 'time' => $time, 345 'success_msg' => sprintf( __( 'Replace completed for the text "%s" which was replaced by "%s". %d tables scanned with %d total rows. Replacement took %f seconds.', $this->text_domain ), 346 $search, $replace, $report[ 'tables' ], $report[ 'rows' ], $report[ 'change' ], $report[ 'updates' ], $time ), 347 'errors_msg' => $errors 348 ); 349 350 $response = json_encode( $response ); 351 header( "Content-Type: application/json" ); 352 echo $response; 353 exit; 354 } 201 355 202 356 … … 224 378 } 225 379 } 380 381 382 /** 383 * Take a serialised array and unserialise it replacing elements as needed and 384 * unserialising any subordinate arrays and performing the replace on those too. 385 * 386 * @param string $from String we're looking to replace. 387 * @param string $to What we want it to be replaced with 388 * @param array $data Used to pass any subordinate arrays back to in. 389 * @param bool $serialised Does the array passed via $data need serialising. 390 * 391 * @return array The original array with all elements replaced as needed. 392 */ 393 private function recursive_unserialize_replace( $from = '', $to = '', $data = '', $serialised = false ) { 394 // some unseriliased data cannot be re-serialised eg. SimpleXMLElements 395 try { 396 397 if ( is_string( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) { 398 $data = $this->recursive_unserialize_replace( $from, $to, $unserialized, true ); 399 } 400 401 elseif ( is_array( $data ) ) { 402 $_tmp = array( ); 403 foreach ( $data as $key => $value ) { 404 $_tmp[ $key ] = $this->recursive_unserialize_replace( $from, $to, $value, false ); 405 } 406 407 $data = $_tmp; 408 unset( $_tmp ); 409 } 410 411 else { 412 if ( is_string( $data ) ) 413 $data = str_replace( $from, $to, $data ); 414 } 415 416 if ( $serialised ) 417 return serialize( $data ); 418 419 } catch( Exception $error ) { 420 421 } 422 423 return $data; 424 } 226 425 } 227 426 new uPress_Link();
Note: See TracChangeset
for help on using the changeset viewer.