Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
66 changes: 54 additions & 12 deletions Factory/JsFormValidatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -91,7 +95,7 @@ public function __construct(
*/
protected function getMetadataFor($className)
{
return $this->validator->getMetadataFactory()->getMetadataFor($className);
return $this->validator->getMetadataFor($className);
}

/**
Expand Down Expand Up @@ -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);
Expand All @@ -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
*
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand All @@ -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
*
Expand All @@ -471,7 +514,6 @@ protected function parseTransformers(array $transformers)

$result[] = $item;
}

return $result;
}

Expand All @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion Model/JsModelAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -101,4 +108,4 @@ public function toArray()

return $result;
}
}
}
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -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<a name="p_1"></a>
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<a name="p_1"></a>

### 1.1 Download FpJsFormValidatorBundle using composer<a name="p_1_1"></a>

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<a name="p_1_2"></a>

Expand Down
Loading