<?php
/**
 * WPSEO Premium plugin file.
 *
 * @package WPSEO\Premium
 */

if ( ! defined( 'WPSEO_VERSION' ) ) {
	header( 'HTTP/1.0 403 Forbidden' );
	die;
}

if ( ! defined( 'WPSEO_PREMIUM_PATH' ) ) {
	define( 'WPSEO_PREMIUM_PATH', plugin_dir_path( __FILE__ ) );
}

if ( ! defined( 'WPSEO_PREMIUM_FILE' ) ) {
	define( 'WPSEO_PREMIUM_FILE', __FILE__ );
}

/**
 * Class WPSEO_Premium
 */
class WPSEO_Premium {

	/** @var string */
	const OPTION_CURRENT_VERSION = 'wpseo_current_version';

	/** @var string */
	const PLUGIN_VERSION_NAME = '8.2.2';

	/** @var string */
	const PLUGIN_VERSION_CODE = '16';

	/** @var string */
	const PLUGIN_AUTHOR = 'Yoast';

	/** @var string */
	const EDD_STORE_URL = 'http://my.yoast.com';

	/** @var string */
	const EDD_PLUGIN_NAME = 'Yoast SEO Premium';

	/**
	 * @var WPSEO_Redirect_Page
	 */
	private $redirects;

	/**
	 * @var WPSEO_WordPress_Integration[]
	 */
	private $integrations = array();

	/**
	 * Function that will be executed when plugin is activated.
	 */
	public static function install() {

		// Load the Redirect File Manager.
		require_once WPSEO_PREMIUM_PATH . 'classes/redirect/redirect-file-util.php';

		// Create the upload directory.
		WPSEO_Redirect_File_Util::create_upload_dir();

		self::activate_license();

		// Make sure the notice will be given at install.
		require_once WPSEO_PREMIUM_PATH . 'classes/premium-prominent-words-recalculation-notifier.php';
		$recalculation_notifier = new WPSEO_Premium_Prominent_Words_Recalculation_Notifier();
		$recalculation_notifier->manage_notification();
	}

	/**
	 * Creates instance of license manager if needed and returns the instance of it.
	 *
	 * @return Yoast_Plugin_License_Manager
	 */
	public static function get_license_manager() {
		static $license_manager;

		if ( $license_manager === null ) {
			$license_manager = new Yoast_Plugin_License_Manager( new WPSEO_Product_Premium() );
		}

		return $license_manager;
	}

	/**
	 * WPSEO_Premium Constructor
	 */
	public function __construct() {
		$link_suggestions_service        = new WPSEO_Premium_Link_Suggestions_Service();
		$prominent_words_unindexed_query = new WPSEO_Premium_Prominent_Words_Unindexed_Post_Query();
		$prominent_words_support         = new WPSEO_Premium_Prominent_Words_Support();

		$this->integrations = array(
			'premium-metabox'                        => new WPSEO_Premium_Metabox(),
			'prominent-words-registration'           => new WPSEO_Premium_Prominent_Words_Registration(),
			'prominent-words-endpoint'               => new WPSEO_Premium_Prominent_Words_Endpoint( new WPSEO_Premium_Prominent_Words_Service() ),
			'prominent-words-recalculation'          => new WPSEO_Premium_Prominent_Words_Recalculation( $prominent_words_unindexed_query, $prominent_words_support ),
			'prominent-words-recalculation-link'     => new WPSEO_Premium_Prominent_Words_Link_Endpoint( new WPSEO_Premium_Prominent_Words_Link_Service() ),
			'prominent-words-recalculation-notifier' => new WPSEO_Premium_Prominent_Words_Recalculation_Notifier(),
			'prominent-words-recalculation-endpoint' => new WPSEO_Premium_Prominent_Words_Recalculation_Endpoint( new WPSEO_Premium_Prominent_Words_Recalculation_Service() ),
			'prominent-words-version'                => new WPSEO_Premium_Prominent_Words_Versioning(),
			'link-suggestions'                       => new WPSEO_Metabox_Link_Suggestions(),
			'link-suggestions-endpoint'              => new WPSEO_Premium_Link_Suggestions_Endpoint( $link_suggestions_service ),
			'premium-search-console'                 => new WPSEO_Premium_GSC(),
			'redirects-endpoint'                     => new WPSEO_Premium_Redirect_EndPoint( new WPSEO_Premium_Redirect_Service() ),
			'redirect-export-manager'                => new WPSEO_Premium_Redirect_Export_Manager(),
			'keyword-export-manager'                 => new WPSEO_Premium_Keyword_Export_Manager(),
			'orphaned-post-filter'                   => new WPSEO_Premium_Orphaned_Post_Filter(),
			'orphaned-post-notifier'                 => new WPSEO_Premium_Orphaned_Post_Notifier( array( 'post', 'page' ), Yoast_Notification_Center::get() ),
			'request-free-translations'              => new WPSEO_Premium_Free_Translations(),
			'expose-javascript-shortlinks'           => new WPSEO_Premium_Expose_Shortlinks(),
		);

		$this->setup();
	}

