<?php
/**
 * WooCommerce Global Payments HPP
 *
 * This source file is subject to the GNU General Public License v3.0
 * that is bundled with this package in the file license.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-3.0.html
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@skyverge.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade WooCommerce Global Payments HPP to newer
 * versions in the future. If you wish to customize WooCommerce Global Payments HPP for your
 * needs please refer to https://docs.woocommerce.com/document/woocommerce-global-payments/ for more information.
 *
 * @author      SkyVerge
 * @copyright   Copyright (c) 2012-2024, SkyVerge, Inc.
 * @license     http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
 */

defined( 'ABSPATH' ) or exit;

use SkyVerge\WooCommerce\PluginFramework\v5_12_5 as Framework;
use SkyVerge\WooCommerce\Realex_HPP\Admin\Admin;

/**
 * The Realex HPP payment gateway plugin class.
 *
 * This is primarily a hosted gateway with some additional direct API components,
 * such as refunds, captures, tokenization, and Subscriptions/Pre-Orders
 * integrations.
 */
class WC_Realex_Redirect extends Framework\SV_WC_Payment_Gateway_Plugin {


	/** plugin version number */
	const VERSION = '3.3.1';

	/** plugin ID */
	const PLUGIN_ID = 'realex_redirect';

	/** the gateway class name */
	const GATEWAY_CLASS_NAME = 'WC_Gateway_Realex_Redirect';

	/** the gateway ID */
	const GATEWAY_ID = 'realex_redirect';

	/** @var \WC_Realex_Redirect singleton instance of this plugin */
	protected static $instance;

	/** @var null|Admin admin handler instance */
	private $admin_instance;


	/**
	 * Constructs the plugin.
	 *
	 * @since 1.0.0
	 *
	 * @see Framework\SV_WC_Payment_Gateway_Plugin::__construct()
	 */
	public function __construct() {

		parent::__construct( self::PLUGIN_ID, self::VERSION, array(
			'gateways'           => [
				self::GATEWAY_ID => self::GATEWAY_CLASS_NAME,
			],
			'supported_features' => [
				'hpos'   => true,
				'blocks' => [
					'cart'     => true,
					'checkout' => true,
				],
			],
			'supports'           => [
				self::FEATURE_CUSTOMER_ID,
				self::FEATURE_CAPTURE_CHARGE,
				self::FEATURE_MY_PAYMENT_METHODS,
			],
			'text_domain'        => 'woocommerce-gateway-realex-redirect',
		) );

		// load the files
		$this->includes();

		add_filter( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );

		// remove certain My Payment Methods token actions
		add_filter( 'wc_' . $this->get_id() . '_my_payment_methods_table_method_actions', array( $this, 'remove_my_payment_methods_actions' ) );
	}


	/**
	 * Initializes the plugin's handlers.
	 *
	 * @internal
	 *
	 * @since 3.0.0
	 */
	public function init_plugin() {

		if ( is_admin() ) {
			$this->admin_instance = new Admin();
		}
	}


	/**
	 * Requires the necessary files.
	 *
	 * @since 1.2.0
	 */
	public function includes() {

		require_once( $this->get_plugin_path() . '/src/hpp/Payment_Form_Helper.php' );
		require_once( $this->get_plugin_path() . '/src/class-wc-gateway-realex-redirect.php' );
		require_once( $this->get_plugin_path() . '/src/Admin/Admin.php' );

		// HPP classes
		require_once( $this->get_plugin_path() . '/src/hpp/class-wc-realex-redirect-hpp-response.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/class-wc-realex-redirect-hpp-credit-card-response.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/class-wc-realex-redirect-hpp-saved-card-response.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/class-wc-realex-redirect-hpp-paypal-response.php' );

		// APM classes
		require_once( $this->get_plugin_path() . '/src/hpp/APM/Alternative_Payment_Method.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/APM/Alternative_Payment_Methods.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/APM/Redirect_Response.php' );
		require_once( $this->get_plugin_path() . '/src/hpp/APM/Status_Response.php' );
	}


