HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/Init.php.tar
httpdocs/wp-content/plugins/woocommerce/src/Admin/Features/ProductBlockEditor/Init.php000064400000015121151550006200033477 0ustar00var/www/vhosts/uyarreklam.com.tr<?php
/**
 * WooCommerce Product Block Editor
 */

namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry\BlockTemplateRegistry;
use WP_Block_Editor_Context;

/**
 * Loads assets related to the product block editor.
 */
class Init {
	/**
	 * The context name used to identify the editor.
	 */
	const EDITOR_CONTEXT_NAME = 'woocommerce/edit-product';

	/**
	 * Supported post types.
	 *
	 * @var array
	 */
	private $supported_post_types = array( 'simple' );

	/**
	 * Redirection controller.
	 *
	 * @var RedirectionController
	 */
	private $redirection_controller;

	/**
	 * Constructor
	 */
	public function __construct() {
		if ( Features::is_enabled( 'product-variation-management' ) ) {
			array_push( $this->supported_post_types, 'variable' );
		}

		$this->redirection_controller = new RedirectionController( $this->supported_post_types );

		if ( \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
			// Register the product block template.
			$template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
			$template_registry->register( new SimpleProductTemplate() );

			if ( ! Features::is_enabled( 'new-product-management-experience' ) ) {
				add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
				add_action( 'admin_enqueue_scripts', array( $this, 'dequeue_conflicting_styles' ), 100 );
				add_action( 'get_edit_post_link', array( $this, 'update_edit_product_link' ), 10, 2 );
			}
			add_filter( 'woocommerce_admin_get_user_data_fields', array( $this, 'add_user_data_fields' ) );
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
			add_filter( 'woocommerce_register_post_type_product', array( $this, 'add_product_template' ) );

			add_action( 'current_screen', array( $this, 'set_current_screen_to_block_editor_if_wc_admin' ) );

			$block_registry = new BlockRegistry();
			$block_registry->init();

			$tracks = new Tracks();
			$tracks->init();
		}
	}

