namespace Ice\Auth\Social;
use Ice\Di;
use Ice\Exception;
/**
* Auth social adapter.
*
* @package Ice/Auth
* @category Adapter
* @author Ice Team
* @copyright (c) 2014-2025 Ice Team
* @license http://iceframework.org/license
*/
abstract class Adapter implements SocialInterface
{
protected options;
protected accessToken { set, get };
protected clientId;
protected clientSecret;
protected redirectUri;
protected provider { get };
protected socialFieldsMap = [];
protected userInfo;
protected responseType = "code" { get };
const GET = 0;
const POST = 1;
/**
* Adapter constructor.
*
* @param array config
* @throws Exception
*/
public function __construct(config = [])
{
var clientId, clientSecret, redirectUri, di, auth;
let di = Di::$fetch();
if !count(config) {
let auth = di->get("config")->get("auth");
if auth && auth->has(this->provider) {
let config = auth->get(this->provider)->toArray();
}
}
if fetch clientId, config["client_id"] {
let this->clientId = clientId;
}
if fetch clientSecret, config["client_secret"] {
let this->clientSecret = clientSecret;
}
if fetch redirectUri, config["redirect_uri"] {
let this->redirectUri = di->has("url") ? di->get("url")->href(redirectUri) : redirectUri;
}
if !this->clientId || !this->clientSecret || !this->redirectUri {
throw new Exception(["Option `%s`, `%s`, `%s` are required", "client_id", "client_secret", "redirect_uri"]);
}
let this->options = config;
}
/**
* Magic method to get user's info.
*
* @param string method
* @param mixed arguments
* @return mixed
*/
public function __call(string! name, arguments = null)
{
var key, value;
if starts_with(name, "get") {
let key = lcfirst(substr(name, 3));
if this->has(key) {
fetch value, arguments[0];
return this->get(key, value);
} else {
return null;
}
}
}
/**
* Whether or not an data exists by key.
*
* @param string key The data key
* @return boolean
*/
public function has(string key) -> boolean
{
// Unify the key between adapters
if isset this->socialFieldsMap[key] {
let key = this->socialFieldsMap[key];
}
return isset this->userInfo[key];
}
/**
* Retrieve a single key from an array.
* If the key does not exist in the array, the default value will be returned.
*
* @param string key The data key
* @param mixed defaultValue The value to return if data key does not exist
* @return mixed
*/
public function get(string key, var defaultValue = null)
{
var value;
// Unify the key between adapters
if isset this->socialFieldsMap[key] {
let key = this->socialFieldsMap[key];
}
if fetch value, this->userInfo[key] {
return value;
}
return defaultValue;
}
/**
* Get authentication url.
*
* @return string
*/
public function getAuthUrl()
{
var config;
let config = this->{"prepareAuthParams"}();
return config["auth_url"] . "?" . urldecode(http_build_query(config["auth_params"]));
}
/**
* Get option value with key.
*
* @param string key The option key
* @param mixed defaultValue The value to return if option key does not exist
* @return mixed
*/
public function getOption(string! key, var defaultValue = null)
{
var value;
if fetch value, this->options[key] {
return value;
}
return defaultValue;
}
/**
* Make curl get/post request and return result.
*
* @param int method
* @param string url
* @param array params
* @param boolean parse
* @return array|string
*/
protected function call(int method = self::GET, string url, array params, boolean parse = true)
{
var curl, result;
let curl = curl_init();
if method == self::GET {
curl_setopt(curl, CURLOPT_URL, url . "?" . urldecode(http_build_query(params)));
} else {
curl_setopt(curl, CURLOPT_URL, url);
curl_setopt(curl, CURLOPT_POST, 1);
curl_setopt(curl, CURLOPT_POSTFIELDS, urldecode(http_build_query(params)));
}
curl_setopt(curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
let result = curl_exec(curl);
curl_close(curl);
if parse {
let result = json_decode(result, true);
}
return result;
}
}