	/**
	 * Enqueues Global Payments HPP admin scripts.
	 *
	 * @internal
	 *
	 * @since 2.4.0
	 */
	public function enqueue_admin_scripts() {

		if ( $this->is_plugin_settings() ) {

			wp_enqueue_script(
				'woocommerce_global_payments_hpp_admin_settings',
				$this->get_plugin_url() . '/assets/js/admin/wc-global-payments-hpp-admin-settings.min.js',
				[ 'jquery' ],
				self::VERSION,
				true
			);
		}
	}


	/**
	 * Removes certain My Payment Methods token actions.
	 *
	 * There is no need for a "Make Default" action, since method selection is
	 * handled on the hosted payment page.
	 *
	 * @internal
	 *
	 * @since 2.0.0
	 *
	 * @return array
	 */
	public function remove_my_payment_methods_actions( $actions ) {

		unset( $actions['make_default'] );

		return $actions;
	}


	/**
	 * Gets deprecated/removed hooks.
	 *
	 * @since 2.0.0
	 *
	 * @return array
	 */
	protected function get_deprecated_hooks() {

		return array(
			'woocommerce_realex_icon' => array(
				'version'     => '2.0.0',
				'removed'     => true,
				'replacement' => 'wc_realex_redirect_icon',
				'map'         => true,
			),
			'woocommerce_realex_redirect_card_types' => array(
				'version'     => '2.0.0',
				'removed'     => true,
				'replacement' => 'wc_realex_redirect_available_card_types',
			),
			'woocommerce_realex_account' => array(
				'version'     => '2.0.0',
				'removed'     => true,
				'replacement' => 'wc_realex_redirect_subaccount',
				'map'         => true,
			),
			'wc_realex_redirect_order_number_suffix' => array(
				'version' => '2.0.0',
				'removed' => true,
			),
			'wc_realex_redirect_form_params' => array(
				'version'     => '2.0.0',
				'removed'     => true,
				'replacement' => 'wc_realex_redirect_hpp_params',
				'map'         => true,
			),
			'wc_realex_redirect_endpoint_url' => array(
				'version'     => '2.0.0',
				'removed'     => true,
				'replacement' => 'wc_realex_redirect_hpp_endpoint_url',
			),
		);
	}


	/**
	 * Adds any admin notices.
	 *
	 * @since 2.0.0
	 */
	public function add_admin_notices() {

		parent::add_admin_notices();

		if ( get_option( 'woocommerce_realex_redirect_settings_upgraded', false ) ) {

			$this->get_admin_notice_handler()->add_admin_notice(
				sprintf(
					__( 'Heads up! You\'ve upgraded to a major new version of %1$s. If you experience any issues with the payment form, please review our %2$sUpgrade Guide%3$s to ensure your merchant account is compatible with this new version.', 'woocommerce-gateway-realex-redirect' ),
					'<strong>' . $this->get_plugin_name() . '</strong>',
					'<a href="' . esc_url( 'https://docs.woocommerce.com/document/woocommerce-global-payments/#upgrading' ) . '">', '</a>'
				),
				self::PLUGIN_ID . '-2-0-upgrade',
				array(
					'always_show_on_settings' => false,
					'notice_class'            => 'notice-warning',
				)
			);
		}
	}


	/** Helper methods ******************************************************/


	/**
	 * Encrypts a connection credential for storage.
	 *
	 * @since 2.0.0
	 * @param string $data the credential value
	 * @return string
	 */
	public static function encrypt_credential( $data ) {

		$data = trim( $data );

		if ( empty( $data ) ) {
			return '';
		}

		$vector = '';

		if ( function_exists( 'openssl_encrypt' ) ) {
			$vector = openssl_random_pseudo_bytes( self::get_encryption_vector_length() );
			$data   = openssl_encrypt( $data, self::get_encryption_method(), self::get_encryption_key(), OPENSSL_RAW_DATA, $vector );
		}

		return base64_encode( $vector . $data );
	}


	/**
	 * Decrypts a connection credential for use.
	 *
	 * @since 2.0.0
	 * @param string $data the encrypted credential value
	 * @return string
	 */
	public function decrypt_credential( $data ) {

		if ( empty( $data ) ) {
			return '';
		}

		$data = base64_decode( $data );

		if ( function_exists( 'openssl_decrypt' ) ) {

			$vector_length = self::get_encryption_vector_length();
			$vector        = substr( $data, 0, $vector_length );
			$data          = substr( $data, $vector_length );
			$data          = openssl_decrypt( $data, self::get_encryption_method(), self::get_encryption_key(), OPENSSL_RAW_DATA, $vector );
		}

		return trim( $data );
	}


