Skip to content

Commit 2cb04b4

Browse files
committed
Merge pull request #105 from vaniocz/master
PHP7 & Symfony3 compatibility
2 parents 873b030 + 5d8615c commit 2cb04b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+395
-457
lines changed

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
language: php
22

3-
php: [5.3,5.4,5.5,5.6]
3+
php: [5.5,5.6,7.0]
44

55
env:
6-
- SF_VERSION='>=2.5.5,<2.6.0'
7-
- SF_VERSION='~2.6.0'
8-
- SF_VERSION='~2.7.0'
6+
- SF_VERSION='~3.0.0'
97

108
before_script:
119
- export WEB_FIXTURES_HOST=http://localhost/index.php
@@ -30,6 +28,7 @@ before_script:
3028
- sudo apt-get update > /dev/null
3129
- sudo apt-get install -y --force-yes apache2 libapache2-mod-fastcgi > /dev/null
3230
# enable php-fpm
31+
- 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
3332
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
3433
- sudo a2enmod rewrite actions fastcgi alias
3534
- echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini

Factory/JsFormValidatorFactory.php

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
use Fp\JsFormValidatorBundle\Form\Constraint\UniqueEntity;
66
use Fp\JsFormValidatorBundle\Model\JsConfig;
77
use Fp\JsFormValidatorBundle\Model\JsFormElement;
8+
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
89
use Symfony\Component\Form\DataTransformerInterface;
9-
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
10+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
11+
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
1012
use Symfony\Component\Form\Form;
1113
use Symfony\Component\Form\FormInterface;
1214
use Symfony\Component\Translation\TranslatorInterface;
1315
use Symfony\Component\Validator\Constraint;
1416
use Symfony\Component\Validator\Mapping\ClassMetadata;
1517
use Symfony\Component\Validator\Mapping\GetterMetadata;
1618
use Symfony\Component\Validator\Mapping\PropertyMetadata;
17-
use Symfony\Component\Validator\ValidatorInterface;
19+
use Symfony\Component\Validator\Validator\ValidatorInterface;
1820

1921
/**
2022
* This factory uses to parse a form to a tree of JsFormElement's
@@ -91,7 +93,7 @@ public function __construct(
9193
*/
9294
protected function getMetadataFor($className)
9395
{
94-
return $this->validator->getMetadataFactory()->getMetadataFor($className);
96+
return $this->validator->getMetadataFor($className);
9597
}
9698

