Make WordPress Core

Ticket #5625: 5625.r6603.diff

File 5625.r6603.diff, 11.1 KB (added by darkdragon, 17 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?>