	/**
	 * Adds a feature toggle to the given feature_toggles.
	 *
	 * @param array $feature_toggles The feature toggles to extend.
	 *
	 * @return array
	 */
	public function add_feature_toggles( array $feature_toggles ) {
		$language = WPSEO_Utils::get_language( get_locale() );

		$language_support = new WPSEO_Premium_Prominent_Words_Language_Support();

		if ( $language_support->is_language_supported( $language ) ) {
			$feature_toggles[] = (object) array(
				'name'            => __( 'Insights', 'wordpress-seo-premium' ),
				'setting'         => 'enable_metabox_insights',
				'label'           => __( 'The Insights section in our metabox shows you useful data about your content, like what words you use most often.', 'wordpress-seo-premium' ),
				'read_more_label' => __( 'Read more about how the insights can help you improve your content.', 'wordpress-seo-premium' ),
				'read_more_url'   => 'https://yoa.st/2ai',
				'order'           => 41,
			);
			$feature_toggles[] = (object) array(
				'name'            => __( 'Link suggestions', 'wordpress-seo-premium' ),
				'setting'         => 'enable_link_suggestions',
				'label'           => __( 'The link suggestions metabox contains a list of posts on your blog with similar content that might be interesting to link to.', 'wordpress-seo-premium' ),
				'read_more_label' => __( 'Read more about how internal linking can improve your site structure.', 'wordpress-seo-premium' ),
				'read_more_url'   => 'https://yoa.st/17g',
				'order'           => 42,
			);
		}

		return $feature_toggles;
	}

	/**
	 * Sets up the Yoast SEO premium plugin.
	 */
	private function setup() {

		self::autoloader();

		$this->load_textdomain();

		$this->redirect_setup();
		$this->export_setup();

		if ( is_admin() ) {
			// Make sure priority is below registration of other implementations of the beacon in News, Video, etc.
			add_action( 'admin_init', array( $this, 'init_helpscout_support' ), 1 );
			add_filter( 'wpseo_feature_toggles', array( $this, 'add_feature_toggles' ) );

			// Only register the yoast i18n when the page is a Yoast SEO page.
			if ( $this->is_yoast_seo_premium_page( filter_input( INPUT_GET, 'page' ) ) ) {
				$this->register_i18n_promo_class();
			}

			// Add custom fields plugin to post and page edit pages.
			global $pagenow;
			if ( in_array( $pagenow, array( 'post-new.php', 'post.php', 'edit.php' ), true ) ) {
				new WPSEO_Custom_Fields_Plugin();
			}

			add_action( 'admin_init', array( $this, 'initialize_tracking' ), 1 );

			// Disable Yoast SEO.
			add_action( 'admin_init', array( $this, 'disable_wordpress_seo' ), 1 );

			// Add Sub Menu page and add redirect page to admin page array.
			// This should be possible in one method in the future, see #535.
			add_filter( 'wpseo_submenu_pages', array( $this, 'add_submenu_pages' ), 9 );

			// Add input fields to page meta post types.
			add_action( 'wpseo_admin_page_meta_post_types', array(
				$this,
				'admin_page_meta_post_types_checkboxes',
			), 10, 2 );

			// Add page analysis fields to variable array key patterns.
			add_filter( 'wpseo_option_titles_variable_array_key_patterns', array(
				$this,
				'add_variable_array_key_pattern',
			) );

			// Settings.
			add_action( 'admin_init', array( $this, 'register_settings' ) );

			// Licensing part.
			$license_manager = self::get_license_manager();

			// Setup constant name.
			$license_manager->set_license_constant_name( 'WPSEO_LICENSE' );

			// Setup license hooks.
			$license_manager->setup_hooks();

			// Add this plugin to licensing form.
			add_action( 'wpseo_licenses_forms', array( $license_manager, 'show_license_form' ) );

			if ( $license_manager->license_is_valid() ) {
				add_action( 'admin_head', array( $this, 'admin_css' ) );
			}

			// Add Premium imports.
			new WPSEO_Premium_Import_Manager();

			// Only activate post and term watcher if permalink structure is enabled.
			if ( get_option( 'permalink_structure' ) ) {
				add_action( 'admin_init', array( $this, 'init_watchers' ) );

				// Check if we need to display an admin message.
				$redirect_created = filter_input( INPUT_GET, 'yoast-redirect-created' );
				if ( isset( $redirect_created ) && $redirect_created !== false ) {

					// Message object.
					$message = new WPSEO_Message_Redirect_Created( $redirect_created );
					add_action( 'all_admin_notices', array( $message, 'display' ) );
				}
			}
		}
		else {
			// Add 404 redirect link to WordPress toolbar.
			add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 96 );

			add_filter( 'redirect_canonical', array( $this, 'redirect_canonical_fix' ), 1, 2 );
		}