	/**
	 * Enqueue scripts needed for the product form block editor.
	 */
	public function enqueue_scripts() {
		if ( ! PageController::is_admin_or_embed_page() ) {
			return;
		}
		$post_type_object     = get_post_type_object( 'product' );
		$block_editor_context = new WP_Block_Editor_Context( array( 'name' => self::EDITOR_CONTEXT_NAME ) );

		$editor_settings = array();
		if ( ! empty( $post_type_object->template ) ) {
			$editor_settings['template']                 = $post_type_object->template;
			$editor_settings['templateLock']             = ! empty( $post_type_object->template_lock ) ? $post_type_object->template_lock : false;
		}

		$editor_settings = get_block_editor_settings( $editor_settings, $block_editor_context );

		$script_handle = 'wc-admin-edit-product';
		wp_register_script( $script_handle, '', array(), '0.1.0', true );
		wp_enqueue_script( $script_handle );
		wp_add_inline_script(
			$script_handle,
			'var productBlockEditorSettings = productBlockEditorSettings || ' . wp_json_encode( $editor_settings ) . ';',
			'before'
		);
		wp_add_inline_script(
			$script_handle,
			sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( $editor_settings['blockCategories'] ) ),
			'before'
		);
		wp_tinymce_inline_scripts();
		wp_enqueue_media();
	}

	/**
	 * Enqueue styles needed for the rich text editor.
	 */
	public function enqueue_styles() {
		if ( ! PageController::is_admin_or_embed_page() ) {
			return;
		}
		wp_enqueue_style( 'wp-edit-blocks' );
		wp_enqueue_style( 'wp-format-library' );
		wp_enqueue_editor();
		/**
		 * Enqueue any block editor related assets.
		 *
		 * @since 7.1.0
		*/
		do_action( 'enqueue_block_editor_assets' );
	}

	/**
	 * Dequeue conflicting styles.
	 */
	public function dequeue_conflicting_styles() {
		if ( ! PageController::is_admin_or_embed_page() ) {
			return;
		}
		// Dequeing this to avoid conflicts, until we remove the 'woocommerce-page' class.
		wp_dequeue_style( 'woocommerce-blocktheme' );
	}

	/**
	 * Update the edit product links when the new experience is enabled.
	 *
	 * @param string $link    The edit link.
	 * @param int    $post_id Post ID.
	 * @return string
	 */
	public function update_edit_product_link( $link, $post_id ) {
		$product = wc_get_product( $post_id );

		if ( ! $product ) {
			return $link;
		}

		if ( $product->get_type() === 'simple' ) {
			return admin_url( 'admin.php?page=wc-admin&path=/product/' . $product->get_id() );
		}

		return $link;
	}

	/**
	 * Enqueue styles needed for the rich text editor.
	 *
	 * @param array $args Array of post type arguments.
	 * @return array Array of post type arguments.
	 */
	public function add_product_template( $args ) {
		if ( ! isset( $args['template'] ) ) {
			// Get the template from the registry.
			$template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
			$template          = $template_registry->get_registered( 'simple-product' );

			if ( isset( $template ) ) {
				$args['template_lock'] = 'all';
				$args['template']      = $template->get_formatted_template();
			}
		}
		return $args;
	}

	/**
	 * Adds fields so that we can store user preferences for the variations block.
	 *
	 * @param array $user_data_fields User data fields.
	 * @return array
	 */
	public function add_user_data_fields( $user_data_fields ) {
		return array_merge(
			$user_data_fields,
			array(
				'variable_product_block_tour_shown',
				'product_block_variable_options_notice_dismissed',
				'variable_items_without_price_notice_dismissed'
			)
		);
	}

	/**
	 * Sets the current screen to the block editor if a wc-admin page.
	 */
	public function set_current_screen_to_block_editor_if_wc_admin() {
		$screen = get_current_screen();

		// phpcs:ignore Squiz.PHP.CommentedOutCode.Found
		// (no idea why I need that phpcs:ignore above, but I'm tired trying to re-write this comment to get it to pass)
		// we can't check the 'path' query param because client-side routing is used within wc-admin,
		// so this action handler is only called on the initial page load from the server, which might
		// not be the product edit page (it mostly likely isn't).
		if ( PageController::is_admin_page() ) {
			$screen->is_block_editor( true );

			wp_add_inline_script(
				'wp-blocks',
				'wp.blocks && wp.blocks.unstable__bootstrapServerSideBlockDefinitions && wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
			);
		}
	}
}
httpdocs/wp-content/plugins/woocommerce/src/Admin/Features/AsyncProductEditorCategoryField/Init.php000064400000004641151550535270036207 0ustar00var/www/vhosts/uyarreklam.com.tr<?php
/**
 * WooCommerce Async Product Editor Category Field.
 */

namespace Automattic\WooCommerce\Admin\Features\AsyncProductEditorCategoryField;

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Admin\PageController;

/**
 * Loads assets related to the async category field for the product editor.
 */
class Init {

	const FEATURE_ID = 'async-product-editor-category-field';

	/**
	 * Constructor
	 */
	public function __construct() {
		if ( Features::is_enabled( self::FEATURE_ID ) ) {
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
			add_filter( 'woocommerce_taxonomy_args_product_cat', array( $this, 'add_metabox_args' ) );
		}
	}

	/**
	 * Adds meta_box_cb callback arguments for custom metabox.
	 *
	 * @param array $args Category taxonomy args.
	 * @return array $args category taxonomy args.
	 */
	public function add_metabox_args( $args ) {
		if ( ! isset( $args['meta_box_cb'] ) ) {
			$args['meta_box_cb']          = 'WC_Meta_Box_Product_Categories::output';
			$args['meta_box_sanitize_cb'] = 'taxonomy_meta_box_sanitize_cb_checkboxes';
		}
		return $args;
	}

	/**
	 * Enqueue scripts needed for the product form block editor.
	 */
	public function enqueue_scripts() {
		if ( ! PageController::is_embed_page() ) {
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'product-category-metabox', true );
		wp_localize_script(
			'wc-admin-product-category-metabox',
			'wc_product_category_metabox_params',
			array(
				'search_categories_nonce'     => wp_create_nonce( 'search-categories' ),
				'search_taxonomy_terms_nonce' => wp_create_nonce( 'search-taxonomy-terms' ),
			)
		);
		wp_enqueue_script( 'product-category-metabox' );

	}

