Skip to content

Commit

Permalink
integrating hCaptcha and ReCaptcha adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
Vahram1995 committed Apr 13, 2023
1 parent c01d744 commit 1491d2f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 189 deletions.
68 changes: 36 additions & 32 deletions src/Libraries/Captcha/Adapters/HcaptchaAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Quantum\Libraries\Captcha\Adapters;

use Quantum\Exceptions\CaptchaException;
use Quantum\Libraries\Captcha\CaptchaInterface;
use Quantum\Libraries\Curl\HttpClient;

Expand Down Expand Up @@ -73,35 +72,15 @@ public static function getInstance(array $params): HcaptchaAdapter
*
* @return string
*/
public function display($formIdentifier = '', $attributes = [])
public function display(string $formIdentifier = '', array $attributes = []): string
{
$captchaElement = '';
if (strtolower($this->type) == 'visible'){
$attributes = $this->prepareAttributes($attributes);
$captchaEleme = '<div' . $this->buildAttributes($attributes) . '></div>';
$captchaElement = $this->getVisibleElement($attributes);
} elseif (strtolower($this->type) == 'invisible') {
$captchaEleme = '';
if (!isset($attributes['data-callback'])) {
$functionName = 'onSubmit' . str_replace(['-', '=', '\'', '"', '<', '>', '`'], '', $formIdentifier);
$attributes['data-callback'] = $functionName;
$captchaEleme = '<script>
document.addEventListener("DOMContentLoaded", function() {
let button = document.getElementsByTagName("button");
button[0].setAttribute("data-sitekey", "' . $this->sitekey . '");
button[0].setAttribute("data-callback", "'. $functionName .'");
button[0].classList.add("h-captcha");
})
function '. $functionName .'(){
document.getElementById("'. $formIdentifier .'").submit();
}
</script>';
}
}else{
throw CaptchaException::cantConnect();
$captchaElement = $this->getInvisibleElement($formIdentifier);
}

return $captchaEleme;
return $captchaElement;
}

