WordPress.org

Make WordPress Core

Ticket #5625: 5625.r6603.diff

File 5625.r6603.diff, 11.1 KB (added by darkdragon, 6 years ago)

Patch that allows for dynamically adding of options and tables. Full patch with all of other three patches

  • wp-admin/includes/plugin.php

     
    190190        return 0; 
    191191} 
    192192 
     193/** 
     194* get_plugin_assets() retrieves the plugin's registered assets from the option 
     195* 
     196* Part of the uninstall process.  
     197* This function checks whether the plugin author has registered any assets 
     198* that can be uninstalled and if so returns a named array with those options. 
     199* 
     200* @link http://trac.wordpress.org/ticket/5625 
     201* 
     202* @param string $plugin_file the path to the plugin file, usually given by __FILE__ 
     203* @return array|bool the plugin's uninstallable assets, or false if there are none 
     204* 
     205*/ 
     206function get_plugin_assets( $plugin_file ) { 
     207        $plugin_assets = get_option( 'plugin_assets' ); 
     208        $plugin = plugin_basename( $plugin_file ); 
     209        if ( !is_array( $plugin_assets ) ) 
     210                return false; 
     211        if ( isset( $plugin_assets[$plugin] ) ) { 
     212                return $plugin_assets[$plugin]; 
     213        } else { 
     214                return false; 
     215        } 
     216} 
     217 
     218/** 
     219* is_plugin_uninstallable() checks if a plugin has registered any uninstallable assets 
     220* 
     221* Part of the uninstall process.  
     222* This function checks whether the plugin author has registered any assets 
     223* that can be uninstalled. 
     224* 
     225* @link http://trac.wordpress.org/ticket/5625 
     226* 
     227* @param string $plugin_file the path to the plugin file, usually given by __FILE__ 
     228* @return bool true if the plugin has assets that can be uninstalled 
     229* 
     230*/       
     231function is_plugin_uninstallable( $plugin_file ){ 
     232        $uninstallable_plugins = get_option( 'plugin_assets' ); 
     233        $plugin = plugin_basename( $plugin_file ); 
     234        if ( isset( $uninstallable_plugins[$plugin] ) ) { 
     235                return true; 
     236        } else { 
     237                return false; 
     238        } 
     239} 
     240 
     241 
     242/** 
     243 * delete_plugin_assets() - Delete the database tables and options created by a plugin 
     244 * 
     245 * Part of the uninstall process.  
     246 * This function retrieves the list of assets the plugin author registered, using 
     247 * register_plugin_assets and removes the database tables and options specified. 
     248 * 
     249 * @link http://trac.wordpress.org/ticket/5625 
     250 * 
     251 * @param string $plugin_file the path to the plugin 
     252 * @return bool returns true if the tables and options are no longer present 
     253 */ 
     254function delete_plugin_assets( $plugin_file ){ 
     255        global $wpdb; 
     256        $deletion_complete = true; 
     257        $uninstallable_plugins = get_option( 'plugin_assets' ); 
     258        $plugin = plugin_basename( $plugin_file ); 
     259        if ( isset( $uninstallable_plugins[$plugin] ) ) { 
     260                $plugin_assets = $uninstallable_plugins[$plugin]; 
     261                //remove tables 
     262                $remove_table_sql = 'DROP TABLE IF EXISTS `%s`'; 
     263                $check_table_sql = 'SELECT 1 FROM `%s` LIMIT 0'; 
     264                foreach( $plugin_assets['tables'] as $table ){ 
     265                        //filter 
     266                        $table = str_replace( '`' , '' , $table); 
     267                        $table = str_replace( ';' , '' , $table); 
     268                        $table = str_replace( '*' , '' , $table); 
     269                         
     270                        //check against core tables 
     271                        if ( !in_array( str_replace( $wpdb->prefix , '' , $table ) , $wpdb->tables ) ) { 
     272                                $sql = sprintf( $remove_table_sql , $table ); 
     273                                $wpdb->query( $sql ); 
     274                                //check if table is now gone 
     275                                if ( $wpdb->query( sprintf( $check_table_sql , $table ) ) ) { 
     276                                        $deletion_complete = false; 
     277                                } 
     278                        } 
     279                } 
     280                //remove options 
     281                foreach( $plugin_assets['options'] as $option ){ 
     282                        delete_option( $option ); 
     283                        if ( get_option( $option ) ) { 
     284                                $deletion_complete = false; 
     285                        }; 
     286                } 
     287                //remove assets from asset list 
     288                if ( $deletion_complete ) { 
     289                         unregister_plugin_assets( $plugin_file ); 
     290                } 
     291        }  
     292        return $deletion_complete; 
     293} 
     294 
     295 
    193296// 
    194297// Menu 
    195298// 
  • wp-admin/plugins.php

     
    2727                check_admin_referer('reactivate-all'); 
    2828                reactivate_all_plugins('plugins.php?errors=true'); 
    2929                wp_redirect('plugins.php?reactivate-all=true'); // overrides the ?error=true one above 
     30        } elseif ( 'uninstall' == $_GET['action'] ) { 
     31                check_admin_referer('uninstall-plugin_' . $_GET['plugin']); 
     32                $current = get_option('active_plugins'); 
     33                $plugin = trim($_GET['plugin']); 
     34                if ( validate_file($plugin) ) 
     35                        wp_die(__('Invalid plugin.')); 
     36                if ( ! file_exists(ABSPATH . PLUGINDIR . '/' . $plugin) ) 
     37                        wp_die(__('Plugin file does not exist.'));       
     38                if ( !in_array($plugin, $current ) && is_plugin_uninstallable( $plugin ) ) {     
     39                        $plugin_assets = get_plugin_assets( $plugin ); 
     40                        //check for a callback function 
     41                        if ( $plugin_assets['callback'] != NULL ) { 
     42                                //include the plugin file 
     43                                include_once( ABSPATH . PLUGINDIR . '/' . $plugin ); 
     44                                //create and call the action 
     45                                add_action( 'uninstall_plugin_' . $plugin , $plugin_assets['callback'] ); 
     46                                do_action( 'uninstall_plugin_' . $plugin ); 
     47                        } 
     48                        if ( !delete_plugin_assets( $plugin ) ) { 
     49                                wp_redirect('plugins.php?uninstalled=false'); 
     50                        } 
     51                } 
     52                wp_redirect('plugins.php?uninstalled=true'); 
    3053        } 
    3154 
    3255        exit; 
     
    5982        <div id="message" class="updated fade"><p><?php _e('All plugins <strong>deactivated</strong>.'); ?></p></div> 
    6083<?php elseif (isset($_GET['reactivate-all'])) : ?> 
    6184        <div id="message" class="updated fade"><p><?php _e('All plugins <strong>reactivated</strong>.'); ?></p></div> 
     85<?php elseif (isset($_GET['uninstalled']) && $_GET['uninstalled'] == 'true') : ?> 
     86<div id="message" class="updated fade"><p><?php _e('Plugin <strong>uninstalled</strong>.'); ?></p></div> 
     87<?php elseif (isset($_GET['uninstalled']) && $_GET['uninstalled'] != 'true') : ?> 
     88<div id="message" class="updated fade"> 
     89<p><?php _e('The plugin could not be completely uninstalled. Some database tables, options or files may still exist.'); ?></p> 
     90</div> 
    6291<?php endif; ?> 
    6392 
    6493<div class="wrap"> 
     
    128157                <td>$edit</td>"; 
    129158                echo" 
    130159        </tr>"; 
     160         
     161        if ( is_plugin_uninstallable( $plugin_file ) && (empty( $current_plugins ) || !in_array($plugin_file, $current_plugins) ) ) { 
     162                $plugin_data = get_plugin_data( ABSPATH . PLUGINDIR . '/' . $plugin_file ); 
     163                $toggle = "<a href='" . wp_nonce_url("plugins.php?action=uninstall&amp;plugin=$plugin_file", 'uninstall-plugin_' . $plugin_file) . "' title='".__('Uninstall this plugin')."' class='delete'><strong>".__("Uninstall all the options and settings (including database tables ) relating to ").$plugin_data['Name']."</strong></a>"; 
     164                        ?> 
     165                        <tr> 
     166                        <td colspan="5" style="border-top:1px solid #ccc; border-bottom:1px solid #ccc; background-color:#F9B7E0"><?php echo $toggle; ?></td> 
     167                        </tr> 
     168                        <?php 
     169                        }                
     170         
     171         
     172         
    131173        do_action( 'after_plugin_row', $plugin_file ); 
    132174        } 
    133175?> 
  • wp-includes/plugin.php

     
    593593                return $function[0].$function[1]; 
    594594} 
    595595 
     596/** 
     597* register_plugin_assets() - Add the plugin's database tables and option names as assets so they can be removed later. 
     598* 
     599* Part of the uninstall process.  
     600* When a plugin activates, and creates the database tables, and WordPress options it needs to run the plugin author 
     601* can register those database tables and WordPress options so that they will be removed when the plugin is uninstalled. 
     602* A callback can also be registered to handle more complex uninstall requirements. 
     603* 
     604* Note: This does not allow files to be registered as there is danger of getting paths wrong and removing 
     605* similarly named files in different paths. 
     606* 
     607* @link http://trac.wordpress.org/ticket/5625 
     608* 
     609* @param string $plugin_file the path to the plugin file, usually given by __FILE__ 
     610* @param callback $callback function name of the plugin's uninstaller, can be NULL 
     611* @param array $tables array of table names that should be dropped when the plugin is uninstalled 
     612* @param array $options array of option names that should be deleted when the plugin is uninstalled 
     613* 
     614*/ 
     615function register_plugin_assets( $plugin_file , $callback , $tables = array() , $options = array() ) { 
     616        $plugin_assets = get_option( 'plugin_assets' ); 
     617        $plugin = plugin_basename( $plugin_file ); 
     618 
     619        if ( !is_array( $plugin_assets ) ) 
     620                $plugin_assets = array(); 
     621 
     622        if( !isset($plugin_assets[$plugin]) ) 
     623                $plugin_assets[$plugin] = array( 'callback' => null, 'tables' => array(), 'options' => array() ); 
     624 
     625        if( !is_null( $callback ) ) { 
     626                $plugin_assets[$plugin]['callback'] = $callback; 
     627        } 
     628 
     629        if( is_array($options) && !empty($options) ) 
     630                $plugin_assets[$plugin]['options'] = array_merge( $options, $plugin_assets[$plugin]['options']); 
     631 
     632        if( is_array($tables) && !empty($tables) ) 
     633                $plugin_assets[$plugin]['tables'] = array_merge( $tables, $plugin_assets[$plugin]['tables']); 
     634 
     635        update_option( 'plugin_assets' , $plugin_assets ); 
     636} 
     637 
     638/** 
     639 * register_uninstall_hook() - Registers an uninstall callback that will be run when uninstalling the plugin. 
     640 * 
     641 * @param string $plugin_file Plugin file path 
     642 * @param callback $callback The hook that will be called during the plugin's uninstall process 
     643 */ 
     644function register_uninstall_hook($plugin_file, $callback) { 
     645        register_plugin_assets($plugin_file, $callback); 
     646} 
     647 
     648/** 
     649 * register_plugin_option_asset() - Registers option(s) that will be uninstalled. 
     650 * 
     651 * If there are already options available that will be uninstalled, then the $options 
     652 * will be added to the list. If there are no options already, then the options will 
     653 * just be set. 
     654 * 
     655 * This function is useful for dynamically adding options that should be uninstalled 
     656 * during the uninstall process and the plugin won't be used any longer. 
     657 * 
     658 * The options should be given as a list without any keys. 
     659 * 
     660 * @param string $plugin_file Plugin file path 
     661 * @param string|array $options Single option or list of options to uninstall 
     662 */ 
     663function register_plugin_option_asset($plugin_file, $options) { 
     664        if( !is_array($options) ) 
     665                $options = array( $options ); 
     666 
     667        register_plugin_assets($plugin_file, null, null, $options); 
     668} 
     669 
     670/** 
     671 * register_plugin_table_asset() - Registers table(s) that will be uninstalled. 
     672 * 
     673 * The table(s) should only be the ones that were added by your plugin and should 
     674 * not include the core plugins that WordPress installs. If you need to remove 
     675 * options then do so using the register_plugin_option_asset() or 
     676 * register_plugin_asset() function. 
     677 * 
     678 * The tables should be given as a list without any keys. 
     679 * 
     680 * @param string $plugin_file The path to the plugin file, usually given by __FILE__ 
     681 * @param string|array $tables Table or tables to uninstall 
     682 */ 
     683function register_plugin_table_asset($plugin_file, $tables) { 
     684        if( !is_array($tables) ) 
     685                $tables = array( $tables ); 
     686 
     687        register_plugin_assets($plugin_file, null, $tables); 
     688} 
     689 
     690/** 
     691* unregister_plugin_assets() - Unregisters the plugins uninstallable assets from the option 
     692* 
     693* @link http://trac.wordpress.org/ticket/5625 
     694* 
     695* @param string $plugin_file The path to the plugin file, usually given by __FILE__ 
     696* 
     697*/ 
     698function unregister_plugin_assets( $plugin_file ){ 
     699        $plugin_assets = get_option( 'plugin_assets' ); 
     700        $plugin = plugin_basename( $plugin_file ); 
     701        if ( isset( $plugin_assets[$plugin] ) ) { 
     702                unset($plugin_assets[$plugin]); 
     703                update_option( 'plugin_assets' , $plugin_assets ); 
     704        } 
     705} 
     706 
    596707?>