	/**
	 * Enqueue styles needed for the rich text editor.
	 */
	public function enqueue_styles() {
		if ( ! PageController::is_embed_page() ) {
			return;
		}
		$version = Constants::get_constant( 'WC_VERSION' );

		wp_register_style(
			'woocommerce_admin_product_category_metabox_styles',
			WCAdminAssets::get_url( 'product-category-metabox/style', 'css' ),
			array(),
			$version
		);
		wp_style_add_data( 'woocommerce_admin_product_category_metabox_styles', 'rtl', 'replace' );

		wp_enqueue_style( 'woocommerce_admin_product_category_metabox_styles' );
	}

}
httpdocs/wp-content/plugins/woocommerce/src/Internal/Admin/RemoteFreeExtensions/Init.php000064400000004004151551444450034064 0ustar00var/www/vhosts/uyarreklam.com.tr<?php
/**
 * Handles running payment method specs
 */

namespace Automattic\WooCommerce\Internal\Admin\RemoteFreeExtensions;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Internal\Admin\RemoteFreeExtensions\DefaultFreeExtensions;

/**
 * Remote Payment Methods engine.
 * This goes through the specs and gets eligible payment methods.
 */
class Init {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'woocommerce_updated', array( __CLASS__, 'delete_specs_transient' ) );
	}

	/**
	 * Go through the specs and run them.
	 *
	 * @param array $allowed_bundles Optional array of allowed bundles to be returned.
	 * @return array
	 */
	public static function get_extensions( $allowed_bundles = array() ) {
		$bundles = array();
		$specs   = self::get_specs();

		foreach ( $specs as $spec ) {
			$spec              = (object) $spec;
			$bundle            = (array) $spec;
			$bundle['plugins'] = array();

			if ( ! empty( $allowed_bundles ) && ! in_array( $spec->key, $allowed_bundles, true ) ) {
				continue;
			}

			foreach ( $spec->plugins as $plugin ) {
				$extension = EvaluateExtension::evaluate( (object) $plugin );

				if ( ! property_exists( $extension, 'is_visible' ) || $extension->is_visible ) {
					$bundle['plugins'][] = $extension;
				}
			}

			$bundles[] = $bundle;
		}

		return $bundles;
	}

	/**
	 * Delete the specs transient.
	 */
	public static function delete_specs_transient() {
		RemoteFreeExtensionsDataSourcePoller::get_instance()->delete_specs_transient();
	}

	/**
	 * Get specs or fetch remotely if they don't exist.
	 */
	public static function get_specs() {
		if ( 'no' === get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) ) {
			return DefaultFreeExtensions::get_all();
		}
		$specs = RemoteFreeExtensionsDataSourcePoller::get_instance()->get_specs_from_data_sources();

		// Fetch specs if they don't yet exist.
		if ( false === $specs || ! is_array( $specs ) || 0 === count( $specs ) ) {
			return DefaultFreeExtensions::get_all();
		}

		return $specs;
	}
}
httpdocs/wp-content/plugins/woocommerce/src/Admin/Features/PaymentGatewaySuggestions/Init.php000064400000005517151552424140035150 0ustar00var/www/vhosts/uyarreklam.com.tr<?php
/**
 * Handles running payment gateway suggestion specs
 */

namespace Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\DefaultPaymentGateways;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\PaymentGatewaysController;

/**
 * Remote Payment Methods engine.
 * This goes through the specs and gets eligible payment gateways.
 */
class Init {
	/**
	 * Option name for dismissed payment method suggestions.
	 */
	const RECOMMENDED_PAYMENT_PLUGINS_DISMISS_OPTION = 'woocommerce_setting_payments_recommendations_hidden';

	/**
	 * Constructor.
	 */
	public function __construct() {
		PaymentGatewaysController::init();
	}

	/**
	 * Go through the specs and run them.
	 *
	 * @param array|null $specs payment suggestion spec array.
	 * @return array
	 */
	public static function get_suggestions( array $specs = null ) {
		$suggestions = array();
		if ( null === $specs ) {
			$specs = self::get_specs();
		}

		foreach ( $specs as $spec ) {
			$suggestion    = EvaluateSuggestion::evaluate( $spec );
			$suggestions[] = $suggestion;
		}

		return array_values(
			array_filter(
				$suggestions,
				function( $suggestion ) {
					return ! property_exists( $suggestion, 'is_visible' ) || $suggestion->is_visible;
				}
			)
		);

	}