/**
Expand All @@ -113,7 +92,7 @@ function '. $functionName .'(){
*
* @return string
*/
public function renderJs($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
public function renderJs($lang = null, $callback = false, $onLoadClass = 'onloadCallBack'): string
{
return '<script src="' . $this->getJsLink($lang, $callback, $onLoadClass) . '" async defer></script>' . "\n";
}
Expand All @@ -126,7 +105,7 @@ public function renderJs($lang = null, $callback = false, $onLoadClass = 'onload
*
* @return bool
*/
public function verifyResponse($response, $clientIp = null)
public function verifyResponse(string $response, string $clientIp = null): bool
{
if (empty($response)) {
return false;
Expand Down Expand Up @@ -161,7 +140,7 @@ public function verifyResponse($response, $clientIp = null)
*
* @return string
*/
public function getJsLink($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
public function getJsLink(string $lang = null, bool $callback = false, string $onLoadClass = 'onloadCallBack'): string
{
$client_api = static::CLIENT_API;
$params = [];
Expand Down Expand Up @@ -189,7 +168,7 @@ protected function setCallBackParams(&$params, $onLoadClass)
*
* @return array
*/
protected function sendRequestVerify(array $query = [])
protected function sendRequestVerify(array $query = []): array
{
$this->http->createRequest(static::VERIFY_URL)->setMethod('POST')->setData($query)->start();

Expand All @@ -203,7 +182,7 @@ protected function sendRequestVerify(array $query = [])
*
* @return array
*/
protected function prepareAttributes(array $attributes)
protected function prepareAttributes(array $attributes): array
{
$attributes['data-sitekey'] = $this->sitekey;
if (!isset($attributes['class'])) {
Expand All @@ -221,7 +200,7 @@ protected function prepareAttributes(array $attributes)
*
* @return string
*/
protected function buildAttributes(array $attributes)
protected function buildAttributes(array $attributes): string
{
$html = [];

Expand All @@ -231,4 +210,29 @@ protected function buildAttributes(array $attributes)

return count($html) ? ' ' . implode(' ', $html) : '';
}

private function getInvisibleElement($formIdentifier): string
{
$functionName = 'onSubmit' . str_replace(['-', '=', '\'', '"', '<', '>', '`'], '', $formIdentifier);

return '<script>
document.addEventListener("DOMContentLoaded", function() {
let button = document.getElementsByTagName("button");
button[0].setAttribute("data-sitekey", "' . $this->sitekey . '");
button[0].setAttribute("data-callback", "'. $functionName .'");
button[0].classList.add("h-captcha");
})
function '. $functionName .'(){
document.getElementById("'. $formIdentifier .'").submit();
}
</script>';
}

private function getVisibleElement($attributes): string
{
$attributes = $this->prepareAttributes($attributes);
return '<div' . $this->buildAttributes($attributes) . '></div>';
}
}
196 changes: 42 additions & 154 deletions src/Libraries/Captcha/Adapters/RecaptchaAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,15 @@ class RecaptchaAdapter implements CaptchaInterface
*/
private $secretkey;

private $http;

/**
* Remote IP address
*
* @var string
*/
protected $remoteIp = null;

/**
* Supported themes
*
* @var array
* @see https://developers.google.com/recaptcha/docs/display#config
*/
protected static $themes = array('light', 'dark');

/**
* Captcha theme. Default : light
*
* @var string
* @see https://developers.google.com/recaptcha/docs/display#config
*/
protected $theme = null;

/**
* Supported types
*
Expand All @@ -77,12 +63,6 @@ class RecaptchaAdapter implements CaptchaInterface
*/
protected $language = null;

/**
* CURL timeout (in seconds) to verify response
*
* @var int
*/
private $verifyTimeout = 1;

/**
* Captcha size. Default : normal
Expand Down Expand Up @@ -131,151 +111,35 @@ public static function getInstance(array $params): RecaptchaAdapter
return self::$instance;
}

/**
* Set theme
*
* @param string $theme (see https://developers.google.com/recaptcha/docs/display#config)
* @return object
*/
public function setTheme($theme = 'light')
{
if (in_array($theme, self::$themes))
$this->theme = $theme;
else
throw new \Exception('Theme "' . $theme . '"" is not supported. Available themes : ' . join(', ', self::$themes));

return $this;
}

/**
* Set type
*
* @param string $type (see https://developers.google.com/recaptcha/docs/display#config)
* @return object
*/
public function setType($type = 'image')
{
if (in_array($type, self::$types))
$this->type = $type;

return $this;
}

/**
* Set language
*
* @param string $language (see https://developers.google.com/recaptcha/docs/language)
* @return object
*/
public function setLanguage($language)
{
$this->language = $language;

return $this;
}

/**
* Set timeout
*
* @param int $timeout
* @return object
*/
public function setVerifyTimeout($timeout)
{
$this->verifyTimeout = $timeout;

return $this;
}

/**
* Set size
*
* @param string $size (see https://developers.google.com/recaptcha/docs/display#render_param)
* @return object
*/
public function setSize($size)
{
$this->size = $size;

return $this;
}

/**
* Generate the JS code of the captcha
*
* @return string
*/
public function renderJs($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
{
$data = array();
if (!is_null($this->language))
$data = array('hl' => $this->language);

return '<script src="https://www.google.com/recaptcha/api.js?' . http_build_query($data) . '"></script>';
}

/**
* Get hCaptcha js link.
*
* @param string $lang
* @param boolean $callback
* @param null $lang
* @param bool $callback
* @param string $onLoadClass
*
* @return string
*/
public function getJsLink($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
public function renderJs($lang = null, $callback = false, $onLoadClass = 'onloadCallBack'): string
{
$client_api = static::CLIENT_API;
$params = [];

$callback ? $this->setCallBackParams($params, $onLoadClass) : false;
$lang ? $params['hl'] = $lang : null;

return $client_api . '?' . http_build_query($params);
return '<script src="'. self::CLIENT_API .'"></script>';
}

/**
* Generate the HTML code block for the captcha
*
* @param string $formIdentifier
* @param array $attributes
* @return string
*/
public function display($formIdentifier = '', $attributes = [])
public function display(string $formIdentifier = '', array $attributes = []): string
{
if (!empty($this->sitekey)) {
if (strtolower($this->type) == 'visible'){
$data = 'data-sitekey="' . $this->sitekey . '"';

if (!is_null($this->theme))
$data .= ' data-theme="' . $this->theme . '"';

if (!is_null($this->type))
$data .= ' data-type="' . $this->type . '"';

if (!is_null($this->size))
$data .= ' data-size="' . $this->size . '"';

$captchaEleme = '<div class="col s1 offset-s2 g-recaptcha" ' . $data . '></div>';
} elseif (strtolower($this->type) == 'invisible') {
$captchaEleme = '';
if (!isset($attributes['data-callback'])) {
$captchaEleme = '<script>
document.addEventListener("DOMContentLoaded", function() {
let button = document.getElementsByTagName("button");
button[0].setAttribute("data-sitekey", "' . $this->sitekey . '");
button[0].setAttribute("data-callback", "onSubmit");
button[0].setAttribute("data-action", "submit");
button[0].classList.add("g-recaptcha");
})
function onSubmit (token){
document.getElementById("'. $formIdentifier .'").submit();
}
</script>';
}
}
return $captchaEleme;
$captchaElement = '';
if (strtolower($this->type) == 'visible'){
$captchaElement = $this->getVisibleElement();
} elseif (strtolower($this->type) == 'invisible') {
$captchaElement = $this->getInvisibleElement($formIdentifier);
}
return $captchaElement;
}

/**
Expand All @@ -284,7 +148,7 @@ function onSubmit (token){
* @param string $response Response code after submitting form (usually $_POST['g-recaptcha-response'])
* @return bool
*/
public function verifyResponse($response, $clientIp = null)
public function verifyResponse(string $response, $clientIp = null): bool
{
if (is_null($this->secretkey))
throw new \Exception('You must set your secret key');
Expand Down Expand Up @@ -323,7 +187,7 @@ public function verifyResponse($response, $clientIp = null)
*
* @return array Errors code and name
*/
public function getErrorCodes()
public function getErrorCodes(): array
{
$errors = array();

Expand Down Expand Up @@ -390,5 +254,29 @@ public function getErrorCodes()

return $errors;
}


private function getInvisibleElement(string $formIdentifier): string
{
return '<script>
document.addEventListener("DOMContentLoaded", function() {
let button = document.getElementsByTagName("button");
button[0].setAttribute("data-sitekey", "' . $this->sitekey . '");
button[0].setAttribute("data-callback", "onSubmit");
button[0].setAttribute("data-action", "submit");
button[0].classList.add("g-recaptcha");
})
function onSubmit (){
document.getElementById("'. $formIdentifier .'").submit();
}
</script>';
}

private function getVisibleElement(): string
{
$data = 'data-sitekey="' . $this->sitekey . '"';

return '<div class="col s1 offset-s2 g-recaptcha" ' . $data . '></div>';
}
}

0 comments on commit 1491d2f

Please sign in to comment.