validate_params( 'action' ); $plugins = isset( $_POST['plugin'] ) ? explode( '||', sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) ) : ''; $action_items = array(); include_once ABSPATH . '/wp-admin/includes/plugin.php'; // NOSONAR -- WP compatible. include_once ABSPATH . 'wp-admin/includes/file.php'; // NOSONAR -- WP compatible get_home_path(). include_once ABSPATH . 'wp-admin/includes/misc.php'; // NOSONAR -- WP compatible extract_from_markers(). if ( 'activate' === $action ) { foreach ( $plugins as $plugin ) { if ( $plugin !== $mainWPChild->plugin_slug ) { $thePlugin = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); if ( null !== $thePlugin && '' !== $thePlugin ) { if ( 'quotes-collection/quotes-collection.php' === $plugin ) { activate_plugin( $plugin, '', false, true ); } else { activate_plugin( $plugin ); } $action_items[ $plugin ] = array( 'name' => $thePlugin['Name'], 'version' => $thePlugin['Version'], 'slug' => $plugin, ); } } } } elseif ( 'deactivate' === $action ) { include_once ABSPATH . '/wp-admin/includes/plugin.php'; // NOSONAR -- WP compatible. foreach ( $plugins as $plugin ) { if ( $plugin !== $mainWPChild->plugin_slug ) { $thePlugin = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); if ( null !== $thePlugin && '' !== $thePlugin ) { deactivate_plugins( $plugin ); $action_items[ $plugin ] = array( 'name' => $thePlugin['Name'], 'version' => $thePlugin['Version'], 'slug' => $plugin, ); } } } } elseif ( 'delete' === $action ) { $this->delete_plugins( $plugins, $output ); if ( ! empty( $output ) ) { $action_items = $output; } } elseif ( 'changelog_info' === $action ) { include_once ABSPATH . '/wp-admin/includes/plugin-install.php'; // NOSONAR -- WP compatible. $_slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : ''; $api = plugins_api( 'plugin_information', array( 'slug' => $_slug, ) ); $information['update'] = $api; } else { $information['status'] = 'FAIL'; } // phpcs:enable if ( ! isset( $information['status'] ) ) { $information['status'] = 'SUCCESS'; } if ( 'changelog_info' !== $action ) { $information['sync'] = MainWP_Child_Stats::get_instance()->get_site_stats( array(), false ); } $information['other_data'] = array( 'plugin_action_data' => $action_items, ); MainWP_Helper::write( $information ); } /** * Method delete_plugins() * * Delete a plugin from the Child Site. * * @param array $plugins An array of plugins to delete. * @param array $output An array output data. * * @uses get_plugin_data() Parses the plugin contents to retrieve plugin’s metadata. * @see https://developer.wordpress.org/reference/functions/get_plugin_data/ * * @uses deactivate_plugin() Deactivate a single plugin or multiple plugins. * @see https://developer.wordpress.org/reference/functions/deactivate_plugin/ * * @uses is_plugin_active() Determines whether a plugin is active. * @see https://developer.wordpress.org/reference/functions/is_plugin_active/ * * @uses \MainWP\Child\MainWP_Helper::check_wp_filesystem() * * @used-by \MainWP\Child\MainWP_Child_Install::plugin_action() Plugin Activate, Deactivate & Delete actions. */ private function delete_plugins( $plugins, &$output = array() ) { //phpcs:ignore -- NOSONAR - complex. /** * MainWP Child instance. * * @global object */ global $mainWPChild; include_once ABSPATH . '/wp-admin/includes/plugin.php'; // NOSONAR -- WP compatible. if ( file_exists( ABSPATH . '/wp-admin/includes/screen.php' ) ) { include_once ABSPATH . '/wp-admin/includes/screen.php'; // NOSONAR -- WP compatible. } include_once ABSPATH . '/wp-admin/includes/file.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/template.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/misc.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-direct.php'; // NOSONAR -- WP compatible. MainWP_Helper::check_wp_filesystem(); $pluginUpgrader = new \Plugin_Upgrader(); $all_plugins = get_plugins(); foreach ( $plugins as $plugin ) { if ( $plugin !== $mainWPChild->plugin_slug && isset( $all_plugins[ $plugin ] ) ) { $old_plugin = $all_plugins[ $plugin ]; if ( is_plugin_active( $plugin ) ) { $thePlugin = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); if ( null !== $thePlugin && '' !== $thePlugin ) { deactivate_plugins( $plugin ); } } $tmp['plugin'] = $plugin; if ( true === $pluginUpgrader->delete_old_plugin( null, null, null, $tmp ) ) { $args = array( 'action' => 'delete', 'Name' => $old_plugin['Name'], ); do_action( 'mainwp_child_plugin_action', $args ); $output[ $plugin ] = array( 'name' => $old_plugin['Name'], 'version' => $old_plugin['Version'], 'slug' => $plugin, ); } } } } /** * Method theme_action() * * Theme Activate, Deactivate & Delete actions. * * @uses wp_get_theme() Gets a WP_Theme object for a theme. * @see https://developer.wordpress.org/reference/functions/wp_get_theme/ * * @uses switch_theme() Switches the theme. * @see https://developer.wordpress.org/reference/functions/switch_theme/ * * @uses \MainWP\Child\MainWP_Child_Stats::get_site_stats() * @uses \MainWP\Child\MainWP_Helper::check_wp_filesystem() * @uses \MainWP\Child\MainWP_Helper::write() */ public function theme_action() { // phpcs:ignore -- NOSONAR - Current complexity is the only way to achieve desired results, pull request solutions appreciated. // phpcs:disable WordPress.Security.NonceVerification $action = MainWP_System::instance()->validate_params( 'action' ); $theme = isset( $_POST['theme'] ) ? sanitize_text_field( wp_unslash( $_POST['theme'] ) ) : ''; $action_items = array(); $deactivate_theme = array(); // phpcs:enable if ( 'activate' === $action ) { include_once ABSPATH . '/wp-admin/includes/theme.php'; // NOSONAR -- WP compatible. $theTheme = wp_get_theme( $theme ); if ( null !== $theTheme && '' !== $theTheme ) { $current_theme = wp_get_theme()->get( 'Name' ); $deactivate_theme[ $current_theme ] = array( 'name' => $current_theme, 'version' => wp_get_theme()->display( 'Version', true, false ), 'slug' => wp_get_theme()->get_stylesheet(), ); switch_theme( $theTheme['Template'], $theTheme['Stylesheet'] ); $action_items[ $theme ] = array( 'name' => $theTheme->get( 'Name' ), 'version' => $theTheme->display( 'Version', true, false ), 'slug' => $theTheme->get_stylesheet(), ); } } elseif ( 'delete' === $action ) { include_once ABSPATH . '/wp-admin/includes/theme.php'; // NOSONAR -- WP compatible. if ( file_exists( ABSPATH . '/wp-admin/includes/screen.php' ) ) { // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/screen.php'; // NOSONAR -- WP compatible. } include_once ABSPATH . '/wp-admin/includes/file.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/template.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/misc.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-direct.php'; // NOSONAR -- WP compatible. MainWP_Helper::check_wp_filesystem(); $themeUpgrader = new \Theme_Upgrader(); $theme_name = wp_get_theme()->get_stylesheet(); $parent = wp_get_theme()->parent(); $parent_name = $parent ? $parent->get_stylesheet() : ''; $themes = explode( '||', $theme ); $themes = array_filter( $themes ); if ( count( $themes ) === 1 ) { $themeToDelete = current( $themes ); if ( $themeToDelete === $theme_name ) { $information['error']['is_activated_theme'] = $themeToDelete; MainWP_Helper::write( $information ); return; } elseif ( $themeToDelete === $parent_name ) { $information['error']['is_activated_parent'] = $themeToDelete; MainWP_Helper::write( $information ); return; } } foreach ( $themes as $themeToDelete ) { if ( $themeToDelete === $theme_name ) { $information['error']['is_activated_theme'] = $themeToDelete; } elseif ( $themeToDelete === $parent_name ) { $information['error']['is_activated_parent'] = $themeToDelete; } if ( $themeToDelete !== $theme_name && $themeToDelete !== $parent_name ) { $theTheme = wp_get_theme( $themeToDelete ); if ( null !== $theTheme && '' !== $theTheme ) { $tmp['theme'] = $theTheme->stylesheet; // to fix delete parent theme issue. if ( true === $themeUpgrader->delete_old_theme( null, null, null, $tmp ) ) { $args = array( 'action' => 'delete', 'Name' => $theTheme['Name'], ); do_action( 'mainwp_child_theme_action', $args ); $action_items[ $themeToDelete ] = array( 'name' => $theTheme->get( 'Name' ), 'version' => $theTheme->display( 'Version', true, false ), 'slug' => $theTheme->get_stylesheet(), ); } } } } } else { $information['status'] = 'FAIL'; } if ( ! isset( $information['status'] ) ) { $information['status'] = 'SUCCESS'; } $information['sync'] = MainWP_Child_Stats::get_instance()->get_site_stats( array(), false ); $information['other_data'] = array( 'theme_action_data' => $action_items, ); if ( 'activate' === $action && ! empty( $deactivate_theme ) ) { $information['other_data']['theme_deactivate_data'] = $deactivate_theme; } MainWP_Helper::write( $information ); } /** * Method install_plugin_theme() * * Plugin & Theme Installation functions. * * @uses \MainWP\Child\MainWP_Child_Install::require_files() Include necessary files. * @uses \MainWP\Child\MainWP_Child_Install::after_installed() After plugin or theme has been installed. * @uses \MainWP\Child\MainWP_Child_Install::no_ssl_filter_function() Hook to set ssl verify value. * @uses \MainWP\Child\MainWP_Child_Install::try_second_install() Alternative installation method. * @uses \MainWP\Child\MainWP_Helper::check_wp_filesystem() * @uses \MainWP\Child\MainWP_Helper::instance()->error() * @uses \MainWP\Child\MainWP_Helper::get_class_name() * @uses \MainWP\Child\MainWP_Helper::write() */ public function install_plugin_theme() { //phpcs:ignore -- NOSONAR - complex. MainWP_Helper::check_wp_filesystem(); // phpcs:disable WordPress.Security.NonceVerification if ( ! isset( $_POST['type'] ) || ! isset( $_POST['url'] ) || ( 'plugin' !== $_POST['type'] && 'theme' !== $_POST['type'] ) || '' === $_POST['url'] ) { MainWP_Helper::instance()->error( esc_html__( 'Plugin or theme not specified, or missing required data. Please reload the page and try again.', 'mainwp-child' ) ); } $type = sanitize_text_field( wp_unslash( $_POST['type'] ) ); $this->require_files(); $urlgot = isset( $_POST['url'] ) ? json_decode( stripslashes( wp_unslash( $_POST['url'] ) ) ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $urls = array(); if ( ! is_array( $urlgot ) ) { $urls[] = $urlgot; } else { $urls = $urlgot; } // ensure admin upgrade classes are available. if ( ! class_exists( '\Automatic_Upgrader_Skin' ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // NOSONAR -ok. require_once ABSPATH . 'wp-admin/includes/file.php'; // NOSONAR -ok. require_once ABSPATH . 'wp-admin/includes/plugin.php'; // NOSONAR -ok. } // To fix conflict. if ( is_plugin_active( 'git-updater/git-updater.php' ) ) { remove_all_filters( 'upgrader_source_selection' ); } $install_results = array(); $result = array(); $install_items = array(); foreach ( $urls as $url ) { $skin = new \Automatic_Upgrader_Skin(); $installer = new \WP_Upgrader( $skin ); $ssl_verify = true; // @see wp-admin/includes/class-wp-upgrader.php if ( isset( $_POST['sslVerify'] ) && '0' === $_POST['sslVerify'] ) { add_filter( 'http_request_args', array( static::get_class_name(), 'no_ssl_filter_function' ), 99, 2 ); $ssl_verify = false; } add_filter( 'http_request_args', array( MainWP_Helper::get_class_name(), 'reject_unsafe_urls' ), 99, 2 ); $result = $installer->run( array( 'package' => $url, 'destination' => ( 'plugin' === $type ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/themes' ), 'clear_destination' => ( isset( $_POST['overwrite'] ) && sanitize_text_field( wp_unslash( $_POST['overwrite'] ) ) ), 'clear_working' => true, 'hook_extra' => array(), ) ); if ( is_wp_error( $result ) && true === $ssl_verify && strpos( $url, 'https://' ) === 0 ) { $ssl_verify = false; $result = $this->try_second_install( $url, $installer ); } remove_filter( 'http_request_args', array( MainWP_Helper::get_class_name(), 'reject_unsafe_urls' ), 99, 2 ); if ( false === $ssl_verify ) { remove_filter( 'http_request_args', array( static::get_class_name(), 'no_ssl_filter_function' ), 99 ); } $this->after_installed( $result, $output ); $basename = basename( rawurldecode( $url ) ); $install_results[ $basename ] = is_array( $result ) && isset( $result['destination_name'] ) ? true : false; if ( is_array( $output ) ) { if ( 'plugin' === $type && isset( $output['Name'] ) ) { $install_items[] = array( 'name' => $output['Name'], 'version' => $output['Version'], 'slug' => $output['slug'], ); } elseif ( 'theme' === $type && isset( $output['slug'] ) ) { $install_items[] = array( 'name' => isset( $output['name'] ) ? $output['name'] : $output['slug'], 'slug' => $output['slug'], 'version' => isset( $output['version'] ) ? $output['version'] : '', ); } } } // phpcs:enable $information['installation'] = 'SUCCESS'; $information['destination_name'] = $result['destination_name']; $information['install_results'] = $install_results; $information['other_data']['install_items'] = $install_items; MainWP_Helper::write( $information ); } /** * Method no_ssl_filter_function() * * Hook to set ssl verify value. * * @param array $r Request's array values. * * @used-by install_plugin_theme() Plugin & Theme Installation functions. * * @return array $r Request's array values. */ public static function no_ssl_filter_function( $r ) { $r['sslverify'] = false; return $r; } /** * Method require_files() * * Include necessary files. * * @used-by install_plugin_theme() Plugin & Theme Installation functions. */ private function require_files() { if ( file_exists( ABSPATH . '/wp-admin/includes/screen.php' ) ) { include_once ABSPATH . '/wp-admin/includes/screen.php'; // NOSONAR -- WP compatible. } include_once ABSPATH . '/wp-admin/includes/template.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/misc.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; // NOSONAR -- WP compatible. include_once ABSPATH . '/wp-admin/includes/plugin.php'; // NOSONAR -- WP compatible. } /** * Method after_installed() * * After plugin or theme has been installed. * * @param array $result Results array from static::install_plugin_theme(). * @param array $output Results output array. * * @uses wp_cache_set() Saves the data to the cache. * @see https://developer.wordpress.org/reference/functions/wp_cache_set/ * * @uses activate_plugin() Attempts activation of plugin in a “sandbox” and redirects on success. * @see https://developer.wordpress.org/reference/functions/activate_plugin/ * * @uses get_plugin_data() Parses the plugin contents to retrieve plugin’s metadata. * @see https://developer.wordpress.org/reference/functions/get_plugin_data/ * * @used-by install_plugin_theme() Plugin & Theme Installation functions. */ private function after_installed( $result, &$output ) { //phpcs:ignore -- NOSONAR - complex. $args = array( 'success' => 1, 'action' => 'install', ); // phpcs:disable WordPress.Security.NonceVerification if ( isset( $_POST['type'] ) && 'plugin' === $_POST['type'] ) { $path = $result['destination']; $fileName = ''; wp_cache_set( 'plugins', array(), 'plugins' ); foreach ( $result['source_files'] as $srcFile ) { if ( is_dir( $path . $srcFile ) ) { continue; } $thePlugin = get_plugin_data( $path . $srcFile ); if ( null !== $thePlugin && '' !== $thePlugin && '' !== $thePlugin['Name'] && 'readme.txt' !== $srcFile && 'README.md' !== $srcFile ) { // to fix: skip readme.txt. $args['type'] = 'plugin'; $args['Name'] = $thePlugin['Name']; $args['Version'] = $thePlugin['Version']; $args['slug'] = $result['destination_name'] . '/' . $srcFile; $fileName = $srcFile; break; } } if ( ! empty( $fileName ) ) { do_action_deprecated( 'mainwp_child_installPluginTheme', array( $args ), '4.0.7.1', 'mainwp_child_install_plugin_theme' ); // NOSONAR - no IP. do_action( 'mainwp_child_install_plugin_theme', $args ); if ( isset( $_POST['activatePlugin'] ) && 'yes' === $_POST['activatePlugin'] ) { // to fix activate issue. if ( 'quotes-collection/quotes-collection.php' === $args['slug'] ) { activate_plugin( $path . $fileName, '', false, true ); } else { activate_plugin( $path . $fileName, '' ); } } } } else { $args['type'] = 'theme'; $slug = $result['destination_name']; $args['slug'] = $slug; if ( ! empty( $slug ) ) { wp_clean_themes_cache(); $theme = wp_get_theme( $slug ); if ( $theme ) { $args['name'] = $theme->name; $args['version'] = $theme->version; } } do_action_deprecated( 'mainwp_child_installPluginTheme', array( $args ), '4.0.7.1', 'mainwp_child_install_plugin_theme' ); // NOSONAR - no IP. do_action( 'mainwp_child_install_plugin_theme', $args ); } $output = $args; // phpcs:enable } /** * Method try_second_install() * * Alternative installation method. * * @return object $result Return error messages or TRUE. * * @param string $url Package URL. * @param object $installer Instance of \WP_Upgrader. * * @uses is_wp_error() Check whether variable is a WordPress Error. * @see https://developer.wordpress.org/reference/functions/is_wp_error/ * * @uses \MainWP\Child\MainWP_Helper::instance()->error() * * @used-by install_plugin_theme() Plugin & Theme Installation functions. */ private function try_second_install( $url, $installer ) { // phpcs:disable WordPress.Security.NonceVerification $result = $installer->run( array( 'package' => $url, 'destination' => ( isset( $_POST['type'] ) && 'plugin' === $_POST['type'] ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/themes' ), 'clear_destination' => ( isset( $_POST['overwrite'] ) && sanitize_text_field( wp_unslash( $_POST['overwrite'] ) ) ), 'clear_working' => true, 'hook_extra' => array(), ) ); // phpcs:enable if ( is_wp_error( $result ) ) { $err_code = $result->get_error_code(); if ( $result->get_error_data() && is_string( $result->get_error_data() ) ) { $error = $result->get_error_data(); MainWP_Helper::instance()->error( $error, $err_code ); } else { MainWP_Helper::instance()->error( '', $err_code ); } } return $result; } }