	/**
	 * Delete the specs transient.
	 */
	public static function delete_specs_transient() {
		PaymentGatewaySuggestionsDataSourcePoller::get_instance()->delete_specs_transient();
	}

	/**
	 * Get specs or fetch remotely if they don't exist.
	 */
	public static function get_specs() {
		if ( 'no' === get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) ) {
			return apply_filters( 'woocommerce_admin_payment_gateway_suggestion_specs', DefaultPaymentGateways::get_all() );
		}
		$specs = PaymentGatewaySuggestionsDataSourcePoller::get_instance()->get_specs_from_data_sources();

		// Fetch specs if they don't yet exist.
		if ( false === $specs || ! is_array( $specs ) || 0 === count( $specs ) ) {
			return apply_filters( 'woocommerce_admin_payment_gateway_suggestion_specs', DefaultPaymentGateways::get_all() );
		}

		return apply_filters( 'woocommerce_admin_payment_gateway_suggestion_specs', $specs );
	}

	/**
	 * Check if suggestions should be shown in the settings screen.
	 *
	 * @return bool
	 */
	public static function should_display() {
		if ( 'yes' === get_option( self::RECOMMENDED_PAYMENT_PLUGINS_DISMISS_OPTION, 'no' ) ) {
			return false;
		}

		if ( 'no' === get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) ) {
			return false;
		}

		return apply_filters( 'woocommerce_allow_payment_recommendations', true );
	}

	/**
	 * Dismiss the suggestions.
	 */
	public static function dismiss() {
		return update_option( self::RECOMMENDED_PAYMENT_PLUGINS_DISMISS_OPTION, 'yes' );
	}
}
httpdocs/wp-content/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Init.php000064400000002116151552727340033046 0ustar00var/www/vhosts/uyarreklam.com.tr<?php
/**
 * WooCommerce Onboarding Tasks
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedOptions;

/**
 * Contains the logic for completing onboarding tasks.
 */
class Init {
	/**
	 * Class instance.
	 *
	 * @var OnboardingTasks instance
	 */
	protected static $instance = null;

	/**
	 * Get class instance.
	 */
	public static function get_instance() {
		if ( ! self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor
	 */
	public function __construct() {
		DeprecatedOptions::init();
		TaskLists::init();
	}

	/**
	 * Get task item data for settings filter.
	 *
	 * @return array
	 */
	public static function get_settings() {
		$settings            = array();
		$wc_pay_is_connected = false;
		if ( class_exists( '\WC_Payments' ) ) {
			$wc_payments_gateway = \WC_Payments::get_gateway();
			$wc_pay_is_connected = method_exists( $wc_payments_gateway, 'is_connected' )
				? $wc_payments_gateway->is_connected()
				: false;
		}

		return $settings;
	}
}
uyarreklam.com.tr/httpdocs/wp-content/plugins/woocommerce/src/Internal/Admin/WCPayPromotion/Init.php000064400000012223151553355670032652 0ustar00var/www/vhosts<?php
/**
 * Handles wcpay promotion
 */

namespace Automattic\WooCommerce\Internal\Admin\WCPayPromotion;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\DataSourcePoller;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\EvaluateSuggestion;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\PaymentGatewaySuggestionsDataSourcePoller as PaymentGatewaySuggestionsDataSourcePoller;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

/**
 * WC Pay Promotion engine.
 */
class Init {
	const EXPLAT_VARIATION_PREFIX = 'woocommerce_wc_pay_promotion_payment_methods_table_';

	/**
	 * Constructor.
	 */
	public function __construct() {
		include_once __DIR__ . '/WCPaymentGatewayPreInstallWCPayPromotion.php';

		$is_payments_page = isset( $_GET['page'] ) && $_GET['page'] === 'wc-settings' && isset( $_GET['tab'] ) && $_GET['tab'] === 'checkout'; // phpcs:ignore WordPress.Security.NonceVerification
		if ( ! wp_is_json_request() && ! $is_payments_page ) {
			return;
		}

		add_filter( 'woocommerce_payment_gateways', array( __CLASS__, 'possibly_register_pre_install_wc_pay_promotion_gateway' ) );
		add_filter( 'option_woocommerce_gateway_order', [ __CLASS__, 'set_gateway_top_of_list' ] );
		add_filter( 'default_option_woocommerce_gateway_order', [ __CLASS__, 'set_gateway_top_of_list' ] );

		$rtl = is_rtl() ? '.rtl' : '';

		wp_enqueue_style(
			'wc-admin-payment-method-promotions',
			WCAdminAssets::get_url( "payment-method-promotions/style{$rtl}", 'css' ),
			array( 'wp-components' ),
			WCAdminAssets::get_file_version( 'css' )
		);

		WCAdminAssets::register_script( 'wp-admin-scripts', 'payment-method-promotions', true );
	}

	/**
	 * Possibly registers the pre install wc pay promoted gateway.
	 *
	 * @param array $gateways list of gateway classes.
	 * @return array list of gateway classes.
	 */
	public static function possibly_register_pre_install_wc_pay_promotion_gateway( $gateways ) {
		if ( self::can_show_promotion() && ! WCPaymentGatewayPreInstallWCPayPromotion::is_dismissed() ) {
			$gateways[] = 'Automattic\WooCommerce\Internal\Admin\WCPayPromotion\WCPaymentGatewayPreInstallWCPayPromotion';
		}
		return $gateways;
	}

	/**
	 * Checks if promoted gateway can be registered.
	 *
	 * @return boolean if promoted gateway should be registered.
	 */
	public static function can_show_promotion() {
		// Check if WC Pay is enabled.
		if ( class_exists( '\WC_Payments' ) ) {
			return false;
		}
		if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) === 'no' ) {
			return false;
		}
		if ( ! apply_filters( 'woocommerce_allow_marketplace_suggestions', true ) ) {
			return false;
		}

		$wc_pay_spec = self::get_wc_pay_promotion_spec();
		if ( ! $wc_pay_spec ) {
			return false;
		}
		return true;
	}