	/**
	 * Gets the key used to encrypt the connection credentials.
	 *
	 * @return string
	 */
	private static function get_encryption_key() {

		return md5( wp_salt(), true );
	}


	/**
	 * Gets the vector length for encrypting credentials.
	 *
	 * @since 2.0.0
	 *
	 * @return int
	 */
	private static function get_encryption_vector_length() {

		return openssl_cipher_iv_length( self::get_encryption_method() );
	}


	/**
	 * Gets the method used for encrypting credentials.
	 *
	 * @since 2.0.0
	 *
	 * @return string
	 */
	private static function get_encryption_method() {

		$available_methods = openssl_get_cipher_methods();
		$preferred_method  = 'AES-128-CBC';

		$method = in_array( $preferred_method, $available_methods, true ) ? $preferred_method : $available_methods[0];

		return $method;
	}


	/**
	 * Gets the singleton instances of this class.
	 *
	 * @since 1.3.0
	 * @see wc_realex_redirect()
	 *
	 * @return \WC_Realex_Redirect plugin object
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}


	/**
	 * Gets the sales page URL.
	 *
	 * @since 2.2.0
	 *
	 * @return string
	 */
	public function get_sales_page_url() {

		return 'https://woocommerce.com/products/woocommerce-global-payments/';
	}


	/**
	 * Gets the plugin documentation url.
	 *
	 * @see Framework\SV_WC_Plugin::get_documentation_url()
	 *
	 * @since 1.4.0
	 *
	 * @return string
	 */
	public function get_documentation_url() {

		return 'https://docs.woocommerce.com/document/woocommerce-global-payments/';
	}


	/**
	 * Gets the plugin support URL.
	 *
	 * @see Framework\SV_WC_Plugin::get_support_url()
	 *
	 * @since 1.4.0
	 *
	 * @return string
	 */
	public function get_support_url() {

		return 'https://woocommerce.com/my-account/marketplace-ticket-form/';
	}


	/**
	 * Returns the plugin name, localized.
	 *
	 * @see Framework\SV_WC_Plugin::get_plugin_name()
	 *
	 * @since 1.2.0
	 *
	 * @return string
	 */
	public function get_plugin_name() {

		return __( 'WooCommerce Global Payments HPP', 'woocommerce-gateway-realex-redirect' );
	}


	/**
	 * Gets the full path and filename of the plugin file.
	 *
	 * @see Framework\SV_WC_Plugin::get_file()
	 *
	 * @since 1.2.0
	 *
	 * @return string
	 */
	protected function get_file() {
		return __FILE__;
	}


	/**
	 * Initializes the lifecycle handler.
	 *
	 * @since 2.1.2
	 */
	protected function init_lifecycle_handler() {

		require_once( $this->get_plugin_path() . '/src/Lifecycle.php' );

		$this->lifecycle_handler = new \SkyVerge\WooCommerce\Realex_HPP\Lifecycle( $this );
	}


	/**
	 * Gets the Admin handler instance.
	 *
	 * @since 3.0.0
	 *
	 * @return null|Admin
	 */
	public function get_admin_handler() {

		return $this->admin_instance;
	}

	/**
	 * @inheritDoc
	 */
	public function log( $message, $log_id = null )
	{

		/*
		 * The plugin ID uses the old name (`realex_redirect`). This can make it confusing for people to find the correct
		 * log file, as the plugin has been renamed to "Global Payments HPP". Changing the plugin ID could have a wide
		 * impact, so we just change the log ID name here on the fly.
		 */
		if ( is_null( $log_id ) || $log_id === self::PLUGIN_ID ) {
			$log_id = 'global_payments_hpp';
		}

		parent::log( $message, $log_id );
	}


} // end WC_Realex_Redirect


/**
 * Returns the One True Instance of Realex Redirect
 *
 * @since 1.3.0
 * @return WC_Realex_Redirect
 */
function wc_realex_redirect() {
	return WC_Realex_Redirect::instance();
}
