瀏覽代碼

Add inline/conditional validation option

Thomas Rabaix 14 年之前
父節點
當前提交
e0fe30f5f1

+ 27 - 1
Admin/Admin.php

@@ -11,7 +11,9 @@
 
 namespace Sonata\AdminBundle\Admin;
 
+use Symfony\Component\Form\Form;
 use Symfony\Component\Form\FormBuilder;
+use Symfony\Component\Validator\ValidatorInterface;
 use Symfony\Component\Routing\RouterInterface;
 use Symfony\Component\Translation\TranslatorInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -22,6 +24,7 @@ use Sonata\AdminBundle\Datagrid\ListMapper;
 use Sonata\AdminBundle\Datagrid\DatagridMapper;
 
 use Sonata\AdminBundle\Admin\Pool;
+use Sonata\AdminBundle\Validator\ErrorElement;
 
 use Sonata\AdminBundle\Builder\FormContractorInterface;
 use Sonata\AdminBundle\Builder\ListBuilderInterface;
@@ -329,6 +332,8 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
 
     protected $securityHandler = null;
 
+    protected $validator = null;
+
     /**
      * The configuration pool
      *
@@ -402,6 +407,11 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
 
     }
 
+    public function validate(ErrorElement $errorElement, $object)
+    {
+
+    }
+
     /**
      * @param string $code
      * @param string $class
@@ -754,7 +764,6 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
         return $this->class;
     }
 
-
     /**
      * Returns the list of batchs actions
      *
@@ -974,6 +983,13 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
             $object = $this->getNewInstance();
         }
 
+        // add the custom inline validation option
+        $metadata = $this->validator->getMetadataFactory()->getClassMetadata($this->class);
+        $metadata->addConstraint(new \Sonata\AdminBundle\Validator\Constraints\InlineConstraint(array(
+            'service' => $this,
+            'method'  => 'validate'
+        )));
+
         $formBuilder = $this->getFormContractor()->getFormBuilder(
             $this->getUniqid(),
             array_merge($this->formOptions, $options)
@@ -2094,4 +2110,14 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
     {
         return $this->getNormalizedIdentifier($entity);
     }
+
+    public function setValidator(ValidatorInterface $validator)
+    {
+      $this->validator = $validator;
+    }
+
+    public function getValidator()
+    {
+      return $this->validator;
+    }
 }

+ 4 - 0
DependencyInjection/Compiler/AddDependencyCallsPass.php

@@ -124,6 +124,10 @@ class AddDependencyCallsPass implements CompilerPassInterface
             $definition->addMethodCall('setRouter', array(new Reference('router')));
         }
 
+        if (!$definition->hasMethodCall('setValidator')) {
+            $definition->addMethodCall('setValidator', array(new Reference('validator')));
+        }
+
         if (!$definition->hasMethodCall('setSecurityHandler')) {
             $definition->addMethodCall('setSecurityHandler', array(new Reference('sonata.admin.security.handler')));
         }

+ 1 - 1
Resources/doc/index.rst

@@ -25,7 +25,7 @@ Reference Guide
    reference/routing
    reference/dashboard
    reference/security
-   reference/inline_validation
+   reference/conditional_validation
 
 
 Doctrine ORM

+ 4 - 2
Resources/doc/reference/inline_validation.rst

@@ -37,8 +37,10 @@ object. The object can be use to check assertion against a model :
                 ->end()
         }
 
-Please note, this solution rely on the validator component so validation defined through
-the validator component will be used.
+.. note::
+
+    This solution rely on the validator component so validation defined through
+    the validator component will be used.
 
 Using this validator
 --------------------

+ 16 - 1
Resources/doc/reference/form_field_definition.rst

@@ -9,8 +9,9 @@ Example
     <?php
     namespace Sonta\NewsBundle\Admin;
 
-    use Sonata\AdminBundle\Form\FormMapper;
     use Sonata\AdminBundle\Admin\Admin;
+    use Sonata\AdminBundle\Form\FormMapper;
+    use Sonata\AdminBundle\Validator\ErrorElement;
 
     class PostAdmin extends Admin
     {
@@ -38,6 +39,20 @@ Example
                 ));
 
         }
+
+        public function validate(ErrorElement $errorElement, $object)
+        {
+            // conditional validation, see the related section for more information
+            if ($object->getEnabled()) {
+                // abstract cannot be empty when the post is enabled
+                $errorElement
+                    ->with('abtract')
+                        ->assertNotBlank()
+                        ->assertNotNull()
+                    ->end()
+                ;
+            }
+        }
     }
 
 .. note::

+ 12 - 3
Validator/ErrorElement.php

@@ -83,7 +83,7 @@ class ErrorElement
 
         $validator->isValid($value, $constraint);
 
-        $this->context->setPropertyPath($this->propertyPaths[$this->current]);
+        $this->context->setPropertyPath($this->getCurrentPropertyPath());
         $this->context->setGroup($this->group);
 
         $validator->initialize($this->context);
@@ -104,7 +104,7 @@ class ErrorElement
      */
     protected function getValue()
     {
-        return $this->propertyPaths[$this->current]->getValue($this->subject);
+        return $this->getCurrentPropertyPath()->getValue($this->subject);
     }
 
     public function getSubject()
@@ -123,9 +123,18 @@ class ErrorElement
         return new $className($options);
     }
 
+    protected function getCurrentPropertyPath()
+    {
+        if (!isset($this->propertyPaths[$this->current])) {
+            throw new \RunTimeException('You must define a property by using the `with` method');
+        }
+
+        return $this->propertyPaths[$this->current];
+    }
+
     public function addViolation($error)
     {
-        $this->context->setPropertyPath($this->propertyPaths[$this->current]);
+        $this->context->setPropertyPath($this->getCurrentPropertyPath());
         $this->context->setGroup($this->group);
 
         if (!is_array($error)) {

+ 5 - 1
Validator/InlineValidator.php

@@ -28,7 +28,11 @@ class InlineValidator extends ConstraintValidator
 
     public function isValid($value, Constraint $constraint)
     {
-        $service = $this->container->get($constraint->getService());
+        if (is_string($constraint->getService())) {
+            $service = $this->container->get($constraint->getService());
+        } else {
+            $service = $constraint->getService();
+        }
 
         $errorElement = new ErrorElement(
             $value,