	/**
	 * By default, new payment gateways are put at the bottom of the list on the admin "Payments" settings screen.
	 * For visibility, we want WooCommerce Payments to be at the top of the list.
	 *
	 * @param array $ordering Existing ordering of the payment gateways.
	 *
	 * @return array Modified ordering.
	 */
	public static function set_gateway_top_of_list( $ordering ) {
		$ordering = (array) $ordering;
		$id       = WCPaymentGatewayPreInstallWCPayPromotion::GATEWAY_ID;
		// Only tweak the ordering if the list hasn't been reordered with WooCommerce Payments in it already.
		if ( ! isset( $ordering[ $id ] ) || ! is_numeric( $ordering[ $id ] ) ) {
			$is_empty        = empty( $ordering ) || ( count( $ordering ) === 1 && $ordering[0] === false );
			$ordering[ $id ] = $is_empty ? 0 : ( min( $ordering ) - 1 );
		}
		return $ordering;
	}

	/**
	 * Get WC Pay promotion spec.
	 */
	public static function get_wc_pay_promotion_spec() {
		$promotions            = self::get_promotions();
		$wc_pay_promotion_spec = array_values(
			array_filter(
				$promotions,
				function( $promotion ) {
					return isset( $promotion->plugins ) && in_array( 'woocommerce-payments', $promotion->plugins, true );
				}
			)
		);

		return current( $wc_pay_promotion_spec );
	}

	/**
	 * Go through the specs and run them.
	 */
	public static function get_promotions() {
		$suggestions = array();
		$specs       = self::get_specs();

		foreach ( $specs as $spec ) {
			$suggestion    = EvaluateSuggestion::evaluate( $spec );
			$suggestions[] = $suggestion;
		}

		return array_values(
			array_filter(
				$suggestions,
				function( $suggestion ) {
					return ! property_exists( $suggestion, 'is_visible' ) || $suggestion->is_visible;
				}
			)
		);

	}

	/**
	 * Get merchant WooPay eligibility.
	 */
	public static function is_woopay_eligible() {
		$wcpay_promotion = self::get_wc_pay_promotion_spec();

		return $wcpay_promotion && 'woocommerce_payments:woopay' === $wcpay_promotion->id;
	}

	/**
	 * Delete the specs transient.
	 */
	public static function delete_specs_transient() {
		WCPayPromotionDataSourcePoller::get_instance()->delete_specs_transient();
	}

