protected function format_plugin($plugin_file, $plugin_data) { $plugin = array(); $plugin['id'] = preg_replace("/(.+)\\.php\$/", "\$1", $plugin_file); $plugin['slug'] = $this->get_plugin_slug($plugin_file); $plugin['active'] = Jetpack::is_plugin_active($plugin_file); $plugin['name'] = $plugin_data['Name']; $plugin['plugin_url'] = $plugin_data['PluginURI']; $plugin['version'] = $plugin_data['Version']; $plugin['description'] = $plugin_data['Description']; $plugin['author'] = $plugin_data['Author']; $plugin['author_url'] = $plugin_data['AuthorURI']; $plugin['network'] = $plugin_data['Network']; $plugin['update'] = $this->get_plugin_updates($plugin_file); $plugin['next_autoupdate'] = date('Y-m-d H:i:s', wp_next_scheduled('wp_maybe_auto_update')); $plugin['autoupdate'] = in_array($plugin_file, Jetpack_Options::get_option('autoupdate_plugins', array())); $plugin['uninstallable'] = is_uninstallable_plugin($plugin_file); if (!empty($this->log[$plugin_file])) { $plugin['log'] = $this->log[$plugin_file]; } return $plugin; }
/** * Remove directory and files of a plugin for a single or list of plugin(s). * * If the plugins parameter list is empty, false will be returned. True when * completed. * * @since 2.6.0 * * @param array $plugins List of plugin * @param string $redirect Redirect to page when complete. * @return mixed */ function delete_plugins($plugins, $redirect = '') { global $wp_filesystem; if (empty($plugins)) { return false; } $checked = array(); foreach ($plugins as $plugin) { $checked[] = 'checked[]=' . $plugin; } ob_start(); $url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins'); if (false === ($credentials = request_filesystem_credentials($url))) { $data = ob_get_contents(); ob_end_clean(); if (!empty($data)) { include_once ABSPATH . 'wp-admin/admin-header.php'; echo $data; include ABSPATH . 'wp-admin/admin-footer.php'; exit; } return; } if (!WP_Filesystem($credentials)) { request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again $data = ob_get_contents(); ob_end_clean(); if (!empty($data)) { include_once ABSPATH . 'wp-admin/admin-header.php'; echo $data; include ABSPATH . 'wp-admin/admin-footer.php'; exit; } return; } if (!is_object($wp_filesystem)) { return new WP_Error('fs_unavailable', __('Could not access filesystem.')); } if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) { return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); } //Get the base plugin folder $plugins_dir = $wp_filesystem->wp_plugins_dir(); if (empty($plugins_dir)) { return new WP_Error('fs_no_plugins_dir', __('Unable to locate WordPress Plugin directory.')); } $plugins_dir = trailingslashit($plugins_dir); $errors = array(); foreach ($plugins as $plugin_file) { // Run Uninstall hook if (is_uninstallable_plugin($plugin_file)) { uninstall_plugin($plugin_file); } $this_plugin_dir = trailingslashit(dirname($plugins_dir . $plugin_file)); // If plugin is in its own directory, recursively delete the directory. if (strpos($plugin_file, '/') && $this_plugin_dir != $plugins_dir) { //base check on if plugin includes directory separator AND that its not the root plugin folder $deleted = $wp_filesystem->delete($this_plugin_dir, true); } else { $deleted = $wp_filesystem->delete($plugins_dir . $plugin_file); } if (!$deleted) { $errors[] = $plugin_file; } } if (!empty($errors)) { return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors))); } // Force refresh of plugin update information if ($current = get_site_transient('update_plugins')) { unset($current->response[$plugin_file]); set_site_transient('update_plugins', $current); } return true; }
$plugin_info[$plugin]['is_uninstallable'] = is_uninstallable_plugin($plugin); if (!$plugin_info[$plugin]['Network']) { $have_non_network_plugins = true; } } } else { // Locate all the files in that folder. $files = list_files(WP_PLUGIN_DIR . '/' . $plugin_slug); if ($files) { $files_to_delete = array_merge($files_to_delete, $files); } // Get plugins list from that folder. if ($folder_plugins = get_plugins('/' . $plugin_slug)) { foreach ($folder_plugins as $plugin_file => $data) { $plugin_info[$plugin_file] = _get_plugin_data_markup_translate($plugin_file, $data); $plugin_info[$plugin_file]['is_uninstallable'] = is_uninstallable_plugin($plugin); if (!$plugin_info[$plugin_file]['Network']) { $have_non_network_plugins = true; } } } // Add translation files. if (!empty($plugin_translations[$plugin_slug])) { $translations = $plugin_translations[$plugin_slug]; foreach ($translations as $translation => $data) { $files_to_delete[] = $plugin_slug . '-' . $translation . '.po'; $files_to_delete[] = $plugin_slug . '-' . $translation . '.mo'; } } } }
/** * Remove directory and files of a plugin for a list of plugins. * * @since 2.6.0 * * @global WP_Filesystem_Base $wp_filesystem * * @param array $plugins List of plugins to delete. * @param string $deprecated Deprecated. * @return bool|null|WP_Error True on success, false is $plugins is empty, WP_Error on failure. * Null if filesystem credentials are required to proceed. */ function delete_plugins( $plugins, $deprecated = '' ) { global $wp_filesystem; if ( empty($plugins) ) return false; $checked = array(); foreach( $plugins as $plugin ) $checked[] = 'checked[]=' . $plugin; ob_start(); $url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins'); if ( false === ($credentials = request_filesystem_credentials($url)) ) { $data = ob_get_contents(); ob_end_clean(); if ( ! empty($data) ){ include_once( ABSPATH . 'wp-admin/admin-header.php'); echo $data; include( ABSPATH . 'wp-admin/admin-footer.php'); exit; } return; } if ( ! WP_Filesystem($credentials) ) { request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again $data = ob_get_contents(); ob_end_clean(); if ( ! empty($data) ){ include_once( ABSPATH . 'wp-admin/admin-header.php'); echo $data; include( ABSPATH . 'wp-admin/admin-footer.php'); exit; } return; } if ( ! is_object($wp_filesystem) ) return new WP_Error('fs_unavailable', __('Could not access filesystem.')); if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); // Get the base plugin folder. $plugins_dir = $wp_filesystem->wp_plugins_dir(); if ( empty( $plugins_dir ) ) { return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress Plugin directory.' ) ); } $plugins_dir = trailingslashit( $plugins_dir ); $plugin_translations = wp_get_installed_translations( 'plugins' ); $errors = array(); foreach( $plugins as $plugin_file ) { // Run Uninstall hook. if ( is_uninstallable_plugin( $plugin_file ) ) { uninstall_plugin($plugin_file); } $this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) ); // If plugin is in its own directory, recursively delete the directory. if ( strpos( $plugin_file, '/' ) && $this_plugin_dir != $plugins_dir ) { //base check on if plugin includes directory separator AND that it's not the root plugin folder $deleted = $wp_filesystem->delete( $this_plugin_dir, true ); } else { $deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file ); } if ( ! $deleted ) { $errors[] = $plugin_file; continue; } // Remove language files, silently. $plugin_slug = dirname( $plugin_file ); if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) { $translations = $plugin_translations[ $plugin_slug ]; foreach ( $translations as $translation => $data ) { $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' ); $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' ); } } } // Remove deleted plugins from the plugin updates list. if ( $current = get_site_transient('update_plugins') ) { // Don't remove the plugins that weren't deleted. $deleted = array_diff( $plugins, $errors ); foreach ( $deleted as $plugin_file ) { unset( $current->response[ $plugin_file ] ); } set_site_transient( 'update_plugins', $current ); } if ( ! empty($errors) ) return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors)) ); return true; }
/** * @covers ::is_uninstallable_plugin */ public function test_is_uninstallable_plugin_true() { $plugin = $this->_create_plugin(); $uninstallable_plugins = (array) get_option('uninstall_plugins'); $uninstallable_plugins[$plugin[0]] = true; update_option('uninstall_plugins', $uninstallable_plugins); $this->assertTrue(is_uninstallable_plugin($plugin[0])); unset($uninstallable_plugins[$plugin[0]]); update_option('uninstall_plugins', $uninstallable_plugins); unlink($plugin[1]); }
/** * Uninstall a plugin on this site. */ function _wprp_uninstall_plugin($plugin) { global $wp_filesystem; if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { return new WP_Error('disallow-file-mods', __("File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote')); } include_once ABSPATH . 'wp-admin/includes/admin.php'; include_once ABSPATH . 'wp-admin/includes/upgrade.php'; include_once ABSPATH . 'wp-includes/update.php'; if (!_wpr_check_filesystem_access() || !WP_Filesystem()) { return new WP_Error('filesystem-not-writable', __('The filesystem is not writable with the supplied credentials', 'wpremote')); } $plugins_dir = $wp_filesystem->wp_plugins_dir(); if (empty($plugins_dir)) { return new WP_Error('missing-plugin-dir', __('Unable to locate WordPress Plugin directory.', 'wpremote')); } $plugins_dir = trailingslashit($plugins_dir); if (is_uninstallable_plugin($plugin)) { uninstall_plugin($plugin); } $this_plugin_dir = trailingslashit(dirname($plugins_dir . $plugin)); // If plugin is in its own directory, recursively delete the directory. if (strpos($plugin, '/') && $this_plugin_dir != $plugins_dir) { //base check on if plugin includes directory separator AND that it's not the root plugin folder $deleted = $wp_filesystem->delete($this_plugin_dir, true); } else { $deleted = $wp_filesystem->delete($plugins_dir . $plugin); } if ($deleted) { if ($current = get_site_transient('update_plugins')) { unset($current->response[$plugin]); set_site_transient('update_plugins', $current); } return array('status' => 'success'); } else { return new WP_Error('plugin-uninstall', __('Plugin uninstalled, but not deleted.', 'wpremote')); } }