<?php
/**
 * API Class handler
 *
 * @package UM_Social_Login_API
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class UM_Social_Login_API
 */
class UM_Social_Login_API {

	/**
	 * For backward compatibility with 1.3.x and PHP8.2 compatibility.
	 *
	 * @var bool
	 */
	public $plugin_inactive = false;

	/**
	 * Instance
	 *
	 * @var $instance
	 *
	 * @since  2.0
	 */
	private static $instance;

	/**
	 * Network Providers
	 *
	 * @var array
	 *
	 * @since  2.0
	 */
	public $networks;

	/**
	 * API Response fields
	 *
	 * @var array
	 *
	 * @since  2.2
	 */
	public $api_response_fields;

	/**
	 * Profile object
	 *
	 * @var array
	 *
	 * @since  2.4.4
	 */
	public $profile;

	/**
	 * Show overlay
	 *
	 * @var bool
	 */
	public $show_overlay = false;

	/**
	 * Shortcode ID
	 *
	 * @var bool
	 */
	public $shortcode_id = false;

	/**
	 * Set instance
	 *
	 * @return UM_Social_Login_API
	 *
	 * @since  2.0
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * UM_Social_Login_API constructor
	 *
	 * @since  2.0
	 */
	public function __construct() {
		// Global for backwards compatibility.
		$GLOBALS['um_social_login'] = $this;

		add_filter( 'um_call_object_Social_Login_API', array( &$this, 'get_this' ) );

		// Fix for the REST API test in the Site Health.
		if ( function_exists( 'rest_get_url_prefix' ) ) {
			$rest_prefix = rest_get_url_prefix();

			$strpos = strpos( $_SERVER['REQUEST_URI'], $rest_prefix ); //phpcs:ignore
			if ( 1 === $strpos ) {
				return;
			}
		}

		$this->init_networks();

		$this->api_response_fields();

		$this->user_connect();

		$this->user_disconnect();

		$this->admin();

		$this->enqueue();

		$this->shortcode();

		$this->ajax();

		$this->hybridauth();

		add_action( 'plugins_loaded', array( &$this, 'init' ) );

		add_filter( 'query_vars', array( &$this, 'query_vars' ), 10, 1 );

		add_action( 'init', array( &$this, 'create_taxonomies' ), 2 );
		add_filter( 'um_cpt_list', array( &$this, 'add_cpt' ) );

		add_filter( 'um_settings_default_values', array( &$this, 'default_settings' ), 10, 1 );

		add_action( 'um_mycred_load_hooks', array( &$this, 'um_mycred_social_login_hooks' ) );

		add_action( 'wp_logout', array( &$this, 'um_clear_session_after_logout' ) );

		add_action( 'wp_ajax_um_social_login_change_photo', array( $this->ajax(), 'ajax_change_photo' ) );

		add_filter( 'um_custom_error_message_handler', array( &$this, 'error_message_handler' ), 99999, 2 );
	}


	/**
	 * Social network members data
	 *
	 * @since  2.2.0
	 */
	public function api_response_fields() {
		$this->api_response_fields = array(
			'identifier'    => 'ID',
			'profileURL'    => 'Profile URL',
			'webSiteURL'    => 'Website URL',
			'photoURL'      => 'Photo URL',
			'displayName'   => 'Display Name',
			'description'   => 'Description',
			'firstName'     => 'First Name',
			'lastName'      => 'Last Name',
			'gender'        => 'Gender',
			'language'      => 'Language',
			'age'           => 'Age',
			'birthDay'      => 'Birth Day',
			'birthMonth'    => 'Birth Month',
			'birthYear'     => 'Birth Year',
			'email'         => 'Email Address',
			'emailVerified' => 'Email Verified',
			'phone'         => 'Phone Number',
			'address'       => 'Address',
			'country'       => 'Country',
			'region'        => 'Region',
			'city'          => 'City',
			'zip'           => 'Zip',
			'extend'        => 'Extended Data',
		);
	}

	/**
	 * Mycred integration
	 *
	 * @param string $action Action.
	 *
	 * @since  2.0
	 */
	public function um_mycred_social_login_hooks( $action ) {
		$this->init_networks();
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/hooks/um-mycred-social-login.php';
	}


	/**
	 * Init network filter
	 *
	 * @since  2.0
	 */
	public function init_networks() {

		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-providers.php';

		$this->networks = apply_filters( 'um_social_login_networks', $this->networks );
	}