	/**
	 * Get specs or fetch remotely if they don't exist.
	 */
	public static function get_specs() {
		if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) === 'no' ) {
			return array();
		}
		return WCPayPromotionDataSourcePoller::get_instance()->get_specs_from_data_sources();
	}
}

var/www/vhosts/uyarreklam.com.tr/httpdocs/wp-content/plugins/woocommerce/src/Admin/API/Init.php000064400000020511151555754570026677 0ustar00<?php
/**
 * REST API bootstrap.
 */

namespace Automattic\WooCommerce\Admin\API;

use AllowDynamicProperties;
use Automattic\WooCommerce\Admin\Features\Features;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Internal\Admin\Loader;

/**
 * Init class.
 *
 * @internal
 */
#[AllowDynamicProperties]
class Init {
	/**
	 * The single instance of the class.
	 *
	 * @var object
	 */
	protected static $instance = null;

	/**
	 * Get class instance.
	 *
	 * @return object Instance.
	 */
	final public static function instance() {
		if ( null === static::$instance ) {
			static::$instance = new static();
		}
		return static::$instance;
	}

	/**
	 * Bootstrap REST API.
	 */
	public function __construct() {
		// Hook in data stores.
		add_filter( 'woocommerce_data_stores', array( __CLASS__, 'add_data_stores' ) );
		// REST API extensions init.
		add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );

