diff --git a/.travis.yml b/.travis.yml
index da40526..98d0468 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
language: php
-php: [5.3,5.4,5.5,5.6]
+php: [5.3,5.4,5.5,5.6,7.0]
env:
- - SF_VERSION='~2.3.0,>=2.3.19'
- - SF_VERSION='~2.4.0,>=2.4.9'
- - SF_VERSION='~2.5.0,>=2.5.3,<=2.5.4'
+ - SF_VERSION='~2.7.0'
+ - SF_VERSION='~2.8.0'
before_script:
- export WEB_FIXTURES_HOST=http://localhost/index.php
@@ -14,7 +13,6 @@ before_script:
- export DISPLAY=:99.0
- sleep 4
- - Tests/app/switch_sf_version.sh "$SF_VERSION"
- curl -sS https://getcomposer.org/installer | php
- php -d memory_limit=-1 composer.phar require "symfony/symfony:${SF_VERSION}"
- php -d memory_limit=-1 composer.phar install -n
@@ -31,6 +29,7 @@ before_script:
- sudo apt-get update > /dev/null
- sudo apt-get install -y --force-yes apache2 libapache2-mod-fastcgi > /dev/null
# enable php-fpm
+ - if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf; fi
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
- sudo a2enmod rewrite actions fastcgi alias
- echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
diff --git a/Factory/JsFormValidatorFactory.php b/Factory/JsFormValidatorFactory.php
index b7cdd8c..68c8fe6 100644
--- a/Factory/JsFormValidatorFactory.php
+++ b/Factory/JsFormValidatorFactory.php
@@ -5,16 +5,20 @@
use Fp\JsFormValidatorBundle\Form\Constraint\UniqueEntity;
use Fp\JsFormValidatorBundle\Model\JsConfig;
use Fp\JsFormValidatorBundle\Model\JsFormElement;
+use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\DataTransformerInterface;
-use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
+use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer;
+use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Form\ResolvedFormTypeInterface;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\GetterMetadata;
use Symfony\Component\Validator\Mapping\PropertyMetadata;
-use Symfony\Component\Validator\ValidatorInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* This factory uses to parse a form to a tree of JsFormElement's
@@ -63,7 +67,7 @@ class JsFormValidatorFactory
/**
* @param ValidatorInterface $validator
* @param TranslatorInterface $translator
- * @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $router
+ * @param UrlGeneratorInterface $router
* @param array $config
* @param string $domain
*/
@@ -91,7 +95,7 @@ public function __construct(
*/
protected function getMetadataFor($className)
{
- return $this->validator->getMetadataFactory()->getMetadataFor($className);
+ return $this->validator->getMetadataFor($className);
}
/**
@@ -242,12 +246,12 @@ public function createJsModel(Form $form)
$model = new JsFormElement;
$model->id = $this->getElementId($form);
$model->name = $form->getName();
- $model->type = $conf->getType()->getInnerType()->getName();
+ $model->type = $this->getFormTypeHierarchy($conf->getType());
$model->invalidMessage = $this->translateMessage(
$conf->getOption('invalid_message'),
$conf->getOption('invalid_message_parameters')
);
- $model->transformers = $this->parseTransformers($form->getConfig()->getViewTransformers());
+ $model->transformers = $this->parseTransformers($this->getViewTransformers($form));
$model->cascade = $conf->getOption('cascade_validation');
$model->bubbling = $conf->getOption('error_bubbling');
$model->data = $this->getValidationData($form);
@@ -262,6 +266,19 @@ public function createJsModel(Form $form)
return $model;
}
+ private function getFormTypeHierarchy(ResolvedFormTypeInterface $formType)
+ {
+ $type = array(
+ $formType->getName(),
+ );
+
+ while ($formType = $formType->getParent()) {
+ $type[] = $formType->getName();
+ }
+
+ return $type;
+ }
+
/**
* Create the JsFormElement for all the children of specified element
*
@@ -315,8 +332,8 @@ protected function getValidationData(Form $form)
$parent = $form->getParent();
if ($parent && null !== $parent->getConfig()->getDataClass()) {
$classMetadata = $metadata = $this->getMetadataFor($parent->getConfig()->getDataClass());
- if ($classMetadata->hasMemberMetadatas($form->getName())) {
- $metadata = $classMetadata->getMemberMetadatas($form->getName());
+ if ($classMetadata->hasPropertyMetadata($form->getName())) {
+ $metadata = $classMetadata->getPropertyMetadata($form->getName());
/** @var PropertyMetadata $item */
foreach ($metadata as $item) {
$this->composeValidationData(
@@ -428,8 +445,8 @@ protected function getValidationGroups(Form $form)
// If groups is an array - return groups as is
$result = $groups;
} elseif ($groups instanceof \Closure) {
- // If groups is a Closure - return the form class name to look for javascript
- $result = $this->getElementId($form);
+ // If groups is a Closure - return the closure response
+ $result = $groups($form);
}
return $result;
@@ -448,6 +465,32 @@ protected function isProcessableElement($element)
&& ('hidden' !== $element->getConfig()->getType()->getName());
}
+ /**
+ * Gets view transformers from the given form.
+ * Merges in an extra Choice(s)ToBooleanArrayTransformer transformer in case of expanded choice.
+ *
+ * @param FormInterface $form
+ *
+ * @return array
+ */
+ protected function getViewTransformers(FormInterface $form)
+ {
+ $config = $form->getConfig();
+ $type = $config->getType()->getInnerType()->getName();
+ $viewTransformers = $config->getViewTransformers();
+
+ // Choice(s)ToBooleanArrayTransformer was deprecated in SF2.7 in favor of CheckboxListMapper and RadioListMapper
+ if ($type === 'choice' && $config->getOption('expanded')) {
+ $choiceList = $config->getOption('choice_list');
+ $transformer = $config->getOption('multiple')
+ ? @new ChoicesToBooleanArrayTransformer($choiceList)
+ : @new ChoiceToBooleanArrayTransformer($choiceList, $config->getOption('placeholder'));
+ array_unshift($viewTransformers, $transformer);
+ }
+
+ return $viewTransformers;
+ }
+
/**
* Convert transformers objects to data arrays
*
@@ -471,7 +514,6 @@ protected function parseTransformers(array $transformers)
$result[] = $item;
}
-
return $result;
}
@@ -495,7 +537,7 @@ protected function getTransformerParam(DataTransformerInterface $transformer, $p
} elseif (is_scalar($value) || is_array($value)) {
$result = $value;
} elseif ($value instanceof ChoiceListInterface) {
- $result = $value->getChoices();
+ $result = array_values($value->getChoices());
}
return $result;
diff --git a/Model/JsModelAbstract.php b/Model/JsModelAbstract.php
index 20f4339..59bb792 100644
--- a/Model/JsModelAbstract.php
+++ b/Model/JsModelAbstract.php
@@ -2,6 +2,8 @@
namespace Fp\JsFormValidatorBundle\Model;
+use Symfony\Component\Validator\Constraint;
+
/**
* All the models inherited from this class converted to a similar Javascript model by printing them as a string
*
@@ -38,6 +40,11 @@ public function __toString()
*/
public static function phpValueToJs($value)
{
+ // Initialize "groups" option if it is not set
+ if ($value instanceof Constraint) {
+ $value->groups;
+ }
+
// For object which has own __toString method
if ($value instanceof JsModelAbstract) {
return $value->toJsString();
@@ -101,4 +108,4 @@ public function toArray()
return $result;
}
-}
\ No newline at end of file
+}
diff --git a/README.md b/README.md
index 0b57f56..080c363 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,21 @@
# FpJsFormValidatorBundle
-[![Build Status](https://travis-ci.org/formapro/JsFormValidatorBundle.svg?branch=1.2)](https://travis-ci.org/formapro/JsFormValidatorBundle)
+[![Build Status](https://travis-ci.org/formapro/JsFormValidatorBundle.svg?branch=1.3)](https://travis-ci.org/formapro/JsFormValidatorBundle)
[![Total Downloads](https://poser.pugx.org/fp/jsformvalidator-bundle/downloads.png)](https://packagist.org/packages/fp/jsformvalidator-bundle)
-This module enables validation of the Symfony2 forms on the JavaScript side.
+This module enables validation of the Symfony 2.7+ forms on the JavaScript side.
It converts form type constraints into JavaScript validation rules.
+If you have Symfony 3 or more - you need to use [Version 1.4+](https://github.com/formapro/JsFormValidatorBundle/tree/master)
-## 1 Installation
+If you have Symfony 2.3+ - you need to use [Version 1.2.*](https://github.com/formapro/JsFormValidatorBundle/tree/1.2)
-[Upgrade from the previous version](https://github.com/formapro/JsFormValidatorBundle/blob/master/UPGRADE-1.1.md)
+## 1 Installation
### 1.1 Download FpJsFormValidatorBundle using composer
Run in terminal:
```bash
-$ php composer.phar require "fp/jsformvalidator-bundle":"v1.2.*"
+$ php composer.phar require "fp/jsformvalidator-bundle":"v1.3.*"
```
### 1.2 Enable the bundle
diff --git a/Resources/public/js/FpJsFormValidator.js b/Resources/public/js/FpJsFormValidator.js
index 2f346aa..a88ab88 100644
--- a/Resources/public/js/FpJsFormValidator.js
+++ b/Resources/public/js/FpJsFormValidator.js
@@ -1,3 +1,29 @@
+function FpJsFormError(message) {
+ this.message = message;
+ this.atPath = null;
+
+ this.getTarget = function(rootElement) {
+ if (!this.atPath) {
+ return rootElement;
+ }
+
+ var path = this.atPath.split('.');
+ var targetElement = rootElement;
+ var pathSegment;
+
+ while (pathSegment = path.shift()) {
+ if (!targetElement.children[pathSegment]) {
+ return targetElement;
+ }
+
+ targetElement = targetElement.children[pathSegment];
+ }
+
+ // fallback to rootElement in case the targetElement is not found
+ return targetElement || rootElement;
+ }
+}
+
function FpJsFormElement() {
this.id = '';
this.name = '';
@@ -26,22 +52,47 @@ function FpJsFormElement() {
var self = this;
var sourceId = 'form-error-' + String(this.id).replace(/_/g, '-');
- self.errors[sourceId] = FpJsFormValidator.validateElement(self);
-
- var errorPath = FpJsFormValidator.getErrorPathElement(self);
- var domNode = errorPath.domNode;
- if (!domNode) {
- for (var childName in errorPath.children) {
- var childDomNode = errorPath.children[childName].domNode;
- if (childDomNode) {
- domNode = childDomNode;
- break;
+ this.clearErrorsRecursively(sourceId);
+
+ if (this.domNode && this.domNode.disabled) {
+ return true;
+ }
+
+ var validationErrors = FpJsFormValidator.validateElement(self);
+
+ var invalidTargets = {};
+ var validationError, errorTarget;
+ for (var v = 0, vel = validationErrors.length; v < vel; ++v) {
+ validationError = validationErrors[v];
+ errorTarget = validationError.getTarget(self);
+
+ invalidTargets[errorTarget.id] = errorTarget;
+
+ if (!errorTarget.errors[sourceId]) {
+ errorTarget.errors[sourceId] = [];
+ }
+
+ errorTarget.errors[sourceId].push(validationError.message);
+ }
+
+ for (var id in invalidTargets) {
+ self = invalidTargets[id];
+
+ var errorPath = FpJsFormValidator.getErrorPathElement(self);
+ var domNode = errorPath.domNode;
+ if (!domNode) {
+ for (var childName in errorPath.children) {
+ var childDomNode = errorPath.children[childName].domNode;
+ if (childDomNode) {
+ domNode = childDomNode;
+ break;
+ }
}
}
+ errorPath.showErrors.apply(domNode, [self.errors[sourceId], sourceId]);
}
- errorPath.showErrors.apply(domNode, [self.errors[sourceId], sourceId]);
- return self.errors[sourceId].length == 0;
+ return validationErrors.length === 0;
};
this.validateRecursively = function () {
@@ -67,6 +118,24 @@ function FpJsFormElement() {
return true;
};
+ this.clearErrors = function(sourceId) {
+ if (!sourceId) {
+ for (sourceId in this.errors) {
+ this.clearErrors(sourceId);
+ }
+ } else {
+ this.errors[sourceId] = [];
+ this.showErrors.apply(this.domNode, [this.errors[sourceId], sourceId]);
+ }
+ };
+
+ this.clearErrorsRecursively = function (sourceId) {
+ this.clearErrors(sourceId);
+ for (var childName in this.children) {
+ this.children[childName].clearErrorsRecursively(sourceId);
+ }
+ };
+
this.showErrors = function (errors, sourceId) {
if (!(this instanceof HTMLElement)) {
return;
@@ -375,6 +444,10 @@ var FpJsFormValidator = new function () {
this.customizeMethods = new FpJsCustomizeMethods();
this.constraintsCounter = 0;
+ function elementIsType(element, type) {
+ return element.type.indexOf(type) >= 0;
+ }
+
//noinspection JSUnusedGlobalSymbols
this.addModel = function (model, onLoad) {
var self = this;
@@ -511,7 +584,7 @@ var FpJsFormValidator = new function () {
this.checkParentCascadeOption = function (element) {
var result = true;
- if (element.parent && !element.parent.cascade && 'collection' != element.parent.type) {
+ if (element.parent && !element.parent.cascade && !elementIsType(element.parent, 'collection')) {
result = false;
} else if (element.parent) {
result = this.checkParentCascadeOption(element.parent);
@@ -531,12 +604,19 @@ var FpJsFormValidator = new function () {
this.validateConstraints = function (value, constraints, groups, owner) {
var errors = [];
var i = constraints.length;
+
while (i--) {
if (this.checkValidationGroups(groups, constraints[i])) {
errors = errors.concat(constraints[i].validate(value, owner));
}
}
+ for (var e = 0, el = errors.length; e < el; ++e) {
+ if (typeof errors[e] === 'string') {
+ errors[e] = new FpJsFormError(errors[e]);
+ }
+ }
+
return errors;
};
@@ -569,7 +649,7 @@ var FpJsFormValidator = new function () {
if (i && undefined === value) {
value = this.getMappedValue(element);
- } else if ('collection' == element.type) {
+ } else if (elementIsType(element, 'collection')) {
value = {};
for (var childName in element.children) {
value[childName] = this.getMappedValue(element.children[childName]);
@@ -609,7 +689,7 @@ var FpJsFormValidator = new function () {
}
var value;
- if ('checkbox' == element.type || 'radio' == element.type) {
+ if (elementIsType(element, 'checkbox') || elementIsType(element, 'radio')) {
value = element.domNode.checked;
} else if ('select' === element.domNode.tagName.toLowerCase()) {
value = [];
diff --git a/Resources/public/js/constraints/Choice.js b/Resources/public/js/constraints/Choice.js
index fade18b..f2ce4eb 100644
--- a/Resources/public/js/constraints/Choice.js
+++ b/Resources/public/js/constraints/Choice.js
@@ -28,12 +28,10 @@ function SymfonyComponentValidatorConstraintsChoice() {
if (this.multiple) {
if (invalidCnt) {
- while (invalidCnt--) {
- errors.push(this.multipleMessage.replace(
- '{{ value }}',
- FpJsBaseConstraint.formatValue(invalidList[invalidCnt])
- ));
- }
+ errors.push(this.multipleMessage.replace(
+ '{{ value }}',
+ FpJsBaseConstraint.formatValue(invalidList[0])
+ ));
}
if (!isNaN(this.min) && value.length < this.min) {
errors.push(this.minMessage);
diff --git a/Resources/public/js/constraints/False.js b/Resources/public/js/constraints/False.js
index cd54e9a..ad84b61 100644
--- a/Resources/public/js/constraints/False.js
+++ b/Resources/public/js/constraints/False.js
@@ -4,15 +4,4 @@
* @constructor
* @author dev.ymalcev@gmail.com
*/
-function SymfonyComponentValidatorConstraintsFalse() {
- this.message = '';
-
- this.validate = function (value) {
- var errors = [];
- if ('' !== value && false !== value) {
- errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
- }
-
- return errors;
- }
-}
+var SymfonyComponentValidatorConstraintsFalse = SymfonyComponentValidatorConstraintsIsFalse;
diff --git a/Resources/public/js/constraints/IsFalse.js b/Resources/public/js/constraints/IsFalse.js
new file mode 100644
index 0000000..512f493
--- /dev/null
+++ b/Resources/public/js/constraints/IsFalse.js
@@ -0,0 +1,18 @@
+//noinspection JSUnusedGlobalSymbols
+/**
+ * Checks if value is (bool) false
+ * @constructor
+ * @author dev.ymalcev@gmail.com
+ */
+function SymfonyComponentValidatorConstraintsIsFalse() {
+ this.message = '';
+
+ this.validate = function (value) {
+ var errors = [];
+ if ('' !== value && false !== value) {
+ errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
+ }
+
+ return errors;
+ }
+}
diff --git a/Resources/public/js/constraints/IsNull.js b/Resources/public/js/constraints/IsNull.js
new file mode 100644
index 0000000..c630ecb
--- /dev/null
+++ b/Resources/public/js/constraints/IsNull.js
@@ -0,0 +1,18 @@
+//noinspection JSUnusedGlobalSymbols
+/**
+ * Checks if value is null
+ * @constructor
+ * @author dev.ymalcev@gmail.com
+ */
+function SymfonyComponentValidatorConstraintsIsNull() {
+ this.message = '';
+
+ this.validate = function(value) {
+ var errors = [];
+ if (null !== value) {
+ errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
+ }
+
+ return errors;
+ }
+}
diff --git a/Resources/public/js/constraints/IsTrue.js b/Resources/public/js/constraints/IsTrue.js
new file mode 100644
index 0000000..322db60
--- /dev/null
+++ b/Resources/public/js/constraints/IsTrue.js
@@ -0,0 +1,23 @@
+//noinspection JSUnusedGlobalSymbols
+/**
+ * Checks if value is (bool) true
+ * @constructor
+ * @author dev.ymalcev@gmail.com
+ */
+function SymfonyComponentValidatorConstraintsIsTrue() {
+ this.message = '';
+
+ this.validate = function(value) {
+ if ('' === value) {
+ return [];
+ }
+
+ var errors = [];
+ if (true !== value) {
+ errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
+ }
+
+ return errors;
+ }
+}
+
diff --git a/Resources/public/js/constraints/Null.js b/Resources/public/js/constraints/Null.js
index b1113be..8e3bce0 100644
--- a/Resources/public/js/constraints/Null.js
+++ b/Resources/public/js/constraints/Null.js
@@ -4,15 +4,4 @@
* @constructor
* @author dev.ymalcev@gmail.com
*/
-function SymfonyComponentValidatorConstraintsNull() {
- this.message = '';
-
- this.validate = function(value) {
- var errors = [];
- if (null !== value) {
- errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
- }
-
- return errors;
- }
-}
+var SymfonyComponentValidatorConstraintsNull = SymfonyComponentValidatorConstraintsIsNull;
diff --git a/Resources/public/js/constraints/True.js b/Resources/public/js/constraints/True.js
index 2441ce8..dd8ad53 100644
--- a/Resources/public/js/constraints/True.js
+++ b/Resources/public/js/constraints/True.js
@@ -4,20 +4,4 @@
* @constructor
* @author dev.ymalcev@gmail.com
*/
-function SymfonyComponentValidatorConstraintsTrue() {
- this.message = '';
-
- this.validate = function(value) {
- if ('' === value) {
- return [];
- }
-
- var errors = [];
- if (true !== value) {
- errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
- }
-
- return errors;
- }
-}
-
+var SymfonyComponentValidatorConstraintsTrue = SymfonyComponentValidatorConstraintsIsTrue;
diff --git a/Tests/BaseMinkTestCase.php b/Tests/BaseMinkTestCase.php
index a0e7345..b3ffe92 100644
--- a/Tests/BaseMinkTestCase.php
+++ b/Tests/BaseMinkTestCase.php
@@ -139,12 +139,9 @@ protected function makeScreenshot()
}
try {
- $name = date('Y-m-d_H:i:s') . '.png';
- file_put_contents(
- '/tmp/' . $name,
- $this->session->getScreenshot()
- );
- $imageUrl = $this->getUploader()->upload('/tmp/' . $name);
+ $path = sprintf('%s/%s.png', sys_get_temp_dir(), date('Y-m-d_H-i-s'));
+ file_put_contents($path, $this->session->getScreenshot());
+ $imageUrl = $this->getUploader()->upload($path);
} catch (\Exception $e) {
$imageUrl = $e->getMessage();
}
diff --git a/Tests/Factory/JsFormValidatorFactoryTest.php b/Tests/Factory/JsFormValidatorFactoryTest.php
new file mode 100644
index 0000000..64bd672
--- /dev/null
+++ b/Tests/Factory/JsFormValidatorFactoryTest.php
@@ -0,0 +1,121 @@
+factory = $this->getMockBuilder('Fp\JsFormValidatorBundle\Factory\JsFormValidatorFactory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * Tears down test class properties.
+ */
+ public function tearDown()
+ {
+ $this->factory = null;
+ }
+
+ /**
+ * Tests the getValidationGroups() method when returning an empty array.
+ */
+ public function testGetValidationGroupsWhenEmpty()
+ {
+ // Given
+ $formConfig = $this->getMock('Symfony\Component\Form\FormConfigInterface');
+ $formConfig
+ ->expects($this->once())
+ ->method('getOption')
+ ->with($this->equalTo('validation_groups'))
+ ->will($this->returnValue(null));
+
+ $form = $this->getMockBuilder('Symfony\Component\Form\Form')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $form->expects($this->once())->method('getConfig')->will($this->returnValue($formConfig));
+
+ $factory = new \ReflectionMethod($this->factory, 'getValidationGroups');
+ $factory->setAccessible(true);
+
+ // When
+ $result = $factory->invoke($this->factory, $form);
+
+ // Then
+ $this->assertEquals(array('Default'), $result, 'Should return Default as validation_groups');
+ }
+
+ /**
+ * Tests the getValidationGroups() method when using a simple array.
+ */
+ public function testGetValidationGroupsWhenArray()
+ {
+ // Given
+ $formConfig = $this->getMock('Symfony\Component\Form\FormConfigInterface');
+ $formConfig
+ ->expects($this->once())
+ ->method('getOption')
+ ->with($this->equalTo('validation_groups'))
+ ->will($this->returnValue(array('test1', 'test2')));
+
+ $form = $this->getMockBuilder('Symfony\Component\Form\Form')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $form->expects($this->once())->method('getConfig')->will($this->returnValue($formConfig));
+
+ $factory = new \ReflectionMethod($this->factory, 'getValidationGroups');
+ $factory->setAccessible(true);
+
+ // When
+ $result = $factory->invoke($this->factory, $form);
+
+ // Then
+ $this->assertEquals(array('test1', 'test2'), $result, 'Should return the validation_groups array');
+ }
+
+ /**
+ * Tests the getValidationGroups() method when using a Closure.
+ */
+ public function testGetValidationGroupsWhenClosure()
+ {
+ // Given
+ $formConfig = $this->getMock('Symfony\Component\Form\FormConfigInterface');
+ $formConfig
+ ->expects($this->once())
+ ->method('getOption')
+ ->with($this->equalTo('validation_groups'))
+ ->will($this->returnValue(function () { return array('person'); }));
+
+ $form = $this->getMockBuilder('Symfony\Component\Form\Form')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $form->expects($this->once())->method('getConfig')->will($this->returnValue($formConfig));
+
+ $factory = new \ReflectionMethod($this->factory, 'getValidationGroups');
+ $factory->setAccessible(true);
+
+ // When
+ $result = $factory->invoke($this->factory, $form);
+
+ // Then
+ $this->assertEquals(array('person'), $result, 'Should return the closure response as validation_groups');
+ }
+}
\ No newline at end of file
diff --git a/Tests/Fixtures/Entity.php b/Tests/Fixtures/Entity.php
index 7729800..5ccf618 100644
--- a/Tests/Fixtures/Entity.php
+++ b/Tests/Fixtures/Entity.php
@@ -74,7 +74,7 @@ public function setName($name)
/**
* @return bool
- * @Assert\True(message = "wrong_name")
+ * @Assert\IsTrue(message = "wrong_name")
*/
public function isNameLegal()
{
diff --git a/Tests/Functional/MainFunctionalTest.php b/Tests/Functional/MainFunctionalTest.php
index 73033b2..fbc531f 100644
--- a/Tests/Functional/MainFunctionalTest.php
+++ b/Tests/Functional/MainFunctionalTest.php
@@ -321,12 +321,12 @@ public function testCollection()
$addComment->click();
$submit->click();
- $this->assertEquals($getExpected(4, 3, 0), array_count_values($getErrors()));
+ $this->assertEquals($getExpected(1, 1, 0), array_count_values($getErrors()));
$this->find('#del_form_task_tags_2')->click();
$this->find('#del_form_task_comments_1')->click();
$submit->click();
- $this->assertEquals($getExpected(3, 2, 0), array_count_values($getErrors()));
+ $this->assertEquals($getExpected(1, 1, 0), array_count_values($getErrors()));
$page->findField('form_task_tags_0_title')->setValue('asdf');
$page->findField('form_task_tags_1_title')->setValue('asdf');
@@ -462,4 +462,4 @@ public function testPassForm_invalid()
$this->assertTrue($page->hasContent('Fp\JsFormValidatorBundle\Exception\UndefinedFormException'), 'Exception was thrown');
$this->assertTrue($page->hasContent("Form 'wrong_name' was not found. Existing forms: async_load"), 'Correct message');
}
-}
\ No newline at end of file
+}
diff --git a/Tests/TestBundles/DefaultTestBundle/Controller/FunctionalTestsController.php b/Tests/TestBundles/DefaultTestBundle/Controller/FunctionalTestsController.php
index aaca67c..3a0bed1 100644
--- a/Tests/TestBundles/DefaultTestBundle/Controller/FunctionalTestsController.php
+++ b/Tests/TestBundles/DefaultTestBundle/Controller/FunctionalTestsController.php
@@ -24,11 +24,12 @@
use Symfony\Component\Validator\Constraints\DateTime;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\EqualTo;
-use Symfony\Component\Validator\Constraints\False;
use Symfony\Component\Validator\Constraints\GreaterThan;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\IdenticalTo;
use Symfony\Component\Validator\Constraints\Ip;
+use Symfony\Component\Validator\Constraints\IsFalse;
+use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\LessThan;
use Symfony\Component\Validator\Constraints\LessThanOrEqual;
@@ -37,7 +38,6 @@
use Symfony\Component\Validator\Constraints\NotIdenticalTo;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Time;
-use Symfony\Component\Validator\Constraints\True;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Constraints\Url;
@@ -293,10 +293,10 @@ public function transformersAction(Request $request, $isValid, $js)
'checkbox',
array(
'constraints' => array(
- new True(array(
+ new IsTrue(array(
'message' => 'checkbox_false'
)),
- new False(array(
+ new IsFalse(array(
'message' => 'checkbox_true'
))
)
@@ -307,10 +307,10 @@ public function transformersAction(Request $request, $isValid, $js)
'radio',
array(
'constraints' => array(
- new True(array(
+ new IsTrue(array(
'message' => 'radio_false'
)),
- new False(array(
+ new IsFalse(array(
'message' => 'radio_true'
))
)
@@ -469,7 +469,7 @@ public function emptyAction(
'constraints' => array(
new Email(array('message' => 'wrong_email')),
new EqualTo(array('value' => 'asdf', 'message' => 'wrong_equal_to')),
- new False(array('message' => 'wrong_false')),
+ new IsFalse(array('message' => 'wrong_false')),
new GreaterThan(array('value' => 5, 'message' => 'wrong_greater_than')),
new GreaterThanOrEqual(array('value' => 5, 'message' => 'wrong_greater_than_or_equal')),
new IdenticalTo(array('value' => 5, 'message' => 'wrong_identical_to')),
@@ -491,7 +491,7 @@ public function emptyAction(
new Time(array('message' => 'wrong_time')),
new Date(array('message' => 'wrong_date')),
new DateTime(array('message' => 'wrong_date_time')),
- new True(array('message' => 'wrong_true')),
+ new IsTrue(array('message' => 'wrong_true')),
new Type(array('type' => 'integer', 'message' => 'wrong_type')),
new Url(array('message' => 'wrong_url')),
)
diff --git a/Tests/TestBundles/DefaultTestBundle/Entity/BasicConstraintsEntity.php b/Tests/TestBundles/DefaultTestBundle/Entity/BasicConstraintsEntity.php
index 37313f5..8219c0a 100644
--- a/Tests/TestBundles/DefaultTestBundle/Entity/BasicConstraintsEntity.php
+++ b/Tests/TestBundles/DefaultTestBundle/Entity/BasicConstraintsEntity.php
@@ -352,7 +352,7 @@ public function getDatetime()
/**
* @return bool
- * @Assert\True(message="true_value")
+ * @Assert\IsTrue(message="true_value")
*/
public function isTrue()
{
@@ -361,7 +361,7 @@ public function isTrue()
/**
* @return bool
- * @Assert\False(message="false_value")
+ * @Assert\IsFalse(message="false_value")
*/
public function isFalse()
{
@@ -370,7 +370,7 @@ public function isFalse()
/**
* @return bool
- * @Assert\Null(message="null_{{ value }}")
+ * @Assert\IsNull(message="null_{{ value }}")
*/
public function isNull()
{
@@ -711,7 +711,7 @@ public function isValidSingleChoice()
*/
public function isValidMultipleChoice()
{
- return $this->_t_get(array('June', 'July'), array('June', 'May', 'September'));
+ return $this->_t_get(array('June', 'July'), array('June', 'May'));
}
/**
diff --git a/Tests/TestBundles/DefaultTestBundle/Entity/CustomizationEntity.php b/Tests/TestBundles/DefaultTestBundle/Entity/CustomizationEntity.php
index 9b8ba1f..ff09310 100644
--- a/Tests/TestBundles/DefaultTestBundle/Entity/CustomizationEntity.php
+++ b/Tests/TestBundles/DefaultTestBundle/Entity/CustomizationEntity.php
@@ -189,7 +189,7 @@ public function setEmail($email)
/**
* @return bool
*
- * @Assert\True(
+ * @Assert\IsTrue(
* message="getter_message",
* groups={"groups_callback"}
* )
diff --git a/Tests/TestBundles/DefaultTestBundle/Entity/TestEntity.php b/Tests/TestBundles/DefaultTestBundle/Entity/TestEntity.php
index bad2909..3b9aec7 100644
--- a/Tests/TestBundles/DefaultTestBundle/Entity/TestEntity.php
+++ b/Tests/TestBundles/DefaultTestBundle/Entity/TestEntity.php
@@ -116,11 +116,11 @@ public function setEmail($email)
/**
* @return bool
- * @Assert\True(
+ * @Assert\IsTrue(
* message="getter_groups_array_message",
* groups={"groups_array"}
* )
- * @Assert\True(
+ * @Assert\IsTrue(
* message="getter_no_groups_message"
* )
*/
diff --git a/Tests/TestBundles/DefaultTestBundle/Entity/TestSubEntity.php b/Tests/TestBundles/DefaultTestBundle/Entity/TestSubEntity.php
index a0a6329..2d7c52e 100644
--- a/Tests/TestBundles/DefaultTestBundle/Entity/TestSubEntity.php
+++ b/Tests/TestBundles/DefaultTestBundle/Entity/TestSubEntity.php
@@ -74,15 +74,15 @@ public function getName()
/**
* @return bool
- * @Assert\True(
+ * @Assert\IsTrue(
* message="sub_entity_getter_groups_child_message",
* groups={"groups_child"}
* )
- * @Assert\True(
+ * @Assert\IsTrue(
* message="sub_entity_getter_groups_array_message",
* groups={"groups_array"}
* )
- * @Assert\True(
+ * @Assert\IsTrue(
* message="sub_entity_getter_no_groups_message"
* )
*/
diff --git a/Tests/TestBundles/DefaultTestBundle/Resources/views/FunctionalTests/index.html.twig b/Tests/TestBundles/DefaultTestBundle/Resources/views/FunctionalTests/index.html.twig
index 5bc0b3e..c1dcc05 100644
--- a/Tests/TestBundles/DefaultTestBundle/Resources/views/FunctionalTests/index.html.twig
+++ b/Tests/TestBundles/DefaultTestBundle/Resources/views/FunctionalTests/index.html.twig
@@ -74,7 +74,7 @@
'isTypeScalar': function() { return _t.get(1, [1,2,3]); },
'isTypeString': function() { return _t.get('1', 1); },
'isValidSingleChoice': function() { return _t.get('male', 'wrong_choice'); },
- 'isValidMultipleChoice': function() { return _t.get(['June', 'July'], ['June', 'May', 'September']); },
+ 'isValidMultipleChoice': function() { return _t.get(['June', 'July'], ['June', 'May']); },
'isMinMultipleChoice': function() { return _t.get(['June', 'July'], ['June']); },
'isMaxMultipleChoice': function() { return _t.get(['June'], ['June', 'July']); },
diff --git a/Tests/TestBundles/DefaultTestBundle/Twig/Extension/TestTwigExtension.php b/Tests/TestBundles/DefaultTestBundle/Twig/Extension/TestTwigExtension.php
index 0ede9fe..deac8a4 100644
--- a/Tests/TestBundles/DefaultTestBundle/Twig/Extension/TestTwigExtension.php
+++ b/Tests/TestBundles/DefaultTestBundle/Twig/Extension/TestTwigExtension.php
@@ -12,9 +12,6 @@
*/
class TestTwigExtension extends \Twig_Extension
{
- /** @var \Twig_Environment */
- protected $env;
-
/**
* @var Kernel
*/
@@ -25,21 +22,13 @@ public function __construct($kernel)
$this->kernel = $kernel;
}
- /**
- * @param \Twig_Environment $environment
- */
- public function initRuntime(\Twig_Environment $environment)
- {
- $this->env = $environment;
- }
-
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return array(
- 'update_js_lib' => new \Twig_Function_Method($this, 'updateJsLib'),
+ new \Twig_SimpleFunction('update_js_lib', array($this, 'updateJsLib')),
);
}
diff --git a/Tests/app/AppKernel.php b/Tests/app/AppKernel.php
index 710d0a5..92712ad 100644
--- a/Tests/app/AppKernel.php
+++ b/Tests/app/AppKernel.php
@@ -42,13 +42,6 @@ public function registerContainerConfiguration(LoaderInterface $loader)
$loader->load(__DIR__.'/Resources/config.php');
}
- /**
- * An empty init function
- */
- public function init()
- {
- }
-
/**
* @param string $name
* @param string $extension
diff --git a/Tests/app/Resources/BasicConstraintsEntity_sf_2_3.php b/Tests/app/Resources/BasicConstraintsEntity_sf_2_3.php
index 24905d7..4e096d1 100644
--- a/Tests/app/Resources/BasicConstraintsEntity_sf_2_3.php
+++ b/Tests/app/Resources/BasicConstraintsEntity_sf_2_3.php
@@ -712,7 +712,7 @@ public function isValidSingleChoice()
*/
public function isValidMultipleChoice()
{
- return $this->_t_get(array('June', 'July'), array('June', 'May', 'September'));
+ return $this->_t_get(array('June', 'July'), array('June', 'May'));
}
/**
diff --git a/Tests/app/Resources/config.php b/Tests/app/Resources/config.php
index 684628b..a2b5161 100644
--- a/Tests/app/Resources/config.php
+++ b/Tests/app/Resources/config.php
@@ -53,9 +53,7 @@
$container->loadFromExtension('twig', array(
'debug' => true,
'strict_variables' => true,
- 'form' => array(
- 'resources' => array('DefaultTestBundle::form_theme.html.twig')
- ),
+ 'form_themes' => array('DefaultTestBundle::form_theme.html.twig')
));
$container->loadFromExtension('doctrine', array(
'orm' => array(
diff --git a/Twig/Extension/JsFormValidatorTwigExtension.php b/Twig/Extension/JsFormValidatorTwigExtension.php
index 4950216..a1f16fa 100644
--- a/Twig/Extension/JsFormValidatorTwigExtension.php
+++ b/Twig/Extension/JsFormValidatorTwigExtension.php
@@ -12,17 +12,6 @@
*/
class JsFormValidatorTwigExtension extends \Twig_Extension
{
- /** @var \Twig_Environment */
- protected $env;
-
- /**
- * @param \Twig_Environment $environment
- */
- public function initRuntime(\Twig_Environment $environment)
- {
- $this->env = $environment;
- }
-
/**
* @var JsFormValidatorFactory
*/
@@ -53,8 +42,12 @@ public function __construct(JsFormValidatorFactory $factory)
public function getFunctions()
{
return array(
- 'init_js_validation' => new \Twig_Function_Method($this, 'getJsValidator', array('is_safe' => array('html'))),
- 'js_validator_config' => new \Twig_Function_Method($this, 'getConfig', array('is_safe' => array('html'))),
+ new \Twig_SimpleFunction('init_js_validation', array($this, 'getJsValidator'), array(
+ 'is_safe' => array('html')
+ )),
+ new \Twig_SimpleFunction('js_validator_config', array($this, 'getConfig'), array(
+ 'is_safe' => array('html')
+ )),
);
}
diff --git a/composer.json b/composer.json
index 6892948..f15740a 100644
--- a/composer.json
+++ b/composer.json
@@ -19,15 +19,15 @@
"require": {
"php": ">=5.3.2",
- "symfony/form": ">=2.3,<=2.5.4",
- "symfony/validator": "~2.3.0,>=2.3.19||~2.4.0,>=2.4.9||~2.5.0,>=2.5.3,<=2.5.4",
- "symfony/symfony": "~2.3.0,>=2.3.19"
+ "symfony/form": "^2.7",
+ "symfony/validator": "^2.7"
},
"require-dev": {
"doctrine/orm": ">=2.2.3",
- "doctrine/doctrine-bundle": "~1.2",
- "symfony/assetic-bundle": ">=2.3,<=2.5.4",
+ "doctrine/doctrine-bundle": "~1.4",
+ "symfony/symfony": "^2.7",
+ "symfony/assetic-bundle": ">=2.5",
"phpunit/phpunit": "3.7.*",
"behat/mink-bundle": "dev-master",
"behat/mink-selenium2-driver": "1.1.0",
@@ -51,7 +51,7 @@
"extra": {
"branch-alias": {
- "dev-master": "1.1-dev"
+ "dev-master": "1.3-dev"
}
}
}