| 1 | Index: wp-admin/includes/plugin.php |
|---|
| 2 | =================================================================== |
|---|
| 3 | --- wp-admin/includes/plugin.php (revision 8554) |
|---|
| 4 | +++ wp-admin/includes/plugin.php (working copy) |
|---|
| 5 | @@ -157,7 +157,15 @@ |
|---|
| 6 | return $wp_plugins; |
|---|
| 7 | } |
|---|
| 8 | |
|---|
| 9 | -function is_plugin_active($plugin){ |
|---|
| 10 | +/** |
|---|
| 11 | + * Check whether the plugin is active by checking the active_plugins list. |
|---|
| 12 | + * |
|---|
| 13 | + * @since 2.5.0 |
|---|
| 14 | + * |
|---|
| 15 | + * @param string $plugin Base plugin path from plugins directory. |
|---|
| 16 | + * @return bool True, if in the active plugins list. False, not in the list. |
|---|
| 17 | + */ |
|---|
| 18 | +function is_plugin_active($plugin) { |
|---|
| 19 | return in_array($plugin, get_option('active_plugins')); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | @@ -277,6 +285,10 @@ |
|---|
| 23 | $errors = array(); |
|---|
| 24 | |
|---|
| 25 | foreach( $plugins as $plugin_file ) { |
|---|
| 26 | + // Run Uninstall hook |
|---|
| 27 | + if ( is_uninstallable_plugin( $plugin_file ) ) |
|---|
| 28 | + uninstall_plugin($plugin_file); |
|---|
| 29 | + |
|---|
| 30 | $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin_file) ); |
|---|
| 31 | // If plugin is in its own directory, recursively delete the directory. |
|---|
| 32 | if ( strpos($plugin_file, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory seperator AND that its not the root plugin folder |
|---|
| 33 | @@ -328,6 +340,66 @@ |
|---|
| 34 | return 0; |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | +/** |
|---|
| 38 | + * Whether the plugin can be uninstalled. |
|---|
| 39 | + * |
|---|
| 40 | + * @since {@internal Version Unknown}} |
|---|
| 41 | + * |
|---|
| 42 | + * @param string $plugin Plugin path to check. |
|---|
| 43 | + * @return bool Whether plugin can be uninstalled. |
|---|
| 44 | + */ |
|---|
| 45 | +function is_uninstallable_plugin($plugin) { |
|---|
| 46 | + $file = plugin_basename($plugin); |
|---|
| 47 | + |
|---|
| 48 | + $uninstallable_plugins = (array) get_option('uninstall_plugins'); |
|---|
| 49 | + if ( isset( $uninstallable_plugins[$file] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) |
|---|
| 50 | + return true; |
|---|
| 51 | + |
|---|
| 52 | + return false; |
|---|
| 53 | +} |
|---|
| 54 | + |
|---|
| 55 | +/** |
|---|
| 56 | + * Uninstall a single plugin. |
|---|
| 57 | + * |
|---|
| 58 | + * Calls the uninstall hook, if it is available. |
|---|
| 59 | + * |
|---|
| 60 | + * @param string $plugin Relative plugin path from Plugin Directory. |
|---|
| 61 | + */ |
|---|
| 62 | +function uninstall_plugin($plugin) { |
|---|
| 63 | + $file = plugin_basename($plugin); |
|---|
| 64 | + |
|---|
| 65 | + if ( is_plugin_active($file) ) |
|---|
| 66 | + return false; |
|---|
| 67 | + |
|---|
| 68 | + $uninstallable_plugins = (array) get_option('uninstall_plugins'); |
|---|
| 69 | + if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) { |
|---|
| 70 | + if ( isset( $uninstallable_plugins[$file] ) ) { |
|---|
| 71 | + unset($uninstallable_plugins[$file]); |
|---|
| 72 | + set_option('uninstall_plugins', $uninstallable_plugins); |
|---|
| 73 | + } |
|---|
| 74 | + unset($uninstallable_plugins); |
|---|
| 75 | + |
|---|
| 76 | + define('WP_UNINSTALL_PLUGIN', $file); |
|---|
| 77 | + include WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php'; |
|---|
| 78 | + |
|---|
| 79 | + return true; |
|---|
| 80 | + } |
|---|
| 81 | + |
|---|
| 82 | + if ( isset( $uninstallable_plugins[$file] ) ) { |
|---|
| 83 | + $callable = $uninstallable_plugins[$file]; |
|---|
| 84 | + unset($uninstallable_plugins[$file]); |
|---|
| 85 | + set_option('uninstall_plugins', $uninstallable_plugins); |
|---|
| 86 | + unset($uninstallable_plugins); |
|---|
| 87 | + |
|---|
| 88 | + include WP_PLUGIN_DIR . '/' . $file; |
|---|
| 89 | + |
|---|
| 90 | + add_action( 'uninstall_' . $file, $callable ); |
|---|
| 91 | + do_action( 'uninstall_' . $file ); |
|---|
| 92 | + |
|---|
| 93 | + deactivate_plugins($file, true); |
|---|
| 94 | + } |
|---|
| 95 | +} |
|---|
| 96 | + |
|---|
| 97 | // |
|---|
| 98 | // Menu |
|---|
| 99 | // |
|---|
| 100 | @@ -616,4 +688,4 @@ |
|---|
| 101 | return true; |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | -?> |
|---|
| 105 | +?> |
|---|
| 106 | \ No newline at end of file |
|---|
| 107 | Index: wp-includes/plugin.php |
|---|
| 108 | =================================================================== |
|---|
| 109 | --- wp-includes/plugin.php (revision 8554) |
|---|
| 110 | +++ wp-includes/plugin.php (working copy) |
|---|
| 111 | @@ -20,7 +20,7 @@ |
|---|
| 112 | */ |
|---|
| 113 | |
|---|
| 114 | /** |
|---|
| 115 | - * add_filter() - Hooks a function or method to a specific filter action. |
|---|
| 116 | + * Hooks a function or method to a specific filter action. |
|---|
| 117 | * |
|---|
| 118 | * Filters are the hooks that WordPress launches to modify text of various types |
|---|
| 119 | * before adding it to the database or sending it to the browser screen. Plugins |
|---|
| 120 | @@ -69,7 +69,7 @@ |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | /** |
|---|
| 124 | - * has_filter() - Check if any filter has been registered for a hook. |
|---|
| 125 | + * Check if any filter has been registered for a hook. |
|---|
| 126 | * |
|---|
| 127 | * @package WordPress |
|---|
| 128 | * @subpackage Plugin |
|---|
| 129 | @@ -99,7 +99,7 @@ |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | /** |
|---|
| 133 | - * apply_filters() - Call the functions added to a filter hook. |
|---|
| 134 | + * Call the functions added to a filter hook. |
|---|
| 135 | * |
|---|
| 136 | * The callback functions attached to filter hook <tt>$tag</tt> are invoked by |
|---|
| 137 | * calling this function. This function can be used to create a new filter hook |
|---|
| 138 | @@ -171,14 +171,14 @@ |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | /** |
|---|
| 142 | - * remove_filter() - Removes a function from a specified filter hook. |
|---|
| 143 | + * Removes a function from a specified filter hook. |
|---|
| 144 | * |
|---|
| 145 | * This function removes a function attached to a specified filter hook. This |
|---|
| 146 | * method can be used to remove default functions attached to a specific filter |
|---|
| 147 | * hook and possibly replace them with a substitute. |
|---|
| 148 | * |
|---|
| 149 | - * To remove a hook, the <tt>$function_to_remove</tt> and <tt>$priority</tt> arguments |
|---|
| 150 | - * must match when the hook was added. This goes for both filters and actions. No warning |
|---|
| 151 | + * To remove a hook, the $function_to_remove and $priority arguments must match |
|---|
| 152 | + * when the hook was added. This goes for both filters and actions. No warning |
|---|
| 153 | * will be given on removal failure. |
|---|
| 154 | * |
|---|
| 155 | * @package WordPress |
|---|
| 156 | @@ -208,7 +208,7 @@ |
|---|
| 157 | |
|---|
| 158 | |
|---|
| 159 | /** |
|---|
| 160 | - * current_filter() - Return the name of the current filter or action. |
|---|
| 161 | + * Return the name of the current filter or action. |
|---|
| 162 | * |
|---|
| 163 | * @package WordPress |
|---|
| 164 | * @subpackage Plugin |
|---|
| 165 | @@ -223,7 +223,7 @@ |
|---|
| 166 | |
|---|
| 167 | |
|---|
| 168 | /** |
|---|
| 169 | - * add_action() - Hooks a function on to a specific action. |
|---|
| 170 | + * Hooks a function on to a specific action. |
|---|
| 171 | * |
|---|
| 172 | * Actions are the hooks that the WordPress core launches at specific points |
|---|
| 173 | * during execution, or when specific events occur. Plugins can specify that |
|---|
| 174 | @@ -247,7 +247,7 @@ |
|---|
| 175 | |
|---|
| 176 | |
|---|
| 177 | /** |
|---|
| 178 | - * do_action() - Execute functions hooked on a specific action hook. |
|---|
| 179 | + * Execute functions hooked on a specific action hook. |
|---|
| 180 | * |
|---|
| 181 | * This function invokes all functions attached to action hook <tt>$tag</tt>. |
|---|
| 182 | * It is possible to create new action hooks by simply calling this function, |
|---|
| 183 | @@ -316,7 +316,7 @@ |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | /** |
|---|
| 187 | - * did_action() - Return the number times an action is fired. |
|---|
| 188 | + * Return the number times an action is fired. |
|---|
| 189 | * |
|---|
| 190 | * @package WordPress |
|---|
| 191 | * @subpackage Plugin |
|---|
| 192 | @@ -336,7 +336,7 @@ |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | /** |
|---|
| 196 | - * do_action_ref_array() - Execute functions hooked on a specific action hook, specifying arguments in an array. |
|---|
| 197 | + * Execute functions hooked on a specific action hook, specifying arguments in an array. |
|---|
| 198 | * |
|---|
| 199 | * @see do_action() This function is identical, but the arguments passed to |
|---|
| 200 | * the functions hooked to <tt>$tag</tt> are supplied using an array. |
|---|
| 201 | @@ -391,7 +391,7 @@ |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | /** |
|---|
| 205 | - * has_action() - Check if any action has been registered for a hook. |
|---|
| 206 | + * Check if any action has been registered for a hook. |
|---|
| 207 | * |
|---|
| 208 | * @package WordPress |
|---|
| 209 | * @subpackage Plugin |
|---|
| 210 | @@ -407,7 +407,7 @@ |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | /** |
|---|
| 214 | - * remove_action() - Removes a function from a specified action hook. |
|---|
| 215 | + * Removes a function from a specified action hook. |
|---|
| 216 | * |
|---|
| 217 | * This function removes a function attached to a specified action hook. This |
|---|
| 218 | * method can be used to remove default functions attached to a specific filter |
|---|
| 219 | @@ -432,7 +432,7 @@ |
|---|
| 220 | // |
|---|
| 221 | |
|---|
| 222 | /** |
|---|
| 223 | - * plugin_basename() - Gets the basename of a plugin. |
|---|
| 224 | + * Gets the basename of a plugin. |
|---|
| 225 | * |
|---|
| 226 | * This method extracts the name of a plugin from its filename. |
|---|
| 227 | * |
|---|
| 228 | @@ -456,7 +456,7 @@ |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | /** |
|---|
| 232 | - * register_activation_hook() - Hook a function on a plugin activation action hook. |
|---|
| 233 | + * Set the activation hook for a plugin. |
|---|
| 234 | * |
|---|
| 235 | * When a plugin is activated, the action 'activate_PLUGINNAME' hook is |
|---|
| 236 | * activated. In the name of this hook, PLUGINNAME is replaced with the name of |
|---|
| 237 | @@ -474,7 +474,7 @@ |
|---|
| 238 | * @access private |
|---|
| 239 | * |
|---|
| 240 | * @param string $file The filename of the plugin including the path. |
|---|
| 241 | - * @param string $function the function hooked to the 'activate_PLUGIN' action. |
|---|
| 242 | + * @param callback $function the function hooked to the 'activate_PLUGIN' action. |
|---|
| 243 | */ |
|---|
| 244 | function register_activation_hook($file, $function) { |
|---|
| 245 | $file = plugin_basename($file); |
|---|
| 246 | @@ -482,13 +482,14 @@ |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | /** |
|---|
| 250 | - * register_deactivation_hook() - Hook a function on a plugin deactivation action hook. |
|---|
| 251 | + * Set the deactivation hook for a plugin. |
|---|
| 252 | * |
|---|
| 253 | * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is |
|---|
| 254 | - * deactivated. In the name of this hook, PLUGINNAME is replaced with the name of |
|---|
| 255 | - * the plugin, including the optional subdirectory. For example, when the plugin |
|---|
| 256 | - * is located in <tt>wp-content/plugin/sampleplugin/sample.php</tt>, then the |
|---|
| 257 | - * name of this hook will become 'activate_sampleplugin/sample.php'. |
|---|
| 258 | + * deactivated. In the name of this hook, PLUGINNAME is replaced with the name |
|---|
| 259 | + * of the plugin, including the optional subdirectory. For example, when the |
|---|
| 260 | + * plugin is located in <tt>wp-content/plugin/sampleplugin/sample.php</tt>, then |
|---|
| 261 | + * the name of this hook will become 'activate_sampleplugin/sample.php'. |
|---|
| 262 | + * |
|---|
| 263 | * When the plugin consists of only one file and is (as by default) located at |
|---|
| 264 | * <tt>wp-content/plugin/sample.php</tt> the name of this hook will be |
|---|
| 265 | * 'activate_sample.php'. |
|---|
| 266 | @@ -500,7 +501,7 @@ |
|---|
| 267 | * @access private |
|---|
| 268 | * |
|---|
| 269 | * @param string $file The filename of the plugin including the path. |
|---|
| 270 | - * @param string $function the function hooked to the 'activate_PLUGIN' action. |
|---|
| 271 | + * @param callback $function the function hooked to the 'activate_PLUGIN' action. |
|---|
| 272 | */ |
|---|
| 273 | function register_deactivation_hook($file, $function) { |
|---|
| 274 | $file = plugin_basename($file); |
|---|
| 275 | @@ -508,15 +509,48 @@ |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | /** |
|---|
| 279 | - * _wp_call_all_hook() - Calls the 'all' hook, which will process the functions hooked into it. |
|---|
| 280 | + * Set the uninstallation hook for a plugin. |
|---|
| 281 | * |
|---|
| 282 | - * The 'all' hook passes all of the arguments or parameters that were used for the |
|---|
| 283 | - * hook, which this function was called for. |
|---|
| 284 | + * Registers the uninstall hook that will be called when the user clicks on the |
|---|
| 285 | + * uninstall link that calls for the plugin to uninstall itself. The link won't |
|---|
| 286 | + * be active unless the plugin hooks into the action. |
|---|
| 287 | * |
|---|
| 288 | - * This function is used internally for apply_filters(), do_action(), and do_action_ref_array() |
|---|
| 289 | - * and is not meant to be used from outside those functions. This function does not check for the |
|---|
| 290 | - * existence of the all hook, so it will fail unless the all hook exists prior to this function call. |
|---|
| 291 | + * The plugin should not run arbitrary code outside of functions, when |
|---|
| 292 | + * registering the uninstall hook. In order to run using the hook, the plugin |
|---|
| 293 | + * will have to be included, which means that any code laying outside of a |
|---|
| 294 | + * function will be run during the uninstall process. The plugin should not |
|---|
| 295 | + * hinder the uninstall process. |
|---|
| 296 | * |
|---|
| 297 | + * If the plugin can not be written without running code within the plugin, then |
|---|
| 298 | + * the plugin should create a file named 'uninstall.php' in the base plugin |
|---|
| 299 | + * folder. This file will be called, if it exists, during the uninstall process |
|---|
| 300 | + * bypassing the uninstall hook. The plugin, when using the 'uninstall.php' |
|---|
| 301 | + * should always check for the 'WP_UNINSTALLING_PLUGIN' constant, before |
|---|
| 302 | + * executing. |
|---|
| 303 | + * |
|---|
| 304 | + * @param string $file |
|---|
| 305 | + * @param callback $callback The callback to run when the hook is called. |
|---|
| 306 | + */ |
|---|
| 307 | +function register_uninstall_hook($file, $callback) { |
|---|
| 308 | + // The option should not be autoloaded, because it is not needed in most |
|---|
| 309 | + // cases. Emphasis should be put on using the 'uninstall.php' way of |
|---|
| 310 | + // uninstalling the plugin. |
|---|
| 311 | + $uninstallable_plugins = (array) get_option('uninstall_plugins'); |
|---|
| 312 | + $uninstallable_plugins[$file] = $callback; |
|---|
| 313 | + set_option('uninstall_plugins', $uninstallable_plugins); |
|---|
| 314 | +} |
|---|
| 315 | + |
|---|
| 316 | +/** |
|---|
| 317 | + * Calls the 'all' hook, which will process the functions hooked into it. |
|---|
| 318 | + * |
|---|
| 319 | + * The 'all' hook passes all of the arguments or parameters that were used for |
|---|
| 320 | + * the hook, which this function was called for. |
|---|
| 321 | + * |
|---|
| 322 | + * This function is used internally for apply_filters(), do_action(), and |
|---|
| 323 | + * do_action_ref_array() and is not meant to be used from outside those |
|---|
| 324 | + * functions. This function does not check for the existence of the all hook, so |
|---|
| 325 | + * it will fail unless the all hook exists prior to this function call. |
|---|
| 326 | + * |
|---|
| 327 | * @package WordPress |
|---|
| 328 | * @subpackage Plugin |
|---|
| 329 | * @since 2.5 |
|---|
| 330 | @@ -540,7 +574,7 @@ |
|---|
| 331 | } |
|---|
| 332 | |
|---|
| 333 | /** |
|---|
| 334 | - * _wp_filter_build_unique_id() - Build Unique ID for storage and retrieval |
|---|
| 335 | + * Build Unique ID for storage and retrieval. |
|---|
| 336 | * |
|---|
| 337 | * The old way to serialize the callback caused issues and this function is the |
|---|
| 338 | * solution. It works by checking for objects and creating an a new property in |
|---|
| 339 | @@ -549,12 +583,12 @@ |
|---|
| 340 | * |
|---|
| 341 | * It also allows for the removal of actions and filters for objects after they |
|---|
| 342 | * change class properties. It is possible to include the property $wp_filter_id |
|---|
| 343 | - * in your class and set it to "null" or a number to bypass the workaround. However |
|---|
| 344 | - * this will prevent you from adding new classes and any new classes will overwrite |
|---|
| 345 | - * the previous hook by the same class. |
|---|
| 346 | + * in your class and set it to "null" or a number to bypass the workaround. |
|---|
| 347 | + * However this will prevent you from adding new classes and any new classes |
|---|
| 348 | + * will overwrite the previous hook by the same class. |
|---|
| 349 | * |
|---|
| 350 | - * Functions and static method callbacks are just returned as strings and shouldn't |
|---|
| 351 | - * have any speed penalty. |
|---|
| 352 | + * Functions and static method callbacks are just returned as strings and |
|---|
| 353 | + * shouldn't have any speed penalty. |
|---|
| 354 | * |
|---|
| 355 | * @package WordPress |
|---|
| 356 | * @subpackage Plugin |
|---|