	/**
	 * Default settings
	 *
	 * @param array $defaults Default settings.
	 *
	 * @return array
	 *
	 * @since  2.0
	 */
	public function default_settings( $defaults ) {
		$defaults = array_merge( $defaults, $this->setup()->settings_defaults );
		return $defaults;
	}


	/**
	 * Create a post type
	 *
	 * @since  2.0
	 */
	public function create_taxonomies() {
		register_post_type(
			'um_social_login',
			array(
				'labels'          =>
				array(
					'name'               => __( 'Social Login Shortcodes', 'um-social-login' ),
					'singular_name'      => __( 'Social Login Shortcode', 'um-social-login' ),
					'add_new'            => __( 'Add New', 'um-social-login' ),
					'add_new_item'       => __( 'Add New Social Login Shortcode', 'um-social-login' ),
					'edit_item'          => __( 'Edit', 'um-social-login' ),
					'not_found'          => __( 'You did not create any social login shortcodes yet', 'um-social-login' ),
					'not_found_in_trash' => __( 'Nothing found in Trash', 'um-social-login' ),
					'search_items'       => __( 'Search social login shortcodes', 'um-social-login' ),
				),
				'show_ui'         => true,
				'show_in_menu'    => false,
				'public'          => false,
				'supports'        => array( 'title' ),
				'capability_type' => 'page',
			)
		);
	}

	/**
	 * Add Custom Post Type
	 *
	 * @param array $um_cpt Custom Post Types.
	 *
	 * @return array
	 */
	public function add_cpt( $um_cpt ) {
		$um_cpt[] = 'um_social_login';
		return $um_cpt;
	}

	/**
	 * This class
	 *
	 * @return $this
	 *
	 * @since  2.0
	 */
	public function get_this() {
		return $this;
	}

	/**
	 * Setup class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Setup()
	 *
	 * @since  2.0
	 */
	public function setup() {
		if ( empty( UM()->classes['um_social_login_setup'] ) ) {
			UM()->classes['um_social_login_setup'] = new um_ext\um_social_login\core\Social_Login_Setup();
		}
		return UM()->classes['um_social_login_setup'];
	}


	/**
	 * Admin class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Admin()
	 *
	 * @since  2.0
	 */
	public function admin() {
		if ( empty( UM()->classes['um_social_login_admin'] ) ) {
			UM()->classes['um_social_login_admin'] = new um_ext\um_social_login\core\Social_Login_Admin();
		}
		return UM()->classes['um_social_login_admin'];
	}


	/**
	 * Enqueue class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Enqueue()
	 */
	public function enqueue() {
		if ( empty( UM()->classes['um_social_login_enqueue'] ) ) {
			UM()->classes['um_social_login_enqueue'] = new um_ext\um_social_login\core\Social_Login_Enqueue();
		}
		return UM()->classes['um_social_login_enqueue'];
	}


	/**
	 * Shortcode class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Shortcode()
	 *
	 * @since  2.0
	 */
	public function shortcode() {
		if ( empty( UM()->classes['um_social_login_shortcode'] ) ) {
			UM()->classes['um_social_login_shortcode'] = new um_ext\um_social_login\core\Social_Login_Shortcode();
		}
		return UM()->classes['um_social_login_shortcode'];
	}


	/**
	 * Ajax class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Ajax()
	 *
	 * @since  2.0
	 */
	public function ajax() {
		if ( empty( UM()->classes['um_social_login_ajax'] ) ) {
			UM()->classes['um_social_login_ajax'] = new um_ext\um_social_login\core\Social_Login_Ajax();
		}
		return UM()->classes['um_social_login_ajax'];
	}


	/**
	 * Hybridauth class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Hybridauth()
	 *
	 * @since  2.2
	 */
	public function hybridauth() {
		if ( empty( UM()->classes['um_social_login_hybridauth'] ) ) {
			UM()->classes['um_social_login_hybridauth'] = new um_ext\um_social_login\core\Social_Login_Hybridauth();
		}
		return UM()->classes['um_social_login_hybridauth'];
	}


	/**
	 * Connect class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Connect()
	 *
	 * @since  2.2
	 */
	public function user_connect() {
		if ( empty( UM()->classes['um_social_login_connect'] ) ) {
			UM()->classes['um_social_login_connect'] = new um_ext\um_social_login\core\Social_Login_Connect();
		}
		return UM()->classes['um_social_login_connect'];
	}


