Added functionality to generate image files for older browsers.

This commit is contained in:
Bjoern Fromme 2011-11-09 14:43:25 +01:00
parent 22da6b0256
commit 572b58a41a
6 changed files with 110 additions and 18 deletions

View File

@ -15,13 +15,16 @@ class Configuration implements ConfigurationInterface
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('gregwar_captcha', 'array'); $rootNode = $treeBuilder->root('gregwar_captcha', 'array');
$rootNode $rootNode
->addDefaultsIfNotSet() ->addDefaultsIfNotSet()
->children() ->children()
->scalarNode('length')->defaultValue(5)->end() ->scalarNode('length')->defaultValue(5)->end()
->scalarNode('width')->defaultValue(120)->end() ->scalarNode('width')->defaultValue(120)->end()
->scalarNode('height')->defaultValue(40)->end() ->scalarNode('height')->defaultValue(40)->end()
->scalarNode('as_file')->defaultValue(false)->end()
->scalarNode('image_folder')->defaultValue('captcha')->end()
->scalarNode('web_path')->defaultValue('%kernel.root_dir%/../web')->end()
->end() ->end()
; ;
return $treeBuilder; return $treeBuilder;

View File

@ -22,11 +22,14 @@ class GregwarCaptchaExtension extends Extension
$container->setParameter('gregwar_captcha.length', $config['length']); $container->setParameter('gregwar_captcha.length', $config['length']);
$container->setParameter('gregwar_captcha.height', $config['height']); $container->setParameter('gregwar_captcha.height', $config['height']);
$container->setParameter('gregwar_captcha.width', $config['width']); $container->setParameter('gregwar_captcha.width', $config['width']);
$container->setParameter('gregwar_captcha.as_file', $config['as_file']);
$container->setParameter('gregwar_captcha.image_folder', $config['image_folder']);
$container->setParameter('gregwar_captcha.web_path', $config['web_path']);
$resources = $container->getParameter('twig.form.resources'); $resources = $container->getParameter('twig.form.resources');
$container->setParameter('twig.form.resources',array_merge(array('GregwarCaptchaBundle::captcha.html.twig'), $resources)); $container->setParameter('twig.form.resources',array_merge(array('GregwarCaptchaBundle::captcha.html.twig'), $resources));
} }
} }

View File

