HEX
Server: nginx/1.24.0
System: Linux server 6.12.74+deb13+1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.74-2 (2026-03-08) x86_64
User: www (1001)
PHP: 8.5.2
Disabled: passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Upload Files
File: /www/wwwroot/claudiayancor.duckdns.org/wp-content/plugins/photonic/Modules/OAuth2.php
<?php

namespace Photonic_Plugin\Modules;

use Photonic_Plugin\Core\Photonic;

require_once 'Core.php';
require_once 'Authenticator.php';

abstract class OAuth2 extends Core {
	use Authenticator;

	public $scope;
	public $response_type;
	public $client_id;
	public $client_secret;
	public $state;
	public $access_token;
	public $auth_error;
	public $soon_limit;

	protected function __construct() {
		$this->soon_limit = 30;
		parent::__construct();
	}

	abstract public function authentication_url();

	abstract public function access_token_url();

	abstract public function renew_token($token);

	abstract protected function set_token_validity($validity);

	public function redirect_url() {
		return get_site_url();
	}

	public function get_authorization_url($args = []) {
		$url        = add_query_arg('test', 'test');
		$url        = remove_query_arg('test', $url);
		$parameters = array_merge(
			[
				'response_type' => $this->response_type,
				'redirect_uri'  => $this->redirect_url(),
				'client_id'     => $this->client_id,
				'scope'         => $this->scope,
				'access_type'   => 'offline',
				'state'         => md5($this->client_secret . $this->provider) . '::' . rawurlencode($url),
			],
			$args
		);
		return $this->authentication_url() . "?" . Authenticator::build_query($parameters);
	}

	/**
	 * Takes an OAuth request token and exchanges it for an access token.
	 *
	 * @param $request_token
	 */
	public function get_access_token($request_token) {
		$code       = $request_token['code'];
		$state_args = explode('::', $request_token['state']);

		if (md5($this->client_secret . $this->provider) === $state_args[0]) {
			$url      = urldecode($state_args[1]);
			$response = Photonic::http(
				$this->access_token_URL(),
				'POST',
				[
					'code'          => $code,
					'grant_type'    => 'authorization_code',
					'client_id'     => $this->client_id,
					'client_secret' => $this->client_secret,
					'redirect_uri'  => $this->redirect_url(),
				]
			);

			if (is_wp_error($response)) {
				$url = add_query_arg('error', $response->get_error_code(), $url);
			}
			elseif (empty($response)) {
				$url = add_query_arg('error', 'null', $url);
			}
		}
		else {
			$url = remove_query_arg(['token', 'code', 'state']);
		}
		wp_safe_redirect($url);
		exit();
	}

	/**
	 * @param $base_token
	 */
	public function authenticate($base_token) {
		$photonic_authentication = get_option('photonic_authentication');
		if (!isset($photonic_authentication)) {
			$photonic_authentication = [];
		}

		$transient_token = get_transient('photonic_' . $this->provider . '_token');
		if (empty($transient_token) && !isset($photonic_authentication[$this->provider]) && !empty($base_token)) {
			// Nothing is in the authentication option, but there is a token in overall Photonic Options.
			// Refresh it if required, and save it as a transient via renew_token.
			list($token, $error) = $this->renew_token($base_token);
		}
		elseif ($transient_token || isset($photonic_authentication[$this->provider])) {
			$token = empty($transient_token) ? $photonic_authentication[$this->provider] : $transient_token;
			if (!empty($token)) {
				if (empty($transient_token) && !($this->is_token_expired($token) || $this->is_token_expiring_soon($this->soon_limit) > 0)) {
					set_transient('photonic_' . $this->provider . '_token', $token, $token['oauth_token_expires']);
					$this->set_token_validity(true);
				}
				elseif ($this->is_token_expired($token) || $this->is_token_expiring_soon($this->soon_limit) > 0) {
					list($token, $error) = $this->renew_token($base_token);
				}
				else {
					$this->set_token_validity(true);
				}
			}
			else {
				list($token, $error) = $this->renew_token($base_token);
			}
		}

		if (!empty($token)) {
			$this->access_token = $token['oauth_token'];
			$this->auth_error   = '';
		}
		else {
			$this->set_token_validity(false);
			if (!empty($error)) {
				$this->auth_error = $error;
			}
			else {
				$this->auth_error = '';
			}
		}
	}

	public function is_token_expired($token) {
		if (empty($token)) {
			return true;
		}
		if (!isset($token['oauth_token']) || !isset($token['oauth_token_created']) || !isset($token['oauth_token_expires'])) {
			return true;
		}
		if (!isset($token['client_id']) || (isset($token['client_id']) && $token['client_id'] !== $this->client_id)) {
			return true;
		}
		$current = time();
		if ($token['oauth_token_created'] + $token['oauth_token_expires'] < $current) {
			return true;
		}
		return false;
	}

	/**
	 * Checks if a token will expire soon. This is used to trigger a refresh for sources such as Instagram. Google uses a separate "Refresh Token",
	 * so this is not applicable to it. The <code>soon_limit</code> defines how many days is "soon", and a refresh is triggered if the current date
	 * is in the "soon" range. E.g. If you have a soon limit of 30 days, and your token expires in 15 days when you load the page, this method will
	 * return <code>true</code>.
	 *
	 * For cases where the token does not exist yet, the method returns <code>null</code>.
	 *
	 * @param $soon_limit int Number of days to check the expiry limit for.
	 * @return int|null If there is no token, return null. Otherwise, if there are < $soon_limit days left, return 1, if token is expired return -1, and if there is time return 0.
	 */
	abstract public function is_token_expiring_soon($soon_limit);

	/**
	 * Takes a token response from a request token call, then puts it in an appropriate array.
	 *
	 * @param $response
	 * @return array
	 */
	public function parse_token($response) {
		$token = [];
		if (!is_wp_error($response) && is_array($response)) {
			$body = $response['body'];
			$body = json_decode($body);
			if (empty($body->error)) {
				$token['oauth_token']         = $body->access_token;
				$token['oauth_token_type']    = $body->token_type;
				$token['oauth_token_created'] = time();
				$token['oauth_token_expires'] = $body->expires_in;
				$this->set_token_validity(true);
			}
			else {
				$this->set_token_validity(false);
			}
		}
		return $token;
	}
}