9799
/**
@@ -242,13 +244,15 @@ public function createJsModel(Form $form)
242244
$model = new JsFormElement;
243245
$model->id = $this->getElementId($form);
244246
$model->name = $form->getName();
245-
$model->type = $conf->getType()->getInnerType()->getName();
247+
$model->type = get_class($conf->getType()->getInnerType());
246248
$model->invalidMessage = $this->translateMessage(
247249
$conf->getOption('invalid_message'),
248250
$conf->getOption('invalid_message_parameters')
249251
);
250-
$model->transformers = $this->parseTransformers($form->getConfig()->getViewTransformers());
251-
$model->cascade = $conf->getOption('cascade_validation');
252+
$model->transformers = $this->normalizeViewTransformers(
253+
$form,
254+
$this->parseTransformers($conf->getViewTransformers())
255+
);
252256
$model->bubbling = $conf->getOption('error_bubbling');
253257
$model->data = $this->getValidationData($form);
254258
$model->children = $this->processChildren($form);
@@ -315,8 +319,8 @@ protected function getValidationData(Form $form)
315319
$parent = $form->getParent();
316320
if ($parent && null !== $parent->getConfig()->getDataClass()) {
317321
$classMetadata = $metadata = $this->getMetadataFor($parent->getConfig()->getDataClass());
318-
if ($classMetadata->hasMemberMetadatas($form->getName())) {
319-
$metadata = $classMetadata->getMemberMetadatas($form->getName());
322+
if ($classMetadata->hasPropertyMetadata($form->getName())) {
323+
$metadata = $classMetadata->getPropertyMetadata($form->getName());
320324
/** @var PropertyMetadata $item */
321325
foreach ($metadata as $item) {
322326
$this->composeValidationData(
@@ -444,8 +448,33 @@ protected function getValidationGroups(Form $form)
444448
*/
445449
protected function isProcessableElement($element)
446450
{
447-
return ($element instanceof Form)
448-
&& ('hidden' !== $element->getConfig()->getType()->getName());
451+
return ($element instanceof Form) && (!is_a($element->getConfig()->getType(), HiddenType::class, true));
452+
}
453+
454+
/**
455+
* Gets view transformers from the given form.
456+
* Merges in an extra Choice(s)ToBooleanArrayTransformer transformer in case of expanded choice.
457+
*
458+
* @param FormInterface $form
459+
* @param array $viewTransformers
460+
*
461+
* @return array
462+
*/
463+
protected function normalizeViewTransformers(FormInterface $form, array $viewTransformers)
464+
{
465+
$config = $form->getConfig();
466+
467+
// Choice(s)ToBooleanArrayTransformer was deprecated in SF2.7 in favor of CheckboxListMapper and RadioListMapper
468+
if ($config->getType()->getInnerType() instanceof ChoiceType && $config->getOption('expanded')) {
469+
$namespace = 'Symfony\Component\Form\Extension\Core\DataTransformer\\';
470+
$transformer = $config->getOption('multiple')
471+
? array('name' => $namespace . 'ChoicesToBooleanArrayTransformer')
472+
: array('name' => $namespace . 'ChoiceToBooleanArrayTransformer');
473+
$transformer['choiceList'] = array_values($config->getOption('choices'));
474+
array_unshift($viewTransformers, $transformer);
475+
}
476+
477+
return $viewTransformers;
449478
}
450479

451480
/**
@@ -471,7 +500,6 @@ protected function parseTransformers(array $transformers)
471500

472501
$result[] = $item;
473502
}
474-
475503
return $result;
476504
}
477505

@@ -495,7 +523,7 @@ protected function getTransformerParam(DataTransformerInterface $transformer, $p
495523
} elseif (is_scalar($value) || is_array($value)) {
496524
$result = $value;
497525
} elseif ($value instanceof ChoiceListInterface) {
498-
$result = $value->getChoices();
526+
$result = array_values($value->getChoices());
499527
}
500528

501529
return $result;

Form/Extension/FormExtension.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use Fp\JsFormValidatorBundle\Factory\JsFormValidatorFactory;
55
use Fp\JsFormValidatorBundle\Form\Subscriber\SubscriberToQueue;
66
use Symfony\Component\Form\AbstractTypeExtension;
7+
use Symfony\Component\Form\Extension\Core\Type\FormType;
78
use Symfony\Component\Form\FormBuilderInterface;
89
use Symfony\Component\OptionsResolver\OptionsResolver;
910

@@ -37,7 +38,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3738
}
3839

3940
/**
40-
* @param OptionsResolverInterface $resolver
41+
* @param OptionsResolver $resolver
4142
*/
4243
public function configureOptions(OptionsResolver $resolver)
4344
{
@@ -51,6 +52,6 @@ public function configureOptions(OptionsResolver $resolver)
5152
*/
5253
public function getExtendedType()
5354
{
54-
return 'form';
55+
return FormType::class;
5556
}
5657
}

Model/JsFormElement.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ class JsFormElement extends JsModelAbstract
3131
*/
3232
public $invalidMessage;
3333

34-
/**
35-
* @var bool
36-
*/
37-
public $cascade = false;
38-
3934
/**
4035
* @var bool
4136
*/

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
[![Build Status](https://travis-ci.org/formapro/JsFormValidatorBundle.svg?branch=master)](https://travis-ci.org/formapro/JsFormValidatorBundle)
33
[![Total Downloads](https://poser.pugx.org/fp/jsformvalidator-bundle/downloads.png)](https://packagist.org/packages/fp/jsformvalidator-bundle)
44

5-
This module enables validation of the Symfony 2.5.5+ forms on the JavaScript side.
5+
This module enables validation of the 3.0+ forms on the JavaScript side.
66
It converts form type constraints into JavaScript validation rules.
77

8-
If you have Symfony 2.5.4* or less* - you need to use [Version 1.2.*](https://github.com/formapro/JsFormValidatorBundle/tree/1.2)
9-
10-
* More details here: [Symfony2](https://github.com/symfony/symfony/commit/97243bcd024bbfa458d66a4263a50ee7f16bbe74), [PR #83](https://github.com/formapro/JsFormValidatorBundle/pull/83)
11-
8+
If you have Symfony 2.8.* or 2.7.* - you need to use [Version 1.3.*](https://github.com/formapro/JsFormValidatorBundle/tree/1.3)
9+
If you have Symfony 2.6.* or less - you need to use [Version 1.2.*](https://github.com/formapro/JsFormValidatorBundle/tree/1.2)
1210

1311
## 1 Installation<a name="p_1"></a>
1412

Resources/config/services.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
<service id="fp_js_form_validator.extension" class="%fp_js_form_validator.extension.class%">
2020
<argument type="service" id="fp_js_form_validator.factory" />
21-
<tag name="form.type_extension" alias="form" />
21+
<tag name="form.type_extension" extended-type="Symfony\Component\Form\Extension\Core\Type\FormType" />
2222
</service>
2323

2424
<service id="fp_js_form_validator.factory" class="%fp_js_form_validator.factory.class%">

Resources/public/js/FpJsFormValidator.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ function FpJsFormElement() {
33
this.name = '';
44
this.type = '';
55
this.invalidMessage = '';
6-
this.cascade = false;
76
this.bubbling = false;
87
this.disabled = false;
98
this.transformers = [];
@@ -46,6 +45,7 @@ function FpJsFormElement() {
4645

4746
this.validateRecursively = function () {
4847
this.validate();
48+
4949
for (var childName in this.children) {
5050
this.children[childName].validateRecursively();
5151
}
@@ -470,17 +470,16 @@ var FpJsFormValidator = new function () {
470470
this.validateElement = function (element) {
471471
var errors = [];
472472
var value = this.getElementValue(element);
473-
for (var type in element.data) {
474473

475-
if (!this.checkParentCascadeOption(element) && 'entity' == type) {
474+
for (var type in element.data) {
475+
if ('entity' == type && element.parent && !this.shouldValidEmbedded(element)) {
476476
continue;
477477
}
478478

479-
if (element.parent && !this.checkParentCascadeOption(element.parent) && 'parent' == type) {
479+
if ('parent' == type && element.parent && element.parent.parent && !this.shouldValidEmbedded(element.parent)) {
480480
continue;
481481
}
482482

483-
484483
// Evaluate groups
485484
var groupsValue = element.data[type]['groups'];
486485
if (typeof groupsValue == "string") {
@@ -505,19 +504,32 @@ var FpJsFormValidator = new function () {
505504
}
506505
}
507506
}
508-
509507
return errors;
510508
};
511509

512-
this.checkParentCascadeOption = function (element) {
513-
var result = true;
514-
if (element.parent && !element.parent.cascade && 'collection' != element.parent.type) {
515-
result = false;
516-
} else if (element.parent) {
517-
result = this.checkParentCascadeOption(element.parent);
510+
this.shouldValidEmbedded = function (element) {
511+
if (this.getElementValidConstraint(element)) {
512+
return true;
513+
} else if (
514+
element.parent
515+
&& 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType' == element.parent.type
516+
) {
517+
var validConstraint = this.getElementValidConstraint(element);
518+
519+
return !validConstraint || validConstraint.traverse;
518520
}
519521

520-
return result;
522+
return false;
523+
};
524+
525+
this.getElementValidConstraint = function (element) {
526+
if (element.data && element.data.form) {
527+
for (var i in element.data.form.constraints) {
528+
if (element.data.form.constraints[i] instanceof SymfonyComponentValidatorConstraintsValid) {
529+
return element.data.form.constraints[i];
530+
}
531+
}
532+
}
521533
};
522534

523535
/**
@@ -569,7 +581,7 @@ var FpJsFormValidator = new function () {
569581

570582
if (i && undefined === value) {
571583
value = this.getMappedValue(element);
572-
} else if ('collection' == element.type) {
584+
} else if ('Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType' == element.type) {
573585
value = {};
574586
for (var childName in element.children) {
575587
value[childName] = this.getMappedValue(element.children[childName]);
@@ -609,7 +621,10 @@ var FpJsFormValidator = new function () {
609621
}
610622

611623
var value;
612-
if ('checkbox' == element.type || 'radio' == element.type) {
624+
if (
625+
'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType' == element.type
626+
|| 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType' == element.type
627+
) {
613628
value = element.domNode.checked;
614629
} else if ('select' === element.domNode.tagName.toLowerCase()) {
615630
value = [];

Resources/public/js/constraints/Callback.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function SymfonyComponentValidatorConstraintsCallback () {
1111
if (!this.callback) {
1212
this.callback = [];
1313
}
14-
if (!this.methods) {
14+
if (!this.methods.length) {
1515
this.methods = [this.callback];
1616
}
1717

Resources/public/js/constraints/Choice.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ function SymfonyComponentValidatorConstraintsChoice() {
2828

2929
if (this.multiple) {
3030
if (invalidCnt) {
31-
while (invalidCnt--) {
32-
errors.push(this.multipleMessage.replace(
33-
'{{ value }}',
34-
FpJsBaseConstraint.formatValue(invalidList[invalidCnt])
35-
));
36-
}
31+
errors.push(this.multipleMessage.replace(
32+
'{{ value }}',
33+
FpJsBaseConstraint.formatValue(invalidList[0])
34+
));
3735
}
3836
if (!isNaN(this.min) && value.length < this.min) {
3937
errors.push(this.minMessage);

Resources/public/js/constraints/False.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,4 @@
44
* @constructor
55
66
*/
7-
function SymfonyComponentValidatorConstraintsFalse() {
8-
this.message = '';
9-
10-
this.validate = function (value) {
11-
var errors = [];
12-
if ('' !== value && false !== value) {
13-
errors.push(this.message.replace('{{ value }}', FpJsBaseConstraint.formatValue(value)));
14-
}
15-
16-
return errors;
17-
}
18-
}
7+
var SymfonyComponentValidatorConstraintsFalse = SymfonyComponentValidatorConstraintsIsFalse;

0 commit comments

Comments
 (0)