Merge pull request #208 from Olaf1989/symfony-5
Fully support Symfony 4 and 5
This commit is contained in:
commit
a22ba77f52
|
@ -1,32 +1,37 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\Controller;
|
namespace Gregwar\CaptchaBundle\Controller;
|
||||||
|
|
||||||
|
use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a captcha via a URL
|
* Generates a captcha via a URL.
|
||||||
*
|
*
|
||||||
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
|
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
|
||||||
*/
|
*/
|
||||||
class CaptchaController extends AbstractController
|
class CaptchaController extends AbstractController
|
||||||
{
|
{
|
||||||
/**
|
/** @var CaptchaGenerator */
|
||||||
* Action that is used to generate the captcha, save its code, and stream the image
|
private $captchaGenerator;
|
||||||
*
|
|
||||||
* @param string $key
|
/** @var array */
|
||||||
*
|
private $config;
|
||||||
* @return Response
|
|
||||||
*
|
public function __construct(CaptchaGenerator $captchaGenerator, array $config)
|
||||||
* @throws NotFoundHttpException
|
|
||||||
*/
|
|
||||||
public function generateCaptchaAction($key)
|
|
||||||
{
|
{
|
||||||
$options = $this->container->getParameter('gregwar_captcha.config');
|
$this->captchaGenerator = $captchaGenerator;
|
||||||
$session = $this->get('session');
|
$this->config = $config;
|
||||||
$whitelistKey = $options['whitelist_key'];
|
}
|
||||||
|
|
||||||
|
public function generateCaptchaAction(Request $request, string $key): Response
|
||||||
|
{
|
||||||
|
$session = $request->getSession();
|
||||||
|
$whitelistKey = $this->config['whitelist_key'];
|
||||||
$isOk = false;
|
$isOk = false;
|
||||||
|
|
||||||
if ($session->has($whitelistKey)) {
|
if ($session->has($whitelistKey)) {
|
||||||
|
@ -37,21 +42,18 @@ class CaptchaController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$isOk) {
|
if (!$isOk) {
|
||||||
return $this->error($options);
|
return $this->error($this->config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */
|
|
||||||
$generator = $this->container->get('gregwar_captcha.generator');
|
|
||||||
|
|
||||||
$persistedOptions = $session->get($key, array());
|
$persistedOptions = $session->get($key, array());
|
||||||
$options = array_merge($options, $persistedOptions);
|
$options = array_merge($this->config, $persistedOptions);
|
||||||
|
|
||||||
$phrase = $generator->getPhrase($options);
|
$phrase = $this->captchaGenerator->getPhrase($options);
|
||||||
$generator->setPhrase($phrase);
|
$this->captchaGenerator->setPhrase($phrase);
|
||||||
$persistedOptions['phrase'] = $phrase;
|
$persistedOptions['phrase'] = $phrase;
|
||||||
$session->set($key, $persistedOptions);
|
$session->set($key, $persistedOptions);
|
||||||
|
|
||||||
$response = new Response($generator->generate($options));
|
$response = new Response($this->captchaGenerator->generate($options));
|
||||||
$response->headers->set('Content-type', 'image/jpeg');
|
$response->headers->set('Content-type', 'image/jpeg');
|
||||||
$response->headers->set('Pragma', 'no-cache');
|
$response->headers->set('Pragma', 'no-cache');
|
||||||
$response->headers->set('Cache-Control', 'no-cache');
|
$response->headers->set('Cache-Control', 'no-cache');
|
||||||
|
@ -59,20 +61,11 @@ class CaptchaController extends AbstractController
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function error(array $options): Response
|
||||||
* Returns an empty image with status code 428 Precondition Required
|
|
||||||
*
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
protected function error($options)
|
|
||||||
{
|
{
|
||||||
/* @var \Gregwar\CaptchaBundle\Generator\CaptchaGenerator $generator */
|
$this->captchaGenerator->setPhrase('');
|
||||||
$generator = $this->container->get('gregwar_captcha.generator');
|
|
||||||
$generator->setPhrase('');
|
|
||||||
|
|
||||||
$response = new Response($generator->generate($options));
|
$response = new Response($this->captchaGenerator->generate($options));
|
||||||
$response->setStatusCode(428);
|
$response->setStatusCode(428);
|
||||||
$response->headers->set('Content-type', 'image/jpeg');
|
$response->headers->set('Content-type', 'image/jpeg');
|
||||||
$response->headers->set('Pragma', 'no-cache');
|
$response->headers->set('Pragma', 'no-cache');
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\DependencyInjection;
|
namespace Gregwar\CaptchaBundle\DependencyInjection;
|
||||||
|
|
||||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
|
@ -7,21 +9,10 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||||
|
|
||||||
class Configuration implements ConfigurationInterface
|
class Configuration implements ConfigurationInterface
|
||||||
{
|
{
|
||||||
/**
|
public function getConfigTreeBuilder(): TreeBuilder
|
||||||
* Generates the configuration tree.
|
|
||||||
*
|
|
||||||
* @return TreeBuilder
|
|
||||||
*/
|
|
||||||
public function getConfigTreeBuilder()
|
|
||||||
{
|
{
|
||||||
$treeBuilder = new TreeBuilder('gregwar_captcha');
|
$treeBuilder = new TreeBuilder('gregwar_captcha');
|
||||||
|
|
||||||
if (method_exists($treeBuilder, 'getRootNode')) {
|
|
||||||
$rootNode = $treeBuilder->getRootNode();
|
$rootNode = $treeBuilder->getRootNode();
|
||||||
} else {
|
|
||||||
// BC for symfony/config <= 4.1
|
|
||||||
$rootNode = $treeBuilder->root('gregwar_captcha');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rootNode
|
$rootNode
|
||||||
->addDefaultsIfNotSet()
|
->addDefaultsIfNotSet()
|
||||||
|
@ -36,7 +27,7 @@ class Configuration implements ConfigurationInterface
|
||||||
->scalarNode('as_url')->defaultValue(false)->end()
|
->scalarNode('as_url')->defaultValue(false)->end()
|
||||||
->scalarNode('reload')->defaultValue(false)->end()
|
->scalarNode('reload')->defaultValue(false)->end()
|
||||||
->scalarNode('image_folder')->defaultValue('captcha')->end()
|
->scalarNode('image_folder')->defaultValue('captcha')->end()
|
||||||
->scalarNode('web_path')->defaultValue('%kernel.root_dir%/../web')->end()
|
->scalarNode('web_path')->defaultValue('%kernel.project_dir%/public')->end()
|
||||||
->scalarNode('gc_freq')->defaultValue(100)->end()
|
->scalarNode('gc_freq')->defaultValue(100)->end()
|
||||||
->scalarNode('expiration')->defaultValue(60)->end()
|
->scalarNode('expiration')->defaultValue(60)->end()
|
||||||
->scalarNode('quality')->defaultValue(50)->end()
|
->scalarNode('quality')->defaultValue(50)->end()
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\DependencyInjection;
|
namespace Gregwar\CaptchaBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension used to load the configuration, set parameters, and initialize the captcha view
|
* Extension used to load the configuration, set parameters, and initialize the captcha view.
|
||||||
*
|
*
|
||||||
* @author Gregwar <g.passault@gmail.com>
|
* @author Gregwar <g.passault@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -17,8 +20,10 @@ class GregwarCaptchaExtension extends Extension
|
||||||
/**
|
/**
|
||||||
* @param array $configs
|
* @param array $configs
|
||||||
* @param ContainerBuilder $container
|
* @param ContainerBuilder $container
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function load(array $configs, ContainerBuilder $container)
|
public function load(array $configs, ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||||
$loader->load('services.yml');
|
$loader->load('services.yml');
|
||||||
|
|
|
@ -1,41 +1,33 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\Generator;
|
namespace Gregwar\CaptchaBundle\Generator;
|
||||||
|
|
||||||
use Gregwar\Captcha\CaptchaBuilder;
|
use Gregwar\Captcha\CaptchaBuilder;
|
||||||
use Gregwar\Captcha\PhraseBuilder;
|
use Gregwar\Captcha\PhraseBuilder;
|
||||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|
||||||
use Symfony\Component\Routing\RouterInterface;
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
|
|
||||||
use Gregwar\Captcha\CaptchaBuilderInterface;
|
use Gregwar\Captcha\CaptchaBuilderInterface;
|
||||||
use Gregwar\Captcha\PhraseBuilderInterface;
|
use Gregwar\Captcha\PhraseBuilderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses configuration parameters to call the services that generate captcha images
|
* Uses configuration parameters to call the services that generate captcha images.
|
||||||
*
|
*
|
||||||
* @author Gregwar <g.passault@gmail.com>
|
* @author Gregwar <g.passault@gmail.com>
|
||||||
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
|
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
|
||||||
*/
|
*/
|
||||||
class CaptchaGenerator
|
class CaptchaGenerator
|
||||||
{
|
{
|
||||||
/**
|
/** @var RouterInterface */
|
||||||
* @var RouterInterface
|
|
||||||
*/
|
|
||||||
protected $router;
|
protected $router;
|
||||||
|
|
||||||
/**
|
/** @var CaptchaBuilder */
|
||||||
* @var CaptchaBuilder
|
|
||||||
*/
|
|
||||||
protected $builder;
|
protected $builder;
|
||||||
|
|
||||||
/**
|
/** @var PhraseBuilder */
|
||||||
* @var PhraseBuilder
|
|
||||||
*/
|
|
||||||
protected $phraseBuilder;
|
protected $phraseBuilder;
|
||||||
|
|
||||||
/**
|
/** @var ImageFileHandler */
|
||||||
* @var ImageFileHandler
|
|
||||||
*/
|
|
||||||
protected $imageFileHandler;
|
protected $imageFileHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,14 +48,7 @@ class CaptchaGenerator
|
||||||
$this->imageFileHandler = $imageFileHandler;
|
$this->imageFileHandler = $imageFileHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getCaptchaCode(array &$options): string
|
||||||
* Get the captcha URL, stream, or filename that will go in the image's src attribute
|
|
||||||
*
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getCaptchaCode(array &$options)
|
|
||||||
{
|
{
|
||||||
$this->builder->setPhrase($this->getPhrase($options));
|
$this->builder->setPhrase($this->getPhrase($options));
|
||||||
|
|
||||||
|
@ -76,27 +61,21 @@ class CaptchaGenerator
|
||||||
|
|
||||||
// Returns the image generation URL
|
// Returns the image generation URL
|
||||||
if ($options['as_url']) {
|
if ($options['as_url']) {
|
||||||
return $this->router->generate('gregwar_captcha.generate_captcha',
|
return $this->router->generate(
|
||||||
array('key' => $options['session_key'], 'n' => md5(microtime(true).mt_rand())));
|
'gregwar_captcha.generate_captcha',
|
||||||
|
array('key' => $options['session_key'], 'n' => md5(microtime(true).mt_rand()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'data:image/jpeg;base64,' . base64_encode($this->generate($options));
|
return 'data:image/jpeg;base64,'.base64_encode($this->generate($options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function setPhrase(string $phrase): void
|
||||||
* Sets the phrase to the builder
|
|
||||||
*/
|
|
||||||
public function setPhrase($phrase)
|
|
||||||
{
|
{
|
||||||
$this->builder->setPhrase($phrase);
|
$this->builder->setPhrase($phrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function generate(array &$options): string
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function generate(array &$options)
|
|
||||||
{
|
{
|
||||||
$this->builder->setDistortion($options['distortion']);
|
$this->builder->setDistortion($options['distortion']);
|
||||||
|
|
||||||
|
@ -104,7 +83,7 @@ class CaptchaGenerator
|
||||||
$this->builder->setMaxBehindLines($options['max_behind_lines']);
|
$this->builder->setMaxBehindLines($options['max_behind_lines']);
|
||||||
|
|
||||||
if (isset($options['text_color']) && $options['text_color']) {
|
if (isset($options['text_color']) && $options['text_color']) {
|
||||||
if (count($options['text_color']) !== 3) {
|
if (3 !== count($options['text_color'])) {
|
||||||
throw new \RuntimeException('text_color should be an array of r, g and b');
|
throw new \RuntimeException('text_color should be an array of r, g and b');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +92,7 @@ class CaptchaGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options['background_color']) && $options['background_color']) {
|
if (isset($options['background_color']) && $options['background_color']) {
|
||||||
if (count($options['background_color']) !== 3) {
|
if (3 !== count($options['background_color'])) {
|
||||||
throw new \RuntimeException('background_color should be an array of r, g and b');
|
throw new \RuntimeException('background_color should be an array of r, g and b');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +128,7 @@ class CaptchaGenerator
|
||||||
return $this->imageFileHandler->saveAsFile($content);
|
return $this->imageFileHandler->saveAsFile($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getPhrase(array &$options): string
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getPhrase(array &$options)
|
|
||||||
{
|
{
|
||||||
// Get the phrase that we'll use for this image
|
// Get the phrase that we'll use for this image
|
||||||
if ($options['keep_value'] && isset($options['phrase'])) {
|
if ($options['keep_value'] && isset($options['phrase'])) {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\Generator;
|
namespace Gregwar\CaptchaBundle\Generator;
|
||||||
|
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles actions related to captcha image files including saving and garbage collection
|
* Handles actions related to captcha image files including saving and garbage collection.
|
||||||
*
|
*
|
||||||
* @author Gregwar <g.passault@gmail.com>
|
* @author Gregwar <g.passault@gmail.com>
|
||||||
* @author Jeremy Livingston <jeremy@quizzle.com>
|
* @author Jeremy Livingston <jeremy@quizzle.com>
|
||||||
|
@ -13,36 +15,40 @@ use Symfony\Component\Finder\Finder;
|
||||||
class ImageFileHandler
|
class ImageFileHandler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Name of folder for captcha images
|
* Name of folder for captcha images.
|
||||||
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $imageFolder;
|
protected $imageFolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Absolute path to public web folder
|
* Absolute path to public web folder.
|
||||||
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $webPath;
|
protected $webPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frequency of garbage collection in fractions of 1
|
* Frequency of garbage collection in fractions of 1.
|
||||||
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $gcFreq;
|
protected $gcFreq;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum age of images in minutes
|
* Maximum age of images in minutes.
|
||||||
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $expiration;
|
protected $expiration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $imageFolder
|
* @param string $imageFolder
|
||||||
* @param $webPath
|
* @param string $webPath
|
||||||
* @param $gcFreq
|
* @param string $gcFreq
|
||||||
* @param $expiration
|
* @param string $expiration
|
||||||
*/
|
*/
|
||||||
public function __construct($imageFolder, $webPath, $gcFreq, $expiration)
|
public function __construct(string $imageFolder, string $webPath, string $gcFreq, string $expiration)
|
||||||
{
|
{
|
||||||
$this->imageFolder = $imageFolder;
|
$this->imageFolder = $imageFolder;
|
||||||
$this->webPath = $webPath;
|
$this->webPath = $webPath;
|
||||||
|
@ -50,32 +56,20 @@ class ImageFileHandler
|
||||||
$this->expiration = $expiration;
|
$this->expiration = $expiration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function saveAsFile($contents): string
|
||||||
* Saves the provided image content as a file
|
|
||||||
*
|
|
||||||
* @param string $contents
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function saveAsFile($contents)
|
|
||||||
{
|
{
|
||||||
$this->createFolderIfMissing();
|
$this->createFolderIfMissing();
|
||||||
|
|
||||||
$filename = md5(uniqid()) . '.jpg';
|
$filename = md5(uniqid()).'.jpg';
|
||||||
$filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename;
|
$filePath = $this->webPath.'/'.$this->imageFolder.'/'.$filename;
|
||||||
imagejpeg($contents, $filePath, 15);
|
imagejpeg($contents, $filePath, 15);
|
||||||
|
|
||||||
return '/' . $this->imageFolder . '/' . $filename;
|
return '/'.$this->imageFolder.'/'.$filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function collectGarbage(): bool
|
||||||
* Randomly runs garbage collection on the image directory
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function collectGarbage()
|
|
||||||
{
|
{
|
||||||
if (!mt_rand(1, $this->gcFreq) == 1) {
|
if (1 == !mt_rand(1, $this->gcFreq)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,23 +77,20 @@ class ImageFileHandler
|
||||||
|
|
||||||
$finder = new Finder();
|
$finder = new Finder();
|
||||||
$criteria = sprintf('<= now - %s minutes', $this->expiration);
|
$criteria = sprintf('<= now - %s minutes', $this->expiration);
|
||||||
$finder->in($this->webPath . '/' . $this->imageFolder)
|
$finder->in($this->webPath.'/'.$this->imageFolder)
|
||||||
->date($criteria);
|
->date($criteria);
|
||||||
|
|
||||||
foreach($finder->files() as $file) {
|
foreach ($finder->files() as $file) {
|
||||||
unlink($file->getPathname());
|
unlink($file->getPathname());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function createFolderIfMissing(): void
|
||||||
* Creates the folder if it doesn't exist
|
|
||||||
*/
|
|
||||||
protected function createFolderIfMissing()
|
|
||||||
{
|
{
|
||||||
if (!file_exists($this->webPath . '/' . $this->imageFolder)) {
|
if (!file_exists($this->webPath.'/'.$this->imageFolder)) {
|
||||||
mkdir($this->webPath . '/' . $this->imageFolder, 0755);
|
mkdir($this->webPath.'/'.$this->imageFolder, 0755);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle;
|
namespace Gregwar\CaptchaBundle;
|
||||||
|
|
||||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
|
98
README.md
98
README.md
|
@ -11,106 +11,45 @@ It uses [gregwar/captcha](https://github.com/Gregwar/Captcha) as captcha generat
|
||||||
Compatibility with Symfony
|
Compatibility with Symfony
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
If you are using Symfony `< 2.8`, you should use version `1.*`
|
| CaptchaBundle | Symfony | PHP |
|
||||||
|
|:---------------:|:---------:|:-------:|
|
||||||
|
| 3.* | 4.* - 5.* | 7.1 > |
|
||||||
|
| 2.* | 2.8 - 3.* | 5.3.9 > |
|
||||||
|
| 1.* | 2.1 - 2.7 | 5.3.0 > |
|
||||||
|
|
||||||
If you are using Symfony `>= 2.8`, you should use version `2.*`
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
### Step 1: Download the GregwarCaptchaBundle
|
### Step 1: Download the GregwarCaptchaBundle
|
||||||
|
|
||||||
Ultimately, the GregwarCaptchaBundle files should be downloaded to the
|
|
||||||
'vendor/bundles/Gregwar/CaptchaBundle' directory.
|
|
||||||
|
|
||||||
You can accomplish this several ways, depending on your personal preference.
|
|
||||||
The first method is the standard Symfony method.
|
|
||||||
|
|
||||||
***Using Composer***
|
|
||||||
|
|
||||||
Use composer require to download and install the package.
|
Use composer require to download and install the package.
|
||||||
|
At the end of the installation you can automaticly create the configuration thanks to the Symfony recipe.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
composer require gregwar/captcha-bundle
|
composer require gregwar/captcha-bundle
|
||||||
```
|
```
|
||||||
|
|
||||||
***Using the vendors script***
|
|
||||||
|
|
||||||
Add the following lines to your `deps` file:
|
|
||||||
|
|
||||||
```
|
|
||||||
[GregwarCaptchaBundle]
|
|
||||||
git=http://github.com/Gregwar/CaptchaBundle.git
|
|
||||||
target=/bundles/Gregwar/CaptchaBundle
|
|
||||||
version=origin/2.0 <- add this if you are using Symfony 2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, run the vendors script to download the bundle:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ php bin/vendors install
|
|
||||||
```
|
|
||||||
|
|
||||||
***Using submodules***
|
|
||||||
|
|
||||||
If you prefer instead to use git submodules, then run the following:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ git submodule add git://github.com/Gregwar/CaptchaBundle.git vendor/bundles/Gregwar/CaptchaBundle
|
|
||||||
$ git submodule update --init
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Configure the Autoloader
|
|
||||||
|
|
||||||
If you use composer, you can skip this step.
|
|
||||||
|
|
||||||
Now you will need to add the `Gregwar` namespace to your autoloader:
|
|
||||||
|
|
||||||
``` php
|
|
||||||
<?php
|
|
||||||
// app/autoload.php
|
|
||||||
|
|
||||||
$loader->registerNamespaces(array(
|
|
||||||
// ...
|
|
||||||
'Gregwar' => __DIR__.'/../vendor/bundles',
|
|
||||||
));
|
|
||||||
```
|
|
||||||
### Step 3: Enable the bundle
|
|
||||||
|
|
||||||
Finally, enable the bundle in the kernel:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// app/appKernel.php
|
|
||||||
|
|
||||||
public function registerBundles()
|
|
||||||
{
|
|
||||||
$bundles = array(
|
|
||||||
// ...
|
|
||||||
new Gregwar\CaptchaBundle\GregwarCaptchaBundle(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Add the following configuration to your `app/config/config.yml`:
|
If you made the configuration automaticly trough the Symfony recipe, you should have the following config file `/config/packages/gregwar_captcha.yaml`
|
||||||
|
|
||||||
|
Otherwise you can create it manually `/config/packages/gregwar_captcha.yaml` with the following default configuration:
|
||||||
|
``` yaml
|
||||||
gregwar_captcha: ~
|
gregwar_captcha: ~
|
||||||
|
```
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
You can use the "captcha" type in your forms this way:
|
You can use the "captcha" type in your forms this way:
|
||||||
|
|
||||||
```php
|
``` php
|
||||||
<?php
|
<?php
|
||||||
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
||||||
// ...
|
// ...
|
||||||
$builder->add('captcha', CaptchaType::class); // That's all !
|
$builder->add('captcha', CaptchaType::class); // That's all !
|
||||||
// If you're using php<5.5, you can use instead:
|
|
||||||
$builder->add('captcha', 'Gregwar\CaptchaBundle\Type\CaptchaType');
|
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -123,7 +62,7 @@ Options
|
||||||
You can define the following configuration options globally:
|
You can define the following configuration options globally:
|
||||||
|
|
||||||
* **image_folder**: name of folder for captcha images relative to public web folder in case **as_file** is set to true (default="captcha")
|
* **image_folder**: name of folder for captcha images relative to public web folder in case **as_file** is set to true (default="captcha")
|
||||||
* **web_path**: absolute path to public web folder (default="%kernel.root_dir%/../web")
|
* **web_path**: absolute path to public web folder (default='%kernel.project_dir%/public')
|
||||||
* **gc_freq**: frequency of garbage collection in fractions of 1 (default=100)
|
* **gc_freq**: frequency of garbage collection in fractions of 1 (default=100)
|
||||||
* **expiration**: maximum lifetime of captcha image files in minutes (default=60)
|
* **expiration**: maximum lifetime of captcha image files in minutes (default=60)
|
||||||
|
|
||||||
|
@ -155,7 +94,7 @@ number of lines depends on the size of the image). (default=null)
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
```php
|
``` php
|
||||||
<?php
|
<?php
|
||||||
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
||||||
// ...
|
// ...
|
||||||
|
@ -168,11 +107,12 @@ Example :
|
||||||
|
|
||||||
You can also set these options for your whole application using the `gregwar_captcha`
|
You can also set these options for your whole application using the `gregwar_captcha`
|
||||||
configuration entry in your `config.yml` file:
|
configuration entry in your `config.yml` file:
|
||||||
|
``` yaml
|
||||||
gregwar_captcha:
|
gregwar_captcha:
|
||||||
width: 200
|
width: 200
|
||||||
height: 50
|
height: 50
|
||||||
length: 6
|
length: 6
|
||||||
|
```
|
||||||
|
|
||||||
Translation
|
Translation
|
||||||
===========
|
===========
|
||||||
|
@ -182,15 +122,17 @@ The messages are using the translator, you can either change the `invalid_messag
|
||||||
As URL
|
As URL
|
||||||
============
|
============
|
||||||
To use a URL to generate a captcha image, you must add the bundle's routing configuration to your app/routing.yml file:
|
To use a URL to generate a captcha image, you must add the bundle's routing configuration to your app/routing.yml file:
|
||||||
|
``` yaml
|
||||||
gregwar_captcha_routing:
|
gregwar_captcha_routing:
|
||||||
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
|
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
|
||||||
|
```
|
||||||
|
|
||||||
This will use the bundle's route of "/generate-captcha/{key}" to handle the generation. If this route conflicts with an application route, you can prefix the bundle's routes when you import:
|
This will use the bundle's route of "/generate-captcha/{key}" to handle the generation. If this route conflicts with an application route, you can prefix the bundle's routes when you import:
|
||||||
|
``` yaml
|
||||||
gregwar_captcha_routing:
|
gregwar_captcha_routing:
|
||||||
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
|
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
|
||||||
prefix: /_gcb
|
prefix: /_gcb
|
||||||
|
```
|
||||||
|
|
||||||
Since the session key is transported in the URL, it's also added in another session array, under the `whitelist_key` key, for security reasons
|
Since the session key is transported in the URL, it's also added in another session array, under the `whitelist_key` key, for security reasons
|
||||||
|
|
||||||
|
@ -201,7 +143,7 @@ The widget support the standard Symfony theming, see the [documentation](http://
|
||||||
|
|
||||||
The default rendering is:
|
The default rendering is:
|
||||||
|
|
||||||
```html
|
``` twig
|
||||||
{% block captcha_widget %}
|
{% block captcha_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />
|
<img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
parameters:
|
parameters:
|
||||||
|
gregwar_captcha.controller.class: Gregwar\CaptchaBundle\Controller\CaptchaController
|
||||||
gregwar_captcha.captcha_type.class: Gregwar\CaptchaBundle\Type\CaptchaType
|
gregwar_captcha.captcha_type.class: Gregwar\CaptchaBundle\Type\CaptchaType
|
||||||
gregwar_captcha.captcha_generator.class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator
|
gregwar_captcha.captcha_generator.class: Gregwar\CaptchaBundle\Generator\CaptchaGenerator
|
||||||
gregwar_captcha.image_file_handler.class: Gregwar\CaptchaBundle\Generator\ImageFileHandler
|
gregwar_captcha.image_file_handler.class: Gregwar\CaptchaBundle\Generator\ImageFileHandler
|
||||||
|
@ -6,7 +7,15 @@ parameters:
|
||||||
gregwar_captcha.phrase_builder.class: Gregwar\Captcha\PhraseBuilder
|
gregwar_captcha.phrase_builder.class: Gregwar\Captcha\PhraseBuilder
|
||||||
|
|
||||||
services:
|
services:
|
||||||
captcha.type:
|
gregwar_captcha.controller:
|
||||||
|
class: '%gregwar_captcha.controller.class%'
|
||||||
|
public: true
|
||||||
|
arguments:
|
||||||
|
- '@gregwar_captcha.generator'
|
||||||
|
- '%gregwar_captcha.config%'
|
||||||
|
|
||||||
|
# captcha.type:
|
||||||
|
gregwar_captcha.type:
|
||||||
class: '%gregwar_captcha.captcha_type.class%'
|
class: '%gregwar_captcha.captcha_type.class%'
|
||||||
public: true
|
public: true
|
||||||
arguments:
|
arguments:
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\Type;
|
namespace Gregwar\CaptchaBundle\Type;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||||
use Symfony\Component\Form\FormView;
|
use Symfony\Component\Form\FormView;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
|
||||||
use Symfony\Component\Form\FormEvents;
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
use Gregwar\CaptchaBundle\Validator\CaptchaValidator;
|
use Gregwar\CaptchaBundle\Validator\CaptchaValidator;
|
||||||
use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
|
use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captcha type
|
* Captcha type.
|
||||||
*
|
*
|
||||||
* @author Gregwar <g.passault@gmail.com>
|
* @author Gregwar <g.passault@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -24,25 +25,16 @@ class CaptchaType extends AbstractType
|
||||||
{
|
{
|
||||||
const SESSION_KEY_PREFIX = '_captcha_';
|
const SESSION_KEY_PREFIX = '_captcha_';
|
||||||
|
|
||||||
/**
|
/** @var SessionInterface */
|
||||||
* @var SessionInterface
|
|
||||||
*/
|
|
||||||
protected $session;
|
protected $session;
|
||||||
|
|
||||||
/**
|
/** @var CaptchaGenerator */
|
||||||
* @var CaptchaGenerator
|
|
||||||
*/
|
|
||||||
protected $generator;
|
protected $generator;
|
||||||
|
|
||||||
/**
|
/** @var TranslatorInterface */
|
||||||
* @var TranslatorInterface
|
|
||||||
*/
|
|
||||||
protected $translator;
|
protected $translator;
|
||||||
|
|
||||||
/**
|
/** @var array */
|
||||||
* Options
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $options = array();
|
private $options = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,8 +64,8 @@ class CaptchaType extends AbstractType
|
||||||
$options['bypass_code'],
|
$options['bypass_code'],
|
||||||
$options['humanity']
|
$options['humanity']
|
||||||
);
|
);
|
||||||
$event = \Symfony\Component\HttpKernel\Kernel::VERSION >= 2.3 ? FormEvents::POST_SUBMIT : FormEvents::POST_BIND;
|
|
||||||
$builder->addEventListener($event, array($validator, 'validate'));
|
$builder->addEventListener(FormEvents::POST_SUBMIT, array($validator, 'validate'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,12 +103,12 @@ class CaptchaType extends AbstractType
|
||||||
'image_id' => uniqid('captcha_'),
|
'image_id' => uniqid('captcha_'),
|
||||||
'captcha_code' => $this->generator->getCaptchaCode($options),
|
'captcha_code' => $this->generator->getCaptchaCode($options),
|
||||||
'value' => '',
|
'value' => '',
|
||||||
'is_human' => $isHuman
|
'is_human' => $isHuman,
|
||||||
));
|
));
|
||||||
|
|
||||||
$persistOptions = array();
|
$persistOptions = array();
|
||||||
foreach (array('phrase', 'width', 'height', 'distortion', 'length',
|
foreach (array('phrase', 'width', 'height', 'distortion', 'length',
|
||||||
'quality', 'background_color', 'background_images', 'text_color') as $key) {
|
'quality', 'background_color', 'background_images', 'text_color', ) as $key) {
|
||||||
$persistOptions[$key] = $options[$key];
|
$persistOptions[$key] = $options[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,36 +124,17 @@ class CaptchaType extends AbstractType
|
||||||
$resolver->setDefaults($this->options);
|
$resolver->setDefaults($this->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getParent(): string
|
||||||
* {@inheritdoc}
|
|
||||||
* BC for SF < 2.7
|
|
||||||
*/
|
|
||||||
public function setDefaultOptions(OptionsResolverInterface $resolver)
|
|
||||||
{
|
{
|
||||||
$this->configureOptions($resolver);
|
return TextType::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getName(): string
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getParent()
|
|
||||||
{
|
|
||||||
// Not using ::class to support Symfony 2.8 w/ php>=5.3.9
|
|
||||||
return 'Symfony\Component\Form\Extension\Core\Type\TextType';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
{
|
||||||
return $this->getBlockPrefix();
|
return $this->getBlockPrefix();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getBlockPrefix(): string
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getBlockPrefix()
|
|
||||||
{
|
{
|
||||||
return 'captcha';
|
return 'captcha';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +1,76 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Gregwar\CaptchaBundle\Validator;
|
namespace Gregwar\CaptchaBundle\Validator;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||||
use Symfony\Component\Form\FormError;
|
use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\Form\FormEvent;
|
use Symfony\Component\Form\FormEvent;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captcha validator
|
* Captcha validator.
|
||||||
*
|
*
|
||||||
* @author Gregwar <g.passault@gmail.com>
|
* @author Gregwar <g.passault@gmail.com>
|
||||||
*/
|
*/
|
||||||
class CaptchaValidator
|
class CaptchaValidator
|
||||||
{
|
{
|
||||||
/**
|
/** @var SessionInterface */
|
||||||
* @var SessionInterface
|
|
||||||
*/
|
|
||||||
private $session;
|
private $session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session key to store the code
|
* Session key to store the code.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $key;
|
private $key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error message text for non-matching submissions
|
* Error message text for non-matching submissions.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $invalidMessage;
|
private $invalidMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration parameter used to bypass a required code match
|
* Configuration parameter used to bypass a required code match.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $bypassCode;
|
private $bypassCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of form that the user can submit without captcha
|
* Number of form that the user can submit without captcha.
|
||||||
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $humanity;
|
private $humanity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator
|
* Translator.
|
||||||
|
*
|
||||||
* @var TranslatorInterface
|
* @var TranslatorInterface
|
||||||
*/
|
*/
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
/**
|
public function __construct(
|
||||||
* @param TranslatorInterface $translator
|
TranslatorInterface $translator,
|
||||||
* @param SessionInterface $session
|
SessionInterface $session,
|
||||||
* @param string $key
|
string $key,
|
||||||
* @param string $invalidMessage
|
string $invalidMessage,
|
||||||
* @param string $bypassCode
|
?string $bypassCode,
|
||||||
* @param int $humanity
|
int $humanity
|
||||||
*/
|
) {
|
||||||
public function __construct(TranslatorInterface $translator, SessionInterface $session, $key, $invalidMessage, $bypassCode, $humanity)
|
|
||||||
{
|
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->session = $session;
|
$this->session = $session;
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
$this->invalidMessage = $invalidMessage;
|
$this->invalidMessage = $invalidMessage;
|
||||||
$this->bypassCode = (string)$bypassCode;
|
$this->bypassCode = $bypassCode;
|
||||||
$this->humanity = $humanity;
|
$this->humanity = $humanity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function validate(FormEvent $event): void
|
||||||
* @param FormEvent $event
|
|
||||||
*/
|
|
||||||
public function validate(FormEvent $event)
|
|
||||||
{
|
{
|
||||||
$form = $event->getForm();
|
$form = $event->getForm();
|
||||||
|
|
||||||
|
@ -77,12 +80,13 @@ class CaptchaValidator
|
||||||
if ($this->humanity > 0) {
|
if ($this->humanity > 0) {
|
||||||
$humanity = $this->getHumanity();
|
$humanity = $this->getHumanity();
|
||||||
if ($humanity > 0) {
|
if ($humanity > 0) {
|
||||||
$this->updateHumanity($humanity-1);
|
$this->updateHumanity($humanity - 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($code !== null && is_string($code) && ($this->compare($code, $expectedCode) || $this->compare($code, $this->bypassCode)))) {
|
if (!(null !== $code && is_string($code) && ($this->compare($code, $expectedCode) || $this->compare($code, $this->bypassCode)))) {
|
||||||
$form->addError(new FormError($this->translator->trans($this->invalidMessage, array(), 'validators')));
|
$form->addError(new FormError($this->translator->trans($this->invalidMessage, array(), 'validators')));
|
||||||
} else {
|
} else {
|
||||||
if ($this->humanity > 0) {
|
if ($this->humanity > 0) {
|
||||||
|
@ -92,13 +96,13 @@ class CaptchaValidator
|
||||||
|
|
||||||
$this->session->remove($this->key);
|
$this->session->remove($this->key);
|
||||||
|
|
||||||
if ($this->session->has($this->key . '_fingerprint')) {
|
if ($this->session->has($this->key.'_fingerprint')) {
|
||||||
$this->session->remove($this->key . '_fingerprint');
|
$this->session->remove($this->key.'_fingerprint');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the expected CAPTCHA code
|
* Retrieve the expected CAPTCHA code.
|
||||||
*
|
*
|
||||||
* @return mixed|null
|
* @return mixed|null
|
||||||
*/
|
*/
|
||||||
|
@ -114,51 +118,39 @@ class CaptchaValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the humanity
|
* Retrieve the humanity.
|
||||||
*
|
*
|
||||||
* @return mixed|null
|
* @return mixed|null
|
||||||
*/
|
*/
|
||||||
protected function getHumanity()
|
protected function getHumanity()
|
||||||
{
|
{
|
||||||
return $this->session->get($this->key . '_humanity', 0);
|
return $this->session->get($this->key.'_humanity', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function updateHumanity(int $newValue): void
|
||||||
* Updates the humanity
|
|
||||||
*/
|
|
||||||
protected function updateHumanity($newValue)
|
|
||||||
{
|
{
|
||||||
if ($newValue > 0) {
|
if ($newValue > 0) {
|
||||||
$this->session->set($this->key . '_humanity', $newValue);
|
$this->session->set($this->key.'_humanity', $newValue);
|
||||||
} else {
|
} else {
|
||||||
$this->session->remove($this->key . '_humanity');
|
$this->session->remove($this->key.'_humanity');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
protected function niceize(string $code): string
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the codes
|
|
||||||
*
|
|
||||||
* @param $code
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function niceize($code)
|
|
||||||
{
|
{
|
||||||
return strtr(strtolower($code), 'oil', '01l');
|
return strtr(strtolower($code), 'oil', '01l');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a match comparison on the provided code and the expected code
|
* Run a match comparison on the provided code and the expected code.
|
||||||
*
|
*
|
||||||
* @param $code
|
* @param string $code
|
||||||
* @param $expectedCode
|
* @param string|null $expectedCode
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function compare($code, $expectedCode)
|
protected function compare($code, $expectedCode): bool
|
||||||
{
|
{
|
||||||
return ($expectedCode !== null && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode));
|
return null !== $expectedCode && is_string($expectedCode) && $this->niceize($code) == $this->niceize($expectedCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,23 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": "^7.1.3",
|
||||||
|
"ext-gd": "*",
|
||||||
"gregwar/captcha": "~1.1",
|
"gregwar/captcha": "~1.1",
|
||||||
"symfony/framework-bundle": "~3.0|~4.0|~5.0",
|
"symfony/form": "~4.0|~5.0",
|
||||||
"symfony/form": "~3.0|~4.0|~5.0",
|
"symfony/framework-bundle": "~4.0|~5.0",
|
||||||
"twig/twig": "^1.40|^2.9|^3"
|
"symfony/translation": "~4.0|^5.0",
|
||||||
|
"twig/twig": "^2.10|^3.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Gregwar\\CaptchaBundle\\": "/"
|
"Gregwar\\CaptchaBundle\\": "/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symplify/easy-coding-standard": "^6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
parameters:
|
||||||
|
exclude_files:
|
||||||
|
- 'vendor/*'
|
||||||
|
- 'LICENSE'
|
||||||
|
- 'README.md'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# PSR1
|
||||||
|
PhpCsFixer\Fixer\Basic\EncodingFixer: ~
|
||||||
|
PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer: ~
|
||||||
|
|
||||||
|
PhpCsFixer\Fixer\NamespaceNotation\BlankLineAfterNamespaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\ElseifFixer: ~
|
||||||
|
PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\LineEndingFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Casing\ConstantCaseFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Casing\LowercaseKeywordsFixer: ~
|
||||||
|
PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer:
|
||||||
|
ensure_fully_multiline: true
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer: ~
|
||||||
|
PhpCsFixer\Fixer\PhpTag\NoClosingTagFixer: ~
|
||||||
|
PhpCsFixer\Fixer\FunctionNotation\NoSpacesAfterFunctionNameFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Comment\NoTrailingWhitespaceInCommentFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer:
|
||||||
|
elements:
|
||||||
|
- 'property'
|
||||||
|
PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer: ~
|
||||||
|
|
||||||
|
PhpCsFixer\Fixer\Basic\BracesFixer:
|
||||||
|
allow_single_line_closure: true
|
||||||
|
PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\ConcatSpaceFixer:
|
||||||
|
spacing: none
|
||||||
|
PhpCsFixer\Fixer\Operator\NewWithBracesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer:
|
||||||
|
tags:
|
||||||
|
- method
|
||||||
|
- param
|
||||||
|
- property
|
||||||
|
- return
|
||||||
|
- throws
|
||||||
|
- type
|
||||||
|
- var
|
||||||
|
PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\IncrementStyleFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer: ~
|
||||||
|
PhpCsFixer\Fixer\CastNotation\CastSpacesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer: ~
|
||||||
|
PhpCsFixer\Fixer\FunctionNotation\FunctionTypehintSpaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer:
|
||||||
|
comment_types:
|
||||||
|
- hash
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\IncludeFixer: ~
|
||||||
|
PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer:
|
||||||
|
elements:
|
||||||
|
- method
|
||||||
|
PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\NoBlankLinesAfterPhpdocFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Comment\NoEmptyCommentFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocSeparationFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer:
|
||||||
|
tokens:
|
||||||
|
- curly_brace_block
|
||||||
|
- extra
|
||||||
|
- parenthesis_brace_block
|
||||||
|
- square_brace_block
|
||||||
|
- throw
|
||||||
|
- use
|
||||||
|
PhpCsFixer\Fixer\NamespaceNotation\NoLeadingNamespaceWhitespaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer: ~
|
||||||
|
PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\NoTrailingCommaInListCallFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\NoTrailingCommaInSinglelineArrayFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\TrailingCommaInMultilineArrayFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\NormalizeIndexBraceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocAnnotationWithoutDotFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocIndentFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocNoAccessFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocNoEmptyReturnFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocNoPackageFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocNoUselessInheritdocFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocReturnSelfReferenceFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocScalarFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocSingleLineVarSpacingFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocSummaryFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocToCommentFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocVarWithoutNameFixer: ~
|
||||||
|
PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\SelfAccessorFixer: ~
|
||||||
|
PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer: ~
|
||||||
|
PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Semicolon\SpaceAfterSemicolonFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\TrimArraySpacesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer:
|
||||||
|
singleLine: true
|
||||||
|
PhpCsFixer\Fixer\Casing\MagicConstantCasingFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer:
|
||||||
|
use: echo
|
||||||
|
PhpCsFixer\Fixer\Import\NoLeadingImportSlashFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Import\NoUnusedImportsFixer: ~
|
||||||
|
PhpCsFixer\Fixer\PhpUnit\PhpUnitFqcnAnnotationFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\PhpdocNoAliasTagFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer: ~
|
||||||
|
PhpCsFixer\Fixer\NamespaceNotation\SingleBlankLineBeforeNamespaceFixer: ~
|
||||||
|
|
||||||
|
# new since PHP-CS-Fixer 2.6
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\NoUnneededCurlyBracesFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer: ~
|
||||||
|
PhpCsFixer\Fixer\Semicolon\SemicolonAfterInstructionFixer: ~
|
||||||
|
PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer: ~
|
||||||
|
|
||||||
|
# new since 2.11
|
||||||
|
PhpCsFixer\Fixer\Operator\StandardizeIncrementFixer: ~
|
Loading…
Reference in New Issue