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

/**
 * Class WPSEO_Redirect_Manager.
 */
class WPSEO_Redirect_Upgrade {

	/**
	 * Lookup table for previous redirect format constants to their current counterparts.
	 *
	 * @var array
	 */
	private static $redirect_option_names = [
		WPSEO_Redirect_Option::OLD_OPTION_PLAIN => WPSEO_Redirect_Formats::PLAIN,
		WPSEO_Redirect_Option::OLD_OPTION_REGEX => WPSEO_Redirect_Formats::REGEX,
	];

	/**
	 * Upgrade routine from Yoast SEO premium 1.2.0.
	 *
	 * @return void
	 */
	public static function upgrade_1_2_0() {
		$redirect_option = self::get_redirect_option();
		$redirects       = [];

		foreach ( self::$redirect_option_names as $redirect_option_name => $redirect_format ) {
			$old_redirects = $redirect_option->get_from_option( $redirect_option_name );

			foreach ( $old_redirects as $origin => $redirect ) {
				// Check if the redirect is not an array yet.
				if ( ! is_array( $redirect ) ) {
					$redirects[] = new WPSEO_Redirect( $origin, $redirect['url'], $redirect['type'], $redirect_format );
				}
			}
		}

		self::import_redirects( $redirects );
	}

	/**
	 * Check if redirects should be imported from the free version.
	 *
	 * @since 2.3
	 *
	 * @return void
	 */
	public static function import_redirects_2_3() {
		// phpcs:ignore WordPress.DB.SlowDBQuery -- Upgrade routine, so rarely used, therefore not an issue.
		$wp_query = new WP_Query( 'post_type=any&meta_key=_yoast_wpseo_redirect&order=ASC' );

		if ( ! empty( $wp_query->posts ) ) {
			$redirects = [];

			foreach ( $wp_query->posts as $post ) {

				$old_url = '/' . $post->post_name . '/';
				$new_url = get_post_meta( $post->ID, '_yoast_wpseo_redirect', true );

				// Create redirect.
				$redirects[] = new WPSEO_Redirect( $old_url, $new_url, 301, WPSEO_Redirect_Formats::PLAIN );

				// Remove post meta value.
				delete_post_meta( $post->ID, '_yoast_wpseo_redirect' );
			}

			self::import_redirects( $redirects );
		}
	}

	/**
	 * Upgrade routine to merge plain and regex redirects in a single option.
	 *
	 * @return void
	 */
	public static function upgrade_3_1() {
		$redirects = [];

		foreach ( self::$redirect_option_names as $redirect_option_name => $redirect_format ) {
			$old_redirects = get_option( $redirect_option_name, [] );

			foreach ( $old_redirects as $origin => $redirect ) {
				// Only when URL and type is set.
				if ( array_key_exists( 'url', $redirect ) && array_key_exists( 'type', $redirect ) ) {
					$redirects[] = new WPSEO_Redirect( $origin, $redirect['url'], $redirect['type'], $redirect_format );
				}
			}
		}

		// Saving the redirects to the option.
		self::import_redirects( $redirects, [ new WPSEO_Redirect_Option_Exporter() ] );
	}

	/**
	 * Exports the redirects to htaccess or nginx file if needed.
	 *
	 * @return void
	 */
	public static function upgrade_13_0() {
		$redirect_manager = new WPSEO_Redirect_Manager();
		$redirect_manager->export_redirects();
	}

	/**
	 * Imports an array of redirect objects.
	 *
	 * @param WPSEO_Redirect[]               $redirects The redirects.
	 * @param WPSEO_Redirect_Exporter[]|null $exporters The exporters.
	 *
	 * @return void
	 */
	private static function import_redirects( $redirects, $exporters = null ) {
		if ( empty( $redirects ) ) {
			return;
		}

		$redirect_option  = self::get_redirect_option();
		$redirect_manager = new WPSEO_Redirect_Manager( null, $exporters, $redirect_option );

		foreach ( $redirects as $redirect ) {
			$redirect_option->add( $redirect );
		}

		$redirect_option->save( false );
		$redirect_manager->export_redirects();
	}

	/**
	 * Gets and caches the redirect option.
	 *
	 * @return WPSEO_Redirect_Option
	 */
	private static function get_redirect_option() {
		static $redirect_option;

		if ( empty( $redirect_option ) ) {
			$redirect_option = new WPSEO_Redirect_Option( false );
		}

		return $redirect_option;
	}
}
