praiadeseselle/site/modules/MarkupGoogleRecaptcha/MarkupGoogleRecaptcha.module
2024-04-16 11:51:21 +02:00

331 lines
12 KiB
Text

<?php
class MarkupGoogleRecaptcha extends WireData implements Module, ConfigurableModule {
static function getModuleInfo() {
return [
'title' => 'Markup Google reCAPTCHA',
'summary' => 'Google reCAPTCHA for ProcessWire',
'version' => '2.0.0',
'author' => 'flydev',
'href' => 'https://processwire.com/talk/topic/13738-markup-google-recaptcha/',
'icon' => 'puzzle-piece',
'autoload'=> false,
'singular'=> false
];
}
const SITE_RECAPTCHA_API_URL = "https://www.google.com/recaptcha/api.js";
const SITE_VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";
protected static $defaultSettings = [
'site_key' => '',
'secret_key' => '',
'data_theme' => '0',
'data_type' => '0',
'data_size' => '0',
'data_index' => '0',
'data_recaptcha_type' => 'recaptchav2'
];
public function __construct()
{
$this->setArray(self::$defaultSettings);
}
public function render($form = null, $lang = "")
{
if(!$form instanceof InputfieldForm)
{
$out = $this->buildGoogleDiv($lang);
return $out;
}
else
{
$inputfield = $this->modules->get("InputfieldMarkup");
$inputfield->value = $this->buildGoogleDiv($lang);
return $form->add($inputfield);
}
}
protected function buildGoogleDiv($lang = "")
{
$reCaptchaClass = "g-recaptcha";
$reCaptchaID = $reCaptchaClass . "-" . uniqid();
$attributes = array(
'id' => $reCaptchaID,
'class' => $reCaptchaClass,
'data-id' => $reCaptchaID,
'data-hl' => $lang,
'data-sitekey' => $this->site_key,
'data-theme' => ($this->data_theme) ? 'dark' : 'light',
'data-type' => ($this->data_type) ? 'audio' : 'image',
'data-size' => ($this->data_size) ? 'compact' : 'normal',
'data-index' => ($this->data_index) ? $this->data_index : '0',
);
if($this->data_recaptcha_type == 'invisible') {
$attributes['data-size'] = 'invisible';
$attributes['data-badge'] = ($this->data_badge) ? $this->data_badge : 'bottomright';
}
$div = '<div '.join(' ', array_map(function($key) use ($attributes)
{
if(is_bool($attributes[$key]))
return $attributes[$key] ? $key : '';
return $key.'="'.$attributes[$key].'"';
}, array_keys($attributes))).' ></div>';
/*if(isset($this->data_recaptcha_type) && $this->data_recaptcha_type == 'invisible') {
$div .= "
<script>
var renderInvisibleCallback = function() {
for (var i = 0; i < document.forms.length; ++i) {
var form = document.forms[i];
var div = form.querySelector('.g-recaptcha');
if (null === div){
continue;
}
(function(f){
var divId = grecaptcha.render(div,{
'sitekey': '" . $attributes['data-sitekey'] . "',
'size': '" . $attributes['data-size'] . "',
'badge' : '" . $attributes['data-badge'] . "',
'callback' : function (recaptchaToken) {
HTMLFormElement.prototype.submit.call(f);
}
});
f.onsubmit = function (e){
e.preventDefault();
grecaptcha.execute(divId);
};
})(form);
}
};
</script>";
}*/
return $div;
}
public function getScript()
{
$params = '';
if(isset($this->data_recaptcha_type) && $this->data_recaptcha_type == 'invisible') {
$params = '?onload=renderInvisibleCallback&render=explicit';
$return = "
<script>
var renderInvisibleCallback = function() {
for (var i = 0; i < document.forms.length; ++i) {
var form = document.forms[i];
var div = form.querySelector('.g-recaptcha');
if (null === div){
continue;
}
(function(f){
var divId = grecaptcha.render(div, {
'sitekey': div.getAttribute('data-sitekey'),
'size': div.getAttribute('data-size'),
'badge' : div.getAttribute('data-badge'),
'callback' : function (recaptchaToken) {
HTMLFormElement.prototype.submit.call(f);
}
});
f.onsubmit = function (e){
e.preventDefault();
grecaptcha.execute(divId);
};
})(form);
}
};
</script>";
$return .= "<script src='".self::SITE_RECAPTCHA_API_URL."$params' async defer></script>";
}
elseif(isset($this->data_recaptcha_type) && $this->data_recaptcha_type == 'recaptchav2') {
$return = "<script src='".self::SITE_RECAPTCHA_API_URL."' async defer></script>";
}
return $return;
}
public function getScriptMulti() {
$return = "<script type='text/javascript'>
var onloadReCaptchaCallback = function(){
jQuery('.g-recaptcha').each(function() {
var _this = jQuery(this);
var recaptchaID = _this.data('id'),
hl = _this.data('hl'),
sitekey = _this.data('sitekey'),
theme = _this.data('theme'),
type = _this.data('type'),
size = _this.data('size'),
index = _this.data('index');
if(recaptchaID !== undefined) {
var recaptchaWidget = grecaptcha.render(recaptchaID, {
'hl' : hl,
'sitekey' : sitekey,
'theme' : theme,
'type' : type,
'size' : size,
'index' : index
});
grecaptcha.getResponse(recaptchaWidget);
// grecaptcha.reset(recaptchaWidget);
}
});
};
</script>";
$return .= "<script src='".self::SITE_RECAPTCHA_API_URL."?onload=onloadReCaptchaCallback&render=explicit' async defer></script>";
return $return;
}
public function verifyResponse()
{
if (!wire('input')->post['g-recaptcha-response'])
return false;
$data = [
'remoteip' => $_SERVER["REMOTE_ADDR"],
'secret' => $this->secret_key,
'response' => wire('input')->post['g-recaptcha-response']
];
$http = new WireHttp();
$query = http_build_query($data);
$response = $http->get(self::SITE_VERIFY_URL."?{$query}");
$response = json_decode($response, true);
return ($response['success'] === true) ? true : false;
}
public static function getModuleConfigInputfields(array $data)
{
$wrap = new InputfieldWrapper();
/*
* api settings
*/
$form = wire('modules')->get('InputfieldFieldset');
$form->label = __('Google reCAPTCHA API Settings');
$form->notes = __('You can obtain the above information by creating an API key at [http://www.google.com/recaptcha/admin](http://www.google.com/recaptcha/admin)');
$form->collapsed = Inputfield::collapsedYes;
$inputfields = [
'site_key' => __('Site key'),
'secret_key' => __('Secret key')
];
foreach($inputfields as $name => $label) {
$f = wire('modules')->get('InputfieldText');
$f->attr('name', $name);
$f->label = $label;
$f->required = true;
$f->columnWidth = 50;
if(isset($data[$name])) $f->attr('value', $data[$name]);
$form->add($f);
}
$wrap->add($form);
/*
* mode
*/
$form = wire('modules')->get('InputfieldFieldset');
$form->label = __('Widget Mode');
$f = wire('modules')->get("InputfieldRadios");
$options = array('recaptchav2' => 'reCaptcha V2', 'invisible' => 'Invisible');
$f->name = 'data_recaptcha_type';
$f->label = __("Type of reCaptcha");
$f->description = __("Choose the type of reCaptcha.");
$f->addOptions($options);
isset($data['data_recaptcha_type']) ? $f->attr('value', $data['data_recaptcha_type']) : $f->attr('value', 'recaptchav2');
$f->columnWidth = 100;
$form->add($f);
$wrap->add($form);
/*
* recapatcha invisible settings
*/
$form = wire('modules')->get('InputfieldFieldset');
$form->label = __('Invisible Widget Settings');
$form->showIf = "data_recaptcha_type=invisible";
$f = wire('modules')->get("InputfieldSelect");
$options = array('bottomright' => 'bottomright', 'bottomleft' => 'bottomleft' , 'inline' => 'inline');
$f->name = 'data_badge';
$f->label = __("Badge");
$f->description = __("Reposition the reCAPTCHA badge. 'inline' allows you to control the CSS.");
$f->addOptions($options);
if(isset($data['data_badge'])) $f->attr('value', $data['data_badge']);
$f->columnWidth = 100;
$form->add($f);
$wrap->add($form);
/*
* recapatcha v2 settings
*/
$form = wire('modules')->get('InputfieldFieldset');
$form->label = __('reCapatcha V2 Widget Settings');
$form->showIf = "data_recaptcha_type=recaptchav2";
$inputfields = [
'data_theme' => ['label' => __("Use dark theme"), 'description' => __('The color theme of the widget. Default: light') ],
'data_size' => ['label' => __('Use compact widget'), 'description' => __('The size of the widget. Default: normal') ]
];
foreach($inputfields as $name => $value) {
$f = wire('modules')->get("InputfieldCheckbox");
$f->name = $name;
$f->label = $value['label'];
$f->description = $value['description'];
$f->value = 0;
$f->attr('checked', empty($data[$name]) ? '' : 'checked');
$f->columnWidth = 50;
$form->add($f);
}
$wrap->add($form);
/*
* global settings
*/
$form = wire('modules')->get('InputfieldFieldset');
$form->label = __('Global Widget Settings');
$inputfields = [
'data_type' => ['label' => __('Use audio type'), 'description' => __('The type of CAPTCHA to serve. Default: image') ],
'data_index' => ['name' => 'data_index', 'label' => __('Tabindex '), 'description' => __('The tabindex of the widget and challenge. Default: 0') ]
];
$f = wire('modules')->get('InputfieldText');
$f->name = $inputfields['data_index']['name'];
$f->label = $inputfields['data_index']['label'];
$f->description = $inputfields['data_index']['description'];
$f->value = (isset($data['data_index'])) ? $data['data_index'] : '0';
$f->columnWidth = 50;
$form->add($f);
$f = wire('modules')->get("InputfieldCheckbox");
$f->name = 'data_type';
$f->label = $inputfields['data_type']['label'];
$f->description = $inputfields['data_type']['description'];
$f->attr('checked', empty($data['data_type']) ? '' : 'checked');
$f->columnWidth = 50;
$form->add($f);
$wrap->add($form);
return $wrap;
}
}