		add_action( 'admin_init', array( $this, 'enqueue_multi_keyword' ) );
		add_action( 'admin_init', array( $this, 'enqueue_social_previews' ) );

		add_action( 'wpseo_premium_indicator_classes', array( $this, 'change_premium_indicator' ) );
		add_action( 'wpseo_premium_indicator_text', array( $this, 'change_premium_indicator_text' ) );

		// Only initialize the AJAX for all tabs except settings.
		$facebook_name = new WPSEO_Facebook_Profile();
		$facebook_name->set_hooks();

		foreach ( $this->integrations as $integration ) {
			$integration->register_hooks();
		}
	}

	/**
	 * Checks if the page is a premium page.
	 *
	 * @param string $page The page to check.
	 *
	 * @return bool
	 */
	private function is_yoast_seo_premium_page( $page ) {
		$premium_pages = array( 'wpseo_redirects' );

		return in_array( $page, $premium_pages, true );
	}

	/**
	 * Registers the promotion class for our GlotPress instance.
	 *
	 * @link https://github.com/Yoast/i18n-module
	 */
	private function register_i18n_promo_class() {
		new Yoast_I18n_v3(
			array(
				'textdomain'     => 'wordpress-seo-premium',
				'project_slug'   => 'wordpress-seo-premium',
				'plugin_name'    => 'Yoast SEO premium',
				'hook'           => 'wpseo_admin_promo_footer',
				'glotpress_url'  => 'http://translate.yoast.com/gp/',
				'glotpress_name' => 'Yoast Translate',
				'glotpress_logo' => 'https://translate.yoast.com/gp-templates/images/Yoast_Translate.svg',
				'register_url'   => 'https://yoa.st/translate',
			)
		);
	}

	/**
	 * Sets the autoloader for the redirects and instantiates the redirect page object.
	 */
	private function redirect_setup() {
		// Set the autoloader for redirects.
		new WPSEO_Premium_Autoloader( 'WPSEO_Redirect', 'redirect/', 'WPSEO_' );

		$this->redirects = new WPSEO_Redirect_Page();

		// Adds integration that filters redirected entries from the sitemap.
		$this->integrations['redirect-sitemap-filter'] = new WPSEO_Redirect_Sitemap_Filter( home_url() );
	}

	/**
	 * Sets the autoloader for the exports.
	 */
	private function export_setup() {
		// Set the autoloader for redirects.
		new WPSEO_Premium_Autoloader( 'WPSEO_Export', 'export/', 'WPSEO_' );
	}

	/**
	 * We might want to reactivate the license.
	 */
	private static function activate_license() {
		$license_manager = self::get_license_manager();
		$license_manager->activate_license();
	}

	/**
	 * Initialize the watchers for the posts and the terms
	 */
	public function init_watchers() {
		// The Post Watcher.
		new WPSEO_Post_Watcher();

		// The Term Watcher.
		new WPSEO_Term_Watcher();
	}

	/**
	 * Adds multi keyword functionality if we are on the correct pages
	 */
	public function enqueue_multi_keyword() {
		global $pagenow;

		if ( WPSEO_Metabox::is_post_edit( $pagenow ) ) {
			new WPSEO_Multi_Keyword();
		}
	}

	/**
	 * Adds multi keyword functionality if we are on the correct pages
	 */
	public function enqueue_social_previews() {
		global $pagenow;

		$social_previews = new WPSEO_Social_Previews();
		if ( WPSEO_Metabox::is_post_edit( $pagenow ) || WPSEO_Taxonomy::is_term_edit( $pagenow ) ) {
			$social_previews->set_hooks();
		}
		$social_previews->set_ajax_hooks();
	}

	/**
	 * Hooks into the `redirect_canonical` filter to catch ongoing redirects and move them to the correct spot
	 *
	 * @param string $redirect_url  The target url where the requested URL will be redirected to.
	 * @param string $requested_url The current requested URL.
	 *
	 * @return string
	 */
	public function redirect_canonical_fix( $redirect_url, $requested_url ) {
		$redirects = new WPSEO_Redirect_Option( false );
		$path      = wp_parse_url( $requested_url, PHP_URL_PATH );
		$redirect  = $redirects->get( $path );
		if ( $redirect === false ) {
			return $redirect_url;
		}

		$redirect_url = $redirect->get_origin();
		if ( '/' === substr( $redirect_url, 0, 1 ) ) {
			$redirect_url = home_url( $redirect_url );
		}

		wp_redirect( $redirect_url, $redirect->get_type() );
		exit;
	}

	/**
	 * Disable Yoast SEO
	 */
	public function disable_wordpress_seo() {
		if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) ) {
			deactivate_plugins( 'wordpress-seo/wp-seo.php' );
		}
	}

	/**
	 * Add 'Create Redirect' option to admin bar menu on 404 pages
	 */
	public function admin_bar_menu() {
		if ( ! is_404() ) {
			return;
		}

		global $wp, $wp_admin_bar;

		$parsed_url = wp_parse_url( home_url( $wp->request ) );

		if ( ! is_array( $parsed_url ) ) {
			return;
		}

		$old_url = WPSEO_Redirect_Util::strip_base_url_path_from_url( home_url(), $parsed_url['path'] );

		if ( isset( $parsed_url['query'] ) && $parsed_url['query'] !== '' ) {
			$old_url .= '?' . $parsed_url['query'];
		}

		$old_url = rawurlencode( $old_url );

		$wp_admin_bar->add_menu( array(
			'id'    => 'wpseo-premium-create-redirect',
			'title' => __( 'Create Redirect', 'wordpress-seo-premium' ),
			'href'  => admin_url( 'admin.php?page=wpseo_redirects&old_url=' . $old_url ),
		) );
	}

	/**
	 * Add page analysis to array with variable array key patterns
	 *
	 * @param array $patterns Array with patterns for page analysis.
	 *
	 * @return array
	 */
	public function add_variable_array_key_pattern( $patterns ) {
		if ( true !== in_array( 'page-analyse-extra-', $patterns, true ) ) {
			$patterns[] = 'page-analyse-extra-';
		}

		return $patterns;
	}

	/**
	 * This hook will add an input-field for specifying custom fields for page analysis.
	 *
	 * The values will be comma-separated and will target the belonging field in the post_meta. Page analysis will
	 * use the content of it by sticking it to the post_content.
	 *
	 * @param array  $wpseo_admin_pages Unused. Array with admin pages.
	 * @param string $name              The name for the text input field.
	 */
	public function admin_page_meta_post_types_checkboxes( $wpseo_admin_pages, $name ) {
		Yoast_Form::get_instance()->textinput( 'page-analyse-extra-' . $name, __( 'Add custom fields to page analysis', 'wordpress-seo-premium' ) );
	}

	/**
	 * Function adds the premium pages to the Yoast SEO menu
	 *
	 * @param array $submenu_pages Array with the configuration for the submenu pages.
	 *
	 * @return array
	 */
	public function add_submenu_pages( $submenu_pages ) {
		/**
		 * Filter: 'wpseo_premium_manage_redirects_role' - Change the minimum rule to access and change the site redirects
		 *
		 * @api string wpseo_manage_redirects
		 */
		$submenu_pages[] = array(
			'wpseo_dashboard',
			'',
			__( 'Redirects', 'wordpress-seo-premium' ),
			apply_filters_deprecated( 'wpseo_premium_manage_redirects_role', array( 'wpseo_manage_redirects' ), 'WPSEO 5.5', false, 'Use the introduced wpseo_manage_redirects capability instead.' ),
			'wpseo_redirects',
			array( $this->redirects, 'display' ),
		);

		return $submenu_pages;
	}

	/**
	 * Change premium indicator to green when premium is enabled
	 *
	 * @param string[] $classes The current classes for the indicator.
	 * @returns string[] The new classes for the indicator.
	 */
	public function change_premium_indicator( $classes ) {
		$class_no = array_search( 'wpseo-premium-indicator--no', $classes, true );

		if ( false !== $class_no ) {
			unset( $classes[ $class_no ] );

			$classes[] = 'wpseo-premium-indicator--yes';
		}

		return $classes;
	}

	/**
	 * Replaces the screen reader text for the premium indicator.
	 *
	 * @param string $text The original text.
	 * @return string The new text.
	 */
	public function change_premium_indicator_text( $text ) {
		return __( 'Enabled', 'wordpress-seo-premium' );
	}

	/**
	 * Register the premium settings
	 */
	public function register_settings() {
		register_setting( 'yoast_wpseo_redirect_options', 'wpseo_redirect' );
	}

	/**
	 * Output admin css in admin head
	 */
	public function admin_css() {
		echo "<style type='text/css'>#wpseo_content_top{ padding-left: 0; margin-left: 0; }</style>";
	}

	/**
	 * Load textdomain
	 */
	private function load_textdomain() {
		load_plugin_textdomain( 'wordpress-seo-premium', false, dirname( plugin_basename( WPSEO_FILE ) ) . '/premium/languages/' );
	}

	/**
	 * Loads the autoloader
	 */
	public static function autoloader() {

		if ( ! class_exists( 'WPSEO_Premium_Autoloader', false ) ) {
			// Setup autoloader.
			require_once WPSEO_PREMIUM_PATH . 'classes/premium-autoloader.php';
			$autoloader = new WPSEO_Premium_Autoloader( 'WPSEO_', '' );
		}
	}

	/**
	 * Initializes the helpscout support modal for wpseo settings pages
	 */
	public function init_helpscout_support() {
		$page      = filter_input( INPUT_GET, 'page' );
		$query_var = '';
		if ( isset( $page ) && $page !== false ) {
			$query_var = $page;
		}

		$is_beacon_page = in_array( strtolower( $query_var ), $this->get_beacon_pages(), true );

		// Only add the helpscout beacon on Yoast SEO pages.
		if ( WPSEO_Metabox::is_post_edit( $GLOBALS['pagenow'] ) || $is_beacon_page ) {
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_contact_support' ) );

			$beacon = yoast_get_helpscout_beacon( $query_var, 'no_search' );
			$beacon->add_setting( new WPSEO_Premium_Beacon_Setting() );
			$beacon->register_hooks();
		}
	}

	/**
	 * Get the pages the Premium beacon should be displayed on
	 *
	 * @return array
	 */
	private function get_beacon_pages() {
		return array(
			'wpseo_dashboard',
			'wpseo_titles',
			'wpseo_social',
			'wpseo_xml',
			'wpseo_advanced',
			'wpseo_tools',
			'wpseo_search_console',
			'wpseo_licenses',
		);
	}

	/**
	 * Add the Yoast contact support assets
	 */
	public function enqueue_contact_support() {
		$asset_manager = new WPSEO_Admin_Asset_Manager();
		$version       = $asset_manager->flatten_version( WPSEO_VERSION );

		wp_enqueue_script( 'yoast-contact-support', plugin_dir_url( WPSEO_PREMIUM_FILE ) . 'assets/js/dist/wpseo-premium-contact-support-' . $version . WPSEO_CSSJS_SUFFIX . '.js', array( 'jquery', 'yoast-seo-premium-commons' ), WPSEO_VERSION );
	}

	/**
	 * Initializes the tracking class, for sending data.
	 *
	 * @return void
	 */
	public function initialize_tracking() {
		global $pagenow;

		/**
		 * Filter: 'wpseo_disable_tracking' - Disables the data tracking of Yoast SEO Premium.
		 *
		 * @api string $is_disabled The disabled state. Default is false.
		 */
		if ( apply_filters( 'wpseo_disable_tracking', false ) === true ) {
			return;
		}

		// Because we don't want to possibly block plugin actions with our routines.
		if ( in_array( $pagenow, array( 'plugins.php', 'plugin-install.php', 'plugin-editor.php' ), true ) ) {
			return;
		}

		$tracker = new WPSEO_Tracking( 'https://search-yoast-poc-gdaxpa7udbwtvpgxqaufa3dejm.eu-central-1.es.amazonaws.com/yoast/tracking', ( WEEK_IN_SECONDS * 2 ) );
		$tracker->send();
	}
}