	/**
	 * Disconnect class
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Disconnect()
	 *
	 * @since  2.2
	 */
	public function user_disconnect() {
		if ( empty( UM()->classes['um_social_login_disconnect'] ) ) {
			UM()->classes['um_social_login_disconnect'] = new um_ext\um_social_login\core\Social_Login_Disconnect();
		}
		return UM()->classes['um_social_login_disconnect'];
	}


	/**
	 * User class
	 *
	 * @param integer $user_id User ID.
	 *
	 * @return um_ext\um_social_login\core\Social_Login_Users()
	 *
	 * @since  2.2
	 */
	public function user( $user_id = null ) {
		if ( empty( UM()->classes['um_social_login_users'] ) ) {
			UM()->classes['um_social_login_users'] = new um_ext\um_social_login\core\Social_Login_Users( $user_id );
		}
		return UM()->classes['um_social_login_users'];
	}


	/**
	 * Session start
	 *
	 * @uses um_is_session_started
	 *
	 * @since  2.0
	 */
	public function session_start() {

		if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
			return;
		}

		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			return;
		}

		if ( um_is_session_started() === false ) {
			@session_start(); //phpcs:ignore
		}
	}


	/**
	 * Init
	 *
	 * @uses session_start
	 *
	 * @since  2.0
	 */
	public function init() {

		// Actions.
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/actions/um-social-login-form.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/actions/um-social-login-admin.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/actions/um-social-login-connect.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/actions/um-social-login-compatibility.php';

		// Filters.
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-license.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-settings.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-account.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-profile.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-connect.php';
		require_once UM_SOCIAL_LOGIN_PATH . 'includes/core/filters/um-social-login-notifications.php';
	}


	/**
	 * Available networks
	 *
	 * @return mixed
	 *
	 * @since  2.0
	 */
	public function available_networks() {

		$arr_networks = apply_filters( 'um_social_login_networks', $this->networks );

		foreach ( $arr_networks as $id => $data ) {
			if ( empty( UM()->options()->get( 'enable_' . $id ) ) ) {
				unset( $arr_networks[ $id ] );
			}
		}

		$this->networks = $arr_networks;

		return $arr_networks;
	}


	/**
	 * Network Icons
	 *
	 * @param string $provider Provider slug.
	 *
	 * @since  2.2
	 */
	public function get_network_icon( $provider = '' ) {

		$networks = $this->available_networks();

		if ( isset( $networks[ $provider ]['icon'] ) ) {
			return '<i class="' . esc_attr( $networks[ $provider ]['icon'] ) . '" style="float: left;margin-left: -40px;margin-top: 30px;"></i>';
		}
	}

	/**
	 * Network Provider name
	 *
	 * @param string $provider Social Network Provider.
	 *
	 * @since  2.2
	 */
	public function get_network_name( $provider = '' ) {

		$networks = $this->available_networks();

		if ( isset( $networks[ $provider ]['name'] ) ) {
			return $networks[ $provider ]['name'];
		}

		return false;
	}

	/**
	 * Available networks with single callback urls
	 *
	 * @return array
	 *
	 * @since  2.2
	 */
	public function get_single_callback_networks() {

		$networks     = $this->available_networks();
		$arr_networks = array();

		foreach ( $networks as $provider => $options ) {
			if ( isset( $options['has_single_callback'] ) ) {
				$arr_networks[ $provider ] = $options;
			}
		}

		return $arr_networks;
	}


	/**
	 * Number of connected users
	 *
	 * @param integer $id Provider handler ID.
	 *
	 * @return int
	 *
	 * @since  2.0
	 */
	public function count_users( $id ) {
		$args = array(
			'fields' => 'ID',
			'number' => 0,
		);

		$args['meta_query'][] = array(
			array(
				'key'     => '_uid_' . $id,
				'value'   => '',
				'compare' => '!=',
			),
		);

		$users = new WP_User_Query( $args );

		return count( $users->results );
	}


	/**
	 * Set Redirect from sessions
	 *
	 * @return array
	 *
	 * @since  2.0
	 */
	public function redirect() {
		$sso_session = UM()->Social_Login_API()->hybridauth()->session();
		if ( null !== $sso_session->get( 'um_social_login_redirect_after' ) ) {

			$redirect_to  = $sso_session->get( 'um_social_login_redirect_after' );
			$is_shortcode = $sso_session->get( 'um_sso' );
			$sso_session->delete( 'um_social_login_redirect' );
			return array(
				'has_redirect' => true,
				'redirect_to'  => $redirect_to,
				'is_shortcode' => $is_shortcode,
			);
		}

		return array(
			'has_redirect' => false,
			'redirect_to'  => '',
			'is_shortcode' => false,
		);
	}

	/**
	 * Get submit button on form
	 *
	 * @since  2.0
	 */
	public function show_submit_button() {
		?>

		<div class="um-col-alt">
			<input type="hidden" name="_social_login_form" id="_social_login_form" value="true" />
			<div class="um-center"><input type="submit" value="<?php esc_attr_e( 'Complete Registration', 'um-social-login' ); ?>" class="um-button" /></div>
			<div class="um-clear"></div>
		</div>

		<?php
	}


	/**
	 * Get form id
	 *
	 * @return int
	 *
	 * @since  2.0
	 */
	public function form_id() {
		return get_option( 'um_social_login_form_installed' );
	}


	/**
	 * Modify global query vars
	 *
	 * @param array $public_query_vars Query vars.
	 *
	 * @return array
	 *
	 * @since  2.0
	 */
	public function query_vars( $public_query_vars ) {
		$public_query_vars[] = 'state';
		$public_query_vars[] = 'code';
		$public_query_vars[] = 'provider';

		return $public_query_vars;
	}


	/**
	 *  Clear session after user logout
	 *
	 * @since  2.0
	 */
	public function um_clear_session_after_logout() {
		unset( $_COOKIE['PHPSESSID'] );
		setcookie( 'PHPSESSID', '', -1, '/' );
	}


	/**
	 * Error Message handler
	 *
	 * @param string $err Error.
	 * @param string $error_code Error code.
	 *
	 * @return string
	 *
	 * @since  2.0
	 */
	public function error_message_handler( $err, $error_code ) {
		switch ( $error_code ) {
			case 'um_social_user_denied':
				$err = __( 'We were unable to request application access permissions.', 'um-social-login' );
				break;
			case 'um_social_unauthorized_scope_error':
				$err = __( 'One of the scopes is not authorized by your developer application.', 'um-social-login' );
				break;
			case 'um_sso_not_linked':
				if ( isset( $_REQUEST['um_dynamic_sso'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
					/* translators: %s is a registration page link */
					$err = sprintf( __( 'Your social account is not yet linked to the site. Please login with your username and password or <a href="%s">click here</a> to register with your social account..', 'um-social-login' ), um_get_core_page( 'register' ) );
				} else {
					/* translators: %s is a registration page link */
					$err = sprintf( __( 'Your social account is not yet linked to the site. Please login below with your username and password or <a href="%s">click here</a> to register with your social account..', 'um-social-login' ), um_get_core_page( 'register' ) );
				}
				break;
			case 'um_sso_already_linked':
				$err = __( 'Your social account is already linked to the site.', 'um-social-login' );
				break;
			case 'um_sso_email_already_linked':
				$err = __( 'You\'re not allowed to create a new account with the email address added to your social account. Please login and link your social account in the Account page.', 'um-social-login' );
				break;
		}

		return $err;
	}

	/**
	 * Generate unique username
	 *
	 * @param string $username Username.
	 * @return string
	 *
	 * @since  2.2
	 */
	public function generate_unique_username( $username ) {

		$username = sanitize_user( $username );

		static $i;
		if ( null === $i ) {
			$i = 1;
		} else {
			++$i;
		}
		if ( ! username_exists( $username ) ) {
			return $username;
		}
		$new_username = sprintf( '%s-%s', $username, $i );
		if ( ! username_exists( $new_username ) ) {
			return $new_username;
		} else {
			return call_user_func( array( $this, __FUNCTION__ ), $username );
		}
	}

	/**
	 * Remote Request with Delete method
	 *
	 * @param string $url the URL.
	 * @param array  $args URL parameters.
	 *
	 * @since 2.3.13
	 */
	public function wp_remote_delete( $url, $args ) {
		$defaults = array( 'method' => 'DELETE' );
		$r        = wp_parse_args( $args, $defaults );
		return wp_remote_request( $url, $r );
	}
}

/**
 * Create class variable
 *
 * @since  2.0
 */
function um_init_social_login() {
	if ( function_exists( 'UM' ) ) {
		UM()->set_class( 'Social_Login_API', true );
	}
}
add_action( 'plugins_loaded', 'um_init_social_login', -10, 1 );