		// Add currency symbol to orders endpoint response.
		add_filter( 'woocommerce_rest_prepare_shop_order_object', array( __CLASS__, 'add_currency_symbol_to_order_response' ) );
	}

	/**
	 * Init REST API.
	 */
	public function rest_api_init() {
		$controllers = array(
			'Automattic\WooCommerce\Admin\API\Features',
			'Automattic\WooCommerce\Admin\API\Notes',
			'Automattic\WooCommerce\Admin\API\NoteActions',
			'Automattic\WooCommerce\Admin\API\Coupons',
			'Automattic\WooCommerce\Admin\API\Data',
			'Automattic\WooCommerce\Admin\API\DataCountries',
			'Automattic\WooCommerce\Admin\API\DataDownloadIPs',
			'Automattic\WooCommerce\Admin\API\Experiments',
			'Automattic\WooCommerce\Admin\API\Marketing',
			'Automattic\WooCommerce\Admin\API\MarketingOverview',
			'Automattic\WooCommerce\Admin\API\MarketingRecommendations',
			'Automattic\WooCommerce\Admin\API\MarketingChannels',
			'Automattic\WooCommerce\Admin\API\MarketingCampaigns',
			'Automattic\WooCommerce\Admin\API\MarketingCampaignTypes',
			'Automattic\WooCommerce\Admin\API\Options',
			'Automattic\WooCommerce\Admin\API\Orders',
			'Automattic\WooCommerce\Admin\API\PaymentGatewaySuggestions',
			'Automattic\WooCommerce\Admin\API\Products',
			'Automattic\WooCommerce\Admin\API\ProductAttributes',
			'Automattic\WooCommerce\Admin\API\ProductAttributeTerms',
			'Automattic\WooCommerce\Admin\API\ProductCategories',
			'Automattic\WooCommerce\Admin\API\ProductVariations',
			'Automattic\WooCommerce\Admin\API\ProductReviews',
			'Automattic\WooCommerce\Admin\API\ProductVariations',
			'Automattic\WooCommerce\Admin\API\ProductsLowInStock',
			'Automattic\WooCommerce\Admin\API\SettingOptions',
			'Automattic\WooCommerce\Admin\API\Themes',
			'Automattic\WooCommerce\Admin\API\Plugins',
			'Automattic\WooCommerce\Admin\API\OnboardingFreeExtensions',
			'Automattic\WooCommerce\Admin\API\OnboardingProductTypes',
			'Automattic\WooCommerce\Admin\API\OnboardingProfile',
			'Automattic\WooCommerce\Admin\API\OnboardingTasks',
			'Automattic\WooCommerce\Admin\API\OnboardingThemes',
			'Automattic\WooCommerce\Admin\API\OnboardingPlugins',
			'Automattic\WooCommerce\Admin\API\NavigationFavorites',
			'Automattic\WooCommerce\Admin\API\Taxes',
			'Automattic\WooCommerce\Admin\API\MobileAppMagicLink',
			'Automattic\WooCommerce\Admin\API\ShippingPartnerSuggestions',
		);

		$product_form_controllers = array();
		if ( Features::is_enabled( 'new-product-management-experience' ) ) {
			$product_form_controllers[] = 'Automattic\WooCommerce\Admin\API\ProductForm';
		}

		if ( Features::is_enabled( 'analytics' ) ) {
			$analytics_controllers = array(
				'Automattic\WooCommerce\Admin\API\Customers',
				'Automattic\WooCommerce\Admin\API\Leaderboards',
				'Automattic\WooCommerce\Admin\API\Reports\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Import\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Export\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Products\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Variations\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Products\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Variations\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Revenue\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Orders\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Categories\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Taxes\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Coupons\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Coupons\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Stock\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Stock\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Downloads\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Downloads\Stats\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Customers\Controller',
				'Automattic\WooCommerce\Admin\API\Reports\Customers\Stats\Controller',
			);

			// The performance indicators controller must be registered last, after other /stats endpoints have been registered.
			$analytics_controllers[] = 'Automattic\WooCommerce\Admin\API\Reports\PerformanceIndicators\Controller';

			$controllers = array_merge( $controllers, $analytics_controllers, $product_form_controllers );
		}

		/**
		 * Filter for the WooCommerce Admin REST controllers.
		 *
		 * @since 3.5.0
		 * @param array $controllers List of rest API controllers.
		 */
		$controllers = apply_filters( 'woocommerce_admin_rest_controllers', $controllers );

		foreach ( $controllers as $controller ) {
			$this->$controller = new $controller();
			$this->$controller->register_routes();
		}
	}

	/**
	 * Adds data stores.
	 *
	 * @internal
	 * @param array $data_stores List of data stores.
	 * @return array
	 */
	public static function add_data_stores( $data_stores ) {
		return array_merge(
			$data_stores,
			array(
				'report-revenue-stats'    => 'Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore',
				'report-orders'           => 'Automattic\WooCommerce\Admin\API\Reports\Orders\DataStore',
				'report-orders-stats'     => 'Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore',
				'report-products'         => 'Automattic\WooCommerce\Admin\API\Reports\Products\DataStore',
				'report-variations'       => 'Automattic\WooCommerce\Admin\API\Reports\Variations\DataStore',
				'report-products-stats'   => 'Automattic\WooCommerce\Admin\API\Reports\Products\Stats\DataStore',
				'report-variations-stats' => 'Automattic\WooCommerce\Admin\API\Reports\Variations\Stats\DataStore',
				'report-categories'       => 'Automattic\WooCommerce\Admin\API\Reports\Categories\DataStore',
				'report-taxes'            => 'Automattic\WooCommerce\Admin\API\Reports\Taxes\DataStore',
				'report-taxes-stats'      => 'Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore',
				'report-coupons'          => 'Automattic\WooCommerce\Admin\API\Reports\Coupons\DataStore',
				'report-coupons-stats'    => 'Automattic\WooCommerce\Admin\API\Reports\Coupons\Stats\DataStore',
				'report-downloads'        => 'Automattic\WooCommerce\Admin\API\Reports\Downloads\DataStore',
				'report-downloads-stats'  => 'Automattic\WooCommerce\Admin\API\Reports\Downloads\Stats\DataStore',
				'admin-note'              => 'Automattic\WooCommerce\Admin\Notes\DataStore',
				'report-customers'        => 'Automattic\WooCommerce\Admin\API\Reports\Customers\DataStore',
				'report-customers-stats'  => 'Automattic\WooCommerce\Admin\API\Reports\Customers\Stats\DataStore',
				'report-stock-stats'      => 'Automattic\WooCommerce\Admin\API\Reports\Stock\Stats\DataStore',
			)
		);
	}

	/**
	 * Add the currency symbol (in addition to currency code) to each Order
	 * object in REST API responses. For use in formatAmount().
	 *
	 * @internal
	 * @param {WP_REST_Response} $response REST response object.
	 * @returns {WP_REST_Response}
	 */
	public static function add_currency_symbol_to_order_response( $response ) {
		$response_data                    = $response->get_data();
		$currency_code                    = $response_data['currency'];
		$currency_symbol                  = get_woocommerce_currency_symbol( $currency_code );
		$response_data['currency_symbol'] = html_entity_decode( $currency_symbol );
		$response->set_data( $response_data );

		return $response;
	}
}