t_status() ) { return; } // Mark the installer as having been started but not completed. \update_option( self::OPTION_KEY, 'started', true ); require_once \ABSPATH . 'wp-admin/includes/plugin.php'; $this->detect_yoast_seo(); // Either the plugin is not installed or is installed and too old. if ( \version_compare( $this->yoast_seo_version, self::MINIMUM_YOAST_SEO_VERSION . '-RC0', '<' ) ) { include_once \ABSPATH . 'wp-includes/pluggable.php'; include_once \ABSPATH . 'wp-admin/includes/file.php'; include_once \ABSPATH . 'wp-admin/includes/misc.php'; require_once \ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // The class is defined inline to avoid problems with the autoloader when extending a WP class. $skin = new class() extends Plugin_Installer_Skin { /** * Suppresses the header. * * @return void */ public function header() { } /** * Suppresses the footer. * * @return void */ public function footer() { } /** * Suppresses the errors. * * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Flags unused params which are required via the interface. Invalid. * * @param string|WP_Error $errors Errors. * * @return void */ public function error( $errors ) { } /** * Suppresses the feedback. * * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Flags unused params which are required via the interface. Invalid. * * @param string $feedback Message data. * @param array ...$args Optional text replacements. * * @return void */ public function feedback( $feedback, ...$args ) { } }; // Check if the minimum version is available, otherwise we'll download the zip from SVN trunk (which should be the latest RC). $url = 'https://downloads.wordpress.org/plugin/wordpress-seo.' . self::MINIMUM_YOAST_SEO_VERSION . '.zip'; $check_result = \wp_remote_retrieve_response_code( \wp_remote_head( $url ) ); if ( $check_result !== 200 ) { $url = 'https://downloads.wordpress.org/plugin/wordpress-seo.zip'; } $upgrader = new Plugin_Upgrader( $skin ); $installed = $upgrader->install( $url ); if ( \is_wp_error( $installed ) || ! $installed ) { throw new Exception( 'Could not automatically install Yoast SEO' ); } } $this->ensure_yoast_seo_is_activated(); $this->transfer_auto_update_settings(); // Mark the installer as having been completed. \update_option( self::OPTION_KEY, 'completed', true ); } /** * Detects the Yoast SEO plugin file and version. * * @return void */ protected function detect_yoast_seo() { // Make sure Yoast SEO isn't already installed in another directory. foreach ( \get_plugins() as $file => $plugin ) { // Use text domain to identify the plugin as it's the closest thing to a slug. if ( isset( $plugin['TextDomain'] ) && $plugin['TextDomain'] === 'wordpress-seo' && isset( $plugin['Name'] ) && $plugin['Name'] === 'Yoast SEO' ) { $this->yoast_seo_file = $file; $this->yoast_seo_version = ( $plugin['Version'] ?? '0' ); $this->yoast_seo_dir = \WP_PLUGIN_DIR . '/' . \dirname( $file ); } } } /** * Activates Yoast SEO. * * @return void * * @throws Exception If Yoast SEO could not be activated. */ protected function ensure_yoast_seo_is_activated() { if ( ! \is_plugin_active( $this->yoast_seo_file ) ) { $network_active = \is_plugin_active_for_network( \WPSEO_PREMIUM_BASENAME ); // If we're not active at all it means we're being activated. if ( ! $network_active && ! \is_plugin_active( \WPSEO_PREMIUM_BASENAME ) ) { // So set network active to whether or not we're in the network admin. $network_active = \is_network_admin(); } // Activate Yoast SEO. If Yoast SEO Premium is network active then make sure Yoast SEO is as well. $activation = \activate_plugin( $this->yoast_seo_file, '', $network_active ); if ( \is_wp_error( $activation ) ) { throw new Exception( \esc_html( 'Could not activate Yoast SEO: ' . $activation->get_error_message() ) ); } } } /** * Transfers the auto update settings for Yoast SEO Premium to Yoast SEO. * * @return void */ protected function transfer_auto_update_settings() { $auto_updates = (array) \get_site_option( 'auto_update_plugins', [] ); if ( \in_array( \WPSEO_PREMIUM_BASENAME, $auto_updates, true ) ) { $auto_updates[] = $this->yoast_seo_file; $auto_updates = \array_unique( $auto_updates ); \update_site_option( 'auto_update_plugins', $auto_updates ); } } /** * Wether or not the notification to install Yoast SEO should be shown. * * This is copied from the Yoast_Admin_And_Dashboard_Conditional which we can't use as Yoast SEO may not be installed. * * @return bool */ protected function should_show_notification() { global $pagenow; // Do not output on plugin / theme upgrade pages or when WordPress is upgrading. if ( ( \defined( 'IFRAME_REQUEST' ) && \IFRAME_REQUEST ) || \wp_installing() ) { return false; } /* * IFRAME_REQUEST is not defined on these pages, * though these action pages do show when upgrading themes or plugins. */ $actions = [ 'do-theme-upgrade', 'do-plugin-upgrade', 'do-core-upgrade', 'do-core-reinstall' ]; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information. if ( isset( $_GET['action'] ) && \in_array( $_GET['action'], $actions, true ) ) { return false; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput -- Reason: We are not processing form information, only a strpos is done in the input. if ( $pagenow === 'admin.php' && isset( $_GET['page'] ) && \strpos( $_GET['page'], 'wpseo' ) === 0 ) { return true; } $target_pages = [ 'index.php', 'plugins.php', 'update-core.php', 'options-permalink.php', ]; return \in_array( $pagenow, $target_pages, true ); } }