\dirname( $this->yoast_seo_file ) . '/wp-seo.php'; } $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 ); } /** * Loads Yoast SEO from the vendor directory. * * @return void */ protected function load_yoast_seo_from_vendor_directory() { if ( \file_exists( $this->base_dir . '/vendor/yoast/wordpress-seo/wp-seo.php' ) ) { require_once $this->base_dir . '/vendor/yoast/wordpress-seo/wp-seo.php'; \register_activation_hook( \WPSEO_PREMIUM_FILE, 'wpseo_activate' ); \register_deactivation_hook( \WPSEO_PREMIUM_FILE, 'wpseo_deactivate' ); } } /** * 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 = isset( $plugin['Version'] ) ? $plugin['Version'] : '0'; $this->yoast_seo_dir = \WP_PLUGIN_DIR . '/' . \dirname( $file ); } } } /** * Asserts the vendor directory exists. * * @return void * * @throws Exception If the required vendor directory does not exist. */ protected function ensure_vendor_directory_exists() { // If Yoast SEO no longer exists in the vendor directory then abort. if ( ! \file_exists( $this->base_dir . '/vendor/yoast/wordpress-seo/wp-seo.php' ) ) { throw new Exception( 'Missing Yoast SEO in Yoast SEO Premium vendor.' ); } } /** * Cleans the target directory. * * @return void * * @throws Exception If the target directory could not be cleaned. */ protected function clean_target_directory() { if ( \file_exists( \WP_PLUGIN_DIR . '/' . $this->yoast_seo_file ) ) { if ( \file_exists( $this->yoast_seo_dir . '/.git' ) ) { throw new Exception( 'Existing Yoast SEO installation has a .git directory, refusing to automatically install.' ); } if ( ! $this->remove_directory( $this->yoast_seo_dir ) ) { throw new Exception( 'Could not remove old Yoast SEO installation.' ); } } } /** * Removes a directory and all it's contents. * * @param string $directory The full path to the directory. * * @return bool Whether or not the remove was succesfull. */ protected function remove_directory( $directory ) { $items = \scandir( $directory ); foreach ( $items as $item ) { if ( $item === '.' || $item === '..' ) { continue; } $path = $directory . '/' . $item; if ( \is_dir( $path ) ) { if ( ! $this->remove_directory( $path ) ) { return false; } continue; } if ( ! \unlink( $path ) ) { return false; } } return \rmdir( $directory ); } /** * Moves the vendor directory to the target directory. * * @return void * * @throws Exception If the move failed. */ protected function move_vendor_directory() { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Prevent a potential PHP warning on Windows. if ( ! @\rename( $this->base_dir . '/vendor/yoast/wordpress-seo', $this->yoast_seo_dir ) ) { throw new Exception( 'Could not automatically install Yoast SEO' ); } } /** * 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( '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' ]; if ( isset( $_GET['action'] ) && \in_array( $_GET['action'], $actions, true ) ) { return false; } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- 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 ); } }