Commit de90b3f4 authored by Tino Goratsch's avatar Tino Goratsch

Merge branch 'feature/recaptcha' into develop

parents 25171244 5a644dc9
......@@ -69,7 +69,7 @@ class Settings implements SettingsInterface
*
* @return bool
*/
public function saveSettings($data, $module)
public function saveSettings(array $data, $module)
{
$bool = $bool2 = false;
$moduleId = $this->systemModuleRepository->getModuleId($module);
......
......@@ -25,5 +25,5 @@ interface SettingsInterface
*
* @return bool
*/
public function saveSettings($data, $module);
public function saveSettings(array $data, $module);
}
......@@ -51,19 +51,6 @@ class Validator
return $this;
}
/**
* @return array
*/
protected function getDefaultConstraintParams()
{
return [
'data' => null,
'field' => '',
'message' => '',
'extra' => []
];
}
/**
* @param string $validationRule
* @param array $params
......@@ -80,6 +67,19 @@ class Validator
return $this;
}
/**
* @return array
*/
protected function getDefaultConstraintParams()
{
return [
'data' => null,
'field' => '',
'message' => '',
'extra' => []
];
}
/**
* @param string $message
* @param string|array $field
......@@ -148,9 +148,7 @@ class Validator
$params['extra']
);
} else {
throw new ValidationRuleNotFoundException(
'Can not find the validation rule with the name ' . $constraint['rule'] . '.'
);
throw new ValidationRuleNotFoundException(sprintf($this->getExceptionMessage(), $constraint['rule']));
}
}
......@@ -159,6 +157,22 @@ class Validator
}
}
/**
* @return string
*/
private function getExceptionMessage()
{
return 'Can not find the validation rule with the name "%s".';
}
/**
* @return bool
*/
protected function hasErrors()
{
return !empty($this->errors);
}
/**
* @param string $validationRule
* @param mixed $field
......@@ -172,14 +186,6 @@ class Validator
return $this->validationRules[$validationRule]->isValid($field);
}
throw new ValidationRuleNotFoundException('Can not find the validation rule with the name ' . $validationRule . '.');
}
/**
* @return bool
*/
protected function hasErrors()
{
return !empty($this->errors);
throw new ValidationRuleNotFoundException(sprintf($this->getExceptionMessage(), $validationRule));
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Controller\Admin\Index;
use ACP3\Core\Controller\AbstractAdminAction;
class Index extends AbstractAdminAction
{
public function execute()
{
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Controller\Admin\Index;
use ACP3\Core\Controller\AbstractAdminAction;
use ACP3\Core\Controller\Context\FrontendContext;
use ACP3\Core\Helpers\Forms;
use ACP3\Core\Helpers\FormToken;
use ACP3\Modules\ACP3\Captcha\Extension\CaptchaExtensionInterface;
use ACP3\Modules\ACP3\Captcha\Installer\Schema;
use ACP3\Modules\ACP3\Captcha\Utility\CaptchaRegistrar;
use ACP3\Modules\ACP3\Captcha\Validation\AdminSettingsFormValidation;
class Settings extends AbstractAdminAction
{
/**
* @var Forms
*/
private $forms;
/**
* @var FormToken
*/
private $formToken;
/**
* @var CaptchaRegistrar
*/
private $captchaRegistrar;
/**
* @var AdminSettingsFormValidation
*/
private $formValidation;
/**
* Settings constructor.
*
* @param FrontendContext $context
* @param Forms $forms
* @param FormToken $formToken
* @param CaptchaRegistrar $captchaRegistrar
* @param AdminSettingsFormValidation $formValidation
*/
public function __construct(
FrontendContext $context,
Forms $forms,
FormToken $formToken,
CaptchaRegistrar $captchaRegistrar,
AdminSettingsFormValidation $formValidation
) {
parent::__construct($context);
$this->forms = $forms;
$this->formToken = $formToken;
$this->captchaRegistrar = $captchaRegistrar;
$this->formValidation = $formValidation;
}
/**
* @return array
*/
public function execute()
{
$settings = $this->config->getSettings(Schema::MODULE_NAME);
$captchas = [];
foreach ($this->captchaRegistrar->getAvailableCaptchas() as $serviceId => $captcha) {
/** @var CaptchaExtensionInterface $captcha */
$captchas[$serviceId] = $captcha->getCaptchaName();
}
return [
'captchas' => $this->forms->choicesGenerator('captcha', $captchas, $settings['captcha']),
'form' => array_merge($settings, $this->request->getPost()->all()),
'form_token' => $this->formToken->renderFormToken()
];
}
/**
* @return array|string|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function executePost()
{
return $this->actionHelper->handleSettingsPostAction(function () {
$formData = $this->request->getPost()->all();
$this->formValidation->validate($formData);
return $this->config->saveSettings($formData, Schema::MODULE_NAME);
});
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Controller\Index;
namespace ACP3\Modules\ACP3\Captcha\Controller\Frontend\Index;
use ACP3\Core;
/**
* Class Image
* @package ACP3\Modules\ACP3\Captcha\Controller\Index
*/
class Image extends Core\Controller\AbstractFrontendAction
{
/**
......
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\DependencyInjection;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class CaptchaCompilerPass implements CompilerPassInterface
{
/**
* @inheritdoc
*/
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('captcha.utility.captcha_registrar');
$plugins = $container->findTaggedServiceIds('captcha.extension.captcha');
foreach ($plugins as $serviceId => $tags) {
$definition->addMethodCall(
'registerCaptcha',
[$serviceId, new Reference($serviceId)]
);
}
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Event\Listener;
use ACP3\Core\View;
use ACP3\Core\View\Event\TemplateEvent;
class OnCaptchaAdminSettingsCustomFieldsListener
{
/**
* @var View
*/
private $view;
/**
* OnCaptchaAdminSettingsCustomFieldsListener constructor.
* @param View $view
*/
public function __construct(View $view)
{
$this->view = $view;
}
/**
* @param TemplateEvent $event
*/
public function renderRecaptchaSettings(TemplateEvent $event)
{
$params = $event->getParameters();
$this->view->assign('form', $params['form']);
$this->view->displayTemplate('Captcha/Partials/captcha_recaptcha.admin_settings.tpl');
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Event\Listener;
use ACP3\Core\I18n\Translator;
use ACP3\Core\Validation\Event\FormValidationEvent;
use ACP3\Core\Validation\ValidationRules\NotEmptyValidationRule;
class OnCaptchaValidationAdminSettingsCustomFieldsListener
{
/**
* @var Translator
*/
private $translator;
/**
* OnCaptchaValidationAdminSettingsCustomFieldsListener constructor.
* @param Translator $translator
*/
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
/**
* @param FormValidationEvent $event
*/
public function validateRecaptchaSettings(FormValidationEvent $event)
{
$formData = $event->getFormData();
if ($this->isRecaptcha($formData)) {
$event->getValidator()
->addConstraint(NotEmptyValidationRule::class, [
'data' => $formData,
'field' => 'recaptcha_sitekey',
'message' => $this->translator->t('captcha', 'type_in_recaptcha_sitekey')
])
->addConstraint(NotEmptyValidationRule::class, [
'data' => $formData,
'field' => 'recaptcha_secret',
'message' => $this->translator->t('captcha', 'type_in_recaptcha_secret')
]);
}
}
/**
* @param array $formData
* @return bool
*/
private function isRecaptcha(array $formData)
{
return !empty($formData['captcha']) && $formData['captcha'] === 'captcha.extension.recaptcha_captcha_extension';
}
}
......@@ -8,12 +8,8 @@ namespace ACP3\Modules\ACP3\Captcha\Event\Listener;
use ACP3\Core\ACL;
use ACP3\Core\View\Event\TemplateEvent;
use ACP3\Modules\ACP3\Captcha\Helpers;
use ACP3\Modules\ACP3\Captcha\Extension\CaptchaExtensionInterface;
/**
* Class OnFormAfterListener
* @package ACP3\Modules\ACP3\Captcha\Event\Listener
*/
class OnDisplayCaptchaListener
{
/**
......@@ -21,20 +17,20 @@ class OnDisplayCaptchaListener
*/
protected $acl;
/**
* @var \ACP3\Modules\ACP3\Captcha\Helpers
* @var CaptchaExtensionInterface
*/
protected $captchaHelper;
private $captchaExtension;
/**
* OnAfterFormListener constructor.
* OnDisplayCaptchaListener constructor.
*
* @param \ACP3\Core\ACL $acl
* @param \ACP3\Modules\ACP3\Captcha\Helpers $captchaHelper
* @param ACL $acl
* @param CaptchaExtensionInterface $captchaExtension
*/
public function __construct(ACL $acl, Helpers $captchaHelper)
public function __construct(ACL $acl, CaptchaExtensionInterface $captchaExtension)
{
$this->acl = $acl;
$this->captchaHelper = $captchaHelper;
$this->captchaExtension = $captchaExtension;
}
/**
......@@ -44,9 +40,10 @@ class OnDisplayCaptchaListener
{
if ($this->acl->hasPermission('frontend/captcha/index/image') === true) {
$arguments = $templateEvent->getParameters();
echo $this->captchaHelper->captcha(
isset($arguments['length']) ? $arguments['length'] : Helpers::CAPTCHA_DEFAULT_LENGTH,
isset($arguments['input_id']) ? $arguments['input_id'] : Helpers::CAPTCHA_DEFAULT_INPUT_ID,
echo $this->captchaExtension->getCaptcha(
isset($arguments['length']) ? $arguments['length'] : CaptchaExtensionInterface::CAPTCHA_DEFAULT_LENGTH,
isset($arguments['input_id']) ? $arguments['input_id'] : CaptchaExtensionInterface::CAPTCHA_DEFAULT_INPUT_ID,
isset($arguments['input_only']) ? $arguments['input_only'] : false,
isset($arguments['path']) ? $arguments['path'] : ''
);
......
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Event\Listener;
use ACP3\Core\I18n\Translator;
use ACP3\Core\Settings\SettingsInterface;
use ACP3\Core\View;
use ACP3\Modules\ACP3\Captcha\Installer\Schema;
use ACP3\Modules\ACP3\Users\Model\UserModel;
class RenderRecaptchaOnLayoutContentBeforeListener
{
/**
* @var SettingsInterface
*/
private $settings;
/**
* @var View
*/
private $view;
/**
* @var UserModel
*/
private $userModel;
/**
* @var Translator
*/
private $translator;
/**
* RenderRecaptchaOnLayoutContentBeforeListener constructor.
* @param Translator $translator
* @param SettingsInterface $settings
* @param View $view
* @param UserModel $userModel
*/
public function __construct(
Translator $translator,
SettingsInterface $settings,
View $view,
UserModel $userModel)
{
$this->settings = $settings;
$this->view = $view;
$this->userModel = $userModel;
$this->translator = $translator;
}
public function renderRecaptcha()
{
$settings = $this->settings->getSettings(Schema::MODULE_NAME);
if ($this->isRecaptcha($settings)) {
$this->view->assign('recaptcha', [
'sitekey' => $settings['recaptcha_sitekey'],
'lang' => $this->translator->getShortIsoCode()
]);
$this->view->displayTemplate('Captcha/Partials/captcha_recaptcha.onload.tpl');
}
}
/**
* @param array $settings
* @return bool
*/
private function isRecaptcha(array $settings)
{
return $settings['captcha'] === 'captcha.extension.recaptcha_captcha_extension'
&& !empty($settings['recaptcha_sitekey'])
&& !empty($settings['recaptcha_secret']);
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Extension;
interface CaptchaExtensionInterface
{
const CAPTCHA_DEFAULT_LENGTH = 5;
const CAPTCHA_DEFAULT_INPUT_ID = 'captcha';
/**
* @return string
*/
public function getCaptchaName();
/**
* Creates and returns the view of the captcha
*
* @param integer $captchaLength
* @param string $formFieldId
* @param bool $inputOnly
* @param string $path
*
* @return string
*/
public function getCaptcha(
$captchaLength = self::CAPTCHA_DEFAULT_LENGTH,
$formFieldId = self::CAPTCHA_DEFAULT_INPUT_ID,
$inputOnly = false,
$path = ''
);
/**
* Checks, whether the typed in captcha is valid
*
* @param mixed $formData
* @param string $formFieldName
* @param array $extra
* @return bool
*/
public function isCaptchaValid($formData, $formFieldName, array $extra = []);
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Extension;
use ACP3\Core\Settings\SettingsInterface;
use ACP3\Modules\ACP3\Captcha\Installer\Schema;
use Symfony\Component\DependencyInjection\ContainerInterface;
class CaptchaFactory
{
/**
* @var ContainerInterface
*/
private $container;
/**
* @var SettingsInterface
*/
private $settings;
/**
* CaptchaFactory constructor.
* @param SettingsInterface $settings
* @param ContainerInterface $container
*/
public function __construct(SettingsInterface $settings, ContainerInterface $container)
{
$this->container = $container;
$this->settings = $settings;
}
/**
* @return CaptchaExtensionInterface
*/
public function create()
{
$settings = $this->settings->getSettings(Schema::MODULE_NAME);
if ($this->container->has($settings['captcha'])) {
/** @var CaptchaExtensionInterface $service */
$service = $this->container->get($settings['captcha']);
return $service;
}
throw new \InvalidArgumentException(
sprintf('Can not find the captcha extension with the name "%s".', $settings['captcha'])
);
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Captcha\Extension;
use ACP3\Core;
use ACP3\Core\I18n\Translator;
class NativeCaptchaExtension implements CaptchaExtensionInterface
{
/**
* @var Translator
*/
private $translator;
/**
* @var \ACP3\Core\Helpers\Secure
*/
private $secureHelper;
/**
* @var \ACP3\Core\Http\RequestInterface
*/
private $request;
/**
* @var \ACP3\Core\Router\RouterInterface
*/
private $router;
/**
* @var \ACP3\Core\Session\SessionHandlerInterface
*/
private $sessionHandler;
/**
* @var \ACP3\Core\View
*/
private $view;
/**
* @var \ACP3\Modules\ACP3\Users\Model\UserModel
*/
private $user;
/**
* @var Core\ACL
*/
private $acl;
/**
* NativeCaptchaExtension constructor.
* @param Core\ACL $acl
* @param Translator $translator
* @param Core\Http\RequestInterface $request
* @param Core\Router\RouterInterface $router
* @param Core\Session\SessionHandlerInterface $sessionHandler
* @param Core\View $view
* @param Core\Helpers\Secure $secureHelper
* @param \ACP3\Modules\ACP3\Users\Model\UserModel $user
*/
public function __construct(
Core\ACL $acl,
Translator $translator,
Core\Http\RequestInterface $request,
Core\Router\RouterInterface $router,
Core\Session\SessionHandlerInterface $sessionHandler,
Core\View $view,
Core\Helpers\Secure $secureHelper,
\ACP3\Modules\ACP3\Users\Model\UserModel $user
) {
$this->translator = $translator;
$this->request = $request;
$this->router = $router;
$this->sessionHandler = $sessionHandler;
$this->view = $view;
$this->secureHelper = $secureHelper;
$this->user = $user;
$this->acl = $acl;
}
/**
* @return string
*/
public function getCaptchaName()
{
return $this->translator->t('captcha', 'native');