Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
isometriks committed Jul 10, 2013
0 parents commit 4d97769
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 0 deletions.
29 changes: 29 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Isometriks\Bundle\SpamBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('isometriks_spam');

// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.

return $treeBuilder;
}
}
28 changes: 28 additions & 0 deletions DependencyInjection/IsometriksSpamExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Isometriks\Bundle\SpamBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class IsometriksSpamExtension extends Extension
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
}
}
64 changes: 64 additions & 0 deletions Form/Extension/Spam/EventListener/TimedSpamValidationListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Isometriks\Bundle\SpamBundle\Form\Extension\Spam\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;
use Symfony\Component\Translation\TranslatorInterface;


class TimedSpamValidationListener implements EventSubscriberInterface
{
private $errorMessage;
private $translator;
private $translationDomain;
private $minTime;

public function __construct(TranslatorInterface $translator, $translationDomain, $errorMessage, $minTime)
{
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->errorMessage = $errorMessage;
$this->minTime = $minTime;
}

public function preSubmit(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();

if ($form->isRoot() && $form->getConfig()->getOption('compound')) {
if(!isset($data['_timed_spam']) || !$this->timeValid($data['_timed_spam'])){
$errorMessage = $this->errorMessage;

if (null !== $this->translator) {
$errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain);
}

$form->addError(new FormError($errorMessage));
}

if(is_array($data)) {
unset($data['_timed_spam']);
}
}

$event->setData($data);
}

protected function timeValid($value)
{
$time = base64_decode($value);

return ctype_digit($time) && (time() - $time) > $this->minTime;
}

public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SUBMIT => 'preSubmit',
);
}
}
67 changes: 67 additions & 0 deletions Form/Extension/Spam/Type/FormTypeTimedSpamExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Isometriks\Bundle\SpamBundle\Form\Extension\Spam\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Isometriks\Bundle\SpamBundle\Form\Extension\Spam\EventListener\TimedSpamValidationListener;

class FormTypeTimedSpamExtension extends AbstractTypeExtension
{
private $translator;
private $translationDomain;

public function __construct(TranslatorInterface $translator, $translationDomain)
{
$this->translator = $translator;
$this->translationDomain = $translationDomain;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
if (!$options['timed_spam']) {
return;
}

$builder
->setAttribute('timed_spam_factory', $builder->getFormFactory())
->addEventSubscriber(new TimedSpamValidationListener(
$this->translator,
$this->translationDomain,
$options['timed_spam_message'],
$options['timed_spam_min']
));
}

public function finishView(FormView $view, FormInterface $form, array $options)
{
if ($options['timed_spam'] && !$view->parent && $options['compound']) {
$factory = $form->getConfig()->getAttribute('timed_spam_factory');
$data = base64_encode(time());

$spamForm = $factory->createNamed('_timed_spam', 'hidden', $data, array(
'mapped' => false,
));

$view->children['_timed_spam'] = $spamForm->createView($view);
}
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'timed_spam' => false,
'timed_spam_min' => 7,
'timed_spam_message' => 'You are doing that too quickly.',
));
}

public function getExtendedType()
{
return 'form';
}
}
9 changes: 9 additions & 0 deletions IsometriksSpamBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Isometriks\Bundle\SpamBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class IsometriksSpamBundle extends Bundle
{
}
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Symfony2 SpamBundle

Please feel free to send pull requests. I would like to incorporate a bunch of
spam methods into this project.

Currently we have:

### Timed Spam Prevention

Requires forms to be sent after a certain amount of time. Most bots won't wait
to submit your forms, so requiring an amount of time between render and submit
can help deter these bots.
18 changes: 18 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<parameters>
<parameter key="isometriks_spam.form.extension.type.timed_spam.class">Isometriks\Bundle\SpamBundle\Form\Extension\Spam\Type\FormTypeTimedSpamExtension</parameter>
</parameters>

<services>
<service id="isometriks_spam.form.extension.type.timed_spam" class="%isometriks_spam.form.extension.type.timed_spam.class%">
<tag name="form.type_extension" alias="form" />
<argument type="service" id="translator.default" />
<argument>%validator.translation_domain%</argument>
</service>
</services>
</container>

0 comments on commit 4d97769

Please sign in to comment.