@ -2,27 +2,68 @@
namespace Gregwar\CaptchaBundle\Generator; namespace Gregwar\CaptchaBundle\Generator;
use Symfony\Component\Finder\Finder;
/** /**
* Generates a CAPTCHA image * Generates a CAPTCHA image
*/ */
class CaptchaGenerator { class CaptchaGenerator {
public $imageFolder;
public $webPath;
public $value; public $value;
public function __construct($value) public function __construct($value, $imageFolder, $webPath)
{ {
$this->value = $value; $this->value = $value;
$this->imageFolder = $imageFolder;
$this->webPath = $webPath;
} }
public function getCode($width = 120, $height = 40) public function getCode($width = 120, $height = 40)
{ {
return 'data:image/jpeg;base64,'.base64_encode($this->generate($width, $height)); return 'data:image/jpeg;base64,'.base64_encode($this->generate($width, $height));
} }
/**
* Creates a captcha image with provided dimensions
* and randomly executes a garbage collection
*
* @param int $width
* @param int $height
* @return string Web path to the created image
*/
public function getFile($width = 120, $height = 40)
{
if (rand(0, 10) == 5) {
$this->garbageCollection();
}
return $this->generate($width, $height, true);
}
/**
* Deletes all images in the configured folder
* that are older than 10 minutes
*
* @return void
*/
public function garbageCollection()
{
$finder = new Finder();
$finder->in($this->webPath . '/' . $this->imageFolder)
->date('since 10 minutes ago');
foreach($finder->files() as $file)
{
@unlink($file->getPathname());
}
}
/** /**
* Generate the image * Generate the image
*/ */
public function generate($width, $height) public function generate($width, $height, $createFile = false)
{ {
$i = imagecreatetruecolor($width,$height); $i = imagecreatetruecolor($width,$height);
@ -73,7 +114,7 @@ class CaptchaGenerator {
} }
$nY = $nY+$Scale*sin($Phase + $nX*0.2); $nY = $nY+$Scale*sin($Phase + $nX*0.2);
$p = $this->bilinearInterpolate($nX-floor($nX), $nY-floor($nY), $p = $this->bilinearInterpolate($nX-floor($nX), $nY-floor($nY),
$this->getCol($i,floor($nX),floor($nY)), $this->getCol($i,floor($nX),floor($nY)),
$this->getCol($i,ceil($nX),floor($nY)), $this->getCol($i,ceil($nX),floor($nY)),
$this->getCol($i,floor($nX),ceil($nY)), $this->getCol($i,floor($nX),ceil($nY)),
@ -87,9 +128,16 @@ class CaptchaGenerator {
} }
// Renders it // Renders it
ob_start(); if (!$createFile) {
imagejpeg($out, null, 15); ob_start();
return ob_get_clean(); imagejpeg($out, null, 15);
return ob_get_clean();
} else {
$filename = md5(uniqid()) . '.jpg';
$filepath = $this->webPath . '/' . $this->imageFolder . '/' . $filename;
imagejpeg($out, $filepath, 15);
return '/' . $this->imageFolder . '/' . $filename;
}
} }
protected function getCol($image, $x, $y) protected function getCol($image, $x, $y)

View File

@ -100,6 +100,9 @@ You can define the following type option :
* **width**: the width of the captcha image (default=120) * **width**: the width of the captcha image (default=120)
* **height**: the height of the captcha image (default=40) * **height**: the height of the captcha image (default=40)
* **length**: the length of the captcha (number of chars, default 5) * **length**: the length of the captcha (number of chars, default 5)
* **as_file**: if set to true an image file will be created instead of embedding to please IE6/7 (default=false)
* **image_folder**: name of folder for captcha images relative to public web folder in case **as_file** ist set to true (default="captcha")
* **web_path**: absolute path to public web folder (default="%kernel.root_dir%/../web")
Example : Example :
@ -109,7 +112,7 @@ Example :
$builder->add('captcha', 'captcha', array( $builder->add('captcha', 'captcha', array(
'width' => 200, 'width' => 200,
'height' => 50, 'height' => 50,
'length' => 6 'length' => 6,
)); ));
``` ```
@ -137,6 +140,11 @@ The default rendering is:
{% endblock %} {% endblock %}
``` ```
Image creation
==============
If you choose to use real images instead of embedded the widget will execute a garbage collection
randomly and delete images that are older than 10 minutes.
License License
======= =======
This bundle is under the MIT license. See the complete license in the bundle: This bundle is under the MIT license. See the complete license in the bundle:

View File

@ -3,6 +3,6 @@ services:
# captcha type # captcha type
captcha.type: captcha.type:
class: Gregwar\CaptchaBundle\Type\CaptchaType class: Gregwar\CaptchaBundle\Type\CaptchaType
arguments: [@session, %gregwar_captcha.width%, %gregwar_captcha.height%, %gregwar_captcha.length%] arguments: [ "@session", %gregwar_captcha.width%, %gregwar_captcha.height%, %gregwar_captcha.length%, %gregwar_captcha.as_file%, %gregwar_captcha.image_folder%, %gregwar_captcha.web_path% ]
tags: tags:
- { name: form.type, alias: captcha } - { name: form.type, alias: captcha }

View File

@ -39,21 +39,43 @@ class CaptchaType extends AbstractType
*/ */
protected $length; protected $length;
/** /**
* Generate image or data
* @var boolean
*/
protected $asFile;
/**
* Folder to save captcha images in,
* relative to public web folder
* @var string
*/
protected $imageFolder;
/**
* Public web folder
* @var string
*/
protected $webPath;
/**
* The session * The session
* @var Symfony\Component\HttpFoundation\Session * @var Symfony\Component\HttpFoundation\Session
*/ */
protected $session; protected $session;
private $key = 'captcha'; private $key = 'captcha';
public function __construct(Session $session, $width, $height, $length) public function __construct(Session $session, $width, $height, $length, $asFile, $imageFolder, $webPath)
{ {
$this->session = $session; $this->session = $session;
$this->width = $width; $this->width = $width;
$this->height = $height; $this->height = $height;
$this->length = $length; $this->length = $length;
$this->asFile = $asFile;
$this->imageFolder = $imageFolder;
$this->webPath = $webPath;
} }
public function buildForm(FormBuilder $builder, array $options) public function buildForm(FormBuilder $builder, array $options)
@ -65,14 +87,18 @@ class CaptchaType extends AbstractType
public function buildView(FormView $view, FormInterface $form) public function buildView(FormView $view, FormInterface $form)
{ {
$generator = new CaptchaGenerator($this->generateCaptchaValue()); $generator = new CaptchaGenerator($this->generateCaptchaValue(), $this->imageFolder, $this->webPath);
$view->set('captcha_code', $generator->getCode($this->width, $this->height)); if ($this->asFile) {
$view->set('captcha_code', $generator->getFile($this->width, $this->height));
} else {
$view->set('captcha_code', $generator->getCode($this->width, $this->height));
}
$view->set('captcha_width', $this->width); $view->set('captcha_width', $this->width);
$view->set('captcha_height', $this->height); $view->set('captcha_height', $this->height);
} }
public function getDefaultOptions(array $options = array()) public function getDefaultOptions(array $options = array())
{ {
if (isset($options['width'])) { if (isset($options['width'])) {
$this->width = $options['width']; $this->width = $options['width'];
@ -83,11 +109,15 @@ class CaptchaType extends AbstractType
if (isset($options['length'])) { if (isset($options['length'])) {
$this->length = $options['length']; $this->length = $options['length'];
} }
if (isset($options['as_file'])) {
$this->asFile = $options['as_file'];
}
return array( return array(
'width' => $this->width, 'width' => $this->width,
'height' => $this->height, 'height' => $this->height,
'length' => $this->length, 'length' => $this->length,
'as_file' => $this->asFile,
'property_path' => false, 'property_path' => false,
); );
} }