<?php
/**
 * Class WordPress\Plugin_Check\Checker\Preparations\Universal_Runtime_Preparation
 *
 * @package plugin-check
 */

namespace WordPress\Plugin_Check\Checker\Preparations;

use Exception;
use WordPress\Plugin_Check\Checker\Check_Context;
use WordPress\Plugin_Check\Checker\Preparation;

/**
 * Class handle all preparations required for when at least one `Runtime_Check` is being run.
 *
 * @since 1.0.0
 */
class Universal_Runtime_Preparation implements Preparation {

	/**
	 * Context for the plugin to check.
	 *
	 * @since 1.0.0
	 * @var Check_Context
	 */
	protected $check_context;

	/**
	 * Sets the context for the plugin to check.
	 *
	 * @since 1.0.0
	 *
	 * @param Check_Context $check_context Check context instance for the plugin.
	 */
	public function __construct( Check_Context $check_context ) {
		$this->check_context = $check_context;
	}

	/**
	 * Runs preparation step for the environment by modifying the plugins and theme to use,
	 * and returns a closure as a cleanup function.
	 *
	 * This preparation needs to be called very early in the WordPress lifecycle, before
	 * plugins are loaded, e.g. from a drop-in like `object-cache.php`.
	 *
	 * @since 1.0.0
	 *
	 * @return callable Cleanup function to revert changes made by theme and plugin preparation classes.
	 *
	 * @throws Exception Thrown when preparation fails.
	 */
	public function prepare() {

		$cleanup_functions = array();

		if ( ! defined( 'WP_PLUGIN_CHECK_PLUGIN_DIR_PATH' ) ) {
			$plugins_dir  = defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins';
			$theme_folder = $plugins_dir . '/plugin-check/runtime-content/themes';
		} else {
			$theme_folder = WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . 'runtime-content/themes';
		}

		$use_custom_db_tables_preparation = new Use_Custom_DB_Tables_Preparation();
		$cleanup_functions[]              = $use_custom_db_tables_preparation->prepare();

		$use_minimal_theme_preparation = new Use_Minimal_Theme_Preparation( 'wp-empty-theme', $theme_folder );
		$cleanup_functions[]           = $use_minimal_theme_preparation->prepare();

		$force_single_plugin_preparation = new Force_Single_Plugin_Preparation( $this->check_context->basename() );
		$cleanup_functions[]             = $force_single_plugin_preparation->prepare();

		// Revert order so that earlier preparations are cleaned up later.
		$cleanup_functions = array_reverse( $cleanup_functions );

		// Return the cleanup function.
		return function () use ( $cleanup_functions ) {

			foreach ( $cleanup_functions as $cleanup_function ) {
				$cleanup_function();
			}
		};
	}
}
